Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ata/src/ata.c

    r07039850 r743f2cdd  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    8484static uint8_t ata_read_cmd_8(ata_channel_t *, uint16_t);
    8585static void ata_write_cmd_8(ata_channel_t *, uint16_t, uint8_t);
    86 static void ata_write_ctl_8(ata_channel_t *, uint16_t, uint8_t);
    8786
    8887static errno_t ata_bd_init_irq(ata_channel_t *);
     
    9796static errno_t ata_bd_get_block_size(bd_srv_t *, size_t *);
    9897static errno_t ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
    99 static errno_t ata_bd_eject(bd_srv_t *);
    10098static errno_t ata_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
    10199
     
    107105static errno_t ata_identify_dev(ata_device_t *, void *);
    108106static errno_t ata_identify_pkt_dev(ata_device_t *, void *);
    109 static errno_t ata_cmd_packet_nondata(ata_device_t *, const void *, size_t);
    110 static errno_t ata_cmd_packet_din(ata_device_t *, const void *, size_t, void *,
     107static errno_t ata_cmd_packet(ata_device_t *, const void *, size_t, void *,
    111108    size_t, size_t *);
    112109static errno_t ata_pcmd_inquiry(ata_device_t *, void *, size_t, size_t *);
     
    114111static errno_t ata_pcmd_read_capacity(ata_device_t *, uint64_t *, size_t *);
    115112static errno_t ata_pcmd_read_toc(ata_device_t *, uint8_t, void *, size_t);
    116 static errno_t ata_pcmd_start_stop_unit(ata_device_t *, uint8_t);
    117113static void disk_print_summary(ata_device_t *);
    118114static size_t ata_disk_maxnb(ata_device_t *);
     
    133129        .get_block_size = ata_bd_get_block_size,
    134130        .get_num_blocks = ata_bd_get_num_blocks,
    135         .sync_cache = ata_bd_sync_cache,
    136         .eject = ata_bd_eject
     131        .sync_cache = ata_bd_sync_cache
    137132};
    138133
     
    156151{
    157152        ata_channel_t *chan;
    158         int i;
    159153
    160154        chan = calloc(1, sizeof(ata_channel_t));
     
    168162        fibril_mutex_initialize(&chan->irq_lock);
    169163        fibril_condvar_initialize(&chan->irq_cv);
    170 
    171         for (i = 0; i < MAX_DEVICES; i++)
    172                 chan->device[i].chan = chan;
    173164
    174165        *rchan = chan;
     
    262253
    263254        for (i = 0; i < MAX_DEVICES; i++) {
    264                 if (chan->device[i].present == false)
    265                         continue;
    266 
    267255                rc = ata_device_remove(&chan->device[i]);
    268256                if (rc != EOK) {
    269257                        ata_msg_error(chan, "Unable to remove device %d.", i);
    270                         fibril_mutex_unlock(&chan->lock);
    271258                        return rc;
    272259                }
     
    275262        ata_bd_fini_irq(chan);
    276263        fibril_mutex_unlock(&chan->lock);
    277         free(chan);
    278 
    279         return rc;
    280 }
    281 
    282 /** Quiesce ATA channel. */
    283 void ata_channel_quiesce(ata_channel_t *chan)
    284 {
    285         ata_msg_debug(chan, ": ata_channel_quiesce()");
    286 
    287         fibril_mutex_lock(&chan->lock);
    288         ata_write_ctl_8(chan, REG_DEVCTL, DCR_SRST | DCR_nIEN);
    289         fibril_mutex_unlock(&chan->lock);
     264
     265        return EOK;
    290266}
    291267
     
    359335{
    360336        return chan->params.write_cmd_8(chan->params.arg, port, value);
    361 }
    362 
    363 /** Write 8 bits to 8-bit control port.
    364  *
    365  * @param chan ATA channel
    366  * @param port Port number
    367  * @param value Register value
    368  */
    369 static void ata_write_ctl_8(ata_channel_t *chan, uint16_t port, uint8_t value)
    370 {
    371         return chan->params.write_ctl_8(chan->params.arg, port, value);
    372337}
    373338
     
    528493        unsigned i;
    529494
     495        d->chan = chan;
    530496        d->device_id = device_id;
    531497        d->present = false;
     
    784750}
    785751
    786 /** Eject medium. */
    787 static errno_t ata_bd_eject(bd_srv_t *bd)
    788 {
    789         ata_device_t *device = bd_srv_device(bd);
    790 
    791         ata_msg_debug(device->chan, "ata_bd_eject()");
    792         return ata_pcmd_start_stop_unit(device, ssf_pc_no_change |
    793             ssf_loej);
    794 }
    795 
    796752/** PIO data-in command protocol. */
    797753static errno_t ata_pio_data_in(ata_device_t *device, void *obuf, size_t obuf_size,
     
    11241080}
    11251081
    1126 /** Issue packet command (i. e. write a command packet to the device)
    1127  * with no data transfer.
     1082/** Issue packet command (i. e. write a command packet to the device).
     1083 *
     1084 * Only data-in commands are supported (e.g. inquiry, read).
    11281085 *
    11291086 * @param device        Device
    1130  * @param cpkt          Command packet
    1131  * @param cpkt_size     Command packet size in bytes
    1132  *
    1133  * @return EOK on success, EIO on error.
    1134  */
    1135 static errno_t ata_cmd_packet_nondata(ata_device_t *device, const void *cpkt,
    1136     size_t cpkt_size)
    1137 {
    1138         ata_channel_t *chan = device->chan;
    1139         uint8_t status;
    1140         uint8_t drv_head;
    1141         errno_t rc;
    1142 
    1143         ata_msg_debug(chan, "ata_cmd_packet_nondata()");
    1144 
    1145         fibril_mutex_lock(&chan->lock);
    1146 
    1147         /* New value for Drive/Head register */
    1148         drv_head =
    1149             ((disk_dev_idx(device) != 0) ? DHR_DRV : 0);
    1150 
    1151         if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
    1152                 fibril_mutex_unlock(&chan->lock);
    1153                 return EIO;
    1154         }
    1155 
    1156         ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
    1157 
    1158         if (wait_status(chan, 0, ~(SR_BSY | SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
    1159                 fibril_mutex_unlock(&chan->lock);
    1160                 return EIO;
    1161         }
    1162 
    1163         ata_write_cmd_8(chan, REG_COMMAND, CMD_PACKET);
    1164 
    1165         if (wait_status(chan, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
    1166                 if (chan->params.use_dma)
    1167                         ata_dma_chan_teardown(device);
    1168                 fibril_mutex_unlock(&chan->lock);
    1169                 return EIO;
    1170         }
    1171 
    1172         /* Write command packet. */
    1173         ata_write_data_16(chan, ((uint16_t *) cpkt), (cpkt_size + 1) / 2);
    1174 
    1175         rc = ata_pio_nondata(device);
    1176 
    1177         fibril_mutex_unlock(&chan->lock);
    1178 
    1179         return rc;
    1180 }
    1181 
    1182 /** Issue packet command (i. e. write a command packet to the device)
    1183  * performing data-in transfer.
    1184  *
    1185  * @param device        Device
    1186  * @param cpkt          Command packet
    1187  * @param cpkt_size     Command packet size in bytes
    11881087 * @param obuf          Buffer for storing data read from device
    11891088 * @param obuf_size     Size of obuf in bytes
     
    11921091 * @return EOK on success, EIO on error.
    11931092 */
    1194 static errno_t ata_cmd_packet_din(ata_device_t *device, const void *cpkt,
    1195     size_t cpkt_size, void *obuf, size_t obuf_size, size_t *rcvd_size)
     1093static errno_t ata_cmd_packet(ata_device_t *device, const void *cpkt, size_t cpkt_size,
     1094    void *obuf, size_t obuf_size, size_t *rcvd_size)
    11961095{
    11971096        ata_channel_t *chan = device->chan;
     
    12881187        cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff));
    12891188
    1290         rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size,
    1291             rcvd_size);
     1189        rc = ata_cmd_packet(device, cpb, sizeof(cpb), obuf, obuf_size, rcvd_size);
    12921190        if (rc != EOK)
    12931191                return rc;
     
    13151213        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
    13161214
    1317         rc = ata_cmd_packet_din(device, &cdb, sizeof(cdb), &data, sizeof(data),
    1318             &rsize);
     1215        rc = ata_cmd_packet(device, &cdb, sizeof(cdb), &data, sizeof(data), &rsize);
    13191216        if (rc != EOK)
    13201217                return rc;
     
    13571254        cp.xfer_len = host2uint32_t_be(cnt);
    13581255
    1359         rc = ata_cmd_packet_din(device, &cp, sizeof(cp), obuf, obuf_size, NULL);
     1256        rc = ata_cmd_packet(device, &cp, sizeof(cp), obuf, obuf_size, NULL);
    13601257        if (rc != EOK)
    13611258                return rc;
     
    13971294        cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
    13981295
    1399         rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size,
    1400             NULL);
     1296        rc = ata_cmd_packet(device, cpb, sizeof(cpb), obuf, obuf_size, NULL);
    14011297        if (rc != EOK)
    14021298                return rc;
    1403 
    1404         return EOK;
    1405 }
    1406 
    1407 /** Issue Start Stop Unit command.
    1408  *
    1409  * @param device        Device
    1410  * @param flags         Flags field of Start Stop Unit command (ssf_*)
    1411  * @return EOK on success, EIO on error.
    1412  */
    1413 static errno_t ata_pcmd_start_stop_unit(ata_device_t *device, uint8_t flags)
    1414 {
    1415         uint8_t cpb[12];
    1416         scsi_cdb_start_stop_unit_t *cp = (scsi_cdb_start_stop_unit_t *)cpb;
    1417         errno_t rc;
    1418 
    1419         ata_msg_debug(device->chan, "ata_pcmd_start_stop_unit(device, 0x%x)",
    1420             flags);
    1421 
    1422         memset(cpb, 0, sizeof(cpb));
    1423 
    1424         /*
    1425          * For SFF 8020 compliance the command must be padded to 12 bytes.
    1426          */
    1427         cp->op_code = SCSI_CMD_START_STOP_UNIT;
    1428         cp->immed = 0;
    1429         cp->flags = flags;
    1430         cp->control = 0;
    1431 
    1432         rc = ata_cmd_packet_nondata(device, cpb, sizeof(cpb));
    1433         if (rc != EOK)
    1434                 return rc;
    1435 
    1436         ata_msg_debug(device->chan, "ata_pcmd_start_stop_unit(): "
    1437             "ata_cmd_packet_nondata -> %d", rc);
    14381299
    14391300        return EOK;
     
    16681529         * exceed DMA buffer size.
    16691530         */
    1670         if (d->chan->params.use_dma) {
    1671                 dma_maxnb = d->chan->params.max_dma_xfer / d->block_size;
    1672                 if (dma_maxnb < maxnb)
    1673                         maxnb = dma_maxnb;
    1674         }
     1531        dma_maxnb = d->chan->params.max_dma_xfer / d->block_size;
     1532        if (dma_maxnb < maxnb)
     1533                maxnb = dma_maxnb;
    16751534
    16761535        return maxnb;
Note: See TracChangeset for help on using the changeset viewer.