From c94d33e8a132f2ab116fc40563803e77ab92f94e Mon Sep 17 00:00:00 2001 From: mav Date: Tue, 21 Aug 2012 11:43:01 +0000 Subject: [PATCH] MFC r238673: Use 16bit PIO instead of 32bit in case of misaligned buffer. It fixes kernel panic during CD write with cdrecord on sparc64. git-svn-id: svn://svn.freebsd.org/base/stable/8@239495 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/ata/ata-lowlevel.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c index 81cc87bd8..8f4d6c52b 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -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", -- 2.45.0