From 6998849dc4a6ba3343348439d35693933d19cdaf Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Wed, 5 Jan 2000 17:13:50 +0000 Subject: [PATCH] Do not attempt to load the firmware a second time. If you reboot your machine but leave your KLSI adapter plugged into your USB port, it may stay powered on and retain its firmware in memory. Trying to load the firmware again in this case will wedge the chip. Try to detect this in the kue_load_fw() routine and bail if the firmware is already loaded and running. Also, in the probe/match routine, force the revision code to the hardware default and force a rescan of the quirk database. This is necessary because the adapter will return a different revision code if the firmware has been loaded. Without the firmware, the revision code is 0x002. With the firmware, the revision code is 0x202. This confuses the quirk mechanism, which won't match a quirk to a device unless the revision code agrees with the quirk table entry. This makes probe/attach of these devices somewhat more reliable. Also add a few comments about the device's operation. --- sys/dev/usb/if_kue.c | 60 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index f26bc2cf1731..890d0f7b7720 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -33,11 +33,33 @@ */ /* + * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver. + * * Written by Bill Paul * Electrical Engineering Department * Columbia University, New York City */ +/* + * The KLSI USB to ethernet adapter chip contains an USB serial interface, + * ethernet MAC and embedded microcontroller (called the QT Engine). + * The chip must have firmware loaded into it before it will operate. + * Packets are passed between the chip and host via bulk transfers. + * There is an interrupt endpoint mentioned in the software spec, however + * it's currently unused. This device is 10Mbps half-duplex only, hence + * there is no media selection logic. The MAC supports a 128 entry + * multicast filter, though the exact size of the filter can depend + * on the firmware. Curiously, while the software spec describes various + * ethernet statistics counters, my sample adapter and firmware combination + * claims not to support any statistics counters at all. + * + * Note that once we load the firmware in the device, we have to be + * careful not to load it again: if you restart your computer but + * leave the adapter attached to the USB controller, it may remain + * powered on and retain its firmware. In this case, we don't need + * to load the firmware a second time. + */ + #include #include #include @@ -69,6 +91,7 @@ #include #include #include +#include #include #include @@ -234,6 +257,27 @@ static int kue_load_fw(sc) struct kue_softc *sc; { usbd_status err; + u_int8_t eaddr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + /* + * First, check if we even need to load the firmware. + * If the device was still attached when the system was + * rebooted, it may already have firmware loaded in it. + * If this is the case, we don't need to do it again. + * And in fact, if we try to load it again, we'll hang, + * so we have to avoid this condition if we don't want + * to look stupid. + * + * We can test this quickly by trying to read the MAC + * address; if this fails to return any data, the firmware + * needs to be reloaded, otherwise the device is already + * operational and we can just return. + */ + err = kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_MAC, + 0, (char *)&eaddr, ETHER_ADDR_LEN); + + if (bcmp(eaddr, etherbroadcastaddr, ETHER_ADDR_LEN)) + return(USBD_NORMAL_COMPLETION); /* Load code segment */ err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, @@ -257,7 +301,7 @@ static int kue_load_fw(sc) err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, kue_trig_seg, sizeof(kue_trig_seg)); if (err) { - printf("kue%d: failed to load fixup segment: %s\n", + printf("kue%d: failed to load trigger segment: %s\n", sc->kue_unit, usbd_errstr(err)); return(ENXIO); } @@ -333,14 +377,28 @@ USB_MATCH(kue) { USB_MATCH_START(kue, uaa); struct kue_type *t; + usb_device_descriptor_t *dd; if (!uaa->iface) return(UMATCH_NONE); + dd = &uaa->device->ddesc; + t = kue_devs; while(t->kue_name != NULL) { if (uaa->vendor == t->kue_vid && uaa->product == t->kue_did) { + /* + * Force the revision code and then rescan the + * quirks so that we get the right quirk bits set. + * Why? The chip without the firmware loaded returns + * one revision code. The chip with the firmware + * loaded and running returns a *different* revision + * code. This confuses the quirk mechanism, which is + * dependent on the revision data. + */ + USETW(dd->bcdDevice, 0x002); + uaa->device->quirks = usbd_find_quirk(dd); device_set_desc(self, t->kue_name); return(UMATCH_VENDOR_PRODUCT); }