Changeset d30e067 in mainline for uspace/lib/ata/src/ata.c


Ignore:
Timestamp:
2025-03-02T20:02:33Z (5 months ago)
Author:
Miroslav Cimerman <mc@…>
Children:
8cdf360
Parents:
7debda3 (diff), 4285f384 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge 'upstream/master' into helenraid-para

File:
1 edited

Legend:

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

    r7debda3 rd30e067  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    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
     
    257261
    258262        for (i = 0; i < MAX_DEVICES; i++) {
     263                if (chan->device[i].present == false)
     264                        continue;
     265
    259266                rc = ata_device_remove(&chan->device[i]);
    260267                if (rc != EOK) {
    261268                        ata_msg_error(chan, "Unable to remove device %d.", i);
    262                         break;
     269                        fibril_mutex_unlock(&chan->lock);
     270                        return rc;
    263271                }
    264272        }
     
    266274        ata_bd_fini_irq(chan);
    267275        fibril_mutex_unlock(&chan->lock);
     276        free(chan);
    268277
    269278        return rc;
     
    753762}
    754763
     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
    755774/** PIO data-in command protocol. */
    756775static errno_t ata_pio_data_in(ata_device_t *device, void *obuf, size_t obuf_size,
     
    10831102}
    10841103
    1085 /** Issue packet command (i. e. write a command packet to the device).
    1086  *
    1087  * 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.
    10881106 *
    10891107 * @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
    10901166 * @param obuf          Buffer for storing data read from device
    10911167 * @param obuf_size     Size of obuf in bytes
     
    10941170 * @return EOK on success, EIO on error.
    10951171 */
    1096 static errno_t ata_cmd_packet(ata_device_t *device, const void *cpkt, size_t cpkt_size,
    1097     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)
    10981174{
    10991175        ata_channel_t *chan = device->chan;
     
    11901266        cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff));
    11911267
    1192         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);
    11931270        if (rc != EOK)
    11941271                return rc;
     
    12161293        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
    12171294
    1218         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);
    12191297        if (rc != EOK)
    12201298                return rc;
     
    12571335        cp.xfer_len = host2uint32_t_be(cnt);
    12581336
    1259         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);
    12601338        if (rc != EOK)
    12611339                return rc;
     
    12971375        cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */
    12981376
    1299         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);
    13001379        if (rc != EOK)
    13011380                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);
    13021416
    13031417        return EOK;
     
    15321646         * exceed DMA buffer size.
    15331647         */
    1534         dma_maxnb = d->chan->params.max_dma_xfer / d->block_size;
    1535         if (dma_maxnb < maxnb)
    1536                 maxnb = dma_maxnb;
     1648        if (d->chan->params.use_dma) {
     1649                dma_maxnb = d->chan->params.max_dma_xfer / d->block_size;
     1650                if (dma_maxnb < maxnb)
     1651                        maxnb = dma_maxnb;
     1652        }
    15371653
    15381654        return maxnb;
Note: See TracChangeset for help on using the changeset viewer.