Changeset 9739b5a in mainline
- Timestamp:
- 2024-06-11T09:32:59Z (3 months ago)
- Branches:
- master
- Children:
- c4ed9fa
- Parents:
- a38d504
- git-author:
- Jiri Svoboda <jiri@…> (2024-06-10 18:32:24)
- git-committer:
- Jiri Svoboda <jiri@…> (2024-06-11 09:32:59)
- Location:
- uspace/lib/ata
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ata/include/ata/ata_hw.h
ra38d504 r9739b5a 105 105 #define REG_STATUS offsetof(ata_cmd_t, status) 106 106 #define REG_COMMAND offsetof(ata_cmd_t, command) 107 #define REG_FEATURES offsetof(ata_cmd_t, features) 107 108 108 109 enum devctl_bits { -
uspace/lib/ata/src/ata.c
ra38d504 r9739b5a 878 878 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY); 879 879 880 /* Tear down DMA channel */ 881 ata_dma_chan_teardown(device); 882 880 883 if (rc != EOK) { 881 884 ata_msg_debug(chan, "wait_irq/wait_status failed"); 882 885 return EIO; 883 886 } 884 885 /* Tear down DMA channel */886 ata_dma_chan_teardown(device);887 887 888 888 if ((status & SR_ERR) != 0) { … … 973 973 } 974 974 975 /** Issue packet command (i. e. write a command packet to the device). 976 * 977 * Only data-in commands are supported (e.g. inquiry, read). 978 * 979 * @param device Device 980 * @param obuf Buffer for storing data read from device 981 * @param obuf_size Size of obuf in bytes 982 * @param rcvd_size Place to store number of bytes read or @c NULL 983 * 984 * @return EOK on success, EIO on error. 985 */ 986 static errno_t ata_cmd_packet(ata_device_t *device, const void *cpkt, size_t cpkt_size, 987 void *obuf, size_t obuf_size, size_t *rcvd_size) 975 /** Read data using PIO during a PACKET command. 976 * 977 * @param device Device 978 * @param obuf Output buffer 979 * @param obuf_size Output buffer size 980 * @param rcvd_size Place to store number of bytes actually transferred 981 * or @c NULL 982 */ 983 static errno_t ata_packet_pio_data_in(ata_device_t *device, void *obuf, 984 size_t obuf_size, size_t *rcvd_size) 988 985 { 989 986 ata_channel_t *chan = device->chan; 990 uint8_t status;991 uint8_t drv_head;992 987 size_t data_size; 993 988 size_t remain; 994 errno_t rc; 995 996 fibril_mutex_lock(&chan->lock); 997 998 /* New value for Drive/Head register */ 999 drv_head = 1000 ((disk_dev_idx(device) != 0) ? DHR_DRV : 0); 1001 1002 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) { 1003 fibril_mutex_unlock(&chan->lock); 1004 return EIO; 1005 } 1006 1007 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head); 1008 1009 if (wait_status(chan, 0, ~(SR_BSY | SR_DRQ), NULL, TIMEOUT_BSY) != EOK) { 1010 fibril_mutex_unlock(&chan->lock); 1011 return EIO; 1012 } 1013 1014 /* Byte count <- max. number of bytes we can read in one transfer. */ 1015 ata_write_cmd_8(chan, REG_CYLINDER_LOW, 0xfe); 1016 ata_write_cmd_8(chan, REG_CYLINDER_HIGH, 0xff); 1017 1018 ata_write_cmd_8(chan, REG_COMMAND, CMD_PACKET); 1019 1020 if (wait_status(chan, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 1021 fibril_mutex_unlock(&chan->lock); 1022 return EIO; 1023 } 1024 1025 /* Write command packet. */ 1026 ata_write_data_16(chan, ((uint16_t *) cpkt), (cpkt_size + 1) / 2); 989 uint8_t status; 990 errno_t rc; 1027 991 1028 992 remain = obuf_size; … … 1064 1028 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY); 1065 1029 1066 fibril_mutex_unlock(&chan->lock);1067 1068 1030 if (status & SR_ERR) 1069 1031 return EIO; … … 1071 1033 if (rcvd_size != NULL) 1072 1034 *rcvd_size = obuf_size - remain; 1035 1036 return EOK; 1037 } 1038 1039 static errno_t ata_packet_dma(ata_device_t *device, void *buf, size_t buf_size, 1040 ata_dma_dir_t dir) 1041 { 1042 ata_channel_t *chan = device->chan; 1043 uint8_t status; 1044 errno_t rc; 1045 1046 if (chan->params.have_irq) 1047 rc = wait_irq(chan, &status, TIMEOUT_BSY); 1048 else 1049 rc = wait_status(chan, 0, ~SR_BSY, &status, TIMEOUT_BSY); 1050 1051 if (rc != EOK) { 1052 ata_msg_debug(chan, "wait_irq/wait_status failed"); 1053 return EIO; 1054 } 1055 1056 if ((status & SR_ERR) != 0) { 1057 ata_msg_debug(chan, "status & SR_ERR != 0"); 1058 return EIO; 1059 } 1060 1061 return EOK; 1062 } 1063 1064 /** Issue packet command (i. e. write a command packet to the device). 1065 * 1066 * Only data-in commands are supported (e.g. inquiry, read). 1067 * 1068 * @param device Device 1069 * @param obuf Buffer for storing data read from device 1070 * @param obuf_size Size of obuf in bytes 1071 * @param rcvd_size Place to store number of bytes read or @c NULL 1072 * 1073 * @return EOK on success, EIO on error. 1074 */ 1075 static errno_t ata_cmd_packet(ata_device_t *device, const void *cpkt, size_t cpkt_size, 1076 void *obuf, size_t obuf_size, size_t *rcvd_size) 1077 { 1078 ata_channel_t *chan = device->chan; 1079 uint8_t status; 1080 uint8_t drv_head; 1081 errno_t rc; 1082 1083 fibril_mutex_lock(&chan->lock); 1084 1085 /* New value for Drive/Head register */ 1086 drv_head = 1087 ((disk_dev_idx(device) != 0) ? DHR_DRV : 0); 1088 1089 if (wait_status(chan, 0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK) { 1090 fibril_mutex_unlock(&chan->lock); 1091 return EIO; 1092 } 1093 1094 ata_write_cmd_8(chan, REG_DRIVE_HEAD, drv_head); 1095 1096 if (wait_status(chan, 0, ~(SR_BSY | SR_DRQ), NULL, TIMEOUT_BSY) != EOK) { 1097 fibril_mutex_unlock(&chan->lock); 1098 return EIO; 1099 } 1100 1101 if (chan->params.use_dma) { 1102 /* Set up DMA channel */ 1103 ata_dma_chan_setup(device, obuf, obuf_size, ata_dma_read); 1104 ata_write_cmd_8(chan, REG_FEATURES, 0x01); // XXX 1105 } else { 1106 /* 1107 * Byte count <- max. number of bytes we can read in one 1108 * PIO transfer. 1109 */ 1110 ata_write_cmd_8(chan, REG_CYLINDER_LOW, 0xfe); 1111 ata_write_cmd_8(chan, REG_CYLINDER_HIGH, 0xff); 1112 } 1113 1114 ata_write_cmd_8(chan, REG_COMMAND, CMD_PACKET); 1115 1116 if (wait_status(chan, SR_DRQ, ~SR_BSY, &status, TIMEOUT_BSY) != EOK) { 1117 if (chan->params.use_dma) 1118 ata_dma_chan_teardown(device); 1119 fibril_mutex_unlock(&chan->lock); 1120 return EIO; 1121 } 1122 1123 /* Write command packet. */ 1124 ata_write_data_16(chan, ((uint16_t *) cpkt), (cpkt_size + 1) / 2); 1125 1126 if (chan->params.use_dma) { 1127 /* Read data using DMA */ 1128 rc = ata_packet_dma(device, obuf, obuf_size, ata_dma_read); 1129 if (rc == EOK && rcvd_size != NULL) 1130 *rcvd_size = obuf_size; 1131 ata_dma_chan_teardown(device); 1132 } else { 1133 /* Read data using PIO */ 1134 rc = ata_packet_pio_data_in(device, obuf, obuf_size, rcvd_size); 1135 } 1136 1137 fibril_mutex_unlock(&chan->lock); 1138 1139 if (rc != EOK) 1140 return rc; 1141 1073 1142 return EOK; 1074 1143 }
Note:
See TracChangeset
for help on using the changeset viewer.