iPXE
fcp.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 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 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 <stddef.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <assert.h>
33 #include <byteswap.h>
34 #include <ipxe/refcnt.h>
35 #include <ipxe/list.h>
36 #include <ipxe/interface.h>
37 #include <ipxe/xfer.h>
38 #include <ipxe/iobuf.h>
39 #include <ipxe/open.h>
40 #include <ipxe/process.h>
41 #include <ipxe/uri.h>
42 #include <ipxe/acpi.h>
43 #include <ipxe/scsi.h>
44 #include <ipxe/device.h>
45 #include <ipxe/edd.h>
46 #include <ipxe/efi/efi_path.h>
47 #include <ipxe/fc.h>
48 #include <ipxe/fcels.h>
49 #include <ipxe/fcp.h>
50 
51 /** @file
52  *
53  * Fibre Channel Protocol
54  *
55  */
56 
57 /* Disambiguate the various error causes */
58 #define ERANGE_READ_DATA_ORDERING \
59  __einfo_error ( EINFO_ERANGE_READ_DATA_ORDERING )
60 #define EINFO_ERANGE_READ_DATA_ORDERING \
61  __einfo_uniqify ( EINFO_ERANGE, 0x01, "Read data out of order" )
62 #define ERANGE_READ_DATA_OVERRUN \
63  __einfo_error ( EINFO_ERANGE_READ_DATA_OVERRUN )
64 #define EINFO_ERANGE_READ_DATA_OVERRUN \
65  __einfo_uniqify ( EINFO_ERANGE, 0x02, "Read data overrun" )
66 #define ERANGE_WRITE_DATA_STUCK \
67  __einfo_error ( EINFO_ERANGE_WRITE_DATA_STUCK )
68 #define EINFO_ERANGE_WRITE_DATA_STUCK \
69  __einfo_uniqify ( EINFO_ERANGE, 0x03, "Write data stuck" )
70 #define ERANGE_WRITE_DATA_OVERRUN \
71  __einfo_error ( EINFO_ERANGE_WRITE_DATA_OVERRUN )
72 #define EINFO_ERANGE_WRITE_DATA_OVERRUN \
73  __einfo_uniqify ( EINFO_ERANGE, 0x04, "Write data overrun" )
74 #define ERANGE_DATA_UNDERRUN \
75  __einfo_error ( EINFO_ERANGE_DATA_UNDERRUN )
76 #define EINFO_ERANGE_DATA_UNDERRUN \
77  __einfo_uniqify ( EINFO_ERANGE, 0x05, "Data underrun" )
78 
79 /******************************************************************************
80  *
81  * PRLI
82  *
83  ******************************************************************************
84  */
85 
87 
88 /**
89  * Transmit FCP PRLI
90  *
91  * @v els Fibre Channel ELS transaction
92  * @ret rc Return status code
93  */
94 static int fcp_prli_tx ( struct fc_els *els ) {
96 
97  /* Build service parameter page */
98  memset ( &param, 0, sizeof ( param ) );
100 
101  return fc_els_prli_tx ( els, &fcp_prli_descriptor, &param );
102 }
103 
104 /**
105  * Receive FCP PRLI
106  *
107  * @v els Fibre Channel ELS transaction
108  * @v frame ELS frame
109  * @v len Length of ELS frame
110  * @ret rc Return status code
111  */
112 static int fcp_prli_rx ( struct fc_els *els, void *data, size_t len ) {
113  return fc_els_prli_rx ( els, &fcp_prli_descriptor, data, len );
114 }
115 
116 /**
117  * Detect FCP PRLI
118  *
119  * @v els Fibre Channel ELS transaction
120  * @v data ELS frame
121  * @v len Length of ELS frame
122  * @ret rc Return status code
123  */
124 static int fcp_prli_detect ( struct fc_els *els, const void *data,
125  size_t len ) {
126  return fc_els_prli_detect ( els, &fcp_prli_descriptor, data, len );
127 }
128 
129 /** FCP PRLI ELS handler */
130 struct fc_els_handler fcp_prli_handler __fc_els_handler = {
131  .name = "PRLI-FCP",
132  .tx = fcp_prli_tx,
133  .rx = fcp_prli_rx,
134  .detect = fcp_prli_detect,
135 };
136 
137 /** FCP PRLI descriptor */
138 struct fc_els_prli_descriptor fcp_prli_descriptor __fc_els_prli_descriptor = {
139  .type = FC_TYPE_FCP,
140  .param_len = sizeof ( struct fcp_prli_service_parameters ),
141  .handler = &fcp_prli_handler,
142 };
143 
144 /******************************************************************************
145  *
146  * FCP devices and commands
147  *
148  ******************************************************************************
149  */
150 
151 /** An FCP device */
152 struct fcp_device {
153  /** Reference count */
154  struct refcnt refcnt;
155  /** Fibre Channel upper-layer protocol user */
157  /** SCSI command issuing interface */
158  struct interface scsi;
159  /** List of active commands */
161 
162  /** Device description (for boot firmware table) */
164 };
165 
166 /** An FCP command */
167 struct fcp_command {
168  /** Reference count */
169  struct refcnt refcnt;
170  /** FCP SCSI device */
172  /** List of active commands */
173  struct list_head list;
174  /** SCSI command interface */
175  struct interface scsi;
176  /** Fibre Channel exchange interface */
177  struct interface xchg;
178  /** Send process */
179  struct process process;
180  /** Send current IU
181  *
182  * @v fcpcmd FCP command
183  * @ret rc Return status code
184  */
185  int ( * send ) ( struct fcp_command *fcpcmd );
186  /** SCSI command */
188  /** Data offset within command */
189  size_t offset;
190  /** Length of data remaining to be sent within this IU */
191  size_t remaining;
192  /** Exchange ID */
194 };
195 
196 /**
197  * Get reference to FCP device
198  *
199  * @v fcpdev FCP device
200  * @ret fcpdev FCP device
201  */
202 static inline __attribute__ (( always_inline )) struct fcp_device *
203 fcpdev_get ( struct fcp_device *fcpdev ) {
204  ref_get ( &fcpdev->refcnt );
205  return fcpdev;
206 }
207 
208 /**
209  * Drop reference to FCP device
210  *
211  * @v fcpdev FCP device
212  */
213 static inline __attribute__ (( always_inline )) void
214 fcpdev_put ( struct fcp_device *fcpdev ) {
215  ref_put ( &fcpdev->refcnt );
216 }
217 
218 /**
219  * Get reference to FCP command
220  *
221  * @v fcpcmd FCP command
222  * @ret fcpcmd FCP command
223  */
224 static inline __attribute__ (( always_inline )) struct fcp_command *
225 fcpcmd_get ( struct fcp_command *fcpcmd ) {
226  ref_get ( &fcpcmd->refcnt );
227  return fcpcmd;
228 }
229 
230 /**
231  * Drop reference to FCP command
232  *
233  * @v fcpcmd FCP command
234  */
235 static inline __attribute__ (( always_inline )) void
236 fcpcmd_put ( struct fcp_command *fcpcmd ) {
237  ref_put ( &fcpcmd->refcnt );
238 }
239 
240 /**
241  * Start FCP command sending
242  *
243  * @v fcpcmd FCP command
244  * @v send Send method
245  */
246 static inline __attribute__ (( always_inline )) void
248  int ( * send ) ( struct fcp_command *fcpcmd ) ) {
249  fcpcmd->send = send;
250  process_add ( &fcpcmd->process );
251 }
252 
253 /**
254  * Stop FCP command sending
255  *
256  * @v fcpcmd FCP command
257  */
258 static inline __attribute__ (( always_inline )) void
259 fcpcmd_stop_send ( struct fcp_command *fcpcmd ) {
260  process_del ( &fcpcmd->process );
261 }
262 
263 /**
264  * Free FCP command
265  *
266  * @v refcnt Reference count
267  */
268 static void fcpcmd_free ( struct refcnt *refcnt ) {
269  struct fcp_command *fcpcmd =
270  container_of ( refcnt, struct fcp_command, refcnt );
271 
272  /* Remove from list of commands */
273  list_del ( &fcpcmd->list );
274  fcpdev_put ( fcpcmd->fcpdev );
275 
276  /* Free command */
277  free ( fcpcmd );
278 }
279 
280 /**
281  * Close FCP command
282  *
283  * @v fcpcmd FCP command
284  * @v rc Reason for close
285  */
286 static void fcpcmd_close ( struct fcp_command *fcpcmd, int rc ) {
287  struct fcp_device *fcpdev = fcpcmd->fcpdev;
288 
289  if ( rc != 0 ) {
290  DBGC ( fcpdev, "FCP %p xchg %04x closed: %s\n",
291  fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
292  }
293 
294  /* Stop sending */
295  fcpcmd_stop_send ( fcpcmd );
296 
297  /* Shut down interfaces */
298  intf_shutdown ( &fcpcmd->scsi, rc );
299  intf_shutdown ( &fcpcmd->xchg, rc );
300 }
301 
302 /**
303  * Close FCP command in error
304  *
305  * @v fcpcmd FCP command
306  * @v rc Reason for close
307  */
308 static void fcpcmd_close_err ( struct fcp_command *fcpcmd, int rc ) {
309  if ( rc == 0 )
310  rc = -EPIPE;
311  fcpcmd_close ( fcpcmd, rc );
312 }
313 
314 /**
315  * Send FCP command IU
316  *
317  * @v fcpcmd FCP command
318  * @ret rc Return status code
319  */
320 static int fcpcmd_send_cmnd ( struct fcp_command *fcpcmd ) {
321  struct fcp_device *fcpdev = fcpcmd->fcpdev;
322  struct scsi_cmd *command = &fcpcmd->command;
323  struct io_buffer *iobuf;
324  struct fcp_cmnd *cmnd;
325  struct xfer_metadata meta;
326  int rc;
327 
328  /* Sanity check */
329  if ( command->data_in_len && command->data_out_len ) {
330  DBGC ( fcpdev, "FCP %p xchg %04x cannot handle bidirectional "
331  "command\n", fcpdev, fcpcmd->xchg_id );
332  return -ENOTSUP;
333  }
334 
335  /* Allocate I/O buffer */
336  iobuf = xfer_alloc_iob ( &fcpcmd->xchg, sizeof ( *cmnd ) );
337  if ( ! iobuf ) {
338  DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate command IU\n",
339  fcpdev, fcpcmd->xchg_id );
340  return -ENOMEM;
341  }
342 
343  /* Construct command IU frame */
344  cmnd = iob_put ( iobuf, sizeof ( *cmnd ) );
345  memset ( cmnd, 0, sizeof ( *cmnd ) );
346  memcpy ( &cmnd->lun, &command->lun, sizeof ( cmnd->lun ) );
347  assert ( ! ( command->data_in_len && command->data_out_len ) );
348  if ( command->data_in_len )
349  cmnd->dirn |= FCP_CMND_RDDATA;
350  if ( command->data_out_len )
351  cmnd->dirn |= FCP_CMND_WRDATA;
352  memcpy ( &cmnd->cdb, &fcpcmd->command.cdb, sizeof ( cmnd->cdb ) );
353  cmnd->len = htonl ( command->data_in_len + command->data_out_len );
354  memset ( &meta, 0, sizeof ( meta ) );
355  meta.flags = ( XFER_FL_CMD_STAT | XFER_FL_OVER );
356  DBGC2 ( fcpdev, "FCP %p xchg %04x CMND " SCSI_CDB_FORMAT " %04x\n",
357  fcpdev, fcpcmd->xchg_id, SCSI_CDB_DATA ( cmnd->cdb ),
358  ntohl ( cmnd->len ) );
359 
360  /* No further data to send within this IU */
361  fcpcmd_stop_send ( fcpcmd );
362 
363  /* Send command IU frame */
364  if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
365  &meta ) ) != 0 ) {
366  DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver command IU: "
367  "%s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
368  return rc;
369  }
370 
371  return 0;
372 }
373 
374 /**
375  * Handle FCP read data IU
376  *
377  * @v fcpcmd FCP command
378  * @v iobuf I/O buffer
379  * @v meta Data transfer metadata
380  * @ret rc Return status code
381  */
382 static int fcpcmd_recv_rddata ( struct fcp_command *fcpcmd,
383  struct io_buffer *iobuf,
384  struct xfer_metadata *meta ) {
385  struct fcp_device *fcpdev = fcpcmd->fcpdev;
386  struct scsi_cmd *command = &fcpcmd->command;
387  size_t offset = meta->offset;
388  size_t len = iob_len ( iobuf );
389  int rc;
390 
391  /* Sanity checks */
392  if ( ! ( meta->flags & XFER_FL_ABS_OFFSET ) ) {
393  DBGC ( fcpdev, "FCP %p xchg %04x read data missing offset\n",
394  fcpdev, fcpcmd->xchg_id );
396  goto done;
397  }
398  if ( offset != fcpcmd->offset ) {
399  DBGC ( fcpdev, "FCP %p xchg %04x read data out of order "
400  "(expected %zd, received %zd)\n",
401  fcpdev, fcpcmd->xchg_id, fcpcmd->offset, offset );
403  goto done;
404  }
405  if ( ( offset + len ) > command->data_in_len ) {
406  DBGC ( fcpdev, "FCP %p xchg %04x read data overrun (max %zd, "
407  "received %zd)\n", fcpdev, fcpcmd->xchg_id,
408  command->data_in_len, ( offset + len ) );
410  goto done;
411  }
412  DBGC2 ( fcpdev, "FCP %p xchg %04x RDDATA [%08zx,%08zx)\n",
413  fcpdev, fcpcmd->xchg_id, offset, ( offset + len ) );
414 
415  /* Copy to user buffer */
416  copy_to_user ( command->data_in, offset, iobuf->data, len );
417  fcpcmd->offset += len;
418  assert ( fcpcmd->offset <= command->data_in_len );
419 
420  rc = 0;
421  done:
422  free_iob ( iobuf );
423  return rc;
424 }
425 
426 /**
427  * Send FCP write data IU
428  *
429  * @v fcpcmd FCP command
430  * @ret rc Return status code
431  */
432 static int fcpcmd_send_wrdata ( struct fcp_command *fcpcmd ) {
433  struct fcp_device *fcpdev = fcpcmd->fcpdev;
434  struct scsi_cmd *command = &fcpcmd->command;
435  struct io_buffer *iobuf;
436  struct xfer_metadata meta;
437  size_t len;
438  int rc;
439 
440  /* Calculate length to be sent */
441  len = xfer_window ( &fcpcmd->xchg );
442  if ( len > fcpcmd->remaining )
443  len = fcpcmd->remaining;
444 
445  /* Sanity checks */
446  if ( len == 0 ) {
447  DBGC ( fcpdev, "FCP %p xchg %04x write data stuck\n",
448  fcpdev, fcpcmd->xchg_id );
449  return -ERANGE_WRITE_DATA_STUCK;
450  }
451  if ( ( fcpcmd->offset + len ) > command->data_out_len ) {
452  DBGC ( fcpdev, "FCP %p xchg %04x write data overrun (max %zd, "
453  "requested %zd)\n", fcpdev, fcpcmd->xchg_id,
454  command->data_out_len, ( fcpcmd->offset + len ) );
456  }
457 
458  /* Allocate I/O buffer */
459  iobuf = xfer_alloc_iob ( &fcpcmd->xchg, len );
460  if ( ! iobuf ) {
461  DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate write data "
462  "IU for %zd bytes\n", fcpdev, fcpcmd->xchg_id, len );
463  return -ENOMEM;
464  }
465 
466  /* Construct data IU frame */
467  copy_from_user ( iob_put ( iobuf, len ), command->data_out,
468  fcpcmd->offset, len );
469  memset ( &meta, 0, sizeof ( meta ) );
471  meta.offset = fcpcmd->offset;
472  DBGC2 ( fcpdev, "FCP %p xchg %04x WRDATA [%08zx,%04zx)\n",
473  fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
474  ( fcpcmd->offset + iob_len ( iobuf ) ) );
475 
476  /* Calculate amount of data remaining to be sent within this IU */
477  assert ( len <= fcpcmd->remaining );
478  fcpcmd->offset += len;
479  fcpcmd->remaining -= len;
480  assert ( fcpcmd->offset <= command->data_out_len );
481  if ( fcpcmd->remaining == 0 ) {
482  fcpcmd_stop_send ( fcpcmd );
483  meta.flags |= XFER_FL_OVER;
484  }
485 
486  /* Send data IU frame */
487  if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
488  &meta ) ) != 0 ) {
489  DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver write data "
490  "IU: %s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
491  return rc;
492  }
493 
494  return 0;
495 }
496 
497 /**
498  * Handle FCP transfer ready IU
499  *
500  * @v fcpcmd FCP command
501  * @v iobuf I/O buffer
502  * @v meta Data transfer metadata
503  * @ret rc Return status code
504  */
505 static int fcpcmd_recv_xfer_rdy ( struct fcp_command *fcpcmd,
506  struct io_buffer *iobuf,
507  struct xfer_metadata *meta __unused ) {
508  struct fcp_device *fcpdev = fcpcmd->fcpdev;
509  struct fcp_xfer_rdy *xfer_rdy = iobuf->data;
510  int rc;
511 
512  /* Sanity checks */
513  if ( iob_len ( iobuf ) != sizeof ( *xfer_rdy ) ) {
514  DBGC ( fcpdev, "FCP %p xchg %04x received invalid transfer "
515  "ready IU:\n", fcpdev, fcpcmd->xchg_id );
516  DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
517  rc = -EPROTO;
518  goto done;
519  }
520  if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) {
521  /* We do not advertise out-of-order delivery */
522  DBGC ( fcpdev, "FCP %p xchg %04x cannot support out-of-order "
523  "delivery (expected %zd, requested %d)\n",
524  fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
525  ntohl ( xfer_rdy->offset ) );
526  rc = -EPROTO;
527  goto done;
528  }
529  DBGC2 ( fcpdev, "FCP %p xchg %04x XFER_RDY [%08x,%08x)\n",
530  fcpdev, fcpcmd->xchg_id, ntohl ( xfer_rdy->offset ),
531  ( ntohl ( xfer_rdy->offset ) + ntohl ( xfer_rdy->len ) ) );
532 
533  /* Start sending requested data */
534  fcpcmd->remaining = ntohl ( xfer_rdy->len );
536 
537  rc = 0;
538  done:
539  free_iob ( iobuf );
540  return rc;
541 }
542 
543 /**
544  * Handle FCP response IU
545  *
546  * @v fcpcmd FCP command
547  * @v iobuf I/O buffer
548  * @v meta Data transfer metadata
549  * @ret rc Return status code
550  */
551 static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd,
552  struct io_buffer *iobuf,
553  struct xfer_metadata *meta __unused ) {
554  struct fcp_device *fcpdev = fcpcmd->fcpdev;
555  struct scsi_cmd *command = &fcpcmd->command;
556  struct fcp_rsp *rsp = iobuf->data;
557  struct scsi_rsp response;
558  int rc;
559 
560  /* Sanity check */
561  if ( ( iob_len ( iobuf ) < sizeof ( *rsp ) ) ||
562  ( iob_len ( iobuf ) < ( sizeof ( *rsp ) +
564  fcp_rsp_sense_data_len ( rsp ) ) ) ) {
565  DBGC ( fcpdev, "FCP %p xchg %04x received invalid response "
566  "IU:\n", fcpdev, fcpcmd->xchg_id );
567  DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
568  rc = -EPROTO;
569  goto done;
570  }
571  DBGC2 ( fcpdev, "FCP %p xchg %04x RSP stat %02x resid %08x flags %02x"
572  "%s%s%s%s\n", fcpdev, fcpcmd->xchg_id, rsp->status,
573  ntohl ( rsp->residual ), rsp->flags,
574  ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ? " resp" : "" ),
575  ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ? " sense" : "" ),
576  ( ( rsp->flags & FCP_RSP_RESIDUAL_OVERRUN ) ? " over" : "" ),
577  ( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "" ));
578  if ( fcp_rsp_response_data ( rsp ) ) {
579  DBGC2 ( fcpdev, "FCP %p xchg %04x response data:\n",
580  fcpdev, fcpcmd->xchg_id );
581  DBGC2_HDA ( fcpdev, 0, fcp_rsp_response_data ( rsp ),
583  }
584  if ( fcp_rsp_sense_data ( rsp ) ) {
585  DBGC2 ( fcpdev, "FCP %p xchg %04x sense data:\n",
586  fcpdev, fcpcmd->xchg_id );
587  DBGC2_HDA ( fcpdev, 0, fcp_rsp_sense_data ( rsp ),
589  }
590 
591  /* Check for locally-detected command underrun */
592  if ( ( rsp->status == 0 ) &&
593  ( fcpcmd->offset != ( command->data_in_len +
594  command->data_out_len ) ) ) {
595  DBGC ( fcpdev, "FCP %p xchg %04x data underrun (expected %zd, "
596  "got %zd)\n", fcpdev, fcpcmd->xchg_id,
597  ( command->data_in_len + command->data_out_len ),
598  fcpcmd->offset );
600  goto done;
601  }
602 
603  /* Build SCSI response */
604  memset ( &response, 0, sizeof ( response ) );
605  response.status = rsp->status;
606  if ( rsp->flags & ( FCP_RSP_RESIDUAL_OVERRUN |
608  response.overrun = ntohl ( rsp->residual );
609  if ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN )
610  response.overrun = -response.overrun;
611  }
613  fcp_rsp_sense_data_len ( rsp ), &response.sense );
614 
615  /* Free buffer before sending response, to minimise
616  * out-of-memory errors.
617  */
618  free_iob ( iob_disown ( iobuf ) );
619 
620  /* Send SCSI response */
621  scsi_response ( &fcpcmd->scsi, &response );
622 
623  /* Terminate command */
624  fcpcmd_close ( fcpcmd, 0 );
625 
626  rc = 0;
627  done:
628  free_iob ( iobuf );
629  return rc;
630 }
631 
632 /**
633  * Handle unknown FCP IU
634  *
635  * @v fcpcmd FCP command
636  * @v iobuf I/O buffer
637  * @v meta Data transfer metadata
638  * @ret rc Return status code
639  */
640 static int fcpcmd_recv_unknown ( struct fcp_command *fcpcmd,
641  struct io_buffer *iobuf,
642  struct xfer_metadata *meta __unused ) {
643  struct fcp_device *fcpdev = fcpcmd->fcpdev;
644 
645  DBGC ( fcpdev, "FCP %p xchg %04x received unknown IU:\n",
646  fcpdev, fcpcmd->xchg_id );
647  DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
648  free_iob ( iobuf );
649  return -EPROTO;
650 }
651 
652 /**
653  * Transmit FCP frame
654  *
655  * @v fcpcmd FCP command
656  */
657 static void fcpcmd_step ( struct fcp_command *fcpcmd ) {
658  int rc;
659 
660  /* Send the current IU */
661  if ( ( rc = fcpcmd->send ( fcpcmd ) ) != 0 ) {
662  /* Treat failure as a fatal error */
663  fcpcmd_close ( fcpcmd, rc );
664  }
665 }
666 
667 /**
668  * Receive FCP frame
669  *
670  * @v fcpcmd FCP command
671  * @v iobuf I/O buffer
672  * @v meta Data transfer metadata
673  * @ret rc Return status code
674  */
675 static int fcpcmd_deliver ( struct fcp_command *fcpcmd,
676  struct io_buffer *iobuf,
677  struct xfer_metadata *meta ) {
678  int ( * fcpcmd_recv ) ( struct fcp_command *fcpcmd,
679  struct io_buffer *iobuf,
680  struct xfer_metadata *meta );
681  int rc;
682 
683  /* Determine handler */
684  switch ( meta->flags & ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ) ) {
685  case ( XFER_FL_RESPONSE ) :
686  fcpcmd_recv = fcpcmd_recv_rddata;
687  break;
688  case ( XFER_FL_CMD_STAT ) :
689  fcpcmd_recv = fcpcmd_recv_xfer_rdy;
690  break;
692  fcpcmd_recv = fcpcmd_recv_rsp;
693  break;
694  default:
695  fcpcmd_recv = fcpcmd_recv_unknown;
696  break;
697  }
698 
699  /* Handle IU */
700  if ( ( rc = fcpcmd_recv ( fcpcmd, iob_disown ( iobuf ), meta ) ) != 0 ){
701  /* Treat any error as fatal to the command */
702  fcpcmd_close ( fcpcmd, rc );
703  }
704 
705  return rc;
706 }
707 
708 /** FCP command SCSI interface operations */
711 };
712 
713 /** FCP command SCSI interface descriptor */
715  INTF_DESC_PASSTHRU ( struct fcp_command, scsi, fcpcmd_scsi_op, xchg );
716 
717 /** FCP command Fibre Channel exchange interface operations */
721 };
722 
723 /** FCP command Fibre Channel exchange interface descriptor */
725  INTF_DESC_PASSTHRU ( struct fcp_command, xchg, fcpcmd_xchg_op, scsi );
726 
727 /** FCP command process descriptor */
730 
731 /**
732  * Issue FCP SCSI command
733  *
734  * @v fcpdev FCP device
735  * @v parent Parent interface
736  * @v command SCSI command
737  * @ret tag Command tag, or negative error
738  */
739 static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
740  struct interface *parent,
741  struct scsi_cmd *command ) {
742  struct fcp_prli_service_parameters *param = fcpdev->user.ulp->param;
743  struct fcp_command *fcpcmd;
744  int xchg_id;
745  int rc;
746 
747  /* Check link */
748  if ( ( rc = fcpdev->user.ulp->link.rc ) != 0 ) {
749  DBGC ( fcpdev, "FCP %p could not issue command while link is "
750  "down: %s\n", fcpdev, strerror ( rc ) );
751  goto err_link;
752  }
753 
754  /* Check target capability */
755  assert ( param != NULL );
756  assert ( fcpdev->user.ulp->param_len >= sizeof ( *param ) );
757  if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
758  DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
759  fcpdev );
760  rc = -ENOTTY;
761  goto err_target;
762  }
763 
764  /* Allocate and initialise structure */
765  fcpcmd = zalloc ( sizeof ( *fcpcmd ) );
766  if ( ! fcpcmd ) {
767  rc = -ENOMEM;
768  goto err_zalloc;
769  }
770  ref_init ( &fcpcmd->refcnt, fcpcmd_free );
771  intf_init ( &fcpcmd->scsi, &fcpcmd_scsi_desc, &fcpcmd->refcnt );
772  intf_init ( &fcpcmd->xchg, &fcpcmd_xchg_desc, &fcpcmd->refcnt );
774  &fcpcmd->refcnt );
775  fcpcmd->fcpdev = fcpdev_get ( fcpdev );
776  list_add ( &fcpcmd->list, &fcpdev->fcpcmds );
777  memcpy ( &fcpcmd->command, command, sizeof ( fcpcmd->command ) );
778 
779  /* Create new exchange */
780  if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
781  fcpdev->user.ulp->peer->port,
782  &fcpdev->user.ulp->peer->port_id,
783  FC_TYPE_FCP ) ) < 0 ) {
784  rc = xchg_id;
785  DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
786  fcpdev, strerror ( rc ) );
787  goto err_xchg_originate;
788  }
789  fcpcmd->xchg_id = xchg_id;
790 
791  /* Start sending command IU */
793 
794  /* Attach to parent interface, mortalise self, and return */
795  intf_plug_plug ( &fcpcmd->scsi, parent );
796  ref_put ( &fcpcmd->refcnt );
797  return ( FCP_TAG_MAGIC | fcpcmd->xchg_id );
798 
799  err_xchg_originate:
800  fcpcmd_close ( fcpcmd, rc );
801  ref_put ( &fcpcmd->refcnt );
802  err_zalloc:
803  err_target:
804  err_link:
805  return rc;
806 }
807 
808 /**
809  * Close FCP device
810  *
811  * @v fcpdev FCP device
812  * @v rc Reason for close
813  */
814 static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) {
815  struct fcp_command *fcpcmd;
816  struct fcp_command *tmp;
817 
818  DBGC ( fcpdev, "FCP %p closed: %s\n", fcpdev, strerror ( rc ) );
819 
820  /* Shut down interfaces */
821  intf_shutdown ( &fcpdev->scsi, rc );
822 
823  /* Shut down any active commands */
825  fcpcmd_get ( fcpcmd );
826  fcpcmd_close ( fcpcmd, rc );
827  fcpcmd_put ( fcpcmd );
828  }
829 
830  /* Drop reference to ULP */
831  fc_ulp_detach ( &fcpdev->user );
832 }
833 
834 /**
835  * Check FCP device flow-control window
836  *
837  * @v fcpdev FCP device
838  * @ret len Length of window
839  */
840 static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
841  return ( fc_link_ok ( &fcpdev->user.ulp->link ) ?
842  ~( ( size_t ) 0 ) : 0 );
843 }
844 
845 /**
846  * Describe FCP device using EDD
847  *
848  * @v fcpdev FCP device
849  * @v type EDD interface type
850  * @v path EDD device path
851  * @ret rc Return status code
852  */
853 static int fcpdev_edd_describe ( struct fcp_device *fcpdev,
854  struct edd_interface_type *type,
855  union edd_device_path *path ) {
856  union {
857  struct fc_name fc;
858  uint64_t u64;
859  } wwn;
860  union {
861  struct scsi_lun scsi;
862  uint64_t u64;
863  } lun;
864 
866  memcpy ( &wwn.fc, &fcpdev->desc.wwn, sizeof ( wwn.fc ) );
867  path->fibre.wwn = be64_to_cpu ( wwn.u64 );
868  memcpy ( &lun.scsi, &fcpdev->desc.lun, sizeof ( lun.scsi ) );
869  path->fibre.lun = be64_to_cpu ( lun.u64 );
870  return 0;
871 }
872 
873 /**
874  * Identify device underlying FCP device
875  *
876  * @v fcpdev FCP device
877  * @ret device Underlying device
878  */
879 static struct device * fcpdev_identify_device ( struct fcp_device *fcpdev ) {
880 
881  /* We know the underlying device only if the link is up;
882  * otherwise we don't have a port to examine.
883  */
884  if ( ! fc_link_ok ( &fcpdev->user.ulp->link ) ) {
885  DBGC ( fcpdev, "FCP %p doesn't know underlying device "
886  "until link is up\n", fcpdev );
887  return NULL;
888  }
889 
890  /* Hand off to port's transport interface */
891  assert ( fcpdev->user.ulp->peer->port != NULL );
892  return identify_device ( &fcpdev->user.ulp->peer->port->transport );
893 }
894 
895 /**
896  * Describe as an EFI device path
897  *
898  * @v fcp FCP device
899  * @ret path EFI device path, or NULL on error
900  */
902 fcpdev_efi_describe ( struct fcp_device *fcpdev ) {
903 
904  return efi_fcp_path ( &fcpdev->desc );
905 }
906 
907 /** FCP device SCSI interface operations */
911  INTF_OP ( intf_close, struct fcp_device *, fcpdev_close ),
913  INTF_OP ( identify_device, struct fcp_device *,
916 };
917 
918 /** FCP device SCSI interface descriptor */
920  INTF_DESC ( struct fcp_device, scsi, fcpdev_scsi_op );
921 
922 /**
923  * Examine FCP ULP link state
924  *
925  * @v user Fibre Channel upper-layer protocol user
926  */
927 static void fcpdev_examine ( struct fc_ulp_user *user ) {
928  struct fcp_device *fcpdev =
929  container_of ( user, struct fcp_device, user );
930 
931  if ( fc_link_ok ( &fcpdev->user.ulp->link ) ) {
932  DBGC ( fcpdev, "FCP %p link is up\n", fcpdev );
933  } else {
934  DBGC ( fcpdev, "FCP %p link is down: %s\n",
935  fcpdev, strerror ( fcpdev->user.ulp->link.rc ) );
936  }
937 
938  /* Notify SCSI layer of window change */
939  xfer_window_changed ( &fcpdev->scsi );
940 }
941 
942 /**
943  * Open FCP device
944  *
945  * @v parent Parent interface
946  * @v wwn Fibre Channel WWN
947  * @v lun SCSI LUN
948  * @ret rc Return status code
949  */
950 static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
951  struct scsi_lun *lun ) {
952  struct fc_ulp *ulp;
953  struct fcp_device *fcpdev;
954  int rc;
955 
956  /* Get Fibre Channel ULP interface */
958  if ( ! ulp ) {
959  rc = -ENOMEM;
960  goto err_ulp_get;
961  }
962 
963  /* Allocate and initialise structure */
964  fcpdev = zalloc ( sizeof ( *fcpdev ) );
965  if ( ! fcpdev ) {
966  rc = -ENOMEM;
967  goto err_zalloc;
968  }
969  ref_init ( &fcpdev->refcnt, NULL );
970  intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
971  INIT_LIST_HEAD ( &fcpdev->fcpcmds );
972  fc_ulp_user_init ( &fcpdev->user, fcpdev_examine, &fcpdev->refcnt );
973 
974  DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
975 
976  /* Attach to Fibre Channel ULP */
977  fc_ulp_attach ( ulp, &fcpdev->user );
978 
979  /* Preserve parameters required for boot firmware table */
980  memcpy ( &fcpdev->desc.wwn, wwn, sizeof ( fcpdev->desc.wwn ) );
981  memcpy ( &fcpdev->desc.lun, lun, sizeof ( fcpdev->desc.lun ) );
982 
983  /* Attach SCSI device to parent interface */
984  if ( ( rc = scsi_open ( parent, &fcpdev->scsi, lun ) ) != 0 ) {
985  DBGC ( fcpdev, "FCP %p could not create SCSI device: %s\n",
986  fcpdev, strerror ( rc ) );
987  goto err_scsi_open;
988  }
989 
990  /* Drop temporary reference to ULP */
991  fc_ulp_put ( ulp );
992 
993  /* Mortalise self and return */
994  ref_put ( &fcpdev->refcnt );
995  return 0;
996 
997  err_scsi_open:
998  fcpdev_close ( fcpdev, rc );
999  ref_put ( &fcpdev->refcnt );
1000  err_zalloc:
1001  fc_ulp_put ( ulp );
1002  err_ulp_get:
1003  return rc;
1004 }
1005 
1006 /******************************************************************************
1007  *
1008  * FCP URIs
1009  *
1010  ******************************************************************************
1011  */
1012 
1013 /**
1014  * Parse FCP URI
1015  *
1016  * @v uri URI
1017  * @ret wwn Fibre Channel WWN
1018  * @ret lun SCSI LUN
1019  * @ret rc Return status code
1020  *
1021  * An FCP URI has the form "fcp:<wwn>:<lun>" or "fcp://<wwn>/<lun>"
1022  */
1023 static int fcp_parse_uri ( struct uri *uri, struct fc_name *wwn,
1024  struct scsi_lun *lun ) {
1025  char wwn_buf[ FC_NAME_STRLEN + 1 /* NUL */ ];
1026  const char *wwn_text;
1027  const char *lun_text;
1028  int rc;
1029 
1030  /* Extract WWN and LUN texts from URI */
1031  if ( uri->opaque ) {
1032  /* "fcp:<wwn>:<lun>" */
1033  if ( snprintf ( wwn_buf, sizeof ( wwn_buf ), "%s",
1034  uri->opaque ) < ( FC_NAME_STRLEN + 1 /* : */ ) )
1035  return -EINVAL;
1036  if ( uri->opaque[FC_NAME_STRLEN] != ':' )
1037  return -EINVAL;
1038  wwn_text = wwn_buf;
1039  lun_text = &uri->opaque[FC_NAME_STRLEN + 1];
1040  } else {
1041  /* If host exists, path must also exist */
1042  if ( ! ( uri->host && uri->path ) )
1043  return -EINVAL;
1044  if ( uri->path[0] != '/' )
1045  return -EINVAL;
1046  wwn_text = uri->host;
1047  lun_text = ( uri->path + 1 );
1048  }
1049 
1050  /* Parse WWN */
1051  if ( ( rc = fc_aton ( wwn_text, wwn ) ) != 0 )
1052  return rc;
1053 
1054  /* Parse LUN */
1055  if ( ( rc = scsi_parse_lun ( lun_text, lun ) ) != 0 )
1056  return rc;
1057 
1058  return 0;
1059 }
1060 
1061 /**
1062  * Open FCP URI
1063  *
1064  * @v parent Parent interface
1065  * @v uri URI
1066  * @ret rc Return status code
1067  */
1068 static int fcp_open ( struct interface *parent, struct uri *uri ) {
1069  struct fc_name wwn;
1070  struct scsi_lun lun;
1071  int rc;
1072 
1073  /* Parse URI */
1074  if ( ( rc = fcp_parse_uri ( uri, &wwn, &lun ) ) != 0 )
1075  return rc;
1076 
1077  /* Open FCP device */
1078  if ( ( rc = fcpdev_open ( parent, &wwn, &lun ) ) != 0 )
1079  return rc;
1080 
1081  return 0;
1082 }
1083 
1084 /** FCP URI opener */
1085 struct uri_opener fcp_uri_opener __uri_opener = {
1086  .scheme = "fcp",
1087  .open = fcp_open,
1088 };
void scsi_parse_sense(const void *data, size_t len, struct scsi_sns_descriptor *sense)
Parse SCSI sense data.
Definition: scsi.c:146
A process.
Definition: process.h:17
void fc_ulp_detach(struct fc_ulp_user *user)
Detach Fibre Channel upper-layer protocol user.
Definition: fc.c:1625
#define __attribute__(x)
Definition: compiler.h:10
static struct fcp_command * fcpcmd_get(struct fcp_command *fcpcmd)
Get reference to FCP command.
Definition: fcp.c:225
#define EINVAL
Invalid argument.
Definition: errno.h:428
An object interface operation.
Definition: interface.h:17
static struct interface_operation fcpdev_scsi_op[]
FCP device SCSI interface operations.
Definition: fcp.c:908
#define FCP_RSP_RESIDUAL_OVERRUN
Residual represents overrun.
Definition: fcp.h:80
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:146
static struct interface_descriptor fcpdev_scsi_desc
FCP device SCSI interface descriptor.
Definition: fcp.c:919
unsigned short uint16_t
Definition: stdint.h:11
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
#define iob_put(iobuf, len)
Definition: iobuf.h:120
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
An FCP transfer ready IU.
Definition: fcp.h:46
struct fc_ulp * ulp
Fibre Channel upper layer protocol.
Definition: fc.h:455
int fc_xchg_originate(struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
Originate a new Fibre Channel exchange.
Definition: fc.c:728
#define ERANGE_WRITE_DATA_OVERRUN
Definition: fcp.c:70
#define EDD_INTF_TYPE_FIBRE
EDD Fibre Channel interface type.
Definition: edd.h:65
int fc_aton(const char *wwn_text, struct fc_name *wwn)
Parse Fibre Channel WWN.
Definition: fc.c:144
#define ERANGE_WRITE_DATA_STUCK
Definition: fcp.c:66
static int fcpcmd_deliver(struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive FCP frame.
Definition: fcp.c:675
struct process process
Send process.
Definition: fcp.c:179
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
uint64_t wwn
WWN.
Definition: edd.h:131
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:47
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
static int fcpdev_open(struct interface *parent, struct fc_name *wwn, struct scsi_lun *lun)
Open FCP device.
Definition: fcp.c:950
An EDD device path.
Definition: edd.h:98
#define FCP_PRLI_NO_READ_RDY
Read FCP_XFER_RDY disabled.
Definition: fcp.h:140
A Fibre Channel extended link services handler.
Definition: fcels.h:352
A command-line command.
Definition: command.h:9
u16 fc
802.11 Frame Control field
Definition: ieee80211.h:14
I/O buffers.
Fibre Channel Protocol.
Definition: fc.h:193
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
static struct interface_operation fcpcmd_xchg_op[]
FCP command Fibre Channel exchange interface operations.
Definition: fcp.c:718
#define EPIPE
Broken pipe.
Definition: errno.h:619
union scsi_cdb cdb
SCSI CDB.
Definition: fcp.h:31
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
int edd_describe(struct interface *intf, struct edd_interface_type *type, union edd_device_path *path)
Describe a disk device using EDD.
Definition: edd.c:44
An FCP command IU.
Definition: fcp.h:19
#define DBGC(...)
Definition: compiler.h:505
static int fcp_parse_uri(struct uri *uri, struct fc_name *wwn, struct scsi_lun *lun)
Parse FCP URI.
Definition: fcp.c:1023
A process descriptor.
Definition: process.h:31
static int fcpcmd_send_cmnd(struct fcp_command *fcpcmd)
Send FCP command IU.
Definition: fcp.c:320
static int fcpcmd_recv_unknown(struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Handle unknown FCP IU.
Definition: fcp.c:640
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:107
static void fcpcmd_close(struct fcp_command *fcpcmd, int rc)
Close FCP command.
Definition: fcp.c:286
unsigned long long uint64_t
Definition: stdint.h:13
static void fcpcmd_stop_send(struct fcp_command *fcpcmd)
Stop FCP command sending.
Definition: fcp.c:259
static struct process_descriptor fcpcmd_process_desc
FCP command process descriptor.
Definition: fcp.c:728
#define ntohl(value)
Definition: byteswap.h:134
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:158
#define cpu_to_le64(value)
Definition: byteswap.h:108
const char * fc_ntoa(const struct fc_name *wwn)
Format Fibre Channel WWN.
Definition: fc.c:127
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:45
uint32_t offset
Relative offset of data.
Definition: fcp.h:48
union scsi_cdb cdb
CDB for this command.
Definition: scsi.h:253
int scsi_open(struct interface *block, struct interface *scsi, struct scsi_lun *lun)
Open SCSI device.
Definition: scsi.c:984
struct refcnt refcnt
Reference count.
Definition: fcp.c:154
Uniform Resource Identifiers.
struct fc_peer * peer
Fibre Channel peer.
Definition: fc.h:417
void process_del(struct process *process)
Remove process from process list.
Definition: process.c:79
static int fcpcmd_send_wrdata(struct fcp_command *fcpcmd)
Send FCP write data IU.
Definition: fcp.c:432
#define htonl(value)
Definition: byteswap.h:133
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:116
An EDD interface type.
Definition: edd.h:40
struct fc_els_prli_descriptor fcp_prli_descriptor __fc_els_prli_descriptor
FCP PRLI descriptor.
Definition: fcp.c:86
struct fc_name wwn
Fibre Channel WWN.
Definition: fcp.h:169
#define FCP_RSP_RESIDUAL_UNDERRUN
Residual represents underrun.
Definition: fcp.h:83
static int fcpcmd_recv_rsp(struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Handle FCP response IU.
Definition: fcp.c:551
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
A doubly-linked list entry (or list head)
Definition: list.h:18
Data transfer interfaces.
static void fcpcmd_free(struct refcnt *refcnt)
Free FCP command.
Definition: fcp.c:268
A reference counter.
Definition: refcnt.h:26
struct fc_port * port
Fibre Channel port, if known.
Definition: fc.h:354
unsigned long tmp
Definition: linux_pci.h:53
#define XFER_FL_RESPONSE
Data content is a response.
Definition: xfer.h:63
int fc_els_prli_detect(struct fc_els *els __unused, struct fc_els_prli_descriptor *descriptor, const void *data, size_t len)
Detect PRLI.
Definition: fcels.c:1092
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
int fc_els_prli_tx(struct fc_els *els, struct fc_els_prli_descriptor *descriptor, void *param)
Transmit PRLI.
Definition: fcels.c:950
#define ENOMEM
Not enough space.
Definition: errno.h:534
A hardware device.
Definition: device.h:73
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:212
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * name
Name.
Definition: fcels.h:354
static int fcpdev_scsi_command(struct fcp_device *fcpdev, struct interface *parent, struct scsi_cmd *command)
Issue FCP SCSI command.
Definition: fcp.c:739
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
A SCSI command.
Definition: scsi.c:262
Fibre Channel Protocol.
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
static int fcp_prli_rx(struct fc_els *els, void *data, size_t len)
Receive FCP PRLI.
Definition: fcp.c:112
An object interface.
Definition: interface.h:124
void fc_ulp_attach(struct fc_ulp *ulp, struct fc_ulp_user *user)
Attach Fibre Channel upper-layer protocol user.
Definition: fc.c:1607
int scsi_parse_lun(const char *lun_string, struct scsi_lun *lun)
Parse SCSI LUN.
Definition: scsi.c:117
struct ntlm_data user
User name.
Definition: ntlm.h:20
static void * fcp_rsp_sense_data(struct fcp_rsp *rsp)
Get sense data portion of FCP response.
Definition: fcp.h:113
A SCSI response information unit.
Definition: scsi.h:322
static struct interface_descriptor fcpcmd_xchg_desc
FCP command Fibre Channel exchange interface descriptor.
Definition: fcp.c:724
size_t param_len
Service parameter length.
Definition: fc.h:433
#define DBGC_HDA(...)
Definition: compiler.h:506
Object interfaces.
static void fcpdev_put(struct fcp_device *fcpdev)
Drop reference to FCP device.
Definition: fcp.c:214
static int fc_link_ok(struct fc_link_state *link)
Check Fibre Channel link state.
Definition: fc.h:108
#define FCP_CMND_RDDATA
Command includes data-in.
Definition: fcp.h:40
const char * path
Path (after URI decoding)
Definition: uri.h:80
static void fcpcmd_start_send(struct fcp_command *fcpcmd, int(*send)(struct fcp_command *fcpcmd))
Start FCP command sending.
Definition: fcp.c:247
static void * fcp_rsp_response_data(struct fcp_rsp *rsp)
Get response data portion of FCP response.
Definition: fcp.h:91
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
const char * scheme
URI protocol name.
Definition: open.h:53
uint64_t u64
Definition: stdint.h:25
struct interface scsi
SCSI command interface.
Definition: fcp.c:175
struct interface scsi
SCSI command issuing interface.
Definition: fcp.c:158
static EFI_DEVICE_PATH_PROTOCOL * fcpdev_efi_describe(struct fcp_device *fcpdev)
Describe as an EFI device path.
Definition: fcp.c:902
struct fcp_description desc
Device description (for boot firmware table)
Definition: fcp.c:163
EFI_DEVICE_PATH_PROTOCOL * efi_fcp_path(struct fcp_description *desc)
Construct EFI device path for Fibre Channel device.
Definition: efi_path.c:443
struct scsi_lun lun
SCSI LUN.
Definition: fcp.h:21
static struct fcp_device * fcpdev_get(struct fcp_device *fcpdev)
Get reference to FCP device.
Definition: fcp.c:203
uint8_t lun
Logical Unit Number.
Definition: edd.h:32
#define FCP_TAG_MAGIC
FCP tag magic marker.
Definition: fcp.h:43
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:458
#define EPROTO
Protocol error.
Definition: errno.h:624
static struct interface_operation fcpcmd_scsi_op[]
FCP command SCSI interface operations.
Definition: fcp.c:709
static int fcpcmd_recv_rddata(struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle FCP read data IU.
Definition: fcp.c:382
static int fcp_open(struct interface *parent, struct uri *uri)
Open FCP URI.
Definition: fcp.c:1068
void process_add(struct process *process)
Add process to process list.
Definition: process.c:59
int meta(WINDOW *, bool)
Linked lists.
#define DBGC2_HDA(...)
Definition: compiler.h:523
#define EFI_INTF_OP
Definition: efi.h:350
uint64_t rsp
Definition: librm.h:267
An object interface descriptor.
Definition: interface.h:55
A Fibre Channel extended link services transaction.
Definition: fcels.h:323
struct fc_port_id port_id
Peer port ID, if known.
Definition: fc.h:356
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define FCP_PRLI_INITIATOR
Has initiator functionality.
Definition: fcp.h:146
ACPI data structures.
#define be64_to_cpu(value)
Definition: byteswap.h:117
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
void * param
Service parameters, if any.
Definition: fc.h:431
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:92
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
struct hv_monitor_parameter param[4][32]
Parameters.
Definition: hyperv.h:24
static size_t fcp_rsp_response_data_len(struct fcp_rsp *rsp)
Get length of response data portion of FCP response.
Definition: fcp.h:102
uint8_t status
SCSI status code.
Definition: scsi.h:324
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
static __always_inline void copy_to_user(userptr_t dest, off_t dest_off, const void *src, size_t len)
Copy data to user buffer.
Definition: uaccess.h:324
struct fc_link_state link
Link state monitor.
Definition: fc.h:427
struct scsi_cmd command
SCSI command.
Definition: fcp.c:187
#define XFER_FL_CMD_STAT
Data content represents a command or status message.
Definition: xfer.h:60
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
Processes.
#define SCSI_CDB_DATA(cdb)
printf() parameters for dumping a scsi_cdb
Definition: scsi.h:223
Data transfer interface opening.
EFI device paths.
struct interface xchg
Fibre Channel exchange interface.
Definition: fcp.c:177
uint16_t xchg_id
Exchange ID.
Definition: fcp.c:193
A Fibre Channel upper-layer protocol user.
Definition: fc.h:453
static size_t fcpdev_window(struct fcp_device *fcpdev)
Check FCP device flow-control window.
Definition: fcp.c:840
#define FCP_PRLI_TARGET
Has target functionality.
Definition: fcp.h:143
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
#define ERANGE_READ_DATA_OVERRUN
Definition: fcp.c:62
uint8_t lun
Logical Unit Number.
Definition: edd.h:109
Fibre Channel.
#define FCP_RSP_RESPONSE_LEN_VALID
Response length field is valid.
Definition: fcp.h:74
const char * host
Host name.
Definition: uri.h:76
An FCP device description.
Definition: fcp.h:167
struct list_head list
List of active commands.
Definition: fcp.c:173
static int fcpcmd_recv_xfer_rdy(struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Handle FCP transfer ready IU.
Definition: fcp.c:505
size_t offset
Data offset within command.
Definition: fcp.c:189
static void fcpcmd_step(struct fcp_command *fcpcmd)
Transmit FCP frame.
Definition: fcp.c:657
A Fibre Channel name.
Definition: fc.h:29
static int fcp_prli_detect(struct fc_els *els, const void *data, size_t len)
Detect FCP PRLI.
Definition: fcp.c:124
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
void scsi_response(struct interface *intf, struct scsi_rsp *response)
Report SCSI response.
Definition: scsi.c:206
SCSI devices.
A SCSI command information unit.
Definition: scsi.h:249
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:45
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
struct scsi_lun lun
SCSI LUN.
Definition: fcp.h:171
static int fcp_prli_tx(struct fc_els *els)
Transmit FCP PRLI.
Definition: fcp.c:94
static struct interface_descriptor fcpcmd_scsi_desc
FCP command SCSI interface descriptor.
Definition: fcp.c:714
EFI_DEVICE_PATH_PROTOCOL * efi_describe(struct interface *intf)
Describe object as an EFI device path.
Definition: efi_path.c:580
#define SCSI_CDB_FORMAT
printf() format for dumping a scsi_cdb
Definition: scsi.h:219
static struct device * fcpdev_identify_device(struct fcp_device *fcpdev)
Identify device underlying FCP device.
Definition: fcp.c:879
uint32_t len
Length.
Definition: ena.h:14
An FCP PRLI service parameter page.
Definition: fcp.h:131
uint32_t type
Operating system type.
Definition: ena.h:12
const char * opaque
Opaque part.
Definition: uri.h:70
#define DBGC2(...)
Definition: compiler.h:522
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
struct refcnt refcnt
Reference count.
Definition: fcp.c:169
struct scsi_sns_descriptor sense
Autosense data (if any)
Definition: scsi.h:333
size_t remaining
Length of data remaining to be sent within this IU.
Definition: fcp.c:191
void * data
Start of data.
Definition: iobuf.h:48
#define PROC_DESC(object_type, process, _step)
Define a process descriptor.
Definition: process.h:82
struct interface transport
Transport interface.
Definition: fc.h:261
#define ERANGE_DATA_UNDERRUN
Definition: fcp.c:74
static void fc_ulp_put(struct fc_ulp *ulp)
Drop reference to Fibre Channel upper-layer protocol.
Definition: fc.h:485
Reference counting.
uint8_t data[48]
Additional event data.
Definition: ena.h:22
static void fcpcmd_put(struct fcp_command *fcpcmd)
Drop reference to FCP command.
Definition: fcp.c:236
uint32_t len
Data length.
Definition: fcp.h:33
Device model.
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
A Uniform Resource Identifier.
Definition: uri.h:64
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
Definition: interface.h:97
A SCSI LUN.
Definition: scsi.h:236
Enhanced Disk Drive specification.
#define XFER_FL_OVER
Sender is relinquishing use of half-duplex channel.
Definition: xfer.h:50
struct device * identify_device(struct interface *intf)
Identify a device behind an interface.
Definition: device.c:125
static void fcpdev_examine(struct fc_ulp_user *user)
Examine FCP ULP link state.
Definition: fcp.c:927
#define FCP_RSP_SENSE_LEN_VALID
Sense length field is valid.
Definition: fcp.h:77
struct list_head fcpcmds
List of active commands.
Definition: fcp.c:160
struct fc_ulp_user user
Fibre Channel upper-layer protocol user.
Definition: fcp.c:156
An FCP response IU.
Definition: fcp.h:56
int(* send)(struct fcp_command *fcpcmd)
Send current IU.
Definition: fcp.c:185
int fc_els_prli_rx(struct fc_els *els, struct fc_els_prli_descriptor *descriptor, void *data, size_t len)
Receive PRLI.
Definition: fcels.c:1006
struct fc_els_handler fcp_prli_handler __fc_els_handler
FCP PRLI ELS handler.
Definition: fcp.c:130
uint32_t len
Burst length.
Definition: fcp.h:50
#define FCP_CMND_WRDATA
Command includes data-out.
Definition: fcp.h:37
unsigned int type
Upper-layer protocol type.
Definition: fcels.h:388
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:203
A URI opener.
Definition: open.h:47
#define FC_NAME_STRLEN
Length of Fibre Channel name text.
Definition: fc.h:34
A Fibre Channel ELS PRLI descriptor.
Definition: fcels.h:386
An FCP command.
Definition: fcp.c:167
struct fc_ulp * fc_ulp_get_wwn_type(const struct fc_name *port_wwn, unsigned int type)
Get Fibre Channel upper-layer protocol by port name and type.
Definition: fc.c:1880
struct uri_opener fcp_uri_opener __uri_opener
FCP URI opener.
Definition: fcp.c:1085
static void fcpcmd_close_err(struct fcp_command *fcpcmd, int rc)
Close FCP command in error.
Definition: fcp.c:308
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
static void fc_ulp_user_init(struct fc_ulp_user *user, void(*examine)(struct fc_ulp_user *user), struct refcnt *refcnt)
Initialise Fibre Channel upper-layer protocol user.
Definition: fc.h:519
uint8_t dirn
Direction.
Definition: fcp.h:29
struct bofm_section_header done
Definition: bofm_test.c:46
ssize_t overrun
Data overrun (or negative underrun)
Definition: scsi.h:326
static int fcpdev_edd_describe(struct fcp_device *fcpdev, struct edd_interface_type *type, union edd_device_path *path)
Describe FCP device using EDD.
Definition: fcp.c:853
struct fcp_device * fcpdev
FCP SCSI device.
Definition: fcp.c:171
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
A Fibre Channel upper-layer protocol.
Definition: fc.h:413
#define ERANGE_READ_DATA_ORDERING
Definition: fcp.c:58
static size_t fcp_rsp_sense_data_len(struct fcp_rsp *rsp)
Get length of sense data portion of FCP response.
Definition: fcp.h:125
Fibre Channel Extended Link Services.
void * memset(void *dest, int character, size_t len) __nonnull
uint64_t wwn
WWN.
Definition: edd.h:30
An FCP device.
Definition: fcp.c:152
A persistent I/O buffer.
Definition: iobuf.h:33
struct arbelprm_send_doorbell send
Definition: arbel.h:11
static void fcpdev_close(struct fcp_device *fcpdev, int rc)
Close FCP device.
Definition: fcp.c:814