[acpi] Expose system MAC address via ${sysmac} setting
[ipxe.git] / src / drivers / usb / usbblk.c
1 /*
2 * Copyright (C) 2020 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <ipxe/usb.h>
30 #include <ipxe/scsi.h>
31 #include <ipxe/xfer.h>
32 #include <ipxe/uri.h>
33 #include <ipxe/open.h>
34 #include <ipxe/efi/efi_path.h>
35 #include "usbblk.h"
36
37 /** @file
38 *
39 * USB mass storage driver
40 *
41 */
42
43 static void usbblk_stop ( struct usbblk_device *usbblk, int rc );
44
45 /** List of USB block devices */
46 static LIST_HEAD ( usbblk_devices );
47
48 /******************************************************************************
49 *
50 * Endpoint management
51 *
52 ******************************************************************************
53 */
54
55 /**
56 * Open endpoints
57 *
58 * @v usbblk USB block device
59 * @ret rc Return status code
60 */
61 static int usbblk_open ( struct usbblk_device *usbblk ) {
62 struct usb_device *usb = usbblk->func->usb;
63 unsigned int interface = usbblk->func->interface[0];
64 int rc;
65
66 /* Sanity checks */
67 assert ( ! usbblk->in.open );
68 assert ( ! usbblk->out.open );
69
70 /* Issue reset */
71 if ( ( rc = usb_control ( usb, USBBLK_RESET, 0, interface,
72 NULL, 0 ) ) != 0 ) {
73 DBGC ( usbblk, "USBBLK %s could not issue reset: %s\n",
74 usbblk->func->name, strerror ( rc ) );
75 goto err_reset;
76 }
77
78 /* Open bulk OUT endpoint */
79 if ( ( rc = usb_endpoint_open ( &usbblk->out ) ) != 0 ) {
80 DBGC ( usbblk, "USBBLK %s could not open bulk OUT: %s\n",
81 usbblk->func->name, strerror ( rc ) );
82 goto err_open_out;
83 }
84
85 /* Clear any bulk OUT halt condition */
86 if ( ( rc = usb_endpoint_clear_halt ( &usbblk->out ) ) != 0 ) {
87 DBGC ( usbblk, "USBBLK %s could not reset bulk OUT: %s\n",
88 usbblk->func->name, strerror ( rc ) );
89 goto err_clear_out;
90 }
91
92 /* Open bulk IN endpoint */
93 if ( ( rc = usb_endpoint_open ( &usbblk->in ) ) != 0 ) {
94 DBGC ( usbblk, "USBBLK %s could not open bulk IN: %s\n",
95 usbblk->func->name, strerror ( rc ) );
96 goto err_open_in;
97 }
98
99 /* Clear any bulk IN halt condition */
100 if ( ( rc = usb_endpoint_clear_halt ( &usbblk->in ) ) != 0 ) {
101 DBGC ( usbblk, "USBBLK %s could not reset bulk IN: %s\n",
102 usbblk->func->name, strerror ( rc ) );
103 goto err_clear_in;
104 }
105
106 return 0;
107
108 err_clear_in:
109 usb_endpoint_close ( &usbblk->in );
110 err_open_in:
111 err_clear_out:
112 usb_endpoint_close ( &usbblk->out );
113 err_open_out:
114 err_reset:
115 return rc;
116 }
117
118 /**
119 * Close endpoints
120 *
121 * @v usbblk USB block device
122 */
123 static void usbblk_close ( struct usbblk_device *usbblk ) {
124
125 /* Close bulk OUT endpoint */
126 if ( usbblk->out.open )
127 usb_endpoint_close ( &usbblk->out );
128
129 /* Close bulk IN endpoint */
130 if ( usbblk->in.open )
131 usb_endpoint_close ( &usbblk->in );
132 }
133
134 /******************************************************************************
135 *
136 * Bulk OUT endpoint
137 *
138 ******************************************************************************
139 */
140
141 /**
142 * Issue bulk OUT command
143 *
144 * @v usbblk USB block device
145 * @ret rc Return status code
146 */
147 static int usbblk_out_command ( struct usbblk_device *usbblk ) {
148 struct usbblk_command *cmd = &usbblk->cmd;
149 struct usbblk_command_wrapper *wrapper;
150 struct io_buffer *iobuf;
151 int rc;
152
153 /* Sanity checks */
154 assert ( cmd->tag );
155 assert ( ! ( cmd->scsi.data_in_len && cmd->scsi.data_out_len ) );
156
157 /* Allocate I/O buffer */
158 iobuf = alloc_iob ( sizeof ( *wrapper ) );
159 if ( ! iobuf ) {
160 rc = -ENOMEM;
161 goto err_alloc;
162 }
163
164 /* Populate command */
165 wrapper = iob_put ( iobuf, sizeof ( *wrapper ) );
166 memset ( wrapper, 0, sizeof ( *wrapper ) );
167 wrapper->signature = cpu_to_le32 ( USBBLK_COMMAND_SIGNATURE );
168 wrapper->tag = cmd->tag; /* non-endian */
169 if ( cmd->scsi.data_out_len ) {
170 wrapper->len = cpu_to_le32 ( cmd->scsi.data_out_len );
171 } else {
172 wrapper->len = cpu_to_le32 ( cmd->scsi.data_in_len );
173 wrapper->flags = USB_DIR_IN;
174 }
175 wrapper->lun = ntohs ( cmd->scsi.lun.u16[0] );
176 wrapper->cblen = sizeof ( wrapper->cb );
177 memcpy ( wrapper->cb, &cmd->scsi.cdb, sizeof ( wrapper->cb ) );
178
179 /* Issue command */
180 if ( ( rc = usb_stream ( &usbblk->out, iobuf, 0 ) ) != 0 ) {
181 DBGC ( usbblk, "USBBLK %s bulk OUT could not issue command: "
182 "%s\n", usbblk->func->name, strerror ( rc ) );
183 goto err_stream;
184 }
185
186 return 0;
187
188 err_stream:
189 free_iob ( iobuf );
190 err_alloc:
191 return rc;
192 }
193
194 /**
195 * Send bulk OUT data block
196 *
197 * @v usbblk USB block device
198 * @ret rc Return status code
199 */
200 static int usbblk_out_data ( struct usbblk_device *usbblk ) {
201 struct usbblk_command *cmd = &usbblk->cmd;
202 struct io_buffer *iobuf;
203 size_t len;
204 int rc;
205
206 /* Calculate length */
207 assert ( cmd->tag );
208 assert ( cmd->scsi.data_out != UNULL );
209 assert ( cmd->offset < cmd->scsi.data_out_len );
210 len = ( cmd->scsi.data_out_len - cmd->offset );
211 if ( len > USBBLK_MAX_LEN )
212 len = USBBLK_MAX_LEN;
213 assert ( ( len % usbblk->out.mtu ) == 0 );
214
215 /* Allocate I/O buffer */
216 iobuf = alloc_iob ( len );
217 if ( ! iobuf ) {
218 rc = -ENOMEM;
219 goto err_alloc;
220 }
221
222 /* Populate I/O buffer */
223 copy_from_user ( iob_put ( iobuf, len ), cmd->scsi.data_out,
224 cmd->offset, len );
225
226 /* Send data */
227 if ( ( rc = usb_stream ( &usbblk->out, iobuf, 0 ) ) != 0 ) {
228 DBGC ( usbblk, "USBBLK %s bulk OUT could not send data: %s\n",
229 usbblk->func->name, strerror ( rc ) );
230 goto err_stream;
231 }
232
233 /* Consume data */
234 cmd->offset += len;
235
236 return 0;
237
238 err_stream:
239 free_iob ( iobuf );
240 err_alloc:
241 return rc;
242 }
243
244 /**
245 * Refill bulk OUT endpoint
246 *
247 * @v usbblk USB block device
248 * @ret rc Return status code
249 */
250 static int usbblk_out_refill ( struct usbblk_device *usbblk ) {
251 struct usbblk_command *cmd = &usbblk->cmd;
252 int rc;
253
254 /* Sanity checks */
255 assert ( cmd->tag );
256
257 /* Refill endpoint */
258 while ( ( cmd->offset < cmd->scsi.data_out_len ) &&
259 ( usbblk->out.fill < USBBLK_MAX_FILL ) ) {
260 if ( ( rc = usbblk_out_data ( usbblk ) ) != 0 )
261 return rc;
262 }
263
264 return 0;
265 }
266
267 /**
268 * Complete bulk OUT transfer
269 *
270 * @v ep USB endpoint
271 * @v iobuf I/O buffer
272 * @v rc Completion status code
273 */
274 static void usbblk_out_complete ( struct usb_endpoint *ep,
275 struct io_buffer *iobuf, int rc ) {
276 struct usbblk_device *usbblk =
277 container_of ( ep, struct usbblk_device, out );
278 struct usbblk_command *cmd = &usbblk->cmd;
279
280 /* Ignore cancellations after closing endpoint */
281 if ( ! ep->open )
282 goto drop;
283
284 /* Sanity check */
285 assert ( cmd->tag );
286
287 /* Check for failures */
288 if ( rc != 0 ) {
289 DBGC ( usbblk, "USBBLK %s bulk OUT failed: %s\n",
290 usbblk->func->name, strerror ( rc ) );
291 goto err;
292 }
293
294 /* Trigger refill process, if applicable */
295 if ( cmd->offset < cmd->scsi.data_out_len )
296 process_add ( &usbblk->process );
297
298 drop:
299 /* Free I/O buffer */
300 free_iob ( iobuf );
301
302 return;
303
304 err:
305 free_iob ( iobuf );
306 usbblk_stop ( usbblk, rc );
307 }
308
309 /** Bulk OUT endpoint operations */
310 static struct usb_endpoint_driver_operations usbblk_out_operations = {
311 .complete = usbblk_out_complete,
312 };
313
314 /******************************************************************************
315 *
316 * Bulk IN endpoint
317 *
318 ******************************************************************************
319 */
320
321 /**
322 * Handle bulk IN data block
323 *
324 * @v usbblk USB block device
325 * @v data Data block
326 * @v len Length of data
327 * @ret rc Return status code
328 */
329 static int usbblk_in_data ( struct usbblk_device *usbblk, const void *data,
330 size_t len ) {
331 struct usbblk_command *cmd = &usbblk->cmd;
332
333 /* Sanity checks */
334 assert ( cmd->tag );
335 assert ( cmd->scsi.data_in != UNULL );
336 assert ( cmd->offset <= cmd->scsi.data_in_len );
337 assert ( len <= ( cmd->scsi.data_in_len - cmd->offset ) );
338
339 /* Store data */
340 copy_to_user ( cmd->scsi.data_in, cmd->offset, data, len );
341 cmd->offset += len;
342
343 return 0;
344 }
345
346 /**
347 * Handle bulk IN status
348 *
349 * @v usbblk USB block device
350 * @v data Status data
351 * @v len Length of status data
352 * @ret rc Return status code
353 */
354 static int usbblk_in_status ( struct usbblk_device *usbblk, const void *data,
355 size_t len ) {
356 struct usbblk_command *cmd = &usbblk->cmd;
357 const struct usbblk_status_wrapper *stat;
358
359 /* Sanity checks */
360 assert ( cmd->tag );
361
362 /* Validate length */
363 if ( len < sizeof ( *stat ) ) {
364 DBGC ( usbblk, "USBBLK %s bulk IN malformed status:\n",
365 usbblk->func->name );
366 DBGC_HDA ( usbblk, 0, data, len );
367 return -EIO;
368 }
369 stat = data;
370
371 /* Validate signature */
372 if ( stat->signature != cpu_to_le32 ( USBBLK_STATUS_SIGNATURE ) ) {
373 DBGC ( usbblk, "USBBLK %s bulk IN invalid signature %08x:\n",
374 usbblk->func->name, le32_to_cpu ( stat->signature ) );
375 DBGC_HDA ( usbblk, 0, stat, sizeof ( *stat ) );
376 return -EIO;
377 }
378
379 /* Validate tag */
380 if ( stat->tag != cmd->tag ) {
381 DBGC ( usbblk, "USBBLK %s bulk IN tag mismatch (got %08x, "
382 "expected %08x):\n",
383 usbblk->func->name, stat->tag, cmd->tag );
384 DBGC_HDA ( usbblk, 0, stat, sizeof ( *stat ) );
385 return -EIO;
386 }
387
388 /* Check status */
389 if ( stat->status ) {
390 DBGC ( usbblk, "USBBLK %s bulk IN status %02x:\n",
391 usbblk->func->name, stat->status );
392 DBGC_HDA ( usbblk, 0, stat, sizeof ( *stat ) );
393 return -EIO;
394 }
395
396 /* Check for residual data */
397 if ( stat->residue ) {
398 DBGC ( usbblk, "USBBLK %s bulk IN residue %#x:\n",
399 usbblk->func->name, le32_to_cpu ( stat->residue ) );
400 return -EIO;
401 }
402
403 /* Mark command as complete */
404 usbblk_stop ( usbblk, 0 );
405
406 return 0;
407 }
408
409 /**
410 * Refill bulk IN endpoint
411 *
412 * @v usbblk USB block device
413 * @ret rc Return status code
414 */
415 static int usbblk_in_refill ( struct usbblk_device *usbblk ) {
416 struct usbblk_command *cmd = &usbblk->cmd;
417 struct usbblk_status_wrapper *stat;
418 size_t remaining;
419 unsigned int max;
420 int rc;
421
422 /* Sanity checks */
423 assert ( cmd->tag );
424
425 /* Calculate maximum required refill */
426 remaining = sizeof ( *stat );
427 if ( cmd->scsi.data_in_len ) {
428 assert ( cmd->offset <= cmd->scsi.data_in_len );
429 remaining += ( cmd->scsi.data_in_len - cmd->offset );
430 }
431 max = ( ( remaining + USBBLK_MAX_LEN - 1 ) / USBBLK_MAX_LEN );
432
433 /* Refill bulk IN endpoint */
434 if ( ( rc = usb_refill_limit ( &usbblk->in, max ) ) != 0 )
435 return rc;
436
437 return 0;
438 }
439
440 /**
441 * Complete bulk IN transfer
442 *
443 * @v ep USB endpoint
444 * @v iobuf I/O buffer
445 * @v rc Completion status code
446 */
447 static void usbblk_in_complete ( struct usb_endpoint *ep,
448 struct io_buffer *iobuf, int rc ) {
449 struct usbblk_device *usbblk =
450 container_of ( ep, struct usbblk_device, in );
451 struct usbblk_command *cmd = &usbblk->cmd;
452 size_t remaining;
453 size_t len;
454
455 /* Ignore cancellations after closing endpoint */
456 if ( ! ep->open )
457 goto drop;
458
459 /* Sanity check */
460 assert ( cmd->tag );
461
462 /* Handle errors */
463 if ( rc != 0 ) {
464 DBGC ( usbblk, "USBBLK %s bulk IN failed: %s\n",
465 usbblk->func->name, strerror ( rc ) );
466 goto err;
467 }
468
469 /* Trigger refill process */
470 process_add ( &usbblk->process );
471
472 /* Handle data portion, if any */
473 if ( cmd->scsi.data_in_len ) {
474 assert ( cmd->offset <= cmd->scsi.data_in_len );
475 remaining = ( cmd->scsi.data_in_len - cmd->offset );
476 len = iob_len ( iobuf );
477 if ( len > remaining )
478 len = remaining;
479 if ( len ) {
480 if ( ( rc = usbblk_in_data ( usbblk, iobuf->data,
481 len ) ) != 0 )
482 goto err;
483 iob_pull ( iobuf, len );
484 }
485 }
486
487 /* Handle status portion, if any */
488 len = iob_len ( iobuf );
489 if ( len ) {
490 if ( ( rc = usbblk_in_status ( usbblk, iobuf->data,
491 len ) ) != 0 )
492 goto err;
493 }
494
495 drop:
496 /* Free I/O buffer */
497 free_iob ( iobuf );
498
499 return;
500
501 err:
502 free_iob ( iobuf );
503 usbblk_stop ( usbblk, rc );
504 }
505
506 /** Bulk IN endpoint operations */
507 static struct usb_endpoint_driver_operations usbblk_in_operations = {
508 .complete = usbblk_in_complete,
509 };
510
511 /******************************************************************************
512 *
513 * Refill process
514 *
515 ******************************************************************************
516 */
517
518 /**
519 * Refill endpoints
520 *
521 * @v usbblk USB block device
522 */
523 static void usbblk_step ( struct usbblk_device *usbblk ) {
524
525 /* Refill bulk OUT endpoint */
526 usbblk_out_refill ( usbblk );
527
528 /* Refill bulk IN endpoint */
529 usbblk_in_refill ( usbblk );
530 }
531
532 /** Refill process descriptor */
533 static struct process_descriptor usbblk_process_desc =
534 PROC_DESC ( struct usbblk_device, process, usbblk_step );
535
536 /******************************************************************************
537 *
538 * SCSI command management
539 *
540 ******************************************************************************
541 */
542
543 /** Next command tag */
544 static uint16_t usbblk_tag;
545
546 /**
547 * Stop SCSI command
548 *
549 * @v usbblk USB block device
550 * @v rc Reason for stop
551 */
552 static void usbblk_stop ( struct usbblk_device *usbblk, int rc ) {
553
554 /* Stop process */
555 process_del ( &usbblk->process );
556
557 /* Reset command */
558 memset ( &usbblk->cmd, 0, sizeof ( usbblk->cmd ) );
559
560 /* Close endpoints if an error occurred */
561 if ( rc != 0 ) {
562 DBGC ( usbblk, "USBBLK %s closing for error recovery\n",
563 usbblk->func->name );
564 usbblk_close ( usbblk );
565 }
566
567 /* Terminate command */
568 intf_restart ( &usbblk->data, rc );
569 }
570
571 /**
572 * Start new SCSI command
573 *
574 * @v usbblk USB block device
575 * @v scsicmd SCSI command
576 * @ret rc Return status code
577 */
578 static int usbblk_start ( struct usbblk_device *usbblk,
579 struct scsi_cmd *scsicmd ) {
580 struct usbblk_command *cmd = &usbblk->cmd;
581 int rc;
582
583 /* Fail if command is in progress */
584 if ( cmd->tag ) {
585 rc = -EBUSY;
586 DBGC ( usbblk, "USBBLK %s cannot support multiple commands\n",
587 usbblk->func->name );
588 goto err_busy;
589 }
590
591 /* Refuse bidirectional commands */
592 if ( scsicmd->data_in_len && scsicmd->data_out_len ) {
593 rc = -EOPNOTSUPP;
594 DBGC ( usbblk, "USBBLK %s cannot support bidirectional "
595 "commands\n", usbblk->func->name );
596 goto err_bidirectional;
597 }
598
599 /* Sanity checks */
600 assert ( ! process_running ( &usbblk->process ) );
601 assert ( cmd->offset == 0 );
602
603 /* Initialise command */
604 memcpy ( &cmd->scsi, scsicmd, sizeof ( cmd->scsi ) );
605 cmd->tag = ( USBBLK_TAG_MAGIC | ++usbblk_tag );
606
607 /* Issue bulk OUT command */
608 if ( ( rc = usbblk_out_command ( usbblk ) ) != 0 )
609 goto err_command;
610
611 /* Start refill process */
612 process_add ( &usbblk->process );
613
614 return 0;
615
616 err_command:
617 memset ( &usbblk->cmd, 0, sizeof ( usbblk->cmd ) );
618 err_bidirectional:
619 err_busy:
620 return rc;
621 }
622
623 /******************************************************************************
624 *
625 * SCSI interfaces
626 *
627 ******************************************************************************
628 */
629
630 /** SCSI data interface operations */
631 static struct interface_operation usbblk_data_operations[] = {
632 INTF_OP ( intf_close, struct usbblk_device *, usbblk_stop ),
633 };
634
635 /** SCSI data interface descriptor */
636 static struct interface_descriptor usbblk_data_desc =
637 INTF_DESC ( struct usbblk_device, data, usbblk_data_operations );
638
639 /**
640 * Check SCSI command flow-control window
641 *
642 * @v usbblk USB block device
643 * @ret len Length of window
644 */
645 static size_t usbblk_scsi_window ( struct usbblk_device *usbblk ) {
646 struct usbblk_command *cmd = &usbblk->cmd;
647
648 /* Allow a single command if no command is currently in progress */
649 return ( cmd->tag ? 0 : 1 );
650 }
651
652 /**
653 * Issue SCSI command
654 *
655 * @v usbblk USB block device
656 * @v data SCSI data interface
657 * @v scsicmd SCSI command
658 * @ret tag Command tag, or negative error
659 */
660 static int usbblk_scsi_command ( struct usbblk_device *usbblk,
661 struct interface *data,
662 struct scsi_cmd *scsicmd ) {
663 struct usbblk_command *cmd = &usbblk->cmd;
664 int rc;
665
666 /* (Re)open endpoints if needed */
667 if ( ( ! usbblk->in.open ) && ( ( rc = usbblk_open ( usbblk ) ) != 0 ) )
668 goto err_open;
669
670 /* Start new command */
671 if ( ( rc = usbblk_start ( usbblk, scsicmd ) ) != 0 )
672 goto err_start;
673
674 /* Attach to parent interface and return */
675 intf_plug_plug ( &usbblk->data, data );
676 return cmd->tag;
677
678 usbblk_stop ( usbblk, rc );
679 err_start:
680 usbblk_close ( usbblk );
681 err_open:
682 return rc;
683 }
684
685 /**
686 * Close SCSI interface
687 *
688 * @v usbblk USB block device
689 * @v rc Reason for close
690 */
691 static void usbblk_scsi_close ( struct usbblk_device *usbblk, int rc ) {
692
693 /* Restart interfaces */
694 intfs_restart ( rc, &usbblk->scsi, &usbblk->data, NULL );
695
696 /* Stop any in-progress command */
697 usbblk_stop ( usbblk, rc );
698
699 /* Close endpoints */
700 usbblk_close ( usbblk );
701
702 /* Flag as closed */
703 usbblk->opened = 0;
704 }
705
706 /**
707 * Describe as an EFI device path
708 *
709 * @v usbblk USB block device
710 * @ret path EFI device path, or NULL on error
711 */
712 static EFI_DEVICE_PATH_PROTOCOL *
713 usbblk_efi_describe ( struct usbblk_device *usbblk ) {
714
715 return efi_usb_path ( usbblk->func );
716 }
717
718 /** SCSI command interface operations */
719 static struct interface_operation usbblk_scsi_operations[] = {
720 INTF_OP ( scsi_command, struct usbblk_device *, usbblk_scsi_command ),
721 INTF_OP ( xfer_window, struct usbblk_device *, usbblk_scsi_window ),
722 INTF_OP ( intf_close, struct usbblk_device *, usbblk_scsi_close ),
723 EFI_INTF_OP ( efi_describe, struct usbblk_device *,
724 usbblk_efi_describe ),
725 };
726
727 /** SCSI command interface descriptor */
728 static struct interface_descriptor usbblk_scsi_desc =
729 INTF_DESC ( struct usbblk_device, scsi, usbblk_scsi_operations );
730
731 /******************************************************************************
732 *
733 * SAN device interface
734 *
735 ******************************************************************************
736 */
737
738 /**
739 * Find USB block device
740 *
741 * @v name USB block device name
742 * @ret usbblk USB block device, or NULL
743 */
744 static struct usbblk_device * usbblk_find ( const char *name ) {
745 struct usbblk_device *usbblk;
746
747 /* Look for matching device */
748 list_for_each_entry ( usbblk, &usbblk_devices, list ) {
749 if ( strcmp ( usbblk->func->name, name ) == 0 )
750 return usbblk;
751 }
752
753 return NULL;
754 }
755
756 /**
757 * Open USB block device URI
758 *
759 * @v parent Parent interface
760 * @v uri URI
761 * @ret rc Return status code
762 */
763 static int usbblk_open_uri ( struct interface *parent, struct uri *uri ) {
764 static struct scsi_lun lun;
765 struct usbblk_device *usbblk;
766 int rc;
767
768 /* Sanity check */
769 if ( ! uri->opaque )
770 return -EINVAL;
771
772 /* Find matching device */
773 usbblk = usbblk_find ( uri->opaque );
774 if ( ! usbblk )
775 return -ENOENT;
776
777 /* Fail if device is already open */
778 if ( usbblk->opened )
779 return -EBUSY;
780
781 /* Open SCSI device */
782 if ( ( rc = scsi_open ( parent, &usbblk->scsi, &lun ) ) != 0 ) {
783 DBGC ( usbblk, "USBBLK %s could not open SCSI device: %s\n",
784 usbblk->func->name, strerror ( rc ) );
785 return rc;
786 }
787
788 /* Mark as opened */
789 usbblk->opened = 1;
790
791 return 0;
792 }
793
794 /** USB block device URI opener */
795 struct uri_opener usbblk_uri_opener __uri_opener = {
796 .scheme = "usb",
797 .open = usbblk_open_uri,
798 };
799
800 /******************************************************************************
801 *
802 * USB interface
803 *
804 ******************************************************************************
805 */
806
807 /**
808 * Probe device
809 *
810 * @v func USB function
811 * @v config Configuration descriptor
812 * @ret rc Return status code
813 */
814 static int usbblk_probe ( struct usb_function *func,
815 struct usb_configuration_descriptor *config ) {
816 struct usb_device *usb = func->usb;
817 struct usbblk_device *usbblk;
818 struct usb_interface_descriptor *desc;
819 int rc;
820
821 /* Allocate and initialise structure */
822 usbblk = zalloc ( sizeof ( *usbblk ) );
823 if ( ! usbblk ) {
824 rc = -ENOMEM;
825 goto err_alloc;
826 }
827 usbblk->func = func;
828 usb_endpoint_init ( &usbblk->out, usb, &usbblk_out_operations );
829 usb_endpoint_init ( &usbblk->in, usb, &usbblk_in_operations );
830 usb_refill_init ( &usbblk->in, 0, USBBLK_MAX_LEN, USBBLK_MAX_FILL );
831 intf_init ( &usbblk->scsi, &usbblk_scsi_desc, &usbblk->refcnt );
832 intf_init ( &usbblk->data, &usbblk_data_desc, &usbblk->refcnt );
833 process_init_stopped ( &usbblk->process, &usbblk_process_desc,
834 &usbblk->refcnt );
835
836 /* Locate interface descriptor */
837 desc = usb_interface_descriptor ( config, func->interface[0], 0 );
838 if ( ! desc ) {
839 DBGC ( usbblk, "USBBLK %s missing interface descriptor\n",
840 usbblk->func->name );
841 rc = -ENOENT;
842 goto err_desc;
843 }
844
845 /* Describe endpoints */
846 if ( ( rc = usb_endpoint_described ( &usbblk->out, config, desc,
847 USB_BULK_OUT, 0 ) ) != 0 ) {
848 DBGC ( usbblk, "USBBLK %s could not describe bulk OUT: %s\n",
849 usbblk->func->name, strerror ( rc ) );
850 goto err_out;
851 }
852 if ( ( rc = usb_endpoint_described ( &usbblk->in, config, desc,
853 USB_BULK_IN, 0 ) ) != 0 ) {
854 DBGC ( usbblk, "USBBLK %s could not describe bulk IN: %s\n",
855 usbblk->func->name, strerror ( rc ) );
856 goto err_in;
857 }
858
859 /* Add to list of devices */
860 list_add_tail ( &usbblk->list, &usbblk_devices );
861
862 usb_func_set_drvdata ( func, usbblk );
863 return 0;
864
865 err_in:
866 err_out:
867 err_desc:
868 ref_put ( &usbblk->refcnt );
869 err_alloc:
870 return rc;
871 }
872
873 /**
874 * Remove device
875 *
876 * @v func USB function
877 */
878 static void usbblk_remove ( struct usb_function *func ) {
879 struct usbblk_device *usbblk = usb_func_get_drvdata ( func );
880
881 /* Remove from list of devices */
882 list_del ( &usbblk->list );
883
884 /* Close all interfaces */
885 usbblk_scsi_close ( usbblk, -ENODEV );
886
887 /* Shut down interfaces */
888 intfs_shutdown ( -ENODEV, &usbblk->scsi, &usbblk->data, NULL );
889
890 /* Drop reference */
891 ref_put ( &usbblk->refcnt );
892 }
893
894 /** Mass storage class device IDs */
895 static struct usb_device_id usbblk_ids[] = {
896 {
897 .name = "usbblk",
898 .vendor = USB_ANY_ID,
899 .product = USB_ANY_ID,
900 },
901 };
902
903 /** Mass storage driver */
904 struct usb_driver usbblk_driver __usb_driver = {
905 .ids = usbblk_ids,
906 .id_count = ( sizeof ( usbblk_ids ) / sizeof ( usbblk_ids[0] ) ),
907 .class = USB_CLASS_ID ( USB_CLASS_MSC, USB_SUBCLASS_MSC_SCSI,
908 USB_PROTOCOL_MSC_BULK ),
909 .score = USB_SCORE_NORMAL,
910 .probe = usbblk_probe,
911 .remove = usbblk_remove,
912 };