1*89d48367SSimon Glass /* 2*89d48367SSimon Glass * Copyright (c) 2011 The Chromium OS Authors. 3*89d48367SSimon Glass * See file CREDITS for list of people who contributed to this 4*89d48367SSimon Glass * project. 5*89d48367SSimon Glass * 6*89d48367SSimon Glass * This program is free software; you can redistribute it and/or 7*89d48367SSimon Glass * modify it under the terms of the GNU General Public License as 8*89d48367SSimon Glass * published by the Free Software Foundation; either version 2 of 9*89d48367SSimon Glass * the License, or (at your option) any later version. 10*89d48367SSimon Glass * 11*89d48367SSimon Glass * This program is distributed in the hope that it will be useful, 12*89d48367SSimon Glass * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*89d48367SSimon Glass * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*89d48367SSimon Glass * GNU General Public License for more details. 15*89d48367SSimon Glass * 16*89d48367SSimon Glass * You should have received a copy of the GNU General Public License 17*89d48367SSimon Glass * along with this program; if not, write to the Free Software 18*89d48367SSimon Glass * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19*89d48367SSimon Glass * MA 02111-1307 USA 20*89d48367SSimon Glass */ 21*89d48367SSimon Glass 22*89d48367SSimon Glass #include <common.h> 23*89d48367SSimon Glass #include <usb.h> 24*89d48367SSimon Glass 25*89d48367SSimon Glass #include "usb_ether.h" 26*89d48367SSimon Glass 27*89d48367SSimon Glass typedef void (*usb_eth_before_probe)(void); 28*89d48367SSimon Glass typedef int (*usb_eth_probe)(struct usb_device *dev, unsigned int ifnum, 29*89d48367SSimon Glass struct ueth_data *ss); 30*89d48367SSimon Glass typedef int (*usb_eth_get_info)(struct usb_device *dev, struct ueth_data *ss, 31*89d48367SSimon Glass struct eth_device *dev_desc); 32*89d48367SSimon Glass 33*89d48367SSimon Glass struct usb_eth_prob_dev { 34*89d48367SSimon Glass usb_eth_before_probe before_probe; /* optional */ 35*89d48367SSimon Glass usb_eth_probe probe; 36*89d48367SSimon Glass usb_eth_get_info get_info; 37*89d48367SSimon Glass }; 38*89d48367SSimon Glass 39*89d48367SSimon Glass /* driver functions go here, each bracketed by #ifdef CONFIG_USB_ETHER_xxx */ 40*89d48367SSimon Glass static const struct usb_eth_prob_dev prob_dev[] = { 41*89d48367SSimon Glass { }, /* END */ 42*89d48367SSimon Glass }; 43*89d48367SSimon Glass 44*89d48367SSimon Glass static int usb_max_eth_dev; /* number of highest available usb eth device */ 45*89d48367SSimon Glass static struct ueth_data usb_eth[USB_MAX_ETH_DEV]; 46*89d48367SSimon Glass 47*89d48367SSimon Glass /******************************************************************************* 48*89d48367SSimon Glass * tell if current ethernet device is a usb dongle 49*89d48367SSimon Glass */ 50*89d48367SSimon Glass int is_eth_dev_on_usb_host(void) 51*89d48367SSimon Glass { 52*89d48367SSimon Glass int i; 53*89d48367SSimon Glass struct eth_device *dev = eth_get_dev(); 54*89d48367SSimon Glass 55*89d48367SSimon Glass if (dev) { 56*89d48367SSimon Glass for (i = 0; i < usb_max_eth_dev; i++) 57*89d48367SSimon Glass if (&usb_eth[i].eth_dev == dev) 58*89d48367SSimon Glass return 1; 59*89d48367SSimon Glass } 60*89d48367SSimon Glass return 0; 61*89d48367SSimon Glass } 62*89d48367SSimon Glass 63*89d48367SSimon Glass /* 64*89d48367SSimon Glass * Given a USB device, ask each driver if it can support it, and attach it 65*89d48367SSimon Glass * to the first driver that says 'yes' 66*89d48367SSimon Glass */ 67*89d48367SSimon Glass static void probe_valid_drivers(struct usb_device *dev) 68*89d48367SSimon Glass { 69*89d48367SSimon Glass int j; 70*89d48367SSimon Glass 71*89d48367SSimon Glass for (j = 0; prob_dev[j].probe && prob_dev[j].get_info; j++) { 72*89d48367SSimon Glass if (!prob_dev[j].probe(dev, 0, &usb_eth[usb_max_eth_dev])) 73*89d48367SSimon Glass continue; 74*89d48367SSimon Glass /* 75*89d48367SSimon Glass * ok, it is a supported eth device. Get info and fill it in 76*89d48367SSimon Glass */ 77*89d48367SSimon Glass if (prob_dev[j].get_info(dev, 78*89d48367SSimon Glass &usb_eth[usb_max_eth_dev], 79*89d48367SSimon Glass &usb_eth[usb_max_eth_dev].eth_dev)) { 80*89d48367SSimon Glass /* found proper driver */ 81*89d48367SSimon Glass /* register with networking stack */ 82*89d48367SSimon Glass usb_max_eth_dev++; 83*89d48367SSimon Glass 84*89d48367SSimon Glass /* 85*89d48367SSimon Glass * usb_max_eth_dev must be incremented prior to this 86*89d48367SSimon Glass * call since eth_current_changed (internally called) 87*89d48367SSimon Glass * relies on it 88*89d48367SSimon Glass */ 89*89d48367SSimon Glass eth_register(&usb_eth[usb_max_eth_dev - 1].eth_dev); 90*89d48367SSimon Glass break; 91*89d48367SSimon Glass } 92*89d48367SSimon Glass } 93*89d48367SSimon Glass } 94*89d48367SSimon Glass 95*89d48367SSimon Glass /******************************************************************************* 96*89d48367SSimon Glass * scan the usb and reports device info 97*89d48367SSimon Glass * to the user if mode = 1 98*89d48367SSimon Glass * returns current device or -1 if no 99*89d48367SSimon Glass */ 100*89d48367SSimon Glass int usb_host_eth_scan(int mode) 101*89d48367SSimon Glass { 102*89d48367SSimon Glass int i, old_async; 103*89d48367SSimon Glass struct usb_device *dev; 104*89d48367SSimon Glass 105*89d48367SSimon Glass 106*89d48367SSimon Glass if (mode == 1) 107*89d48367SSimon Glass printf(" scanning bus for ethernet devices... "); 108*89d48367SSimon Glass 109*89d48367SSimon Glass old_async = usb_disable_asynch(1); /* asynch transfer not allowed */ 110*89d48367SSimon Glass 111*89d48367SSimon Glass for (i = 0; i < USB_MAX_ETH_DEV; i++) 112*89d48367SSimon Glass memset(&usb_eth[i], 0, sizeof(usb_eth[i])); 113*89d48367SSimon Glass 114*89d48367SSimon Glass for (i = 0; prob_dev[i].probe; i++) { 115*89d48367SSimon Glass if (prob_dev[i].before_probe) 116*89d48367SSimon Glass prob_dev[i].before_probe(); 117*89d48367SSimon Glass } 118*89d48367SSimon Glass 119*89d48367SSimon Glass usb_max_eth_dev = 0; 120*89d48367SSimon Glass for (i = 0; i < USB_MAX_DEVICE; i++) { 121*89d48367SSimon Glass dev = usb_get_dev_index(i); /* get device */ 122*89d48367SSimon Glass debug("i=%d\n", i); 123*89d48367SSimon Glass if (dev == NULL) 124*89d48367SSimon Glass break; /* no more devices avaiable */ 125*89d48367SSimon Glass 126*89d48367SSimon Glass /* find valid usb_ether driver for this device, if any */ 127*89d48367SSimon Glass probe_valid_drivers(dev); 128*89d48367SSimon Glass 129*89d48367SSimon Glass /* check limit */ 130*89d48367SSimon Glass if (usb_max_eth_dev == USB_MAX_ETH_DEV) { 131*89d48367SSimon Glass printf("max USB Ethernet Device reached: %d stopping\n", 132*89d48367SSimon Glass usb_max_eth_dev); 133*89d48367SSimon Glass break; 134*89d48367SSimon Glass } 135*89d48367SSimon Glass } /* for */ 136*89d48367SSimon Glass 137*89d48367SSimon Glass usb_disable_asynch(old_async); /* restore asynch value */ 138*89d48367SSimon Glass printf("%d Ethernet Device(s) found\n", usb_max_eth_dev); 139*89d48367SSimon Glass if (usb_max_eth_dev > 0) 140*89d48367SSimon Glass return 0; 141*89d48367SSimon Glass return -1; 142*89d48367SSimon Glass } 143*89d48367SSimon Glass 144