Changeset 4285f384 in mainline for uspace/lib/ata/src/ata.c


Ignore:
Timestamp:
2025-02-25T20:25:43Z (16 hours ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Parents:
d231a54
Message:

Allow physically ejecting CD-ROM using vol eject -s

File:
1 edited

Legend:

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

    rd231a54 r4285f384  
    9696static errno_t ata_bd_get_block_size(bd_srv_t *, size_t *);
    9797static errno_t ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
     98static errno_t ata_bd_eject(bd_srv_t *);
    9899static errno_t ata_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
    99100
     
    105106static errno_t ata_identify_dev(ata_device_t *, void *);
    106107static errno_t ata_identify_pkt_dev(ata_device_t *, void *);
    107 static errno_t ata_cmd_packet(ata_device_t *, const void *, size_t, void *,
     108static errno_t ata_cmd_packet_nondata(ata_device_t *, const void *, size_t);
     109static errno_t ata_cmd_packet_din(ata_device_t *, const void *, size_t, void *,
    108110    size_t, size_t *);
    109111static errno_t ata_pcmd_inquiry(ata_device_t *, void *, size_t, size_t *);
     
    111113static errno_t ata_pcmd_read_capacity(ata_device_t *, uint64_t *, size_t *);
    112114static errno_t ata_pcmd_read_toc(ata_device_t *, uint8_t, void *, size_t);
     115static errno_t ata_pcmd_start_stop_unit(ata_device_t *, uint8_t);
    113116static void disk_print_summary(ata_device_t *);
    114117static size_t ata_disk_maxnb(ata_device_t *);
     
    129132        .get_block_size = ata_bd_get_block_size,
    130133        .get_num_blocks = ata_bd_get_num_blocks,
    131         .sync_cache = ata_bd_sync_cache
     134        .sync_cache = ata_bd_sync_cache,
     135        .eject = ata_bd_eject
    132136};
    133137
     
    758762}
    759763
     764/** Eject medium. */
     765static errno_t ata_bd_eject(bd_srv_t *bd)
     766{
     767        ata_device_t *device = bd_srv_device(bd);
     768
     769        ata_msg_debug(device->chan, "ata_bd_eject()");
     770        return ata_pcmd_start_stop_unit(device, ssf_pc_no_change |
     771            ssf_loej);
     772}
     773
    760774/** PIO data-in command protocol. */
    761775static errno_t ata_pio_data_in(ata_device_t *device, void *obuf, size_t obuf_size,
     
    10881102}
    10891103
    1090 /** Issue packet command (i. e. write a command packet to the device).
    1091  *
    1092  * Only data-in commands are supported (e.g. inquiry, read).
     1104/** Issue packet command (i. e. write a command packet to the device)
     1105 * with no data transfer.
    10931106 *
    10941107 * @param device        Device
     1108 * @param cpkt          Command packet
     1109 * @param cpkt_size     Command packet size in bytes
     1110 *
     1111 * @return EOK on success, EIO on error.
     1112 */
     1113static errno_t ata_cmd_packet_nondata(ata_device_t *device, const void *cpkt,
     1114    size_t cpkt_size)
     1115{
     1116        ata_channel_t *chan = device->chan;
     1117        uint8_t status;
     1118        uint8_t drv_head;
     1119        errno_t rc;
     1120
     1121        ata_msg_debug(chan, "ata_cmd_packet_nondata()");
     1122
     1123        fibril_mutex_lock(&chan->lock);
     1124
     1125        /* New value for Drive/Head register */
     1126        drv_head =
     1127            ((disk_dev_idx(device) != 0) ? DHR_DRV : 0);
     1128
     1129        if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) {
     1130                fibril_mutex_unlock(&chan->lock);
     1131                return EIO;
     1132        }
     1133
     1134        ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head);
     1135
     1136        if (wait_status(chan, 0, ~(SR_BSY | SR_DRQ), NULL, TIMEOUT_BSY) != EOK) {
     1137                fibril_mutex_unlock(&chan->lock);
     1138                return EIO;
     1139        }
     1140
     1141        ata_write_cmd_8(chan, REG_COMMAND, CMD_PACKET);
     1142
     1143        if (wait_status(chan, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) {
     1144                if (chan->params.use_dma)
     1145                        ata_dma_chan_teardown(device);
     1146                fibril_mutex_unlock(&chan->lock);
     1147                return EIO;
     1148        }
     1149
     1150        /* Write command packet. */
     1151        ata_write_data_16(chan, ((uint16_t *) cpkt), (cpkt_size + 1) / 2);
     1152
     1153        rc = ata_pio_nondata(device);
     1154
     1155        fibril_mutex_unlock(&chan->lock);
     1156
     1157        return rc;
     1158}
     1159
     1160/** Issue packet command (i. e. write a command packet to the device)
     1161 * performing data-in transfer.
     1162 *
     1163 * @param device        Device
     1164 * @param cpkt          Command packet
     1165 * @param cpkt_size     Command packet size in bytes
    10951166 * @param obuf          Buffer for storing data read from device
    10961167 * @param obuf_size     Size of obuf in bytes
     
    10991170 * @return EOK on success, EIO on error.
    11001171 */
    1101 static errno_t ata_cmd_packet(ata_device_t *device, const void *cpkt, size_t cpkt_size,
    1102     void *obuf, size_t obuf_size, size_t *rcvd_size)
     1172static errno_t ata_cmd_packet_din(ata_device_t *device, const void *cpkt,
     1173    size_t cpkt_size, void *obuf, size_t obuf_size, size_t *rcvd_size)
    11031174{
    11041175        ata_channel_t *chan = device->chan;
     
    11951266        cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff));
    11961267
    1197         rc = ata_cmd_packet(device, cpb, sizeof(cpb), obuf, obuf_size, rcvd_size);
     1268        rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size,
     1269            rcvd_size);
    11981270        if (rc != EOK)
    11991271                return rc;
     
    12211293        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
    12221294
    1223         rc = ata_cmd_packet(device, &cdb, sizeof(cdb), &data, sizeof(data), &rsize);
     1295        rc = ata_cmd_packet_din(device, &cdb, sizeof(cdb), &data, sizeof(data),
     1296            &rsize);
    12241297        if (rc != EOK)
    12251298                return rc;
     
    12621335        cp.xfer_len = host2uint32_t_be(cnt);
    12631336
    1264         rc = ata_cmd_packet(device, &cp, sizeof(cp), obuf, obuf_size, NULL);
     1337        rc = ata_cmd_packet_din(device, &cp, sizeof(cp), obuf, obuf_size, NULL);
    12651338        if (rc != EOK)
    12661339                return rc;
     
    13021375        cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
    13031376
    1304         rc = ata_cmd_packet(device, cpb, sizeof(cpb), obuf, obuf_size, NULL);
     1377        rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size,
     1378            NULL);
    13051379        if (rc != EOK)
    13061380                return rc;
     1381
     1382        return EOK;
     1383}
     1384
     1385/** Issue Start Stop Unit command.
     1386 *
     1387 * @param device        Device
     1388 * @param flags         Flags field of Start Stop Unit command (ssf_*)
     1389 * @return EOK on success, EIO on error.
     1390 */
     1391static errno_t ata_pcmd_start_stop_unit(ata_device_t *device, uint8_t flags)
     1392{
     1393        uint8_t cpb[12];
     1394        scsi_cdb_start_stop_unit_t *cp = (scsi_cdb_start_stop_unit_t *)cpb;
     1395        errno_t rc;
     1396
     1397        ata_msg_debug(device->chan, "ata_pcmd_start_stop_unit(device, 0x%x)",
     1398            flags);
     1399
     1400        memset(cpb, 0, sizeof(cpb));
     1401
     1402        /*
     1403         * For SFF 8020 compliance the command must be padded to 12 bytes.
     1404         */
     1405        cp->op_code = SCSI_CMD_START_STOP_UNIT;
     1406        cp->immed = 0;
     1407        cp->flags = flags;
     1408        cp->control = 0;
     1409
     1410        rc = ata_cmd_packet_nondata(device, cpb, sizeof(cpb));
     1411        if (rc != EOK)
     1412                return rc;
     1413
     1414        ata_msg_debug(device->chan, "ata_pcmd_start_stop_unit(): "
     1415            "ata_cmd_packet_nondata -> %d", rc);
    13071416
    13081417        return EOK;
Note: See TracChangeset for help on using the changeset viewer.