1184610Salfred/*-
2184610Salfred * Copyright (c) 1997, 1998, 1999, 2000
3184610Salfred *	Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
4184610Salfred *
5184610Salfred * Redistribution and use in source and binary forms, with or without
6184610Salfred * modification, are permitted provided that the following conditions
7184610Salfred * are met:
8184610Salfred * 1. Redistributions of source code must retain the above copyright
9184610Salfred *    notice, this list of conditions and the following disclaimer.
10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright
11184610Salfred *    notice, this list of conditions and the following disclaimer in the
12184610Salfred *    documentation and/or other materials provided with the distribution.
13184610Salfred * 3. All advertising materials mentioning features or use of this software
14184610Salfred *    must display the following acknowledgement:
15184610Salfred *	This product includes software developed by Bill Paul.
16184610Salfred * 4. Neither the name of the author nor the names of any co-contributors
17184610Salfred *    may be used to endorse or promote products derived from this software
18184610Salfred *    without specific prior written permission.
19184610Salfred *
20184610Salfred * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23184610Salfred * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24184610Salfred * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25184610Salfred * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26184610Salfred * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27184610Salfred * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28184610Salfred * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29184610Salfred * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30184610Salfred * THE POSSIBILITY OF SUCH DAMAGE.
31184610Salfred */
32184610Salfred
33184610Salfred#include <sys/cdefs.h>
34184610Salfred__FBSDID("$FreeBSD$");
35184610Salfred
36184610Salfred/*
37184610Salfred * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver.
38184610Salfred *
39184610Salfred * Written by Bill Paul <wpaul@ee.columbia.edu>
40184610Salfred * Electrical Engineering Department
41184610Salfred * Columbia University, New York City
42184610Salfred */
43184610Salfred
44184610Salfred/*
45184610Salfred * The KLSI USB to ethernet adapter chip contains an USB serial interface,
46184610Salfred * ethernet MAC and embedded microcontroller (called the QT Engine).
47184610Salfred * The chip must have firmware loaded into it before it will operate.
48184610Salfred * Packets are passed between the chip and host via bulk transfers.
49184610Salfred * There is an interrupt endpoint mentioned in the software spec, however
50184610Salfred * it's currently unused. This device is 10Mbps half-duplex only, hence
51184610Salfred * there is no media selection logic. The MAC supports a 128 entry
52184610Salfred * multicast filter, though the exact size of the filter can depend
53184610Salfred * on the firmware. Curiously, while the software spec describes various
54184610Salfred * ethernet statistics counters, my sample adapter and firmware combination
55184610Salfred * claims not to support any statistics counters at all.
56184610Salfred *
57184610Salfred * Note that once we load the firmware in the device, we have to be
58184610Salfred * careful not to load it again: if you restart your computer but
59184610Salfred * leave the adapter attached to the USB controller, it may remain
60184610Salfred * powered on and retain its firmware. In this case, we don't need
61184610Salfred * to load the firmware a second time.
62184610Salfred *
63184610Salfred * Special thanks to Rob Furr for providing an ADS Technologies
64184610Salfred * adapter for development and testing. No monkeys were harmed during
65184610Salfred * the development of this driver.
66184610Salfred */
67184610Salfred
68194677Sthompsa#include <sys/stdint.h>
69194677Sthompsa#include <sys/stddef.h>
70194677Sthompsa#include <sys/param.h>
71194677Sthompsa#include <sys/queue.h>
72194677Sthompsa#include <sys/types.h>
73194677Sthompsa#include <sys/systm.h>
74194677Sthompsa#include <sys/kernel.h>
75194677Sthompsa#include <sys/bus.h>
76194677Sthompsa#include <sys/module.h>
77194677Sthompsa#include <sys/lock.h>
78194677Sthompsa#include <sys/mutex.h>
79194677Sthompsa#include <sys/condvar.h>
80194677Sthompsa#include <sys/sysctl.h>
81194677Sthompsa#include <sys/sx.h>
82194677Sthompsa#include <sys/unistd.h>
83194677Sthompsa#include <sys/callout.h>
84194677Sthompsa#include <sys/malloc.h>
85194677Sthompsa#include <sys/priv.h>
86194677Sthompsa
87194677Sthompsa#include <dev/usb/usb.h>
88194677Sthompsa#include <dev/usb/usbdi.h>
89194677Sthompsa#include <dev/usb/usbdi_util.h>
90188746Sthompsa#include "usbdevs.h"
91184610Salfred
92184610Salfred#define	USB_DEBUG_VAR kue_debug
93194677Sthompsa#include <dev/usb/usb_debug.h>
94188942Sthompsa#include <dev/usb/usb_process.h>
95184610Salfred
96188942Sthompsa#include <dev/usb/net/usb_ethernet.h>
97188942Sthompsa#include <dev/usb/net/if_kuereg.h>
98188942Sthompsa#include <dev/usb/net/if_kuefw.h>
99184610Salfred
100184610Salfred/*
101184610Salfred * Various supported device vendors/products.
102184610Salfred */
103223486Shselaskystatic const STRUCT_USB_HOST_ID kue_devs[] = {
104201028Sthompsa#define	KUE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
105201028Sthompsa	KUE_DEV(3COM, 3C19250),
106201028Sthompsa	KUE_DEV(3COM, 3C460),
107201028Sthompsa	KUE_DEV(ABOCOM, URE450),
108201028Sthompsa	KUE_DEV(ADS, UBS10BT),
109201028Sthompsa	KUE_DEV(ADS, UBS10BTX),
110201028Sthompsa	KUE_DEV(AOX, USB101),
111201028Sthompsa	KUE_DEV(ASANTE, EA),
112201028Sthompsa	KUE_DEV(ATEN, DSB650C),
113201028Sthompsa	KUE_DEV(ATEN, UC10T),
114201028Sthompsa	KUE_DEV(COREGA, ETHER_USB_T),
115201028Sthompsa	KUE_DEV(DLINK, DSB650C),
116201028Sthompsa	KUE_DEV(ENTREGA, E45),
117201028Sthompsa	KUE_DEV(ENTREGA, XX1),
118201028Sthompsa	KUE_DEV(ENTREGA, XX2),
119201028Sthompsa	KUE_DEV(IODATA, USBETT),
120201028Sthompsa	KUE_DEV(JATON, EDA),
121201028Sthompsa	KUE_DEV(KINGSTON, XX1),
122201028Sthompsa	KUE_DEV(KLSI, DUH3E10BT),
123201028Sthompsa	KUE_DEV(KLSI, DUH3E10BTN),
124201028Sthompsa	KUE_DEV(LINKSYS, USB10T),
125201028Sthompsa	KUE_DEV(MOBILITY, EA),
126201028Sthompsa	KUE_DEV(NETGEAR, EA101),
127201028Sthompsa	KUE_DEV(NETGEAR, EA101X),
128201028Sthompsa	KUE_DEV(PERACOM, ENET),
129201028Sthompsa	KUE_DEV(PERACOM, ENET2),
130201028Sthompsa	KUE_DEV(PERACOM, ENET3),
131201028Sthompsa	KUE_DEV(PORTGEAR, EA8),
132201028Sthompsa	KUE_DEV(PORTGEAR, EA9),
133201028Sthompsa	KUE_DEV(PORTSMITH, EEA),
134201028Sthompsa	KUE_DEV(SHARK, PA),
135201028Sthompsa	KUE_DEV(SILICOM, GPE),
136201028Sthompsa	KUE_DEV(SILICOM, U2E),
137201028Sthompsa	KUE_DEV(SMC, 2102USB),
138201028Sthompsa#undef KUE_DEV
139184610Salfred};
140184610Salfred
141184610Salfred/* prototypes */
142184610Salfred
143184610Salfredstatic device_probe_t kue_probe;
144184610Salfredstatic device_attach_t kue_attach;
145184610Salfredstatic device_detach_t kue_detach;
146184610Salfred
147193045Sthompsastatic usb_callback_t kue_bulk_read_callback;
148193045Sthompsastatic usb_callback_t kue_bulk_write_callback;
149184610Salfred
150193045Sthompsastatic uether_fn_t kue_attach_post;
151193045Sthompsastatic uether_fn_t kue_init;
152193045Sthompsastatic uether_fn_t kue_stop;
153193045Sthompsastatic uether_fn_t kue_start;
154193045Sthompsastatic uether_fn_t kue_setmulti;
155193045Sthompsastatic uether_fn_t kue_setpromisc;
156184610Salfred
157188412Sthompsastatic int	kue_do_request(struct kue_softc *,
158192984Sthompsa		    struct usb_device_request *, void *);
159188412Sthompsastatic int	kue_setword(struct kue_softc *, uint8_t, uint16_t);
160188412Sthompsastatic int	kue_ctl(struct kue_softc *, uint8_t, uint8_t, uint16_t,
161188412Sthompsa		    void *, int);
162188412Sthompsastatic int	kue_load_fw(struct kue_softc *);
163188412Sthompsastatic void	kue_reset(struct kue_softc *);
164184610Salfred
165207077Sthompsa#ifdef USB_DEBUG
166184610Salfredstatic int kue_debug = 0;
167184610Salfred
168227309Sedstatic SYSCTL_NODE(_hw_usb, OID_AUTO, kue, CTLFLAG_RW, 0, "USB kue");
169192502SthompsaSYSCTL_INT(_hw_usb_kue, OID_AUTO, debug, CTLFLAG_RW, &kue_debug, 0,
170184610Salfred    "Debug level");
171184610Salfred#endif
172184610Salfred
173192984Sthompsastatic const struct usb_config kue_config[KUE_N_TRANSFER] = {
174184610Salfred
175187259Sthompsa	[KUE_BULK_DT_WR] = {
176184610Salfred		.type = UE_BULK,
177184610Salfred		.endpoint = UE_ADDR_ANY,
178184610Salfred		.direction = UE_DIR_OUT,
179190734Sthompsa		.bufsize = (MCLBYTES + 2 + 64),
180190734Sthompsa		.flags = {.pipe_bof = 1,},
181190734Sthompsa		.callback = kue_bulk_write_callback,
182190734Sthompsa		.timeout = 10000,	/* 10 seconds */
183184610Salfred	},
184184610Salfred
185187259Sthompsa	[KUE_BULK_DT_RD] = {
186184610Salfred		.type = UE_BULK,
187184610Salfred		.endpoint = UE_ADDR_ANY,
188184610Salfred		.direction = UE_DIR_IN,
189190734Sthompsa		.bufsize = (MCLBYTES + 2),
190190734Sthompsa		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
191190734Sthompsa		.callback = kue_bulk_read_callback,
192190734Sthompsa		.timeout = 0,	/* no timeout */
193184610Salfred	},
194184610Salfred};
195184610Salfred
196184610Salfredstatic device_method_t kue_methods[] = {
197184610Salfred	/* Device interface */
198184610Salfred	DEVMETHOD(device_probe, kue_probe),
199184610Salfred	DEVMETHOD(device_attach, kue_attach),
200184610Salfred	DEVMETHOD(device_detach, kue_detach),
201184610Salfred
202246128Ssbz	DEVMETHOD_END
203184610Salfred};
204184610Salfred
205184610Salfredstatic driver_t kue_driver = {
206184610Salfred	.name = "kue",
207184610Salfred	.methods = kue_methods,
208184610Salfred	.size = sizeof(struct kue_softc),
209184610Salfred};
210184610Salfred
211184610Salfredstatic devclass_t kue_devclass;
212184610Salfred
213189275SthompsaDRIVER_MODULE(kue, uhub, kue_driver, kue_devclass, NULL, 0);
214188942SthompsaMODULE_DEPEND(kue, uether, 1, 1, 1);
215188942SthompsaMODULE_DEPEND(kue, usb, 1, 1, 1);
216184610SalfredMODULE_DEPEND(kue, ether, 1, 1, 1);
217212122SthompsaMODULE_VERSION(kue, 1);
218184610Salfred
219192984Sthompsastatic const struct usb_ether_methods kue_ue_methods = {
220188412Sthompsa	.ue_attach_post = kue_attach_post,
221188412Sthompsa	.ue_start = kue_start,
222188412Sthompsa	.ue_init = kue_init,
223188412Sthompsa	.ue_stop = kue_stop,
224188412Sthompsa	.ue_setmulti = kue_setmulti,
225188412Sthompsa	.ue_setpromisc = kue_setpromisc,
226188412Sthompsa};
227188412Sthompsa
228184610Salfred/*
229184610Salfred * We have a custom do_request function which is almost like the
230184610Salfred * regular do_request function, except it has a much longer timeout.
231184610Salfred * Why? Because we need to make requests over the control endpoint
232184610Salfred * to download the firmware to the device, which can take longer
233184610Salfred * than the default timeout.
234184610Salfred */
235188412Sthompsastatic int
236192984Sthompsakue_do_request(struct kue_softc *sc, struct usb_device_request *req,
237184610Salfred    void *data)
238184610Salfred{
239193045Sthompsa	usb_error_t err;
240184610Salfred
241194228Sthompsa	err = uether_do_request(&sc->sc_ue, req, data, 60000);
242184610Salfred
243188412Sthompsa	return (err);
244184610Salfred}
245184610Salfred
246188412Sthompsastatic int
247188412Sthompsakue_setword(struct kue_softc *sc, uint8_t breq, uint16_t word)
248184610Salfred{
249192984Sthompsa	struct usb_device_request req;
250184610Salfred
251184610Salfred	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
252184610Salfred	req.bRequest = breq;
253184610Salfred	USETW(req.wValue, word);
254184610Salfred	USETW(req.wIndex, 0);
255184610Salfred	USETW(req.wLength, 0);
256184610Salfred
257188412Sthompsa	return (kue_do_request(sc, &req, NULL));
258184610Salfred}
259184610Salfred
260188412Sthompsastatic int
261188412Sthompsakue_ctl(struct kue_softc *sc, uint8_t rw, uint8_t breq,
262188412Sthompsa    uint16_t val, void *data, int len)
263184610Salfred{
264192984Sthompsa	struct usb_device_request req;
265184610Salfred
266188412Sthompsa	if (rw == KUE_CTL_WRITE)
267184610Salfred		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
268188412Sthompsa	else
269184610Salfred		req.bmRequestType = UT_READ_VENDOR_DEVICE;
270184610Salfred
271188412Sthompsa
272184610Salfred	req.bRequest = breq;
273184610Salfred	USETW(req.wValue, val);
274184610Salfred	USETW(req.wIndex, 0);
275184610Salfred	USETW(req.wLength, len);
276184610Salfred
277188412Sthompsa	return (kue_do_request(sc, &req, data));
278184610Salfred}
279184610Salfred
280188412Sthompsastatic int
281188412Sthompsakue_load_fw(struct kue_softc *sc)
282184610Salfred{
283192984Sthompsa	struct usb_device_descriptor *dd;
284184610Salfred	uint16_t hwrev;
285193045Sthompsa	usb_error_t err;
286184610Salfred
287194228Sthompsa	dd = usbd_get_device_descriptor(sc->sc_ue.ue_udev);
288184610Salfred	hwrev = UGETW(dd->bcdDevice);
289184610Salfred
290184610Salfred	/*
291184610Salfred	 * First, check if we even need to load the firmware.
292184610Salfred	 * If the device was still attached when the system was
293184610Salfred	 * rebooted, it may already have firmware loaded in it.
294184610Salfred	 * If this is the case, we don't need to do it again.
295184610Salfred	 * And in fact, if we try to load it again, we'll hang,
296184610Salfred	 * so we have to avoid this condition if we don't want
297184610Salfred	 * to look stupid.
298184610Salfred	 *
299184610Salfred	 * We can test this quickly by checking the bcdRevision
300184610Salfred	 * code. The NIC will return a different revision code if
301184610Salfred	 * it's probed while the firmware is still loaded and
302184610Salfred	 * running.
303184610Salfred	 */
304188412Sthompsa	if (hwrev == 0x0202)
305188412Sthompsa		return(0);
306188412Sthompsa
307188412Sthompsa	/* Load code segment */
308188412Sthompsa	err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
309188412Sthompsa	    0, kue_code_seg, sizeof(kue_code_seg));
310188412Sthompsa	if (err) {
311188412Sthompsa		device_printf(sc->sc_ue.ue_dev, "failed to load code segment: %s\n",
312194228Sthompsa		    usbd_errstr(err));
313188412Sthompsa		return(ENXIO);
314184610Salfred	}
315184610Salfred
316188412Sthompsa	/* Load fixup segment */
317188412Sthompsa	err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
318184610Salfred	    0, kue_fix_seg, sizeof(kue_fix_seg));
319188412Sthompsa	if (err) {
320188412Sthompsa		device_printf(sc->sc_ue.ue_dev, "failed to load fixup segment: %s\n",
321194228Sthompsa		    usbd_errstr(err));
322188412Sthompsa		return(ENXIO);
323188412Sthompsa	}
324184610Salfred
325188412Sthompsa	/* Send trigger command. */
326188412Sthompsa	err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
327184610Salfred	    0, kue_trig_seg, sizeof(kue_trig_seg));
328188412Sthompsa	if (err) {
329188412Sthompsa		device_printf(sc->sc_ue.ue_dev, "failed to load trigger segment: %s\n",
330194228Sthompsa		    usbd_errstr(err));
331188412Sthompsa		return(ENXIO);
332188412Sthompsa	}
333188412Sthompsa
334188412Sthompsa	return (0);
335184610Salfred}
336184610Salfred
337184610Salfredstatic void
338192984Sthompsakue_setpromisc(struct usb_ether *ue)
339184610Salfred{
340194228Sthompsa	struct kue_softc *sc = uether_getsc(ue);
341194228Sthompsa	struct ifnet *ifp = uether_getifp(ue);
342184610Salfred
343188412Sthompsa	KUE_LOCK_ASSERT(sc, MA_OWNED);
344188412Sthompsa
345188412Sthompsa	if (ifp->if_flags & IFF_PROMISC)
346188412Sthompsa		sc->sc_rxfilt |= KUE_RXFILT_PROMISC;
347188412Sthompsa	else
348188412Sthompsa		sc->sc_rxfilt &= ~KUE_RXFILT_PROMISC;
349188412Sthompsa
350188412Sthompsa	kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->sc_rxfilt);
351184610Salfred}
352184610Salfred
353184610Salfredstatic void
354192984Sthompsakue_setmulti(struct usb_ether *ue)
355184610Salfred{
356194228Sthompsa	struct kue_softc *sc = uether_getsc(ue);
357194228Sthompsa	struct ifnet *ifp = uether_getifp(ue);
358188412Sthompsa	struct ifmultiaddr *ifma;
359188412Sthompsa	int i = 0;
360184610Salfred
361188412Sthompsa	KUE_LOCK_ASSERT(sc, MA_OWNED);
362184610Salfred
363188412Sthompsa	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
364188412Sthompsa		sc->sc_rxfilt |= KUE_RXFILT_ALLMULTI;
365188412Sthompsa		sc->sc_rxfilt &= ~KUE_RXFILT_MULTICAST;
366188412Sthompsa		kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->sc_rxfilt);
367188412Sthompsa		return;
368184610Salfred	}
369184610Salfred
370188412Sthompsa	sc->sc_rxfilt &= ~KUE_RXFILT_ALLMULTI;
371184610Salfred
372195049Srwatson	if_maddr_rlock(ifp);
373188412Sthompsa	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
374188412Sthompsa	{
375188412Sthompsa		if (ifma->ifma_addr->sa_family != AF_LINK)
376188412Sthompsa			continue;
377188412Sthompsa		/*
378188412Sthompsa		 * If there are too many addresses for the
379188412Sthompsa		 * internal filter, switch over to allmulti mode.
380188412Sthompsa		 */
381188412Sthompsa		if (i == KUE_MCFILTCNT(sc))
382188412Sthompsa			break;
383227461Shselasky		memcpy(KUE_MCFILT(sc, i),
384227461Shselasky		    LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
385227461Shselasky		    ETHER_ADDR_LEN);
386188412Sthompsa		i++;
387188412Sthompsa	}
388195049Srwatson	if_maddr_runlock(ifp);
389184610Salfred
390188412Sthompsa	if (i == KUE_MCFILTCNT(sc))
391188412Sthompsa		sc->sc_rxfilt |= KUE_RXFILT_ALLMULTI;
392188412Sthompsa	else {
393188412Sthompsa		sc->sc_rxfilt |= KUE_RXFILT_MULTICAST;
394188412Sthompsa		kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS,
395188412Sthompsa		    i, sc->sc_mcfilters, i * ETHER_ADDR_LEN);
396188412Sthompsa	}
397184610Salfred
398188412Sthompsa	kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->sc_rxfilt);
399184610Salfred}
400184610Salfred
401184610Salfred/*
402184610Salfred * Issue a SET_CONFIGURATION command to reset the MAC. This should be
403184610Salfred * done after the firmware is loaded into the adapter in order to
404184610Salfred * bring it into proper operation.
405184610Salfred */
406184610Salfredstatic void
407188412Sthompsakue_reset(struct kue_softc *sc)
408184610Salfred{
409192984Sthompsa	struct usb_config_descriptor *cd;
410193045Sthompsa	usb_error_t err;
411184610Salfred
412194228Sthompsa	cd = usbd_get_config_descriptor(sc->sc_ue.ue_udev);
413184610Salfred
414194228Sthompsa	err = usbd_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx,
415184610Salfred	    cd->bConfigurationValue);
416188412Sthompsa	if (err)
417184610Salfred		DPRINTF("reset failed (ignored)\n");
418188412Sthompsa
419188412Sthompsa	/* wait a little while for the chip to get its brains in order */
420194228Sthompsa	uether_pause(&sc->sc_ue, hz / 100);
421188412Sthompsa}
422188412Sthompsa
423188412Sthompsastatic void
424192984Sthompsakue_attach_post(struct usb_ether *ue)
425188412Sthompsa{
426194228Sthompsa	struct kue_softc *sc = uether_getsc(ue);
427188412Sthompsa	int error;
428188412Sthompsa
429188412Sthompsa	/* load the firmware into the NIC */
430188412Sthompsa	error = kue_load_fw(sc);
431188412Sthompsa	if (error) {
432188412Sthompsa		device_printf(sc->sc_ue.ue_dev, "could not load firmware\n");
433188412Sthompsa		/* ignore the error */
434184610Salfred	}
435188412Sthompsa
436188412Sthompsa	/* reset the adapter */
437188412Sthompsa	kue_reset(sc);
438188412Sthompsa
439188412Sthompsa	/* read ethernet descriptor */
440188412Sthompsa	kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR,
441188412Sthompsa	    0, &sc->sc_desc, sizeof(sc->sc_desc));
442188412Sthompsa
443188412Sthompsa	/* copy in ethernet address */
444188412Sthompsa	memcpy(ue->ue_eaddr, sc->sc_desc.kue_macaddr, sizeof(ue->ue_eaddr));
445184610Salfred}
446184610Salfred
447184610Salfred/*
448184610Salfred * Probe for a KLSI chip.
449184610Salfred */
450184610Salfredstatic int
451184610Salfredkue_probe(device_t dev)
452184610Salfred{
453192984Sthompsa	struct usb_attach_arg *uaa = device_get_ivars(dev);
454184610Salfred
455192499Sthompsa	if (uaa->usb_mode != USB_MODE_HOST)
456184610Salfred		return (ENXIO);
457188412Sthompsa	if (uaa->info.bConfigIndex != KUE_CONFIG_IDX)
458184610Salfred		return (ENXIO);
459188412Sthompsa	if (uaa->info.bIfaceIndex != KUE_IFACE_IDX)
460184610Salfred		return (ENXIO);
461188412Sthompsa
462194228Sthompsa	return (usbd_lookup_id_by_uaa(kue_devs, sizeof(kue_devs), uaa));
463184610Salfred}
464184610Salfred
465184610Salfred/*
466184610Salfred * Attach the interface. Allocate softc structures, do
467184610Salfred * setup and ethernet/BPF attach.
468184610Salfred */
469184610Salfredstatic int
470184610Salfredkue_attach(device_t dev)
471184610Salfred{
472192984Sthompsa	struct usb_attach_arg *uaa = device_get_ivars(dev);
473184610Salfred	struct kue_softc *sc = device_get_softc(dev);
474192984Sthompsa	struct usb_ether *ue = &sc->sc_ue;
475184610Salfred	uint8_t iface_index;
476188412Sthompsa	int error;
477184610Salfred
478194228Sthompsa	device_set_usb_desc(dev);
479188412Sthompsa	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
480184610Salfred
481184610Salfred	iface_index = KUE_IFACE_IDX;
482194228Sthompsa	error = usbd_transfer_setup(uaa->device, &iface_index,
483187259Sthompsa	    sc->sc_xfer, kue_config, KUE_N_TRANSFER, sc, &sc->sc_mtx);
484184610Salfred	if (error) {
485199816Sthompsa		device_printf(dev, "allocating USB transfers failed\n");
486184610Salfred		goto detach;
487184610Salfred	}
488188412Sthompsa
489188412Sthompsa	sc->sc_mcfilters = malloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN,
490188412Sthompsa	    M_USBDEV, M_WAITOK);
491188412Sthompsa	if (sc->sc_mcfilters == NULL) {
492199816Sthompsa		device_printf(dev, "failed allocating USB memory\n");
493184610Salfred		goto detach;
494184610Salfred	}
495184610Salfred
496188412Sthompsa	ue->ue_sc = sc;
497188412Sthompsa	ue->ue_dev = dev;
498188412Sthompsa	ue->ue_udev = uaa->device;
499188412Sthompsa	ue->ue_mtx = &sc->sc_mtx;
500188412Sthompsa	ue->ue_methods = &kue_ue_methods;
501184610Salfred
502194228Sthompsa	error = uether_ifattach(ue);
503188412Sthompsa	if (error) {
504188412Sthompsa		device_printf(dev, "could not attach interface\n");
505188412Sthompsa		goto detach;
506188412Sthompsa	}
507184610Salfred	return (0);			/* success */
508184610Salfred
509184610Salfreddetach:
510184610Salfred	kue_detach(dev);
511184610Salfred	return (ENXIO);			/* failure */
512184610Salfred}
513184610Salfred
514184610Salfredstatic int
515184610Salfredkue_detach(device_t dev)
516184610Salfred{
517184610Salfred	struct kue_softc *sc = device_get_softc(dev);
518192984Sthompsa	struct usb_ether *ue = &sc->sc_ue;
519184610Salfred
520194228Sthompsa	usbd_transfer_unsetup(sc->sc_xfer, KUE_N_TRANSFER);
521194228Sthompsa	uether_ifdetach(ue);
522184610Salfred	mtx_destroy(&sc->sc_mtx);
523188412Sthompsa	free(sc->sc_mcfilters, M_USBDEV);
524184610Salfred
525184610Salfred	return (0);
526184610Salfred}
527184610Salfred
528184610Salfred/*
529184610Salfred * A frame has been uploaded: pass the resulting mbuf chain up to
530184610Salfred * the higher level protocols.
531184610Salfred */
532184610Salfredstatic void
533194677Sthompsakue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
534184610Salfred{
535194677Sthompsa	struct kue_softc *sc = usbd_xfer_softc(xfer);
536192984Sthompsa	struct usb_ether *ue = &sc->sc_ue;
537194228Sthompsa	struct ifnet *ifp = uether_getifp(ue);
538194677Sthompsa	struct usb_page_cache *pc;
539184610Salfred	uint8_t buf[2];
540188412Sthompsa	int len;
541194677Sthompsa	int actlen;
542184610Salfred
543194677Sthompsa	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
544194677Sthompsa
545184610Salfred	switch (USB_GET_STATE(xfer)) {
546184610Salfred	case USB_ST_TRANSFERRED:
547184610Salfred
548233774Shselasky		if (actlen <= (int)(2 + sizeof(struct ether_header))) {
549184610Salfred			ifp->if_ierrors++;
550184610Salfred			goto tr_setup;
551184610Salfred		}
552194677Sthompsa		pc = usbd_xfer_get_frame(xfer, 0);
553194677Sthompsa		usbd_copy_out(pc, 0, buf, 2);
554194677Sthompsa		actlen -= 2;
555184610Salfred		len = buf[0] | (buf[1] << 8);
556194677Sthompsa		len = min(actlen, len);
557184610Salfred
558194677Sthompsa		uether_rxbuf(ue, pc, 2, len);
559188412Sthompsa		/* FALLTHROUGH */
560184610Salfred	case USB_ST_SETUP:
561184610Salfredtr_setup:
562194677Sthompsa		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
563194228Sthompsa		usbd_transfer_submit(xfer);
564194228Sthompsa		uether_rxflush(ue);
565184610Salfred		return;
566184610Salfred
567184610Salfred	default:			/* Error */
568188412Sthompsa		DPRINTF("bulk read error, %s\n",
569194677Sthompsa		    usbd_errstr(error));
570188412Sthompsa
571194677Sthompsa		if (error != USB_ERR_CANCELLED) {
572184610Salfred			/* try to clear stall first */
573194677Sthompsa			usbd_xfer_set_stall(xfer);
574188412Sthompsa			goto tr_setup;
575184610Salfred		}
576184610Salfred		return;
577184610Salfred
578184610Salfred	}
579184610Salfred}
580184610Salfred
581184610Salfredstatic void
582194677Sthompsakue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
583184610Salfred{
584194677Sthompsa	struct kue_softc *sc = usbd_xfer_softc(xfer);
585194228Sthompsa	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
586194677Sthompsa	struct usb_page_cache *pc;
587184610Salfred	struct mbuf *m;
588188412Sthompsa	int total_len;
589188412Sthompsa	int temp_len;
590184610Salfred	uint8_t buf[2];
591184610Salfred
592184610Salfred	switch (USB_GET_STATE(xfer)) {
593184610Salfred	case USB_ST_TRANSFERRED:
594184610Salfred		DPRINTFN(11, "transfer complete\n");
595184610Salfred		ifp->if_opackets++;
596184610Salfred
597188412Sthompsa		/* FALLTHROUGH */
598184610Salfred	case USB_ST_SETUP:
599188412Sthompsatr_setup:
600184610Salfred		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
601184610Salfred
602188412Sthompsa		if (m == NULL)
603188412Sthompsa			return;
604188412Sthompsa		if (m->m_pkthdr.len > MCLBYTES)
605184610Salfred			m->m_pkthdr.len = MCLBYTES;
606184610Salfred		temp_len = (m->m_pkthdr.len + 2);
607184610Salfred		total_len = (temp_len + (64 - (temp_len % 64)));
608184610Salfred
609184610Salfred		/* the first two bytes are the frame length */
610184610Salfred
611184610Salfred		buf[0] = (uint8_t)(m->m_pkthdr.len);
612184610Salfred		buf[1] = (uint8_t)(m->m_pkthdr.len >> 8);
613184610Salfred
614194677Sthompsa		pc = usbd_xfer_get_frame(xfer, 0);
615194677Sthompsa		usbd_copy_in(pc, 0, buf, 2);
616194677Sthompsa		usbd_m_copy_in(pc, 2, m, 0, m->m_pkthdr.len);
617184610Salfred
618194677Sthompsa		usbd_frame_zero(pc, temp_len, total_len - temp_len);
619194677Sthompsa		usbd_xfer_set_frame_len(xfer, 0, total_len);
620184610Salfred
621184610Salfred		/*
622184610Salfred		 * if there's a BPF listener, bounce a copy
623184610Salfred		 * of this frame to him:
624184610Salfred		 */
625184610Salfred		BPF_MTAP(ifp, m);
626184610Salfred
627184610Salfred		m_freem(m);
628184610Salfred
629194228Sthompsa		usbd_transfer_submit(xfer);
630184610Salfred
631184610Salfred		return;
632184610Salfred
633184610Salfred	default:			/* Error */
634184610Salfred		DPRINTFN(11, "transfer error, %s\n",
635194677Sthompsa		    usbd_errstr(error));
636184610Salfred
637188412Sthompsa		ifp->if_oerrors++;
638188412Sthompsa
639194677Sthompsa		if (error != USB_ERR_CANCELLED) {
640184610Salfred			/* try to clear stall first */
641194677Sthompsa			usbd_xfer_set_stall(xfer);
642188412Sthompsa			goto tr_setup;
643184610Salfred		}
644184610Salfred		return;
645184610Salfred
646184610Salfred	}
647184610Salfred}
648184610Salfred
649184610Salfredstatic void
650192984Sthompsakue_start(struct usb_ether *ue)
651184610Salfred{
652194228Sthompsa	struct kue_softc *sc = uether_getsc(ue);
653184610Salfred
654188412Sthompsa	/*
655188412Sthompsa	 * start the USB transfers, if not already started:
656188412Sthompsa	 */
657194228Sthompsa	usbd_transfer_start(sc->sc_xfer[KUE_BULK_DT_RD]);
658194228Sthompsa	usbd_transfer_start(sc->sc_xfer[KUE_BULK_DT_WR]);
659184610Salfred}
660184610Salfred
661184610Salfredstatic void
662192984Sthompsakue_init(struct usb_ether *ue)
663184610Salfred{
664194228Sthompsa	struct kue_softc *sc = uether_getsc(ue);
665194228Sthompsa	struct ifnet *ifp = uether_getifp(ue);
666184610Salfred
667188412Sthompsa	KUE_LOCK_ASSERT(sc, MA_OWNED);
668184610Salfred
669184610Salfred	/* set MAC address */
670188412Sthompsa	kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MAC,
671188412Sthompsa	    0, IF_LLADDR(ifp), ETHER_ADDR_LEN);
672184610Salfred
673184610Salfred	/* I'm not sure how to tune these. */
674184610Salfred#if 0
675184610Salfred	/*
676184610Salfred	 * Leave this one alone for now; setting it
677184610Salfred	 * wrong causes lockups on some machines/controllers.
678184610Salfred	 */
679188412Sthompsa	kue_setword(sc, KUE_CMD_SET_SOFS, 1);
680184610Salfred#endif
681188412Sthompsa	kue_setword(sc, KUE_CMD_SET_URB_SIZE, 64);
682184610Salfred
683184610Salfred	/* load the multicast filter */
684188412Sthompsa	kue_setpromisc(ue);
685184610Salfred
686194677Sthompsa	usbd_xfer_set_stall(sc->sc_xfer[KUE_BULK_DT_WR]);
687184610Salfred
688188412Sthompsa	ifp->if_drv_flags |= IFF_DRV_RUNNING;
689188412Sthompsa	kue_start(ue);
690184610Salfred}
691184610Salfred
692184610Salfredstatic void
693192984Sthompsakue_stop(struct usb_ether *ue)
694184610Salfred{
695194228Sthompsa	struct kue_softc *sc = uether_getsc(ue);
696194228Sthompsa	struct ifnet *ifp = uether_getifp(ue);
697184610Salfred
698188412Sthompsa	KUE_LOCK_ASSERT(sc, MA_OWNED);
699184610Salfred
700188412Sthompsa	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
701184610Salfred
702184610Salfred	/*
703184610Salfred	 * stop all the transfers, if not already stopped:
704184610Salfred	 */
705194228Sthompsa	usbd_transfer_stop(sc->sc_xfer[KUE_BULK_DT_WR]);
706194228Sthompsa	usbd_transfer_stop(sc->sc_xfer[KUE_BULK_DT_RD]);
707184610Salfred}
708