Warning, cross-references for /kernel/drivers/usb/umsc.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include "drivers/usb/usb.h"
0020 #include "drivers/usb/uhci.h"
0021 #include "util/printf.h"
0022 #include "sched/vcpu.h"
0023 #include "sched/sched.h"
0024 #include "kernel.h"
0025
0026 #define USB_MASS_STORAGE_CLASS 0x8
0027 #define UMSC_PROTOCOL 0x50
0028
0029
0030
0031 #ifdef DEBUG_UMSC
0032 #define DLOG(fmt,...) DLOG_PREFIX("umsc",fmt,##__VA_ARGS__)
0033 #else
0034 #define DLOG(fmt,...) ;
0035 #endif
0036
0037 #define UMSC_CBW_SIGNATURE 0x43425355
0038 struct umsc_cbw {
0039 uint32 dCBWSignature;
0040 uint32 dCBWTag;
0041 uint32 dCBWDataTransferLength;
0042 union {
0043 uint8 raw;
0044 struct {
0045 uint8 _reserved:7;
0046 uint8 direction:1;
0047 };
0048 } bmCBWFlags;
0049 uint8 bCBWLUN:4;
0050 uint8 _reserved1:4;
0051 uint8 bCBWCBLength:5;
0052 uint8 _reserved2:3;
0053 uint8 CBWCB[16];
0054 } PACKED;
0055 typedef struct umsc_cbw UMSC_CBW;
0056
0057 #define UMSC_CSW_SIGNATURE 0x53425355
0058 struct umsc_csw {
0059 uint32 dCSWSignature;
0060 uint32 dCSWTag;
0061 uint32 dCSWDataResidue;
0062 uint8 bCSWStatus;
0063 } PACKED;
0064 typedef struct umsc_csw UMSC_CSW;
0065
0066 static uint testaddr, testepout, testepin;
0067
0068 typedef struct {
0069 USB_DEVICE_INFO *devinfo;
0070 uint ep_out, ep_in, maxpkt, last_lba, sector_size;
0071 } umsc_device_t;
0072
0073 #define UMSC_MAX_DEVICES 16
0074 static umsc_device_t umsc_devs[UMSC_MAX_DEVICES];
0075 static uint num_umsc_devs=0;
0076
0077 sint
0078 umsc_bulk_scsi (uint addr, uint ep_out, uint ep_in,
0079 uint8 cmd[16], uint dir, uint8* data,
0080 uint data_len, uint maxpkt)
0081 {
0082 UMSC_CBW cbw;
0083 UMSC_CSW csw;
0084 sint status;
0085 uint32 act_len;
0086
0087 DLOG ("cmd: %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X",
0088 cmd[0], cmd[1], cmd[2], cmd[3],
0089 cmd[4], cmd[5], cmd[6], cmd[7],
0090 cmd[8], cmd[9], cmd[10], cmd[11],
0091 cmd[12], cmd[13], cmd[14], cmd[15]);
0092
0093 memset (&cbw, 0, sizeof (cbw));
0094 memset (&csw, 0, sizeof (csw));
0095
0096 cbw.dCBWSignature = UMSC_CBW_SIGNATURE;
0097 cbw.dCBWDataTransferLength = data_len;
0098 cbw.bmCBWFlags.direction = dir;
0099 cbw.bCBWCBLength = 16;
0100 memcpy (cbw.CBWCB, cmd, 16);
0101
0102 status = uhci_bulk_transfer (addr, ep_out, &cbw, 0x1f, maxpkt, DIR_OUT, &act_len);
0103
0104 DLOG ("status=%d", status);
0105
0106 if (data_len > 0) {
0107 if (dir) {
0108 status = uhci_bulk_transfer (addr, ep_in, data, data_len, maxpkt, DIR_IN, &act_len);
0109 }
0110 else {
0111 status = uhci_bulk_transfer (addr, ep_out, data, data_len, maxpkt, DIR_OUT, &act_len);
0112 }
0113
0114 DLOG ("status=%d", status);
0115
0116 if (status != 0) return status;
0117
0118 DLOG ("data=%.02X %.02X %.02X %.02X", data[0], data[1], data[2], data[3]);
0119
0120 }
0121
0122 status = uhci_bulk_transfer (addr, ep_in, (addr_t) &csw, 0x0d, maxpkt, DIR_IN, &act_len);
0123
0124 DLOG ("status=%d", status);
0125
0126 if (status != 0) return status;
0127
0128 DLOG ("csw sig=%p tag=%p res=%d status=%d",
0129 csw.dCSWSignature, csw.dCSWTag, csw.dCSWDataResidue, csw.bCSWStatus);
0130
0131 return status;
0132 }
0133
0134 sint
0135 _umsc_read_sector (uint dev_index, uint32 lba, uint8 *sector, uint len)
0136 {
0137 umsc_device_t *umsc;
0138 uint8 cmd[16] = { [0] = 0x28,
0139 [2] = (lba >> 0x18) & 0xFF,
0140 [3] = (lba >> 0x10) & 0xFF,
0141 [4] = (lba >> 0x08) & 0xFF,
0142 [5] = (lba >> 0x00) & 0xFF,
0143 [8] = 1 };
0144 if (dev_index >= num_umsc_devs) return 0;
0145 umsc = &umsc_devs[dev_index];
0146 if (len < umsc->sector_size) return 0;
0147
0148 if (umsc_bulk_scsi (umsc->devinfo->address,
0149 umsc->ep_out, umsc->ep_in, cmd, 1, sector,
0150 umsc->sector_size, umsc->maxpkt) != 0)
0151 return 0;
0152 return umsc->sector_size;
0153 }
0154
0155
0156
0157 static task_id umsc_cur_task = 0, umsc_waitq = 0, umsc_thread_id = 0;
0158 static u32 umsc_cur_dev_index, umsc_cur_lba, umsc_cur_len;
0159 static u8 umsc_cur_sector[512];
0160 static sint umsc_cur_res;
0161 static u32 umsc_stack[1024] ALIGNED (0x1000);
0162
0163 static void
0164 umsc_thread (void)
0165 {
0166 logger_printf ("umsc_thread: hello from 0x%x\n", str ());
0167 for (;;) {
0168 if (umsc_cur_task) {
0169 DLOG ("thread: read_sector for 0x%x (%d, %d, %p, %d)", umsc_cur_task,
0170 umsc_cur_dev_index, umsc_cur_lba, umsc_cur_sector,
0171 umsc_cur_len);
0172 umsc_cur_res = _umsc_read_sector (umsc_cur_dev_index, umsc_cur_lba,
0173 umsc_cur_sector, umsc_cur_len);
0174 wakeup (umsc_cur_task);
0175 umsc_cur_task = 0;
0176 }
0177 iovcpu_job_completion ();
0178 }
0179 }
0180
0181 sint
0182 umsc_read_sector (uint dev_index, u32 lba, u8 *sector, uint len)
0183 {
0184 sint res;
0185
0186 if (dev_index >= num_umsc_devs) return 0;
0187 if (len < umsc_devs[dev_index].sector_size) return 0;
0188
0189 if (!mp_enabled || !umsc_thread_id) {
0190 return _umsc_read_sector (dev_index, lba, sector, len);
0191 }
0192
0193 while (umsc_cur_task) {
0194 queue_append (&umsc_waitq, str ());
0195 schedule ();
0196 }
0197
0198 umsc_cur_dev_index = dev_index;
0199 umsc_cur_lba = lba;
0200 umsc_cur_len = len;
0201
0202 umsc_cur_task = str ();
0203
0204 iovcpu_job_wakeup_for_me (umsc_thread_id);
0205
0206 schedule ();
0207
0208 memcpy (sector, umsc_cur_sector, sizeof (umsc_cur_sector));
0209 res = umsc_cur_res;
0210
0211 wakeup_queue (&umsc_waitq);
0212
0213 return res;
0214 }
0215
0216 static bool
0217 umsc_probe (USB_DEVICE_INFO *info, USB_CFG_DESC *cfgd, USB_IF_DESC *ifd)
0218 {
0219 uint i, addr = info->address, ep_in=0, ep_out=0;
0220 USB_EPT_DESC *ep;
0221 uint last_lba, sector_size, maxpkt=64;
0222 uint8 conf[512];
0223 umsc_device_t *umsc;
0224
0225 if (num_umsc_devs >= UMSC_MAX_DEVICES)
0226 return FALSE;
0227
0228 if (ifd->bInterfaceClass != USB_MASS_STORAGE_CLASS ||
0229 ifd->bInterfaceProtocol != UMSC_PROTOCOL)
0230 return FALSE;
0231
0232 ep = (USB_EPT_DESC *)(&ifd[1]);
0233
0234 if (ep[0].wMaxPacketSize != ep[1].wMaxPacketSize) {
0235 DLOG ("endpoint packet sizes don't match!");
0236 return FALSE;
0237 }
0238 maxpkt = ep[0].wMaxPacketSize;
0239 for (i=0; i<ifd->bNumEndpoints; i++)
0240 if (ep[i].bEndpointAddress & 0x80)
0241 ep_in = ep[i].bEndpointAddress & 0x7F;
0242 else
0243 ep_out = ep[i].bEndpointAddress & 0x7F;
0244
0245 if (!(ep_in && ep_out))
0246 return FALSE;
0247
0248 DLOG ("detected device=%d ep_in=%d ep_out=%d maxpkt=%d",
0249 addr, ep_in, ep_out, maxpkt);
0250
0251 usb_set_configuration (info, cfgd->bConfigurationValue);
0252 delay (50);
0253
0254 testaddr = addr;
0255 testepin = ep_in;
0256 testepout = ep_out;
0257
0258 {
0259 uint8 cmd[16] = {0x12,0,0,0,0x24,0,0,0,0,0,0,0};
0260 DLOG ("SENDING INQUIRY");
0261 if (umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 0x24, maxpkt) != 0)
0262 return FALSE;
0263 }
0264
0265 {
0266 uint8 cmd[16] = {0,0,0,0,0,0,0,0,0,0,0,0};
0267 DLOG ("SENDING TEST UNIT READY");
0268 if (umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 0, maxpkt) != 0)
0269 return FALSE;
0270 }
0271
0272 {
0273 uint8 cmd[16] = {0x03,0,0,0,0x24,0,0,0,0,0,0,0};
0274 DLOG ("SENDING REQUEST SENSE");
0275 if (umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 0x24, maxpkt) != 0)
0276 return FALSE;
0277 }
0278
0279 {
0280 uint8 cmd[16] = {0,0,0,0,0,0,0,0,0,0,0,0};
0281 DLOG ("SENDING TEST UNIT READY");
0282 if (umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 0, maxpkt) != 0)
0283 return FALSE;
0284 }
0285
0286 {
0287 uint8 cmd[16] = {0x03,0,0,0,0x24,0,0,0,0,0,0,0};
0288 DLOG ("SENDING REQUEST SENSE");
0289 if (umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 0x24, maxpkt) != 0)
0290 return FALSE;
0291 }
0292
0293 {
0294 uint8 cmd[16] = {0x25,0,0,0,0,0,0,0,0,0,0,0};
0295 DLOG ("SENDING READ CAPACITY");
0296 if (umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 0x8, maxpkt) != 0)
0297 return FALSE;
0298 last_lba = conf[3] | conf[2] << 8 | conf[1] << 16 | conf[0] << 24;
0299 sector_size = conf[7] | conf[6] << 8 | conf[5] << 16 | conf[4] << 24;
0300 DLOG ("sector_size=0x%x last_lba=0x%x total_size=%d bytes",
0301 sector_size, last_lba, sector_size * (last_lba + 1));
0302 }
0303
0304 memset (conf, 0, 512);
0305 {
0306 uint8 cmd[16] = { [0] = 0x28, [8] = 1 };
0307 DLOG ("SENDING READ (10)");
0308 if (umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 512, maxpkt) != 0)
0309 return FALSE;
0310 DLOG ("read from sector 0: %.02X %.02X %.02X %.02X",
0311 conf[0], conf[1], conf[2], conf[3]);
0312 if (conf[510] == 0x55 && conf[511] == 0xAA)
0313 DLOG ("Found boot sector magic number");
0314 }
0315
0316 umsc = &umsc_devs[num_umsc_devs];
0317 umsc->devinfo = info;
0318 umsc->sector_size = sector_size;
0319 umsc->last_lba = last_lba;
0320 umsc->ep_out = ep_out;
0321 umsc->ep_in = ep_in;
0322 umsc->maxpkt = maxpkt;
0323
0324 DLOG ("Registered UMSC device index=%d", num_umsc_devs);
0325
0326 num_umsc_devs++;
0327
0328 umsc_thread_id =
0329 start_kernel_thread ((u32) umsc_thread, (u32) &umsc_stack[1023]);
0330 set_iovcpu (umsc_thread_id, IOVCPU_CLASS_USB | IOVCPU_CLASS_DISK);
0331
0332 return TRUE;
0333 }
0334
0335 static USB_DRIVER umsc_driver = {
0336 .probe = umsc_probe
0337 };
0338
0339 extern bool
0340 usb_mass_storage_driver_init (void)
0341 {
0342 return usb_register_driver (&umsc_driver);
0343 }
0344
0345 extern void
0346 umsc_tmr_test (void)
0347 {
0348 void uhci_show_regs (void);
0349 uint8 conf[16];
0350 uint addr = testaddr, ep_out = testepout, ep_in = testepin, maxpkt=64;
0351 uint last_lba, sector_size;
0352 {
0353 uint8 cmd[16] = {0x25,0,0,0,0,0,0,0,0,0,0,0};
0354 DLOG ("SENDING READ CAPACITY");
0355 umsc_bulk_scsi (addr, ep_out, ep_in, cmd, 1, conf, 0x8, maxpkt);
0356 last_lba = conf[3] | conf[2] << 8 | conf[1] << 16 | conf[0] << 24;
0357 sector_size = conf[7] | conf[6] << 8 | conf[5] << 16 | conf[4] << 24;
0358 DLOG ("sector_size=0x%x last_lba=0x%x total_size=%d bytes",
0359 sector_size, last_lba, sector_size * (last_lba + 1));
0360 }
0361
0362 uhci_show_regs ();
0363 }
0364
0365 #include "module/header.h"
0366
0367 static const struct module_ops mod_ops = {
0368 .init = usb_mass_storage_driver_init
0369 };
0370
0371 DEF_MODULE (usb___umsc, "USB mass storage driver", &mod_ops, {"usb"});
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383