Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/qbus Driver for the DELQA-PLUS card in Turbo mode, f...



details:   https://anonhg.NetBSD.org/src/rev/5aa04a389736
branches:  trunk
changeset: 551052:5aa04a389736
user:      ragge <ragge%NetBSD.org@localhost>
date:      Thu Aug 28 10:03:32 2003 +0000

description:
Driver for the DELQA-PLUS card in Turbo mode, from 2.11BSD, written by
Steven M. Schultz.

diffstat:

 sys/dev/qbus/if_qt.c    |  920 ++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/qbus/if_qtreg.h |  208 ++++++++++
 2 files changed, 1128 insertions(+), 0 deletions(-)

diffs (truncated from 1136 to 300 lines):

diff -r 6a228297d1b2 -r 5aa04a389736 sys/dev/qbus/if_qt.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/qbus/if_qt.c      Thu Aug 28 10:03:32 2003 +0000
@@ -0,0 +1,920 @@
+/*     $NetBSD: if_qt.c,v 1.1 2003/08/28 10:03:32 ragge Exp $  */
+/*
+ * Copyright (c) 1992 Steven M. Schultz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     @(#)if_qt.c     1.2 (2.11BSD) 2/20/93
+ */
+/*
+ *
+ * Modification History 
+ * 23-Feb-92 -- sms
+ *     Rewrite the buffer handling so that fewer than the maximum number of
+ *     buffers may be used (32 receive and 12 transmit buffers consume 66+kb
+ *     of main system memory in addition to the internal structures in the
+ *     networking code).  A freelist of available buffers is maintained now.
+ *     When I/O operations complete the associated buffer is placed on the 
+ *     freelist (a single linked list for simplicity) and when an I/O is 
+ *     started a buffer is pulled off the list. 
+ *
+ * 20-Feb-92 -- sms
+ *     It works!  Darned board couldn't handle "short" rings - those rings
+ *     where only half the entries were made available to the board (the
+ *     ring descriptors were the full size, merely half the entries were
+ *     flagged as belonging always to the driver).  Grrrr.  Would have thought
+ *     the board could skip over those entries reserved by the driver. 
+ *     Now to find a way not to have to allocated 32+12 times 1.5kb worth of 
+ *     buffers...
+ *
+ * 03-Feb-92 -- sms
+ *     Released but still not working.  The driver now responds to arp and
+ *     ping requests.  The board is apparently not returning ring descriptors
+ *     to the driver so eventually we run out of buffers.  Back to the
+ *     drawing board.
+ *
+ * 28-Dec-92 -- sms
+ *     Still not released.  Hiatus in finding free time and thin-netting
+ *     the systems (many thanks Terry!).
+ *     Added logic to dynamically allocate a vector and initialize it.
+ *
+ * 23-Oct-92 -- sms
+ *     The INIT block must (apparently) be quadword aligned [no thanks to
+ *     the manual for not mentioning that fact].  The necessary alignment
+ *     is achieved by allocating the INIT block from main memory ('malloc'
+ *     guarantees click alignment) and mapping it as needed (which is _very_
+ *     infrequently).  A check for quadword alignment of the ring descriptors
+ *     was added - at present the descriptors are properly aligned, if this
+ *     should change then something will have to be done (like do it "right").
+ *     Darned alignment restrictions!
+ *
+ *     A couple of typos were corrected (missing parentheses, reversed 
+ *     arguments to printf calls, etc).
+ *
+ * 13-Oct-92 -- sms%wlv.iipo.gtegsc.com@localhost
+ *     Created based on the DELQA-PLUS addendum to DELQA User's Guide.
+ *     This driver ('qt') is selected at system configuration time.  If the 
+ *     board * is not a DELQA-YM an error message will be printed and the 
+ *     interface will not be attached.
+*/
+ 
+#include "qt.h"
+#if    NQT > 0
+
+#include "param.h"
+#include "pdp/psl.h"
+#include "pdp/seg.h"
+#include "map.h"
+#include "systm.h"
+#include "mbuf.h"
+#include "buf.h"
+#include "protosw.h"
+#include "socket.h"
+#include "ioctl.h"
+#include "errno.h"
+#include "syslog.h"
+#include "time.h"
+#include "kernel.h"
+
+#include "../net/if.h"
+#include "../net/netisr.h"
+#include "../net/route.h"
+
+#ifdef INET
+#include "domain.h"
+#include "../netinet/in.h"
+#include "../netinet/in_systm.h"
+#include "../netinet/in_var.h"
+#include "../netinet/ip.h"
+#include "../netinet/if_ether.h"
+#endif
+
+#ifdef NS
+#include "../netns/ns.h"
+#include "../netns/ns_if.h"
+#endif
+
+#include "if_qtreg.h"
+#include "if_uba.h"
+#include "../pdpuba/ubavar.h"
+ 
+#define NRCV   16              /* Receive descriptors (must be <= 32) */
+#define NXMT   6               /* Transmit descriptors (must be <= 12) */
+#if    NRCV > 32 || NXMT > 12
+       generate an error
+#endif
+ 
+       struct  qt_uba
+               {
+               struct  qt_uba  *next;  /* link to next buffer in list or
+                                        * NULL if the last buffer
+                                       */
+               struct  ifuba   ubabuf; /* buffer descriptor */
+               };
+
+struct qt_softc {
+       struct  arpcom is_ac;           /* common part - must be first  */
+#define        is_if   is_ac.ac_if             /* network-visible interface    */
+#define        is_addr is_ac.ac_enaddr         /* hardware Ethernet address    */
+       struct  qt_uba  *freelist;      /* list of available buffers    */
+       struct  qt_uba  ifrw[NRCV + NXMT];
+       u_short initclick;              /* click addr of the INIT block */
+       struct  qt_rring *rring;        /* Receive ring address         */
+       struct  qt_tring *tring;        /* Transmit ring address        */
+       char    r_align[QT_MAX_RCV * sizeof (struct qt_rring) + 8];
+       char    t_align[QT_MAX_XMT * sizeof (struct qt_tring) + 8];
+       short   qt_flags;               /* software state               */
+#define        QTF_RUNNING     0x1
+#define        QTF_STARTUP     0x2             /* Waiting for start interrupt  */
+       char    rindex;                 /* Receive Completed Index      */
+       char    nxtrcv;                 /* Next Receive Index           */
+       char    nrcv;                   /* Number of Receives active    */
+       char    tindex;                 /* Transmit index               */
+       char    otindex;                /* Old transmit index           */
+       char    nxmit;                  /* # of xmits in progress       */
+       struct  qtdevice *addr;         /* device CSR addr              */
+} qt_softc[NQT];
+
+struct uba_device *qtinfo[NQT];
+ 
+int    qtattach(), qtintr(), qtinit(), qtoutput(), qtioctl();
+ 
+extern struct ifnet loif;
+
+u_short qtstd[] = { 0 };
+
+struct uba_driver qtdriver =
+       { 0, 0, qtattach, 0, qtstd, "qe", qtinfo };
+ 
+/*
+ * Maximum packet size needs to include 4 bytes for the CRC 
+ * on received packets.
+*/
+#define MAXPACKETSIZE (ETHERMTU + sizeof (struct ether_header) + 4)
+#define        MINPACKETSIZE 64
+
+/*
+ * The C compiler's propensity for prepending '_'s to names is the reason
+ * for the hack below.  We need the "handler" address (the code which
+ * sets up the interrupt stack frame) in order to initialize the vector.
+*/
+
+static int qtfoo()
+       {
+       asm("mov $qtintr, r0");         /* return value is in r0 */
+       }
+
+/*
+ * Interface exists.  More accurately, something exists at the CSR (see
+ * sys/sys_net.c) -- there's no guarantee it's a DELQA-YM.
+ *
+ * The ring descriptors are initialized, the buffers allocated using first the
+ * DMA region allocated at network load time and then later main memory.  The
+ * INIT block is filled in and the device is poked/probed to see if it really
+ * is a DELQA-YM.  If the device is not a -YM then a message is printed and
+ * the 'if_attach' call is skipped.  For a -YM the START command is issued,
+ * but the device is not marked as running|up - that happens at interrupt level
+ * when the device interrupts to say it has started.
+*/
+
+qtattach(ui)
+       struct uba_device *ui;
+       {
+       register struct qt_softc *sc = &qt_softc[ui->ui_unit];
+       register struct ifnet *ifp = &sc->is_if;
+       register struct qt_init *iniblk = (struct qt_init *)SEG5;
+       segm    seg5;
+       long    bufaddr;
+       extern int nextiv();
+ 
+       ifp->if_unit = ui->ui_unit;
+       ifp->if_name = "qe";
+       ifp->if_mtu = ETHERMTU;
+       ifp->if_flags = IFF_BROADCAST;
+ 
+/*
+ * Fill in most of the INIT block: vector, options (interrupt enable), ring
+ * locations.  The physical address is copied from the ROMs as part of the
+ * -YM testing proceedure.  The CSR is saved here rather than in qtinit()
+ * because the qtturbo() routine needs it.
+ *
+ * The INIT block must be quadword aligned.  Using malloc() guarantees click
+ * (64 byte) alignment.  Since the only time the INIT block is referenced is
+ * at 'startup' or 'reset' time there is really no time penalty (and a modest
+ * D space savings) involved.
+*/
+       sc->addr = (struct qtdevice *)ui->ui_addr;
+       sc->initclick = MALLOC(coremap, btoc(sizeof (struct qt_init)));
+       saveseg5(seg5);
+       mapseg5(sc->initclick, 077406);
+       bzero(iniblk, sizeof (struct qt_init));
+       sc->rring = (struct qt_rring *)(((int)sc->r_align + 7) & ~7);
+       sc->tring = (struct qt_tring *)(((int)sc->t_align + 7) & ~7);
+
+/*
+ * Fetch the next available interrupt vector.  The routine is in the kernel
+ * (for several reasons) so use SKcall.  Then initialize the vector with
+ * the address of our 'handler' and PSW of supervisor, priority 4 and unit
+*/
+       iniblk->vector = SKcall(nextiv, 0);
+       mtkd(iniblk->vector, qtfoo());
+       mtkd(iniblk->vector + 2, PSL_CURSUP | PSL_BR4 | ifp->if_unit);
+
+       iniblk->options = INIT_OPTIONS_INT;
+       bufaddr = startnet + (long)sc->rring;
+       iniblk->rx_lo = loint(bufaddr);
+       iniblk->rx_hi = hiint(bufaddr);
+       bufaddr = startnet + (long)sc->tring;
+       iniblk->tx_lo = loint(bufaddr);
+       iniblk->tx_hi = hiint(bufaddr);
+       restorseg5(seg5);
+
+/*
+ * Now allocate the buffers and initialize the buffers.  This should _never_
+ * fail because main memory is allocated after the DMA pool is used up.
+*/
+
+       if      (!qbaini(sc, NRCV + NXMT))
+               return;         /* XXX */
+ 
+       ifp->if_init = qtinit;
+       ifp->if_output = qtoutput;
+       ifp->if_ioctl = qtioctl;
+       ifp->if_reset = 0;
+       if      (qtturbo(sc))
+               if_attach(ifp);
+       }
+ 
+qtturbo(sc)
+       register struct qt_softc *sc;
+       {
+       register int i;
+       register struct qtdevice *addr = sc->addr;
+       struct  qt_init *iniblk = (struct qt_init *)SEG5;
+       segm    seg5;
+
+/*
+ * Issue the software reset.  Delay 150us.  The board should now be in
+ * DELQA-Normal mode.  Set ITB and DEQTA select.  If both bits do not
+ * stay turned on then the board is not a DELQA-YM.
+*/
+       addr->arqr = ARQR_SR;
+       addr->arqr = 0;
+       delay(150L);
+
+       addr->srr = 0x8001;             /* MS | ITB */
+       i = addr->srr;
+       addr->srr = 0x8000;             /* Turn off ITB, set DELQA select */
+       if      (i != 0x8001)
+               {
+               printf("qt@%o !-YM\n", addr);
+               return(0);
+               }
+/*
+ * Board is a DELQA-YM.  Send the commands to enable Turbo mode.  Delay
+ * 1 second, testing the SRR register every millisecond to see if the



Home | Main Index | Thread Index | Old Index