Changes in uspace/lib/ata/src/ata.c [743f2cdd:07039850] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ata/src/ata.c
r743f2cdd r07039850 1 1 /* 2 * Copyright (c) 202 4Jiri Svoboda2 * Copyright (c) 2025 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 84 84 static uint8_t ata_read_cmd_8(ata_channel_t *, uint16_t); 85 85 static 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); 86 87 87 88 static errno_t ata_bd_init_irq(ata_channel_t *); … … 96 97 static errno_t ata_bd_get_block_size(bd_srv_t *, size_t *); 97 98 static errno_t ata_bd_get_num_blocks(bd_srv_t *, aoff64_t *); 99 static errno_t ata_bd_eject(bd_srv_t *); 98 100 static errno_t ata_bd_sync_cache(bd_srv_t *, aoff64_t, size_t); 99 101 … … 105 107 static errno_t ata_identify_dev(ata_device_t *, void *); 106 108 static 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 *, 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 *, 108 111 size_t, size_t *); 109 112 static errno_t ata_pcmd_inquiry(ata_device_t *, void *, size_t, size_t *); … … 111 114 static errno_t ata_pcmd_read_capacity(ata_device_t *, uint64_t *, size_t *); 112 115 static 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); 113 117 static void disk_print_summary(ata_device_t *); 114 118 static size_t ata_disk_maxnb(ata_device_t *); … … 129 133 .get_block_size = ata_bd_get_block_size, 130 134 .get_num_blocks = ata_bd_get_num_blocks, 131 .sync_cache = ata_bd_sync_cache 135 .sync_cache = ata_bd_sync_cache, 136 .eject = ata_bd_eject 132 137 }; 133 138 … … 151 156 { 152 157 ata_channel_t *chan; 158 int i; 153 159 154 160 chan = calloc(1, sizeof(ata_channel_t)); … … 162 168 fibril_mutex_initialize(&chan->irq_lock); 163 169 fibril_condvar_initialize(&chan->irq_cv); 170 171 for (i = 0; i < MAX_DEVICES; i++) 172 chan->device[i].chan = chan; 164 173 165 174 *rchan = chan; … … 253 262 254 263 for (i = 0; i < MAX_DEVICES; i++) { 264 if (chan->device[i].present == false) 265 continue; 266 255 267 rc = ata_device_remove(&chan->device[i]); 256 268 if (rc != EOK) { 257 269 ata_msg_error(chan, "Unable to remove device %d.", i); 270 fibril_mutex_unlock(&chan->lock); 258 271 return rc; 259 272 } … … 262 275 ata_bd_fini_irq(chan); 263 276 fibril_mutex_unlock(&chan->lock); 264 265 return EOK; 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); 266 290 } 267 291 … … 335 359 { 336 360 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); 337 372 } 338 373 … … 493 528 unsigned i; 494 529 495 d->chan = chan;496 530 d->device_id = device_id; 497 531 d->present = false; … … 750 784 } 751 785 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 752 796 /** PIO data-in command protocol. */ 753 797 static errno_t ata_pio_data_in(ata_device_t *device, void *obuf, size_t obuf_size, … … 1080 1124 } 1081 1125 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). 1126 /** Issue packet command (i. e. write a command packet to the device) 1127 * with no data transfer. 1085 1128 * 1086 1129 * @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 1087 1188 * @param obuf Buffer for storing data read from device 1088 1189 * @param obuf_size Size of obuf in bytes … … 1091 1192 * @return EOK on success, EIO on error. 1092 1193 */ 1093 static 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)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) 1095 1196 { 1096 1197 ata_channel_t *chan = device->chan; … … 1187 1288 cp->alloc_len = host2uint16_t_be(min(obuf_size, 0xff)); 1188 1289 1189 rc = ata_cmd_packet(device, cpb, sizeof(cpb), obuf, obuf_size, rcvd_size); 1290 rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size, 1291 rcvd_size); 1190 1292 if (rc != EOK) 1191 1293 return rc; … … 1213 1315 cdb.op_code = SCSI_CMD_READ_CAPACITY_10; 1214 1316 1215 rc = ata_cmd_packet(device, &cdb, sizeof(cdb), &data, sizeof(data), &rsize); 1317 rc = ata_cmd_packet_din(device, &cdb, sizeof(cdb), &data, sizeof(data), 1318 &rsize); 1216 1319 if (rc != EOK) 1217 1320 return rc; … … 1254 1357 cp.xfer_len = host2uint32_t_be(cnt); 1255 1358 1256 rc = ata_cmd_packet (device, &cp, sizeof(cp), obuf, obuf_size, NULL);1359 rc = ata_cmd_packet_din(device, &cp, sizeof(cp), obuf, obuf_size, NULL); 1257 1360 if (rc != EOK) 1258 1361 return rc; … … 1294 1397 cp->control = 0x40; /* 0x01 = multi-session mode (shifted to MSB) */ 1295 1398 1296 rc = ata_cmd_packet(device, cpb, sizeof(cpb), obuf, obuf_size, NULL); 1399 rc = ata_cmd_packet_din(device, cpb, sizeof(cpb), obuf, obuf_size, 1400 NULL); 1297 1401 if (rc != EOK) 1298 1402 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); 1299 1438 1300 1439 return EOK; … … 1529 1668 * exceed DMA buffer size. 1530 1669 */ 1531 dma_maxnb = d->chan->params.max_dma_xfer / d->block_size; 1532 if (dma_maxnb < maxnb) 1533 maxnb = dma_maxnb; 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 } 1534 1675 1535 1676 return maxnb;
Note:
See TracChangeset
for help on using the changeset viewer.