diff options
Diffstat (limited to 'sys/dev/ata')
-rw-r--r-- | sys/dev/ata/ata-disk.c | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 926f8f6..08e7f34 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -331,28 +331,34 @@ addump(void *arg, void *virtual, vm_offset_t physical, bzero(&request, sizeof(struct ata_request)); request.device = adp->device; - request.data = virtual; - request.bytecount = length; - request.transfersize = min(length, adp->max_iosize); - request.flags = ATA_R_WRITE; - if (adp->max_iosize > DEV_BSIZE) - request.u.ata.command = ATA_WRITE_MUL; - else - request.u.ata.command = ATA_WRITE; - request.u.ata.lba = offset / DEV_BSIZE; - request.u.ata.count = request.bytecount / DEV_BSIZE; + if (length) { + request.data = virtual; + request.bytecount = length; + request.transfersize = min(length, adp->max_iosize); + request.flags = ATA_R_WRITE; + if (adp->max_iosize > DEV_BSIZE) + request.u.ata.command = ATA_WRITE_MUL; + else + request.u.ata.command = ATA_WRITE; + request.u.ata.lba = offset / DEV_BSIZE; + request.u.ata.count = request.bytecount / DEV_BSIZE; + } + else { + request.u.ata.command = ATA_FLUSHCACHE; + request.flags = ATA_R_CONTROL; + } - if (adp->device->channel->hw.transaction(&request) == ATA_OP_FINISHED) - return EIO; - while (request.bytecount > request.donecount) { - DELAY(20); - adp->device->channel->running = &request; - adp->device->channel->hw.interrupt(adp->device->channel); - adp->device->channel->running = NULL; - if (request.status & ATA_S_ERROR) - return EIO; + if (request.device->channel->hw.transaction(&request) == ATA_OP_CONTINUES) { + while (request.device->channel->running == &request && + !(request.status & ATA_S_ERROR)) { + DELAY(20); + request.device->channel->running = &request; + request.device->channel->hw.interrupt(request.device->channel); + } } + if (request.status & ATA_S_ERROR) + return EIO; return 0; } |