From 2ea70294082a05811858ef49ac9c5c80b5a55b31 Mon Sep 17 00:00:00 2001 From: augustss Date: Mon, 17 Jan 2000 01:38:43 +0000 Subject: [PATCH] Add Bill Paul's FreeBSD driver for the Kawasaki LSI KL5KUSB101B USB Ethernet chip. --- sys/dev/usb/if_kue.c | 1504 +++++++++++++++++++++++++++++++++++++++ sys/dev/usb/if_kuereg.h | 189 +++++ sys/dev/usb/kue_fw.h | 686 ++++++++++++++++++ 3 files changed, 2379 insertions(+) create mode 100644 sys/dev/usb/if_kue.c create mode 100644 sys/dev/usb/if_kuereg.h create mode 100644 sys/dev/usb/kue_fw.h diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c new file mode 100644 index 000000000000..c8f456d14ba0 --- /dev/null +++ b/sys/dev/usb/if_kue.c @@ -0,0 +1,1504 @@ +/* $NetBSD: if_kue.c,v 1.1 2000/01/17 01:38:43 augustss Exp $ */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/usb/if_kue.c,v 1.14 2000/01/14 01:36:15 wpaul Exp $ + */ + +/* + * 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. + * + * Special thanks to Rob Furr for providing an ADS Technologies + * adapter for development and testing. No monkeys were harmed during + * the development of this driver. + */ + +/* + * Ported to NetBSD and somewhat rewritten by Lennart Augustsson. + */ + +/* + * TODO: + * only use kue_do_request for downloading firmware. + * more DPRINTF + * proper cleanup on errors + */ +#if defined(__NetBSD__) || defined(__OpenBSD__) +#include "opt_inet.h" +#include "opt_ns.h" +#include "bpfilter.h" +#include "rnd.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__FreeBSD__) + +#include +#include /* for DELAY */ +#include + +#elif defined(__NetBSD__) || defined(__OpenBSD__) + +#include + +#endif + +#include +#include +#include +#include + +#if defined(__NetBSD__) || defined(__OpenBSD__) +#include + +#define bpf_mtap(ifp, m) bpf_tap((ifp)->if_bpf, mtod((m), caddr_t), (m)->m_len) + +#endif + +#if defined(__FreeBSD__) || NBPFILTER > 0 +#include +#endif + +#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef INET +#include +#include +#endif + +#ifdef NS +#include +#include +#endif +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ + +#include +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#endif + +#include +#include + +#ifdef KUE_DEBUG +#define DPRINTF(x) if (kuedebug) logprintf x +#define DPRINTFN(n,x) if (kuedebug >= (n)) logprintf x +int kuedebug = 0; +#else +#define DPRINTF(x) +#define DPRINTFN(n,x) +#endif + +/* + * Various supported device vendors/products. + */ +static struct kue_type kue_devs[] = { + { USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101 }, + { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT }, + { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T }, + { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101 }, + { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET }, + { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2 }, + { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45 }, + { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250 }, + { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T }, + { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C }, + { USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB }, + { 0, 0 } +}; + +USB_DECLARE_DRIVER(kue); + +static int kue_tx_list_init __P((struct kue_softc *)); +static int kue_rx_list_init __P((struct kue_softc *)); +static int kue_newbuf __P((struct kue_softc *, struct kue_chain *, + struct mbuf *)); +static int kue_send __P((struct kue_softc *, struct mbuf *, int)); +static int kue_open_pipes __P((struct kue_softc *)); +static void kue_rxeof __P((usbd_xfer_handle, + usbd_private_handle, usbd_status)); +static void kue_txeof __P((usbd_xfer_handle, + usbd_private_handle, usbd_status)); +static void kue_start __P((struct ifnet *)); +static int kue_ioctl __P((struct ifnet *, u_long, caddr_t)); +static void kue_init __P((void *)); +static void kue_stop __P((struct kue_softc *)); +static void kue_watchdog __P((struct ifnet *)); + +static void kue_setmulti __P((struct kue_softc *)); +static void kue_reset __P((struct kue_softc *)); + +static usbd_status kue_do_request + __P((usbd_device_handle, + usb_device_request_t *, void *, u_int16_t, + u_int32_t *)); +static usbd_status kue_ctl_l __P((struct kue_softc *, int, u_int8_t, + u_int16_t, char *, u_int32_t, + u_int32_t, u_int32_t *)); +#define kue_ctl(sc, rw, breq, val, data, len) \ + kue_ctl_l(sc, rw, breq, val, data, len, 0, 0) +static usbd_status kue_setword __P((struct kue_softc *, u_int8_t, u_int16_t)); +static int kue_load_fw __P((struct kue_softc *)); + +#if defined(__FreeBSD__) +#ifndef lint +static const char rcsid[] = + "$FreeBSD: src/sys/dev/usb/if_kue.c,v 1.14 2000/01/14 01:36:15 wpaul Exp $"; +#endif + +static void kue_rxstart __P((struct ifnet *)); +static void kue_shutdown __P((device_t)); + +static struct usb_qdat kue_qdat; + +static device_method_t kue_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, kue_match), + DEVMETHOD(device_attach, kue_attach), + DEVMETHOD(device_detach, kue_detach), + DEVMETHOD(device_shutdown, kue_shutdown), + + { 0, 0 } +}; + +static driver_t kue_driver = { + "kue", + kue_methods, + sizeof(struct kue_softc) +}; + +static devclass_t kue_devclass; + +DRIVER_MODULE(if_kue, uhub, kue_driver, kue_devclass, usbd_driver_load, 0); + +#endif /* __FreeBSD__ */ + +/* + * We have a custom do_request function which is almost like the + * regular do_request function, except it has a much longer timeout. + * Why? Because we need to make requests over the control endpoint + * to download the firmware to the device, which can take longer + * than the default timeout. + */ +static usbd_status +kue_do_request(dev, req, data, flags, lenp) + usbd_device_handle dev; + usb_device_request_t *req; + void *data; + u_int16_t flags; + u_int32_t *lenp; +{ + usbd_xfer_handle xfer; + usbd_status err; + + DPRINTFN(15,("kue_do_request: enter\n")); + + xfer = usbd_alloc_xfer(dev); + /* XXX 20000 */ + usbd_setup_default_xfer(xfer, dev, 0, 20000, req, + data, UGETW(req->wLength), flags, 0); + err = usbd_sync_transfer(xfer); + if (lenp != NULL) + usbd_get_xfer_status(xfer, NULL, NULL, lenp, NULL); + usbd_free_xfer(xfer); + + return (err); +} + +static usbd_status +kue_setword(sc, breq, word) + struct kue_softc *sc; + u_int8_t breq; + u_int16_t word; +{ + usb_device_request_t req; + usbd_status err; + int s; + + DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + req.bmRequestType = UT_WRITE_VENDOR_DEVICE; + req.bRequest = breq; + USETW(req.wValue, word); + USETW(req.wIndex, 0); + USETW(req.wLength, 0); + + s = splusb(); + err = kue_do_request(sc->kue_udev, &req, NULL, sc->kue_xfer_flags, 0); + splx(s); + + return (err); +} + +static usbd_status +kue_ctl_l(sc, rw, breq, val, data, len, flags, lenp) + struct kue_softc *sc; + int rw; + u_int8_t breq; + u_int16_t val; + char *data; + u_int32_t len; + u_int32_t flags; + u_int32_t *lenp; +{ + usb_device_request_t req; + usbd_status err; + int s; + + DPRINTFN(10,("%s: %s: enter, len=%d\n", USBDEVNAME(sc->kue_dev), + __FUNCTION__, len)); + + if (rw == KUE_CTL_WRITE) + req.bmRequestType = UT_WRITE_VENDOR_DEVICE; + else + req.bmRequestType = UT_READ_VENDOR_DEVICE; + + req.bRequest = breq; + USETW(req.wValue, val); + USETW(req.wIndex, 0); + USETW(req.wLength, len); + + s = splusb(); + err = kue_do_request(sc->kue_udev, &req, data, + sc->kue_xfer_flags | flags, lenp); + splx(s); + + return (err); +} + +static int +kue_load_fw(sc) + struct kue_softc *sc; +{ + usbd_status err; + u_char eaddr[ETHER_ADDR_LEN]; + u_int32_t alen; + + DPRINTFN(1,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __FUNCTION__)); + + /* + * 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_l(sc, KUE_CTL_READ, KUE_CMD_GET_MAC, 0, (char *)&eaddr, + ETHER_ADDR_LEN, USBD_SHORT_XFER_OK, &alen); + + if (err) { + printf("%s: kue_load_fw: failed to read MAC: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + return (EIO); + } + + if (alen == ETHER_ADDR_LEN) { + printf("%s: warm boot, no firmware download\n", + USBDEVNAME(sc->kue_dev)); + return (0); + } + + printf("%s: cold boot, downloading firmware\n", + USBDEVNAME(sc->kue_dev)); + + /* Load code segment */ + DPRINTFN(1,("%s: kue_load_fw: download code_seg\n", + USBDEVNAME(sc->kue_dev))); + err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, + 0, kue_code_seg, sizeof(kue_code_seg)); + if (err) { + printf("%s: failed to load code segment: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + return (EIO); + } + + /* Load fixup segment */ + DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n", + USBDEVNAME(sc->kue_dev))); + err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, + 0, kue_fix_seg, sizeof(kue_fix_seg)); + if (err) { + printf("%s: failed to load fixup segment: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + return (EIO); + } + + /* Send trigger command. */ + DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n", + USBDEVNAME(sc->kue_dev))); + err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, + 0, kue_trig_seg, sizeof(kue_trig_seg)); + if (err) { + printf("%s: failed to load trigger segment: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + return (EIO); + } + + usbd_delay_ms(sc->kue_udev, 10); + + /* + * Reload device descriptor. + * 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. + */ + (void)usbd_reload_device_desc(sc->kue_udev); + + DPRINTFN(1,("%s: %s: done\n", USBDEVNAME(sc->kue_dev), __FUNCTION__)); + + /* Reset the adapter. */ + kue_reset(sc); + + return (0); +} + +static void +kue_setmulti(sc) + struct kue_softc *sc; +{ + struct ifnet *ifp = GET_IFP(sc); +#if defined(__FreeBSD__) + struct ifmultiaddr *ifma; +#elif defined(__NetBSD__) || defined(__OpenBSD__) + struct ether_multi *enm; + struct ether_multistep step; +#endif + int i; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __FUNCTION__)); + + if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { + sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI; + sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST; + kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); + return; + } + + sc->kue_rxfilt &= ~KUE_RXFILT_ALLMULTI; + + i = 0; +#if defined(__FreeBSD__) + for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; + ifma = ifma->ifma_link.le_next) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + /* + * If there are too many addresses for the + * internal filter, switch over to allmulti mode. + */ + if (i == KUE_MCFILTCNT(sc)) + break; + bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), + KUE_MCFILT(sc, i), ETHER_ADDR_LEN); + i++; + } +#elif defined(__NetBSD__) || defined(__OpenBSD__) + ETHER_FIRST_MULTI(step, &sc->kue_ec, enm); + while (enm != NULL) { + if (i == KUE_MCFILTCNT(sc)) + break; +#if 0 + if (memcmp(enm->enm_addrlo, + enm->enm_addrhi, ETHER_ADDR_LEN) != 0) { + ifp->if_flags |= IFF_ALLMULTI; + /* XXX what now? */ + return; + } +#endif + memcpy(KUE_MCFILT(sc, i), enm->enm_addrlo, ETHER_ADDR_LEN); + ETHER_NEXT_MULTI(step, enm); + i++; + } +#endif + + if (i == KUE_MCFILTCNT(sc)) + sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI; + else { + sc->kue_rxfilt |= KUE_RXFILT_MULTICAST; + kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS, + i, sc->kue_mcfilters, i * ETHER_ADDR_LEN); + } + + kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); +} + +/* + * Issue a SET_CONFIGURATION command to reset the MAC. This should be + * done after the firmware is loaded into the adapter in order to + * bring it into proper operation. + */ +static void +kue_reset(sc) + struct kue_softc *sc; +{ + usbd_status err; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __FUNCTION__)); + + err = usbd_set_config_no(sc->kue_udev, KUE_CONFIG_NO, 0); + if (err) + printf("%s: reset failed\n", USBDEVNAME(sc->kue_dev)); + + /* Wait a little while for the chip to get its brains in order. */ + usbd_delay_ms(sc->kue_udev, 10); +} + +/* + * Probe for a KLSI chip. + */ +USB_MATCH(kue) +{ + USB_MATCH_START(kue, uaa); + struct kue_type *t; + + DPRINTFN(25,("kue_match: enter\n")); + + if (uaa->iface != NULL) + return (UMATCH_NONE); + + for (t = kue_devs; t->kue_vid != 0; t++) + if (uaa->vendor == t->kue_vid && uaa->product == t->kue_did) + return (UMATCH_VENDOR_PRODUCT); + + return (UMATCH_NONE); +} + +/* + * Attach the interface. Allocate softc structures, do + * setup and ethernet/BPF attach. + */ +USB_ATTACH(kue) +{ + USB_ATTACH_START(kue, sc, uaa); + char devinfo[1024]; + int s; + struct ifnet *ifp; + usbd_device_handle dev = uaa->device; + usbd_interface_handle iface; + usbd_status err; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + int i; + +#ifdef __FreeBSD__ + bzero(sc, sizeof(struct kue_softc)); +#endif + + DPRINTFN(5,(" : kue_attach: sc=%p, dev=%p", sc, dev)); + + usbd_devinfo(dev, 0, devinfo); + USB_ATTACH_SETUP; + printf("%s: %s\n", USBDEVNAME(sc->kue_dev), devinfo); + + err = usbd_set_config_no(dev, KUE_CONFIG_NO, 0); + if (err) { + printf("%s: setting config no failed\n", + USBDEVNAME(sc->kue_dev)); + USB_ATTACH_ERROR_RETURN; + } + + sc->kue_udev = dev; + sc->kue_product = uaa->product; + sc->kue_vendor = uaa->vendor; + + /* Load the firmware into the NIC. */ + if (kue_load_fw(sc)) { + printf("%s: loading firmware failed\n", + USBDEVNAME(sc->kue_dev)); + USB_ATTACH_ERROR_RETURN; + } + + err = usbd_device2interface_handle(dev, KUE_IFACE_IDX, &iface); + if (err) { + printf("%s: getting interface handle failed\n", + USBDEVNAME(sc->kue_dev)); + USB_ATTACH_ERROR_RETURN; + } + + sc->kue_iface = iface; + id = usbd_get_interface_descriptor(iface); + + /* Find endpoints. */ + for (i = 0; i < id->bNumEndpoints; i++) { + ed = usbd_interface2endpoint_descriptor(iface, i); + if (ed == NULL) { + printf("%s: couldn't get ep %d\n", + USBDEVNAME(sc->kue_dev), i); + splx(s); + USB_ATTACH_ERROR_RETURN; + } + if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && + (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { + sc->kue_ed[KUE_ENDPT_RX] = ed->bEndpointAddress; + } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && + (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { + sc->kue_ed[KUE_ENDPT_TX] = ed->bEndpointAddress; + } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && + (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { + sc->kue_ed[KUE_ENDPT_INTR] = ed->bEndpointAddress; + } + } + + if (sc->kue_ed[KUE_ENDPT_RX] == 0 || sc->kue_ed[KUE_ENDPT_TX] == 0) { + printf("%s: missing endpoint\n", USBDEVNAME(sc->kue_dev)); + USB_ATTACH_ERROR_RETURN; + } + + /* Read ethernet descriptor */ + err = kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR, + 0, (char *)&sc->kue_desc, sizeof(sc->kue_desc)); + if (err) { + printf("%s: could not read Ethernet descriptor\n", + USBDEVNAME(sc->kue_dev)); + USB_ATTACH_ERROR_RETURN; + } + + sc->kue_mcfilters = malloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, + M_USBDEV, M_NOWAIT); + if (sc->kue_mcfilters == NULL) { + printf("%s: no memory for multicast filter buffer\n", + USBDEVNAME(sc->kue_dev)); + USB_ATTACH_ERROR_RETURN; + } + + sc->kue_xfer_flags = USBD_NO_TSLEEP; + + s = splimp(); + + /* + * A KLSI chip was detected. Inform the world. + */ +#if defined(__FreeBSD__) + printf("%s: Ethernet address: %6D\n", USBDEVNAME(sc->kue_dev), + sc->kue_desc.kue_macaddr, ":"); + + bcopy(sc->kue_desc.kue_macaddr, + (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); + + ifp = GET_IFP(sc); + ifp->if_softc = sc; + ifp->if_unit = sc->kue_unit; + ifp->if_name = "kue"; + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = kue_ioctl; + ifp->if_output = ether_output; + ifp->if_start = kue_start; + ifp->if_watchdog = kue_watchdog; + ifp->if_init = kue_init; + ifp->if_baudrate = 10000000; + ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + + kue_qdat.ifp = ifp; + kue_qdat.if_rxstart = kue_rxstart; + + /* + * Call MI attach routines. + */ + if_attach(ifp); + ether_ifattach(ifp); + bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); + usb_register_netisr(); + +#elif defined(__NetBSD__) || defined(__OpenBSD__) + + printf("%s: Ethernet address %s\n", USBDEVNAME(sc->kue_dev), + ether_sprintf(sc->kue_desc.kue_macaddr)); + + /* Initialize interface info.*/ + ifp = GET_IFP(sc); + ifp->if_softc = sc; + ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = kue_ioctl; + ifp->if_start = kue_start; + ifp->if_watchdog = kue_watchdog; + ifp->if_baudrate = 10000000; + strncpy(ifp->if_xname, USBDEVNAME(sc->kue_dev), IFNAMSIZ); + + /* Attach the interface. */ + if_attach(ifp); + ether_ifattach(ifp, sc->kue_desc.kue_macaddr); + +#if NBPFILTER > 0 + bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, + sizeof(struct ether_header)); +#endif +#if RND > 0 + rnd_attach_source(&sc->rnd_source, USBDEVNAME(sc->kue_dev), + RND_TYPE_NET, 0); +#endif + +#endif /* __NetBSD__ */ + splx(s); + USB_ATTACH_SUCCESS_RETURN; +} + +USB_DETACH(kue) +{ + USB_DETACH_START(kue, sc); +#if defined(__FreeBSD__) + struct ifnet *ifp; + int s; + + s = splusb(); + + sc = device_get_softc(dev); + ifp = GET_IFP(sc); + + if (ifp != NULL) + if_detach(ifp); + + if (sc->kue_ep[KUE_ENDPT_TX] != NULL) + usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]); + if (sc->kue_ep[KUE_ENDPT_RX] != NULL) + usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]); + if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) + usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]); + + if (sc->kue_mcfilters != NULL) + free(sc->kue_mcfilters, M_USBDEV); + + splx(s); + + return (0); +#elif defined(__NetBSD__) || defined(__OpenBSD__) + sc = sc; /* XXX use sc */ + /* XXX deallocate */ + +#ifdef notyet + /* + * Our softc is about to go away, so drop our refernce + * to the ifnet. + */ + if_delref(sc->kue_ec.ec_if); + return (0); +#else + return (EBUSY); +#endif + +#endif +} + +#if defined(__NetBSD__) || defined(__OpenBSD__) +int +kue_activate(self, act) + device_ptr_t self; + enum devact act; +{ + struct kue_softc *sc = (struct kue_softc *)self; + + DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __FUNCTION__)); + + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + break; + + case DVACT_DEACTIVATE: +#ifdef notyet + /* First, kill off the interface. */ + if_detach(sc->kue_ec.ec_if); +#endif + sc->kue_dying = 1; + break; + } + return (0); +} +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ + +/* + * Initialize an RX descriptor and attach an MBUF cluster. + */ +static int +kue_newbuf(sc, c, m) + struct kue_softc *sc; + struct kue_chain *c; + struct mbuf *m; +{ + struct mbuf *m_new = NULL; + + DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + if (m == NULL) { + MGETHDR(m_new, M_DONTWAIT, MT_DATA); + if (m_new == NULL) { + printf("%s: no memory for rx list " + "-- packet dropped!\n", USBDEVNAME(sc->kue_dev)); + return (ENOBUFS); + } + + MCLGET(m_new, M_DONTWAIT); + if (!(m_new->m_flags & M_EXT)) { + printf("%s: no memory for rx list " + "-- packet dropped!\n", USBDEVNAME(sc->kue_dev)); + m_freem(m_new); + return (ENOBUFS); + } + m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; + } else { + m_new = m; + m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; + m_new->m_data = m_new->m_ext.ext_buf; + } + + c->kue_mbuf = m_new; + + return (0); +} + +static int +kue_rx_list_init(sc) + struct kue_softc *sc; +{ + struct kue_cdata *cd; + struct kue_chain *c; + int i; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __FUNCTION__)); + + cd = &sc->kue_cdata; + for (i = 0; i < KUE_RX_LIST_CNT; i++) { + c = &cd->kue_rx_chain[i]; + c->kue_sc = sc; + c->kue_idx = i; + if (kue_newbuf(sc, c, NULL) == ENOBUFS) + return (ENOBUFS); + if (c->kue_xfer == NULL) { + c->kue_xfer = usbd_alloc_xfer(sc->kue_udev); + if (c->kue_xfer == NULL) + return (ENOBUFS); + c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ); + if (c->kue_buf == NULL) + return (ENOBUFS); /* XXX free xfer */ + } + } + + return (0); +} + +static int +kue_tx_list_init(sc) + struct kue_softc *sc; +{ + struct kue_cdata *cd; + struct kue_chain *c; + int i; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev), __FUNCTION__)); + + cd = &sc->kue_cdata; + for (i = 0; i < KUE_TX_LIST_CNT; i++) { + c = &cd->kue_tx_chain[i]; + c->kue_sc = sc; + c->kue_idx = i; + c->kue_mbuf = NULL; + if (c->kue_xfer == NULL) { + c->kue_xfer = usbd_alloc_xfer(sc->kue_udev); + if (c->kue_xfer == NULL) + return (ENOBUFS); + c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ); + if (c->kue_buf == NULL) + return (ENOBUFS); + } + } + + return (0); +} + +#ifdef __FreeBSD__ +static void +kue_rxstart(ifp) + struct ifnet *ifp; +{ + struct kue_softc *sc; + struct kue_chain *c; + + sc = ifp->if_softc; + c = &sc->kue_cdata.kue_rx_chain[sc->kue_cdata.kue_rx_prod]; + + if (kue_newbuf(sc, c, NULL) == ENOBUFS) { + ifp->if_ierrors++; + return; + } + + /* Setup new transfer. */ + usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX], + c, c->kue_buf, KUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, + USBD_NO_TIMEOUT, kue_rxeof); + usbd_transfer(c->kue_xfer); +} +#endif + +/* + * A frame has been uploaded: pass the resulting mbuf chain up to + * the higher level protocols. + */ +static void +kue_rxeof(xfer, priv, status) + usbd_xfer_handle xfer; + usbd_private_handle priv; + usbd_status status; +{ + struct kue_chain *c = priv; + struct kue_softc *sc = c->kue_sc; + struct ifnet *ifp = GET_IFP(sc); + struct mbuf *m; + int total_len = 0; +#if defined(__NetBSD__) || defined(__OpenBSD__) + int s; +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ + + DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->kue_dev), + __FUNCTION__, status)); + + if (!(ifp->if_flags & IFF_RUNNING)) + return; + + if (status != USBD_NORMAL_COMPLETION) { + if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) + return; + printf("%s: usb error on rx: %s\n", USBDEVNAME(sc->kue_dev), + usbd_errstr(status)); + if (status == USBD_STALLED) + usbd_clear_endpoint_stall(sc->kue_ep[KUE_ENDPT_RX]); + goto done; + } + + usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); + + DPRINTFN(10,("%s: %s: total_len=%d len=%d\n", USBDEVNAME(sc->kue_dev), + __FUNCTION__, total_len, + UGETW(mtod(c->kue_mbuf, u_int8_t *)))); + + m = c->kue_mbuf; + if (total_len <= 1) + goto done; + + /* copy data to mbuf */ + memcpy(mtod(m, char*), c->kue_buf, total_len); + + /* No errors; receive the packet. */ + total_len = UGETW(mtod(m, u_int8_t *)); + m_adj(m, sizeof(u_int16_t)); + + if (total_len < sizeof(struct ether_header)) { + ifp->if_ierrors++; + goto done; + } + + ifp->if_ipackets++; + m->m_pkthdr.len = m->m_len = total_len; + +#if defined(__FreeBSD__) + m->m_pkthdr.rcvif = (struct ifnet *)&kue_qdat; + /* Put the packet on the special USB input queue. */ + usb_ether_input(m); + + return; + +#elif defined(__NetBSD__) || defined(__OpenBSD__) + m->m_pkthdr.rcvif = ifp; + + s = splimp(); + + /* XXX ugly */ + if (kue_newbuf(sc, c, NULL) == ENOBUFS) { + ifp->if_ierrors++; + goto done1; + } + + /* + * Handle BPF listeners. Let the BPF user see the packet, but + * don't pass it up to the ether_input() layer unless it's + * a broadcast packet, multicast packet, matches our ethernet + * address or the interface is in promiscuous mode. + */ + if (ifp->if_bpf) { + struct ether_header *eh = mtod(m, struct ether_header *); + bpf_mtap(ifp, m); + if ((ifp->if_flags & IFF_PROMISC) && + memcmp(eh->ether_dhost, LLADDR(ifp->if_sadl), + ETHER_ADDR_LEN) && + !(eh->ether_dhost[0] & 1)) { + m_freem(m); + goto done1; + } + } + + DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->kue_dev), + __FUNCTION__, m->m_len)); + (*ifp->if_input)(ifp, m); + done1: + splx(s); +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ + + done: + + /* Setup new transfer. */ + usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX], + c, c->kue_buf, KUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, + USBD_NO_TIMEOUT, kue_rxeof); + usbd_transfer(c->kue_xfer); + + DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->kue_dev), + __FUNCTION__)); +} + +/* + * A frame was downloaded to the chip. It's safe for us to clean up + * the list buffers. + */ + +static void +kue_txeof(xfer, priv, status) + usbd_xfer_handle xfer; + usbd_private_handle priv; + usbd_status status; +{ + struct kue_chain *c = priv; + struct kue_softc *sc = c->kue_sc; + struct ifnet *ifp = GET_IFP(sc); + int s; + + s = splimp(); + + DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->kue_dev), + __FUNCTION__, status)); + + ifp->if_timer = 0; + ifp->if_flags &= ~IFF_OACTIVE; + + if (status != USBD_NORMAL_COMPLETION) { + if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { + splx(s); + return; + } + ifp->if_oerrors++; + printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->kue_dev), + usbd_errstr(status)); + if (status == USBD_STALLED) + usbd_clear_endpoint_stall(sc->kue_ep[KUE_ENDPT_TX]); + splx(s); + return; + } + + ifp->if_opackets++; + +#if defined(__FreeBSD__) + c->kue_mbuf->m_pkthdr.rcvif = ifp; + usb_tx_done(c->kue_mbuf); + c->kue_mbuf = NULL; +#elif defined(__NetBSD__) || defined(__OpenBSD__) + m_freem(c->kue_mbuf); + c->kue_mbuf = NULL; + + if (ifp->if_snd.ifq_head != NULL) + kue_start(ifp); +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ + + splx(s); +} + +static int +kue_send(sc, m, idx) + struct kue_softc *sc; + struct mbuf *m; + int idx; +{ + int total_len; + struct kue_chain *c; + usbd_status err; + + DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + c = &sc->kue_cdata.kue_tx_chain[idx]; + + /* + * Copy the mbuf data into a contiguous buffer, leaving two + * bytes at the beginning to hold the frame length. + */ + m_copydata(m, 0, m->m_pkthdr.len, c->kue_buf + 2); + c->kue_mbuf = m; + + total_len = m->m_pkthdr.len + 2; + /* XXX what's this? */ + total_len += 64 - (total_len % 64); + + /* Frame length is specified in the first 2 bytes of the buffer. */ + c->kue_buf[0] = (u_int8_t)m->m_pkthdr.len; + c->kue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8); + + /* XXX 10000 */ + usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_TX], + c, c->kue_buf, total_len, USBD_NO_COPY, 10000, kue_txeof); + + /* Transmit */ + err = usbd_transfer(c->kue_xfer); + if (err != USBD_IN_PROGRESS) { + kue_stop(sc); + return (EIO); + } + + sc->kue_cdata.kue_tx_cnt++; + + return (0); +} + +static void +kue_start(ifp) + struct ifnet *ifp; +{ + struct kue_softc *sc = ifp->if_softc; + struct mbuf *m_head = NULL; + + DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + if (ifp->if_flags & IFF_OACTIVE) + return; + + IF_DEQUEUE(&ifp->if_snd, m_head); + if (m_head == NULL) + return; + + if (kue_send(sc, m_head, 0)) { + IF_PREPEND(&ifp->if_snd, m_head); + ifp->if_flags |= IFF_OACTIVE; + return; + } + + /* + * If there's a BPF listener, bounce a copy of this frame + * to him. + */ + if (ifp->if_bpf) + bpf_mtap(ifp, m_head); + + ifp->if_flags |= IFF_OACTIVE; + + /* + * Set a timeout in case the chip goes out to lunch. + */ + ifp->if_timer = 5; +} + +static void +kue_init(xsc) + void *xsc; +{ + struct kue_softc *sc = xsc; + struct ifnet *ifp = GET_IFP(sc); + int s; + u_char *eaddr; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + if (ifp->if_flags & IFF_RUNNING) + return; + + s = splimp(); + +#if defined(__FreeBSD__) + eaddr = sc->arpcom.ac_enaddr; +#elif defined(__NetBSD__) || defined(__OpenBSD__) + eaddr = LLADDR(ifp->if_sadl); +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ + /* Set MAC address */ + kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MAC, 0, eaddr, ETHER_ADDR_LEN); + + sc->kue_rxfilt = KUE_RXFILT_UNICAST | KUE_RXFILT_BROADCAST; + + /* If we want promiscuous mode, set the allframes bit. */ + if (ifp->if_flags & IFF_PROMISC) + sc->kue_rxfilt |= KUE_RXFILT_PROMISC; + + kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt); + + /* I'm not sure how to tune these. */ +#if 0 + /* + * Leave this one alone for now; setting it + * wrong causes lockups on some machines/controllers. + */ + kue_setword(sc, KUE_CMD_SET_SOFS, 1); +#endif + kue_setword(sc, KUE_CMD_SET_URB_SIZE, 64); + + /* Init TX ring. */ + if (kue_tx_list_init(sc) == ENOBUFS) { + printf("%s: tx list init failed\n", USBDEVNAME(sc->kue_dev)); + splx(s); + return; + } + + /* Init RX ring. */ + if (kue_rx_list_init(sc) == ENOBUFS) { + printf("%s: rx list init failed\n", USBDEVNAME(sc->kue_dev)); + splx(s); + return; + } + + /* Load the multicast filter. */ + kue_setmulti(sc); + + if (sc->kue_ep[KUE_ENDPT_RX] == NULL) { + if (kue_open_pipes(sc)) { + splx(s); + return; + } + } + + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + splx(s); +} + +static int +kue_open_pipes(sc) + struct kue_softc *sc; +{ + usbd_status err; + struct kue_chain *c; + int i; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + /* Open RX and TX pipes. */ + err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_RX], + USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_RX]); + if (err) { + printf("%s: open rx pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + return (EIO); + } + + err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_TX], + USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_TX]); + if (err) { + printf("%s: open tx pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + return (EIO); + } + + /* Start up the receive pipe. */ + for (i = 0; i < KUE_RX_LIST_CNT; i++) { + c = &sc->kue_cdata.kue_rx_chain[i]; + usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX], + c, c->kue_buf, KUE_BUFSZ, + USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, + kue_rxeof); + usbd_transfer(c->kue_xfer); + DPRINTFN(5,("%s: %s: start read\n", USBDEVNAME(sc->kue_dev), + __FUNCTION__)); + } + + return (0); +} + +static int +kue_ioctl(ifp, command, data) + struct ifnet *ifp; + u_long command; + caddr_t data; +{ + struct kue_softc *sc = ifp->if_softc; +#if defined(__NetBSD__) || defined(__OpenBSD__) + struct ifaddr *ifa = (struct ifaddr *)data; + struct ifreq *ifr = (struct ifreq *)data; +#endif + int s, error = 0; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + s = splimp(); + + switch(command) { +#if defined(__FreeBSD__) + case SIOCSIFADDR: + case SIOCGIFADDR: + case SIOCSIFMTU: + error = ether_ioctl(ifp, command, data); + break; +#elif defined(__NetBSD__) || defined(__OpenBSD__) + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + kue_init(sc); + + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + arp_ifinit(ifp, ifa); + break; +#endif /* INET */ +#ifdef NS + case AF_NS: + { + struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; + + if (ns_nullhost(*ina)) + ina->x_host = *(union ns_host *) + LLADDR(ifp->if_sadl); + else + memcpy(LLADDR(ifp->if_sadl), + ina->x_host.c_host, + ifp->if_addrlen); + break; + } +#endif /* NS */ + } + break; + + case SIOCSIFMTU: + if (ifr->ifr_mtu > ETHERMTU) + error = EINVAL; + else + ifp->if_mtu = ifr->ifr_mtu; + break; + +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ + + case SIOCSIFFLAGS: + if (ifp->if_flags & IFF_UP) { + if (ifp->if_flags & IFF_RUNNING && + ifp->if_flags & IFF_PROMISC && + !(sc->kue_if_flags & IFF_PROMISC)) { + sc->kue_rxfilt |= KUE_RXFILT_PROMISC; + kue_setword(sc, KUE_CMD_SET_PKT_FILTER, + sc->kue_rxfilt); + } else if (ifp->if_flags & IFF_RUNNING && + !(ifp->if_flags & IFF_PROMISC) && + sc->kue_if_flags & IFF_PROMISC) { + sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC; + kue_setword(sc, KUE_CMD_SET_PKT_FILTER, + sc->kue_rxfilt); + } else if (!(ifp->if_flags & IFF_RUNNING)) + kue_init(sc); + } else { + if (ifp->if_flags & IFF_RUNNING) + kue_stop(sc); + } + sc->kue_if_flags = ifp->if_flags; + error = 0; + break; + case SIOCADDMULTI: + case SIOCDELMULTI: + kue_setmulti(sc); + error = 0; + break; + default: + error = EINVAL; + break; + } + + splx(s); + + return (error); +} + +static void +kue_watchdog(ifp) + struct ifnet *ifp; +{ + struct kue_softc *sc = ifp->if_softc; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + ifp->if_oerrors++; + printf("%s: watchdog timeout\n", USBDEVNAME(sc->kue_dev)); + + /* + * The polling business is a kludge to avoid allowing the + * USB code to call tsleep() in usbd_delay_ms(), which will + * kill us since the watchdog routine is invoked from + * interrupt context. + */ + usbd_set_polling(sc->kue_udev, 1); + kue_stop(sc); + kue_init(sc); + usbd_set_polling(sc->kue_udev, 0); + + if (ifp->if_snd.ifq_head != NULL) + kue_start(ifp); +} + +/* + * Stop the adapter and free any mbufs allocated to the + * RX and TX lists. + */ +static void +kue_stop(sc) + struct kue_softc *sc; +{ + usbd_status err; + struct ifnet *ifp; + int i; + + DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->kue_dev),__FUNCTION__)); + + ifp = GET_IFP(sc); + ifp->if_timer = 0; + + /* Stop transfers. */ + if (sc->kue_ep[KUE_ENDPT_RX] != NULL) { + err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]); + if (err) { + printf("%s: abort rx pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + } + err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_RX]); + if (err) { + printf("%s: close rx pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + } + sc->kue_ep[KUE_ENDPT_RX] = NULL; + } + + if (sc->kue_ep[KUE_ENDPT_TX] != NULL) { + err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]); + if (err) { + printf("%s: abort tx pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + } + err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_TX]); + if (err) { + printf("%s: close tx pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + } + sc->kue_ep[KUE_ENDPT_TX] = NULL; + } + + if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) { + err = usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]); + if (err) { + printf("%s: abort intr pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + } + err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_INTR]); + if (err) { + printf("%s: close intr pipe failed: %s\n", + USBDEVNAME(sc->kue_dev), usbd_errstr(err)); + } + sc->kue_ep[KUE_ENDPT_INTR] = NULL; + } + + /* Free RX resources. */ + for (i = 0; i < KUE_RX_LIST_CNT; i++) { + if (sc->kue_cdata.kue_rx_chain[i].kue_buf != NULL) { + sc->kue_cdata.kue_rx_chain[i].kue_buf = NULL; + } + if (sc->kue_cdata.kue_rx_chain[i].kue_mbuf != NULL) { + m_freem(sc->kue_cdata.kue_rx_chain[i].kue_mbuf); + sc->kue_cdata.kue_rx_chain[i].kue_mbuf = NULL; + } + if (sc->kue_cdata.kue_rx_chain[i].kue_xfer != NULL) { + usbd_free_xfer(sc->kue_cdata.kue_rx_chain[i].kue_xfer); + sc->kue_cdata.kue_rx_chain[i].kue_xfer = NULL; + } + } + + /* Free TX resources. */ + for (i = 0; i < KUE_TX_LIST_CNT; i++) { + if (sc->kue_cdata.kue_tx_chain[i].kue_buf != NULL) { + sc->kue_cdata.kue_tx_chain[i].kue_buf = NULL; + } + if (sc->kue_cdata.kue_tx_chain[i].kue_mbuf != NULL) { + m_freem(sc->kue_cdata.kue_tx_chain[i].kue_mbuf); + sc->kue_cdata.kue_tx_chain[i].kue_mbuf = NULL; + } + if (sc->kue_cdata.kue_tx_chain[i].kue_xfer != NULL) { + usbd_free_xfer(sc->kue_cdata.kue_tx_chain[i].kue_xfer); + sc->kue_cdata.kue_tx_chain[i].kue_xfer = NULL; + } + } + + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); +} + +#ifdef __FreeBSD__ +/* + * Stop all chip I/O so that the kernel's probe routines don't + * get confused by errant DMAs when rebooting. + */ +static void +kue_shutdown(dev) + device_t dev; +{ + struct kue_softc *sc; + + sc = device_get_softc(dev); + + kue_stop(sc); +} +#endif diff --git a/sys/dev/usb/if_kuereg.h b/sys/dev/usb/if_kuereg.h new file mode 100644 index 000000000000..2d31faf7c28d --- /dev/null +++ b/sys/dev/usb/if_kuereg.h @@ -0,0 +1,189 @@ +/* $NetBSD: if_kuereg.h,v 1.1 2000/01/17 01:38:43 augustss Exp $ */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/usb/if_kuereg.h,v 1.2 2000/01/06 07:39:07 wpaul Exp $ + */ + +/* + * Definitions for the KLSI KL5KUSB101B USB to ethernet controller. + * The KLSI part is controlled via vendor control requests, the structure + * of which depend a bit on the firmware running on the internal + * microcontroller. The one exception is the 'send scan data' command, + * which is used to load the firmware. + */ + +#define KUE_CONFIG_NO 1 +#define KUE_IFACE_IDX 0 + +#define KUE_CMD_GET_ETHER_DESCRIPTOR 0x00 +#define KUE_CMD_SET_MCAST_FILTERS 0x01 +#define KUE_CMD_SET_PKT_FILTER 0x02 +#define KUE_CMD_GET_ETHERSTATS 0x03 +#define KUE_CMD_GET_GPIO 0x04 +#define KUE_CMD_SET_GPIO 0x05 +#define KUE_CMD_SET_MAC 0x06 +#define KUE_CMD_GET_MAC 0x07 +#define KUE_CMD_SET_URB_SIZE 0x08 +#define KUE_CMD_SET_SOFS 0x09 +#define KUE_CMD_SET_EVEN_PKTS 0x0A +#define KUE_CMD_SEND_SCAN 0xFF + +struct kue_ether_desc { + u_int8_t kue_len; + u_int8_t kue_rsvd0; + u_int8_t kue_rsvd1; + u_int8_t kue_macaddr[ETHER_ADDR_LEN]; + u_int8_t kue_etherstats[4]; + u_int8_t kue_maxseg[2]; + u_int8_t kue_mcastfilt[2]; + u_int8_t kue_rsvd2; +}; + +#define KUE_ETHERSTATS(x) \ + (*(u_int32_t *)&(x)->kue_desc.kue_etherstats) +#define KUE_MAXSEG(x) \ + (*(u_int16_t *)&(x)->kue_desc.kue_maxseg) +#define KUE_MCFILTCNT(x) \ + ((*(u_int16_t *)&(x)->kue_desc.kue_mcastfilt) & 0x7FFF) +#define KUE_MCFILT(x, y) \ + (char *)&(sc->kue_mcfilters[y * ETHER_ADDR_LEN]) + +#define KUE_STAT_TX_OK 0x00000001 +#define KUE_STAT_RX_OK 0x00000002 +#define KUE_STAT_TX_ERR 0x00000004 +#define KUE_STAT_RX_ERR 0x00000008 +#define KUE_STAT_RX_NOBUF 0x00000010 +#define KUE_STAT_TX_UCAST_BYTES 0x00000020 +#define KUE_STAT_TX_UCAST_FRAMES 0x00000040 +#define KUE_STAT_TX_MCAST_BYTES 0x00000080 +#define KUE_STAT_TX_MCAST_FRAMES 0x00000100 +#define KUE_STAT_TX_BCAST_BYTES 0x00000200 +#define KUE_STAT_TX_BCAST_FRAMES 0x00000400 +#define KUE_STAT_RX_UCAST_BYTES 0x00000800 +#define KUE_STAT_RX_UCAST_FRAMES 0x00001000 +#define KUE_STAT_RX_MCAST_BYTES 0x00002000 +#define KUE_STAT_RX_MCAST_FRAMES 0x00004000 +#define KUE_STAT_RX_BCAST_BYTES 0x00008000 +#define KUE_STAT_RX_BCAST_FRAMES 0x00010000 +#define KUE_STAT_RX_CRCERR 0x00020000 +#define KUE_STAT_TX_QUEUE_LENGTH 0x00040000 +#define KUE_STAT_RX_ALIGNERR 0x00080000 +#define KUE_STAT_TX_SINGLECOLL 0x00100000 +#define KUE_STAT_TX_MULTICOLL 0x00200000 +#define KUE_STAT_TX_DEFERRED 0x00400000 +#define KUE_STAT_TX_MAXCOLLS 0x00800000 +#define KUE_STAT_RX_OVERRUN 0x01000000 +#define KUE_STAT_TX_UNDERRUN 0x02000000 +#define KUE_STAT_TX_SQE_ERR 0x04000000 +#define KUE_STAT_TX_CARRLOSS 0x08000000 +#define KUE_STAT_RX_LATECOLL 0x10000000 + +#define KUE_RXFILT_PROMISC 0x0001 +#define KUE_RXFILT_ALLMULTI 0x0002 +#define KUE_RXFILT_UNICAST 0x0004 +#define KUE_RXFILT_BROADCAST 0x0008 +#define KUE_RXFILT_MULTICAST 0x0010 + +#define KUE_TIMEOUT 1000 +#define ETHER_ALIGN 2 +#define KUE_BUFSZ 1536 +#define KUE_CUTOFF 1088 +#define KUE_MIN_FRAMELEN 60 + +#define KUE_RX_LIST_CNT 1 +#define KUE_TX_LIST_CNT 1 + +#define KUE_CTL_READ 0x01 +#define KUE_CTL_WRITE 0x02 + +/* + * The interrupt endpoint is currently unused + * by the KLSI part. + */ +#define KUE_ENDPT_RX 0x0 +#define KUE_ENDPT_TX 0x1 +#define KUE_ENDPT_INTR 0x2 +#define KUE_ENDPT_MAX 0x3 + +struct kue_type { + u_int16_t kue_vid; + u_int16_t kue_did; +}; + +struct kue_softc; + +struct kue_chain { + struct kue_softc *kue_sc; + usbd_xfer_handle kue_xfer; + char *kue_buf; + struct mbuf *kue_mbuf; + int kue_idx; +}; + +struct kue_cdata { + struct kue_chain kue_tx_chain[KUE_TX_LIST_CNT]; + struct kue_chain kue_rx_chain[KUE_RX_LIST_CNT]; + int kue_tx_prod; + int kue_tx_cons; + int kue_tx_cnt; + int kue_rx_prod; +}; + +#define KUE_INC(x, y) (x) = (x + 1) % y + +struct kue_softc { + USBBASEDEVICE kue_dev; + +#if defined(__FreeBSD__) + struct arpcom arpcom; + struct callout_handle kue_stat_ch; +#define GET_IFP(sc) (&(sc)->arpcom.ac_if) +#elif defined(__NetBSD__) + struct ethercom kue_ec; + char kue_dying; +#define GET_IFP(sc) (&(sc)->kue_ec.ec_if) +#endif + + u_int16_t kue_xfer_flags; + + usbd_device_handle kue_udev; + usbd_interface_handle kue_iface; + u_int16_t kue_vendor; + u_int16_t kue_product; + struct kue_ether_desc kue_desc; + int kue_ed[KUE_ENDPT_MAX]; + usbd_pipe_handle kue_ep[KUE_ENDPT_MAX]; + int kue_if_flags; + u_int16_t kue_rxfilt; + u_int8_t *kue_mcfilters; + struct kue_cdata kue_cdata; +}; diff --git a/sys/dev/usb/kue_fw.h b/sys/dev/usb/kue_fw.h new file mode 100644 index 000000000000..7903ecfb305c --- /dev/null +++ b/sys/dev/usb/kue_fw.h @@ -0,0 +1,686 @@ +/* $NetBSD: kue_fw.h,v 1.1 2000/01/17 01:38:43 augustss Exp $ */ +/* + * Copyright (c) 1997, 1998, 1999, 2000 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/usb/kue_fw.h,v 1.1 2000/01/05 04:27:07 wpaul Exp $ + */ + +/* + * This file contains the firmware needed to make the KLSI chip work, + * along with a few constants related to the QT Engine microcontroller + * embedded in the KLSI part. + * + * Firmware is loaded using the vendor-specific 'send scan data' + * command (0xFF). The basic operation is that we must load the + * firmware, then issue some trigger commands to fix it up and start + * it running. There are three transfers: load the binary code, + * load the 'fixup' (data segment?), then issue a command to + * start the code firmware running. The data itself is prefixed by + * a 16-bit signature word, a 16-bit length value, a type byte + * and an interrupt (command) byte. The code segment is of type + * 0x02 (replacement interrupt vector data) and the fixup segment + * is of type 0x03 (replacement interrupt fixup data). The interrupt + * code is 0x64 (load new code). The length word is the total length + * of the segment minus 7. I precomputed the values and stuck them + * into the appropriate locations within the segments to save some + * work in the driver. + */ + +/* QT controller data block types. */ +/* Write data into specific memory location. */ +#define KUE_QTBTYPE_WRITE_DATA 0x00 +/* Write data into interrupt vector location */ +#define KUE_QTBTYPE_WRITE_INTVEC 0x01 +/* Replace interrupt vector with this data */ +#define KUE_QTBTYPE_REPL_INTVEC 0x02 +/* Fixup interrupt vector code with this data */ +#define KUE_QTBTYPE_FIXUP_INTVEC 0x03 +/* Force jump to location */ +#define KUE_QTBTYPE_JUMP 0x04 +/* Force call to location */ +#define KUE_QTBTYPE_CALL 0x05 +/* Force interrupt call */ +#define KUE_QTBTYPE_CALLINTR 0x06 +/* + * Cause data to be written using the specified QT engine + * interrupt, from starting location in memory for a specified + * number of bytes. + */ +#define KUE_QTBTYPE_WRITE_WITH_INTR 0x07 +/* Cause data from stream to be written using specified QT interrupt. */ +#define KUE_QTBTYPE_WRITE_STR_WITH_INTR 0x08 +/* Cause data to be written to config locations. */ +/* Addresses assume 0xc000 offset. */ +#define KUE_QTBTYPE_WRITE_CONFIG 0x09 + +#define KUE_QTINTR_LOAD_CODE 0x64 +#define KUE_QTINTR_TRIGGER_CODE 0x3B +#define KUE_QTINTR_LOAD_CODE_HIGH 0x9C + +/* Firmware code segment */ +static unsigned char kue_code_seg[] = +{ + /******************************************/ + /* NOTE: B6/C3 is data header signature */ + /* 0xAA/0xBB is data length = total */ + /* bytes - 7, 0xCC is type, 0xDD is */ + /* interrupt to use. */ + /******************************************/ + 0xB6, 0xC3, 0xf7, 0x0e, 0x02, 0x64, + 0x9f, 0xcf, 0xbc, 0x08, 0xe7, 0x57, 0x00, 0x00, + 0x9a, 0x08, 0x97, 0xc1, 0xe7, 0x67, 0xff, 0x1f, + 0x28, 0xc0, 0xe7, 0x87, 0x00, 0x04, 0x24, 0xc0, + 0xe7, 0x67, 0xff, 0xf9, 0x22, 0xc0, 0x97, 0xcf, + 0xe7, 0x09, 0xa2, 0xc0, 0x94, 0x08, 0xd7, 0x09, + 0x00, 0xc0, 0xe7, 0x59, 0xba, 0x08, 0x94, 0x08, + 0x03, 0xc1, 0xe7, 0x67, 0xff, 0xf7, 0x24, 0xc0, + 0xe7, 0x05, 0x00, 0xc0, 0xa7, 0xcf, 0x92, 0x08, + 0xe7, 0x57, 0x00, 0x00, 0x8e, 0x08, 0xa7, 0xa1, + 0x8e, 0x08, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, + 0xf2, 0x09, 0x0a, 0xc0, 0xe7, 0x57, 0x00, 0x00, + 0xa4, 0xc0, 0xa7, 0xc0, 0x56, 0x08, 0x9f, 0xaf, + 0x70, 0x09, 0xe7, 0x07, 0x00, 0x00, 0xf2, 0x09, + 0xe7, 0x57, 0xff, 0xff, 0x90, 0x08, 0x9f, 0xa0, + 0x40, 0x00, 0xe7, 0x59, 0x90, 0x08, 0x94, 0x08, + 0x9f, 0xa0, 0x40, 0x00, 0xc8, 0x09, 0xa2, 0x08, + 0x08, 0x62, 0x9f, 0xa1, 0x14, 0x0a, 0xe7, 0x57, + 0x00, 0x00, 0x52, 0x08, 0xa7, 0xc0, 0x56, 0x08, + 0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x57, 0x00, 0x00, + 0x8e, 0x08, 0xa7, 0xc1, 0x56, 0x08, 0xc0, 0x09, + 0xa8, 0x08, 0x00, 0x60, 0x05, 0xc4, 0xc0, 0x59, + 0x94, 0x08, 0x02, 0xc0, 0x9f, 0xaf, 0xee, 0x00, + 0xe7, 0x59, 0xae, 0x08, 0x94, 0x08, 0x02, 0xc1, + 0x9f, 0xaf, 0xf6, 0x00, 0x9f, 0xaf, 0x9e, 0x03, + 0xef, 0x57, 0x00, 0x00, 0xf0, 0x09, 0x9f, 0xa1, + 0xde, 0x01, 0xe7, 0x57, 0x00, 0x00, 0x78, 0x08, + 0x9f, 0xa0, 0xe4, 0x03, 0x9f, 0xaf, 0x2c, 0x04, + 0xa7, 0xcf, 0x56, 0x08, 0x48, 0x02, 0xe7, 0x09, + 0x94, 0x08, 0xa8, 0x08, 0xc8, 0x37, 0x04, 0x00, + 0x9f, 0xaf, 0x68, 0x04, 0x97, 0xcf, 0xe7, 0x57, + 0x00, 0x00, 0xa6, 0x08, 0x97, 0xc0, 0xd7, 0x09, + 0x00, 0xc0, 0xc1, 0xdf, 0xc8, 0x09, 0x9c, 0x08, + 0x08, 0x62, 0x1d, 0xc0, 0x27, 0x04, 0x9c, 0x08, + 0x10, 0x94, 0xf0, 0x07, 0xee, 0x09, 0x02, 0x00, + 0xc1, 0x07, 0x01, 0x00, 0x70, 0x00, 0x04, 0x00, + 0xf0, 0x07, 0x44, 0x01, 0x06, 0x00, 0x50, 0xaf, + 0xe7, 0x09, 0x94, 0x08, 0xae, 0x08, 0xe7, 0x17, + 0x14, 0x00, 0xae, 0x08, 0xe7, 0x67, 0xff, 0x07, + 0xae, 0x08, 0xe7, 0x07, 0xff, 0xff, 0xa8, 0x08, + 0xe7, 0x07, 0x00, 0x00, 0xa6, 0x08, 0xe7, 0x05, + 0x00, 0xc0, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, + 0xc1, 0xdf, 0x48, 0x02, 0xd0, 0x09, 0x9c, 0x08, + 0x27, 0x02, 0x9c, 0x08, 0xe7, 0x09, 0x20, 0xc0, + 0xee, 0x09, 0xe7, 0xd0, 0xee, 0x09, 0xe7, 0x05, + 0x00, 0xc0, 0x97, 0xcf, 0x48, 0x02, 0xc8, 0x37, + 0x04, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x60, + 0x21, 0xc0, 0xc0, 0x37, 0x3e, 0x00, 0x23, 0xc9, + 0xc0, 0x57, 0xb4, 0x05, 0x1b, 0xc8, 0xc0, 0x17, + 0x3f, 0x00, 0xc0, 0x67, 0xc0, 0xff, 0x30, 0x00, + 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x02, 0xc0, 0x17, 0x4c, 0x00, 0x30, 0x00, + 0x06, 0x00, 0xf0, 0x07, 0xbe, 0x01, 0x0a, 0x00, + 0x48, 0x02, 0xc1, 0x07, 0x02, 0x00, 0xd7, 0x09, + 0x00, 0xc0, 0xc1, 0xdf, 0x51, 0xaf, 0xe7, 0x05, + 0x00, 0xc0, 0x97, 0xcf, 0x9f, 0xaf, 0x68, 0x04, + 0x9f, 0xaf, 0xe4, 0x03, 0x97, 0xcf, 0x9f, 0xaf, + 0xe4, 0x03, 0xc9, 0x37, 0x04, 0x00, 0xc1, 0xdf, + 0xc8, 0x09, 0x70, 0x08, 0x50, 0x02, 0x67, 0x02, + 0x70, 0x08, 0xd1, 0x07, 0x00, 0x00, 0xc0, 0xdf, + 0x9f, 0xaf, 0xde, 0x01, 0x97, 0xcf, 0xe7, 0x57, + 0x00, 0x00, 0xaa, 0x08, 0x97, 0xc1, 0xe7, 0x57, + 0x01, 0x00, 0x7a, 0x08, 0x97, 0xc0, 0xc8, 0x09, + 0x6e, 0x08, 0x08, 0x62, 0x97, 0xc0, 0x00, 0x02, + 0xc0, 0x17, 0x0e, 0x00, 0x27, 0x00, 0x34, 0x01, + 0x27, 0x0c, 0x0c, 0x00, 0x36, 0x01, 0xef, 0x57, + 0x00, 0x00, 0xf0, 0x09, 0x9f, 0xc0, 0xbe, 0x02, + 0xe7, 0x57, 0x00, 0x00, 0xb0, 0x08, 0x97, 0xc1, + 0xe7, 0x07, 0x09, 0x00, 0x12, 0xc0, 0xe7, 0x77, + 0x00, 0x08, 0x20, 0xc0, 0x9f, 0xc1, 0xb6, 0x02, + 0xe7, 0x57, 0x09, 0x00, 0x12, 0xc0, 0x77, 0xc9, + 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x77, + 0x00, 0x08, 0x20, 0xc0, 0x2f, 0xc1, 0xe7, 0x07, + 0x00, 0x00, 0x42, 0xc0, 0xe7, 0x07, 0x05, 0x00, + 0x90, 0xc0, 0xc8, 0x07, 0x0a, 0x00, 0xe7, 0x77, + 0x04, 0x00, 0x20, 0xc0, 0x09, 0xc1, 0x08, 0xda, + 0x7a, 0xc1, 0xe7, 0x07, 0x00, 0x01, 0x42, 0xc0, + 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, 0x1a, 0xcf, + 0xe7, 0x07, 0x01, 0x00, 0x7a, 0x08, 0x00, 0xd8, + 0x27, 0x50, 0x34, 0x01, 0x17, 0xc1, 0xe7, 0x77, + 0x02, 0x00, 0x20, 0xc0, 0x79, 0xc1, 0x27, 0x50, + 0x34, 0x01, 0x10, 0xc1, 0xe7, 0x77, 0x02, 0x00, + 0x20, 0xc0, 0x79, 0xc0, 0x9f, 0xaf, 0xd8, 0x02, + 0xe7, 0x05, 0x00, 0xc0, 0x00, 0x60, 0x9f, 0xc0, + 0xde, 0x01, 0x97, 0xcf, 0xe7, 0x07, 0x01, 0x00, + 0xb8, 0x08, 0x06, 0xcf, 0xe7, 0x07, 0x30, 0x0e, + 0x02, 0x00, 0xe7, 0x07, 0x50, 0xc3, 0x12, 0xc0, + 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0xe7, 0x07, + 0x01, 0x00, 0xb8, 0x08, 0x97, 0xcf, 0xe7, 0x07, + 0x50, 0xc3, 0x12, 0xc0, 0xe7, 0x07, 0x30, 0x0e, + 0x02, 0x00, 0xe7, 0x07, 0x01, 0x00, 0x7a, 0x08, + 0xe7, 0x07, 0x05, 0x00, 0x90, 0xc0, 0x97, 0xcf, + 0xe7, 0x07, 0x00, 0x01, 0x42, 0xc0, 0xe7, 0x07, + 0x04, 0x00, 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x00, + 0x7a, 0x08, 0xe7, 0x57, 0x0f, 0x00, 0xb2, 0x08, + 0x13, 0xc1, 0x9f, 0xaf, 0x2e, 0x08, 0xca, 0x09, + 0xac, 0x08, 0xf2, 0x17, 0x01, 0x00, 0x5c, 0x00, + 0xf2, 0x27, 0x00, 0x00, 0x5e, 0x00, 0xe7, 0x07, + 0x00, 0x00, 0xb2, 0x08, 0xe7, 0x07, 0x01, 0x00, + 0xb4, 0x08, 0xc0, 0x07, 0xff, 0xff, 0x97, 0xcf, + 0x9f, 0xaf, 0x4c, 0x03, 0xc0, 0x69, 0xb4, 0x08, + 0x57, 0x00, 0x9f, 0xde, 0x33, 0x00, 0xc1, 0x05, + 0x27, 0xd8, 0xb2, 0x08, 0x27, 0xd2, 0xb4, 0x08, + 0xe7, 0x87, 0x01, 0x00, 0xb4, 0x08, 0xe7, 0x67, + 0xff, 0x03, 0xb4, 0x08, 0x00, 0x60, 0x97, 0xc0, + 0xe7, 0x07, 0x01, 0x00, 0xb0, 0x08, 0x27, 0x00, + 0x12, 0xc0, 0x97, 0xcf, 0xc0, 0x09, 0xb6, 0x08, + 0x00, 0xd2, 0x02, 0xc3, 0xc0, 0x97, 0x05, 0x80, + 0x27, 0x00, 0xb6, 0x08, 0xc0, 0x99, 0x82, 0x08, + 0xc0, 0x99, 0xa2, 0xc0, 0x97, 0xcf, 0xe7, 0x07, + 0x00, 0x00, 0xb0, 0x08, 0xc0, 0xdf, 0x97, 0xcf, + 0xc8, 0x09, 0x72, 0x08, 0x08, 0x62, 0x02, 0xc0, + 0x10, 0x64, 0x07, 0xc1, 0xe7, 0x07, 0x00, 0x00, + 0x64, 0x08, 0xe7, 0x07, 0xc8, 0x05, 0x24, 0x00, + 0x97, 0xcf, 0x27, 0x04, 0x72, 0x08, 0xc8, 0x17, + 0x0e, 0x00, 0x27, 0x02, 0x64, 0x08, 0xe7, 0x07, + 0xd6, 0x05, 0x24, 0x00, 0x97, 0xcf, 0xd7, 0x09, + 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, + 0x62, 0x08, 0x13, 0xc1, 0x9f, 0xaf, 0x70, 0x03, + 0xe7, 0x57, 0x00, 0x00, 0x64, 0x08, 0x13, 0xc0, + 0xe7, 0x09, 0x64, 0x08, 0x30, 0x01, 0xe7, 0x07, + 0xf2, 0x05, 0x32, 0x01, 0xe7, 0x07, 0x10, 0x00, + 0x96, 0xc0, 0xe7, 0x09, 0x64, 0x08, 0x62, 0x08, + 0x04, 0xcf, 0xe7, 0x57, 0x00, 0x00, 0x64, 0x08, + 0x02, 0xc1, 0x9f, 0xaf, 0x70, 0x03, 0xe7, 0x05, + 0x00, 0xc0, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, + 0xc1, 0xdf, 0xc8, 0x09, 0x72, 0x08, 0x27, 0x02, + 0x78, 0x08, 0x08, 0x62, 0x03, 0xc1, 0xe7, 0x05, + 0x00, 0xc0, 0x97, 0xcf, 0x27, 0x04, 0x72, 0x08, + 0xe7, 0x05, 0x00, 0xc0, 0xf0, 0x07, 0x40, 0x00, + 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00, + 0x06, 0x00, 0xf0, 0x07, 0x64, 0x01, 0x0a, 0x00, + 0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x02, 0x00, + 0x51, 0xaf, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, + 0x6a, 0x08, 0x97, 0xc0, 0xc1, 0xdf, 0xc8, 0x09, + 0x6a, 0x08, 0x27, 0x04, 0x6a, 0x08, 0x27, 0x52, + 0x6c, 0x08, 0x03, 0xc1, 0xe7, 0x07, 0x6a, 0x08, + 0x6c, 0x08, 0xc0, 0xdf, 0x17, 0x02, 0xc8, 0x17, + 0x0e, 0x00, 0x9f, 0xaf, 0x16, 0x05, 0xc8, 0x05, + 0x00, 0x60, 0x03, 0xc0, 0x9f, 0xaf, 0x80, 0x04, + 0x97, 0xcf, 0x9f, 0xaf, 0x68, 0x04, 0x97, 0xcf, + 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x08, 0x62, + 0x1c, 0xc0, 0xd0, 0x09, 0x72, 0x08, 0x27, 0x02, + 0x72, 0x08, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, + 0x97, 0x02, 0xca, 0x09, 0xac, 0x08, 0xf2, 0x17, + 0x01, 0x00, 0x04, 0x00, 0xf2, 0x27, 0x00, 0x00, + 0x06, 0x00, 0xca, 0x17, 0x2c, 0x00, 0xf8, 0x77, + 0x01, 0x00, 0x0e, 0x00, 0x06, 0xc0, 0xca, 0xd9, + 0xf8, 0x57, 0xff, 0x00, 0x0e, 0x00, 0x01, 0xc1, + 0xca, 0xd9, 0x22, 0x1c, 0x0c, 0x00, 0xe2, 0x27, + 0x00, 0x00, 0xe2, 0x17, 0x01, 0x00, 0xe2, 0x27, + 0x00, 0x00, 0xca, 0x05, 0x00, 0x0c, 0x0c, 0x00, + 0xc0, 0x17, 0x41, 0x00, 0xc0, 0x67, 0xc0, 0xff, + 0x30, 0x00, 0x08, 0x00, 0x00, 0x02, 0xc0, 0x17, + 0x0c, 0x00, 0x30, 0x00, 0x06, 0x00, 0xf0, 0x07, + 0xdc, 0x00, 0x0a, 0x00, 0xf0, 0x07, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x40, 0xd1, + 0x01, 0x00, 0xc0, 0x19, 0xa6, 0x08, 0xc0, 0x59, + 0x98, 0x08, 0x04, 0xc9, 0x49, 0xaf, 0x9f, 0xaf, + 0xee, 0x00, 0x4a, 0xaf, 0x67, 0x10, 0xa6, 0x08, + 0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x01, 0x00, + 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x50, 0xaf, + 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0xc0, 0x07, + 0x01, 0x00, 0xc1, 0x09, 0x7c, 0x08, 0xc1, 0x77, + 0x01, 0x00, 0x97, 0xc1, 0xd8, 0x77, 0x01, 0x00, + 0x12, 0xc0, 0xc9, 0x07, 0x4c, 0x08, 0x9f, 0xaf, + 0x64, 0x05, 0x04, 0xc1, 0xc1, 0x77, 0x08, 0x00, + 0x13, 0xc0, 0x97, 0xcf, 0xc1, 0x77, 0x02, 0x00, + 0x97, 0xc1, 0xc1, 0x77, 0x10, 0x00, 0x0c, 0xc0, + 0x9f, 0xaf, 0x86, 0x05, 0x97, 0xcf, 0xc1, 0x77, + 0x04, 0x00, 0x06, 0xc0, 0xc9, 0x07, 0x7e, 0x08, + 0x9f, 0xaf, 0x64, 0x05, 0x97, 0xc0, 0x00, 0xcf, + 0x00, 0x90, 0x97, 0xcf, 0x50, 0x54, 0x97, 0xc1, + 0x70, 0x5c, 0x02, 0x00, 0x02, 0x00, 0x97, 0xc1, + 0x70, 0x5c, 0x04, 0x00, 0x04, 0x00, 0x97, 0xcf, + 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, + 0x0c, 0x00, 0x06, 0x00, 0x00, 0x00, 0xcb, 0x09, + 0x88, 0x08, 0xcc, 0x09, 0x8a, 0x08, 0x0b, 0x53, + 0x11, 0xc0, 0xc9, 0x02, 0xca, 0x07, 0x78, 0x05, + 0x9f, 0xaf, 0x64, 0x05, 0x97, 0xc0, 0x0a, 0xc8, + 0x82, 0x08, 0x0a, 0xcf, 0x82, 0x08, 0x9f, 0xaf, + 0x64, 0x05, 0x97, 0xc0, 0x05, 0xc2, 0x89, 0x30, + 0x82, 0x60, 0x78, 0xc1, 0x00, 0x90, 0x97, 0xcf, + 0x89, 0x10, 0x09, 0x53, 0x79, 0xc2, 0x89, 0x30, + 0x82, 0x08, 0x7a, 0xcf, 0xc0, 0xdf, 0x97, 0xcf, + 0xe7, 0x09, 0x96, 0xc0, 0x66, 0x08, 0xe7, 0x09, + 0x98, 0xc0, 0x68, 0x08, 0x0f, 0xcf, 0xe7, 0x09, + 0x96, 0xc0, 0x66, 0x08, 0xe7, 0x09, 0x98, 0xc0, + 0x68, 0x08, 0xe7, 0x09, 0x64, 0x08, 0x30, 0x01, + 0xe7, 0x07, 0xf2, 0x05, 0x32, 0x01, 0xe7, 0x07, + 0x10, 0x00, 0x96, 0xc0, 0xd7, 0x09, 0x00, 0xc0, + 0x17, 0x02, 0xc8, 0x09, 0x62, 0x08, 0xc8, 0x37, + 0x0e, 0x00, 0xe7, 0x57, 0x04, 0x00, 0x68, 0x08, + 0x3d, 0xc0, 0xe7, 0x87, 0x00, 0x08, 0x24, 0xc0, + 0xe7, 0x09, 0x94, 0x08, 0xba, 0x08, 0xe7, 0x17, + 0x64, 0x00, 0xba, 0x08, 0xe7, 0x67, 0xff, 0x07, + 0xba, 0x08, 0xe7, 0x77, 0x2a, 0x00, 0x66, 0x08, + 0x30, 0xc0, 0x97, 0x02, 0xca, 0x09, 0xac, 0x08, + 0xe7, 0x77, 0x20, 0x00, 0x66, 0x08, 0x0e, 0xc0, + 0xf2, 0x17, 0x01, 0x00, 0x10, 0x00, 0xf2, 0x27, + 0x00, 0x00, 0x12, 0x00, 0xe7, 0x77, 0x0a, 0x00, + 0x66, 0x08, 0xca, 0x05, 0x1e, 0xc0, 0x97, 0x02, + 0xca, 0x09, 0xac, 0x08, 0xf2, 0x17, 0x01, 0x00, + 0x0c, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x0e, 0x00, + 0xe7, 0x77, 0x02, 0x00, 0x66, 0x08, 0x07, 0xc0, + 0xf2, 0x17, 0x01, 0x00, 0x44, 0x00, 0xf2, 0x27, + 0x00, 0x00, 0x46, 0x00, 0x06, 0xcf, 0xf2, 0x17, + 0x01, 0x00, 0x60, 0x00, 0xf2, 0x27, 0x00, 0x00, + 0x62, 0x00, 0xca, 0x05, 0x9f, 0xaf, 0x68, 0x04, + 0x0f, 0xcf, 0x57, 0x02, 0x09, 0x02, 0xf1, 0x09, + 0x68, 0x08, 0x0c, 0x00, 0xf1, 0xda, 0x0c, 0x00, + 0xc8, 0x09, 0x6c, 0x08, 0x50, 0x02, 0x67, 0x02, + 0x6c, 0x08, 0xd1, 0x07, 0x00, 0x00, 0xc9, 0x05, + 0xe7, 0x09, 0x64, 0x08, 0x62, 0x08, 0xe7, 0x57, + 0x00, 0x00, 0x62, 0x08, 0x02, 0xc0, 0x9f, 0xaf, + 0x70, 0x03, 0xc8, 0x05, 0xe7, 0x05, 0x00, 0xc0, + 0xc0, 0xdf, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, + 0x17, 0x00, 0x17, 0x02, 0x97, 0x02, 0xc0, 0x09, + 0x92, 0xc0, 0xe7, 0x87, 0x00, 0x08, 0x24, 0xc0, + 0xe7, 0x09, 0x94, 0x08, 0xba, 0x08, 0xe7, 0x17, + 0x64, 0x00, 0xba, 0x08, 0xe7, 0x67, 0xff, 0x07, + 0xba, 0x08, 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, + 0xca, 0x09, 0xac, 0x08, 0xe7, 0x07, 0x00, 0x00, + 0x7a, 0x08, 0xe7, 0x07, 0x66, 0x03, 0x02, 0x00, + 0xc0, 0x77, 0x02, 0x00, 0x10, 0xc0, 0xef, 0x57, + 0x00, 0x00, 0xf0, 0x09, 0x04, 0xc0, 0x9f, 0xaf, + 0xd8, 0x02, 0x9f, 0xcf, 0x12, 0x08, 0xf2, 0x17, + 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27, 0x00, 0x00, + 0x52, 0x00, 0x9f, 0xcf, 0x12, 0x08, 0xef, 0x57, + 0x00, 0x00, 0xf0, 0x09, 0x08, 0xc0, 0xe7, 0x57, + 0x00, 0x00, 0xb8, 0x08, 0xe7, 0x07, 0x00, 0x00, + 0xb8, 0x08, 0x0a, 0xc0, 0x03, 0xcf, 0xc0, 0x77, + 0x10, 0x00, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, + 0x58, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x5a, 0x00, + 0xc0, 0x77, 0x80, 0x00, 0x06, 0xc0, 0xf2, 0x17, + 0x01, 0x00, 0x70, 0x00, 0xf2, 0x27, 0x00, 0x00, + 0x72, 0x00, 0xc0, 0x77, 0x08, 0x00, 0x1d, 0xc1, + 0xf2, 0x17, 0x01, 0x00, 0x08, 0x00, 0xf2, 0x27, + 0x00, 0x00, 0x0a, 0x00, 0xc0, 0x77, 0x00, 0x02, + 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x64, 0x00, + 0xf2, 0x27, 0x00, 0x00, 0x66, 0x00, 0xc0, 0x77, + 0x40, 0x00, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, + 0x5c, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x5e, 0x00, + 0xc0, 0x77, 0x01, 0x00, 0x01, 0xc0, 0x37, 0xcf, + 0x36, 0xcf, 0xf2, 0x17, 0x01, 0x00, 0x00, 0x00, + 0xf2, 0x27, 0x00, 0x00, 0x02, 0x00, 0xef, 0x57, + 0x00, 0x00, 0xf0, 0x09, 0x18, 0xc0, 0xe7, 0x57, + 0x01, 0x00, 0xb2, 0x08, 0x0e, 0xc2, 0x07, 0xc8, + 0xf2, 0x17, 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27, + 0x00, 0x00, 0x52, 0x00, 0x06, 0xcf, 0xf2, 0x17, + 0x01, 0x00, 0x54, 0x00, 0xf2, 0x27, 0x00, 0x00, + 0x56, 0x00, 0xe7, 0x07, 0x00, 0x00, 0xb2, 0x08, + 0xe7, 0x07, 0x01, 0x00, 0xb4, 0x08, 0xc8, 0x09, + 0x34, 0x01, 0xca, 0x17, 0x14, 0x00, 0xd8, 0x77, + 0x01, 0x00, 0x05, 0xc0, 0xca, 0xd9, 0xd8, 0x57, + 0xff, 0x00, 0x01, 0xc0, 0xca, 0xd9, 0xe2, 0x19, + 0x94, 0xc0, 0xe2, 0x27, 0x00, 0x00, 0xe2, 0x17, + 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, 0x9f, 0xaf, + 0x2e, 0x08, 0x9f, 0xaf, 0xde, 0x01, 0xe7, 0x57, + 0x00, 0x00, 0xaa, 0x08, 0x9f, 0xa1, 0xf0, 0x0b, + 0xca, 0x05, 0xc8, 0x05, 0xc0, 0x05, 0xe7, 0x05, + 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0xc8, 0x09, + 0x6e, 0x08, 0x08, 0x62, 0x97, 0xc0, 0x27, 0x04, + 0x6e, 0x08, 0x27, 0x52, 0x70, 0x08, 0x03, 0xc1, + 0xe7, 0x07, 0x6e, 0x08, 0x70, 0x08, 0x9f, 0xaf, + 0x68, 0x04, 0x97, 0xcf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x33, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0xe7, 0x57, 0x00, 0x80, + 0xb2, 0x00, 0x06, 0xc2, 0xe7, 0x07, 0x52, 0x0e, + 0x12, 0x00, 0xe7, 0x07, 0x98, 0x0e, 0xb2, 0x00, + 0xe7, 0x07, 0xa4, 0x09, 0xf2, 0x02, 0xc8, 0x09, + 0xb4, 0x00, 0xf8, 0x07, 0x02, 0x00, 0x0d, 0x00, + 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07, 0x00, 0x00, + 0x0e, 0xc0, 0xc8, 0x09, 0xdc, 0x00, 0xf0, 0x07, + 0xff, 0xff, 0x09, 0x00, 0xf0, 0x07, 0xfb, 0x13, + 0x0b, 0x00, 0xe7, 0x09, 0xc0, 0x00, 0x58, 0x08, + 0xe7, 0x09, 0xbe, 0x00, 0x54, 0x08, 0xe7, 0x09, + 0x10, 0x00, 0x92, 0x08, 0xc8, 0x07, 0xb4, 0x09, + 0x9f, 0xaf, 0x8c, 0x09, 0x9f, 0xaf, 0xe2, 0x0b, + 0xc0, 0x07, 0x80, 0x01, 0x44, 0xaf, 0x27, 0x00, + 0x88, 0x08, 0x27, 0x00, 0x8a, 0x08, 0x27, 0x00, + 0x8c, 0x08, 0xc0, 0x07, 0x74, 0x00, 0x44, 0xaf, + 0x27, 0x00, 0xac, 0x08, 0x08, 0x00, 0x00, 0x90, + 0xc1, 0x07, 0x1d, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x01, 0xda, 0x7c, 0xc1, 0x9f, 0xaf, 0x8a, 0x0b, + 0xc0, 0x07, 0x4c, 0x00, 0x48, 0xaf, 0x27, 0x00, + 0x56, 0x08, 0x9f, 0xaf, 0x72, 0x0c, 0xe7, 0x07, + 0x00, 0x80, 0x96, 0x08, 0xef, 0x57, 0x00, 0x00, + 0xf0, 0x09, 0x03, 0xc0, 0xe7, 0x07, 0x01, 0x00, + 0x1c, 0xc0, 0xe7, 0x05, 0x0e, 0xc0, 0x97, 0xcf, + 0x49, 0xaf, 0xe7, 0x87, 0x43, 0x00, 0x0e, 0xc0, + 0xe7, 0x07, 0xff, 0xff, 0x94, 0x08, 0x9f, 0xaf, + 0x8a, 0x0c, 0xc0, 0x07, 0x01, 0x00, 0x60, 0xaf, + 0x4a, 0xaf, 0x97, 0xcf, 0x00, 0x08, 0x09, 0x08, + 0x11, 0x08, 0x00, 0xda, 0x7c, 0xc1, 0x97, 0xcf, + 0x67, 0x04, 0xcc, 0x02, 0xc0, 0xdf, 0x51, 0x94, + 0xb1, 0xaf, 0x06, 0x00, 0xc1, 0xdf, 0xc9, 0x09, + 0xcc, 0x02, 0x49, 0x62, 0x75, 0xc1, 0xc0, 0xdf, + 0xa7, 0xcf, 0xd6, 0x02, 0x0e, 0x00, 0x24, 0x00, + 0xd6, 0x05, 0x22, 0x00, 0xc4, 0x06, 0xd0, 0x00, + 0xf0, 0x0b, 0xaa, 0x00, 0x0e, 0x0a, 0xbe, 0x00, + 0x2c, 0x0c, 0x10, 0x00, 0x20, 0x00, 0x04, 0x00, + 0xc4, 0x05, 0x02, 0x00, 0x66, 0x03, 0x06, 0x00, + 0x00, 0x00, 0x24, 0xc0, 0x04, 0x04, 0x28, 0xc0, + 0xfe, 0xfb, 0x1e, 0xc0, 0x00, 0x04, 0x22, 0xc0, + 0xff, 0xf0, 0xc0, 0x00, 0x60, 0x0b, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x34, 0x0a, 0x3e, 0x0a, + 0x9e, 0x0a, 0xa8, 0x0a, 0xce, 0x0a, 0xd2, 0x0a, + 0xd6, 0x0a, 0x00, 0x0b, 0x10, 0x0b, 0x1e, 0x0b, + 0x20, 0x0b, 0x28, 0x0b, 0x28, 0x0b, 0x27, 0x02, + 0xa2, 0x08, 0x97, 0xcf, 0xe7, 0x07, 0x00, 0x00, + 0xa2, 0x08, 0x0a, 0x0e, 0x01, 0x00, 0xca, 0x57, + 0x0e, 0x00, 0x9f, 0xc3, 0x2a, 0x0b, 0xca, 0x37, + 0x00, 0x00, 0x9f, 0xc2, 0x2a, 0x0b, 0x0a, 0xd2, + 0xb2, 0xcf, 0xf4, 0x09, 0xc8, 0x09, 0xde, 0x00, + 0x07, 0x06, 0x9f, 0xcf, 0x3c, 0x0b, 0xf0, 0x57, + 0x80, 0x01, 0x06, 0x00, 0x9f, 0xc8, 0x2a, 0x0b, + 0x27, 0x0c, 0x02, 0x00, 0x86, 0x08, 0xc0, 0x09, + 0x88, 0x08, 0x27, 0x00, 0x8a, 0x08, 0xe7, 0x07, + 0x00, 0x00, 0x84, 0x08, 0x27, 0x00, 0x5c, 0x08, + 0x00, 0x1c, 0x06, 0x00, 0x27, 0x00, 0x8c, 0x08, + 0x41, 0x90, 0x67, 0x50, 0x86, 0x08, 0x0d, 0xc0, + 0x67, 0x00, 0x5a, 0x08, 0x27, 0x0c, 0x06, 0x00, + 0x5e, 0x08, 0xe7, 0x07, 0x8a, 0x0a, 0x60, 0x08, + 0xc8, 0x07, 0x5a, 0x08, 0x41, 0x90, 0x51, 0xaf, + 0x97, 0xcf, 0x9f, 0xaf, 0xac, 0x0e, 0xe7, 0x09, + 0x8c, 0x08, 0x8a, 0x08, 0xe7, 0x09, 0x86, 0x08, + 0x84, 0x08, 0x59, 0xaf, 0x97, 0xcf, 0x27, 0x0c, + 0x02, 0x00, 0x7c, 0x08, 0x59, 0xaf, 0x97, 0xcf, + 0x09, 0x0c, 0x02, 0x00, 0x09, 0xda, 0x49, 0xd2, + 0xc9, 0x19, 0xac, 0x08, 0xc8, 0x07, 0x5a, 0x08, + 0xe0, 0x07, 0x00, 0x00, 0x60, 0x02, 0xe0, 0x07, + 0x04, 0x00, 0xd0, 0x07, 0x9a, 0x0a, 0x48, 0xdb, + 0x41, 0x90, 0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, + 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, 0xf0, 0x57, + 0x06, 0x00, 0x06, 0x00, 0x26, 0xc1, 0xe7, 0x07, + 0x7e, 0x08, 0x5c, 0x08, 0x41, 0x90, 0x67, 0x00, + 0x5a, 0x08, 0x27, 0x0c, 0x06, 0x00, 0x5e, 0x08, + 0xe7, 0x07, 0x5c, 0x0b, 0x60, 0x08, 0xc8, 0x07, + 0x5a, 0x08, 0x41, 0x90, 0x51, 0xaf, 0x97, 0xcf, + 0x07, 0x0c, 0x06, 0x00, 0xc7, 0x57, 0x06, 0x00, + 0x10, 0xc1, 0xc8, 0x07, 0x7e, 0x08, 0x16, 0xcf, + 0x00, 0x0c, 0x02, 0x00, 0x00, 0xda, 0x40, 0xd1, + 0x27, 0x00, 0x98, 0x08, 0x1f, 0xcf, 0x1e, 0xcf, + 0x27, 0x0c, 0x02, 0x00, 0xa4, 0x08, 0x1a, 0xcf, + 0x00, 0xcf, 0x27, 0x02, 0x20, 0x01, 0xe7, 0x07, + 0x08, 0x00, 0x22, 0x01, 0xe7, 0x07, 0x13, 0x00, + 0xb0, 0xc0, 0x97, 0xcf, 0x41, 0x90, 0x67, 0x00, + 0x5a, 0x08, 0xe7, 0x01, 0x5e, 0x08, 0x27, 0x02, + 0x5c, 0x08, 0xe7, 0x07, 0x5c, 0x0b, 0x60, 0x08, + 0xc8, 0x07, 0x5a, 0x08, 0xc1, 0x07, 0x00, 0x80, + 0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, + 0x00, 0x60, 0x05, 0xc0, 0xe7, 0x07, 0x00, 0x00, + 0x9a, 0x08, 0xa7, 0xcf, 0x58, 0x08, 0x9f, 0xaf, + 0xe2, 0x0b, 0xe7, 0x07, 0x01, 0x00, 0x9a, 0x08, + 0x49, 0xaf, 0xd7, 0x09, 0x00, 0xc0, 0x07, 0xaf, + 0xe7, 0x05, 0x00, 0xc0, 0x4a, 0xaf, 0xa7, 0xcf, + 0x58, 0x08, 0xc0, 0x07, 0x40, 0x00, 0x44, 0xaf, + 0x27, 0x00, 0xa0, 0x08, 0x08, 0x00, 0xc0, 0x07, + 0x20, 0x00, 0x20, 0x94, 0x00, 0xda, 0x7d, 0xc1, + 0xc0, 0x07, 0xfe, 0x7f, 0x44, 0xaf, 0x40, 0x00, + 0x41, 0x90, 0xc0, 0x37, 0x08, 0x00, 0xdf, 0xde, + 0x50, 0x06, 0xc0, 0x57, 0x10, 0x00, 0x02, 0xc2, + 0xc0, 0x07, 0x10, 0x00, 0x27, 0x00, 0x76, 0x08, + 0x41, 0x90, 0x9f, 0xde, 0x40, 0x06, 0x44, 0xaf, + 0x27, 0x00, 0x74, 0x08, 0xc0, 0x09, 0x76, 0x08, + 0x41, 0x90, 0x00, 0xd2, 0x00, 0xd8, 0x9f, 0xde, + 0x08, 0x00, 0x44, 0xaf, 0x27, 0x00, 0x9e, 0x08, + 0x97, 0xcf, 0xe7, 0x87, 0x00, 0x84, 0x28, 0xc0, + 0xe7, 0x67, 0xff, 0xf3, 0x24, 0xc0, 0x97, 0xcf, + 0xe7, 0x87, 0x01, 0x00, 0xaa, 0x08, 0xe7, 0x57, + 0x00, 0x00, 0x7a, 0x08, 0x97, 0xc1, 0x9f, 0xaf, + 0xe2, 0x0b, 0xe7, 0x87, 0x00, 0x06, 0x22, 0xc0, + 0xe7, 0x07, 0x00, 0x00, 0x90, 0xc0, 0xe7, 0x67, + 0xfe, 0xff, 0x3e, 0xc0, 0xe7, 0x07, 0x2e, 0x00, + 0x0a, 0xc0, 0xe7, 0x87, 0x01, 0x00, 0x3e, 0xc0, + 0xe7, 0x07, 0xff, 0xff, 0x94, 0x08, 0x9f, 0xaf, + 0xf0, 0x0c, 0x97, 0xcf, 0x17, 0x00, 0xa7, 0xaf, + 0x54, 0x08, 0xc0, 0x05, 0x27, 0x00, 0x52, 0x08, + 0xe7, 0x87, 0x01, 0x00, 0xaa, 0x08, 0x9f, 0xaf, + 0xe2, 0x0b, 0xe7, 0x07, 0x0c, 0x00, 0x40, 0xc0, + 0x9f, 0xaf, 0xf0, 0x0c, 0xe7, 0x07, 0x00, 0x00, + 0x78, 0x08, 0x00, 0x90, 0xe7, 0x09, 0x88, 0x08, + 0x8a, 0x08, 0x27, 0x00, 0x84, 0x08, 0x27, 0x00, + 0x7c, 0x08, 0x9f, 0xaf, 0x8a, 0x0c, 0xe7, 0x07, + 0x00, 0x00, 0xb2, 0x02, 0xe7, 0x07, 0x00, 0x00, + 0xb4, 0x02, 0xc0, 0x07, 0x06, 0x00, 0xc8, 0x09, + 0xde, 0x00, 0xc8, 0x17, 0x03, 0x00, 0xc9, 0x07, + 0x7e, 0x08, 0x29, 0x0a, 0x00, 0xda, 0x7d, 0xc1, + 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, + 0x00, 0x90, 0x27, 0x00, 0x6a, 0x08, 0xe7, 0x07, + 0x6a, 0x08, 0x6c, 0x08, 0x27, 0x00, 0x6e, 0x08, + 0xe7, 0x07, 0x6e, 0x08, 0x70, 0x08, 0x27, 0x00, + 0x78, 0x08, 0x27, 0x00, 0x62, 0x08, 0x27, 0x00, + 0x64, 0x08, 0xc8, 0x09, 0x74, 0x08, 0xc1, 0x09, + 0x76, 0x08, 0xc9, 0x07, 0x72, 0x08, 0x11, 0x02, + 0x09, 0x02, 0xc8, 0x17, 0x40, 0x06, 0x01, 0xda, + 0x7a, 0xc1, 0x51, 0x94, 0xc8, 0x09, 0x9e, 0x08, + 0xc9, 0x07, 0x9c, 0x08, 0xc1, 0x09, 0x76, 0x08, + 0x01, 0xd2, 0x01, 0xd8, 0x11, 0x02, 0x09, 0x02, + 0xc8, 0x17, 0x08, 0x00, 0x01, 0xda, 0x7a, 0xc1, + 0x51, 0x94, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, + 0xe7, 0x57, 0x00, 0x00, 0x52, 0x08, 0x97, 0xc0, + 0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x09, 0x94, 0x08, + 0x90, 0x08, 0xe7, 0x57, 0xff, 0xff, 0x90, 0x08, + 0x04, 0xc1, 0xe7, 0x07, 0xf0, 0x0c, 0x8e, 0x08, + 0x97, 0xcf, 0xe7, 0x17, 0x32, 0x00, 0x90, 0x08, + 0xe7, 0x67, 0xff, 0x07, 0x90, 0x08, 0xe7, 0x07, + 0x26, 0x0d, 0x8e, 0x08, 0x97, 0xcf, 0xd7, 0x09, + 0x00, 0xc0, 0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, + 0x96, 0x08, 0x23, 0xc0, 0xe7, 0x07, 0x00, 0x80, + 0x80, 0xc0, 0xe7, 0x07, 0x04, 0x00, 0x90, 0xc0, + 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, + 0x00, 0x80, 0x80, 0xc0, 0xc0, 0x07, 0x00, 0x00, + 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, + 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, + 0x00, 0x80, 0x80, 0xc0, 0xe7, 0x07, 0x00, 0x80, + 0x40, 0xc0, 0xc0, 0x07, 0x00, 0x00, 0xe7, 0x07, + 0x00, 0x00, 0x40, 0xc0, 0xe7, 0x07, 0x00, 0x00, + 0x80, 0xc0, 0xef, 0x57, 0x00, 0x00, 0xf1, 0x09, + 0x9f, 0xa0, 0xc0, 0x0d, 0xe7, 0x07, 0x04, 0x00, + 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x02, 0x40, 0xc0, + 0xe7, 0x07, 0x0c, 0x02, 0x40, 0xc0, 0xe7, 0x07, + 0x00, 0x00, 0x96, 0x08, 0xe7, 0x07, 0x00, 0x00, + 0x8e, 0x08, 0xe7, 0x07, 0x00, 0x00, 0xaa, 0x08, + 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x9f, 0xaf, + 0x9e, 0x03, 0xe7, 0x05, 0x00, 0xc0, 0x9f, 0xaf, + 0xde, 0x01, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, + 0x9f, 0xaf, 0xde, 0x0d, 0xef, 0x77, 0x00, 0x00, + 0xf1, 0x09, 0x97, 0xc1, 0x9f, 0xaf, 0xde, 0x0d, + 0xef, 0x77, 0x00, 0x00, 0xf1, 0x09, 0x97, 0xc1, + 0xef, 0x07, 0x01, 0x00, 0xf1, 0x09, 0xe7, 0x87, + 0x00, 0x08, 0x1e, 0xc0, 0xe7, 0x87, 0x00, 0x08, + 0x22, 0xc0, 0xe7, 0x67, 0xff, 0xf7, 0x22, 0xc0, + 0xe7, 0x77, 0x00, 0x08, 0x20, 0xc0, 0x11, 0xc0, + 0xe7, 0x67, 0xff, 0xf7, 0x1e, 0xc0, 0xe7, 0x87, + 0x00, 0x08, 0x22, 0xc0, 0xe7, 0x67, 0xff, 0xf7, + 0x22, 0xc0, 0xe7, 0x77, 0x00, 0x08, 0x20, 0xc0, + 0x04, 0xc1, 0xe7, 0x87, 0x00, 0x08, 0x22, 0xc0, + 0x97, 0xcf, 0xe7, 0x07, 0x01, 0x01, 0xf0, 0x09, + 0xef, 0x57, 0x18, 0x00, 0xfe, 0xff, 0x97, 0xc2, + 0xef, 0x07, 0x00, 0x00, 0xf0, 0x09, 0x97, 0xcf, + 0xd7, 0x09, 0x00, 0xc0, 0x17, 0x00, 0x17, 0x02, + 0x97, 0x02, 0xe7, 0x57, 0x00, 0x00, 0x7a, 0x08, + 0x06, 0xc0, 0xc0, 0x09, 0x92, 0xc0, 0xc0, 0x77, + 0x09, 0x02, 0x9f, 0xc1, 0xea, 0x06, 0x9f, 0xcf, + 0x20, 0x08, 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07, + 0x00, 0x00, 0x0e, 0xc0, 0x9f, 0xaf, 0x66, 0x0e, + 0xe7, 0x05, 0x0e, 0xc0, 0x97, 0xcf, 0xd7, 0x09, + 0x00, 0xc0, 0x17, 0x02, 0xc8, 0x09, 0xb0, 0xc0, + 0xe7, 0x67, 0xfe, 0x7f, 0xb0, 0xc0, 0xc8, 0x77, + 0x00, 0x20, 0x9f, 0xc1, 0x64, 0xeb, 0xe7, 0x57, + 0x00, 0x00, 0xc8, 0x02, 0x9f, 0xc1, 0x80, 0xeb, + 0xc8, 0x99, 0xca, 0x02, 0xc8, 0x67, 0x04, 0x00, + 0x9f, 0xc1, 0x96, 0xeb, 0x9f, 0xcf, 0x4c, 0xeb, + 0xe7, 0x07, 0x00, 0x00, 0xa6, 0xc0, 0xe7, 0x09, + 0xb0, 0xc0, 0xc8, 0x02, 0xe7, 0x07, 0x03, 0x00, + 0xb0, 0xc0, 0x97, 0xcf, 0xc0, 0x09, 0x86, 0x08, + 0xc0, 0x37, 0x01, 0x00, 0x97, 0xc9, 0xc9, 0x09, + 0x88, 0x08, 0x02, 0x00, 0x41, 0x90, 0x48, 0x02, + 0xc9, 0x17, 0x06, 0x00, 0x9f, 0xaf, 0x64, 0x05, + 0x9f, 0xa2, 0xd6, 0x0e, 0x02, 0xda, 0x77, 0xc1, + 0x41, 0x60, 0x71, 0xc1, 0x97, 0xcf, 0x17, 0x02, + 0x57, 0x02, 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00, + 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00, 0x43, 0x04, + 0x21, 0x04, 0xe0, 0x00, 0xc1, 0x07, 0x01, 0x00, + 0xc9, 0x05, 0xc8, 0x05, 0x97, 0xcf, + 0, 0 +}; + +/* Firmware fixup (data?) segment */ +static unsigned char kue_fix_seg[] = +{ + /******************************************/ + /* NOTE: B6/C3 is data header signature */ + /* 0xAA/0xBB is data length = total */ + /* bytes - 7, 0xCC is type, 0xDD is */ + /* interrupt to use. */ + /******************************************/ + 0xB6, 0xC3, 0xc9, 0x02, 0x03, 0x64, + 0x02, 0x00, 0x08, 0x00, 0x24, 0x00, 0x2e, 0x00, + 0x2c, 0x00, 0x3e, 0x00, 0x44, 0x00, 0x48, 0x00, + 0x50, 0x00, 0x5c, 0x00, 0x60, 0x00, 0x66, 0x00, + 0x6c, 0x00, 0x70, 0x00, 0x76, 0x00, 0x74, 0x00, + 0x7a, 0x00, 0x7e, 0x00, 0x84, 0x00, 0x8a, 0x00, + 0x8e, 0x00, 0x92, 0x00, 0x98, 0x00, 0x9c, 0x00, + 0xa0, 0x00, 0xa8, 0x00, 0xae, 0x00, 0xb4, 0x00, + 0xb2, 0x00, 0xba, 0x00, 0xbe, 0x00, 0xc4, 0x00, + 0xc8, 0x00, 0xce, 0x00, 0xd2, 0x00, 0xd6, 0x00, + 0xda, 0x00, 0xe2, 0x00, 0xe0, 0x00, 0xea, 0x00, + 0xf2, 0x00, 0xfe, 0x00, 0x06, 0x01, 0x0c, 0x01, + 0x1a, 0x01, 0x24, 0x01, 0x22, 0x01, 0x2a, 0x01, + 0x30, 0x01, 0x36, 0x01, 0x3c, 0x01, 0x4e, 0x01, + 0x52, 0x01, 0x58, 0x01, 0x5c, 0x01, 0x9c, 0x01, + 0xb6, 0x01, 0xba, 0x01, 0xc0, 0x01, 0xca, 0x01, + 0xd0, 0x01, 0xda, 0x01, 0xe2, 0x01, 0xea, 0x01, + 0xf0, 0x01, 0x0a, 0x02, 0x0e, 0x02, 0x14, 0x02, + 0x26, 0x02, 0x6c, 0x02, 0x8e, 0x02, 0x98, 0x02, + 0xa0, 0x02, 0xa6, 0x02, 0xba, 0x02, 0xc6, 0x02, + 0xce, 0x02, 0xe8, 0x02, 0xee, 0x02, 0xf4, 0x02, + 0xf8, 0x02, 0x0a, 0x03, 0x10, 0x03, 0x1a, 0x03, + 0x1e, 0x03, 0x2a, 0x03, 0x2e, 0x03, 0x34, 0x03, + 0x3a, 0x03, 0x44, 0x03, 0x4e, 0x03, 0x5a, 0x03, + 0x5e, 0x03, 0x6a, 0x03, 0x72, 0x03, 0x80, 0x03, + 0x84, 0x03, 0x8c, 0x03, 0x94, 0x03, 0x98, 0x03, + 0xa8, 0x03, 0xae, 0x03, 0xb4, 0x03, 0xba, 0x03, + 0xce, 0x03, 0xcc, 0x03, 0xd6, 0x03, 0xdc, 0x03, + 0xec, 0x03, 0xf0, 0x03, 0xfe, 0x03, 0x1c, 0x04, + 0x30, 0x04, 0x38, 0x04, 0x3c, 0x04, 0x40, 0x04, + 0x48, 0x04, 0x46, 0x04, 0x54, 0x04, 0x5e, 0x04, + 0x64, 0x04, 0x74, 0x04, 0x78, 0x04, 0x84, 0x04, + 0xd8, 0x04, 0xec, 0x04, 0xf0, 0x04, 0xf8, 0x04, + 0xfe, 0x04, 0x1c, 0x05, 0x2c, 0x05, 0x30, 0x05, + 0x4a, 0x05, 0x56, 0x05, 0x5a, 0x05, 0x88, 0x05, + 0x8c, 0x05, 0x96, 0x05, 0x9a, 0x05, 0xa8, 0x05, + 0xcc, 0x05, 0xd2, 0x05, 0xda, 0x05, 0xe0, 0x05, + 0xe4, 0x05, 0xfc, 0x05, 0x06, 0x06, 0x14, 0x06, + 0x12, 0x06, 0x1a, 0x06, 0x20, 0x06, 0x26, 0x06, + 0x2e, 0x06, 0x34, 0x06, 0x48, 0x06, 0x52, 0x06, + 0x64, 0x06, 0x86, 0x06, 0x90, 0x06, 0x9a, 0x06, + 0xa0, 0x06, 0xac, 0x06, 0xaa, 0x06, 0xb2, 0x06, + 0xb8, 0x06, 0xdc, 0x06, 0xda, 0x06, 0xe2, 0x06, + 0xe8, 0x06, 0xf2, 0x06, 0xf8, 0x06, 0xfc, 0x06, + 0x0a, 0x07, 0x10, 0x07, 0x14, 0x07, 0x24, 0x07, + 0x2a, 0x07, 0x32, 0x07, 0x38, 0x07, 0xb2, 0x07, + 0xba, 0x07, 0xde, 0x07, 0xe4, 0x07, 0x10, 0x08, + 0x14, 0x08, 0x1a, 0x08, 0x1e, 0x08, 0x30, 0x08, + 0x38, 0x08, 0x3c, 0x08, 0x44, 0x08, 0x42, 0x08, + 0x48, 0x08, 0xc6, 0x08, 0xcc, 0x08, 0xd2, 0x08, + 0xfe, 0x08, 0x04, 0x09, 0x0a, 0x09, 0x0e, 0x09, + 0x12, 0x09, 0x16, 0x09, 0x20, 0x09, 0x24, 0x09, + 0x28, 0x09, 0x32, 0x09, 0x46, 0x09, 0x4a, 0x09, + 0x50, 0x09, 0x54, 0x09, 0x5a, 0x09, 0x60, 0x09, + 0x7c, 0x09, 0x80, 0x09, 0xb8, 0x09, 0xbc, 0x09, + 0xc0, 0x09, 0xc4, 0x09, 0xc8, 0x09, 0xcc, 0x09, + 0xd0, 0x09, 0xd4, 0x09, 0xec, 0x09, 0xf4, 0x09, + 0xf6, 0x09, 0xf8, 0x09, 0xfa, 0x09, 0xfc, 0x09, + 0xfe, 0x09, 0x00, 0x0a, 0x02, 0x0a, 0x04, 0x0a, + 0x06, 0x0a, 0x08, 0x0a, 0x0a, 0x0a, 0x0c, 0x0a, + 0x10, 0x0a, 0x18, 0x0a, 0x24, 0x0a, 0x2c, 0x0a, + 0x32, 0x0a, 0x3c, 0x0a, 0x46, 0x0a, 0x4c, 0x0a, + 0x50, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x5e, 0x0a, + 0x66, 0x0a, 0x6c, 0x0a, 0x72, 0x0a, 0x78, 0x0a, + 0x7e, 0x0a, 0x7c, 0x0a, 0x82, 0x0a, 0x8c, 0x0a, + 0x92, 0x0a, 0x90, 0x0a, 0x98, 0x0a, 0x96, 0x0a, + 0xa2, 0x0a, 0xb2, 0x0a, 0xb6, 0x0a, 0xc4, 0x0a, + 0xe2, 0x0a, 0xe0, 0x0a, 0xe8, 0x0a, 0xee, 0x0a, + 0xf4, 0x0a, 0xf2, 0x0a, 0xf8, 0x0a, 0x0c, 0x0b, + 0x1a, 0x0b, 0x24, 0x0b, 0x40, 0x0b, 0x44, 0x0b, + 0x48, 0x0b, 0x4e, 0x0b, 0x4c, 0x0b, 0x52, 0x0b, + 0x68, 0x0b, 0x6c, 0x0b, 0x70, 0x0b, 0x76, 0x0b, + 0x88, 0x0b, 0x92, 0x0b, 0xbe, 0x0b, 0xca, 0x0b, + 0xce, 0x0b, 0xde, 0x0b, 0xf4, 0x0b, 0xfa, 0x0b, + 0x00, 0x0c, 0x24, 0x0c, 0x28, 0x0c, 0x30, 0x0c, + 0x36, 0x0c, 0x3c, 0x0c, 0x40, 0x0c, 0x4a, 0x0c, + 0x50, 0x0c, 0x58, 0x0c, 0x56, 0x0c, 0x5c, 0x0c, + 0x60, 0x0c, 0x64, 0x0c, 0x80, 0x0c, 0x94, 0x0c, + 0x9a, 0x0c, 0x98, 0x0c, 0x9e, 0x0c, 0xa4, 0x0c, + 0xa2, 0x0c, 0xa8, 0x0c, 0xac, 0x0c, 0xb0, 0x0c, + 0xb4, 0x0c, 0xb8, 0x0c, 0xbc, 0x0c, 0xce, 0x0c, + 0xd2, 0x0c, 0xd6, 0x0c, 0xf4, 0x0c, 0xfa, 0x0c, + 0x00, 0x0d, 0xfe, 0x0c, 0x06, 0x0d, 0x0e, 0x0d, + 0x0c, 0x0d, 0x16, 0x0d, 0x1c, 0x0d, 0x22, 0x0d, + 0x20, 0x0d, 0x30, 0x0d, 0x7e, 0x0d, 0x82, 0x0d, + 0x9a, 0x0d, 0xa0, 0x0d, 0xa6, 0x0d, 0xb0, 0x0d, + 0xb8, 0x0d, 0xc2, 0x0d, 0xc8, 0x0d, 0xce, 0x0d, + 0xd4, 0x0d, 0xdc, 0x0d, 0x1e, 0x0e, 0x2c, 0x0e, + 0x3e, 0x0e, 0x4c, 0x0e, 0x50, 0x0e, 0x5e, 0x0e, + 0xae, 0x0e, 0xb8, 0x0e, 0xc6, 0x0e, 0xca, 0x0e, + 0, 0 +}; + +/* Fixup command. */ +#define KUE_TRIGCMD_OFFSET 5 +static unsigned char kue_trig_seg[] = { + 0xb6, 0xc3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00 +};