iPXE
aoe.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stddef.h>
00027 #include <string.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <errno.h>
00031 #include <assert.h>
00032 #include <byteswap.h>
00033 #include <ipxe/list.h>
00034 #include <ipxe/if_ether.h>
00035 #include <ipxe/iobuf.h>
00036 #include <ipxe/uaccess.h>
00037 #include <ipxe/netdevice.h>
00038 #include <ipxe/features.h>
00039 #include <ipxe/interface.h>
00040 #include <ipxe/xfer.h>
00041 #include <ipxe/uri.h>
00042 #include <ipxe/open.h>
00043 #include <ipxe/ata.h>
00044 #include <ipxe/device.h>
00045 #include <ipxe/aoe.h>
00046 
00047 /** @file
00048  *
00049  * AoE protocol
00050  *
00051  */
00052 
00053 FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 );
00054 
00055 struct net_protocol aoe_protocol __net_protocol;
00056 struct acpi_model abft_model __acpi_model;
00057 
00058 /******************************************************************************
00059  *
00060  * AoE devices and commands
00061  *
00062  ******************************************************************************
00063  */
00064 
00065 /** List of all AoE devices */
00066 static LIST_HEAD ( aoe_devices );
00067 
00068 /** List of active AoE commands */
00069 static LIST_HEAD ( aoe_commands );
00070 
00071 /** An AoE device */
00072 struct aoe_device {
00073         /** Reference counter */
00074         struct refcnt refcnt;
00075 
00076         /** Network device */
00077         struct net_device *netdev;
00078         /** ATA command issuing interface */
00079         struct interface ata;
00080 
00081         /** Major number */
00082         uint16_t major;
00083         /** Minor number */
00084         uint8_t minor;
00085         /** Target MAC address */
00086         uint8_t target[MAX_LL_ADDR_LEN];
00087 
00088         /** Saved timeout value */
00089         unsigned long timeout;
00090 
00091         /** Configuration command interface */
00092         struct interface config;
00093         /** Device is configued */
00094         int configured;
00095 
00096         /** ACPI descriptor */
00097         struct acpi_descriptor desc;
00098 };
00099 
00100 /** An AoE command */
00101 struct aoe_command {
00102         /** Reference count */
00103         struct refcnt refcnt;
00104         /** AOE device */
00105         struct aoe_device *aoedev;
00106         /** List of active commands */
00107         struct list_head list;
00108 
00109         /** ATA command interface */
00110         struct interface ata;
00111 
00112         /** ATA command */
00113         struct ata_cmd command;
00114         /** Command type */
00115         struct aoe_command_type *type;
00116         /** Command tag */
00117         uint32_t tag;
00118 
00119         /** Retransmission timer */
00120         struct retry_timer timer;
00121 };
00122 
00123 /** An AoE command type */
00124 struct aoe_command_type {
00125         /**
00126          * Calculate length of AoE command IU
00127          *
00128          * @v aoecmd            AoE command
00129          * @ret len             Length of command IU
00130          */
00131         size_t ( * cmd_len ) ( struct aoe_command *aoecmd );
00132         /**
00133          * Build AoE command IU
00134          *
00135          * @v aoecmd            AoE command
00136          * @v data              Command IU
00137          * @v len               Length of command IU
00138          */
00139         void ( * cmd ) ( struct aoe_command *aoecmd, void *data, size_t len );
00140         /**
00141          * Handle AoE response IU
00142          *
00143          * @v aoecmd            AoE command
00144          * @v data              Response IU
00145          * @v len               Length of response IU
00146          * @v ll_source         Link-layer source address
00147          * @ret rc              Return status code
00148          */
00149         int ( * rsp ) ( struct aoe_command *aoecmd, const void *data,
00150                         size_t len, const void *ll_source );
00151 };
00152 
00153 /**
00154  * Get reference to AoE device
00155  *
00156  * @v aoedev            AoE device
00157  * @ret aoedev          AoE device
00158  */
00159 static inline __attribute__ (( always_inline )) struct aoe_device *
00160 aoedev_get ( struct aoe_device *aoedev ) {
00161         ref_get ( &aoedev->refcnt );
00162         return aoedev;
00163 }
00164 
00165 /**
00166  * Drop reference to AoE device
00167  *
00168  * @v aoedev            AoE device
00169  */
00170 static inline __attribute__ (( always_inline )) void
00171 aoedev_put ( struct aoe_device *aoedev ) {
00172         ref_put ( &aoedev->refcnt );
00173 }
00174 
00175 /**
00176  * Get reference to AoE command
00177  *
00178  * @v aoecmd            AoE command
00179  * @ret aoecmd          AoE command
00180  */
00181 static inline __attribute__ (( always_inline )) struct aoe_command *
00182 aoecmd_get ( struct aoe_command *aoecmd ) {
00183         ref_get ( &aoecmd->refcnt );
00184         return aoecmd;
00185 }
00186 
00187 /**
00188  * Drop reference to AoE command
00189  *
00190  * @v aoecmd            AoE command
00191  */
00192 static inline __attribute__ (( always_inline )) void
00193 aoecmd_put ( struct aoe_command *aoecmd ) {
00194         ref_put ( &aoecmd->refcnt );
00195 }
00196 
00197 /**
00198  * Name AoE device
00199  *
00200  * @v aoedev            AoE device
00201  * @ret name            AoE device name
00202  */
00203 static const char * aoedev_name ( struct aoe_device *aoedev ) {
00204         static char buf[16];
00205 
00206         snprintf ( buf, sizeof ( buf ), "%s/e%d.%d", aoedev->netdev->name,
00207                    aoedev->major, aoedev->minor );
00208         return buf;
00209 }
00210 
00211 /**
00212  * Free AoE command
00213  *
00214  * @v refcnt            Reference counter
00215  */
00216 static void aoecmd_free ( struct refcnt *refcnt ) {
00217         struct aoe_command *aoecmd =
00218                 container_of ( refcnt, struct aoe_command, refcnt );
00219 
00220         assert ( ! timer_running ( &aoecmd->timer ) );
00221         assert ( list_empty ( &aoecmd->list ) );
00222 
00223         aoedev_put ( aoecmd->aoedev );
00224         free ( aoecmd );
00225 }
00226 
00227 /**
00228  * Close AoE command
00229  *
00230  * @v aoecmd            AoE command
00231  * @v rc                Reason for close
00232  */
00233 static void aoecmd_close ( struct aoe_command *aoecmd, int rc ) {
00234         struct aoe_device *aoedev = aoecmd->aoedev;
00235 
00236         /* Stop timer */
00237         stop_timer ( &aoecmd->timer );
00238 
00239         /* Preserve the timeout value for subsequent commands */
00240         aoedev->timeout = aoecmd->timer.timeout;
00241 
00242         /* Remove from list of commands */
00243         if ( ! list_empty ( &aoecmd->list ) ) {
00244                 list_del ( &aoecmd->list );
00245                 INIT_LIST_HEAD ( &aoecmd->list );
00246                 aoecmd_put ( aoecmd );
00247         }
00248 
00249         /* Shut down interfaces */
00250         intf_shutdown ( &aoecmd->ata, rc );
00251 }
00252 
00253 /**
00254  * Transmit AoE command request
00255  *
00256  * @v aoecmd            AoE command
00257  * @ret rc              Return status code
00258  */
00259 static int aoecmd_tx ( struct aoe_command *aoecmd ) {
00260         struct aoe_device *aoedev = aoecmd->aoedev;
00261         struct net_device *netdev = aoedev->netdev;
00262         struct io_buffer *iobuf;
00263         struct aoehdr *aoehdr;
00264         size_t cmd_len;
00265         int rc;
00266 
00267         /* Sanity check */
00268         assert ( netdev != NULL );
00269 
00270         /* If we are transmitting anything that requires a response,
00271          * start the retransmission timer.  Do this before attempting
00272          * to allocate the I/O buffer, in case allocation itself
00273          * fails.
00274          */
00275         start_timer ( &aoecmd->timer );
00276 
00277         /* Create outgoing I/O buffer */
00278         cmd_len = aoecmd->type->cmd_len ( aoecmd );
00279         iobuf = alloc_iob ( MAX_LL_HEADER_LEN + cmd_len );
00280         if ( ! iobuf )
00281                 return -ENOMEM;
00282         iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
00283         aoehdr = iob_put ( iobuf, cmd_len );
00284 
00285         /* Fill AoE header */
00286         memset ( aoehdr, 0, sizeof ( *aoehdr ) );
00287         aoehdr->ver_flags = AOE_VERSION;
00288         aoehdr->major = htons ( aoedev->major );
00289         aoehdr->minor = aoedev->minor;
00290         aoehdr->tag = htonl ( aoecmd->tag );
00291         aoecmd->type->cmd ( aoecmd, iobuf->data, iob_len ( iobuf ) );
00292 
00293         /* Send packet */
00294         if ( ( rc = net_tx ( iobuf, netdev, &aoe_protocol, aoedev->target,
00295                              netdev->ll_addr ) ) != 0 ) {
00296                 DBGC ( aoedev, "AoE %s/%08x could not transmit: %s\n",
00297                        aoedev_name ( aoedev ), aoecmd->tag,
00298                        strerror ( rc ) );
00299                 return rc;
00300         }
00301 
00302         return 0;
00303 }
00304 
00305 /**
00306  * Receive AoE command response
00307  *
00308  * @v aoecmd            AoE command
00309  * @v iobuf             I/O buffer
00310  * @v ll_source         Link-layer source address
00311  * @ret rc              Return status code
00312  */
00313 static int aoecmd_rx ( struct aoe_command *aoecmd, struct io_buffer *iobuf,
00314                        const void *ll_source ) {
00315         struct aoe_device *aoedev = aoecmd->aoedev;
00316         struct aoehdr *aoehdr = iobuf->data;
00317         int rc;
00318 
00319         /* Sanity check */
00320         if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
00321                 DBGC ( aoedev, "AoE %s/%08x received underlength response "
00322                        "(%zd bytes)\n", aoedev_name ( aoedev ),
00323                        aoecmd->tag, iob_len ( iobuf ) );
00324                 rc = -EINVAL;
00325                 goto done;
00326         }
00327         if ( ( ntohs ( aoehdr->major ) != aoedev->major ) ||
00328              ( aoehdr->minor != aoedev->minor ) ) {
00329                 DBGC ( aoedev, "AoE %s/%08x received response for incorrect "
00330                        "device e%d.%d\n", aoedev_name ( aoedev ), aoecmd->tag,
00331                        ntohs ( aoehdr->major ), aoehdr->minor );
00332                 rc = -EINVAL;
00333                 goto done;
00334         }
00335 
00336         /* Catch command failures */
00337         if ( aoehdr->ver_flags & AOE_FL_ERROR ) {
00338                 DBGC ( aoedev, "AoE %s/%08x terminated in error\n",
00339                        aoedev_name ( aoedev ), aoecmd->tag );
00340                 aoecmd_close ( aoecmd, -EIO );
00341                 rc = -EIO;
00342                 goto done;
00343         }
00344 
00345         /* Hand off to command completion handler */
00346         if ( ( rc = aoecmd->type->rsp ( aoecmd, iobuf->data, iob_len ( iobuf ),
00347                                         ll_source ) ) != 0 )
00348                 goto done;
00349 
00350  done:
00351         /* Free I/O buffer */
00352         free_iob ( iobuf );
00353 
00354         /* Terminate command */
00355         aoecmd_close ( aoecmd, rc );
00356 
00357         return rc;
00358 }
00359 
00360 /**
00361  * Handle AoE retry timer expiry
00362  *
00363  * @v timer             AoE retry timer
00364  * @v fail              Failure indicator
00365  */
00366 static void aoecmd_expired ( struct retry_timer *timer, int fail ) {
00367         struct aoe_command *aoecmd =
00368                 container_of ( timer, struct aoe_command, timer );
00369 
00370         if ( fail ) {
00371                 aoecmd_close ( aoecmd, -ETIMEDOUT );
00372         } else {
00373                 aoecmd_tx ( aoecmd );
00374         }
00375 }
00376 
00377 /**
00378  * Calculate length of AoE ATA command IU
00379  *
00380  * @v aoecmd            AoE command
00381  * @ret len             Length of command IU
00382  */
00383 static size_t aoecmd_ata_cmd_len ( struct aoe_command *aoecmd ) {
00384         struct ata_cmd *command = &aoecmd->command;
00385 
00386         return ( sizeof ( struct aoehdr ) + sizeof ( struct aoeata ) +
00387                  command->data_out_len );
00388 }
00389 
00390 /**
00391  * Build AoE ATA command IU
00392  *
00393  * @v aoecmd            AoE command
00394  * @v data              Command IU
00395  * @v len               Length of command IU
00396  */
00397 static void aoecmd_ata_cmd ( struct aoe_command *aoecmd,
00398                              void *data, size_t len ) {
00399         struct aoe_device *aoedev = aoecmd->aoedev;
00400         struct ata_cmd *command = &aoecmd->command;
00401         struct aoehdr *aoehdr = data;
00402         struct aoeata *aoeata = &aoehdr->payload[0].ata;
00403 
00404         /* Sanity check */
00405         linker_assert ( AOE_FL_DEV_HEAD == ATA_DEV_SLAVE, __fix_ata_h__ );
00406         assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) +
00407                           command->data_out_len ) );
00408 
00409         /* Build IU */
00410         aoehdr->command = AOE_CMD_ATA;
00411         memset ( aoeata, 0, sizeof ( *aoeata ) );
00412         aoeata->aflags = ( ( command->cb.lba48 ? AOE_FL_EXTENDED : 0 ) |
00413                            ( command->cb.device & ATA_DEV_SLAVE ) |
00414                            ( command->data_out_len ? AOE_FL_WRITE : 0 ) );
00415         aoeata->err_feat = command->cb.err_feat.bytes.cur;
00416         aoeata->count = command->cb.count.native;
00417         aoeata->cmd_stat = command->cb.cmd_stat;
00418         aoeata->lba.u64 = cpu_to_le64 ( command->cb.lba.native );
00419         if ( ! command->cb.lba48 )
00420                 aoeata->lba.bytes[3] |=
00421                         ( command->cb.device & ATA_DEV_MASK );
00422         copy_from_user ( aoeata->data, command->data_out, 0,
00423                          command->data_out_len );
00424 
00425         DBGC2 ( aoedev, "AoE %s/%08x ATA cmd %02x:%02x:%02x:%02x:%08llx",
00426                 aoedev_name ( aoedev ), aoecmd->tag, aoeata->aflags,
00427                 aoeata->err_feat, aoeata->count, aoeata->cmd_stat,
00428                 aoeata->lba.u64 );
00429         if ( command->data_out_len )
00430                 DBGC2 ( aoedev, " out %04zx", command->data_out_len );
00431         if ( command->data_in_len )
00432                 DBGC2 ( aoedev, " in %04zx", command->data_in_len );
00433         DBGC2 ( aoedev, "\n" );
00434 }
00435 
00436 /**
00437  * Handle AoE ATA response IU
00438  *
00439  * @v aoecmd            AoE command
00440  * @v data              Response IU
00441  * @v len               Length of response IU
00442  * @v ll_source         Link-layer source address
00443  * @ret rc              Return status code
00444  */
00445 static int aoecmd_ata_rsp ( struct aoe_command *aoecmd, const void *data,
00446                             size_t len, const void *ll_source __unused ) {
00447         struct aoe_device *aoedev = aoecmd->aoedev;
00448         struct ata_cmd *command = &aoecmd->command;
00449         const struct aoehdr *aoehdr = data;
00450         const struct aoeata *aoeata = &aoehdr->payload[0].ata;
00451         size_t data_len;
00452 
00453         /* Sanity check */
00454         if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) ) {
00455                 DBGC ( aoedev, "AoE %s/%08x received underlength ATA response "
00456                        "(%zd bytes)\n", aoedev_name ( aoedev ),
00457                        aoecmd->tag, len );
00458                 return -EINVAL;
00459         }
00460         data_len = ( len - ( sizeof ( *aoehdr ) + sizeof ( *aoeata ) ) );
00461         DBGC2 ( aoedev, "AoE %s/%08x ATA rsp %02x in %04zx\n",
00462                 aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat,
00463                 data_len );
00464 
00465         /* Check for command failure */
00466         if ( aoeata->cmd_stat & ATA_STAT_ERR ) {
00467                 DBGC ( aoedev, "AoE %s/%08x status %02x\n",
00468                        aoedev_name ( aoedev ), aoecmd->tag, aoeata->cmd_stat );
00469                 return -EIO;
00470         }
00471 
00472         /* Check data-in length is sufficient.  (There may be trailing
00473          * garbage due to Ethernet minimum-frame-size padding.)
00474          */
00475         if ( data_len < command->data_in_len ) {
00476                 DBGC ( aoedev, "AoE %s/%08x data-in underrun (received %zd, "
00477                        "expected %zd)\n", aoedev_name ( aoedev ), aoecmd->tag,
00478                        data_len, command->data_in_len );
00479                 return -ERANGE;
00480         }
00481 
00482         /* Copy out data payload */
00483         copy_to_user ( command->data_in, 0, aoeata->data,
00484                        command->data_in_len );
00485 
00486         return 0;
00487 }
00488 
00489 /** AoE ATA command */
00490 static struct aoe_command_type aoecmd_ata = {
00491         .cmd_len = aoecmd_ata_cmd_len,
00492         .cmd = aoecmd_ata_cmd,
00493         .rsp = aoecmd_ata_rsp,
00494 };
00495 
00496 /**
00497  * Calculate length of AoE configuration command IU
00498  *
00499  * @v aoecmd            AoE command
00500  * @ret len             Length of command IU
00501  */
00502 static size_t aoecmd_cfg_cmd_len ( struct aoe_command *aoecmd __unused ) {
00503         return ( sizeof ( struct aoehdr ) + sizeof ( struct aoecfg ) );
00504 }
00505 
00506 /**
00507  * Build AoE configuration command IU
00508  *
00509  * @v aoecmd            AoE command
00510  * @v data              Command IU
00511  * @v len               Length of command IU
00512  */
00513 static void aoecmd_cfg_cmd ( struct aoe_command *aoecmd,
00514                              void *data, size_t len ) {
00515         struct aoe_device *aoedev = aoecmd->aoedev;
00516         struct aoehdr *aoehdr = data;
00517         struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
00518 
00519         /* Sanity check */
00520         assert ( len == ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) );
00521 
00522         /* Build IU */
00523         aoehdr->command = AOE_CMD_CONFIG;
00524         memset ( aoecfg, 0, sizeof ( *aoecfg ) );
00525 
00526         DBGC ( aoedev, "AoE %s/%08x CONFIG cmd\n",
00527                aoedev_name ( aoedev ), aoecmd->tag );
00528 }
00529 
00530 /**
00531  * Handle AoE configuration response IU
00532  *
00533  * @v aoecmd            AoE command
00534  * @v data              Response IU
00535  * @v len               Length of response IU
00536  * @v ll_source         Link-layer source address
00537  * @ret rc              Return status code
00538  */
00539 static int aoecmd_cfg_rsp ( struct aoe_command *aoecmd, const void *data,
00540                             size_t len, const void *ll_source ) {
00541         struct aoe_device *aoedev = aoecmd->aoedev;
00542         struct ll_protocol *ll_protocol = aoedev->netdev->ll_protocol;
00543         const struct aoehdr *aoehdr = data;
00544         const struct aoecfg *aoecfg = &aoehdr->payload[0].cfg;
00545 
00546         /* Sanity check */
00547         if ( len < ( sizeof ( *aoehdr ) + sizeof ( *aoecfg ) ) ) {
00548                 DBGC ( aoedev, "AoE %s/%08x received underlength "
00549                        "configuration response (%zd bytes)\n",
00550                        aoedev_name ( aoedev ), aoecmd->tag, len );
00551                 return -EINVAL;
00552         }
00553         DBGC ( aoedev, "AoE %s/%08x CONFIG rsp buf %04x fw %04x scnt %02x\n",
00554                aoedev_name ( aoedev ), aoecmd->tag, ntohs ( aoecfg->bufcnt ),
00555                aoecfg->fwver, aoecfg->scnt );
00556 
00557         /* Record target MAC address */
00558         memcpy ( aoedev->target, ll_source, ll_protocol->ll_addr_len );
00559         DBGC ( aoedev, "AoE %s has MAC address %s\n",
00560                aoedev_name ( aoedev ), ll_protocol->ntoa ( aoedev->target ) );
00561 
00562         return 0;
00563 }
00564 
00565 /** AoE configuration command */
00566 static struct aoe_command_type aoecmd_cfg = {
00567         .cmd_len = aoecmd_cfg_cmd_len,
00568         .cmd = aoecmd_cfg_cmd,
00569         .rsp = aoecmd_cfg_rsp,
00570 };
00571 
00572 /** AoE command ATA interface operations */
00573 static struct interface_operation aoecmd_ata_op[] = {
00574         INTF_OP ( intf_close, struct aoe_command *, aoecmd_close ),
00575 };
00576 
00577 /** AoE command ATA interface descriptor */
00578 static struct interface_descriptor aoecmd_ata_desc =
00579         INTF_DESC ( struct aoe_command, ata, aoecmd_ata_op );
00580 
00581 /**
00582  * Identify AoE command by tag
00583  *
00584  * @v tag               Command tag
00585  * @ret aoecmd          AoE command, or NULL
00586  */
00587 static struct aoe_command * aoecmd_find_tag ( uint32_t tag ) {
00588         struct aoe_command *aoecmd;
00589 
00590         list_for_each_entry ( aoecmd, &aoe_commands, list ) {
00591                 if ( aoecmd->tag == tag )
00592                         return aoecmd;
00593         }
00594         return NULL;
00595 }
00596 
00597 /**
00598  * Choose an AoE command tag
00599  *
00600  * @ret tag             New tag, or negative error
00601  */
00602 static int aoecmd_new_tag ( void ) {
00603         static uint16_t tag_idx;
00604         unsigned int i;
00605 
00606         for ( i = 0 ; i < 65536 ; i++ ) {
00607                 tag_idx++;
00608                 if ( aoecmd_find_tag ( tag_idx ) == NULL )
00609                         return ( AOE_TAG_MAGIC | tag_idx );
00610         }
00611         return -EADDRINUSE;
00612 }
00613 
00614 /**
00615  * Create AoE command
00616  *
00617  * @v aoedev            AoE device
00618  * @v type              AoE command type
00619  * @ret aoecmd          AoE command
00620  */
00621 static struct aoe_command * aoecmd_create ( struct aoe_device *aoedev,
00622                                             struct aoe_command_type *type ) {
00623         struct aoe_command *aoecmd;
00624         int tag;
00625 
00626         /* Allocate command tag */
00627         tag = aoecmd_new_tag();
00628         if ( tag < 0 )
00629                 return NULL;
00630 
00631         /* Allocate and initialise structure */
00632         aoecmd = zalloc ( sizeof ( *aoecmd ) );
00633         if ( ! aoecmd )
00634                 return NULL;
00635         ref_init ( &aoecmd->refcnt, aoecmd_free );
00636         list_add ( &aoecmd->list, &aoe_commands );
00637         intf_init ( &aoecmd->ata, &aoecmd_ata_desc, &aoecmd->refcnt );
00638         timer_init ( &aoecmd->timer, aoecmd_expired, &aoecmd->refcnt );
00639         aoecmd->aoedev = aoedev_get ( aoedev );
00640         aoecmd->type = type;
00641         aoecmd->tag = tag;
00642 
00643         /* Preserve timeout from last completed command */
00644         aoecmd->timer.timeout = aoedev->timeout;
00645 
00646         /* Return already mortalised.  (Reference is held by command list.) */
00647         return aoecmd;
00648 }
00649 
00650 /**
00651  * Issue AoE ATA command
00652  *
00653  * @v aoedev            AoE device
00654  * @v parent            Parent interface
00655  * @v command           ATA command
00656  * @ret tag             Command tag, or negative error
00657  */
00658 static int aoedev_ata_command ( struct aoe_device *aoedev,
00659                                 struct interface *parent,
00660                                 struct ata_cmd *command ) {
00661         struct net_device *netdev = aoedev->netdev;
00662         struct aoe_command *aoecmd;
00663 
00664         /* Fail immediately if net device is closed */
00665         if ( ! netdev_is_open ( netdev ) ) {
00666                 DBGC ( aoedev, "AoE %s cannot issue command while net device "
00667                        "is closed\n", aoedev_name ( aoedev ) );
00668                 return -EWOULDBLOCK;
00669         }
00670 
00671         /* Create command */
00672         aoecmd = aoecmd_create ( aoedev, &aoecmd_ata );
00673         if ( ! aoecmd )
00674                 return -ENOMEM;
00675         memcpy ( &aoecmd->command, command, sizeof ( aoecmd->command ) );
00676 
00677         /* Attempt to send command.  Allow failures to be handled by
00678          * the retry timer.
00679          */
00680         aoecmd_tx ( aoecmd );
00681 
00682         /* Attach to parent interface, leave reference with command
00683          * list, and return.
00684          */
00685         intf_plug_plug ( &aoecmd->ata, parent );
00686         return aoecmd->tag;
00687 }
00688 
00689 /**
00690  * Issue AoE configuration command
00691  *
00692  * @v aoedev            AoE device
00693  * @v parent            Parent interface
00694  * @ret tag             Command tag, or negative error
00695  */
00696 static int aoedev_cfg_command ( struct aoe_device *aoedev,
00697                                 struct interface *parent ) {
00698         struct aoe_command *aoecmd;
00699 
00700         /* Create command */
00701         aoecmd = aoecmd_create ( aoedev, &aoecmd_cfg );
00702         if ( ! aoecmd )
00703                 return -ENOMEM;
00704 
00705         /* Attempt to send command.  Allow failures to be handled by
00706          * the retry timer.
00707          */
00708         aoecmd_tx ( aoecmd );
00709 
00710         /* Attach to parent interface, leave reference with command
00711          * list, and return.
00712          */
00713         intf_plug_plug ( &aoecmd->ata, parent );
00714         return aoecmd->tag;
00715 }
00716 
00717 /**
00718  * Free AoE device
00719  *
00720  * @v refcnt            Reference count
00721  */
00722 static void aoedev_free ( struct refcnt *refcnt ) {
00723         struct aoe_device *aoedev =
00724                 container_of ( refcnt, struct aoe_device, refcnt );
00725 
00726         netdev_put ( aoedev->netdev );
00727         free ( aoedev );
00728 }
00729 
00730 /**
00731  * Close AoE device
00732  *
00733  * @v aoedev            AoE device
00734  * @v rc                Reason for close
00735  */
00736 static void aoedev_close ( struct aoe_device *aoedev, int rc ) {
00737         struct aoe_command *aoecmd;
00738         struct aoe_command *tmp;
00739 
00740         /* Shut down interfaces */
00741         intf_shutdown ( &aoedev->ata, rc );
00742         intf_shutdown ( &aoedev->config, rc );
00743 
00744         /* Shut down any active commands */
00745         list_for_each_entry_safe ( aoecmd, tmp, &aoe_commands, list ) {
00746                 if ( aoecmd->aoedev != aoedev )
00747                         continue;
00748                 aoecmd_get ( aoecmd );
00749                 aoecmd_close ( aoecmd, rc );
00750                 aoecmd_put ( aoecmd );
00751         }
00752 }
00753 
00754 /**
00755  * Check AoE device flow-control window
00756  *
00757  * @v aoedev            AoE device
00758  * @ret len             Length of window
00759  */
00760 static size_t aoedev_window ( struct aoe_device *aoedev ) {
00761         return ( aoedev->configured ? ~( ( size_t ) 0 ) : 0 );
00762 }
00763 
00764 /**
00765  * Handle AoE device configuration completion
00766  *
00767  * @v aoedev            AoE device
00768  * @v rc                Reason for completion
00769  */
00770 static void aoedev_config_done ( struct aoe_device *aoedev, int rc ) {
00771 
00772         /* Shut down interface */
00773         intf_shutdown ( &aoedev->config, rc );
00774 
00775         /* Close device on failure */
00776         if ( rc != 0 ) {
00777                 aoedev_close ( aoedev, rc );
00778                 return;
00779         }
00780 
00781         /* Mark device as configured */
00782         aoedev->configured = 1;
00783         xfer_window_changed ( &aoedev->ata );
00784 }
00785 
00786 /**
00787  * Identify device underlying AoE device
00788  *
00789  * @v aoedev            AoE device
00790  * @ret device          Underlying device
00791  */
00792 static struct device * aoedev_identify_device ( struct aoe_device *aoedev ) {
00793         return aoedev->netdev->dev;
00794 }
00795 
00796 /**
00797  * Get AoE ACPI descriptor
00798  *
00799  * @v aoedev            AoE device
00800  * @ret desc            ACPI descriptor
00801  */
00802 static struct acpi_descriptor * aoedev_describe ( struct aoe_device *aoedev ) {
00803         return &aoedev->desc;
00804 }
00805 
00806 /** AoE device ATA interface operations */
00807 static struct interface_operation aoedev_ata_op[] = {
00808         INTF_OP ( ata_command, struct aoe_device *, aoedev_ata_command ),
00809         INTF_OP ( xfer_window, struct aoe_device *, aoedev_window ),
00810         INTF_OP ( intf_close, struct aoe_device *, aoedev_close ),
00811         INTF_OP ( acpi_describe, struct aoe_device *, aoedev_describe ),
00812         INTF_OP ( identify_device, struct aoe_device *,
00813                   aoedev_identify_device ),
00814 };
00815 
00816 /** AoE device ATA interface descriptor */
00817 static struct interface_descriptor aoedev_ata_desc =
00818         INTF_DESC ( struct aoe_device, ata, aoedev_ata_op );
00819 
00820 /** AoE device configuration interface operations */
00821 static struct interface_operation aoedev_config_op[] = {
00822         INTF_OP ( intf_close, struct aoe_device *, aoedev_config_done ),
00823 };
00824 
00825 /** AoE device configuration interface descriptor */
00826 static struct interface_descriptor aoedev_config_desc =
00827         INTF_DESC ( struct aoe_device, config, aoedev_config_op );
00828 
00829 /**
00830  * Open AoE device
00831  *
00832  * @v parent            Parent interface
00833  * @v netdev            Network device
00834  * @v major             Device major number
00835  * @v minor             Device minor number
00836  * @ret rc              Return status code
00837  */
00838 static int aoedev_open ( struct interface *parent, struct net_device *netdev,
00839                          unsigned int major, unsigned int minor ) {
00840         struct aoe_device *aoedev;
00841         int rc;
00842 
00843         /* Allocate and initialise structure */
00844         aoedev = zalloc ( sizeof ( *aoedev ) );
00845         if ( ! aoedev ) {
00846                 rc = -ENOMEM;
00847                 goto err_zalloc;
00848         }
00849         ref_init ( &aoedev->refcnt, aoedev_free );
00850         intf_init ( &aoedev->ata, &aoedev_ata_desc, &aoedev->refcnt );
00851         intf_init ( &aoedev->config, &aoedev_config_desc, &aoedev->refcnt );
00852         aoedev->netdev = netdev_get ( netdev );
00853         aoedev->major = major;
00854         aoedev->minor = minor;
00855         memcpy ( aoedev->target, netdev->ll_broadcast,
00856                  netdev->ll_protocol->ll_addr_len );
00857         acpi_init ( &aoedev->desc, &abft_model, &aoedev->refcnt );
00858 
00859         /* Initiate configuration */
00860         if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) {
00861                 DBGC ( aoedev, "AoE %s could not initiate configuration: %s\n",
00862                        aoedev_name ( aoedev ), strerror ( rc ) );
00863                 goto err_config;
00864         }
00865 
00866         /* Attach ATA device to parent interface */
00867         if ( ( rc = ata_open ( parent, &aoedev->ata, ATA_DEV_MASTER,
00868                                AOE_MAX_COUNT ) ) != 0 ) {
00869                 DBGC ( aoedev, "AoE %s could not create ATA device: %s\n",
00870                        aoedev_name ( aoedev ), strerror ( rc ) );
00871                 goto err_ata_open;
00872         }
00873 
00874         /* Mortalise self and return */
00875         ref_put ( &aoedev->refcnt );
00876         return 0;
00877 
00878  err_ata_open:
00879  err_config:
00880         aoedev_close ( aoedev, rc );
00881         ref_put ( &aoedev->refcnt );
00882  err_zalloc:
00883         return rc;
00884 }
00885 
00886 /******************************************************************************
00887  *
00888  * AoE network protocol
00889  *
00890  ******************************************************************************
00891  */
00892 
00893 /**
00894  * Process incoming AoE packets
00895  *
00896  * @v iobuf             I/O buffer
00897  * @v netdev            Network device
00898  * @v ll_dest           Link-layer destination address
00899  * @v ll_source         Link-layer source address
00900  * @v flags             Packet flags
00901  * @ret rc              Return status code
00902  */
00903 static int aoe_rx ( struct io_buffer *iobuf,
00904                     struct net_device *netdev __unused,
00905                     const void *ll_dest __unused,
00906                     const void *ll_source,
00907                     unsigned int flags __unused ) {
00908         struct aoehdr *aoehdr = iobuf->data;
00909         struct aoe_command *aoecmd;
00910         int rc;
00911 
00912         /* Sanity check */
00913         if ( iob_len ( iobuf ) < sizeof ( *aoehdr ) ) {
00914                 DBG ( "AoE received underlength packet (%zd bytes)\n",
00915                       iob_len ( iobuf ) );
00916                 rc = -EINVAL;
00917                 goto err_sanity;
00918         }
00919         if ( ( aoehdr->ver_flags & AOE_VERSION_MASK ) != AOE_VERSION ) {
00920                 DBG ( "AoE received packet for unsupported protocol version "
00921                       "%02x\n", ( aoehdr->ver_flags & AOE_VERSION_MASK ) );
00922                 rc = -EPROTONOSUPPORT;
00923                 goto err_sanity;
00924         }
00925         if ( ! ( aoehdr->ver_flags & AOE_FL_RESPONSE ) ) {
00926                 DBG ( "AoE received request packet\n" );
00927                 rc = -EOPNOTSUPP;
00928                 goto err_sanity;
00929         }
00930 
00931         /* Demultiplex amongst active AoE commands */
00932         aoecmd = aoecmd_find_tag ( ntohl ( aoehdr->tag ) );
00933         if ( ! aoecmd ) {
00934                 DBG ( "AoE received packet for unused tag %08x\n",
00935                       ntohl ( aoehdr->tag ) );
00936                 rc = -ENOENT;
00937                 goto err_demux;
00938         }
00939 
00940         /* Pass received frame to command */
00941         aoecmd_get ( aoecmd );
00942         if ( ( rc = aoecmd_rx ( aoecmd, iob_disown ( iobuf ),
00943                                 ll_source ) ) != 0 )
00944                 goto err_rx;
00945 
00946  err_rx:
00947         aoecmd_put ( aoecmd );
00948  err_demux:
00949  err_sanity:
00950         free_iob ( iobuf );
00951         return rc;
00952 }
00953 
00954 /** AoE protocol */
00955 struct net_protocol aoe_protocol __net_protocol = {
00956         .name = "AoE",
00957         .net_proto = htons ( ETH_P_AOE ),
00958         .rx = aoe_rx,
00959 };
00960 
00961 /******************************************************************************
00962  *
00963  * AoE URIs
00964  *
00965  ******************************************************************************
00966  */
00967 
00968 /**
00969  * Parse AoE URI
00970  *
00971  * @v uri               URI
00972  * @ret major           Major device number
00973  * @ret minor           Minor device number
00974  * @ret rc              Return status code
00975  *
00976  * An AoE URI has the form "aoe:e<major>.<minor>".
00977  */
00978 static int aoe_parse_uri ( struct uri *uri, unsigned int *major,
00979                            unsigned int *minor ) {
00980         const char *ptr;
00981         char *end;
00982 
00983         /* Check for URI with opaque portion */
00984         if ( ! uri->opaque )
00985                 return -EINVAL;
00986         ptr = uri->opaque;
00987 
00988         /* Check for initial 'e' */
00989         if ( *ptr != 'e' )
00990                 return -EINVAL;
00991         ptr++;
00992 
00993         /* Parse major device number */
00994         *major = strtoul ( ptr, &end, 10 );
00995         if ( *end != '.' )
00996                 return -EINVAL;
00997         ptr = ( end + 1 );
00998 
00999         /* Parse minor device number */
01000         *minor = strtoul ( ptr, &end, 10 );
01001         if ( *end )
01002                 return -EINVAL;
01003 
01004         return 0;
01005 }
01006 
01007 /**
01008  * Open AoE URI
01009  *
01010  * @v parent            Parent interface
01011  * @v uri               URI
01012  * @ret rc              Return status code
01013  */
01014 static int aoe_open ( struct interface *parent, struct uri *uri ) {
01015         struct net_device *netdev;
01016         unsigned int major;
01017         unsigned int minor;
01018         int rc;
01019 
01020         /* Identify network device.  This is something of a hack, but
01021          * the AoE URI scheme that has been in use for some time now
01022          * provides no way to specify a particular device.
01023          */
01024         netdev = last_opened_netdev();
01025         if ( ! netdev ) {
01026                 DBG ( "AoE cannot identify network device\n" );
01027                 return -ENODEV;
01028         }
01029 
01030         /* Parse URI */
01031         if ( ( rc = aoe_parse_uri ( uri, &major, &minor ) ) != 0 ) {
01032                 DBG ( "AoE cannot parse URI\n" );
01033                 return rc;
01034         }
01035 
01036         /* Open AoE device */
01037         if ( ( rc = aoedev_open ( parent, netdev, major, minor ) ) != 0 )
01038                 return rc;
01039 
01040         return 0;
01041 }
01042 
01043 /** AoE URI opener */
01044 struct uri_opener aoe_uri_opener __uri_opener = {
01045         .scheme = "aoe",
01046         .open = aoe_open,
01047 };
01048 
01049 /******************************************************************************
01050  *
01051  * AoE boot firmware table (aBFT)
01052  *
01053  ******************************************************************************
01054  */
01055 
01056 /**
01057  * Check if AoE boot firmware table descriptor is complete
01058  *
01059  * @v desc              ACPI descriptor
01060  * @ret rc              Return status code
01061  */
01062 static int abft_complete ( struct acpi_descriptor *desc __unused ) {
01063         return 0;
01064 }
01065 
01066 /**
01067  * Install AoE boot firmware table(s)
01068  *
01069  * @v install           Installation method
01070  * @ret rc              Return status code
01071  */
01072 static int abft_install ( int ( * install ) ( struct acpi_header *acpi ) ) {
01073         struct aoe_device *aoedev;
01074         struct abft_table abft;
01075         int rc;
01076 
01077         list_for_each_entry ( aoedev, &abft_model.descs, desc.list ) {
01078 
01079                 /* Populate table */
01080                 memset ( &abft, 0, sizeof ( abft ) );
01081                 abft.acpi.signature = cpu_to_le32 ( ABFT_SIG );
01082                 abft.acpi.length = cpu_to_le32 ( sizeof ( abft ) );
01083                 abft.acpi.revision = 1;
01084                 abft.shelf = cpu_to_le16 ( aoedev->major );
01085                 abft.slot = aoedev->minor;
01086                 memcpy ( abft.mac, aoedev->netdev->ll_addr,
01087                          sizeof ( abft.mac ) );
01088 
01089                 /* Install table */
01090                 if ( ( rc = install ( &abft.acpi ) ) != 0 ) {
01091                         DBGC ( aoedev, "AoE %s could not install aBFT: %s\n",
01092                                aoedev_name ( aoedev ), strerror ( rc ) );
01093                         return rc;
01094                 }
01095         }
01096 
01097         return 0;
01098 }
01099 
01100 /** aBFT model */
01101 struct acpi_model abft_model __acpi_model = {
01102         .descs = LIST_HEAD_INIT ( abft_model.descs ),
01103         .complete = abft_complete,
01104         .install = abft_install,
01105 };