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!  /
 [EMAIL PROTECTED]                    `------------------------------'


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 [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to