Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Jan 2000 18:50:45 -0500 (EST)
From:      Brian Fundakowski Feldman <green@FreeBSD.org>
To:        Soren Schmidt <sos@freebsd.dk>
Cc:        current@FreeBSD.ORG
Subject:   Re: ATA atapi-all.c problems/fixes/cleanups
Message-ID:  <Pine.BSF.4.10.10001051827570.2363-100000@green.dyndns.org>
In-Reply-To: <200001050835.JAA35344@freebsd.dk>

next in thread | previous in thread | raw e-mail | index | archive | help
How about this?  It's mostly the changes in your patch, but it also takes
into account non-int{8,16}_t-sizing/alignment.  It also takes care of the
truncation problem when you use outsl and insl, as part of that.  Please
review it, as I think it should be the right thing to do.

-- 
 Brian Fundakowski Feldman           \  FreeBSD: The Power to Serve!  /
 green@FreeBSD.org                    `------------------------------'


Index: atapi-all.c
===================================================================
RCS file: /usr2/ncvs/src/sys/dev/ata/atapi-all.c,v
retrieving revision 1.29
diff -u -r1.29 atapi-all.c
--- atapi-all.c	2000/01/03 10:26:56	1.29
+++ atapi-all.c	2000/01/05 23:37:27
@@ -552,23 +552,39 @@
 	*buffer = (int8_t *)&request->sense;
 
     if (request->bytecount < length) {
-	printf("%s: read data overrun %d/%d\n",
+	printf("%s: read data buffer too small (bs %d > buflen %d)\n",
 	       request->device->devname, length, request->bytecount);
 #ifdef ATA_16BIT_ONLY
 	insw(request->device->controller->ioaddr + ATA_DATA, 
-	     (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
+	     (void *)*buffer, request->bytecount / sizeof(int16_t));
 #else
 	insl(request->device->controller->ioaddr + ATA_DATA, 
-	     (void *)((uintptr_t)*buffer), length / sizeof(int32_t));
+	     (void *)*buffer, request->bytecount / sizeof(int32_t));
+	if (request->bytecount & sizeof(int16_t)) {
+	     *(int16_t *)(*buffer + request->bytecount -
+		(sizeof(int16_t) + (request->bytecount & sizeof(int8_t)))) =
+		inw(request->device->controller->ioaddr + ATA_DATA);
+	     length -= sizeof(int16_t);
+	}
 #endif
-	for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
-	     inw(request->device->controller->ioaddr + ATA_DATA);
+	if (request->bytecount & sizeof(int8_t)) {
+	     (*buffer)[request->bytecount - sizeof(int8_t)] =
+		 inb(request->device->controller->ioaddr + ATA_DATA);
+	     (void)inb(request->device->controller->ioaddr + ATA_DATA);
+	     length -= sizeof(int8_t);
+	}
+	resid = request->bytecount & ~(sizeof(int16_t) | sizeof(int8_t));
+	for (; resid < length; resid += sizeof(int16_t))
+	     (void)inw(request->device->controller->ioaddr + ATA_DATA);
+	*buffer += request->bytecount;
+	request->bytecount = 0;
     }			
-    else
+    else {
 	insw(request->device->controller->ioaddr + ATA_DATA,
-	     (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
-    request->bytecount -= length;
-    *buffer += length;
+	     (void *)*buffer, length / sizeof(int16_t));
+	*buffer += length;
+	request->bytecount -= length;
+    }
 }
 
 static void
@@ -581,23 +597,38 @@
 	*buffer = (int8_t *)&request->sense;
 
     if (request->bytecount < length) {
-	printf("%s: write data underrun %d/%d\n",
-	       request->device->devname, length, request->bytecount);
+	printf("%s: write data underrun (buflen %d < bs %d), padding written\n",
+	       request->device->devname, request->bytecount, length);
 #ifdef ATA_16BIT_ONLY
 	outsw(request->device->controller->ioaddr + ATA_DATA, 
-	      (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
+	      (void *)*buffer, request->bytecount / sizeof(int16_t));
 #else
 	outsl(request->device->controller->ioaddr + ATA_DATA, 
-	      (void *)((uintptr_t)*buffer), length / sizeof(int32_t));
+	      (void *)*buffer, request->bytecount / sizeof(int32_t));
+	if (request->bytecount & sizeof(int16_t)) {
+	    outw(request->device->controller->ioaddr + ATA_DATA,
+		 *(int16_t *)(*buffer + request->bytecount -
+		 (sizeof(int16_t) + (request->bytecount & sizeof(int8_t)))));
+	    length -= sizeof(int16_t);
+	}
 #endif
-	for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
+	if (request->bytecount & sizeof(int8_t)) {
+	    outb(request->device->controller->ioaddr + ATA_DATA,
+		 (*buffer)[request->bytecount]);
+	    length -= sizeof(int8_t);
+	}
+	resid = request->bytecount & ~(sizeof(int16_t) | sizeof(int8_t));
+	for (; resid < length; resid += sizeof(int16_t))
 	     outw(request->device->controller->ioaddr + ATA_DATA, 0);
+	*buffer += request->bytecount;
+	request->bytecount = 0;
     }
-    else
+    else {
 	outsw(request->device->controller->ioaddr + ATA_DATA, 
-	      (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
-    request->bytecount -= length;
-    *buffer += length;
+	      (void *)*buffer, length / sizeof(int16_t));
+	*buffer += length;
+	request->bytecount -= length;
+    }
 }
 
 static void 



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.10001051827570.2363-100000>