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
24FILE_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 */
94static 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 */
112static 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 */
124static 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 */
130struct 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 */
138struct 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 */
153 /** Reference count */
155 /** Fibre Channel upper-layer protocol user */
157 /** SCSI command issuing interface */
159 /** List of active commands */
161
162 /** Device description (for boot firmware table) */
164};
165
166/** An FCP command */
168 /** Reference count */
170 /** FCP SCSI device */
172 /** List of active commands */
174 /** SCSI command interface */
176 /** Fibre Channel exchange interface */
178 /** Send 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 */
202static inline __attribute__ (( always_inline )) struct fcp_device *
203fcpdev_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 */
213static inline __attribute__ (( always_inline )) void
214fcpdev_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 */
224static inline __attribute__ (( always_inline )) struct fcp_command *
225fcpcmd_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 */
235static inline __attribute__ (( always_inline )) void
236fcpcmd_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 */
246static 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 */
258static inline __attribute__ (( always_inline )) void
259fcpcmd_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 */
268static void fcpcmd_free ( struct refcnt *refcnt ) {
269 struct fcp_command *fcpcmd =
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 */
286static 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 */
308static 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 */
320static 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 */
382static 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 DBGC2 ( fcpdev, "FCP %p xchg %04x RDDATA [%08zx,%08zx)\n",
406 fcpdev, fcpcmd->xchg_id, offset, ( offset + len ) );
407
408 /* Copy to user buffer */
409 if ( ( rc = xferbuf_write ( &command->data_in, offset,
410 iobuf->data, len ) ) != 0 ) {
411 DBGC ( fcpdev, "FCP %p xchg %04x buffer overrun: %s\n",
412 fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
413 goto done;
414 }
415 fcpcmd->offset += len;
416 assert ( fcpcmd->offset <= command->data_in.len );
417
418 rc = 0;
419 done:
420 free_iob ( iobuf );
421 return rc;
422}
423
424/**
425 * Send FCP write data IU
426 *
427 * @v fcpcmd FCP command
428 * @ret rc Return status code
429 */
430static int fcpcmd_send_wrdata ( struct fcp_command *fcpcmd ) {
431 struct fcp_device *fcpdev = fcpcmd->fcpdev;
432 struct scsi_cmd *command = &fcpcmd->command;
433 struct io_buffer *iobuf;
434 struct xfer_metadata meta;
435 size_t len;
436 int rc;
437
438 /* Calculate length to be sent */
439 len = xfer_window ( &fcpcmd->xchg );
440 if ( len > fcpcmd->remaining )
441 len = fcpcmd->remaining;
442
443 /* Sanity checks */
444 if ( len == 0 ) {
445 DBGC ( fcpdev, "FCP %p xchg %04x write data stuck\n",
446 fcpdev, fcpcmd->xchg_id );
448 goto err_sanity;
449 }
450
451 /* Allocate I/O buffer */
452 iobuf = xfer_alloc_iob ( &fcpcmd->xchg, len );
453 if ( ! iobuf ) {
454 DBGC ( fcpdev, "FCP %p xchg %04x cannot allocate write data "
455 "IU for %zd bytes\n", fcpdev, fcpcmd->xchg_id, len );
456 rc = -ENOMEM;
457 goto err_alloc;
458 }
459
460 /* Construct data IU frame */
461 if ( ( rc = xferbuf_read ( &command->data_out, fcpcmd->offset,
462 iob_put ( iobuf, len ), len ) ) != 0 )
463 goto err_read;
464 memset ( &meta, 0, sizeof ( meta ) );
466 meta.offset = fcpcmd->offset;
467 DBGC2 ( fcpdev, "FCP %p xchg %04x WRDATA [%08zx,%04zx)\n",
468 fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
469 ( fcpcmd->offset + iob_len ( iobuf ) ) );
470
471 /* Calculate amount of data remaining to be sent within this IU */
472 assert ( len <= fcpcmd->remaining );
473 fcpcmd->offset += len;
474 fcpcmd->remaining -= len;
475 assert ( fcpcmd->offset <= command->data_out.len );
476 if ( fcpcmd->remaining == 0 ) {
477 fcpcmd_stop_send ( fcpcmd );
478 meta.flags |= XFER_FL_OVER;
479 }
480
481 /* Send data IU frame */
482 if ( ( rc = xfer_deliver ( &fcpcmd->xchg, iob_disown ( iobuf ),
483 &meta ) ) != 0 ) {
484 DBGC ( fcpdev, "FCP %p xchg %04x cannot deliver write data "
485 "IU: %s\n", fcpdev, fcpcmd->xchg_id, strerror ( rc ) );
486 goto err_deliver;
487 }
488
489 return 0;
490
491 err_deliver:
492 err_read:
493 free_iob ( iobuf );
494 err_alloc:
495 err_sanity:
496 return rc;
497}
498
499/**
500 * Handle FCP transfer ready IU
501 *
502 * @v fcpcmd FCP command
503 * @v iobuf I/O buffer
504 * @v meta Data transfer metadata
505 * @ret rc Return status code
506 */
507static int fcpcmd_recv_xfer_rdy ( struct fcp_command *fcpcmd,
508 struct io_buffer *iobuf,
509 struct xfer_metadata *meta __unused ) {
510 struct fcp_device *fcpdev = fcpcmd->fcpdev;
511 struct fcp_xfer_rdy *xfer_rdy = iobuf->data;
512 int rc;
513
514 /* Sanity checks */
515 if ( iob_len ( iobuf ) != sizeof ( *xfer_rdy ) ) {
516 DBGC ( fcpdev, "FCP %p xchg %04x received invalid transfer "
517 "ready IU:\n", fcpdev, fcpcmd->xchg_id );
518 DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
519 rc = -EPROTO;
520 goto done;
521 }
522 if ( ntohl ( xfer_rdy->offset ) != fcpcmd->offset ) {
523 /* We do not advertise out-of-order delivery */
524 DBGC ( fcpdev, "FCP %p xchg %04x cannot support out-of-order "
525 "delivery (expected %zd, requested %d)\n",
526 fcpdev, fcpcmd->xchg_id, fcpcmd->offset,
527 ntohl ( xfer_rdy->offset ) );
528 rc = -EPROTO;
529 goto done;
530 }
531 DBGC2 ( fcpdev, "FCP %p xchg %04x XFER_RDY [%08x,%08x)\n",
532 fcpdev, fcpcmd->xchg_id, ntohl ( xfer_rdy->offset ),
533 ( ntohl ( xfer_rdy->offset ) + ntohl ( xfer_rdy->len ) ) );
534
535 /* Start sending requested data */
536 fcpcmd->remaining = ntohl ( xfer_rdy->len );
538
539 rc = 0;
540 done:
541 free_iob ( iobuf );
542 return rc;
543}
544
545/**
546 * Handle FCP response IU
547 *
548 * @v fcpcmd FCP command
549 * @v iobuf I/O buffer
550 * @v meta Data transfer metadata
551 * @ret rc Return status code
552 */
553static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd,
554 struct io_buffer *iobuf,
555 struct xfer_metadata *meta __unused ) {
556 struct fcp_device *fcpdev = fcpcmd->fcpdev;
557 struct scsi_cmd *command = &fcpcmd->command;
558 struct fcp_rsp *rsp = iobuf->data;
559 struct scsi_rsp response;
560 int rc;
561
562 /* Sanity check */
563 if ( ( iob_len ( iobuf ) < sizeof ( *rsp ) ) ||
564 ( iob_len ( iobuf ) < ( sizeof ( *rsp ) +
566 fcp_rsp_sense_data_len ( rsp ) ) ) ) {
567 DBGC ( fcpdev, "FCP %p xchg %04x received invalid response "
568 "IU:\n", fcpdev, fcpcmd->xchg_id );
569 DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
570 rc = -EPROTO;
571 goto done;
572 }
573 DBGC2 ( fcpdev, "FCP %p xchg %04x RSP stat %02x resid %08x flags %02x"
574 "%s%s%s%s\n", fcpdev, fcpcmd->xchg_id, rsp->status,
575 ntohl ( rsp->residual ), rsp->flags,
576 ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ? " resp" : "" ),
577 ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ? " sense" : "" ),
578 ( ( rsp->flags & FCP_RSP_RESIDUAL_OVERRUN ) ? " over" : "" ),
579 ( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "" ));
580 if ( fcp_rsp_response_data ( rsp ) ) {
581 DBGC2 ( fcpdev, "FCP %p xchg %04x response data:\n",
582 fcpdev, fcpcmd->xchg_id );
583 DBGC2_HDA ( fcpdev, 0, fcp_rsp_response_data ( rsp ),
585 }
586 if ( fcp_rsp_sense_data ( rsp ) ) {
587 DBGC2 ( fcpdev, "FCP %p xchg %04x sense data:\n",
588 fcpdev, fcpcmd->xchg_id );
589 DBGC2_HDA ( fcpdev, 0, fcp_rsp_sense_data ( rsp ),
591 }
592
593 /* Check for locally-detected command underrun */
594 if ( ( rsp->status == 0 ) &&
595 ( fcpcmd->offset != ( command->data_in.len +
596 command->data_out.len ) ) ) {
597 DBGC ( fcpdev, "FCP %p xchg %04x data underrun (expected %zd, "
598 "got %zd)\n", fcpdev, fcpcmd->xchg_id,
599 ( command->data_in.len + command->data_out.len ),
600 fcpcmd->offset );
602 goto done;
603 }
604
605 /* Build SCSI response */
606 memset ( &response, 0, sizeof ( response ) );
607 response.status = rsp->status;
608 if ( rsp->flags & ( FCP_RSP_RESIDUAL_OVERRUN |
610 response.overrun = ntohl ( rsp->residual );
611 if ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN )
612 response.overrun = -response.overrun;
613 }
615 fcp_rsp_sense_data_len ( rsp ), &response.sense );
616
617 /* Free buffer before sending response, to minimise
618 * out-of-memory errors.
619 */
620 free_iob ( iob_disown ( iobuf ) );
621
622 /* Send SCSI response */
623 scsi_response ( &fcpcmd->scsi, &response );
624
625 /* Terminate command */
626 fcpcmd_close ( fcpcmd, 0 );
627
628 rc = 0;
629 done:
630 free_iob ( iobuf );
631 return rc;
632}
633
634/**
635 * Handle unknown FCP IU
636 *
637 * @v fcpcmd FCP command
638 * @v iobuf I/O buffer
639 * @v meta Data transfer metadata
640 * @ret rc Return status code
641 */
642static int fcpcmd_recv_unknown ( struct fcp_command *fcpcmd,
643 struct io_buffer *iobuf,
644 struct xfer_metadata *meta __unused ) {
645 struct fcp_device *fcpdev = fcpcmd->fcpdev;
646
647 DBGC ( fcpdev, "FCP %p xchg %04x received unknown IU:\n",
648 fcpdev, fcpcmd->xchg_id );
649 DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) );
650 free_iob ( iobuf );
651 return -EPROTO;
652}
653
654/**
655 * Transmit FCP frame
656 *
657 * @v fcpcmd FCP command
658 */
659static void fcpcmd_step ( struct fcp_command *fcpcmd ) {
660 int rc;
661
662 /* Send the current IU */
663 if ( ( rc = fcpcmd->send ( fcpcmd ) ) != 0 ) {
664 /* Treat failure as a fatal error */
665 fcpcmd_close ( fcpcmd, rc );
666 }
667}
668
669/**
670 * Receive FCP frame
671 *
672 * @v fcpcmd FCP command
673 * @v iobuf I/O buffer
674 * @v meta Data transfer metadata
675 * @ret rc Return status code
676 */
677static int fcpcmd_deliver ( struct fcp_command *fcpcmd,
678 struct io_buffer *iobuf,
679 struct xfer_metadata *meta ) {
680 int ( * fcpcmd_recv ) ( struct fcp_command *fcpcmd,
681 struct io_buffer *iobuf,
682 struct xfer_metadata *meta );
683 int rc;
684
685 /* Determine handler */
686 switch ( meta->flags & ( XFER_FL_CMD_STAT | XFER_FL_RESPONSE ) ) {
687 case ( XFER_FL_RESPONSE ) :
688 fcpcmd_recv = fcpcmd_recv_rddata;
689 break;
690 case ( XFER_FL_CMD_STAT ) :
691 fcpcmd_recv = fcpcmd_recv_xfer_rdy;
692 break;
694 fcpcmd_recv = fcpcmd_recv_rsp;
695 break;
696 default:
697 fcpcmd_recv = fcpcmd_recv_unknown;
698 break;
699 }
700
701 /* Handle IU */
702 if ( ( rc = fcpcmd_recv ( fcpcmd, iob_disown ( iobuf ), meta ) ) != 0 ){
703 /* Treat any error as fatal to the command */
704 fcpcmd_close ( fcpcmd, rc );
705 }
706
707 return rc;
708}
709
710/** FCP command SCSI interface operations */
713};
714
715/** FCP command SCSI interface descriptor */
717 INTF_DESC_PASSTHRU ( struct fcp_command, scsi, fcpcmd_scsi_op, xchg );
718
719/** FCP command Fibre Channel exchange interface operations */
724
725/** FCP command Fibre Channel exchange interface descriptor */
727 INTF_DESC_PASSTHRU ( struct fcp_command, xchg, fcpcmd_xchg_op, scsi );
728
729/** FCP command process descriptor */
732
733/**
734 * Issue FCP SCSI command
735 *
736 * @v fcpdev FCP device
737 * @v parent Parent interface
738 * @v command SCSI command
739 * @ret tag Command tag, or negative error
740 */
741static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
742 struct interface *parent,
743 struct scsi_cmd *command ) {
745 struct fcp_command *fcpcmd;
746 int xchg_id;
747 int rc;
748
749 /* Check link */
750 if ( ( rc = fcpdev->user.ulp->link.rc ) != 0 ) {
751 DBGC ( fcpdev, "FCP %p could not issue command while link is "
752 "down: %s\n", fcpdev, strerror ( rc ) );
753 goto err_link;
754 }
755
756 /* Check target capability */
757 assert ( param != NULL );
758 assert ( fcpdev->user.ulp->param_len >= sizeof ( *param ) );
759 if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
760 DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
761 fcpdev );
762 rc = -ENOTTY;
763 goto err_target;
764 }
765
766 /* Allocate and initialise structure */
767 fcpcmd = zalloc ( sizeof ( *fcpcmd ) );
768 if ( ! fcpcmd ) {
769 rc = -ENOMEM;
770 goto err_zalloc;
771 }
772 ref_init ( &fcpcmd->refcnt, fcpcmd_free );
773 intf_init ( &fcpcmd->scsi, &fcpcmd_scsi_desc, &fcpcmd->refcnt );
774 intf_init ( &fcpcmd->xchg, &fcpcmd_xchg_desc, &fcpcmd->refcnt );
776 &fcpcmd->refcnt );
777 fcpcmd->fcpdev = fcpdev_get ( fcpdev );
778 list_add ( &fcpcmd->list, &fcpdev->fcpcmds );
779 memcpy ( &fcpcmd->command, command, sizeof ( fcpcmd->command ) );
780
781 /* Create new exchange */
782 if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
785 FC_TYPE_FCP ) ) < 0 ) {
786 rc = xchg_id;
787 DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
788 fcpdev, strerror ( rc ) );
789 goto err_xchg_originate;
790 }
791 fcpcmd->xchg_id = xchg_id;
792
793 /* Start sending command IU */
795
796 /* Attach to parent interface, mortalise self, and return */
797 intf_plug_plug ( &fcpcmd->scsi, parent );
798 ref_put ( &fcpcmd->refcnt );
799 return ( FCP_TAG_MAGIC | fcpcmd->xchg_id );
800
801 err_xchg_originate:
802 fcpcmd_close ( fcpcmd, rc );
803 ref_put ( &fcpcmd->refcnt );
804 err_zalloc:
805 err_target:
806 err_link:
807 return rc;
808}
809
810/**
811 * Close FCP device
812 *
813 * @v fcpdev FCP device
814 * @v rc Reason for close
815 */
816static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) {
817 struct fcp_command *fcpcmd;
818 struct fcp_command *tmp;
819
820 DBGC ( fcpdev, "FCP %p closed: %s\n", fcpdev, strerror ( rc ) );
821
822 /* Shut down interfaces */
824
825 /* Shut down any active commands */
827 fcpcmd_get ( fcpcmd );
828 fcpcmd_close ( fcpcmd, rc );
829 fcpcmd_put ( fcpcmd );
830 }
831
832 /* Drop reference to ULP */
834}
835
836/**
837 * Check FCP device flow-control window
838 *
839 * @v fcpdev FCP device
840 * @ret len Length of window
841 */
842static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
843 return ( fc_link_ok ( &fcpdev->user.ulp->link ) ?
844 ~( ( size_t ) 0 ) : 0 );
845}
846
847/**
848 * Describe FCP device using EDD
849 *
850 * @v fcpdev FCP device
851 * @v type EDD interface type
852 * @v path EDD device path
853 * @ret rc Return status code
854 */
856 struct edd_interface_type *type,
857 union edd_device_path *path ) {
858 union {
859 struct fc_name fc;
861 } wwn;
862 union {
863 struct scsi_lun scsi;
865 } lun;
866
868 memcpy ( &wwn.fc, &fcpdev->desc.wwn, sizeof ( wwn.fc ) );
869 path->fibre.wwn = be64_to_cpu ( wwn.u64 );
870 memcpy ( &lun.scsi, &fcpdev->desc.lun, sizeof ( lun.scsi ) );
871 path->fibre.lun = be64_to_cpu ( lun.u64 );
872 return 0;
873}
874
875/**
876 * Identify device underlying FCP device
877 *
878 * @v fcpdev FCP device
879 * @ret device Underlying device
880 */
881static struct device * fcpdev_identify_device ( struct fcp_device *fcpdev ) {
882
883 /* We know the underlying device only if the link is up;
884 * otherwise we don't have a port to examine.
885 */
886 if ( ! fc_link_ok ( &fcpdev->user.ulp->link ) ) {
887 DBGC ( fcpdev, "FCP %p doesn't know underlying device "
888 "until link is up\n", fcpdev );
889 return NULL;
890 }
891
892 /* Hand off to port's transport interface */
893 assert ( fcpdev->user.ulp->peer->port != NULL );
894 return identify_device ( &fcpdev->user.ulp->peer->port->transport );
895}
896
897/**
898 * Describe as an EFI device path
899 *
900 * @v fcp FCP device
901 * @ret path EFI device path, or NULL on error
902 */
904fcpdev_efi_describe ( struct fcp_device *fcpdev ) {
905
906 return efi_fcp_path ( &fcpdev->desc );
907}
908
909/** FCP device SCSI interface operations */
919
920/** FCP device SCSI interface descriptor */
922 INTF_DESC ( struct fcp_device, scsi, fcpdev_scsi_op );
923
924/**
925 * Examine FCP ULP link state
926 *
927 * @v user Fibre Channel upper-layer protocol user
928 */
929static void fcpdev_examine ( struct fc_ulp_user *user ) {
930 struct fcp_device *fcpdev =
931 container_of ( user, struct fcp_device, user );
932
933 if ( fc_link_ok ( &fcpdev->user.ulp->link ) ) {
934 DBGC ( fcpdev, "FCP %p link is up\n", fcpdev );
935 } else {
936 DBGC ( fcpdev, "FCP %p link is down: %s\n",
937 fcpdev, strerror ( fcpdev->user.ulp->link.rc ) );
938 }
939
940 /* Notify SCSI layer of window change */
941 xfer_window_changed ( &fcpdev->scsi );
942}
943
944/**
945 * Open FCP device
946 *
947 * @v parent Parent interface
948 * @v wwn Fibre Channel WWN
949 * @v lun SCSI LUN
950 * @ret rc Return status code
951 */
952static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
953 struct scsi_lun *lun ) {
954 struct fc_ulp *ulp;
955 struct fcp_device *fcpdev;
956 int rc;
957
958 /* Get Fibre Channel ULP interface */
960 if ( ! ulp ) {
961 rc = -ENOMEM;
962 goto err_ulp_get;
963 }
964
965 /* Allocate and initialise structure */
966 fcpdev = zalloc ( sizeof ( *fcpdev ) );
967 if ( ! fcpdev ) {
968 rc = -ENOMEM;
969 goto err_zalloc;
970 }
971 ref_init ( &fcpdev->refcnt, NULL );
972 intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
973 INIT_LIST_HEAD ( &fcpdev->fcpcmds );
974 fc_ulp_user_init ( &fcpdev->user, fcpdev_examine, &fcpdev->refcnt );
975
976 DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
977
978 /* Attach to Fibre Channel ULP */
979 fc_ulp_attach ( ulp, &fcpdev->user );
980
981 /* Preserve parameters required for boot firmware table */
982 memcpy ( &fcpdev->desc.wwn, wwn, sizeof ( fcpdev->desc.wwn ) );
983 memcpy ( &fcpdev->desc.lun, lun, sizeof ( fcpdev->desc.lun ) );
984
985 /* Attach SCSI device to parent interface */
986 if ( ( rc = scsi_open ( parent, &fcpdev->scsi, lun ) ) != 0 ) {
987 DBGC ( fcpdev, "FCP %p could not create SCSI device: %s\n",
988 fcpdev, strerror ( rc ) );
989 goto err_scsi_open;
990 }
991
992 /* Drop temporary reference to ULP */
993 fc_ulp_put ( ulp );
994
995 /* Mortalise self and return */
996 ref_put ( &fcpdev->refcnt );
997 return 0;
998
999 err_scsi_open:
1000 fcpdev_close ( fcpdev, rc );
1001 ref_put ( &fcpdev->refcnt );
1002 err_zalloc:
1003 fc_ulp_put ( ulp );
1004 err_ulp_get:
1005 return rc;
1006}
1007
1008/******************************************************************************
1009 *
1010 * FCP URIs
1011 *
1012 ******************************************************************************
1013 */
1014
1015/**
1016 * Parse FCP URI
1017 *
1018 * @v uri URI
1019 * @ret wwn Fibre Channel WWN
1020 * @ret lun SCSI LUN
1021 * @ret rc Return status code
1022 *
1023 * An FCP URI has the form "fcp:<wwn>:<lun>" or "fcp://<wwn>/<lun>"
1024 */
1025static int fcp_parse_uri ( struct uri *uri, struct fc_name *wwn,
1026 struct scsi_lun *lun ) {
1027 char wwn_buf[ FC_NAME_STRLEN + 1 /* NUL */ ];
1028 const char *wwn_text;
1029 const char *lun_text;
1030 int rc;
1031
1032 /* Extract WWN and LUN texts from URI */
1033 if ( uri->opaque ) {
1034 /* "fcp:<wwn>:<lun>" */
1035 if ( snprintf ( wwn_buf, sizeof ( wwn_buf ), "%s",
1036 uri->opaque ) < ( FC_NAME_STRLEN + 1 /* : */ ) )
1037 return -EINVAL;
1038 if ( uri->opaque[FC_NAME_STRLEN] != ':' )
1039 return -EINVAL;
1040 wwn_text = wwn_buf;
1041 lun_text = &uri->opaque[FC_NAME_STRLEN + 1];
1042 } else {
1043 /* If host exists, path must also exist */
1044 if ( ! ( uri->host && uri->path ) )
1045 return -EINVAL;
1046 if ( uri->path[0] != '/' )
1047 return -EINVAL;
1048 wwn_text = uri->host;
1049 lun_text = ( uri->path + 1 );
1050 }
1051
1052 /* Parse WWN */
1053 if ( ( rc = fc_aton ( wwn_text, wwn ) ) != 0 )
1054 return rc;
1055
1056 /* Parse LUN */
1057 if ( ( rc = scsi_parse_lun ( lun_text, lun ) ) != 0 )
1058 return rc;
1059
1060 return 0;
1061}
1062
1063/**
1064 * Open FCP URI
1065 *
1066 * @v parent Parent interface
1067 * @v uri URI
1068 * @ret rc Return status code
1069 */
1070static int fcp_open ( struct interface *parent, struct uri *uri ) {
1071 struct fc_name wwn;
1072 struct scsi_lun lun;
1073 int rc;
1074
1075 /* Parse URI */
1076 if ( ( rc = fcp_parse_uri ( uri, &wwn, &lun ) ) != 0 )
1077 return rc;
1078
1079 /* Open FCP device */
1080 if ( ( rc = fcpdev_open ( parent, &wwn, &lun ) ) != 0 )
1081 return rc;
1082
1083 return 0;
1084}
1085
1086/** FCP URI opener */
1087struct uri_opener fcp_uri_opener __uri_opener = {
1088 .scheme = "fcp",
1089 .open = fcp_open,
1090};
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct arbelprm_send_doorbell send
Definition arbel.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
unsigned long long uint64_t
Definition stdint.h:13
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
struct bofm_section_header done
Definition bofm_test.c:46
uint16_t offset
Offset to command line.
Definition bzimage.h:3
struct device * identify_device(struct interface *intf)
Identify a device behind an interface.
Definition device.c:126
Device model.
ring len
Length.
Definition dwmac.h:226
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:45
Enhanced Disk Drive specification.
uint8_t lun
Logical Unit Number.
Definition edd.h:3
uint64_t wwn
WWN.
Definition edd.h:1
#define EDD_INTF_TYPE_FIBRE
EDD Fibre Channel interface type.
Definition edd.h:66
EFI_DEVICE_PATH_PROTOCOL * efi_describe(struct interface *intf)
Describe object as an EFI device path.
Definition efi_path.c:945
EFI_DEVICE_PATH_PROTOCOL * efi_fcp_path(struct fcp_description *desc)
Construct EFI device path for Fibre Channel device.
Definition efi_path.c:641
EFI device paths.
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t meta
Metadata flags.
Definition ena.h:3
Error codes.
int fc_aton(const char *wwn_text, struct fc_name *wwn)
Parse Fibre Channel WWN.
Definition fc.c:144
void fc_ulp_detach(struct fc_ulp_user *user)
Detach Fibre Channel upper-layer protocol user.
Definition fc.c:1625
void fc_ulp_attach(struct fc_ulp *ulp, struct fc_ulp_user *user)
Attach Fibre Channel upper-layer protocol user.
Definition fc.c:1607
const char * fc_ntoa(const struct fc_name *wwn)
Format Fibre Channel WWN.
Definition fc.c:127
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
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
Fibre Channel.
@ FC_TYPE_FCP
Fibre Channel Protocol.
Definition fc.h:194
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:520
static void fc_ulp_put(struct fc_ulp *ulp)
Drop reference to Fibre Channel upper-layer protocol.
Definition fc.h:486
#define FC_NAME_STRLEN
Length of Fibre Channel name text.
Definition fc.h:35
static int fc_link_ok(struct fc_link_state *link)
Check Fibre Channel link state.
Definition fc.h:109
int fc_els_prli_tx(struct fc_els *els, struct fc_els_prli_descriptor *descriptor, void *param)
Transmit PRLI.
Definition fcels.c:950
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
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
Fibre Channel Extended Link Services.
#define __fc_els_handler
Declare a Fibre Channel ELS handler.
Definition fcels.h:384
#define __fc_els_prli_descriptor
Declare a Fibre Channel ELS PRLI descriptor.
Definition fcels.h:401
static int fcp_prli_tx(struct fc_els *els)
Transmit FCP PRLI.
Definition fcp.c:94
static int fcp_prli_rx(struct fc_els *els, void *data, size_t len)
Receive FCP PRLI.
Definition fcp.c:112
static int fcp_prli_detect(struct fc_els *els, const void *data, size_t len)
Detect FCP PRLI.
Definition fcp.c:124
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:553
static int fcp_open(struct interface *parent, struct uri *uri)
Open FCP URI.
Definition fcp.c:1070
static int fcpcmd_send_cmnd(struct fcp_command *fcpcmd)
Send FCP command IU.
Definition fcp.c:320
static struct fcp_device * fcpdev_get(struct fcp_device *fcpdev)
Get reference to FCP device.
Definition fcp.c:203
#define ERANGE_DATA_UNDERRUN
Definition fcp.c:74
#define ERANGE_READ_DATA_ORDERING
Definition fcp.c:58
static struct interface_operation fcpdev_scsi_op[]
FCP device SCSI interface operations.
Definition fcp.c:910
static struct interface_descriptor fcpdev_scsi_desc
FCP device SCSI interface descriptor.
Definition fcp.c:921
static void fcpcmd_put(struct fcp_command *fcpcmd)
Drop reference to FCP command.
Definition fcp.c:236
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:507
static void fcpcmd_close_err(struct fcp_command *fcpcmd, int rc)
Close FCP command in error.
Definition fcp.c:308
static int fcpdev_scsi_command(struct fcp_device *fcpdev, struct interface *parent, struct scsi_cmd *command)
Issue FCP SCSI command.
Definition fcp.c:741
static void fcpcmd_stop_send(struct fcp_command *fcpcmd)
Stop FCP command sending.
Definition fcp.c:259
static struct interface_operation fcpcmd_scsi_op[]
FCP command SCSI interface operations.
Definition fcp.c:711
static struct interface_operation fcpcmd_xchg_op[]
FCP command Fibre Channel exchange interface operations.
Definition fcp.c:720
static void fcpcmd_free(struct refcnt *refcnt)
Free FCP command.
Definition fcp.c:268
static void fcpcmd_close(struct fcp_command *fcpcmd, int rc)
Close FCP command.
Definition fcp.c:286
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:855
static int fcp_parse_uri(struct uri *uri, struct fc_name *wwn, struct scsi_lun *lun)
Parse FCP URI.
Definition fcp.c:1025
#define ERANGE_WRITE_DATA_STUCK
Definition fcp.c:66
static int fcpcmd_send_wrdata(struct fcp_command *fcpcmd)
Send FCP write data IU.
Definition fcp.c:430
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:642
static EFI_DEVICE_PATH_PROTOCOL * fcpdev_efi_describe(struct fcp_device *fcpdev)
Describe as an EFI device path.
Definition fcp.c:904
static void fcpdev_put(struct fcp_device *fcpdev)
Drop reference to FCP device.
Definition fcp.c:214
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 struct fcp_command * fcpcmd_get(struct fcp_command *fcpcmd)
Get reference to FCP command.
Definition fcp.c:225
static struct process_descriptor fcpcmd_process_desc
FCP command process descriptor.
Definition fcp.c:730
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 fcpcmd_step(struct fcp_command *fcpcmd)
Transmit FCP frame.
Definition fcp.c:659
static struct interface_descriptor fcpcmd_xchg_desc
FCP command Fibre Channel exchange interface descriptor.
Definition fcp.c:726
static size_t fcpdev_window(struct fcp_device *fcpdev)
Check FCP device flow-control window.
Definition fcp.c:842
static struct interface_descriptor fcpcmd_scsi_desc
FCP command SCSI interface descriptor.
Definition fcp.c:716
static void fcpdev_examine(struct fc_ulp_user *user)
Examine FCP ULP link state.
Definition fcp.c:929
static void fcpdev_close(struct fcp_device *fcpdev, int rc)
Close FCP device.
Definition fcp.c:816
static int fcpdev_open(struct interface *parent, struct fc_name *wwn, struct scsi_lun *lun)
Open FCP device.
Definition fcp.c:952
static int fcpcmd_deliver(struct fcp_command *fcpcmd, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive FCP frame.
Definition fcp.c:677
static struct device * fcpdev_identify_device(struct fcp_device *fcpdev)
Identify device underlying FCP device.
Definition fcp.c:881
Fibre Channel Protocol.
#define FCP_RSP_RESIDUAL_OVERRUN
Residual represents overrun.
Definition fcp.h:81
#define FCP_RSP_RESPONSE_LEN_VALID
Response length field is valid.
Definition fcp.h:75
static size_t fcp_rsp_sense_data_len(struct fcp_rsp *rsp)
Get length of sense data portion of FCP response.
Definition fcp.h:126
#define FCP_PRLI_TARGET
Has target functionality.
Definition fcp.h:144
#define FCP_CMND_WRDATA
Command includes data-out.
Definition fcp.h:38
#define FCP_RSP_SENSE_LEN_VALID
Sense length field is valid.
Definition fcp.h:78
static size_t fcp_rsp_response_data_len(struct fcp_rsp *rsp)
Get length of response data portion of FCP response.
Definition fcp.h:103
#define FCP_PRLI_NO_READ_RDY
Read FCP_XFER_RDY disabled.
Definition fcp.h:141
#define FCP_PRLI_INITIATOR
Has initiator functionality.
Definition fcp.h:147
#define FCP_RSP_RESIDUAL_UNDERRUN
Residual represents underrun.
Definition fcp.h:84
static void * fcp_rsp_sense_data(struct fcp_rsp *rsp)
Get sense data portion of FCP response.
Definition fcp.h:114
#define FCP_TAG_MAGIC
FCP tag magic marker.
Definition fcp.h:44
#define FCP_CMND_RDDATA
Command includes data-in.
Definition fcp.h:41
static void * fcp_rsp_response_data(struct fcp_rsp *rsp)
Get response data portion of FCP response.
Definition fcp.h:92
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define EINVAL
Invalid argument.
Definition errno.h:429
#define EPROTO
Protocol error.
Definition errno.h:625
#define EPIPE
Broken pipe.
Definition errno.h:620
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define SCSI_CDB_DATA(cdb)
printf() parameters for dumping a scsi_cdb
Definition scsi.h:224
#define SCSI_CDB_FORMAT
printf() format for dumping a scsi_cdb
Definition scsi.h:220
u16 fc
802.11 Frame Control field
Definition ieee80211.h:0
#define ntohl(value)
Definition byteswap.h:135
#define cpu_to_le64(value)
Definition byteswap.h:109
#define htonl(value)
Definition byteswap.h:134
#define be64_to_cpu(value)
Definition byteswap.h:118
#define __attribute__(x)
Definition compiler.h:10
ACPI data structures.
#define EFI_INTF_OP
Definition efi.h:381
struct hv_monitor_parameter param[4][32]
Parameters.
Definition hyperv.h:13
uint64_t u64
Definition stdint.h:26
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
Object interfaces.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
Definition interface.h:98
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
I/O buffers.
#define iob_put(iobuf, len)
Definition iobuf.h:125
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:217
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
uint64_t rsp
Definition librm.h:18
unsigned long tmp
Definition linux_pci.h:65
Linked lists.
#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:459
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Data transfer interface opening.
#define __uri_opener
Register a URI opener.
Definition open.h:68
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
Processes.
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:146
#define PROC_DESC(object_type, process, _step)
Define a process descriptor.
Definition process.h:83
Reference counting.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int scsi_open(struct interface *block, struct interface *scsi, struct scsi_lun *lun)
Open SCSI device.
Definition scsi.c:987
void scsi_response(struct interface *intf, struct scsi_rsp *response)
Report SCSI response.
Definition scsi.c:207
void scsi_parse_sense(const void *data, size_t len, struct scsi_sns_descriptor *sense)
Parse SCSI sense data.
Definition scsi.c:147
int scsi_parse_lun(const char *lun_string, struct scsi_lun *lun)
Parse SCSI LUN.
Definition scsi.c:118
SCSI devices.
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition DevicePath.h:45
A command-line command.
Definition command.h:10
A hardware device.
Definition device.h:77
An EDD interface type.
Definition edd.h:41
A Fibre Channel extended link services handler.
Definition fcels.h:353
A Fibre Channel ELS PRLI descriptor.
Definition fcels.h:387
A Fibre Channel extended link services transaction.
Definition fcels.h:324
A Fibre Channel name.
Definition fc.h:30
struct fc_port * port
Fibre Channel port, if known.
Definition fc.h:355
struct fc_port_id port_id
Peer port ID, if known.
Definition fc.h:357
struct interface transport
Transport interface.
Definition fc.h:262
A Fibre Channel upper-layer protocol user.
Definition fc.h:454
struct fc_ulp * ulp
Fibre Channel upper layer protocol.
Definition fc.h:456
A Fibre Channel upper-layer protocol.
Definition fc.h:414
size_t param_len
Service parameter length.
Definition fc.h:434
struct fc_peer * peer
Fibre Channel peer.
Definition fc.h:418
struct fc_link_state link
Link state monitor.
Definition fc.h:428
void * param
Service parameters, if any.
Definition fc.h:432
An FCP command IU.
Definition fcp.h:20
uint32_t len
Data length.
Definition fcp.h:34
union scsi_cdb cdb
SCSI CDB.
Definition fcp.h:32
uint8_t dirn
Direction.
Definition fcp.h:30
struct scsi_lun lun
SCSI LUN.
Definition fcp.h:22
An FCP command.
Definition fcp.c:167
struct interface xchg
Fibre Channel exchange interface.
Definition fcp.c:177
size_t offset
Data offset within command.
Definition fcp.c:189
struct refcnt refcnt
Reference count.
Definition fcp.c:169
size_t remaining
Length of data remaining to be sent within this IU.
Definition fcp.c:191
int(* send)(struct fcp_command *fcpcmd)
Send current IU.
Definition fcp.c:185
struct process process
Send process.
Definition fcp.c:179
struct list_head list
List of active commands.
Definition fcp.c:173
struct fcp_device * fcpdev
FCP SCSI device.
Definition fcp.c:171
struct interface scsi
SCSI command interface.
Definition fcp.c:175
struct scsi_cmd command
SCSI command.
Definition fcp.c:187
uint16_t xchg_id
Exchange ID.
Definition fcp.c:193
An FCP device description.
Definition fcp.h:168
struct fc_name wwn
Fibre Channel WWN.
Definition fcp.h:170
struct scsi_lun lun
SCSI LUN.
Definition fcp.h:172
An FCP device.
Definition fcp.c:152
struct fcp_description desc
Device description (for boot firmware table).
Definition fcp.c:163
struct fc_ulp_user user
Fibre Channel upper-layer protocol user.
Definition fcp.c:156
struct interface scsi
SCSI command issuing interface.
Definition fcp.c:158
struct list_head fcpcmds
List of active commands.
Definition fcp.c:160
struct refcnt refcnt
Reference count.
Definition fcp.c:154
An FCP PRLI service parameter page.
Definition fcp.h:132
An FCP response IU.
Definition fcp.h:57
An FCP transfer ready IU.
Definition fcp.h:47
uint32_t offset
Relative offset of data.
Definition fcp.h:49
uint32_t len
Burst length.
Definition fcp.h:51
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
A doubly-linked list entry (or list head).
Definition list.h:19
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A reference counter.
Definition refcnt.h:27
A SCSI command information unit.
Definition scsi.h:250
union scsi_cdb cdb
CDB for this command.
Definition scsi.h:254
A SCSI command.
Definition scsi.c:263
A SCSI LUN.
Definition scsi.h:237
A SCSI response information unit.
Definition scsi.h:313
struct scsi_sns_descriptor sense
Autosense data (if any).
Definition scsi.h:324
uint8_t status
SCSI status code.
Definition scsi.h:315
ssize_t overrun
Data overrun (or negative underrun).
Definition scsi.h:317
A URI opener.
Definition open.h:48
A Uniform Resource Identifier.
Definition uri.h:65
const char * path
Path (after URI decoding).
Definition uri.h:81
const char * host
Host name.
Definition uri.h:77
const char * opaque
Opaque part.
Definition uri.h:71
Data transfer metadata.
Definition xfer.h:23
An EDD device path.
Definition edd.h:99
uint8_t lun
Logical Unit Number.
Definition edd.h:110
uint64_t wwn
WWN.
Definition edd.h:132
Uniform Resource Identifiers.
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147
Data transfer interfaces.
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48
#define XFER_FL_OVER
Sender is relinquishing use of half-duplex channel.
Definition xfer.h:51
#define XFER_FL_RESPONSE
Data content is a response.
Definition xfer.h:64
#define XFER_FL_CMD_STAT
Data content represents a command or status message.
Definition xfer.h:61
int xferbuf_read(struct xfer_buffer *xferbuf, size_t offset, void *data, size_t len)
Read from data transfer buffer.
Definition xferbuf.c:138
int xferbuf_write(struct xfer_buffer *xferbuf, size_t offset, const void *data, size_t len)
Write to data transfer buffer.
Definition xferbuf.c:105