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