Changeset 645d3832 in mainline for uspace/lib


Ignore:
Timestamp:
2024-06-10T17:29:13Z (16 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
a38d504
Parents:
69c376b5
git-author:
Jiri Svoboda <jiri@…> (2024-06-10 17:24:58)
git-committer:
Jiri Svoboda <jiri@…> (2024-06-10 17:29:13)
Message:

Add DMA support to PCI-IDE / libata (register commands)

Location:
uspace/lib/ata
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ata/include/ata/ata.h

    r69c376b5 r645d3832  
    4747struct ata_device;
    4848
     49/** ATA DMA direction */
     50typedef enum {
     51        /** DMA read */
     52        ata_dma_read,
     53        /** DMA write */
     54        ata_dma_write
     55} ata_dma_dir_t;
     56
    4957/** ATA channel creation parameters */
    5058typedef struct {
     
    5361        /** IRQ is available */
    5462        bool have_irq;
     63        /** Use DMA transfers */
     64        bool use_dma;
    5565        /** Read 16 bits from the data port */
    5666        void (*write_data_16)(void *, uint16_t *, size_t);
     
    6979        /** Disable interrupts */
    7080        errno_t (*irq_disable)(void *);
     81        /** Set up DMA channel */
     82        void (*dma_chan_setup)(void *, void *, size_t, ata_dma_dir_t);
     83        /** Set up DMA channel */
     84        void (*dma_chan_teardown)(void *);
    7185        /** Add new device */
    7286        errno_t (*add_device)(void *, unsigned, void *);
  • uspace/lib/ata/include/ata/ata_hw.h

    r69c376b5 r645d3832  
    141141        CMD_READ_SECTORS        = 0x20,
    142142        CMD_READ_SECTORS_EXT    = 0x24,
     143        CMD_READ_DMA_EXT        = 0x25,
    143144        CMD_WRITE_SECTORS       = 0x30,
    144145        CMD_WRITE_SECTORS_EXT   = 0x34,
     146        CMD_WRITE_DMA_EXT       = 0x35,
    145147        CMD_PACKET              = 0xA0,
    146148        CMD_IDENTIFY_PKT_DEV    = 0xA1,
     149        CMD_READ_DMA            = 0xC8,
     150        CMD_WRITE_DMA           = 0xCA,
    147151        CMD_IDENTIFY_DRIVE      = 0xEC,
    148152        CMD_FLUSH_CACHE         = 0xE7
  • uspace/lib/ata/src/ata.c

    r69c376b5 r645d3832  
    118118    unsigned);
    119119static errno_t wait_irq(ata_channel_t *, uint8_t *, unsigned);
     120static void ata_dma_chan_setup(ata_device_t *, void *, size_t, ata_dma_dir_t);
     121static void ata_dma_chan_teardown(ata_device_t *);
    120122
    121123static bd_ops_t ata_bd_ops = {
     
    849851}
    850852
     853/** DMA command protocol.
     854 *
     855 * @param device ATA device
     856 * @param cmd Command code
     857 * @param buf Data buffer
     858 * @param buf_size Data buffer size in bytes
     859 * @param dir DMA direction
     860 *
     861 * @return EOK on success or an error code
     862 */
     863static errno_t ata_dma_proto(ata_device_t *device, uint8_t cmd, void *buf,
     864    size_t buf_size, ata_dma_dir_t dir)
     865{
     866        ata_channel_t *chan = device->chan;
     867        uint8_t status;
     868        errno_t rc;
     869
     870        /* Set up DMA channel */
     871        ata_dma_chan_setup(device, buf, buf_size, dir);
     872
     873        ata_write_cmd_8(chan, REG_COMMAND, cmd);
     874
     875        if (chan->params.have_irq)
     876                rc = wait_irq(chan, &status, TIMEOUT_BSY);
     877        else
     878                rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY);
     879
     880        if (rc != EOK) {
     881                ata_msg_debug(chan, "wait_irq/wait_status failed");
     882                return EIO;
     883        }
     884
     885        /* Tear down DMA channel */
     886        ata_dma_chan_teardown(device);
     887
     888        if ((status & SR_ERR) != 0) {
     889                ata_msg_debug(chan, "status & SR_ERR != 0");
     890                return EIO;
     891        }
     892
     893        return EOK;
     894}
     895
    851896/** Issue IDENTIFY DEVICE command.
    852897 *
     
    11841229        uint8_t drv_head;
    11851230        block_coord_t bc;
     1231        uint8_t cmd;
    11861232        errno_t rc;
    11871233
     
    12221268        coord_sc_program(chan, &bc, blk_cnt);
    12231269
    1224         ata_write_cmd_8(chan, REG_COMMAND, device->amode == am_lba48 ?
    1225             CMD_READ_SECTORS_EXT : CMD_READ_SECTORS);
    1226 
    1227         rc = ata_pio_data_in(device, buf, blk_cnt * device->block_size,
    1228             device->block_size, blk_cnt);
     1270        if (chan->params.use_dma) {
     1271                cmd = (device->amode == am_lba48) ? CMD_READ_DMA_EXT :
     1272                    CMD_READ_DMA;
     1273
     1274                rc = ata_dma_proto(device, cmd, buf,
     1275                    blk_cnt * device->block_size, ata_dma_read);
     1276                if (rc != EOK) {
     1277                        ata_msg_note(chan, "ata_rcmd_read() -> dma_proto->%d",
     1278                            rc);
     1279                }
     1280        } else {
     1281                ata_write_cmd_8(chan, REG_COMMAND, device->amode == am_lba48 ?
     1282                    CMD_READ_SECTORS_EXT : CMD_READ_SECTORS);
     1283
     1284                rc = ata_pio_data_in(device, buf, blk_cnt * device->block_size,
     1285                    device->block_size, blk_cnt);
     1286                if (rc != EOK) {
     1287                        ata_msg_note(chan, "ata_rcmd_read() -> pio_data_in->%d",
     1288                            rc);
     1289                }
     1290        }
    12291291
    12301292        fibril_mutex_unlock(&chan->lock);
    12311293
    1232         if (rc != EOK)
    1233                 ata_msg_note(chan, "ata_rcmd_read() -> pio_data_in->%d", rc);
    12341294        return rc;
    12351295}
     
    12501310        uint8_t drv_head;
    12511311        block_coord_t bc;
     1312        uint8_t cmd;
    12521313        errno_t rc;
    12531314
     
    12841345        coord_sc_program(chan, &bc, cnt);
    12851346
    1286         ata_write_cmd_8(chan, REG_COMMAND, device->amode == am_lba48 ?
    1287             CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS);
    1288 
    1289         rc = ata_pio_data_out(device, buf, cnt * device->block_size,
    1290             device->block_size, cnt);
     1347        if (chan->params.use_dma) {
     1348                cmd = (device->amode == am_lba48) ? CMD_WRITE_DMA_EXT :
     1349                    CMD_WRITE_DMA;
     1350
     1351                rc = ata_dma_proto(device, cmd, (void *)buf,
     1352                    cnt * device->block_size, ata_dma_write);
     1353                if (rc != EOK) {
     1354                        ata_msg_note(chan, "ata_rcmd_write() -> dma_proto->%d",
     1355                            rc);
     1356                }
     1357        } else {
     1358                ata_write_cmd_8(chan, REG_COMMAND, device->amode == am_lba48 ?
     1359                    CMD_WRITE_SECTORS_EXT : CMD_WRITE_SECTORS);
     1360
     1361                rc = ata_pio_data_out(device, buf, cnt * device->block_size,
     1362                    device->block_size, cnt);
     1363                if (rc != EOK) {
     1364                        ata_msg_note(chan,
     1365                            "ata_rcmd_read() -> pio_data_out->%d", rc);
     1366                }
     1367        }
    12911368
    12921369        fibril_mutex_unlock(&chan->lock);
     
    15221599}
    15231600
     1601/** Set up DMA channel.
     1602 *
     1603 * @param device ATA device
     1604 * @param buf Data buffer
     1605 * @param buf_size Data buffer size in bytes
     1606 * @param dir DMA direction
     1607 */
     1608static void ata_dma_chan_setup(ata_device_t *device, void *buf,
     1609    size_t buf_size, ata_dma_dir_t dir)
     1610{
     1611        device->chan->params.dma_chan_setup(device->chan->params.arg,
     1612            buf, buf_size, dir);
     1613}
     1614
     1615/** Tear down DMA channel.
     1616 *
     1617 * @param device ATA device
     1618 */
     1619static void ata_dma_chan_teardown(ata_device_t *device)
     1620{
     1621        device->chan->params.dma_chan_teardown(device->chan->params.arg);
     1622}
     1623
    15241624/** Interrupt handler.
    15251625 *
Note: See TracChangeset for help on using the changeset viewer.