Changeset 21989e5 in mainline


Ignore:
Timestamp:
2024-05-01T07:46:48Z (8 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
64cf7a3
Parents:
926d9d9b
Message:

Allow ata_bd to transfer more than 1 block in a single IO

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/block/ata_bd/ata_bd.c

    r926d9d9b r21989e5  
    115115    void *obuf, size_t obuf_size);
    116116static void disk_print_summary(disk_t *d);
     117static size_t ata_disk_maxnb(disk_t *d);
    117118static errno_t coord_calc(disk_t *d, uint64_t ba, block_coord_t *bc);
    118119static void coord_sc_program(ata_ctrl_t *ctrl, const block_coord_t *bc,
     
    514515{
    515516        disk_t *disk = bd_srv_disk(bd);
     517        size_t maxnb;
     518        size_t nb;
    516519        errno_t rc;
    517520
     
    519522                return EINVAL;
    520523
     524        /* Maximum number of blocks to transfer at the same time */
     525        maxnb = ata_disk_maxnb(disk);
    521526        while (cnt > 0) {
     527                nb = min(maxnb, cnt);
    522528                if (disk->dev_type == ata_reg_dev) {
    523                         rc = ata_rcmd_read(disk, ba, 1, buf);
     529                        rc = ata_rcmd_read(disk, ba, nb, buf);
    524530                } else {
    525                         rc = ata_pcmd_read_12(disk, ba, 1, buf,
     531                        rc = ata_pcmd_read_12(disk, ba, nb, buf,
    526532                            disk->block_size);
    527533                }
     
    530536                        return rc;
    531537
    532                 ++ba;
    533                 --cnt;
    534                 buf += disk->block_size;
     538                ba += nb;
     539                cnt -= nb;
     540                buf += disk->block_size * nb;
    535541        }
    536542
     
    551557{
    552558        disk_t *disk = bd_srv_disk(bd);
     559        size_t maxnb;
     560        size_t nb;
    553561        errno_t rc;
    554562
     
    559567                return EINVAL;
    560568
     569        /* Maximum number of blocks to transfer at the same time */
     570        maxnb = ata_disk_maxnb(disk);
    561571        while (cnt > 0) {
    562                 rc = ata_rcmd_write(disk, ba, 1, buf);
     572                nb = min(maxnb, cnt);
     573                rc = ata_rcmd_write(disk, ba, nb, buf);
    563574                if (rc != EOK)
    564575                        return rc;
    565576
    566                 ++ba;
    567                 --cnt;
    568                 buf += disk->block_size;
     577                ba += nb;
     578                cnt -= nb;
     579                buf += disk->block_size * nb;
    569580        }
    570581
     
    609620        uint16_t data;
    610621        size_t i;
     622        size_t bidx;
    611623        uint8_t status;
    612624
    613         /* XXX Support multiple blocks */
    614         assert(nblocks == 1);
     625        assert(nblocks > 0);
    615626        assert(blk_size % 2 == 0);
    616627
    617         if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
    618                 return EIO;
    619 
    620         if ((status & SR_DRQ) != 0) {
     628        bidx = 0;
     629        while (nblocks > 0) {
     630                if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
     631                        return EIO;
     632
     633                if ((status & SR_DRQ) == 0) {
     634                        break;
     635                }
     636
    621637                /* Read data from the device buffer. */
    622 
    623638                for (i = 0; i < blk_size / 2; i++) {
    624639                        data = pio_read_16(&ctrl->cmd->data_port);
    625                         ((uint16_t *) obuf)[i] = data;
    626                 }
     640                        ((uint16_t *) obuf)[bidx++] = data;
     641                }
     642
     643                --nblocks;
    627644        }
    628645
    629646        if ((status & SR_ERR) != 0)
     647                return EIO;
     648        if (nblocks > 0)
    630649                return EIO;
    631650
     
    639658        ata_ctrl_t *ctrl = disk->ctrl;
    640659        size_t i;
     660        size_t bidx;
    641661        uint8_t status;
    642662
    643         /* XXX Support multiple blocks */
    644         assert(nblocks == 1);
     663        assert(nblocks > 0);
    645664        assert(blk_size % 2 == 0);
    646665
    647         if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
    648                 return EIO;
    649 
    650         if ((status & SR_DRQ) != 0) {
     666        bidx = 0;
     667        while (nblocks > 0) {
     668                if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK)
     669                        return EIO;
     670
     671                if ((status & SR_DRQ) == 0)
     672                        break;
     673
    651674                /* Write data to the device buffer. */
    652 
    653675                for (i = 0; i < blk_size / 2; i++) {
    654                         pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) buf)[i]);
    655                 }
     676                        pio_write_16(&ctrl->cmd->data_port,
     677                            ((uint16_t *) buf)[bidx++]);
     678                }
     679
     680                --nblocks;
    656681        }
    657682
    658683        if (status & SR_ERR)
     684                return EIO;
     685        if (nblocks > 0)
    659686                return EIO;
    660687
     
    781808        uint8_t drv_head;
    782809        size_t data_size;
     810        size_t remain;
     811        size_t bidx;
    783812        uint16_t val;
    784813
     
    816845                pio_write_16(&ctrl->cmd->data_port, ((uint16_t *) cpkt)[i]);
    817846
    818         if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
    819                 fibril_mutex_unlock(&ctrl->lock);
    820                 return EIO;
    821         }
    822 
    823         if ((status & SR_DRQ) == 0) {
    824                 fibril_mutex_unlock(&ctrl->lock);
    825                 return EIO;
    826         }
    827 
    828         /* Read byte count. */
    829         data_size = (uint16_t) pio_read_8(&ctrl->cmd->cylinder_low) +
    830             ((uint16_t) pio_read_8(&ctrl->cmd->cylinder_high) << 8);
    831 
    832         /* Check whether data fits into output buffer. */
    833         if (data_size > obuf_size) {
    834                 /* Output buffer is too small to store data. */
    835                 fibril_mutex_unlock(&ctrl->lock);
    836                 return EIO;
    837         }
    838 
    839         /* Read data from the device buffer. */
    840         for (i = 0; i < (data_size + 1) / 2; i++) {
    841                 val = pio_read_16(&ctrl->cmd->data_port);
    842                 ((uint16_t *) obuf)[i] = val;
     847        bidx = 0;
     848        remain = obuf_size;
     849        while (remain > 0) {
     850                if (wait_status(ctrl, 0, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     851                        fibril_mutex_unlock(&ctrl->lock);
     852                        return EIO;
     853                }
     854
     855                if ((status & SR_DRQ) == 0)
     856                        break;
     857
     858                /* Read byte count. */
     859                data_size = (uint16_t) pio_read_8(&ctrl->cmd->cylinder_low) +
     860                    ((uint16_t) pio_read_8(&ctrl->cmd->cylinder_high) << 8);
     861
     862                /* Check whether data fits into output buffer. */
     863                if (data_size > obuf_size) {
     864                        /* Output buffer is too small to store data. */
     865                        fibril_mutex_unlock(&ctrl->lock);
     866                        return EIO;
     867                }
     868
     869                /* Read data from the device buffer. */
     870                for (i = 0; i < (data_size + 1) / 2; i++) {
     871                        val = pio_read_16(&ctrl->cmd->data_port);
     872                        ((uint16_t *) obuf)[bidx++] = val;
     873                }
     874
     875                remain -= data_size;
    843876        }
    844877
     
    849882
    850883        if (rcvd_size != NULL)
    851                 *rcvd_size = data_size;
     884                *rcvd_size = obuf_size - remain;
    852885        return EOK;
    853886}
     
    10401073
    10411074        /* Program block coordinates into the device. */
    1042         coord_sc_program(ctrl, &bc, 1);
     1075        coord_sc_program(ctrl, &bc, blk_cnt);
    10431076
    10441077        pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ?
     
    11001133
    11011134        /* Program block coordinates into the device. */
    1102         coord_sc_program(ctrl, &bc, 1);
     1135        coord_sc_program(ctrl, &bc, cnt);
    11031136
    11041137        pio_write_8(&ctrl->cmd->command, disk->amode == am_lba48 ?
     
    11501183        fibril_mutex_unlock(&ctrl->lock);
    11511184        return rc;
     1185}
     1186
     1187/** Get the maximum number of blocks to be transferred in one I/O
     1188 *
     1189 * @param d Disk
     1190 * @return Maximum number of blocks
     1191 */
     1192static size_t ata_disk_maxnb(disk_t *d)
     1193{
     1194        size_t maxnb;
     1195
     1196        maxnb = 0;
     1197
     1198        if (d->dev_type == ata_pkt_dev) {
     1199                /* Could be more depending on SCSI command support */
     1200                maxnb = 0x100;
     1201        } else {
     1202                switch (d->amode) {
     1203                case am_chs:
     1204                case am_lba28:
     1205                        maxnb = 0x100;
     1206                        break;
     1207                case am_lba48:
     1208                        maxnb = 0x10000;
     1209                        break;
     1210                }
     1211        }
     1212
     1213        /*
     1214         * If using DMA, this needs to be further restricted not to
     1215         * exceed DMA buffer size.
     1216         */
     1217        return maxnb;
    11521218}
    11531219
Note: See TracChangeset for help on using the changeset viewer.