[smsc95xx] Fetch MAC from device tree for Raspberry Pi
[ipxe.git] / src / drivers / net / smsc95xx.c
1 /*
2 * Copyright (C) 2015 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 (at your option) 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 <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <byteswap.h>
30 #include <ipxe/ethernet.h>
31 #include <ipxe/usb.h>
32 #include <ipxe/usbnet.h>
33 #include <ipxe/profile.h>
34 #include <ipxe/base16.h>
35 #include <ipxe/smbios.h>
36 #include <ipxe/fdt.h>
37 #include "smsc95xx.h"
38
39 /** @file
40 *
41 * SMSC LAN95xx USB Ethernet driver
42 *
43 */
44
45 /** Bulk IN completion profiler */
46 static struct profiler smsc95xx_in_profiler __profiler =
47 { .name = "smsc95xx.in" };
48
49 /** Bulk OUT profiler */
50 static struct profiler smsc95xx_out_profiler __profiler =
51 { .name = "smsc95xx.out" };
52
53 /******************************************************************************
54 *
55 * MAC address
56 *
57 ******************************************************************************
58 */
59
60 /**
61 * Construct MAC address for Honeywell VM3
62 *
63 * @v smscusb SMSC USB device
64 * @ret rc Return status code
65 */
66 static int smsc95xx_vm3_fetch_mac ( struct smscusb_device *smscusb ) {
67 struct net_device *netdev = smscusb->netdev;
68 struct smbios_structure structure;
69 struct smbios_system_information system;
70 struct {
71 char manufacturer[ 10 /* "Honeywell" + NUL */ ];
72 char product[ 4 /* "VM3" + NUL */ ];
73 char mac[ base16_encoded_len ( ETH_ALEN ) + 1 /* NUL */ ];
74 } strings;
75 int len;
76 int rc;
77
78 /* Find system information */
79 if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_SYSTEM_INFORMATION, 0,
80 &structure ) ) != 0 ) {
81 DBGC ( smscusb, "SMSC95XX %p could not find system "
82 "information: %s\n", smscusb, strerror ( rc ) );
83 return rc;
84 }
85
86 /* Read system information */
87 if ( ( rc = read_smbios_structure ( &structure, &system,
88 sizeof ( system ) ) ) != 0 ) {
89 DBGC ( smscusb, "SMSC95XX %p could not read system "
90 "information: %s\n", smscusb, strerror ( rc ) );
91 return rc;
92 }
93
94 /* NUL-terminate all strings to be fetched */
95 memset ( &strings, 0, sizeof ( strings ) );
96
97 /* Fetch system manufacturer name */
98 len = read_smbios_string ( &structure, system.manufacturer,
99 strings.manufacturer,
100 ( sizeof ( strings.manufacturer ) - 1 ) );
101 if ( len < 0 ) {
102 rc = len;
103 DBGC ( smscusb, "SMSC95XX %p could not read manufacturer "
104 "name: %s\n", smscusb, strerror ( rc ) );
105 return rc;
106 }
107
108 /* Fetch system product name */
109 len = read_smbios_string ( &structure, system.product, strings.product,
110 ( sizeof ( strings.product ) - 1 ) );
111 if ( len < 0 ) {
112 rc = len;
113 DBGC ( smscusb, "SMSC95XX %p could not read product name: "
114 "%s\n", smscusb, strerror ( rc ) );
115 return rc;
116 }
117
118 /* Ignore non-VM3 devices */
119 if ( ( strcmp ( strings.manufacturer, "Honeywell" ) != 0 ) ||
120 ( strcmp ( strings.product, "VM3" ) != 0 ) )
121 return -ENOTTY;
122
123 /* Find OEM strings */
124 if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_OEM_STRINGS, 0,
125 &structure ) ) != 0 ) {
126 DBGC ( smscusb, "SMSC95XX %p could not find OEM strings: %s\n",
127 smscusb, strerror ( rc ) );
128 return rc;
129 }
130
131 /* Fetch MAC address */
132 len = read_smbios_string ( &structure, SMSC95XX_VM3_OEM_STRING_MAC,
133 strings.mac, ( sizeof ( strings.mac ) - 1 ));
134 if ( len < 0 ) {
135 rc = len;
136 DBGC ( smscusb, "SMSC95XX %p could not read OEM string: %s\n",
137 smscusb, strerror ( rc ) );
138 return rc;
139 }
140
141 /* Sanity check */
142 if ( len != ( ( int ) ( sizeof ( strings.mac ) - 1 ) ) ) {
143 DBGC ( smscusb, "SMSC95XX %p invalid MAC address \"%s\"\n",
144 smscusb, strings.mac );
145 return -EINVAL;
146 }
147
148 /* Decode MAC address */
149 len = base16_decode ( strings.mac, netdev->hw_addr, ETH_ALEN );
150 if ( len < 0 ) {
151 rc = len;
152 DBGC ( smscusb, "SMSC95XX %p invalid MAC address \"%s\"\n",
153 smscusb, strings.mac );
154 return rc;
155 }
156
157 DBGC ( smscusb, "SMSC95XX %p using VM3 MAC %s\n",
158 smscusb, eth_ntoa ( netdev->hw_addr ) );
159 return 0;
160 }
161
162 /**
163 * Fetch MAC address from device tree
164 *
165 * @v smscusb SMSC USB device
166 * @ret rc Return status code
167 */
168 static int smsc95xx_fdt_fetch_mac ( struct smscusb_device *smscusb ) {
169 struct net_device *netdev = smscusb->netdev;
170 unsigned int offset;
171 int rc;
172
173 /* Look for "ethernet[0]" alias */
174 if ( ( rc = fdt_alias ( "ethernet", &offset ) != 0 ) &&
175 ( rc = fdt_alias ( "ethernet0", &offset ) != 0 ) ) {
176 return rc;
177 }
178
179 /* Fetch MAC address */
180 if ( ( rc = fdt_mac ( offset, netdev ) ) != 0 )
181 return rc;
182
183 DBGC ( smscusb, "SMSC95XX %p using FDT MAC %s\n",
184 smscusb, eth_ntoa ( netdev->hw_addr ) );
185 return 0;
186 }
187
188 /**
189 * Fetch MAC address
190 *
191 * @v smscusb SMSC USB device
192 * @ret rc Return status code
193 */
194 static int smsc95xx_fetch_mac ( struct smscusb_device *smscusb ) {
195 struct net_device *netdev = smscusb->netdev;
196 int rc;
197
198 /* Read MAC address from EEPROM, if present */
199 if ( ( rc = smscusb_eeprom_fetch_mac ( smscusb,
200 SMSC95XX_E2P_BASE ) ) == 0 )
201 return 0;
202
203 /* Read MAC address from device tree */
204 if ( ( rc = smsc95xx_fdt_fetch_mac ( smscusb ) ) == 0 )
205 return 0;
206
207 /* Construct MAC address for Honeywell VM3, if applicable */
208 if ( ( rc = smsc95xx_vm3_fetch_mac ( smscusb ) ) == 0 )
209 return 0;
210
211 /* Otherwise, generate a random MAC address */
212 eth_random_addr ( netdev->hw_addr );
213 DBGC ( smscusb, "SMSC95XX %p using random MAC %s\n",
214 smscusb, eth_ntoa ( netdev->hw_addr ) );
215 return 0;
216 }
217
218 /******************************************************************************
219 *
220 * Statistics (for debugging)
221 *
222 ******************************************************************************
223 */
224
225 /**
226 * Dump statistics (for debugging)
227 *
228 * @v smscusb SMSC USB device
229 * @ret rc Return status code
230 */
231 static int smsc95xx_dump_statistics ( struct smscusb_device *smscusb ) {
232 struct smsc95xx_rx_statistics rx;
233 struct smsc95xx_tx_statistics tx;
234 int rc;
235
236 /* Do nothing unless debugging is enabled */
237 if ( ! DBG_LOG )
238 return 0;
239
240 /* Get RX statistics */
241 if ( ( rc = smscusb_get_statistics ( smscusb, SMSC95XX_RX_STATISTICS,
242 &rx, sizeof ( rx ) ) ) != 0 ) {
243 DBGC ( smscusb, "SMSC95XX %p could not get RX statistics: "
244 "%s\n", smscusb, strerror ( rc ) );
245 return rc;
246 }
247
248 /* Get TX statistics */
249 if ( ( rc = smscusb_get_statistics ( smscusb, SMSC95XX_TX_STATISTICS,
250 &tx, sizeof ( tx ) ) ) != 0 ) {
251 DBGC ( smscusb, "SMSC95XX %p could not get TX statistics: "
252 "%s\n", smscusb, strerror ( rc ) );
253 return rc;
254 }
255
256 /* Dump statistics */
257 DBGC ( smscusb, "SMSC95XX %p RX good %d bad %d crc %d und %d aln %d "
258 "ovr %d lat %d drp %d\n", smscusb, le32_to_cpu ( rx.good ),
259 le32_to_cpu ( rx.bad ), le32_to_cpu ( rx.crc ),
260 le32_to_cpu ( rx.undersize ), le32_to_cpu ( rx.alignment ),
261 le32_to_cpu ( rx.oversize ), le32_to_cpu ( rx.late ),
262 le32_to_cpu ( rx.dropped ) );
263 DBGC ( smscusb, "SMSC95XX %p TX good %d bad %d pau %d sgl %d mul %d "
264 "exc %d lat %d und %d def %d car %d\n", smscusb,
265 le32_to_cpu ( tx.good ), le32_to_cpu ( tx.bad ),
266 le32_to_cpu ( tx.pause ), le32_to_cpu ( tx.single ),
267 le32_to_cpu ( tx.multiple ), le32_to_cpu ( tx.excessive ),
268 le32_to_cpu ( tx.late ), le32_to_cpu ( tx.underrun ),
269 le32_to_cpu ( tx.deferred ), le32_to_cpu ( tx.carrier ) );
270
271 return 0;
272 }
273
274 /******************************************************************************
275 *
276 * Device reset
277 *
278 ******************************************************************************
279 */
280
281 /**
282 * Reset device
283 *
284 * @v smscusb SMSC USB device
285 * @ret rc Return status code
286 */
287 static int smsc95xx_reset ( struct smscusb_device *smscusb ) {
288 uint32_t hw_cfg;
289 uint32_t led_gpio_cfg;
290 int rc;
291
292 /* Reset device */
293 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_HW_CFG,
294 SMSC95XX_HW_CFG_LRST ) ) != 0 )
295 return rc;
296
297 /* Wait for reset to complete */
298 udelay ( SMSC95XX_RESET_DELAY_US );
299
300 /* Check that reset has completed */
301 if ( ( rc = smscusb_readl ( smscusb, SMSC95XX_HW_CFG, &hw_cfg ) ) != 0 )
302 return rc;
303 if ( hw_cfg & SMSC95XX_HW_CFG_LRST ) {
304 DBGC ( smscusb, "SMSC95XX %p failed to reset\n", smscusb );
305 return -ETIMEDOUT;
306 }
307
308 /* Configure LEDs */
309 led_gpio_cfg = ( SMSC95XX_LED_GPIO_CFG_GPCTL2_NSPD_LED |
310 SMSC95XX_LED_GPIO_CFG_GPCTL1_NLNKA_LED |
311 SMSC95XX_LED_GPIO_CFG_GPCTL0_NFDX_LED );
312 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_LED_GPIO_CFG,
313 led_gpio_cfg ) ) != 0 ) {
314 DBGC ( smscusb, "SMSC95XX %p could not configure LEDs: %s\n",
315 smscusb, strerror ( rc ) );
316 /* Ignore error and continue */
317 }
318
319 return 0;
320 }
321
322 /******************************************************************************
323 *
324 * Endpoint operations
325 *
326 ******************************************************************************
327 */
328
329 /**
330 * Complete bulk IN transfer
331 *
332 * @v ep USB endpoint
333 * @v iobuf I/O buffer
334 * @v rc Completion status code
335 */
336 static void smsc95xx_in_complete ( struct usb_endpoint *ep,
337 struct io_buffer *iobuf, int rc ) {
338 struct smscusb_device *smscusb =
339 container_of ( ep, struct smscusb_device, usbnet.in );
340 struct net_device *netdev = smscusb->netdev;
341 struct smsc95xx_rx_header *header;
342
343 /* Profile completions */
344 profile_start ( &smsc95xx_in_profiler );
345
346 /* Ignore packets cancelled when the endpoint closes */
347 if ( ! ep->open ) {
348 free_iob ( iobuf );
349 return;
350 }
351
352 /* Record USB errors against the network device */
353 if ( rc != 0 ) {
354 DBGC ( smscusb, "SMSC95XX %p bulk IN failed: %s\n",
355 smscusb, strerror ( rc ) );
356 goto err;
357 }
358
359 /* Sanity check */
360 if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
361 DBGC ( smscusb, "SMSC95XX %p underlength bulk IN\n",
362 smscusb );
363 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
364 rc = -EINVAL;
365 goto err;
366 }
367
368 /* Strip header and CRC */
369 header = iobuf->data;
370 iob_pull ( iobuf, sizeof ( *header ) );
371 iob_unput ( iobuf, 4 /* CRC */ );
372
373 /* Check for errors */
374 if ( header->command & cpu_to_le32 ( SMSC95XX_RX_RUNT |
375 SMSC95XX_RX_LATE |
376 SMSC95XX_RX_CRC ) ) {
377 DBGC ( smscusb, "SMSC95XX %p receive error (%08x):\n",
378 smscusb, le32_to_cpu ( header->command ) );
379 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
380 rc = -EIO;
381 goto err;
382 }
383
384 /* Hand off to network stack */
385 netdev_rx ( netdev, iob_disown ( iobuf ) );
386
387 profile_stop ( &smsc95xx_in_profiler );
388 return;
389
390 err:
391 /* Hand off to network stack */
392 netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
393 }
394
395 /** Bulk IN endpoint operations */
396 static struct usb_endpoint_driver_operations smsc95xx_in_operations = {
397 .complete = smsc95xx_in_complete,
398 };
399
400 /**
401 * Transmit packet
402 *
403 * @v smscusb SMSC USB device
404 * @v iobuf I/O buffer
405 * @ret rc Return status code
406 */
407 static int smsc95xx_out_transmit ( struct smscusb_device *smscusb,
408 struct io_buffer *iobuf ) {
409 struct smsc95xx_tx_header *header;
410 size_t len = iob_len ( iobuf );
411 int rc;
412
413 /* Profile transmissions */
414 profile_start ( &smsc95xx_out_profiler );
415
416 /* Prepend header */
417 if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *header ) ) ) != 0 )
418 return rc;
419 header = iob_push ( iobuf, sizeof ( *header ) );
420 header->command = cpu_to_le32 ( SMSC95XX_TX_FIRST | SMSC95XX_TX_LAST |
421 SMSC95XX_TX_LEN ( len ) );
422 header->len = cpu_to_le32 ( len );
423
424 /* Enqueue I/O buffer */
425 if ( ( rc = usb_stream ( &smscusb->usbnet.out, iobuf, 0 ) ) != 0 )
426 return rc;
427
428 profile_stop ( &smsc95xx_out_profiler );
429 return 0;
430 }
431
432 /******************************************************************************
433 *
434 * Network device interface
435 *
436 ******************************************************************************
437 */
438
439 /**
440 * Open network device
441 *
442 * @v netdev Network device
443 * @ret rc Return status code
444 */
445 static int smsc95xx_open ( struct net_device *netdev ) {
446 struct smscusb_device *smscusb = netdev->priv;
447 int rc;
448
449 /* Clear stored interrupt status */
450 smscusb->int_sts = 0;
451
452 /* Configure bulk IN empty response */
453 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_HW_CFG,
454 SMSC95XX_HW_CFG_BIR ) ) != 0 )
455 goto err_hw_cfg;
456
457 /* Open USB network device */
458 if ( ( rc = usbnet_open ( &smscusb->usbnet ) ) != 0 ) {
459 DBGC ( smscusb, "SMSC95XX %p could not open: %s\n",
460 smscusb, strerror ( rc ) );
461 goto err_open;
462 }
463
464 /* Configure interrupt endpoint */
465 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_INT_EP_CTL,
466 ( SMSC95XX_INT_EP_CTL_RXDF_EN |
467 SMSC95XX_INT_EP_CTL_PHY_EN ) ) ) != 0 )
468 goto err_int_ep_ctl;
469
470 /* Configure bulk IN delay */
471 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_BULK_IN_DLY,
472 SMSC95XX_BULK_IN_DLY_SET ( 0 ) ) ) != 0 )
473 goto err_bulk_in_dly;
474
475 /* Configure MAC */
476 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_MAC_CR,
477 ( SMSC95XX_MAC_CR_RXALL |
478 SMSC95XX_MAC_CR_FDPX |
479 SMSC95XX_MAC_CR_MCPAS |
480 SMSC95XX_MAC_CR_PRMS |
481 SMSC95XX_MAC_CR_PASSBAD |
482 SMSC95XX_MAC_CR_TXEN |
483 SMSC95XX_MAC_CR_RXEN ) ) ) != 0 )
484 goto err_mac_cr;
485
486 /* Configure transmit datapath */
487 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_TX_CFG,
488 SMSC95XX_TX_CFG_ON ) ) != 0 )
489 goto err_tx_cfg;
490
491 /* Set MAC address */
492 if ( ( rc = smscusb_set_address ( smscusb, SMSC95XX_ADDR_BASE ) ) != 0 )
493 goto err_set_address;
494
495 /* Enable PHY interrupts and update link status */
496 if ( ( rc = smscusb_mii_open ( smscusb, SMSC95XX_MII_PHY_INTR_MASK,
497 ( SMSC95XX_PHY_INTR_ANEG_DONE |
498 SMSC95XX_PHY_INTR_LINK_DOWN ) ) ) != 0)
499 goto err_mii_open;
500
501 return 0;
502
503 err_mii_open:
504 err_set_address:
505 err_tx_cfg:
506 err_mac_cr:
507 err_bulk_in_dly:
508 err_int_ep_ctl:
509 usbnet_close ( &smscusb->usbnet );
510 err_open:
511 err_hw_cfg:
512 smsc95xx_reset ( smscusb );
513 return rc;
514 }
515
516 /**
517 * Close network device
518 *
519 * @v netdev Network device
520 */
521 static void smsc95xx_close ( struct net_device *netdev ) {
522 struct smscusb_device *smscusb = netdev->priv;
523
524 /* Close USB network device */
525 usbnet_close ( &smscusb->usbnet );
526
527 /* Dump statistics (for debugging) */
528 smsc95xx_dump_statistics ( smscusb );
529
530 /* Reset device */
531 smsc95xx_reset ( smscusb );
532 }
533
534 /**
535 * Transmit packet
536 *
537 * @v netdev Network device
538 * @v iobuf I/O buffer
539 * @ret rc Return status code
540 */
541 static int smsc95xx_transmit ( struct net_device *netdev,
542 struct io_buffer *iobuf ) {
543 struct smscusb_device *smscusb = netdev->priv;
544 int rc;
545
546 /* Transmit packet */
547 if ( ( rc = smsc95xx_out_transmit ( smscusb, iobuf ) ) != 0 )
548 return rc;
549
550 return 0;
551 }
552
553 /**
554 * Poll for completed and received packets
555 *
556 * @v netdev Network device
557 */
558 static void smsc95xx_poll ( struct net_device *netdev ) {
559 struct smscusb_device *smscusb = netdev->priv;
560 uint32_t int_sts;
561 int rc;
562
563 /* Poll USB bus */
564 usb_poll ( smscusb->bus );
565
566 /* Refill endpoints */
567 if ( ( rc = usbnet_refill ( &smscusb->usbnet ) ) != 0 )
568 netdev_rx_err ( netdev, NULL, rc );
569
570 /* Do nothing more unless there are interrupts to handle */
571 int_sts = smscusb->int_sts;
572 if ( ! int_sts )
573 return;
574
575 /* Check link status if applicable */
576 if ( int_sts & SMSC95XX_INT_STS_PHY_INT ) {
577 smscusb_mii_check_link ( smscusb );
578 int_sts &= ~SMSC95XX_INT_STS_PHY_INT;
579 }
580
581 /* Record RX FIFO overflow if applicable */
582 if ( int_sts & SMSC95XX_INT_STS_RXDF_INT ) {
583 DBGC2 ( smscusb, "SMSC95XX %p RX FIFO overflowed\n",
584 smscusb );
585 netdev_rx_err ( netdev, NULL, -ENOBUFS );
586 int_sts &= ~SMSC95XX_INT_STS_RXDF_INT;
587 }
588
589 /* Check for unexpected interrupts */
590 if ( int_sts ) {
591 DBGC ( smscusb, "SMSC95XX %p unexpected interrupt %#08x\n",
592 smscusb, int_sts );
593 netdev_rx_err ( netdev, NULL, -ENOTTY );
594 }
595
596 /* Clear interrupts */
597 if ( ( rc = smscusb_writel ( smscusb, SMSC95XX_INT_STS,
598 smscusb->int_sts ) ) != 0 )
599 netdev_rx_err ( netdev, NULL, rc );
600 smscusb->int_sts = 0;
601 }
602
603 /** SMSC95xx network device operations */
604 static struct net_device_operations smsc95xx_operations = {
605 .open = smsc95xx_open,
606 .close = smsc95xx_close,
607 .transmit = smsc95xx_transmit,
608 .poll = smsc95xx_poll,
609 };
610
611 /******************************************************************************
612 *
613 * USB interface
614 *
615 ******************************************************************************
616 */
617
618 /**
619 * Probe device
620 *
621 * @v func USB function
622 * @v config Configuration descriptor
623 * @ret rc Return status code
624 */
625 static int smsc95xx_probe ( struct usb_function *func,
626 struct usb_configuration_descriptor *config ) {
627 struct net_device *netdev;
628 struct smscusb_device *smscusb;
629 int rc;
630
631 /* Allocate and initialise structure */
632 netdev = alloc_etherdev ( sizeof ( *smscusb ) );
633 if ( ! netdev ) {
634 rc = -ENOMEM;
635 goto err_alloc;
636 }
637 netdev_init ( netdev, &smsc95xx_operations );
638 netdev->dev = &func->dev;
639 smscusb = netdev->priv;
640 memset ( smscusb, 0, sizeof ( *smscusb ) );
641 smscusb_init ( smscusb, netdev, func, &smsc95xx_in_operations );
642 smscusb_mii_init ( smscusb, SMSC95XX_MII_BASE,
643 SMSC95XX_MII_PHY_INTR_SOURCE );
644 usb_refill_init ( &smscusb->usbnet.in,
645 ( sizeof ( struct smsc95xx_tx_header ) -
646 sizeof ( struct smsc95xx_rx_header ) ),
647 SMSC95XX_IN_MTU, SMSC95XX_IN_MAX_FILL );
648 DBGC ( smscusb, "SMSC95XX %p on %s\n", smscusb, func->name );
649
650 /* Describe USB network device */
651 if ( ( rc = usbnet_describe ( &smscusb->usbnet, config ) ) != 0 ) {
652 DBGC ( smscusb, "SMSC95XX %p could not describe: %s\n",
653 smscusb, strerror ( rc ) );
654 goto err_describe;
655 }
656
657 /* Reset device */
658 if ( ( rc = smsc95xx_reset ( smscusb ) ) != 0 )
659 goto err_reset;
660
661 /* Read MAC address */
662 if ( ( rc = smsc95xx_fetch_mac ( smscusb ) ) != 0 )
663 goto err_fetch_mac;
664
665 /* Register network device */
666 if ( ( rc = register_netdev ( netdev ) ) != 0 )
667 goto err_register;
668
669 usb_func_set_drvdata ( func, netdev );
670 return 0;
671
672 unregister_netdev ( netdev );
673 err_register:
674 err_fetch_mac:
675 err_reset:
676 err_describe:
677 netdev_nullify ( netdev );
678 netdev_put ( netdev );
679 err_alloc:
680 return rc;
681 }
682
683 /**
684 * Remove device
685 *
686 * @v func USB function
687 */
688 static void smsc95xx_remove ( struct usb_function *func ) {
689 struct net_device *netdev = usb_func_get_drvdata ( func );
690
691 unregister_netdev ( netdev );
692 netdev_nullify ( netdev );
693 netdev_put ( netdev );
694 }
695
696 /** SMSC95xx device IDs */
697 static struct usb_device_id smsc95xx_ids[] = {
698 {
699 .name = "smsc9500",
700 .vendor = 0x0424,
701 .product = 0x9500,
702 },
703 {
704 .name = "smsc9505",
705 .vendor = 0x0424,
706 .product = 0x9505,
707 },
708 {
709 .name = "smsc9500a",
710 .vendor = 0x0424,
711 .product = 0x9e00,
712 },
713 {
714 .name = "smsc9505a",
715 .vendor = 0x0424,
716 .product = 0x9e01,
717 },
718 {
719 .name = "smsc9514",
720 .vendor = 0x0424,
721 .product = 0xec00,
722 },
723 {
724 .name = "smsc9500-s",
725 .vendor = 0x0424,
726 .product = 0x9900,
727 },
728 {
729 .name = "smsc9505-s",
730 .vendor = 0x0424,
731 .product = 0x9901,
732 },
733 {
734 .name = "smsc9500a-s",
735 .vendor = 0x0424,
736 .product = 0x9902,
737 },
738 {
739 .name = "smsc9505a-s",
740 .vendor = 0x0424,
741 .product = 0x9903,
742 },
743 {
744 .name = "smsc9514-s",
745 .vendor = 0x0424,
746 .product = 0x9904,
747 },
748 {
749 .name = "smsc9500a-h",
750 .vendor = 0x0424,
751 .product = 0x9905,
752 },
753 {
754 .name = "smsc9505a-h",
755 .vendor = 0x0424,
756 .product = 0x9906,
757 },
758 {
759 .name = "smsc9500-2",
760 .vendor = 0x0424,
761 .product = 0x9907,
762 },
763 {
764 .name = "smsc9500a-2",
765 .vendor = 0x0424,
766 .product = 0x9908,
767 },
768 {
769 .name = "smsc9514-2",
770 .vendor = 0x0424,
771 .product = 0x9909,
772 },
773 {
774 .name = "smsc9530",
775 .vendor = 0x0424,
776 .product = 0x9530,
777 },
778 {
779 .name = "smsc9730",
780 .vendor = 0x0424,
781 .product = 0x9730,
782 },
783 {
784 .name = "smsc89530",
785 .vendor = 0x0424,
786 .product = 0x9e08,
787 },
788 };
789
790 /** SMSC LAN95xx driver */
791 struct usb_driver smsc95xx_driver __usb_driver = {
792 .ids = smsc95xx_ids,
793 .id_count = ( sizeof ( smsc95xx_ids ) / sizeof ( smsc95xx_ids[0] ) ),
794 .class = USB_CLASS_ID ( 0xff, 0x00, 0xff ),
795 .score = USB_SCORE_NORMAL,
796 .probe = smsc95xx_probe,
797 .remove = smsc95xx_remove,
798 };