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