Remove building with NOCRYPTO option
[minix3.git] / minix / drivers / usb / usb_storage / usb_storage.c
blobc40789a374ea6668a7ddb72459ffc0ea0bbe4eee
1 /*
2 * Minix3 USB mass storage driver implementation
3 * using DDEkit, and libblockdriver
4 */
6 #include <sys/cdefs.h> /* __CTASSERT() */
7 #include <sys/ioc_disk.h> /* cases for mass_storage_ioctl */
8 #ifdef USB_STORAGE_SIGNAL
9 #include <sys/signal.h> /* signal handling */
10 #endif
12 #include <ddekit/minix/msg_queue.h>
13 #include <ddekit/thread.h>
14 #include <ddekit/usb.h>
16 #include <minix/blockdriver.h>
17 #include <minix/com.h> /* for msg_queue ranges */
18 #include <minix/drvlib.h> /* DEV_PER_DRIVE, partition */
19 #include <minix/ipc.h> /* message */
20 #include <minix/safecopies.h> /* GRANT_VALID */
21 #include <minix/sef.h>
22 #include <minix/sysutil.h> /* panic */
23 #include <minix/usb.h> /* structures like usb_ctrlrequest */
24 #include <minix/usb_ch9.h> /* descriptor structures */
26 #include <assert.h>
27 #include <limits.h> /* ULONG_MAX */
28 #include <time.h> /* nanosleep */
30 #include "common.h"
31 #include "bulk.h"
32 #include "usb_storage.h"
33 #include "urb_helper.h"
34 #include "scsi.h"
37 /*---------------------------*
38 * declared functions *
39 *---------------------------*/
40 /* TODO: these are missing from DDE header files */
41 extern void ddekit_minix_wait_exit(void);
42 extern void ddekit_shutdown(void);
44 /* SCSI URB related prototypes */
45 static int mass_storage_send_scsi_cbw_out(int, scsi_transfer *);
46 static int mass_storage_send_scsi_data_in(void *, unsigned int);
47 static int mass_storage_send_scsi_data_out(void *, unsigned int);
48 static int mass_storage_send_scsi_csw_in(void);
50 #ifdef MASS_RESET_RECOVERY
51 /* Bulk only URB related prototypes */
52 static int mass_storage_reset_recovery(void);
53 static int mass_storage_send_bulk_reset(void);
54 static int mass_storage_send_clear_feature(int, int);
55 #endif
57 /* SEF related functions */
58 static int mass_storage_sef_hdlr(int, sef_init_info_t *);
59 static void mass_storage_signal_handler(int);
61 /* DDEKit IPC related */
62 static void ddekit_usb_task(void *);
64 /* Mass storage related prototypes */
65 static void mass_storage_task(void *);
66 static int mass_storage_test(void);
67 static int mass_storage_check_error(void);
68 static int mass_storage_try_first_open(void);
69 static int mass_storage_transfer_restrictions(u64_t, unsigned long);
70 static ssize_t mass_storage_write(unsigned long, endpoint_t, iovec_t *,
71 unsigned int, unsigned long);
72 static ssize_t mass_storage_read(unsigned long, endpoint_t, iovec_t *,
73 unsigned int, unsigned long);
75 /* Minix's libblockdriver callbacks */
76 static int mass_storage_open(devminor_t, int);
77 static int mass_storage_close(devminor_t);
78 static ssize_t mass_storage_transfer(devminor_t, int, u64_t, endpoint_t,
79 iovec_t *, unsigned int, int);
80 static int mass_storage_ioctl(devminor_t, unsigned long, endpoint_t,
81 cp_grant_id_t, endpoint_t);
82 static void mass_storage_cleanup(void);
83 static struct device * mass_storage_part(devminor_t);
84 static void mass_storage_geometry(devminor_t, struct part_geom *);
86 /* DDEKit's USB driver callbacks */
87 static void usb_driver_completion(void *);
88 static void usb_driver_connect(struct ddekit_usb_dev *, unsigned int);
89 static void usb_driver_disconnect(struct ddekit_usb_dev *);
91 /* Simplified enumeration method for endpoint resolution */
92 static int mass_storage_get_endpoints(urb_ep_config *, urb_ep_config *);
93 static int mass_storage_parse_endpoint(usb_descriptor_t *, urb_ep_config *,
94 urb_ep_config *);
95 static int mass_storage_parse_descriptors(char *, unsigned int, urb_ep_config *,
96 urb_ep_config *);
99 /*---------------------------*
100 * defined variables *
101 *---------------------------*/
102 #define MASS_PACKED __attribute__((__packed__))
104 /* Mass Storage callback structure */
105 static struct blockdriver mass_storage = {
106 .bdr_type = BLOCKDRIVER_TYPE_DISK,
107 .bdr_open = mass_storage_open,
108 .bdr_close = mass_storage_close,
109 .bdr_transfer = mass_storage_transfer,
110 .bdr_ioctl = mass_storage_ioctl,
111 .bdr_cleanup = mass_storage_cleanup,
112 .bdr_part = mass_storage_part,
113 .bdr_geometry = mass_storage_geometry,
114 .bdr_intr = NULL,
115 .bdr_alarm = NULL,
116 .bdr_other = NULL,
117 .bdr_device = NULL
120 /* USB callback structure */
121 static struct ddekit_usb_driver mass_storage_driver = {
122 .completion = usb_driver_completion,
123 .connect = usb_driver_connect,
124 .disconnect = usb_driver_disconnect
127 /* Instance of global driver information */
128 mass_storage_state driver_state;
130 /* Tags used to pair CBW and CSW for bulk communication
131 * With this we can check if SCSI reply was meant for SCSI request */
132 static unsigned int current_cbw_tag = 0; /* What shall be send next */
133 static unsigned int last_cbw_tag = 0; /* What was sent recently */
135 /* Semaphore used to block mass storage thread to
136 * allow DDE dispatcher operation */
137 static ddekit_sem_t * mass_storage_sem = NULL;
139 /* Mass storage (using libblockdriver) thread */
140 ddekit_thread_t * mass_storage_thread = NULL;
142 /* DDEKit USB message handling thread */
143 ddekit_thread_t * ddekit_usb_thread = NULL;
145 /* Static URB buffer size (must be multiple of SECTOR_SIZE) */
146 #define BUFFER_SIZE (64*SECTOR_SIZE)
148 /* Large buffer for URB read/write operations */
149 static unsigned char buffer[BUFFER_SIZE];
151 /* Length of local buffer where descriptors are temporarily stored */
152 #define MAX_DESCRIPTORS_LEN 128
154 /* Maximum 'Test Unit Ready' command retries */
155 #define MAX_TEST_RETRIES 3
157 /* 'Test Unit Ready' failure delay time (in nanoseconds) */
158 #define NEXT_TEST_DELAY 50000000 /* 50ms */
161 /*---------------------------*
162 * defined functions *
163 *---------------------------*/
164 /*===========================================================================*
165 * main *
166 *===========================================================================*/
168 main(int argc, char * argv[])
170 MASS_DEBUG_MSG("Starting...");
172 /* Store arguments for future parsing */
173 env_setargs(argc, argv);
175 /* Clear current state */
176 memset(&driver_state, 0, sizeof(driver_state));
178 /* Initialize SEF related callbacks */
179 sef_setcb_init_fresh(mass_storage_sef_hdlr);
180 sef_setcb_init_lu(mass_storage_sef_hdlr);
181 sef_setcb_init_restart(mass_storage_sef_hdlr);
182 sef_setcb_signal_handler(mass_storage_signal_handler);
184 /* Initialize DDEkit (involves sef_startup()) */
185 ddekit_init();
186 MASS_DEBUG_MSG("DDEkit ready...");
188 /* Semaphore initialization */
189 mass_storage_sem = ddekit_sem_init(0);
190 if (NULL == mass_storage_sem)
191 panic("Initializing mass_storage_sem failed!");
193 /* Starting mass storage thread */
194 mass_storage_thread = ddekit_thread_create(mass_storage_task, NULL,
195 "mass_storage_task");
196 if (NULL == mass_storage_thread)
197 panic("Initializing mass_storage_thread failed!");
199 MASS_DEBUG_MSG("Storage task (libblockdriver) ready...");
201 /* Run USB IPC task to collect messages */
202 ddekit_usb_thread = ddekit_thread_create(ddekit_usb_task, NULL,
203 "ddekit_task" );
204 if (NULL == ddekit_usb_thread)
205 panic("Initializing ddekit_usb_thread failed!");
207 MASS_DEBUG_MSG("USB IPC task ready...");
209 /* Block and wait until exit signal is received */
210 ddekit_minix_wait_exit();
211 MASS_DEBUG_MSG("Exiting...");
213 /* Release objects that were explicitly allocated above */
214 ddekit_thread_terminate(ddekit_usb_thread);
215 ddekit_thread_terminate(mass_storage_thread);
216 ddekit_sem_deinit(mass_storage_sem);
218 /* TODO: no ddekit_deinit for proper cleanup? */
220 MASS_DEBUG_MSG("Cleanup completed...");
222 return EXIT_SUCCESS;
226 /*===========================================================================*
227 * mass_storage_send_scsi_cbw_out *
228 *===========================================================================*/
229 static int
230 mass_storage_send_scsi_cbw_out(int scsi_cmd, scsi_transfer * info)
232 /* URB to be send */
233 struct ddekit_usb_urb urb;
235 /* CBW data buffer */
236 mass_storage_cbw cbw;
238 MASS_DEBUG_DUMP;
240 /* Reset URB and assign given values */
241 init_urb(&urb, driver_state.cur_periph->dev,
242 &(driver_state.cur_periph->ep_out));
244 /* Reset CBW and assign default values */
245 init_cbw(&cbw, last_cbw_tag = current_cbw_tag++);
247 /* Fill CBW with SCSI command */
248 if (create_scsi_cmd(&cbw, scsi_cmd, info))
249 return EXIT_FAILURE;
251 /* Attach CBW to URB */
252 attach_urb_data(&urb, URB_BUF_TYPE_DATA, &cbw, sizeof(cbw));
254 /* Send and wait for response */
255 if (blocking_urb_submit(&urb, mass_storage_sem, URB_SUBMIT_CHECK_LEN))
256 return EXIT_FAILURE;
258 return EXIT_SUCCESS;
262 /*===========================================================================*
263 * mass_storage_send_scsi_data_in *
264 *===========================================================================*/
265 static int
266 mass_storage_send_scsi_data_in(void * buf, unsigned int in_len)
268 /* URB to be send */
269 struct ddekit_usb_urb urb;
271 MASS_DEBUG_DUMP;
273 /* Reset URB and assign given values */
274 init_urb(&urb, driver_state.cur_periph->dev,
275 &(driver_state.cur_periph->ep_in));
277 /* Attach buffer to URB */
278 attach_urb_data(&urb, URB_BUF_TYPE_DATA, buf, in_len);
280 /* Send and wait for response */
281 if (blocking_urb_submit(&urb, mass_storage_sem, URB_SUBMIT_CHECK_LEN))
282 return EXIT_FAILURE;
284 return EXIT_SUCCESS;
288 /*===========================================================================*
289 * mass_storage_send_scsi_data_out *
290 *===========================================================================*/
291 static int
292 mass_storage_send_scsi_data_out(void * buf, unsigned int out_len)
294 /* URB to be send */
295 struct ddekit_usb_urb urb;
297 MASS_DEBUG_DUMP;
299 /* Reset URB and assign given values */
300 init_urb(&urb, driver_state.cur_periph->dev,
301 &(driver_state.cur_periph->ep_out));
303 /* Attach buffer to URB */
304 attach_urb_data(&urb, URB_BUF_TYPE_DATA, buf, out_len);
306 /* Send and wait for response */
307 if (blocking_urb_submit(&urb, mass_storage_sem, URB_SUBMIT_CHECK_LEN))
308 return EXIT_FAILURE;
310 return EXIT_SUCCESS;
314 /*===========================================================================*
315 * mass_storage_send_scsi_csw_in *
316 *===========================================================================*/
317 static int
318 mass_storage_send_scsi_csw_in(void)
320 /* URB to be send */
321 struct ddekit_usb_urb urb;
323 /* CBW data buffer */
324 mass_storage_csw csw;
326 MASS_DEBUG_DUMP;
328 /* Reset URB and assign given values */
329 init_urb(&urb, driver_state.cur_periph->dev,
330 &(driver_state.cur_periph->ep_in));
332 /* Clear CSW for receiving */
333 init_csw(&csw);
335 /* Attach CSW to URB */
336 attach_urb_data(&urb, URB_BUF_TYPE_DATA, &csw, sizeof(csw));
338 /* Send and wait for response */
339 if (blocking_urb_submit(&urb, mass_storage_sem, URB_SUBMIT_CHECK_LEN))
340 return EXIT_FAILURE;
342 /* Check for proper reply */
343 if (check_csw(&csw, last_cbw_tag))
344 return EXIT_FAILURE;
346 return EXIT_SUCCESS;
350 #ifdef MASS_RESET_RECOVERY
351 /*===========================================================================*
352 * mass_storage_reset_recovery *
353 *===========================================================================*/
354 static int
355 mass_storage_reset_recovery(void)
357 MASS_DEBUG_DUMP;
359 /* Bulk-Only Mass Storage Reset */
360 if (mass_storage_send_bulk_reset()) {
361 MASS_MSG("Bulk-only mass storage reset failed");
362 return EIO;
365 /* Clear Feature HALT to the Bulk-In endpoint */
366 if (URB_INVALID_EP != driver_state.cur_periph->ep_in.ep_num)
367 if (mass_storage_send_clear_feature(
368 driver_state.cur_periph->ep_in.ep_num,
369 DDEKIT_USB_IN)) {
370 MASS_MSG("Resetting IN EP failed");
371 return EIO;
374 /* Clear Feature HALT to the Bulk-Out endpoint */
375 if (URB_INVALID_EP != driver_state.cur_periph->ep_out.ep_num)
376 if (mass_storage_send_clear_feature(
377 driver_state.cur_periph->ep_out.ep_num,
378 DDEKIT_USB_OUT)) {
379 MASS_MSG("Resetting OUT EP failed");
380 return EIO;
383 return EXIT_SUCCESS;
387 /*===========================================================================*
388 * mass_storage_send_bulk_reset *
389 *===========================================================================*/
390 static int
391 mass_storage_send_bulk_reset(void)
393 /* URB to be send */
394 struct ddekit_usb_urb urb;
396 /* Setup buffer to be send */
397 struct usb_ctrlrequest bulk_setup;
399 /* Control EP configuration */
400 urb_ep_config ep_conf;
402 MASS_DEBUG_DUMP;
404 /* Initialize EP configuration */
405 ep_conf.ep_num = 0;
406 ep_conf.direction = DDEKIT_USB_OUT;
407 ep_conf.type = DDEKIT_USB_TRANSFER_CTL;
408 ep_conf.max_packet_size = 0;
409 ep_conf.interval = 0;
411 /* Reset URB and assign given values */
412 init_urb(&urb, driver_state.cur_periph->dev, &ep_conf);
414 /* Clear setup data */
415 memset(&bulk_setup, 0, sizeof(bulk_setup));
417 /* For explanation of these values see usbmassbulk_10.pdf */
418 /* 3.1 Bulk-Only Mass Storage Reset */
419 bulk_setup.bRequestType = 0x21; /* Class, Interface, host to device */
420 bulk_setup.bRequest = 0xff;
421 bulk_setup.wValue = 0x00;
422 bulk_setup.wIndex = 0x00; /* TODO: hard-coded interface 0 */
423 bulk_setup.wLength = 0x00;
425 /* Attach request to URB */
426 attach_urb_data(&urb, URB_BUF_TYPE_SETUP,
427 &bulk_setup, sizeof(bulk_setup));
429 /* Send and wait for response */
430 if (blocking_urb_submit(&urb, mass_storage_sem, URB_SUBMIT_CHECK_LEN))
431 return EXIT_FAILURE;
433 return EXIT_SUCCESS;
437 /*===========================================================================*
438 * mass_storage_send_clear_feature *
439 *===========================================================================*/
440 static int
441 mass_storage_send_clear_feature(int ep_num, int direction)
443 /* URB to be send */
444 struct ddekit_usb_urb urb;
446 /* Setup buffer to be send */
447 struct usb_ctrlrequest bulk_setup;
449 /* Control EP configuration */
450 urb_ep_config ep_conf;
452 MASS_DEBUG_DUMP;
454 assert((ep_num >= 0) && (ep_num < 16));
455 assert((DDEKIT_USB_OUT == direction) || (DDEKIT_USB_IN == direction));
457 /* Initialize EP configuration */
458 ep_conf.ep_num = 0;
459 ep_conf.direction = DDEKIT_USB_OUT;
460 ep_conf.type = DDEKIT_USB_TRANSFER_CTL;
461 ep_conf.max_packet_size = 0;
462 ep_conf.interval = 0;
464 /* Reset URB and assign given values */
465 init_urb(&urb, driver_state.cur_periph->dev, &ep_conf);
467 /* Clear setup data */
468 memset(&bulk_setup, 0, sizeof(bulk_setup));
470 /* For explanation of these values see usbmassbulk_10.pdf */
471 /* 3.1 Bulk-Only Mass Storage Reset */
472 bulk_setup.bRequestType = 0x02; /* Standard, Endpoint, host to device */
473 bulk_setup.bRequest = 0x01; /* CLEAR_FEATURE */
474 bulk_setup.wValue = 0x00; /* Endpoint */
475 bulk_setup.wIndex = ep_num; /* Endpoint number... */
476 if (DDEKIT_USB_IN == direction)
477 bulk_setup.wIndex |= UE_DIR_IN; /* ...and direction bit */
478 bulk_setup.wLength = 0x00;
480 /* Attach request to URB */
481 attach_urb_data(&urb, URB_BUF_TYPE_SETUP,
482 &bulk_setup, sizeof(bulk_setup));
484 /* Send and wait for response */
485 if (blocking_urb_submit(&urb, mass_storage_sem, URB_SUBMIT_CHECK_LEN))
486 return EXIT_FAILURE;
488 return EXIT_SUCCESS;
490 #endif
493 /*===========================================================================*
494 * mass_storage_sef_hdlr *
495 *===========================================================================*/
496 static int
497 mass_storage_sef_hdlr(int type, sef_init_info_t * UNUSED(info))
499 int env_res;
501 MASS_DEBUG_DUMP;
503 /* Parse given environment */
504 env_res = env_parse("instance", "d", 0,
505 &(driver_state.instance),0, 255);
507 /* Get instance number */
508 if (EP_UNSET == env_res) {
509 MASS_DEBUG_MSG("Instance number was not supplied");
510 driver_state.instance = 0;
511 } else {
512 /* Only SET and UNSET are allowed */
513 if (EP_SET != env_res)
514 return EXIT_FAILURE;
517 switch (type) {
518 case SEF_INIT_FRESH:
519 /* Announce we are up! */
520 blockdriver_announce(type);
521 return EXIT_SUCCESS;
522 case SEF_INIT_LU:
523 case SEF_INIT_RESTART:
524 MASS_MSG("Only 'fresh' SEF initialization supported\n");
525 break;
526 default:
527 MASS_MSG("illegal SEF type\n");
528 break;
531 return EXIT_FAILURE;
535 /*===========================================================================*
536 * mass_storage_signal_handler *
537 *===========================================================================*/
538 static void
539 mass_storage_signal_handler(int this_signal)
541 MASS_DEBUG_DUMP;
543 #ifdef USB_STORAGE_SIGNAL
544 /* Only check for termination signal, ignore anything else. */
545 if (this_signal != SIGTERM)
546 return;
547 #else
548 MASS_MSG("Handling signal 0x%X", this_signal);
549 #endif
551 /* Try graceful DDEKit exit */
552 ddekit_shutdown();
554 /* Unreachable, when ddekit_shutdown works correctly */
555 panic("Calling ddekit_shutdown failed!");
559 /*===========================================================================*
560 * ddekit_usb_task *
561 *===========================================================================*/
562 static void
563 ddekit_usb_task(void * UNUSED(arg))
565 MASS_DEBUG_DUMP;
567 /* TODO: This call was meant to return 'int' but loops forever instead,
568 * so no return value is checked */
569 ddekit_usb_init(&mass_storage_driver, NULL, NULL);
573 /*===========================================================================*
574 * mass_storage_task *
575 *===========================================================================*/
576 static void
577 mass_storage_task(void * UNUSED(unused))
579 message m;
580 int ipc_status;
581 struct ddekit_minix_msg_q * mq;
583 MASS_DEBUG_DUMP;
585 mq = ddekit_minix_create_msg_q(BDEV_RQ_BASE, BDEV_RQ_BASE + 0xff);
587 for (;;) {
588 ddekit_minix_rcv(mq, &m, &ipc_status);
589 blockdriver_process(&mass_storage, &m, ipc_status);
594 /*===========================================================================*
595 * mass_storage_test *
596 *===========================================================================*/
597 static int
598 mass_storage_test(void)
600 int repeat;
601 int error;
603 struct timespec test_wait;
605 MASS_DEBUG_DUMP;
607 /* Delay between consecutive test commands, in case of their failure */
608 test_wait.tv_nsec = NEXT_TEST_DELAY;
609 test_wait.tv_sec = 0;
611 for (repeat = 0; repeat < MAX_TEST_RETRIES; repeat++) {
613 /* SCSI TEST UNIT READY OUT stage */
614 if (mass_storage_send_scsi_cbw_out(SCSI_TEST_UNIT_READY, NULL))
615 return EIO;
617 /* TODO: Only CSW failure should normally contribute to retry */
619 /* SCSI TEST UNIT READY IN stage */
620 if (EXIT_SUCCESS == mass_storage_send_scsi_csw_in())
621 return EXIT_SUCCESS;
623 /* Check for errors */
624 if (EXIT_SUCCESS != (error = mass_storage_check_error())) {
625 MASS_MSG("SCSI sense error checking failed");
626 return error;
629 /* Ignore potential signal interruption (no return value check),
630 * since it causes driver termination anyway */
631 if (nanosleep(&test_wait, NULL))
632 MASS_MSG("Calling nanosleep() failed");
635 return EIO;
639 /*===========================================================================*
640 * mass_storage_check_error *
641 *===========================================================================*/
642 static int
643 mass_storage_check_error(void)
645 /* SCSI sense structure for local use */
646 typedef struct MASS_PACKED scsi_sense {
648 uint8_t code : 7;
649 uint8_t valid : 1;
650 uint8_t obsolete : 8;
651 uint8_t sense : 4;
652 uint8_t reserved : 1;
653 uint8_t ili : 1;
654 uint8_t eom : 1;
655 uint8_t filemark : 1;
656 uint32_t information : 32;
657 uint8_t additional_len : 8;
658 uint32_t command_specific : 32;
659 uint8_t additional_code : 8;
660 uint8_t additional_qual : 8;
661 uint8_t unit_code : 8;
662 uint8_t key_specific1 : 7;
663 uint8_t sksv : 1;
664 uint16_t key_specific2 : 16;
666 scsi_sense;
668 /* Sense variable to hold received data */
669 scsi_sense sense;
671 MASS_DEBUG_DUMP;
673 /* Check if bit-fields are packed correctly */
674 __CTASSERT(sizeof(sense) == SCSI_REQUEST_SENSE_DATA_LEN);
676 /* SCSI REQUEST SENSE OUT stage */
677 if (mass_storage_send_scsi_cbw_out(SCSI_REQUEST_SENSE, NULL))
678 return EIO;
680 /* SCSI REQUEST SENSE first IN stage */
681 if (mass_storage_send_scsi_data_in(&sense, sizeof(sense)))
682 return EIO;
684 /* SCSI REQUEST SENSE second IN stage */
685 if (mass_storage_send_scsi_csw_in())
686 return EIO;
688 /* When any sense code is present something may have failed */
689 if (sense.sense) {
690 #ifdef MASS_DEBUG
691 MASS_MSG("SCSI sense: ");
692 MASS_MSG("code : %8X", sense.code );
693 MASS_MSG("valid : %8X", sense.valid );
694 MASS_MSG("obsolete : %8X", sense.obsolete );
695 MASS_MSG("sense : %8X", sense.sense );
696 MASS_MSG("reserved : %8X", sense.reserved );
697 MASS_MSG("ili : %8X", sense.ili );
698 MASS_MSG("eom : %8X", sense.eom );
699 MASS_MSG("filemark : %8X", sense.filemark );
700 MASS_MSG("information : %8X", sense.information );
701 MASS_MSG("additional_len : %8X", sense.additional_len );
702 MASS_MSG("command_specific : %8X", sense.command_specific);
703 MASS_MSG("additional_code : %8X", sense.additional_code );
704 MASS_MSG("additional_qual : %8X", sense.additional_qual );
705 MASS_MSG("unit_code : %8X", sense.unit_code );
706 MASS_MSG("key_specific1 : %8X", sense.key_specific1 );
707 MASS_MSG("sksv : %8X", sense.sksv );
708 MASS_MSG("key_specific2 : %8X", sense.key_specific2 );
709 #else
710 MASS_MSG("SCSI sense: 0x%02X 0x%02X 0x%02X", sense.sense,
711 sense.additional_code, sense.additional_qual);
712 #endif
715 return EXIT_SUCCESS;
719 /*===========================================================================*
720 * mass_storage_try_first_open *
721 *===========================================================================*/
722 static int
723 mass_storage_try_first_open()
725 unsigned int llba;
726 unsigned int blen;
727 unsigned char inquiry[SCSI_INQUIRY_DATA_LEN];
728 unsigned char capacity[SCSI_READ_CAPACITY_DATA_LEN];
730 MASS_DEBUG_DUMP;
732 assert(NULL != driver_state.cur_drive);
734 llba = 0; /* Last logical block address */
735 blen = 0; /* Block length (usually 512B) */
737 /* Run TEST UNIT READY before other SCSI command
738 * Some devices refuse to work without this */
739 if (mass_storage_test())
740 return EIO;
742 /* SCSI INQUIRY OUT stage */
743 if (mass_storage_send_scsi_cbw_out(SCSI_INQUIRY, NULL))
744 return EIO;
746 /* SCSI INQUIRY first IN stage */
747 if (mass_storage_send_scsi_data_in(inquiry, sizeof(inquiry)))
748 return EIO;
750 /* SCSI INQUIRY second IN stage */
751 if (mass_storage_send_scsi_csw_in())
752 return EIO;
754 /* Check for proper reply */
755 if (check_inquiry_reply(inquiry))
756 return EIO;
758 /* Run TEST UNIT READY before other SCSI command
759 * Some devices refuse to work without this */
760 if (mass_storage_test())
761 return EIO;
763 /* SCSI READ CAPACITY OUT stage */
764 if (mass_storage_send_scsi_cbw_out(SCSI_READ_CAPACITY, NULL))
765 return EIO;
767 /* SCSI READ CAPACITY first IN stage */
768 if (mass_storage_send_scsi_data_in(capacity, sizeof(capacity)))
769 return EIO;
771 /* SCSI READ CAPACITY second IN stage */
772 if (mass_storage_send_scsi_csw_in())
773 return EIO;
775 /* Check for proper reply */
776 if (check_read_capacity_reply(capacity, &llba, &blen))
777 return EIO;
779 /* For now only Minix's default SECTOR_SIZE is supported */
780 if (SECTOR_SIZE != blen)
781 panic("Invalid block size used by USB device!");
783 /* Get information about capacity from reply */
784 driver_state.cur_drive->disk.dv_base = 0;
785 driver_state.cur_drive->disk.dv_size = llba * blen;
787 return EXIT_SUCCESS;
791 /*===========================================================================*
792 * mass_storage_transfer_restrictions *
793 *===========================================================================*/
794 static int
795 mass_storage_transfer_restrictions(u64_t pos, unsigned long bytes)
797 MASS_DEBUG_DUMP;
799 assert(NULL != driver_state.cur_device);
801 /* Zero-length request must not be issued */
802 if (0 == bytes) {
803 MASS_MSG("Transfer request length equals 0");
804 return EINVAL;
807 /* Starting position must be aligned to sector */
808 if (0 != (pos % SECTOR_SIZE)) {
809 MASS_MSG("Transfer position not divisible by %u", SECTOR_SIZE);
810 return EINVAL;
813 /* Length must be integer multiple of sector sizes */
814 if (0 != (bytes % SECTOR_SIZE)) {
815 MASS_MSG("Data length not divisible by %u", SECTOR_SIZE);
816 return EINVAL;
819 /* Guard against ridiculous 64B overflow */
820 if ((pos + bytes) <= pos) {
821 MASS_MSG("Request outside available address space");
822 return EINVAL;
825 return EXIT_SUCCESS;
829 /*===========================================================================*
830 * mass_storage_write *
831 *===========================================================================*/
832 static ssize_t
833 mass_storage_write(unsigned long sector_number,
834 endpoint_t endpt,
835 iovec_t * iov,
836 unsigned int iov_count,
837 unsigned long bytes_left)
840 * This function writes whatever was put in 'iov' array
841 * (iov[0] : iov[iov_count]), into continuous region of mass storage,
842 * starting from sector 'sector_number'. Total amount of 'iov'
843 * data should be greater or equal to initial value of 'bytes_left'.
845 * Endpoint value 'endpt', determines if vectors 'iov' contain memory
846 * addresses for copying or grant IDs.
849 iov_state cur_iov; /* Current state of vector copying */
850 unsigned long bytes_to_write; /* To be written in this iteration */
851 ssize_t bytes_already_written; /* Total amount written (retval) */
853 MASS_DEBUG_DUMP;
855 /* Initialize locals */
856 cur_iov.remaining_bytes = 0; /* No IO vector initially */
857 cur_iov.iov_idx = 0; /* Starting from first vector */
858 bytes_already_written = 0; /* Nothing copied yet */
860 /* Mass storage operations are sector based */
861 assert(0 == (sizeof(buffer) % SECTOR_SIZE));
862 assert(0 == (bytes_left % SECTOR_SIZE));
864 while (bytes_left > 0) {
866 /* Fill write buffer with data from IO Vectors */
868 unsigned long buf_offset;
869 unsigned long copy_len;
871 /* Start copying to the beginning of the buffer */
872 buf_offset = 0;
874 /* Copy as long as not copied vectors exist or
875 * buffer is not fully filled */
876 for (;;) {
878 /* If entire previous vector
879 * was used get new one */
880 if (0 == cur_iov.remaining_bytes) {
881 /* Check if there are
882 * vectors to copied */
883 if (cur_iov.iov_idx < iov_count) {
885 cur_iov.base_addr =
886 iov[cur_iov.iov_idx].iov_addr;
887 cur_iov.remaining_bytes =
888 iov[cur_iov.iov_idx].iov_size;
889 cur_iov.offset = 0;
890 cur_iov.iov_idx++;
892 } else {
893 /* All vectors copied */
894 break;
898 /* Copy as much as it is possible from vector
899 * and at most the amount that can be
900 * put in buffer */
901 copy_len = MIN(sizeof(buffer) - buf_offset,
902 cur_iov.remaining_bytes);
904 /* This distinction is required as transfer can
905 * be used from within this process and meaning
906 * of IO vector'a address is different than
907 * grant ID */
908 if (endpt == SELF) {
909 memcpy(&buffer[buf_offset],
910 (void*)(cur_iov.base_addr +
911 cur_iov.offset), copy_len);
912 } else {
913 ssize_t copy_res;
914 if ((copy_res = sys_safecopyfrom(endpt,
915 cur_iov.base_addr,
916 cur_iov.offset,
917 (vir_bytes)
918 (&buffer[buf_offset]),
919 copy_len))) {
920 MASS_MSG("sys_safecopyfrom "
921 "failed");
922 return copy_res;
926 /* Alter current state of copying */
927 buf_offset += copy_len;
928 cur_iov.offset += copy_len;
929 cur_iov.remaining_bytes -= copy_len;
931 /* Buffer was filled */
932 if (sizeof(buffer) == buf_offset)
933 break;
936 /* Determine how many bytes from copied buffer we wish
937 * to write, buf_offset represents total amount of
938 * bytes copied above */
939 if (bytes_left >= buf_offset) {
940 bytes_to_write = buf_offset;
941 bytes_left -= buf_offset;
942 } else {
943 bytes_to_write = bytes_left;
944 bytes_left = 0;
948 /* Send URB and alter sector number */
949 if (bytes_to_write > 0) {
951 scsi_transfer info;
953 info.length = bytes_to_write;
954 info.lba = sector_number;
956 /* SCSI WRITE first OUT stage */
957 if (mass_storage_send_scsi_cbw_out(SCSI_WRITE, &info))
958 return EIO;
960 /* SCSI WRITE second OUT stage */
961 if (mass_storage_send_scsi_data_out(buffer,
962 bytes_to_write))
963 return EIO;
965 /* SCSI WRITE IN stage */
966 if (mass_storage_send_scsi_csw_in())
967 return EIO;
969 /* Writing completed so shift starting
970 * sector for next iteration */
971 sector_number += bytes_to_write / SECTOR_SIZE;
973 /* Update amount of data already copied */
974 bytes_already_written += bytes_to_write;
978 return bytes_already_written;
982 /*===========================================================================*
983 * mass_storage_read *
984 *===========================================================================*/
985 static ssize_t
986 mass_storage_read(unsigned long sector_number,
987 endpoint_t endpt,
988 iovec_t * iov,
989 unsigned int iov_count,
990 unsigned long bytes_left)
993 * This function reads 'bytes_left' bytes of mass storage data into
994 * 'iov' array (iov[0] : iov[iov_count]) starting from sector
995 * 'sector_number'. Total amount of 'iov' data should be greater or
996 * equal to initial value of 'bytes_left'.
998 * Endpoint value 'endpt', determines if vectors 'iov' contain memory
999 * addresses for copying or grant IDs.
1002 iov_state cur_iov; /* Current state of vector copying */
1003 unsigned long bytes_to_read; /* To be read in this iteration */
1004 ssize_t bytes_already_read; /* Total amount read (retval) */
1006 MASS_DEBUG_DUMP;
1008 /* Initialize locals */
1009 cur_iov.remaining_bytes = 0; /* No IO vector initially */
1010 cur_iov.iov_idx = 0; /* Starting from first vector */
1011 bytes_already_read = 0; /* Nothing copied yet */
1013 /* Mass storage operations are sector based */
1014 assert(0 == (sizeof(buffer) % SECTOR_SIZE));
1015 assert(0 == (bytes_left % SECTOR_SIZE));
1017 while (bytes_left > 0) {
1019 /* Decide read length and alter remaining bytes */
1021 /* Number of bytes to be read in next URB */
1022 if (bytes_left > sizeof(buffer)) {
1023 bytes_to_read = sizeof(buffer);
1024 } else {
1025 bytes_to_read = bytes_left;
1028 bytes_left -= bytes_to_read;
1031 /* Send URB and alter sector number */
1033 scsi_transfer info;
1035 info.length = bytes_to_read;
1036 info.lba = sector_number;
1038 /* SCSI READ OUT stage */
1039 if (mass_storage_send_scsi_cbw_out(SCSI_READ, &info))
1040 return EIO;
1042 /* SCSI READ first IN stage */
1043 if (mass_storage_send_scsi_data_in(buffer,
1044 bytes_to_read))
1045 return EIO;
1047 /* SCSI READ second IN stage */
1048 if (mass_storage_send_scsi_csw_in())
1049 return EIO;
1051 /* Reading completed so shift starting
1052 * sector for next iteration */
1053 sector_number += bytes_to_read / SECTOR_SIZE;
1056 /* Fill IO Vectors with data from buffer */
1058 unsigned long buf_offset;
1059 unsigned long copy_len;
1061 /* Start copying from the beginning of the buffer */
1062 buf_offset = 0;
1064 /* Copy as long as there are unfilled vectors
1065 * or data in buffer remains */
1066 for (;;) {
1068 /* If previous vector was filled get new one */
1069 if (0 == cur_iov.remaining_bytes) {
1070 /* Check if there are vectors
1071 * to be filled */
1072 if (cur_iov.iov_idx < iov_count) {
1074 cur_iov.base_addr =
1075 iov[cur_iov.iov_idx].iov_addr;
1076 cur_iov.remaining_bytes =
1077 iov[cur_iov.iov_idx].iov_size;
1078 cur_iov.offset = 0;
1079 cur_iov.iov_idx++;
1081 } else {
1082 /* Total length of vectors
1083 * should be greater or equal
1084 * to initial value of
1085 * bytes_left. Being here means
1086 * that everything should
1087 * have been copied already */
1088 assert(0 == bytes_left);
1089 break;
1093 /* Copy as much as it is possible from buffer
1094 * and at most the amount that can be
1095 * put in vector */
1096 copy_len = MIN(bytes_to_read - buf_offset,
1097 cur_iov.remaining_bytes);
1099 /* This distinction is required as transfer can
1100 * be used from within this process and meaning
1101 * of IO vector'a address is different than
1102 * grant ID */
1103 if (endpt == SELF) {
1104 memcpy((void*)(cur_iov.base_addr +
1105 cur_iov.offset),
1106 &buffer[buf_offset],
1107 copy_len);
1108 } else {
1109 ssize_t copy_res;
1110 if ((copy_res = sys_safecopyto(endpt,
1111 cur_iov.base_addr,
1112 cur_iov.offset,
1113 (vir_bytes)
1114 (&buffer[buf_offset]),
1115 copy_len))) {
1116 MASS_MSG("sys_safecopyto "
1117 "failed");
1118 return copy_res;
1122 /* Alter current state of copying */
1123 buf_offset += copy_len;
1124 cur_iov.offset += copy_len;
1125 cur_iov.remaining_bytes -= copy_len;
1127 /* Everything was copied */
1128 if (bytes_to_read == buf_offset)
1129 break;
1132 /* Update amount of data already copied */
1133 bytes_already_read += buf_offset;
1137 return bytes_already_read;
1141 /*===========================================================================*
1142 * mass_storage_open *
1143 *===========================================================================*/
1144 static int
1145 mass_storage_open(devminor_t minor, int UNUSED(access))
1147 mass_storage_drive * d;
1148 int r;
1150 MASS_DEBUG_DUMP;
1152 /* Decode minor into drive device information */
1153 if (NULL == (mass_storage_part(minor)))
1154 return ENXIO;
1156 /* Copy evaluated current drive for simplified dereference */
1157 d = driver_state.cur_drive;
1159 #ifdef MASS_RESET_RECOVERY
1160 /* In case of previous CBW mismatch */
1161 if (mass_storage_reset_recovery()) {
1162 MASS_MSG("Resetting mass storage device failed");
1163 return EIO;
1165 #endif
1167 /* In case of missing endpoint information, do simple
1168 * enumeration and hold it for future use */
1169 if ((URB_INVALID_EP == driver_state.cur_periph->ep_in.ep_num) ||
1170 (URB_INVALID_EP == driver_state.cur_periph->ep_out.ep_num)) {
1172 if (mass_storage_get_endpoints(&driver_state.cur_periph->ep_in,
1173 &driver_state.cur_periph->ep_out))
1174 return EIO;
1177 /* If drive hasn't been opened yet, try to open it */
1178 if (d->open_ct == 0) {
1179 if ((r = mass_storage_try_first_open())) {
1180 MASS_MSG("Opening mass storage device"
1181 " for the first time failed");
1183 /* Do one more test before failing, to output
1184 * sense errors in case they weren't dumped already */
1185 if (mass_storage_test())
1186 MASS_MSG("Final TEST UNIT READY failed");
1188 return r;
1191 /* Clear remembered device state for current
1192 * drive before calling partition */
1193 memset(&d->part[0], 0, sizeof(d->part));
1194 memset(&d->subpart[0], 0, sizeof(d->subpart));
1196 /* Try parsing partition table (for entire drive) */
1197 /* Warning!! This call uses mass_storage_part with own minors
1198 * and alters global driver_state.cur_device! */
1199 partition(&mass_storage, (d->drive_idx * DEV_PER_DRIVE),
1200 P_PRIMARY, 0);
1202 /* Decode minor into UPDATED drive device information */
1203 if (NULL == (mass_storage_part(minor)))
1204 return ENXIO;
1206 /* Decoded size must be positive or else
1207 * we assume device (partition) is unavailable */
1208 if (0 == driver_state.cur_device->dv_size)
1209 return ENXIO;
1212 /* Run TEST UNIT READY before further commands
1213 * Some devices refuse to work without this */
1214 if (mass_storage_test())
1215 return EIO;
1217 /* Opening completed */
1218 d->open_ct++;
1220 return EXIT_SUCCESS;
1224 /*===========================================================================*
1225 * mass_storage_close *
1226 *===========================================================================*/
1227 static int mass_storage_close(devminor_t minor)
1229 MASS_DEBUG_DUMP;
1231 /* Decode minor into drive device information */
1232 if (NULL == (mass_storage_part(minor)))
1233 return ENXIO;
1235 /* If drive hasn't been opened yet */
1236 if (driver_state.cur_drive->open_ct == 0) {
1237 MASS_MSG("Device was not opened yet");
1238 return ERESTART;
1241 /* Act accordingly */
1242 driver_state.cur_drive->open_ct--;
1244 return EXIT_SUCCESS;
1248 /*===========================================================================*
1249 * mass_storage_transfer *
1250 *===========================================================================*/
1251 static ssize_t
1252 mass_storage_transfer(devminor_t minor, /* device minor number */
1253 int do_write, /* 1 write, 0 read */
1254 u64_t pos, /* position of starting point */
1255 endpoint_t endpt, /* endpoint */
1256 iovec_t * iov, /* vector */
1257 unsigned int iov_count, /* how many vectors */
1258 int UNUSED(flags)) /* transfer flags */
1260 u64_t temp_sector_number;
1261 unsigned long bytes;
1262 unsigned long sector_number;
1263 unsigned int cur_iov_idx;
1264 int r;
1266 MASS_DEBUG_DUMP;
1268 /* Decode minor into drive device information */
1269 if (NULL == (mass_storage_part(minor)))
1270 return ENXIO;
1272 bytes = 0;
1274 /* How much data is going to be transferred? */
1275 for (cur_iov_idx = 0; cur_iov_idx < iov_count; ++cur_iov_idx) {
1277 /* Check if grant ID was supplied
1278 * instead of address and if it is valid */
1279 if (endpt != SELF)
1280 if (!GRANT_VALID((cp_grant_id_t)
1281 (iov[cur_iov_idx].iov_addr)))
1282 return EINVAL;
1284 /* All supplied vectors must have positive length */
1285 if ((signed long)(iov[cur_iov_idx].iov_size) <= 0) {
1286 MASS_MSG("Transfer request length is not positive");
1287 return EINVAL;
1290 /* Requirements were met, more bytes can be transferred */
1291 bytes += iov[cur_iov_idx].iov_size;
1293 /* Request size must never overflow */
1294 if ((signed long)bytes <= 0) {
1295 MASS_MSG("Transfer request length overflowed");
1296 return EINVAL;
1300 /* Check if reading beyond device/partition */
1301 if (pos >= driver_state.cur_device->dv_size) {
1302 MASS_MSG("Request out of bounds for given device");
1303 return 0; /* No error and no bytes read */
1306 /* Check if arguments agree with accepted restriction
1307 * for parameters of transfer */
1308 if ((r = mass_storage_transfer_restrictions(pos, bytes)))
1309 return r;
1311 /* If 'hard' requirements above were met, do additional
1312 * limiting to device/partition boundary */
1313 if ((pos + bytes) > driver_state.cur_device->dv_size)
1314 bytes = (driver_state.cur_device->dv_size - pos) &
1315 ~SECTOR_MASK;
1317 /* We have to obtain sector number of given position
1318 * and limit it to what URB can handle */
1319 temp_sector_number = (driver_state.cur_device->dv_base + pos) /
1320 SECTOR_SIZE;
1321 assert(temp_sector_number < ULONG_MAX); /* LBA is limited to 32B */
1322 sector_number = (unsigned long)temp_sector_number;
1324 if (do_write)
1325 return mass_storage_write(sector_number, endpt, iov,
1326 iov_count, bytes);
1327 else
1328 return mass_storage_read(sector_number, endpt, iov,
1329 iov_count, bytes);
1333 /*===========================================================================*
1334 * mass_storage_ioctl *
1335 *===========================================================================*/
1336 static int
1337 mass_storage_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
1338 cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
1340 MASS_DEBUG_DUMP;
1342 /* Decode minor into drive device information */
1343 if (NULL == (mass_storage_part(minor)))
1344 return ENXIO;
1346 switch (request) {
1347 case DIOCOPENCT:
1348 if (sys_safecopyto(endpt, grant, 0,
1349 (vir_bytes) &(driver_state.cur_drive->open_ct),
1350 sizeof(driver_state.cur_drive->open_ct)))
1351 panic("sys_safecopyto failed!");
1353 return EXIT_SUCCESS;
1355 default:
1356 MASS_MSG("Unimplemented IOCTL request: 0x%X",
1357 (int)request);
1358 break;
1361 return ENOTTY;
1365 /*===========================================================================*
1366 * mass_storage_cleanup *
1367 *===========================================================================*/
1368 static void mass_storage_cleanup(void)
1370 MASS_DEBUG_DUMP;
1371 return;
1375 /*===========================================================================*
1376 * mass_storage_part *
1377 *===========================================================================*/
1378 static struct device *
1379 mass_storage_part(devminor_t minor)
1381 unsigned long sel_drive;
1382 unsigned long sel_device;
1384 MASS_DEBUG_DUMP;
1386 /* Override every time before further decision */
1387 driver_state.cur_drive = NULL;
1388 driver_state.cur_device = NULL;
1389 driver_state.cur_periph = NULL;
1391 /* Decode 'minor' code to find which device file was used */
1392 if (minor < MINOR_d0p0s0) {
1394 /* No sub-partitions used */
1395 sel_drive = minor / DEV_PER_DRIVE;
1396 sel_device = minor % DEV_PER_DRIVE;
1398 /* Only valid minors */
1399 if (sel_drive < MAX_DRIVES) {
1400 /* Associate minor (device/partition)
1401 * with peripheral number */
1402 /* TODO:PERIPH
1403 * Proper peripheral selection based
1404 * on minor should be here: */
1405 driver_state.cur_periph = &driver_state.periph[0];
1407 /* Select drive entry for opening count etc. */
1408 driver_state.cur_drive =
1409 &(driver_state.cur_periph->drives[sel_drive]);
1411 /* Select device entry for given device file */
1412 /* Device 0 means entire drive.
1413 * Devices 1,2,3,4 mean partitions 0,1,2,3 */
1414 if (0 == sel_device)
1415 driver_state.cur_device =
1416 &(driver_state.cur_drive->disk);
1417 else
1418 driver_state.cur_device =
1419 &(driver_state.cur_drive->part
1420 [sel_device-1]);
1423 } else {
1425 /* Shift values accordingly */
1426 minor -= MINOR_d0p0s0;
1428 /* Sub-partitions used */
1429 sel_drive = minor / SUBPART_PER_DISK;
1430 sel_device = minor % SUBPART_PER_DISK;
1432 /* Only valid minors */
1433 if (sel_drive < MAX_DRIVES) {
1434 /* Leave in case of ridiculously high number */
1435 if (minor < SUBPART_PER_DISK) {
1436 /* Associate minor (device/partition)
1437 * with peripheral number */
1438 /* TODO:PERIPH
1439 * Proper peripheral selection based
1440 * on minor should be here: */
1441 driver_state.cur_periph =
1442 &driver_state.periph[0];
1444 /* Select drive entry for opening count etc. */
1445 driver_state.cur_drive =
1446 &(driver_state.cur_periph->drives
1447 [sel_drive]);
1448 /* Select device entry for given
1449 * sub-partition device file */
1450 driver_state.cur_device =
1451 &(driver_state.cur_drive->subpart
1452 [sel_device]);
1457 /* Check for success */
1458 if (NULL == driver_state.cur_device) {
1459 MASS_MSG("Device for minor: %u not found", minor);
1460 } else {
1461 /* Assign index as well */
1462 driver_state.cur_drive->drive_idx = sel_drive;
1465 return driver_state.cur_device;
1469 /*===========================================================================*
1470 * mass_storage_geometry *
1471 *===========================================================================*/
1472 /* This command is optional for most mass storage devices
1473 * It should rather be used with USB floppy disk reader */
1474 #ifdef MASS_USE_GEOMETRY
1475 static void
1476 mass_storage_geometry(devminor_t minor, struct part_geom * part)
1478 char flexible_disk_page[SCSI_MODE_SENSE_FLEX_DATA_LEN];
1480 MASS_DEBUG_DUMP;
1482 /* Decode minor into drive device information */
1483 if (NULL == (mass_storage_part(minor)))
1484 return;
1486 /* SCSI MODE SENSE OUT stage */
1487 if (mass_storage_send_scsi_cbw_out(SCSI_MODE_SENSE, NULL))
1488 return;
1490 /* SCSI MODE SENSE first IN stage */
1491 if (mass_storage_send_scsi_data_in(flexible_disk_page,
1492 sizeof(flexible_disk_page)))
1493 return;
1495 /* SCSI MODE SENSE second IN stage */
1496 if (mass_storage_send_scsi_csw_in())
1497 return;
1499 /* Get geometry from reply */
1500 if (check_mode_sense_reply(flexible_disk_page, &(part->cylinders),
1501 &(part->heads), &(part->sectors)))
1502 return;
1503 #else
1504 static void
1505 mass_storage_geometry(devminor_t UNUSED(minor), struct part_geom * part)
1507 MASS_DEBUG_DUMP;
1509 part->cylinders = part->size / SECTOR_SIZE;
1510 part->heads = 64;
1511 part->sectors = 32;
1512 #endif
1516 /*===========================================================================*
1517 * usb_driver_completion *
1518 *===========================================================================*/
1519 static void
1520 usb_driver_completion(void * UNUSED(priv))
1522 /* Last request was completed so allow continuing
1523 * execution from place where semaphore was downed */
1524 ddekit_sem_up(mass_storage_sem);
1528 /*===========================================================================*
1529 * usb_driver_connect *
1530 *===========================================================================*/
1531 static void
1532 usb_driver_connect(struct ddekit_usb_dev * dev,
1533 unsigned int interfaces)
1535 MASS_DEBUG_DUMP;
1537 /* TODO:PERIPH
1538 * Some sort of more complex peripheral assignment should be here */
1539 driver_state.cur_periph = &driver_state.periph[0];
1541 if (NULL != driver_state.cur_periph->dev)
1542 panic("Only one peripheral can be connected!");
1544 /* Hold host information for future use */
1545 driver_state.cur_periph->dev = dev;
1546 driver_state.cur_periph->interfaces = interfaces;
1547 driver_state.cur_periph->ep_in.ep_num = URB_INVALID_EP;
1548 driver_state.cur_periph->ep_out.ep_num = URB_INVALID_EP;
1552 /*===========================================================================*
1553 * usb_driver_disconnect *
1554 *===========================================================================*/
1555 static void
1556 usb_driver_disconnect(struct ddekit_usb_dev * UNUSED(dev))
1558 MASS_DEBUG_DUMP;
1560 /* TODO:PERIPH
1561 * Some sort of peripheral discard should be here */
1562 driver_state.cur_periph = &driver_state.periph[0];
1564 assert(NULL != driver_state.cur_periph->dev);
1566 /* Clear */
1567 driver_state.cur_periph->dev = NULL;
1568 driver_state.cur_periph->interfaces = 0;
1569 driver_state.cur_periph->ep_in.ep_num = URB_INVALID_EP;
1570 driver_state.cur_periph->ep_out.ep_num = URB_INVALID_EP;
1574 /*===========================================================================*
1575 * mass_storage_get_endpoints *
1576 *===========================================================================*/
1577 static int
1578 mass_storage_get_endpoints(urb_ep_config * ep_in, urb_ep_config * ep_out)
1580 /* URB to be send */
1581 struct ddekit_usb_urb urb;
1583 /* Setup buffer to be attached */
1584 struct usb_ctrlrequest setup_buf;
1586 /* Control EP configuration */
1587 urb_ep_config ep_conf;
1589 /* Descriptors' buffer */
1590 unsigned char descriptors[MAX_DESCRIPTORS_LEN];
1592 MASS_DEBUG_DUMP;
1594 /* Initialize EP configuration */
1595 ep_conf.ep_num = 0;
1596 ep_conf.direction = DDEKIT_USB_IN;
1597 ep_conf.type = DDEKIT_USB_TRANSFER_CTL;
1598 ep_conf.max_packet_size = 0;
1599 ep_conf.interval = 0;
1601 /* Reset URB and assign given values */
1602 init_urb(&urb, driver_state.cur_periph->dev, &ep_conf);
1604 /* Clear setup data */
1605 memset(&setup_buf, 0, sizeof(setup_buf));
1607 /* Standard get endpoint request */
1608 setup_buf.bRequestType = 0x80; /* Device to host */
1609 setup_buf.bRequest = UR_GET_DESCRIPTOR;
1610 setup_buf.wValue = UDESC_CONFIG << 8; /* TODO: configuration 0 */
1611 setup_buf.wIndex = 0x00;
1612 setup_buf.wLength = MAX_DESCRIPTORS_LEN;
1614 /* Attach buffers to URB */
1615 attach_urb_data(&urb, URB_BUF_TYPE_SETUP,
1616 &setup_buf, sizeof(setup_buf));
1617 attach_urb_data(&urb, URB_BUF_TYPE_DATA,
1618 descriptors, sizeof(descriptors));
1620 /* Send and wait for response */
1621 if (blocking_urb_submit(&urb, mass_storage_sem,
1622 URB_SUBMIT_ALLOW_MISMATCH))
1623 return EXIT_FAILURE;
1625 /* Check if buffer was supposed to hold more data */
1626 if (urb.size < urb.actual_length) {
1627 MASS_MSG("Too much descriptor data received");
1628 return EXIT_FAILURE;
1631 return mass_storage_parse_descriptors(urb.data, urb.actual_length,
1632 ep_in, ep_out);
1636 /*===========================================================================*
1637 * mass_storage_parse_endpoint *
1638 *===========================================================================*/
1639 static int
1640 mass_storage_parse_endpoint(usb_descriptor_t * cur_desc,
1641 urb_ep_config * ep_in, urb_ep_config * ep_out)
1643 usb_endpoint_descriptor_t * ep_desc;
1645 urb_ep_config * this_ep;
1647 MASS_DEBUG_DUMP;
1649 ep_desc = (usb_endpoint_descriptor_t *)cur_desc;
1651 /* Only bulk with no other attributes are important */
1652 if (UE_BULK == ep_desc->bmAttributes) {
1654 /* Check for direction */
1655 if (UE_DIR_IN == UE_GET_DIR(ep_desc->bEndpointAddress)) {
1657 this_ep = ep_in;
1658 this_ep->direction = DDEKIT_USB_IN;
1660 } else {
1662 this_ep = ep_out;
1663 this_ep->direction = DDEKIT_USB_OUT;
1666 /* Check if it was set before */
1667 if (URB_INVALID_EP != this_ep->ep_num) {
1668 MASS_MSG("BULK EP already set");
1669 return EXIT_FAILURE;
1672 /* Assign rest */
1673 this_ep->ep_num = UE_GET_ADDR(ep_desc->bEndpointAddress);
1674 this_ep->type = DDEKIT_USB_TRANSFER_BLK;
1675 this_ep->max_packet_size = UGETW(ep_desc->wMaxPacketSize);
1676 this_ep->interval = ep_desc->bInterval;
1679 /* EP type other than bulk, is also correct,
1680 * just no parsing is performed */
1681 return EXIT_SUCCESS;
1684 /*===========================================================================*
1685 * mass_storage_parse_descriptors *
1686 *===========================================================================*/
1687 static int
1688 mass_storage_parse_descriptors(char * desc_buf, unsigned int buf_len,
1689 urb_ep_config * ep_in, urb_ep_config * ep_out)
1691 /* Currently parsed, descriptors */
1692 usb_descriptor_t * cur_desc;
1693 usb_interface_descriptor_t * ifc_desc;
1695 /* Byte counter for descriptor parsing */
1696 unsigned int cur_byte;
1698 /* Non zero if recently parsed interface is valid for this device */
1699 int valid_interface;
1701 MASS_DEBUG_DUMP;
1703 /* Parse descriptors to get endpoints */
1704 ep_in->ep_num = URB_INVALID_EP;
1705 ep_out->ep_num = URB_INVALID_EP;
1706 valid_interface = 0;
1707 cur_byte = 0;
1709 while (cur_byte < buf_len) {
1711 /* Map descriptor to buffer */
1712 /* Structure is packed so alignment should not matter */
1713 cur_desc = (usb_descriptor_t *)&(desc_buf[cur_byte]);
1715 /* Check this so we won't be reading
1716 * memory outside the buffer */
1717 if ((cur_desc->bLength > 3) &&
1718 (cur_byte + cur_desc->bLength <= buf_len)) {
1720 /* Parse based on descriptor type */
1721 switch (cur_desc->bDescriptorType) {
1723 case UDESC_CONFIG: {
1724 if (USB_CONFIG_DESCRIPTOR_SIZE !=
1725 cur_desc->bLength) {
1726 MASS_MSG("Wrong configuration"
1727 " descriptor length");
1728 return EXIT_FAILURE;
1730 break;
1733 case UDESC_STRING:
1734 break;
1736 case UDESC_INTERFACE: {
1737 ifc_desc =
1738 (usb_interface_descriptor_t *)cur_desc;
1740 if (USB_INTERFACE_DESCRIPTOR_SIZE !=
1741 cur_desc->bLength) {
1742 MASS_MSG("Wrong interface"
1743 " descriptor length");
1744 return EXIT_FAILURE;
1747 /* Check if following data is meant
1748 * for our interfaces */
1749 if ((1 << ifc_desc->bInterfaceNumber) &
1750 driver_state.cur_periph->interfaces)
1751 valid_interface = 1;
1752 else
1753 valid_interface = 0;
1755 break;
1758 case UDESC_ENDPOINT: {
1759 if (USB_ENDPOINT_DESCRIPTOR_SIZE !=
1760 cur_desc->bLength) {
1761 MASS_MSG("Wrong endpoint"
1762 " descriptor length");
1763 return EXIT_FAILURE;
1766 /* Previous interface was,
1767 * what we were looking for */
1768 if (valid_interface) {
1769 if (EXIT_SUCCESS !=
1770 mass_storage_parse_endpoint(
1771 cur_desc, ep_in, ep_out))
1772 return EXIT_FAILURE;
1776 break;
1779 default: {
1780 MASS_MSG("Wrong descriptor type");
1781 return EXIT_FAILURE;
1785 } else {
1786 MASS_MSG("Invalid descriptor length");
1787 return EXIT_FAILURE;
1790 /* Get next descriptor */
1791 cur_byte += cur_desc->bLength;
1794 /* Total length should match sum of all descriptors' lengths... */
1795 if (cur_byte > buf_len)
1796 return EXIT_FAILURE;
1798 /* ...and descriptors should be valid */
1799 if ((URB_INVALID_EP == ep_in->ep_num) ||
1800 (URB_INVALID_EP == ep_out->ep_num)) {
1801 MASS_MSG("Valid bulk endpoints not found");
1802 return EXIT_FAILURE;
1805 return EXIT_SUCCESS;