Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / 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 };