Changeset 645d3832 in mainline
- Timestamp:
- 2024-06-10T17:29:13Z (6 months ago)
- 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)
- Location:
- uspace
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/block/pci-ide/main.c
r69c376b5 r645d3832 150 150 ctrl->dev = dev; 151 151 152 rc = pci_ide_ctrl_init(ctrl, &res); 153 if (rc != EOK) 154 goto error; 155 152 156 rc = pci_ide_channel_init(ctrl, &ctrl->channel[0], 0, &res); 153 157 if (rc == ENOENT) … … 333 337 ddf_msg(LVL_DEBUG, "pci_ide_dev_gone(%p)", dev); 334 338 339 rc = pci_ide_ctrl_fini(ctrl); 340 if (rc != EOK) 341 return rc; 342 335 343 rc = pci_ide_channel_fini(&ctrl->channel[0]); 336 344 if (rc != EOK) -
uspace/drv/block/pci-ide/pci-ide.c
r69c376b5 r645d3832 36 36 */ 37 37 38 #include <assert.h> 38 39 #include <ddi.h> 39 40 #include <ddf/interrupt.h> … … 67 68 static errno_t pci_ide_irq_enable(void *); 68 69 static errno_t pci_ide_irq_disable(void *); 70 static void pci_ide_dma_chan_setup(void *, void *, size_t, ata_dma_dir_t); 71 static void pci_ide_dma_chan_teardown(void *); 69 72 static errno_t pci_ide_add_device(void *, unsigned, void *); 70 73 static errno_t pci_ide_remove_device(void *, unsigned); … … 93 96 }; 94 97 98 /** Initialize PCI IDE controller. 99 * 100 * @param ctrl PCI IDE controller 101 * @param res Hardware resources 102 * 103 * @return EOK on success or an error code 104 */ 105 errno_t pci_ide_ctrl_init(pci_ide_ctrl_t *ctrl, pci_ide_hwres_t *res) 106 { 107 errno_t rc; 108 void *vaddr; 109 110 ddf_msg(LVL_DEBUG, "pci_ide_ctrl_init()"); 111 ctrl->bmregs_physical = res->bmregs; 112 113 ddf_msg(LVL_NOTE, "Bus master IDE regs I/O address: 0x%lx", 114 ctrl->bmregs_physical); 115 116 rc = pio_enable((void *)ctrl->bmregs_physical, sizeof(pci_ide_regs_t), 117 &vaddr); 118 if (rc != EOK) { 119 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space."); 120 return rc; 121 } 122 123 ctrl->bmregs = vaddr; 124 125 ddf_msg(LVL_DEBUG, "pci_ide_ctrl_init: DONE"); 126 return EOK; 127 } 128 129 /** Finalize PCI IDE controller. 130 * 131 * @param ctrl PCI IDE controller 132 * @return EOK on success or an error code 133 */ 134 errno_t pci_ide_ctrl_fini(pci_ide_ctrl_t *ctrl) 135 { 136 ddf_msg(LVL_DEBUG, ": pci_ide_ctrl_fini()"); 137 138 // XXX TODO 139 return EOK; 140 } 141 95 142 /** Initialize PCI IDE channel. */ 96 143 errno_t pci_ide_channel_init(pci_ide_ctrl_t *ctrl, pci_ide_channel_t *chan, … … 100 147 bool irq_inited = false; 101 148 ata_params_t params; 102 103 ddf_msg(LVL_DEBUG, "pci_ide_ctrl_init()"); 149 void *buffer; 150 151 ddf_msg(LVL_DEBUG, "pci_ide_channel_init()"); 104 152 105 153 chan->ctrl = ctrl; … … 116 164 } 117 165 166 chan->dma_buf_size = 8192; 167 118 168 ddf_msg(LVL_NOTE, "I/O address %p/%p", (void *) chan->cmd_physical, 119 169 (void *) chan->ctl_physical); … … 128 178 if (rc != EOK) { 129 179 ddf_msg(LVL_NOTE, "init IRQ failed"); 130 return rc;180 goto error; 131 181 } 132 182 133 183 irq_inited = true; 134 184 135 ddf_msg(LVL_DEBUG, "pci_ide_ctrl_init(): Initialize IDE channel"); 185 ddf_msg(LVL_DEBUG, "Allocate PRD table"); 186 187 buffer = AS_AREA_ANY; 188 rc = dmamem_map_anonymous(sizeof (pci_ide_prd_t), DMAMEM_4GiB | 0xffff, 189 AS_AREA_WRITE | AS_AREA_READ, 0, &chan->prdt_pa, &buffer); 190 if (rc != EOK) { 191 ddf_msg(LVL_NOTE, "Failed allocating PRD table."); 192 goto error; 193 } 194 195 chan->prdt = (pci_ide_prd_t *)buffer; 196 197 ddf_msg(LVL_DEBUG, "Allocate DMA buffer"); 198 199 buffer = AS_AREA_ANY; 200 rc = dmamem_map_anonymous(chan->dma_buf_size, DMAMEM_4GiB | 0xffff, 201 AS_AREA_WRITE | AS_AREA_READ, 0, &chan->dma_buf_pa, &buffer); 202 if (rc != EOK) { 203 ddf_msg(LVL_NOTE, "Failed allocating PRD table."); 204 goto error; 205 } 206 207 chan->dma_buf = buffer; 208 209 /* Populate PRD with information on our single DMA buffer */ 210 chan->prdt->pba = host2uint32_t_le(chan->dma_buf_pa); 211 chan->prdt->bcnt = host2uint16_t_le(chan->dma_buf_size); 212 chan->prdt->eot_res = host2uint16_t_le(pci_ide_prd_eot); 213 214 /* Program PRD table pointer register */ 215 if (chan_id == 0) { 216 pio_write_32(&chan->ctrl->bmregs->bmidtpp, 217 (uint32_t)chan->prdt_pa); 218 } else { 219 pio_write_32(&chan->ctrl->bmregs->bmidtps, 220 (uint32_t)chan->prdt_pa); 221 } 222 223 ddf_msg(LVL_DEBUG, "pci_ide_channel_init(): Initialize IDE channel"); 136 224 137 225 params.arg = (void *)chan; 138 226 params.have_irq = (chan->irq >= 0) ? true : false; 227 params.use_dma = true; 139 228 params.write_data_16 = pci_ide_write_data_16; 140 229 params.read_data_16 = pci_ide_read_data_16; … … 145 234 params.irq_enable = pci_ide_irq_enable; 146 235 params.irq_disable = pci_ide_irq_disable; 236 params.dma_chan_setup = pci_ide_dma_chan_setup; 237 params.dma_chan_teardown = pci_ide_dma_chan_teardown; 147 238 params.add_device = pci_ide_add_device; 148 239 params.remove_device = pci_ide_remove_device; … … 160 251 goto error; 161 252 162 ddf_msg(LVL_DEBUG, "pci_ide_c trl_init: DONE");253 ddf_msg(LVL_DEBUG, "pci_ide_channel_init: DONE"); 163 254 return EOK; 164 255 error: … … 174 265 errno_t rc; 175 266 176 ddf_msg(LVL_DEBUG, ": pci_ide_c trl_remove()");267 ddf_msg(LVL_DEBUG, ": pci_ide_channel_fini()"); 177 268 178 269 fibril_mutex_lock(&chan->lock); … … 212 303 213 304 chan->ctl = vaddr; 305 306 rc = pio_enable((void *) chan->cmd_physical, sizeof(ata_cmd_t), &vaddr); 307 if (rc != EOK) { 308 ddf_msg(LVL_ERROR, "Cannot initialize device I/O space."); 309 return rc; 310 } 311 312 chan->cmd = vaddr; 313 214 314 return EOK; 215 315 } … … 435 535 } 436 536 537 /** Set up DMA channel callback handler 538 * 539 * @param arg Argument (pci_ide_channel_t *) 540 * @param buf Buffer 541 * @param buf_size Buffer size 542 * @param dir DMA transfer direction 543 */ 544 static void pci_ide_dma_chan_setup(void *arg, void *buf, size_t buf_size, 545 ata_dma_dir_t dir) 546 { 547 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg; 548 uint8_t *bmicx; 549 uint8_t val; 550 551 /* Needed later in teardown */ 552 chan->cur_dir = dir; 553 chan->cur_buf = buf; 554 chan->cur_buf_size = buf_size; 555 556 if (dir == ata_dma_write) { 557 assert(buf_size < chan->dma_buf_size); 558 memcpy(chan->dma_buf, buf, buf_size); 559 } 560 561 /* Primary or secondary channel control register */ 562 bmicx = (chan->chan_id == 0) ? &chan->ctrl->bmregs->bmicp : 563 &chan->ctrl->bmregs->bmics; 564 565 /* Set read / write */ 566 val = (dir == ata_dma_write) ? bmicx_rwcon : 0; 567 pio_write_8(bmicx, val); 568 569 /* Start bus master DMA engine */ 570 val = val | bmicx_ssbm; 571 pio_write_8(bmicx, val); 572 } 573 574 /** Tear down DMA channel callback handler 575 * 576 * @param arg Argument (pci_ide_channel_t *) 577 */ 578 static void pci_ide_dma_chan_teardown(void *arg) 579 { 580 pci_ide_channel_t *chan = (pci_ide_channel_t *)arg; 581 uint8_t *bmicx; 582 uint8_t val; 583 584 /* Primary or secondary channel control register */ 585 bmicx = (chan->chan_id == 0) ? &chan->ctrl->bmregs->bmicp : 586 &chan->ctrl->bmregs->bmics; 587 588 /* Stop bus master DMA engine clear SSBM but keep RWCON the same */ 589 val = (chan->cur_dir == ata_dma_write) ? bmicx_rwcon : 0; 590 pio_write_8(bmicx, val); 591 592 if (chan->cur_dir == ata_dma_read) { 593 assert(chan->cur_buf_size < chan->dma_buf_size); 594 memcpy(chan->cur_buf, chan->dma_buf, chan->cur_buf_size); 595 } 596 } 597 437 598 /** Add ATA device callback handler. 438 599 * -
uspace/drv/block/pci-ide/pci-ide.h
r69c376b5 r645d3832 42 42 #include <stdbool.h> 43 43 #include <stdint.h> 44 #include "pci-ide_hw.h" 44 45 45 46 #define NAME "pci-ide" … … 79 80 uint8_t irq_status; 80 81 82 /** Physical region descriptor table */ 83 pci_ide_prd_t *prdt; 84 /** Physical region descriptor table physical address */ 85 uintptr_t prdt_pa; 86 /** DMA buffer */ 87 void *dma_buf; 88 /** DMA buffer physical address */ 89 uintptr_t dma_buf_pa; 90 /** DMA buffer size */ 91 size_t dma_buf_size; 92 /** Current DMA transfer direction */ 93 ata_dma_dir_t cur_dir; 94 /** Current data buffer */ 95 void *cur_buf; 96 /** Current data buffer size */ 97 size_t cur_buf_size; 98 81 99 /** Libata ATA channel */ 82 100 ata_channel_t *channel; … … 92 110 ddf_dev_t *dev; 93 111 112 /** I/O base address of bus master IDE registers */ 113 uintptr_t bmregs_physical; 114 /** Bus master IDE registers */ 115 pci_ide_regs_t *bmregs; 94 116 /** Primary and secondary channel */ 95 117 pci_ide_channel_t channel[2]; … … 102 124 } pci_ide_fun_t; 103 125 126 extern errno_t pci_ide_ctrl_init(pci_ide_ctrl_t *, pci_ide_hwres_t *); 127 extern errno_t pci_ide_ctrl_fini(pci_ide_ctrl_t *); 104 128 extern errno_t pci_ide_channel_init(pci_ide_ctrl_t *, pci_ide_channel_t *, 105 129 unsigned, pci_ide_hwres_t *); -
uspace/drv/block/pci-ide/pci-ide_hw.h
r69c376b5 r645d3832 98 98 }; 99 99 100 enum { 101 pci_ide_prd_eot = 0x8000 102 }; 103 104 /** PIIX physical region descriptor */ 105 typedef struct { 106 /** Physical base address */ 107 uint32_t pba; 108 /** Byte count */ 109 uint16_t bcnt; 110 /** EOT / reserved */ 111 uint16_t eot_res; 112 } pci_ide_prd_t; 113 100 114 #endif 101 115 -
uspace/lib/ata/include/ata/ata.h
r69c376b5 r645d3832 47 47 struct ata_device; 48 48 49 /** ATA DMA direction */ 50 typedef enum { 51 /** DMA read */ 52 ata_dma_read, 53 /** DMA write */ 54 ata_dma_write 55 } ata_dma_dir_t; 56 49 57 /** ATA channel creation parameters */ 50 58 typedef struct { … … 53 61 /** IRQ is available */ 54 62 bool have_irq; 63 /** Use DMA transfers */ 64 bool use_dma; 55 65 /** Read 16 bits from the data port */ 56 66 void (*write_data_16)(void *, uint16_t *, size_t); … … 69 79 /** Disable interrupts */ 70 80 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 *); 71 85 /** Add new device */ 72 86 errno_t (*add_device)(void *, unsigned, void *); -
uspace/lib/ata/include/ata/ata_hw.h
r69c376b5 r645d3832 141 141 CMD_READ_SECTORS = 0x20, 142 142 CMD_READ_SECTORS_EXT = 0x24, 143 CMD_READ_DMA_EXT = 0x25, 143 144 CMD_WRITE_SECTORS = 0x30, 144 145 CMD_WRITE_SECTORS_EXT = 0x34, 146 CMD_WRITE_DMA_EXT = 0x35, 145 147 CMD_PACKET = 0xA0, 146 148 CMD_IDENTIFY_PKT_DEV = 0xA1, 149 CMD_READ_DMA = 0xC8, 150 CMD_WRITE_DMA = 0xCA, 147 151 CMD_IDENTIFY_DRIVE = 0xEC, 148 152 CMD_FLUSH_CACHE = 0xE7 -
uspace/lib/ata/src/ata.c
r69c376b5 r645d3832 118 118 unsigned); 119 119 static errno_t wait_irq(ata_channel_t *, uint8_t *, unsigned); 120 static void ata_dma_chan_setup(ata_device_t *, void *, size_t, ata_dma_dir_t); 121 static void ata_dma_chan_teardown(ata_device_t *); 120 122 121 123 static bd_ops_t ata_bd_ops = { … … 849 851 } 850 852 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 */ 863 static 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 851 896 /** Issue IDENTIFY DEVICE command. 852 897 * … … 1184 1229 uint8_t drv_head; 1185 1230 block_coord_t bc; 1231 uint8_t cmd; 1186 1232 errno_t rc; 1187 1233 … … 1222 1268 coord_sc_program(chan, &bc, blk_cnt); 1223 1269 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 } 1229 1291 1230 1292 fibril_mutex_unlock(&chan->lock); 1231 1293 1232 if (rc != EOK)1233 ata_msg_note(chan, "ata_rcmd_read() -> pio_data_in->%d", rc);1234 1294 return rc; 1235 1295 } … … 1250 1310 uint8_t drv_head; 1251 1311 block_coord_t bc; 1312 uint8_t cmd; 1252 1313 errno_t rc; 1253 1314 … … 1284 1345 coord_sc_program(chan, &bc, cnt); 1285 1346 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 } 1291 1368 1292 1369 fibril_mutex_unlock(&chan->lock); … … 1522 1599 } 1523 1600 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 */ 1608 static 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 */ 1619 static void ata_dma_chan_teardown(ata_device_t *device) 1620 { 1621 device->chan->params.dma_chan_teardown(device->chan->params.arg); 1622 } 1623 1524 1624 /** Interrupt handler. 1525 1625 *
Note:
See TracChangeset
for help on using the changeset viewer.