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