From owner-freebsd-hackers Sun Dec 19 12:59:26 1999 Delivered-To: freebsd-hackers@freebsd.org Received: from skynet.ctr.columbia.edu (skynet.ctr.columbia.edu [128.59.64.70]) by hub.freebsd.org (Postfix) with SMTP id 723A6151F6 for ; Sun, 19 Dec 1999 12:59:18 -0800 (PST) (envelope-from wpaul@skynet.ctr.columbia.edu) Received: (from wpaul@localhost) by skynet.ctr.columbia.edu (8.6.12/8.6.9) id QAA03584 for hackers@freebsd.org; Sun, 19 Dec 1999 16:03:28 -0500 From: Bill Paul Message-Id: <199912192103.QAA03584@skynet.ctr.columbia.edu> Subject: USB ethernet hacking To: hackers@freebsd.org Date: Sun, 19 Dec 1999 16:03:26 -0500 (EST) X-Mailer: ELM [version 2.4 PL24] Content-Type: text Content-Length: 5912 Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG For those of you who don't know, I've been working on a driver for the ADMtek USB Ethernet chip (AN986 Pegasus). It kinda sorta works: aue0: ADMtek Inc. ADMtek 10/100 USB MAC, rev 1.10/1.01, addr 2 aue0: Ethernet address: 00:00:e8:00:00:a2 miibus0: on aue0 ukphy0: on miibus0 ukphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto The particular adapter I have is a combo device which supports both 10/100 ethernet and 1Mbps HomePNA (ethernet over home telephone cabling). I only have the ethernet PHY enabled for the moment since I don't have any way to test the HomePNA part, and I need to write a separate HomePNA PHY driver so that the media type is recognized correctly. (Right now, the ukphy driver thinks it's just another 10Mbps PHY, which causes the miibus layer to think the interface has two 10baseT/UTP media selections, which doesn't work.) I've gotten the thing working well enough with FreeBSD-current that I can telnet over it and type this message. However, there are some problems that I've run into which I don't know how to solve due to my inexperience with USB. First of all, there's one major problem with the USB code as it's currently implemented with regard to "synchronous" transfers. There are two basic ways to transfer data to/from a USB device: an asynchronous method, and a synchronous one. The asynchronous one works like this: - allocate a USB transfer handle - set it up with the correct parameters, including a pointer to a callback routine - call usbd_transfer() to initiate it - go off and to other stuff for a while - when the transfer is done, the USB controller's interrupt handler will call the callback routine with the transfer results. The synchronous method works like this: - allocate a USB transfer handle - set it up with the correct parameters - call usbd_sync_transfer() to initiate it - usbd_sync_transfer() blocks until the transfer is complete, and which point you can call usbd_get_xfer_status() to find the results The problem is that the synchronous method is not really synchronous: in usbdi.c:usbd_transfer(), if we are performing a sync transfer and the transfer doesn't complete right away, the code calls tsleep() in the hope that it can pause the process that initiated the transfer and wake it up later. Unfortunately, you can't call tsleep() from interrupt context, and I need to be able to do that. Why? Because reading and writing the registers on the ethernet MAC in the ADMtek device is done by performing transfers using USB endpoint 0 (the control endpoint). The miibus code needs to be able to read the PHY status once in a while, and this is done by setting up a timeout() that fires once a second to tall the aue_tick() routine, which in turn calls mii_tick() to drive the miibus code. But aue_tick() is called at interrupt context, and the kernel panicks whenever it hits that tsleep() in usbd_transfer(). I have worked around this for now by hacking usbdi.c so that it polls the controller interrupt/status register instead of tsleep()ing. I'm not sure this is the best solution, but it's the only one that seems to work. However that's not my biggest problem. My biggest problem is getting transfers over 1100 bytes or so to work reliably. My initial scheme for transmitting and receiving packets was to set up asynchronous transfers with callbacks. Packets are sent over bulk transfer endpoints (one for RX, one for TX). For TX, I would set up a transfer and initiate it, then wait until the callback is called to free the mbuf containing the packet data. This seemed to work, but only for transfers around 1000 to 1100 bytes or so. Trying to transfer packets of 1200 bytes or more always seemed to yield an "IOERROR" error. I switched the packet transmission code to use synchronous transfers (i.e. waiting for the transfer to complete before moving on) and this seemed to help: I could now get transmissions up to 1500 bytes to work without errors. However, I have the same problem now with received packets: trying to receive a frame larger than 1100 bytes also causes an IOERROR, however I can't use a synchronous transfer here since that would cause the kernel to freeze in its tracks waiting for a packet. Tracing down the error shows that the uhci driver is getting an error status of 0x500000, which is apparently the logical OR of two error bits: "babble" and "stall." I have the Intel UHCI spec document and it mentions these errors, however it doesn't seem to say what causes them, how to clear them or, more importantly, how to avoid them. If I could just figure out how to get this thing to handle these "large" transfers, I would be a happy camper. I put a copy of my current code at: http://www.freebsd.org/~wpaul/ADMtek/USB/4.0 This directory contains the source for the if_aue driver, plus a patch for usbdi.c with the changes I made to get sync transfers to work properly in interrupt context. The code is still very grotty. The datasheet for the ADMtek Pegasus chip is at http://www.admtek.com.tw. -Bill P.S.: Please don't write me asking for help getting your USB ethernet adapter work with FreeBSD. Don't ask me when/if the driver will be done. Don't ask me if your favorite adapter will be supported. Don't ask me how to make the code work with FreeBSD 3.x. -- ============================================================================= -Bill Paul (212) 854-6020 | System Manager, Master of Unix-Fu Work: wpaul@ctr.columbia.edu | Center for Telecommunications Research Home: wpaul@skynet.ctr.columbia.edu | Columbia University, New York City ============================================================================= "It is not I who am crazy; it is I who am mad!" - Ren Hoek, "Space Madness" ============================================================================= To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message