static int hd_write_pio(block_dev_t *bdev, char *buffer, size_t count, blkno_t blkno) { hd_t *hd; hdc_t *hdc; int sectsleft; int nsects; int n; int result = 0; char *bufp; if (count == 0) { return 0; } bufp = (char *) buffer; hd = (hd_t *) bdev->privdata; hdc = hd->hdc; sectsleft = count / bdev->block_size; while (sectsleft > 0) { /* Select drive */ ide_select_drive(hd); /* Wait for controller ready */ result = ide_wait(hdc, HDCS_DRDY, HDTIMEOUT_DRDY); if (result != 0) { hdc->result = -EIO; break; } nsects = 1; /* Prepare transfer */ hdc->bufp = bufp; hdc->nsects = nsects; hdc->result = 0; hdc->dir = HD_XFER_WRITE; hdc->active = hd; hd_setup_transfer(hd, blkno, nsects); outb(hd->multsect > 1 ? HDCMD_MULTWRITE : HDCMD_WRITE, hdc->iobase + HDC_COMMAND); /* Wait for data ready */ if (!(inb(hdc->iobase + HDC_ALT_STATUS) & HDCS_DRQ)) { result = ide_wait(hdc, HDCS_DRQ, HDTIMEOUT_DRQ); if (result != 0) { hdc->result = -EIO; break; } } /* Write first sector(s) */ n = hd->multsect; if (n > nsects) { n = nsects; } while (n-- > 0) { pio_write_buffer(hd, hdc->bufp, bdev->block_size); hdc->bufp += bdev->block_size; } /* Wait until data written */ WAITQ_WAIT(&hdc->waitq, hdc->result); if (hdc->result < 0) { break; } /* Advance to next */ sectsleft -= nsects; bufp += nsects * bdev->block_size; blkno += nsects; /*WTF?*/ } /* Cleanup */ hdc->dir = HD_XFER_IDLE; hdc->active = NULL; /* * FIXME This assignment crashes writing, because * hdc->result equal 1 after writing. So, it set result to 1, afterward * (return result == 0 ? count : result) return 1. * --Alexander * result = hdc->result; */ return result == 0 ? count : result; }
static int hd_read_udma(block_dev_t *bdev, char *buffer, size_t count, blkno_t blkno) { hd_t *hd; hdc_t *hdc; int sectsleft; int nsects; int result = 0; char *bufp; if (count == 0) { return 0; } bufp = (char *) buffer; hd = (hd_t *) bdev->privdata; hdc = hd->hdc; sectsleft = count / SECTOR_SIZE; while (sectsleft > 0) { /* Select drive */ ide_select_drive(hd); /* Wait for controller ready */ result = ide_wait(hdc, HDCS_DRDY, HDTIMEOUT_DRDY); if (result != 0) { result = -EIO; break; } /* Calculate maximum number of sectors we can transfer */ if (sectsleft > 256) { nsects = 256; } else { nsects = sectsleft; } if (nsects > MAX_DMA_XFER_SIZE / SECTOR_SIZE) { nsects = MAX_DMA_XFER_SIZE / SECTOR_SIZE; } /* Prepare transfer */ result = 0; hdc->dir = HD_XFER_DMA; hdc->active = hd; hd_setup_transfer(hd, blkno, nsects); /* Setup DMA */ setup_dma(hdc, bufp, nsects * SECTOR_SIZE, BM_CR_WRITE); /* Start read */ outb(HDCMD_READDMA, hdc->iobase + HDC_COMMAND); start_dma(hdc); /* Stop DMA channel and check DMA status */ result = stop_dma(hdc); if (result < 0) { break; } /* Check controller status */ if (hdc->status & HDCS_ERR) { result = -EIO; break; } /* Advance to next */ sectsleft -= nsects; bufp += nsects * SECTOR_SIZE; } /* Cleanup */ hdc->dir = HD_XFER_IDLE; hdc->active = NULL; return result == 0 ? count : result; }
static int hd_read_pio(block_dev_t *bdev, char *buffer, size_t count, blkno_t blkno) { hd_t *hd; hdc_t *hdc; int sectsleft; int nsects; int result = 0; char *bufp; if (count == 0) { return 0; } bufp = (char *) buffer; hd = (hd_t *) bdev->privdata; hdc = hd->hdc; sectsleft = count / bdev->block_size; if (count % bdev->block_size) { sectsleft++; } while (sectsleft > 0) { /* Select drive */ ide_select_drive(hd); /* Wait for controller ready */ result = ide_wait(hdc, HDCS_DRDY, HDTIMEOUT_DRDY); if (result != 0) { hdc->result = -EIO; break; } nsects = 1; /* Prepare transfer */ hdc->bufp = bufp; hdc->nsects = nsects; hdc->result = 0; hdc->dir = HD_XFER_READ; hdc->active = hd; hd_setup_transfer(hd, blkno, nsects); outb(hd->multsect > 1 ? HDCMD_MULTREAD : HDCMD_READ, hdc->iobase + HDC_COMMAND); /* Wait until data read */ WAITQ_WAIT(&hdc->waitq, hdc->result); if (hdc->result < 0) { break; } /* Advance to next */ sectsleft -= nsects; bufp += nsects * bdev->block_size; blkno += nsects; /*WTF?*/ } /* Cleanup */ hdc->dir = HD_XFER_IDLE; hdc->active = NULL; if (0 < hdc->result) { result = hdc->result = 0; } return result == 0 ? count : result; }