1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/** 14 * @brief UFI Command implementation for USB Mass Storage Class 15 * @see USB Mass Storage Class UFI Command Spec 16 */ 17#include <platsupport/delay.h> 18#include <string.h> 19#include <usb/drivers/ufi.h> 20 21#include "storage.h" 22 23/* Operation Code */ 24#define TEST_UNIT_READY 0x00 25#define REZERO_UNIT 0x01 26#define REQUEST_SENSE 0x03 27#define FORMAT_UNIT 0x04 28 29#define INQUIRY 0x12 30#define START_STOP 0x1B 31#define SEND_DIAGNOSTIC 0x1D 32#define ALLOW_REMOVAL 0x1E 33 34#define READ_FORMAT_CAP 0x23 35#define READ_CAPACITY 0x25 36#define READ_10 0x28 37#define WRITE_10 0x2A 38#define SEEK 0x2B 39#define WRITE_VERIFY 0x2E 40#define VERIFY 0x2F 41 42#define MODE_SELECT 0x55 43#define MODE_SENSE 0x5A 44#define READ_12 0xA8 45#define WRITE_12 0xAA 46 47 48#define UFI_OUTPUT 0 49#define UFI_INPUT 1 50 51#define UFI_LBA_SHF 16 52#define UFI_SENSE_LEN 18 53#define UFI_INQ_LEN 36 54#define UFI_MODE_SENSE_LEN 192 55#define UFI_MODE_PAGE_ALL 0x3F 56#define UFI_BLK_SIZE 512 57 58/* Command Descriptor Block */ 59struct ufi_cdb { 60 uint8_t opcode; 61 uint8_t lun; 62 uint32_t lba; 63 uint32_t length; 64 uint16_t reserved; 65} __attribute__((packed)); 66 67static void ufi_format_unit() 68{ 69 ZF_LOGF("Not implemented\n"); 70} 71 72static void ufi_test_unit_ready(usb_dev_t *udev) 73{ 74 int err; 75 struct ufi_cdb cdb; 76 77 memset(&cdb, 0, sizeof(struct ufi_cdb)); 78 79 /* Fill in the command */ 80 cdb.opcode = TEST_UNIT_READY; 81 82 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 83 NULL, 0, UFI_OUTPUT); 84 if (err) { 85 ZF_LOGF("Transfer error\n"); 86 } 87} 88 89static void ufi_request_sense(usb_dev_t *udev) 90{ 91 int err; 92 struct ufi_cdb cdb; 93 struct xact data; 94 95 memset(&cdb, 0, sizeof(struct ufi_cdb)); 96 97 /* Fill in the command */ 98 cdb.opcode = REQUEST_SENSE; 99 cdb.lba = UFI_SENSE_LEN << UFI_LBA_SHF; 100 101 data.type = PID_IN; 102 data.len = UFI_SENSE_LEN; 103 err = usb_alloc_xact(udev->dman, &data, 1); 104 if (err) { 105 ZF_LOGF("Out of DMA memory\n"); 106 } 107 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 108 &data, 1, UFI_INPUT); 109 if (err) { 110 ZF_LOGF("Transfer error\n"); 111 } 112 usb_destroy_xact(udev->dman, &data, 1); 113} 114 115static void ufi_inquiry(usb_dev_t *udev) 116{ 117 int err; 118 struct ufi_cdb cdb; 119 struct xact data; 120 121 memset(&cdb, 0, sizeof(struct ufi_cdb)); 122 123 /* Inquiry UFI disk */ 124 cdb.opcode = INQUIRY; 125 cdb.lba = UFI_INQ_LEN << UFI_LBA_SHF; 126 127 data.type = PID_IN; 128 data.len = UFI_INQ_LEN; 129 err = usb_alloc_xact(udev->dman, &data, 1); 130 if (err) { 131 ZF_LOGF("Out of DMA memory\n"); 132 } 133 134 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 135 &data, 1, UFI_INPUT); 136 if (err) { 137 ZF_LOGF("Transfer error\n"); 138 } 139 140 usb_destroy_xact(udev->dman, &data, 1); 141} 142 143static void ufi_prevent_allow_medium_removal(usb_dev_t *udev, int enable) 144{ 145 int err; 146 struct ufi_cdb cdb; 147 148 memset(&cdb, 0, sizeof(struct ufi_cdb)); 149 150 cdb.opcode = ALLOW_REMOVAL; 151 cdb.lba = enable << 8; 152 153 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 154 NULL, 0, UFI_OUTPUT); 155 if (err) { 156 ZF_LOGF("Transfer error\n"); 157 } 158} 159 160uint32_t ufi_read_capacity(usb_dev_t *udev) 161{ 162 int err; 163 uint32_t ret; 164 struct ufi_cdb cdb; 165 struct xact data; 166 167 memset(&cdb, 0, sizeof(struct ufi_cdb)); 168 169 cdb.opcode = READ_CAPACITY; 170 171 data.type = PID_IN; 172 data.len = 8; 173 err = usb_alloc_xact(udev->dman, &data, 1); 174 if (err) { 175 ZF_LOGF("Out of DMA memory\n"); 176 } 177 178 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 179 &data, 1, UFI_INPUT); 180 if (err) { 181 ZF_LOGF("Transfer error\n"); 182 } 183 184 ret = *(uint32_t*)data.vaddr; 185 usb_destroy_xact(udev->dman, &data, 1); 186 187 return ret; 188} 189 190static void ufi_mode_sense(usb_dev_t *udev) 191{ 192 int err; 193 struct ufi_cdb cdb; 194 struct xact data; 195 196 memset(&cdb, 0, sizeof(struct ufi_cdb)); 197 198 cdb.opcode = MODE_SENSE; 199 cdb.lba = UFI_MODE_PAGE_ALL; 200 cdb.length = UFI_MODE_SENSE_LEN << UFI_LBA_SHF; 201 202 data.type = PID_IN; 203 data.len = UFI_MODE_SENSE_LEN; 204 err = usb_alloc_xact(udev->dman, &data, 1); 205 if (err) { 206 ZF_LOGF("Out of DMA memory\n"); 207 } 208 209 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 210 &data, 1, UFI_INPUT); 211 if (err) { 212 ZF_LOGF("Transfer error\n"); 213 } 214 215 usb_destroy_xact(udev->dman, &data, 1); 216} 217 218static void ufi_read10(usb_dev_t *udev, uint32_t lba, uint16_t count) 219{ 220 int err; 221 struct ufi_cdb cdb; 222 struct xact data; 223 224 memset(&cdb, 0, sizeof(struct ufi_cdb)); 225 226 cdb.opcode = READ_10; 227 cdb.lba = __builtin_bswap32(lba); 228 cdb.length = __builtin_bswap16(count) << 8; 229 230 data.type = PID_IN; 231 data.len = UFI_BLK_SIZE * count; 232 233 err = usb_alloc_xact(udev->dman, &data, 1); 234 if (err) { 235 ZF_LOGF("Out of DMA memory\n"); 236 } 237 238 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 239 &data, 1, UFI_INPUT); 240 if (err) { 241 ZF_LOGF("Transfer error\n"); 242 } 243 244 usb_destroy_xact(udev->dman, &data, 1); 245} 246 247static void ufi_read12(usb_dev_t *udev, uint32_t lba, uint32_t count) 248{ 249 int err; 250 struct ufi_cdb cdb; 251 struct xact data; 252 253 memset(&cdb, 0, sizeof(struct ufi_cdb)); 254 255 cdb.opcode = READ_12; 256 cdb.lba = __builtin_bswap32(lba); 257 cdb.length = __builtin_bswap16(count); 258 259 data.type = PID_IN; 260 data.len = UFI_BLK_SIZE * count; 261 262 err = usb_alloc_xact(udev->dman, &data, 1); 263 if (err) { 264 ZF_LOGF("Out of DMA memory\n"); 265 } 266 267 err = usb_storage_xfer(udev, &cdb, sizeof(struct ufi_cdb), 268 &data, 1, UFI_INPUT); 269 if (err) { 270 ZF_LOGF("Transfer error\n"); 271 } 272 273 usb_destroy_xact(udev->dman, &data, 1); 274} 275 276int 277ufi_init_disk(usb_dev_t *udev) 278{ 279 usb_storage_bind(udev); 280 281 ufi_inquiry(udev); 282 ufi_test_unit_ready(udev); 283 284 ufi_request_sense(udev); 285 ufi_test_unit_ready(udev); 286 287 ufi_read_capacity(udev); 288 ufi_mode_sense(udev); 289 ufi_test_unit_ready(udev); 290 291 ufi_prevent_allow_medium_removal(udev, 0); 292 ufi_request_sense(udev); 293 ufi_test_unit_ready(udev); 294 295 return 0; 296} 297 298