^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*** ltpc.c -- a driver for the LocalTalk PC card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 1995,1996 Bradford W. Johnson <johns393@maroon.tc.umn.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This software may be used and distributed according to the terms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * of the GNU General Public License, incorporated herein by reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This is ALPHA code at best. It may not work for you. It may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * damage your equipment. It may damage your relations with other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * users of your network. Use it at your own risk!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Based in part on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * skeleton.c by Donald Becker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * dummy.c by Nick Holloway and Alan Cox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * loopback.c by Ross Biro, Fred van Kampen, Donald Becker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * the netatalk source code (UMICH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * lots of work on the card...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * I do not have access to the (proprietary) SDK that goes with the card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * If you do, I don't want to know about it, and you can probably write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * a better driver yourself anyway. This does mean that the pieces that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * talk to the card are guesswork on my part, so use at your own risk!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * This is my first try at writing Linux networking code, and is also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * guesswork. Again, use at your own risk! (Although on this part, I'd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * welcome suggestions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * This is a loadable kernel module which seems to work at my site
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * consisting of a 1.2.13 linux box running netatalk 1.3.3, and with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * the kernel support from 1.3.3b2 including patches routing.patch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * and ddp.disappears.from.chooser. In order to run it, you will need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * to patch ddp.c and aarp.c in the kernel, but only a little...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * I'm fairly confident that while this is arguably badly written, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * problems that people experience will be "higher level", that is, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * complications in the netatalk code. The driver itself doesn't do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * anything terribly complicated -- it pretends to be an ether device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * as far as netatalk is concerned, strips the DDP data out of the ether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * frame and builds a LLAP packet to send out the card. In the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * direction, it receives LLAP frames from the card and builds a fake
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * ether packet that it then tosses up to the networking code. You can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * argue (correctly) that this is an ugly way to do things, but it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * requires a minimal amount of fooling with the code in ddp.c and aarp.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * The card will do a lot more than is used here -- I *think* it has the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * layers up through ATP. Even if you knew how that part works (which I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * don't) it would be a big job to carve up the kernel ddp code to insert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * things at a higher level, and probably a bad idea...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * There are a number of other cards that do LocalTalk on the PC. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * nobody finds any insurmountable (at the netatalk level) problems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * here, this driver should encourage people to put some work into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * other cards (some of which I gather are still commercially available)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * and also to put hooks for LocalTalk into the official ddp code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * I welcome comments and suggestions. This is my first try at Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * networking stuff, and there are probably lots of things that I did
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * suboptimally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /***
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * $Log: ltpc.c,v $
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Revision 1.1.2.1 2000/03/01 05:35:07 jgarzik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * at and tr cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Revision 1.8 1997/01/28 05:44:54 bradford
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Clean up for non-module a little.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Hacked about a bit to clean things up - Alan Cox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Probably broken it from the origina 1.8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * 1998/11/09: David Huggins-Daines <dhd@debian.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * Cleaned up the initialization code to use the standard autoirq methods,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) and to probe for things in the standard order of i/o, irq, dma. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) removes the "reset the reset" hack, because I couldn't figure out an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) easy way to get the card to trigger an interrupt after it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Added support for passing configuration parameters on the kernel command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) line and through insmod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * Changed the device name from "ltalk0" to "lt0", both to conform with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) other localtalk driver, and to clear up the inconsistency between the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) module and the non-module versions of the driver :-)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Added a bunch of comments (I was going to make some enums for the state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) codes and the register offsets, but I'm still not sure exactly what their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) semantics are)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Don't poll anymore in interrupt-driven mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * It seems to work as a module now (as of 2.1.127), but I don't think
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) I'm responsible for that...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * Revision 1.7 1996/12/12 03:42:33 bradford
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * DMA alloc cribbed from 3c505.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Revision 1.6 1996/12/12 03:18:58 bradford
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Added virt_to_bus; works in 2.1.13.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Revision 1.5 1996/12/12 03:13:22 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * xmitQel initialization -- think through better though.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Revision 1.4 1996/06/18 14:55:55 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * Change names to ltpc. Tabs. Took a shot at dma alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * although more needs to be done eventually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Revision 1.3 1996/05/22 14:59:39 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Change dev->open, dev->close to track dummy.c in 1.99.(around 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * Revision 1.2 1996/05/22 14:58:24 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Change tabs mostly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * Revision 1.1 1996/04/23 04:45:09 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Initial revision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * Revision 0.16 1996/03/05 15:59:56 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Change ARPHRD_LOCALTLK definition to the "real" one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Revision 0.15 1996/03/05 06:28:30 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * Changes for kernel 1.3.70. Still need a few patches to kernel, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * it's getting closer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * Revision 0.14 1996/02/25 17:38:32 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * More cleanups. Removed query to card on get_stats.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Revision 0.13 1996/02/21 16:27:40 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * Refix debug_print_skb. Fix mac.raw gotcha that appeared in 1.3.65.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Clean up receive code a little.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Revision 0.12 1996/02/19 16:34:53 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * Fix debug_print_skb. Kludge outgoing snet to 0 when using startup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * range. Change debug to mask: 1 for verbose, 2 for higher level stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * including packet printing, 4 for lower level (card i/o) stuff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * Revision 0.11 1996/02/12 15:53:38 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Added router sends (requires new aarp.c patch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Revision 0.10 1996/02/11 00:19:35 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Change source LTALK_LOGGING debug switch to insmod ... debug=2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Revision 0.9 1996/02/10 23:59:35 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Fixed those fixes for 1.2 -- DANGER! The at.h that comes with netatalk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * has a *different* definition of struct sockaddr_at than the Linux kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * does. This is an "insidious and invidious" bug...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * (Actually the preceding comment is false -- it's the atalk.h in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * ancient atalk-0.06 that's the problem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * Revision 0.8 1996/02/10 19:09:00 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Merge 1.3 changes. Tested OK under 1.3.60.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Revision 0.7 1996/02/10 17:56:56 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Added debug=1 parameter on insmod for debugging prints. Tried
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * to fix timer unload on rmmod, but I don't think that's the problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Revision 0.6 1995/12/31 19:01:09 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * Clean up rmmod, irq comments per feedback from Corin Anderson (Thanks Corey!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * Clean up initial probing -- sometimes the card wakes up latched in reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * Revision 0.5 1995/12/22 06:03:44 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * Added comments in front and cleaned up a bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * This version sent out to people.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * Revision 0.4 1995/12/18 03:46:44 root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Return shortDDP to longDDP fake to 0/0. Added command structs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* ltpc jumpers are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Interrupts -- set at most one. If none are set, the driver uses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * polled mode. Because the card was developed in the XT era, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * original documentation refers to IRQ2. Since you'll be running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * this on an AT (or later) class machine, that really means IRQ9.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * SW1 IRQ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * SW2 IRQ 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * SW3 IRQ 9 (2 in original card documentation only applies to XT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * DMA -- choose DMA 1 or 3, and set both corresponding switches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * SW4 DMA 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * SW5 DMA 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * SW6 DMA 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * SW7 DMA 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * I/O address -- choose one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * SW8 220 / 240
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* To have some stuff logged, do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * insmod ltpc.o debug=1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * For a whole bunch of stuff, use higher numbers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * The default is 0, i.e. no messages except for the probe results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* insmod-tweakable variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) static int debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define DEBUG_VERBOSE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) #define DEBUG_UPPER 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #define DEBUG_LOWER 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #include <linux/if_ltalk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #include <linux/atalk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) #include <net/Space.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* our stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #include "ltpc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static DEFINE_SPINLOCK(txqueue_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static DEFINE_SPINLOCK(mbox_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* function prototypes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) void *dbuf, int dbuflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int sendup_buffer (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* Dma Memory related stuff, cribbed directly from 3c505.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static unsigned long dma_mem_alloc(int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int order = get_order(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return __get_dma_pages(GFP_KERNEL, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* DMA data buffer, DMA command buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static unsigned char *ltdmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static unsigned char *ltdmacbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* private struct, holds our appletalk address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct ltpc_private
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct atalk_addr my_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* transmit queue element struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct xmitQel {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct xmitQel *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* command buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) unsigned char *cbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) short cbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* data buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) unsigned char *dbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) short dbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) unsigned char QWrite; /* read or write data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) unsigned char mailbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /* the transmit queue itself */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static struct xmitQel *xmQhd, *xmQtl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void enQ(struct xmitQel *qel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) qel->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) spin_lock_irqsave(&txqueue_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (xmQtl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) xmQtl->next = qel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) xmQhd = qel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) xmQtl = qel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) spin_unlock_irqrestore(&txqueue_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (debug & DEBUG_LOWER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) printk("enqueued a 0x%02x command\n",qel->cbuf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static struct xmitQel *deQ(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct xmitQel *qel=NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) spin_lock_irqsave(&txqueue_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (xmQhd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) qel = xmQhd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) xmQhd = qel->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if(!xmQhd) xmQtl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) spin_unlock_irqrestore(&txqueue_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if ((debug & DEBUG_LOWER) && qel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) printk(KERN_DEBUG "ltpc: dequeued command ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) n = qel->cbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (n>100) n=100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) for(i=0;i<n;i++) printk("%02x ",qel->cbuf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return qel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* and... the queue elements we'll be using */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static struct xmitQel qels[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* and their corresponding mailboxes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static unsigned char mailbox[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static unsigned char mboxinuse[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int wait_timeout(struct net_device *dev, int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* returns true if it stayed c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* this uses base+6, but it's ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* twenty second or so total */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) for(i=0;i<200000;i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if ( c != inb_p(dev->base_addr+6) ) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 1; /* timed out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* get the first free mailbox */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static int getmbox(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) spin_lock_irqsave(&mbox_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) for(i=1;i<16;i++) if(!mboxinuse[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) mboxinuse[i]=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) spin_unlock_irqrestore(&mbox_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) spin_unlock_irqrestore(&mbox_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* read a command from the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void handlefc(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* called *only* from idle, non-reentrant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int dma = dev->dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int base = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) flags=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) disable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) clear_dma_ff(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) set_dma_mode(dma,DMA_MODE_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) set_dma_addr(dma,virt_to_bus(ltdmacbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) set_dma_count(dma,50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) enable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) release_dma_lock(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) inb_p(base+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) inb_p(base+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if ( wait_timeout(dev,0xfc) ) printk("timed out in handlefc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* read data from the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static void handlefd(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int dma = dev->dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int base = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) flags=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) disable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) clear_dma_ff(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) set_dma_mode(dma,DMA_MODE_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) set_dma_addr(dma,virt_to_bus(ltdmabuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) set_dma_count(dma,800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) enable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) release_dma_lock(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) inb_p(base+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) inb_p(base+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if ( wait_timeout(dev,0xfd) ) printk("timed out in handlefd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) sendup_buffer(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static void handlewrite(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* called *only* from idle, non-reentrant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* on entry, 0xfb and ltdmabuf holds data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) int dma = dev->dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int base = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) flags=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) disable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) clear_dma_ff(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) set_dma_mode(dma,DMA_MODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) set_dma_addr(dma,virt_to_bus(ltdmabuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) set_dma_count(dma,800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) enable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) release_dma_lock(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) inb_p(base+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) inb_p(base+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if ( wait_timeout(dev,0xfb) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) flags=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) printk("timed out in handlewrite, dma res %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) get_dma_residue(dev->dma) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) release_dma_lock(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static void handleread(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* on entry, 0xfb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* on exit, ltdmabuf holds data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int dma = dev->dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int base = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) flags=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) disable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) clear_dma_ff(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) set_dma_mode(dma,DMA_MODE_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) set_dma_addr(dma,virt_to_bus(ltdmabuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) set_dma_count(dma,800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) enable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) release_dma_lock(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) inb_p(base+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) inb_p(base+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if ( wait_timeout(dev,0xfb) ) printk("timed out in handleread\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static void handlecommand(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* on entry, 0xfa and ltdmacbuf holds command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int dma = dev->dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int base = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) flags=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) disable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) clear_dma_ff(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) set_dma_mode(dma,DMA_MODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) set_dma_addr(dma,virt_to_bus(ltdmacbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) set_dma_count(dma,50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) enable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) release_dma_lock(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) inb_p(base+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) inb_p(base+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if ( wait_timeout(dev,0xfa) ) printk("timed out in handlecommand\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /* ready made command for getting the result from the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static unsigned char rescbuf[2] = {LT_GETRESULT,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static unsigned char resdbuf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static int QInIdle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* idle expects to be called with the IRQ line high -- either because of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * an interrupt, or because the line is tri-stated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static void idle(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* FIXME This is initialized to shut the warning up, but I need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * think this through again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct xmitQel *q = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int oops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int base = dev->base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) spin_lock_irqsave(&txqueue_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if(QInIdle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) spin_unlock_irqrestore(&txqueue_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) QInIdle = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) spin_unlock_irqrestore(&txqueue_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* this tri-states the IRQ line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) (void) inb_p(base+6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) oops = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (0>oops--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) printk("idle: looped too many times\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) state = inb_p(base+6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (state != inb_p(base+6)) goto loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) switch(state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case 0xfc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* incoming command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (debug & DEBUG_LOWER) printk("idle: fc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) handlefc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) case 0xfd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* incoming data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if(debug & DEBUG_LOWER) printk("idle: fd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) handlefd(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) case 0xf9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* result ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (debug & DEBUG_LOWER) printk("idle: f9\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if(!mboxinuse[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) mboxinuse[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) qels[0].cbuf = rescbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) qels[0].cbuflen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) qels[0].dbuf = resdbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) qels[0].dbuflen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) qels[0].QWrite = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) qels[0].mailbox = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) enQ(&qels[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) inb_p(dev->base_addr+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) inb_p(dev->base_addr+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if( wait_timeout(dev,0xf9) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) printk("timed out idle f9\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) case 0xf8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* ?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (xmQhd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) inb_p(dev->base_addr+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) inb_p(dev->base_addr+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if(wait_timeout(dev,0xf8) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) printk("timed out idle f8\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case 0xfa:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* waiting for command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if(debug & DEBUG_LOWER) printk("idle: fa\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (xmQhd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) q=deQ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) memcpy(ltdmacbuf,q->cbuf,q->cbuflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ltdmacbuf[1] = q->mailbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (debug>1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) printk("ltpc: sent command ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) n = q->cbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (n>100) n=100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) for(i=0;i<n;i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) printk("%02x ",ltdmacbuf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) handlecommand(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if(0xfa==inb_p(base+6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* we timed out, so return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) /* we don't seem to have a command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (!mboxinuse[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) mboxinuse[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) qels[0].cbuf = rescbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) qels[0].cbuflen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) qels[0].dbuf = resdbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) qels[0].dbuflen = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) qels[0].QWrite = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) qels[0].mailbox = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) enQ(&qels[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) printk("trouble: response command already queued\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case 0Xfb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* data transfer ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if(debug & DEBUG_LOWER) printk("idle: fb\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if(q->QWrite) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) memcpy(ltdmabuf,q->dbuf,q->dbuflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) handlewrite(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) handleread(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* non-zero mailbox numbers are for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) commmands, 0 is for GETRESULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if(q->mailbox) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) memcpy(q->dbuf,ltdmabuf,q->dbuflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* this was a result */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) mailbox[ 0x0f & ltdmabuf[0] ] = ltdmabuf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) mboxinuse[0]=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) goto loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) QInIdle=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* now set the interrupts back as appropriate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* the first read takes it out of tri-state (but still high) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* the second resets it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /* note that after this point, any read of base+6 will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) trigger an interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (dev->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) inb_p(base+7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) inb_p(base+7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static int do_write(struct net_device *dev, void *cbuf, int cbuflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) void *dbuf, int dbuflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) int i = getmbox();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) qels[i].cbuf = cbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) qels[i].cbuflen = cbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) qels[i].dbuf = dbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) qels[i].dbuflen = dbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) qels[i].QWrite = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) qels[i].mailbox = i; /* this should be initted rather */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) enQ(&qels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) idle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ret = mailbox[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) mboxinuse[i]=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) printk("ltpc: could not allocate mbox\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) void *dbuf, int dbuflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) int i = getmbox();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) qels[i].cbuf = cbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) qels[i].cbuflen = cbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) qels[i].dbuf = dbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) qels[i].dbuflen = dbuflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) qels[i].QWrite = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) qels[i].mailbox = i; /* this should be initted rather */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) enQ(&qels[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) idle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ret = mailbox[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) mboxinuse[i]=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) printk("ltpc: could not allocate mbox\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* end of idle handlers -- what should be seen is do_read, do_write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static struct timer_list ltpc_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static struct net_device *ltpc_timer_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static netdev_tx_t ltpc_xmit(struct sk_buff *skb, struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) static int read_30 ( struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) lt_command c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) c.getflags.command = LT_GETFLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return do_read(dev, &c, sizeof(c.getflags),&c,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static int set_30 (struct net_device *dev,int x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) lt_command c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) c.setflags.command = LT_SETFLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) c.setflags.flags = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return do_write(dev, &c, sizeof(c.setflags),&c,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* LLAP to DDP translation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int sendup_buffer (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /* on entry, command is in ltdmacbuf, data in ltdmabuf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /* called from idle, non-reentrant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int dnode, snode, llaptype, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int sklen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct lt_rcvlap *ltc = (struct lt_rcvlap *) ltdmacbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (ltc->command != LT_RCVLAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) printk("unknown command 0x%02x from ltpc card\n",ltc->command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) dnode = ltc->dnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) snode = ltc->snode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) llaptype = ltc->laptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) len = ltc->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) sklen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (llaptype == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) sklen += 8; /* correct for short ddp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if(sklen > 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) printk(KERN_INFO "%s: nonsense length in ltpc command 0x14: 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) dev->name,sklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if ( (llaptype==0) || (llaptype>2) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) printk(KERN_INFO "%s: unknown LLAP type: %d\n",dev->name,llaptype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) skb = dev_alloc_skb(3+sklen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) printk("%s: dropping packet due to memory squeeze.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (sklen > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) skb_reserve(skb,8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) skb_put(skb,len+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) skb->protocol = htons(ETH_P_LOCALTALK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /* add LLAP header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) skb->data[0] = dnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) skb->data[1] = snode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) skb->data[2] = llaptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) skb_reset_mac_header(skb); /* save pointer to llap header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) skb_pull(skb,3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* copy ddp(s,e)hdr + contents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) skb_copy_to_linear_data(skb, ltdmabuf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) dev->stats.rx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* toss it onwards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* the handler for the board interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) ltpc_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) struct net_device *dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (dev==NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) printk("ltpc_interrupt: unknown device.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) inb_p(dev->base_addr+6); /* disable further interrupts from board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) idle(dev); /* handle whatever is coming in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* idle re-enables interrupts from board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /***
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * The ioctls that the driver responds to are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * SIOCSIFADDR -- do probe using the passed node hint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * SIOCGIFADDR -- return net, node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * some of this stuff should be done elsewhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct sockaddr_at *sa = (struct sockaddr_at *) &ifr->ifr_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* we'll keep the localtalk node address in dev->pa_addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct ltpc_private *ltpc_priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct atalk_addr *aa = <pc_priv->my_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct lt_init c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) int ltflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if(debug & DEBUG_VERBOSE) printk("ltpc_ioctl called\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) switch(cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case SIOCSIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) aa->s_net = sa->sat_addr.s_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* this does the probe and returns the node addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) c.command = LT_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) c.hint = sa->sat_addr.s_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) aa->s_node = do_read(dev,&c,sizeof(c),&c,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* get all llap frames raw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ltflags = read_30(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ltflags |= LT_FLAG_ALLLAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) set_30 (dev,ltflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) dev->broadcast[0] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) dev->dev_addr[0] = aa->s_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) dev->addr_len=1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) case SIOCGIFADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) sa->sat_addr.s_net = aa->s_net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) sa->sat_addr.s_node = aa->s_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static void set_multicast_list(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) /* This needs to be present to keep netatalk happy. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /* Actually netatalk needs fixing! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static int ltpc_poll_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static void ltpc_poll(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) del_timer(<pc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if(debug & DEBUG_VERBOSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (!ltpc_poll_counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) ltpc_poll_counter = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) printk("ltpc poll is alive\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) ltpc_poll_counter--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) /* poll 20 times per second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) idle(ltpc_timer_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ltpc_timer.expires = jiffies + HZ/20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) add_timer(<pc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /* DDP to LLAP translation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static netdev_tx_t ltpc_xmit(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /* in kernel 1.3.xx, on entry skb->data points to ddp header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * and skb->len is the length of the ddp data + ddp header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) struct lt_sendlap cbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) unsigned char *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) cbuf.command = LT_SENDLAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) cbuf.dnode = skb->data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) cbuf.laptype = skb->data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) skb_pull(skb,3); /* skip past LLAP header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) cbuf.length = skb->len; /* this is host order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if(debug & DEBUG_UPPER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) printk("command ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) for(i=0;i<6;i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) printk("%02x ",((unsigned char *)&cbuf)[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) hdr = skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) do_write(dev, &cbuf, sizeof(cbuf), hdr, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if(debug & DEBUG_UPPER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) printk("sent %d ddp bytes\n",skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) for (i = 0; i < skb->len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) printk("%02x ", hdr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) dev->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) dev->stats.tx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) /* initialization stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) static int __init ltpc_probe_dma(int base, int dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) int want = (dma == 3) ? 2 : (dma == 1) ? 1 : 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) unsigned long f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (want & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (request_dma(1,"ltpc")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) want &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) f=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) disable_dma(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) clear_dma_ff(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) set_dma_mode(1,DMA_MODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) set_dma_addr(1,virt_to_bus(ltdmabuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) set_dma_count(1,sizeof(struct lt_mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) enable_dma(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) release_dma_lock(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (want & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (request_dma(3,"ltpc")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) want &= ~2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) f=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) disable_dma(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) clear_dma_ff(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) set_dma_mode(3,DMA_MODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) set_dma_addr(3,virt_to_bus(ltdmabuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) set_dma_count(3,sizeof(struct lt_mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) enable_dma(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) release_dma_lock(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) /* set up request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /* FIXME -- do timings better! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) ltdmabuf[0] = LT_READMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) ltdmabuf[1] = 1; /* mailbox */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ltdmabuf[2] = 0; ltdmabuf[3] = 0; /* address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) ltdmabuf[4] = 0; ltdmabuf[5] = 1; /* read 0x0100 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) ltdmabuf[6] = 0; /* dunno if this is necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) inb_p(io+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) inb_p(io+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) timeout = jiffies+100*HZ/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) while(time_before(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if ( 0xfa == inb_p(io+6) ) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) inb_p(io+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) inb_p(io+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) while(time_before(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if ( 0xfb == inb_p(io+6) ) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* release the other dma channel (if we opened both of them) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if ((want & 2) && (get_dma_residue(3)==sizeof(struct lt_mem))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) want &= ~2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) free_dma(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if ((want & 1) && (get_dma_residue(1)==sizeof(struct lt_mem))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) want &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) free_dma(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (!want)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return (want & 2) ? 3 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static const struct net_device_ops ltpc_netdev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) .ndo_start_xmit = ltpc_xmit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) .ndo_do_ioctl = ltpc_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) .ndo_set_rx_mode = set_multicast_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) struct net_device * __init ltpc_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) int x=0,y=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) int autoirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) unsigned long f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) dev = alloc_ltalkdev(sizeof(struct ltpc_private));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /* probe for the I/O port address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (io != 0x240 && request_region(0x220,8,"ltpc")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) x = inb_p(0x220+6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if ( (x!=0xff) && (x>=0xf0) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) io = 0x220;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) goto got_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) release_region(0x220,8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (io != 0x220 && request_region(0x240,8,"ltpc")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) y = inb_p(0x240+6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if ( (y!=0xff) && (y>=0xf0) ){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) io = 0x240;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) goto got_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) release_region(0x240,8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /* give up in despair */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) got_port:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) /* probe for the IRQ line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (irq < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) unsigned long irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) irq_mask = probe_irq_on();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /* reset the interrupt line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) inb_p(io+7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) inb_p(io+7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* trigger an interrupt (I hope) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) inb_p(io+6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) mdelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) autoirq = probe_irq_off(irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (autoirq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) printk(KERN_ERR "ltpc: probe at %#x failed to detect IRQ line.\n", io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) irq = autoirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* allocate a DMA buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ltdmabuf = (unsigned char *) dma_mem_alloc(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (!ltdmabuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) printk(KERN_ERR "ltpc: mem alloc failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) goto out2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) ltdmacbuf = <dmabuf[800];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if(debug & DEBUG_VERBOSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /* reset the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) inb_p(io+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) inb_p(io+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) inb_p(io+0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) inb_p(io+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) inb_p(io+7); /* clear reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) inb_p(io+4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) inb_p(io+5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) inb_p(io+5); /* enable dma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) inb_p(io+6); /* tri-state interrupt line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) ssleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /* now, figure out which dma channel we're using, unless it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) already been specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) /* well, 0 is a legal DMA channel, but the LTPC card doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) use it... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) dma = ltpc_probe_dma(io, dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (!dma) { /* no dma channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) printk(KERN_ERR "No DMA channel found on ltpc card.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) goto out3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /* print out friendly message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if(irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) dev->netdev_ops = <pc_netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) dev->base_addr = io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) dev->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) dev->dma = dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) /* the card will want to send a result at this point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) /* (I think... leaving out this part makes the kernel crash,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) so I put it back in...) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) f=claim_dma_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) disable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) clear_dma_ff(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) set_dma_mode(dma,DMA_MODE_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) set_dma_addr(dma,virt_to_bus(ltdmabuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) set_dma_count(dma,0x100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) enable_dma(dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) release_dma_lock(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) (void) inb_p(io+3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) (void) inb_p(io+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) timeout = jiffies+100*HZ/100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) while(time_before(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if( 0xf9 == inb_p(io+6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if(debug & DEBUG_VERBOSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) printk("setting up timer and irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /* grab it and don't let go :-) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (irq && request_irq( irq, ltpc_interrupt, 0, "ltpc", dev) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) (void) inb_p(io+7); /* enable interrupts from board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) (void) inb_p(io+7); /* and reset irq line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if( irq )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) dev->irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* polled mode -- 20 times per second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) /* this is really, really slow... should it poll more often? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) ltpc_timer_dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) timer_setup(<pc_timer, ltpc_poll, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) ltpc_timer.expires = jiffies + HZ/20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) add_timer(<pc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) err = register_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) goto out4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) out4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) del_timer_sync(<pc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (dev->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) out3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) free_pages((unsigned long)ltdmabuf, get_order(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) out2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) release_region(io, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) /* handles "ltpc=io,irq,dma" kernel command lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) static int __init ltpc_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) int ints[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) str = get_options(str, ARRAY_SIZE(ints), ints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (ints[0] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (str && !strncmp(str, "auto", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) /* do nothing :-) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) /* usage message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) printk (KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) "ltpc: usage: ltpc=auto|iobase[,irq[,dma]]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) io = ints[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (ints[0] > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) irq = ints[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (ints[0] > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) dma = ints[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* ignore any other parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) __setup("ltpc=", ltpc_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) #endif /* MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) static struct net_device *dev_ltpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) module_param(debug, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) module_param_hw(io, int, ioport, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) module_param_hw(irq, int, irq, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) module_param_hw(dma, int, dma, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static int __init ltpc_module_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if(io == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) printk(KERN_NOTICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) "ltpc: Autoprobing is not recommended for modules\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) dev_ltpc = ltpc_probe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return PTR_ERR_OR_ZERO(dev_ltpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) module_init(ltpc_module_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) static void __exit ltpc_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) unregister_netdev(dev_ltpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) del_timer_sync(<pc_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if(debug & DEBUG_VERBOSE) printk("freeing irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (dev_ltpc->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) free_irq(dev_ltpc->irq, dev_ltpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if(debug & DEBUG_VERBOSE) printk("freeing dma\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (dev_ltpc->dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) free_dma(dev_ltpc->dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if(debug & DEBUG_VERBOSE) printk("freeing ioaddr\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) if (dev_ltpc->base_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) release_region(dev_ltpc->base_addr,8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) free_netdev(dev_ltpc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) if(debug & DEBUG_VERBOSE) printk("free_pages\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) free_pages( (unsigned long) ltdmabuf, get_order(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if(debug & DEBUG_VERBOSE) printk("returning from cleanup_module\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) module_exit(ltpc_cleanup);