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>
