2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 FILE_LICENCE ( GPL2_OR_LATER
);
28 #include <gpxe/list.h>
29 #include <gpxe/if_ether.h>
30 #include <gpxe/ethernet.h>
31 #include <gpxe/iobuf.h>
32 #include <gpxe/uaccess.h>
34 #include <gpxe/netdevice.h>
35 #include <gpxe/process.h>
36 #include <gpxe/features.h>
45 FEATURE ( FEATURE_PROTOCOL
, "AoE", DHCP_EB_FEATURE_AOE
, 1 );
47 struct net_protocol aoe_protocol
;
49 /** List of all AoE sessions */
50 static LIST_HEAD ( aoe_sessions
);
52 static void aoe_free ( struct refcnt
*refcnt
) {
53 struct aoe_session
*aoe
=
54 container_of ( refcnt
, struct aoe_session
, refcnt
);
56 netdev_put ( aoe
->netdev
);
61 * Mark current AoE command complete
64 * @v rc Return status code
66 static void aoe_done ( struct aoe_session
*aoe
, int rc
) {
68 /* Record overall command status */
70 aoe
->command
->cb
.cmd_stat
= aoe
->status
;
71 aoe
->command
->rc
= rc
;
75 /* Stop retransmission timer */
76 stop_timer ( &aoe
->timer
);
78 /* Mark operation as complete */
86 * @ret rc Return status code
88 * This transmits an AoE command packet. It does not wait for a
91 static int aoe_send_command ( struct aoe_session
*aoe
) {
92 struct ata_command
*command
= aoe
->command
;
93 struct io_buffer
*iobuf
;
94 struct aoehdr
*aoehdr
;
96 struct aoeata
*aoeata
;
98 unsigned int data_out_len
;
99 unsigned int aoecmdlen
;
101 /* Fail immediately if we have no netdev to send on */
102 if ( ! aoe
->netdev
) {
103 aoe_done ( aoe
, -ENETUNREACH
);
107 /* If we are transmitting anything that requires a response,
108 * start the retransmission timer. Do this before attempting
109 * to allocate the I/O buffer, in case allocation itself
112 start_timer ( &aoe
->timer
);
114 /* Calculate count and data_out_len for this subcommand */
115 switch ( aoe
->aoe_cmd_type
) {
117 count
= command
->cb
.count
.native
;
118 if ( count
> AOE_MAX_COUNT
)
119 count
= AOE_MAX_COUNT
;
120 data_out_len
= ( command
->data_out
?
121 ( count
* ATA_SECTOR_SIZE
) : 0 );
122 aoecmdlen
= sizeof ( aoecmd
->ata
);
127 aoecmdlen
= sizeof ( aoecmd
->cfg
);
133 /* Create outgoing I/O buffer */
134 iobuf
= alloc_iob ( ETH_HLEN
+ sizeof ( *aoehdr
) +
135 aoecmdlen
+ data_out_len
);
139 iob_reserve ( iobuf
, ETH_HLEN
);
140 aoehdr
= iob_put ( iobuf
, sizeof ( *aoehdr
) );
141 aoecmd
= iob_put ( iobuf
, aoecmdlen
);
142 memset ( aoehdr
, 0, ( sizeof ( *aoehdr
) + aoecmdlen
) );
144 /* Fill AoE header */
145 aoehdr
->ver_flags
= AOE_VERSION
;
146 aoehdr
->major
= htons ( aoe
->major
);
147 aoehdr
->minor
= aoe
->minor
;
148 aoehdr
->command
= aoe
->aoe_cmd_type
;
149 aoehdr
->tag
= htonl ( ++aoe
->tag
);
151 /* Fill AoE payload */
152 switch ( aoe
->aoe_cmd_type
) {
154 /* Fill AoE command */
155 aoeata
= &aoecmd
->ata
;
156 linker_assert ( AOE_FL_DEV_HEAD
== ATA_DEV_SLAVE
,
158 aoeata
->aflags
= ( ( command
->cb
.lba48
? AOE_FL_EXTENDED
: 0 )|
159 ( command
->cb
.device
& ATA_DEV_SLAVE
) |
160 ( data_out_len
? AOE_FL_WRITE
: 0 ) );
161 aoeata
->err_feat
= command
->cb
.err_feat
.bytes
.cur
;
162 aoeata
->count
= count
;
163 aoeata
->cmd_stat
= command
->cb
.cmd_stat
;
164 aoeata
->lba
.u64
= cpu_to_le64 ( command
->cb
.lba
.native
);
165 if ( ! command
->cb
.lba48
)
166 aoeata
->lba
.bytes
[3] |=
167 ( command
->cb
.device
& ATA_DEV_MASK
);
169 /* Fill data payload */
170 copy_from_user ( iob_put ( iobuf
, data_out_len
),
171 command
->data_out
, aoe
->command_offset
,
182 return net_tx ( iobuf
, aoe
->netdev
, &aoe_protocol
, aoe
->target
);
186 * Handle AoE retry timer expiry
188 * @v timer AoE retry timer
189 * @v fail Failure indicator
191 static void aoe_timer_expired ( struct retry_timer
*timer
, int fail
) {
192 struct aoe_session
*aoe
=
193 container_of ( timer
, struct aoe_session
, timer
);
196 aoe_done ( aoe
, -ETIMEDOUT
);
198 aoe_send_command ( aoe
);
203 * Handle AoE configuration command response
206 * @v ll_source Link-layer source address
207 * @ret rc Return status code
209 static int aoe_rx_cfg ( struct aoe_session
*aoe
, const void *ll_source
) {
211 /* Record target MAC address */
212 memcpy ( aoe
->target
, ll_source
, sizeof ( aoe
->target
) );
213 DBGC ( aoe
, "AoE %p target MAC address %s\n",
214 aoe
, eth_ntoa ( aoe
->target
) );
216 /* Mark config request as complete */
223 * Handle AoE ATA command response
226 * @v aoeata AoE ATA command
227 * @v len Length of AoE ATA command
228 * @ret rc Return status code
230 static int aoe_rx_ata ( struct aoe_session
*aoe
, struct aoeata
*aoeata
,
232 struct ata_command
*command
= aoe
->command
;
233 unsigned int rx_data_len
;
235 unsigned int data_len
;
238 if ( len
< sizeof ( *aoeata
) ) {
239 /* Ignore packet; allow timer to trigger retransmit */
242 rx_data_len
= ( len
- sizeof ( *aoeata
) );
244 /* Calculate count and data_len for this subcommand */
245 count
= command
->cb
.count
.native
;
246 if ( count
> AOE_MAX_COUNT
)
247 count
= AOE_MAX_COUNT
;
248 data_len
= count
* ATA_SECTOR_SIZE
;
250 /* Merge into overall ATA status */
251 aoe
->status
|= aoeata
->cmd_stat
;
253 /* Copy data payload */
254 if ( command
->data_in
) {
255 if ( rx_data_len
> data_len
)
256 rx_data_len
= data_len
;
257 copy_to_user ( command
->data_in
, aoe
->command_offset
,
258 aoeata
->data
, rx_data_len
);
261 /* Update ATA command and offset */
262 aoe
->command_offset
+= data_len
;
263 command
->cb
.lba
.native
+= count
;
264 command
->cb
.count
.native
-= count
;
266 /* Check for operation complete */
267 if ( ! command
->cb
.count
.native
) {
272 /* Transmit next portion of request */
273 stop_timer ( &aoe
->timer
);
274 aoe_send_command ( aoe
);
280 * Process incoming AoE packets
282 * @v iobuf I/O buffer
283 * @v netdev Network device
284 * @v ll_source Link-layer source address
285 * @ret rc Return status code
288 static int aoe_rx ( struct io_buffer
*iobuf
,
289 struct net_device
*netdev __unused
,
290 const void *ll_source
) {
291 struct aoehdr
*aoehdr
= iobuf
->data
;
292 struct aoe_session
*aoe
;
296 if ( iob_len ( iobuf
) < sizeof ( *aoehdr
) ) {
300 if ( ( aoehdr
->ver_flags
& AOE_VERSION_MASK
) != AOE_VERSION
) {
301 rc
= -EPROTONOSUPPORT
;
304 if ( ! ( aoehdr
->ver_flags
& AOE_FL_RESPONSE
) ) {
305 /* Ignore AoE requests that we happen to see */
308 iob_pull ( iobuf
, sizeof ( *aoehdr
) );
310 /* Demultiplex amongst active AoE sessions */
311 list_for_each_entry ( aoe
, &aoe_sessions
, list
) {
312 if ( ntohs ( aoehdr
->major
) != aoe
->major
)
314 if ( aoehdr
->minor
!= aoe
->minor
)
316 if ( ntohl ( aoehdr
->tag
) != aoe
->tag
)
318 if ( aoehdr
->ver_flags
& AOE_FL_ERROR
) {
319 aoe_done ( aoe
, -EIO
);
322 switch ( aoehdr
->command
) {
324 rc
= aoe_rx_ata ( aoe
, iobuf
->data
, iob_len ( iobuf
));
327 rc
= aoe_rx_cfg ( aoe
, ll_source
);
330 DBGC ( aoe
, "AoE %p ignoring command %02x\n",
331 aoe
, aoehdr
->command
);
343 struct net_protocol aoe_protocol __net_protocol
= {
345 .net_proto
= htons ( ETH_P_AOE
),
350 * Issue ATA command via an open AoE session
353 * @v command ATA command
354 * @ret rc Return status code
356 static int aoe_command ( struct ata_device
*ata
,
357 struct ata_command
*command
) {
358 struct aoe_session
*aoe
=
359 container_of ( ata
->backend
, struct aoe_session
, refcnt
);
361 aoe
->command
= command
;
363 aoe
->command_offset
= 0;
364 aoe
->aoe_cmd_type
= AOE_CMD_ATA
;
366 aoe_send_command ( aoe
);
372 * Issue AoE config query for AoE target discovery
375 * @ret rc Return status code
377 static int aoe_discover ( struct aoe_session
*aoe
) {
381 aoe
->aoe_cmd_type
= AOE_CMD_CONFIG
;
384 aoe_send_command ( aoe
);
386 aoe
->rc
= -EINPROGRESS
;
387 while ( aoe
->rc
== -EINPROGRESS
)
394 static int aoe_detached_command ( struct ata_device
*ata __unused
,
395 struct ata_command
*command __unused
) {
399 void aoe_detach ( struct ata_device
*ata
) {
400 struct aoe_session
*aoe
=
401 container_of ( ata
->backend
, struct aoe_session
, refcnt
);
403 stop_timer ( &aoe
->timer
);
404 ata
->command
= aoe_detached_command
;
405 list_del ( &aoe
->list
);
406 ref_put ( ata
->backend
);
410 static int aoe_parse_root_path ( struct aoe_session
*aoe
,
411 const char *root_path
) {
414 if ( strncmp ( root_path
, "aoe:", 4 ) != 0 )
416 ptr
= ( ( char * ) root_path
+ 4 );
421 aoe
->major
= strtoul ( ptr
, &ptr
, 10 );
425 aoe
->minor
= strtoul ( ptr
, &ptr
, 10 );
432 int aoe_attach ( struct ata_device
*ata
, struct net_device
*netdev
,
433 const char *root_path
) {
434 struct aoe_session
*aoe
;
437 /* Allocate and initialise structure */
438 aoe
= zalloc ( sizeof ( *aoe
) );
441 aoe
->refcnt
.free
= aoe_free
;
442 aoe
->netdev
= netdev_get ( netdev
);
443 memcpy ( aoe
->target
, netdev
->ll_broadcast
, sizeof ( aoe
->target
) );
444 aoe
->tag
= AOE_TAG_MAGIC
;
445 aoe
->timer
.expired
= aoe_timer_expired
;
447 /* Parse root path */
448 if ( ( rc
= aoe_parse_root_path ( aoe
, root_path
) ) != 0 )
451 /* Attach parent interface, transfer reference to connection
454 ata
->backend
= ref_get ( &aoe
->refcnt
);
455 ata
->command
= aoe_command
;
456 list_add ( &aoe
->list
, &aoe_sessions
);
458 /* Send discovery packet to find the target MAC address.
459 * Ideally, this ought to be done asynchronously, but the
460 * block device interface does not yet support asynchronous
463 if ( ( rc
= aoe_discover( aoe
) ) != 0 )
469 ref_put ( &aoe
->refcnt
);