svn commit: r238673 - head/sys/dev/ata
Alexander Motin
mav at FreeBSD.org
Sat Jul 21 14:59:44 UTC 2012
Author: mav
Date: Sat Jul 21 14:59:43 2012
New Revision: 238673
URL: http://svn.freebsd.org/changeset/base/238673
Log:
Use 16bit PIO instead of 32bit in case of misaligned buffer.
It fixes kernel panic during CD write with cdrecord on sparc64.
Modified:
head/sys/dev/ata/ata-lowlevel.c
Modified: head/sys/dev/ata/ata-lowlevel.c
==============================================================================
--- head/sys/dev/ata/ata-lowlevel.c Sat Jul 21 14:07:43 2012 (r238672)
+++ head/sys/dev/ata/ata-lowlevel.c Sat Jul 21 14:59:43 2012 (r238673)
@@ -836,23 +836,21 @@ static void
ata_pio_read(struct ata_request *request, int length)
{
struct ata_channel *ch = device_get_softc(request->parent);
+ uint8_t *addr;
int size = min(request->transfersize, length);
int resid;
uint8_t buf[2];
- if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) {
- ATA_IDX_INSW_STRM(ch, ATA_DATA,
- (void*)((uintptr_t)request->data+request->donecount),
- size / sizeof(int16_t));
+ addr = (uint8_t *)request->data + request->donecount;
+ if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
+ ((uintptr_t)addr % sizeof(int32_t))) {
+ ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
if (size & 1) {
ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)buf, 1);
- ((uint8_t *)request->data + request->donecount +
- (size & ~1))[0] = buf[0];
+ (addr + (size & ~1))[0] = buf[0];
}
} else
- ATA_IDX_INSL_STRM(ch, ATA_DATA,
- (void*)((uintptr_t)request->data+request->donecount),
- size / sizeof(int32_t));
+ ATA_IDX_INSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
if (request->transfersize < length) {
device_printf(request->parent, "WARNING - %s read data overrun %d>%d\n",
@@ -867,23 +865,21 @@ static void
ata_pio_write(struct ata_request *request, int length)
{
struct ata_channel *ch = device_get_softc(request->parent);
+ uint8_t *addr;
int size = min(request->transfersize, length);
int resid;
uint8_t buf[2];
- if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) {
- ATA_IDX_OUTSW_STRM(ch, ATA_DATA,
- (void*)((uintptr_t)request->data+request->donecount),
- size / sizeof(int16_t));
+ addr = (uint8_t *)request->data + request->donecount;
+ if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
+ ((uintptr_t)addr % sizeof(int32_t))) {
+ ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
if (size & 1) {
- buf[0] = ((uint8_t *)request->data + request->donecount +
- (size & ~1))[0];
+ buf[0] = (addr + (size & ~1))[0];
ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)buf, 1);
}
} else
- ATA_IDX_OUTSL_STRM(ch, ATA_DATA,
- (void*)((uintptr_t)request->data+request->donecount),
- size / sizeof(int32_t));
+ ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
if (request->transfersize < length) {
device_printf(request->parent, "WARNING - %s write data underrun %d>%d\n",
More information about the svn-src-head
mailing list