Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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 = &ltpc_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(&ltpc_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(&ltpc_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 = &ltdmabuf[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 = &ltpc_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(&ltpc_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(&ltpc_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(&ltpc_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(&ltpc_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);