The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/idt/idt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *      notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *      notice, this list of conditions and the following disclaimer in the
   12  *      documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *      must display the following acknowledgement:
   15  *      This product includes software developed by Matriplex, inc.
   16  * 4. The name of the author may not be used to endorse or promote products
   17  *      derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  ******************************************************************************
   32  *
   33  * This driver is derived from the Nicstar driver by Mark Tinguely, and
   34  * some of the original driver still exists here.  Those portions are...
   35  *   Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
   36  *   All rights reserved.
   37  *
   38  ******************************************************************************
   39  *
   40  *  This driver supports the Fore LE155, LE25, and IDT 77211 cards.
   41  *
   42  *  ATM CBR connections are supported, and bandwidth is allocated in
   43  *  slots of 64k each.  Three VBR queues handle traffic for VBR and
   44  *  UBR.  Two UBR queues prioritize UBR traffic.  ILMI and signalling
   45  *  get the higher priority queue, as well as UBR traffic that specifies
   46  *  a peak cell rate.  All other UBR traffic goes into the lower queue.
   47  *
   48  ******************************************************************************
   49  *
   50  *  The following sysctl variables are used:
   51  *
   52  * hw.idt.log_bufstat  (0)   Log free buffers (every few minutes)
   53  * hw.idt.log_vcs      (0)   Log VC opens, closes, and other events
   54  * hw.idt.bufs_large  (100)  Max/target number of free 2k buffers
   55  * hw.idt.bufs_small  (200)  Max/target number of free mbufs
   56  * hw.idt.cur_large   (R/O)  Current number of free 2k buffers
   57  * hw.idt.cur_small   (R/O)  Current number of free mbufs
   58  * hw.idt.qptr_hold    (1)   Optimize TX queue buffer for lowest overhead
   59  *
   60  * Note that the read-only buffer counts will not work with multiple cards.
   61  *
   62  ******************************************************************************
   63  *
   64  *  Assumptions:
   65  *
   66  *  1.  All mbuf clusters are 2048 bytes, and aligned.
   67  *  2.  All mbufs are 256 bytes, and aligned (see idt_intr_tsq).
   68  *
   69  *  Bugs:
   70  *
   71  *  1.  Function idt_detach() is unusuable because idt_release_mem() is
   72  *      incomplete.  The mbufs held in the free buffer queues can be
   73  *      recovered from the "mcheck" hash table.
   74  *  2.  The memory allocation could be cleaned up quite a bit.
   75  *
   76  ******************************************************************************
   77  */
   78 
   79 #include <sys/cdefs.h>
   80 __FBSDID("$FreeBSD$");
   81 
   82 #include <sys/param.h>
   83 #include <sys/systm.h>
   84 #include <sys/conf.h>
   85 #include <sys/mbuf.h>
   86 #include <sys/protosw.h>
   87 #include <sys/socket.h>
   88 #include <sys/sysctl.h>
   89 
   90 #include <sys/sockio.h>
   91 
   92 #include <sys/errno.h>
   93 #include <sys/malloc.h>
   94 #include <sys/kernel.h>
   95 #include <sys/proc.h>
   96 #include <sys/signalvar.h>
   97 #include <sys/mman.h>
   98 #include <machine/clock.h>
   99 #include <machine/cpu.h>        /* bootverbose */
  100 
  101 #include <sys/bus.h>
  102 #include <machine/bus.h>
  103 #include <sys/rman.h>
  104 #include <machine/resource.h>
  105 
  106 #include <net/if.h>
  107 #include <net/if_arp.h>
  108 
  109 /* Gross kludge to make lint compile again.  This sucks, but oh well */
  110 #ifdef COMPILING_LINT
  111 #undef MCLBYTES
  112 #undef MCLSHIFT
  113 #define MCLBYTES 2048
  114 #define MCLSHIFT 11
  115 #endif
  116 
  117 #if MCLBYTES != 2048
  118 #error "This nicstar driver depends on 2048 byte mbuf clusters."
  119 #endif
  120 
  121 #include <netatm/port.h>
  122 #include <netatm/queue.h>
  123 #include <netatm/atm.h>
  124 #include <netatm/atm_sys.h>
  125 #include <netatm/atm_sap.h>
  126 #include <netatm/atm_cm.h>
  127 #include <netatm/atm_if.h>
  128 #include <netatm/atm_stack.h>
  129 #include <netatm/atm_pcb.h>
  130 #include <netatm/atm_var.h>
  131 #include <netatm/atm_vc.h>
  132 
  133 #include <vm/vm.h>
  134 #include <vm/vm_kern.h>
  135 #include <vm/vm_param.h>
  136 #include <vm/pmap.h>
  137 #include <vm/vm_extern.h>
  138 
  139 #include <dev/idt/idtreg.h>
  140 #include <dev/idt/idtvar.h>
  141 
  142 #define MAXCARDS 10             /* set to impossibly high */
  143 
  144 /******************************************************************************
  145  *
  146  *  You may change IDT_LBUFS and IDT_SBUFS if you wish.
  147  */
  148 
  149 #define NICSTAR_LRG_SIZE        2048    /* must be power of two */
  150 #define IDT_LBUFS               100     /* default number of 2k buffers */
  151 #define IDT_SBUFS               200     /* default number of 96-byte buffers */
  152 
  153 #define IDT_TST_START           0x1c000 /* transmit schedule table start */
  154 #define IDT_SCD_START           0x1d000 /* segmentation channel descriptors start */
  155 #define IDT_SCD_SIZE            509     /* max number of SCD entries */
  156 
  157 #define NICSTAR_FIXPAGES        10
  158 
  159 static int idt_sysctl_logbufs = 0;      /* periodic buffer status messages */
  160        int idt_sysctl_logvcs = 0;       /* log VC open & close events      */
  161 static int idt_sysctl_buflarge = IDT_LBUFS;     /* desired large buffer queue */
  162 static int idt_sysctl_bufsmall = IDT_SBUFS;     /* desired small buffer queue */
  163 static int idt_sysctl_curlarge = 0;     /* current large buffer queue */
  164 static int idt_sysctl_cursmall = 0;     /* current small buffer queue */
  165 static int idt_sysctl_qptrhold = 1;     /* hold TX queue pointer back */
  166        int idt_sysctl_vbriscbr = 0;     /* use CBR slots for VBR VC's */
  167 
  168 SYSCTL_NODE(_hw, OID_AUTO, idt, CTLFLAG_RW, 0, "IDT Nicstar");
  169 
  170 SYSCTL_INT(_hw_idt, OID_AUTO, log_bufstat, CTLFLAG_RW,
  171     &idt_sysctl_logbufs, 0, "Log buffer status");
  172 SYSCTL_INT(_hw_idt, OID_AUTO, log_vcs, CTLFLAG_RW,
  173     &idt_sysctl_logvcs, 0, "Log VC open/close");
  174 
  175 SYSCTL_INT(_hw_idt, OID_AUTO, bufs_large, CTLFLAG_RW,
  176     &idt_sysctl_buflarge, IDT_LBUFS, "Large buffer queue");
  177 SYSCTL_INT(_hw_idt, OID_AUTO, bufs_small, CTLFLAG_RW,
  178     &idt_sysctl_bufsmall, IDT_SBUFS, "Small buffer queue");
  179 SYSCTL_INT(_hw_idt, OID_AUTO, cur_large, CTLFLAG_RD,
  180     &idt_sysctl_curlarge, 0, "Current large queue");
  181 SYSCTL_INT(_hw_idt, OID_AUTO, cur_small, CTLFLAG_RD,
  182     &idt_sysctl_cursmall, 0, "Current small queue");
  183 SYSCTL_INT(_hw_idt, OID_AUTO, qptr_hold, CTLFLAG_RW,
  184     &idt_sysctl_qptrhold, 1, "Optimize TX queue ptr");
  185 SYSCTL_INT(_hw_idt, OID_AUTO, vbr_is_cbr, CTLFLAG_RW,
  186     &idt_sysctl_vbriscbr, 0, "Use CBR for VBR VC's");
  187 
  188 /******************************************************************************
  189  *
  190  * common VCI values
  191  *
  192  * 0/0  Idle cells
  193  * 0/1  Meta signalling
  194  * x/1  Meta signalling
  195  * 0/2  Broadcast signalling
  196  * x/2  Broadcast signalling
  197  * x/3  Segment OAM F4 flow
  198  * x/4  End-end OAM F4 flow
  199  * 0/5  p-p signalling
  200  * x/5  p-p signalling
  201  * x/6  rate management
  202  * 0/14 SPANS
  203  * 0/15 SPANS
  204  * 0/16 ILMI
  205  * 0/18 PNNI
  206  */
  207 
  208 /*******************************************************************************
  209  *
  210  *  fixbuf memory map:
  211  *
  212  *  0000 - 1fff:  TSQ  Transmit status queue 1024 entries *  8 bytes each
  213  *  2000 - 3fff:  RSQ  Receive status queue,  512 entries * 16 bytes each
  214  *  4000 - 5fff:  VBR  segmentation channel queue (highest priority)
  215  *  6000 - 7fff:  ABR  segmentation channel queue (middle priority)
  216  *  8000 - 9fff:  UBR  segmentation channel queue (lowest priority)
  217  *
  218  *  IDT device memory map:
  219  *
  220  *  1fc00:  RX large buffer queue (4k)
  221  *  1f800:  RX small buffer queue (4k)
  222  *  1e800:  RX cells FIFO (16k)
  223  *  1e7f4:  SCD0 - VBR (12)
  224  *  1e7e8:  SCD1 - ABR (12)
  225  *  1e7dc:  SCD2 - UBR (12)
  226  *  1e7db:  CBR SCD end (last word)
  227  *  1d000:  CBR SCD start (509 entries)
  228  *  1cfff:  TST end (4095 available slots)
  229  *  1c000:  TST start (first CBR slot)
  230  *
  231  */
  232 
  233 static u_long idt_found = 0;
  234 
  235  /* -------- buffer management -------- */
  236 static int nicstar_sram_wr(nicstar_reg_t * const, u_long,
  237                            int, u_long, u_long, u_long, u_long);
  238 static int nicstar_sram_rd(nicstar_reg_t * const, u_long, u_long *);
  239 static int nicstar_add_buf(nicstar_reg_t * const, struct mbuf *,
  240                            struct mbuf *, u_long);
  241 static int nicstar_util_rd(nicstar_reg_t * const, u_long, u_long *);
  242 static int nicstar_util_wr(nicstar_reg_t * const, int, u_long, u_long);
  243       void nicstar_ld_rcv_buf(nicstar_reg_t * const);
  244 
  245  /* -------- interface routines -------- */
  246 int nicstar_output(struct ifnet *, struct mbuf *, struct sockaddr *,
  247                    struct rtentry *);
  248 void nicstar_start(struct ifnet *);
  249 
  250  /* -------- VCC open/close routines -------- */
  251 static void nicstar_itrx(nicstar_reg_t *);
  252 
  253  /* -------- receiving routines -------- */
  254 static void nicstar_rawc(nicstar_reg_t *);
  255 static void nicstar_recv(nicstar_reg_t *);
  256 static void nicstar_phys(nicstar_reg_t *);
  257 
  258 /*******************************************************************************
  259  *
  260  *  New functions
  261  */
  262 
  263 static int idt_buffer_init(IDT *);
  264 static struct mbuf *idt_mbufcl_get(void);
  265 
  266 static int idt_connect_init(IDT *, int);
  267 static void idt_connect_newvbr(IDT *);
  268 
  269 static void idt_intr_tsq(IDT *);
  270 
  271 static vm_offset_t idt_malloc_contig(int);
  272 
  273 static int idt_mbuf_align(struct mbuf *, struct mbuf *);
  274 static int idt_mbuf_append4(struct mbuf *, char *);
  275 static struct mbuf *idt_mbuf_copy(IDT *, struct mbuf *);
  276 static int idt_mbuf_prepend(struct mbuf *, char *, int);
  277 static int idt_mbuf_used(struct mbuf *);
  278 
  279 static int idt_mcheck_add(IDT *, struct mbuf *);
  280 static int idt_mcheck_rem(IDT *, struct mbuf *);
  281 static int idt_mcheck_init(IDT *);
  282 
  283 static int idt_queue_flush(CONNECTION *);
  284 static struct mbuf *idt_queue_get(TX_QUEUE *);
  285 static int idt_queue_init(IDT *);
  286 static int idt_queue_put(CONNECTION *, struct mbuf *);
  287 
  288 static int idt_receive_aal5(IDT *, struct mbuf *, struct mbuf *);
  289 static void idt_transmit_drop(IDT *, struct mbuf *);
  290 static void idt_transmit_top(IDT *, TX_QUEUE *);
  291 
  292 static int idt_slots_add(IDT *, TX_QUEUE *, int);
  293 static int idt_slots_init(IDT *);
  294 static int idt_slots_rem(IDT *, TX_QUEUE *);
  295 
  296 static int idt_phys_detect(IDT *);
  297 static void idt_status_bufs(IDT *);
  298 static int idt_status_wait(IDT *);
  299 
  300 /******************************************************************************
  301  *
  302  *  VBR queue divisor table
  303  */
  304 
  305 static unsigned char vbr_div_m[] = {
  306         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2,
  307         1, 2, 2, 2, 3, 1, 2, 1, 3, 2, 3, 3, 4, 3, 3, 2, 4, 1, 3, 3,
  308         1, 5, 5, 4, 4, 5, 4, 4, 6, 5, 1, 5, 4, 6, 2, 6, 7, 7, 4, 1,
  309         3, 5, 7, 7, 5, 5, 7, 7, 7, 2, 7, 7, 7, 7, 2, 3, 6, 1, 6, 3,
  310         2, 3, 5, 1, 7, 4, 5, 2, 3, 4, 7, 1, 7, 4, 3, 2, 7, 7, 5, 7,
  311         1, 7, 5, 7, 5, 2, 7, 3, 4, 6, 7, 1, 1, 7, 4, 7, 5, 7, 2, 5,
  312         3, 4, 5, 7, 1, 1, 1, 7, 5, 4, 7, 3, 7, 2, 7, 5, 3, 7, 4, 5,
  313         7, 7, 1, 1, 1, 7, 7, 5, 4, 7, 3, 5, 7, 7, 2, 7, 5, 5, 3, 7,
  314         4, 5, 6, 7, 7, 1, 1, 1, 1, 7, 7, 7, 5, 5, 4, 7, 3, 3, 5, 5,
  315         7, 2, 2, 2, 7, 5, 5, 3, 3, 7, 4, 4, 5, 6, 7, 7, 7, 7, 1, 1,
  316         1, 1, 1, 7, 7, 7, 7, 6, 5, 5, 4, 4, 7, 7, 3, 3, 5, 5, 5, 7,
  317         7, 2, 2, 2, 2, 7, 7, 5, 5, 5, 3, 3, 3, 7, 7, 4, 4, 5, 5, 5,
  318         6, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7,
  319         7, 6, 6, 5, 5, 4, 4, 4, 7, 7, 7, 3, 3, 3, 3, 3, 5, 5, 5, 7,
  320         7, 7, 7, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 5, 5, 5, 5, 5, 3, 3,
  321         3, 3, 3, 7, 7, 7, 7, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7,
  322         7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  323         1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5,
  324         5, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
  325         5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2,
  326         2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5,
  327         5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
  328         7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
  329         6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  330         7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  331         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  332         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  333         7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  334         5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7,
  335         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
  336         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5,
  337         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  338         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2,
  339         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  340         2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  341         7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  342         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3,
  343         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  344         3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  345         7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  346         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
  347         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  348         5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  349         6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  350         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  351         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  352         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1,
  353         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  354         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  355         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  356 };
  357 
  358 static unsigned char vbr_div_n[] = {
  359         127, 127, 127, 127, 127, 127, 127, 127, 125, 111, 100, 91, 83, 77, 71,
  360         67, 125, 59, 111, 105, 50, 95, 91, 87, 125, 40, 77, 37, 107, 69,
  361         100, 97, 125, 91, 88, 57, 111, 27, 79, 77, 25, 122, 119, 93, 91,
  362         111, 87, 85, 125, 102, 20, 98, 77, 113, 37, 109, 125, 123, 69, 17,
  363         50, 82, 113, 111, 78, 77, 106, 104, 103, 29, 100, 99, 97, 96, 27,
  364         40, 79, 13, 77, 38, 25, 37, 61, 12, 83, 47, 58, 23, 34, 45,
  365         78, 11, 76, 43, 32, 21, 73, 72, 51, 71, 10, 69, 49, 68, 48,
  366         19, 66, 28, 37, 55, 64, 9, 9, 62, 35, 61, 43, 60, 17, 42,
  367         25, 33, 41, 57, 8, 8, 8, 55, 39, 31, 54, 23, 53, 15, 52,
  368         37, 22, 51, 29, 36, 50, 50, 7, 7, 7, 48, 48, 34, 27, 47,
  369         20, 33, 46, 46, 13, 45, 32, 32, 19, 44, 25, 31, 37, 43, 43,
  370         6, 6, 6, 6, 41, 41, 41, 29, 29, 23, 40, 17, 17, 28, 28,
  371         39, 11, 11, 11, 38, 27, 27, 16, 16, 37, 21, 21, 26, 31, 36,
  372         36, 36, 36, 5, 5, 5, 5, 5, 34, 34, 34, 34, 29, 24, 24,
  373         19, 19, 33, 33, 14, 14, 23, 23, 23, 32, 32, 9, 9, 9, 9,
  374         31, 31, 22, 22, 22, 13, 13, 13, 30, 30, 17, 17, 21, 21, 21,
  375         25, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  376         27, 27, 27, 27, 27, 27, 23, 23, 19, 19, 15, 15, 15, 26, 26,
  377         26, 11, 11, 11, 11, 11, 18, 18, 18, 25, 25, 25, 25, 7, 7,
  378         7, 7, 7, 7, 24, 24, 24, 24, 17, 17, 17, 17, 17, 10, 10,
  379         10, 10, 10, 23, 23, 23, 23, 13, 13, 13, 13, 16, 16, 16, 16,
  380         19, 19, 22, 22, 22, 22, 22, 22, 22, 22, 22, 3, 3, 3, 3,
  381         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 20, 20, 20,
  382         20, 20, 20, 20, 20, 20, 20, 17, 17, 17, 17, 14, 14, 14, 14,
  383         14, 11, 11, 11, 11, 11, 11, 19, 19, 19, 19, 19, 8, 8, 8,
  384         8, 8, 8, 8, 8, 13, 13, 13, 13, 13, 13, 13, 18, 18, 18,
  385         18, 18, 18, 18, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  386         5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 12, 12, 12, 12, 12,
  387         12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 16,
  388         16, 16, 16, 16, 16, 16, 9, 9, 9, 9, 9, 9, 9, 9, 9,
  389         11, 11, 11, 11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13,
  390         15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
  391         15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  392         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  393         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13,
  394         13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
  395         13, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 9, 9, 9,
  396         9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7,
  397         7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12,
  398         12, 12, 12, 12, 12, 12, 12, 5, 5, 5, 5, 5, 5, 5, 5,
  399         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 8,
  400         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  401         8, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
  402         11, 11, 11, 11, 11, 11, 11, 3, 3, 3, 3, 3, 3, 3, 3,
  403         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  404         3, 3, 3, 3, 3, 3, 3, 3, 3, 10, 10, 10, 10, 10, 10,
  405         10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
  406         10, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  407         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4,
  408         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  409         4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9,
  410         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
  411         9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5,
  412         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  413         5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
  414         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  415         6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  416         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8,
  417         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  418         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  419         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  420         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  421         8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  422         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  423         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  424         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  425         1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  426 };
  427 
  428 /******************************************************************************
  429  *
  430  *  Stop the device (shutdown)
  431  *
  432  *  in:  IDT device
  433  *
  434  * Date first: 11/14/2000  last: 11/14/2000
  435  */
  436 
  437 void
  438 idt_device_stop(IDT * idt)
  439 {
  440         u_long val;
  441         int s;
  442 
  443         s = splimp();
  444 
  445         *(idt->reg_cfg) = 0x80000000;   /* put chip into reset */
  446         val = *(idt->reg_gp);   /* wait... */
  447         val |= *(idt->reg_gp);  /* wait... */
  448         val |= *(idt->reg_gp);  /* wait... */
  449         *(idt->reg_cfg) = 0;    /* out of reset */
  450 
  451         splx(s);
  452 
  453         return;
  454 }
  455 
  456 /******************************************************************************
  457  *
  458  *  Initialize the hardware
  459  */
  460 
  461 void
  462 phys_init(nicstar_reg_t * const idt)
  463 {
  464         int i;
  465         u_long t;
  466 
  467 #ifdef NICSTAR_TESTSRAM
  468         u_long z, s2, bad;
  469 #endif
  470         u_long x, s1;
  471         volatile u_long *regCFG = (volatile u_long *)(idt->virt_baseaddr + REGCFG);
  472         volatile u_long *regGP = (volatile u_long *)(idt->virt_baseaddr + REGGP);
  473         volatile u_long stat_val;
  474 
  475         /* clean status bits */
  476         stat_val = *(volatile u_long *)idt->stat_reg;
  477         *(volatile u_long *)idt->stat_reg = stat_val | 0xcc30;  /* clear ints */
  478 
  479         idt->flg_le25 = 0;      /* is this FORE LE25 with 77105 PHY? */
  480         idt->flg_igcrc = 0;     /* ignore receive CRC errors? */
  481         idt->hardware = "?";
  482 
  483         /* start signalling SAR reset */
  484         *regCFG = 0x80000000;
  485 
  486         /* SAR reset--clear occurs at lease 2 PCI cycles after setting */
  487         t = *regGP;             /* wait */
  488         t = *regCFG;
  489         *regCFG = 0;            /* clear reset */
  490 
  491         *regGP = 0x00000000;    /* clear PHYS reset */
  492         *regGP = 0x00000008;    /* start PHYS reset */
  493         t = *regGP;             /* wait */
  494         t = *regCFG;
  495         *regGP = 0x00000001;    /* set while changing SUNI settings */
  496         t = *regGP;             /* wait */
  497         t = *regCFG;
  498 
  499         idt->flg_le25 = idt_phys_detect(idt);
  500 
  501         if (idt->flg_le25) {
  502                 idt->cellrate_rmax = 59259;
  503                 idt->cellrate_tmax = 59259;
  504                 idt->cellrate_rcur = 0;
  505                 idt->cellrate_tcur = 0;
  506                 idt->txslots_max = 348; /* use n*348 for higher resolution */
  507                 idt->txslots_cur = 0;
  508                 nicstar_util_wr(idt, 0, 0x00, 0x00);    /* synch (needed for
  509                                                          * 77105?) */
  510                 nicstar_util_wr(idt, 1, 0x00, 0x09);    /* enable interrupts */
  511                 nicstar_util_wr(idt, 1, 0x02, 0x10);    /* 77105 RFLUSH */
  512                 nicstar_util_rd(idt, 0x01, &t); /* read/clear interrupt flag */
  513         } else {
  514                 idt->cellrate_rmax = 353207;    /* 2075 slots of 1 DS0 each... */
  515                 idt->cellrate_tmax = 353207;
  516                 idt->cellrate_rcur = 0;
  517                 idt->cellrate_tcur = 0;
  518                 idt->txslots_max = 2075;
  519                 idt->txslots_cur = 0;
  520 
  521                 /* initialize the 155Mb SUNI */
  522                 nicstar_util_wr(idt, 0, 0x00, 0x00);    /* sync utopia with SAR */
  523                 nicstar_util_wr(idt, 1, 0x00, 0x00);    /* clear SW reset */
  524                 *regGP = 0x00000000;    /* clear when done with SUNI changes */
  525         }
  526 
  527 #ifdef NICSTAR_TESTSRAM
  528         /*
  529          * this will work with 32K and 128K word RAM  because the pattern
  530          * repeats every 4 words
  531          */
  532         for (i = 0; i < 0x20000; i += 4)
  533                 (void)nicstar_sram_wr(idt, i, 4, 0xa5a5a5a5, 0x5a5a5a5a,
  534                     0xa5a5a5a5, 0x5a5a5a5a);
  535         for (i = 0; i < 0x20000; i += 2) {
  536                 s1 = nicstar_sram_rd(idt, i, &x);
  537                 s2 = nicstar_sram_rd(idt, i + 1, &z);
  538                 if (s1 || s2 || x != 0xa5a5a5a5 || z != 0x5a5a5a5a) {
  539                         printf("sram fail1 %d 0x%08x 0x%08x\n", i, x, z);
  540                         break;
  541                 }
  542         }
  543         for (i = 0; i < 0x20000; i += 4)
  544                 (void)nicstar_sram_wr(idt, i, 4, 0x5a5a5a5a, 0xa5a5a5a5,
  545                     0x5a5a5a5a, 0xa5a5a5a5);
  546         for (i = 0; i < 0x20000; i += 2) {
  547                 s1 = nicstar_sram_rd(idt, i, &z);
  548                 s2 = nicstar_sram_rd(idt, i + 1, &x);
  549                 if (s1 || s2 || x != 0xa5a5a5a5 || z != 0x5a5a5a5a) {
  550                         printf("sram fail2 %d 0x%08x 0x%08x\n", i, x, z);
  551                         break;
  552                 }
  553         }
  554 #endif
  555 
  556         /* flush SRAM */
  557         for (i = 0; i < 0x20000; i += 4)
  558                 (void)nicstar_sram_wr(idt, i, 4, 0, 0, 0, 0);
  559 
  560         /*
  561          * the memory map for the 32K word card has the
  562          * addresses 0x8000, 0x10000, 0x18000 mapped back
  563          * to address 0, and 0x8001, ..., 0x18001 is mapped
  564          * to address 1. address 0x4000 is mapped to 0x1c000
  565          */
  566 
  567         /* write in the 0 word, see if we read it at 0x10000 */
  568         (void)nicstar_sram_wr(idt, 0x0, 1, 0xa5a5a5a5, 0, 0, 0);
  569         s1 = nicstar_sram_rd(idt, 0x10000, &x);
  570         (void)nicstar_sram_wr(idt, 0x0, 1, 0, 0, 0, 0);
  571         if (!s1 && x == 0xa5a5a5a5) {
  572                 device_printf(idt->dev, "32K words of RAM\n");
  573                 idt->sram = 0x4000;
  574         } else {
  575                 device_printf(idt->dev, "128K words of RAM\n");
  576                 idt->sram = 0x10000;
  577         }
  578 #ifdef NICSTAR_FORCE32K
  579         idt->sram = 0x4000;
  580         device_printf(idt->dev, "forced to 32K words of RAM\n");
  581 #endif
  582 
  583         return;
  584 }
  585 
  586 /*  Cellrate notes:
  587  *       The cellrate for OC3 is 353207.55, rounded down above.  This makes
  588  *       2075 slots of one DS0 (64003) each.
  589  *
  590  *       The ATM25 rate is calculated from 25.6mb divided by 424 bits for
  591  *       cell plus 8 bits for "opcode" == 432 bits.  59259 * 432 = 25599888.
  592  *       This provides a 47-byte AAL1 bitrate of 22,281,384 bits/sec, or
  593  *       348 slots of one DS0 (64027) each.  If 8khz synch events are to
  594  *       be sent, then only 347 slots are available.
  595  *
  596  ******************************************************************************
  597  *
  598  *  Physical layer detect
  599  *
  600  *  in:  IDT device
  601  * out:  zero = LE155, NZ = LE25
  602  *
  603  * Date first: 10/30/2000  last: 06/08/2001
  604  */
  605 
  606 int
  607 idt_phys_detect(IDT * idt)
  608 {
  609         u_long t;
  610         int retval;
  611 
  612         retval = 0;
  613 
  614         nicstar_util_wr(idt, 0, 0x00, 0x00);    /* synch (needed for 77105?) */
  615         nicstar_util_rd(idt, 0x00, &t); /* get Master Control Register */
  616 
  617         switch (t) {
  618         /* 25.6 Mbps ATM PHY with TC & PMD */
  619         /* http://www.idt.com/products/pages/ATM_Products-77105.html */
  620         case 0x09:
  621                 device_printf(idt->dev, "ATM card is Fore LE25, PHY=77105\n");
  622                 idt->hardware = "ATM25/77105";
  623                 retval = 1;
  624                 break;
  625 
  626         /* S/UNI-155-LITE */
  627         /* http://www.pmc-sierra.com/products/details/pm5346/index.html */
  628         case 0x30:
  629                 device_printf(idt->dev, "ATM card is Fore LE155 or IDT, PHY=PM5346\n");
  630                 idt->hardware = "ATM155/PM5346";
  631                 break;
  632 
  633         /* S/UNI-155-ULTRA */
  634         /* http://www.pmc-sierra.com/products/details/pm5350/index.html */
  635         case 0x31:
  636         case 0x70:
  637         case 0x78:
  638                 device_printf(idt->dev, "ATM card is Fore LE155, PHY=PM5350\n");
  639                 idt->hardware = "ATM155/PM5350";
  640                 break;
  641 
  642         default:
  643                 device_printf(idt->dev,
  644                         "cannot figure out card type, assuming LE155 (reg=%d).\n",
  645                         (int)t);
  646                 idt->hardware = "unknown (LE155?)";
  647                 break;
  648         }
  649         return (retval);
  650 }
  651 
  652 /*  Register 0 values:
  653  *       77105  = 0x09
  654  *       PM5346 = 0x30
  655  *       PM5250 = 0x31  (actually observed)
  656  *       PM5350 = 0x70 or 0x78 (according to docs)
  657  *
  658  ******************************************************************************
  659  *
  660  *  Initialize the data structures
  661  */
  662 
  663 void
  664 nicstar_init(nicstar_reg_t * const idt)
  665 {
  666         int i;
  667         vm_offset_t buf;
  668         u_long *p;
  669 
  670         idt_connect_init(idt, 0);       /* initialize for 0 VPI bits (12 VCI
  671                                          * bits) */
  672 
  673         /* allocate space for TSQ, RSQ, SCD for VBR,ABR, UBR */
  674         idt->fixbuf = (vm_offset_t)contigmalloc(NICSTAR_FIXPAGES * PAGE_SIZE,
  675             M_DEVBUF, M_NOWAIT | M_ZERO, 0x100000, 0xffffffff, 0x2000, 0);
  676         if (idt->fixbuf == 0)
  677                 return;         /* no space card disabled */
  678 
  679         if (idt_buffer_init(idt))       /* allocate large buffers */
  680                 goto freemem;   /* free memory and return */
  681 
  682         if (idt_mcheck_init(idt))
  683                 goto freemem;
  684 
  685         idt_found++;            /* number of cards found on machine */
  686 
  687         if (bootverbose) {
  688                 printf("nicstar: buffer size %d\n", 0);
  689         }
  690         idt_queue_init(idt);    /* initialize all TX_QUEUE structures */
  691         idt_slots_init(idt);    /* initialize CBR table slots */
  692 
  693         /* initialize variable rate mbuf queues */
  694 
  695         /* TSQ initialization */
  696         for (p = (u_long *)idt->fixbuf; p < (u_long *)(idt->fixbuf + 0x2000);) {
  697                 *p++ = 0x00000000;
  698                 *p++ = 0x80000000;      /* set empty bit */
  699         }
  700 
  701         buf = vtophys(idt->fixbuf);
  702         /* Transmit Status Queue Base */
  703         *(volatile u_long *)(idt->virt_baseaddr + REGTSQB) = buf;
  704         /* Transmit Status Queue Head */
  705         *(volatile u_long *)(idt->virt_baseaddr + REGTSQH) = 0; /* 8k aligned */
  706         idt->tsq_base = (u_long *)idt->fixbuf;
  707         idt->tsq_head = (u_long *)idt->fixbuf;
  708         idt->tsq_size = 1024;
  709 
  710         /* Recieve Status Queue Base */
  711         *(volatile u_long *)(idt->virt_baseaddr + REGRSQB) = buf + 0x2000;
  712         /* Transmit Status Queue Head */
  713         *(volatile u_long *)(idt->virt_baseaddr + REGRSQH) = 0; /* 8k aligned */
  714         idt->rsqh = 0;
  715 
  716 
  717         /* Now load receive buffers into SRAM */
  718         nicstar_ld_rcv_buf(idt);
  719 
  720         /* load variable SCQ */
  721         (void)nicstar_sram_wr(idt, 0x1e7dc, 4, (u_long)(buf + 0x8000), 0,
  722             0xffffffff, 0);     /* SD2 */
  723         (void)nicstar_sram_wr(idt, 0x1e7e0, 4, 0, 0, 0, 0);
  724         (void)nicstar_sram_wr(idt, 0x1e7e4, 4, 0, 0, 0, 0);
  725 
  726         (void)nicstar_sram_wr(idt, 0x1e7e8, 4, (u_long)(buf + 0x6000), 0,
  727             0xffffffff, 0);     /* SD1 */
  728         (void)nicstar_sram_wr(idt, 0x1e7ec, 4, 0, 0, 0, 0);
  729         (void)nicstar_sram_wr(idt, 0x1e7f0, 4, 0, 0, 0, 0);
  730 
  731         (void)nicstar_sram_wr(idt, 0x1e7f4, 4, (u_long)(buf + 0x4000), 0,
  732             0xffffffff, 0);     /* SD0 */
  733         (void)nicstar_sram_wr(idt, 0x1e7f8, 4, 0, 0, 0, 0);
  734         (void)nicstar_sram_wr(idt, 0x1e7fc, 4, 0, 0, 0, 0);
  735 
  736         /* initialize RCT */
  737         for (i = 0; i < idt->sram; i += 4) {    /* XXX ifdef table size */
  738                 nicstar_sram_wr(idt, i, 4, 0x0, 0x0, 0x0, 0xffffffff);
  739         }
  740 
  741         /* VPI/VCI mask is 0 */
  742         *(volatile u_long *)(idt->virt_baseaddr + REGVMSK) = 0;
  743 
  744         /* Set the Transmit Schedule Table base address */
  745         *(volatile u_long *)(idt->virt_baseaddr + REGTSTB) = IDT_TST_START;
  746 
  747 
  748 /* Configuration Register settings:
  749  * Bit(s)       Meaning                                 value
  750  * 31           Software reset                          0
  751  * 30           RESERVED                                0
  752  * 29           Recieve Enabled                         1
  753  * 28-27        Small Buffer Size (host memory)         01 (96 bytes)
  754  * 26-25        Large Buffer Size (host memory)         00 (2048 bytes)
  755  * 24           Interrupt on empty free buffer queue    1
  756  *
  757  * 23-22        Recieve Status Queue Size (host memory) 10 (8192 bytes)
  758  * 21           Accpect Invalid cells into Raw Queue    1
  759  * 20           Ignore General Flow control             1
  760  *
  761  * 19-18        VPI/VCI Select                          00
  762  * 17-16        Recieve Connect Table Size              00 (32K SRAM)
  763  *                                                      10 (128K SRAM)
  764  *
  765  * 15           Accpect non-open VPI/VCI to Raw Queue   1
  766  * 14-12        time to delay after Rx and interrupt    001 (0us)
  767  *
  768  * 11           Interrupt when a Raw Cell is added      1
  769  * 10           Interrupt when Recieve Queue near full  1
  770  *  9           Recieve RM (PTI = 110 or 111)           1
  771  *  8           RESERVED                                0
  772  *
  773  *  7           Interrupt on Timer rollover             1
  774  *  6           RESERVED                                0
  775  *  5           Transmit Enabled                        1
  776  *  4           Interrupt on Transmit Status Indicator  1
  777  *
  778  *  3           Interrupt on transmit underruns         1
  779  *  2           UTOPIA cell/byte mode                   0 (cell)
  780  *  1           Interrupt on nearly full TSQ            1
  781  *  0           Enable Physical Interrupt               1
  782  */
  783 
  784         /* original values:  0x31b09ebb and 0x31b29eb  */
  785         /*
  786          * 11/01/2000: changed from 0x31b09eb to 0x29b09eb for 96-byte
  787          * sm-buf
  788          */
  789 
  790         if (idt->sram == 0x4000)/* 32K */
  791                 *(volatile u_long *)(idt->virt_baseaddr + REGCFG) = 0x29b09ebb;
  792         else                    /* 128K */
  793                 *(volatile u_long *)(idt->virt_baseaddr + REGCFG) = 0x29b29ebb;
  794 
  795         return;
  796 
  797 freemem:
  798         /* free memory and return */
  799         idt_release_mem(idt);
  800         device_printf(idt->dev, "cannot allocate memory\n");
  801         return;                 /* no space card disabled */
  802 }
  803 
  804 /******************************************************************************
  805  *
  806  *  Release all allocated memory
  807  *
  808  *  in:  IDT device
  809  *
  810  * Date first: 11/14/2000  last: 11/14/2000
  811  */
  812 
  813 void
  814 idt_release_mem(IDT * idt)
  815 {
  816         if (idt->fixbuf != 0)
  817                 kmem_free(kernel_map, idt->fixbuf,
  818                           (NICSTAR_FIXPAGES * PAGE_SIZE));
  819 
  820         if (idt->cbr_base != 0)
  821                 kmem_free(kernel_map, (vm_offset_t)idt->cbr_base, idt->cbr_size);
  822 
  823         printf("%s() is NOT SAFE!\n", __func__);
  824 
  825         /* we also have idt->connection and idt->mcheck to do as well... */
  826 }
  827 
  828 /******************************************************************************
  829  *
  830  *  Write one to four words to SRAM
  831  *
  832  *    writes one to four words into sram starting at "sram_location"
  833  *
  834  *    returns -1 if sram location is out of range.
  835  *    returns count, if count is not in the range from 1-4.
  836  *    returns 0 if parameters were acceptable
  837  */
  838 
  839 static int
  840 nicstar_sram_wr(nicstar_reg_t * const idt, u_long address, int count,
  841     u_long data0, u_long data1, u_long data2, u_long data3)
  842 {
  843         if (address >= 0x20000) /* bad address */
  844                 return (-1);
  845 
  846         if (idt_status_wait(idt))       /* 12/06/2000 */
  847                 return (-1);
  848 
  849         switch (--count) {
  850         case 3:
  851                 *(idt->reg_data + 3) = data3;   /* drop down to do others */
  852         case 2:
  853                 *(idt->reg_data + 2) = data2;   /* drop down to do others */
  854         case 1:
  855                 *(idt->reg_data + 1) = data1;   /* drop down to do others */
  856         case 0:
  857                 *idt->reg_data = data0; /* load last data item */
  858                 break;          /* done loading values */
  859         default:
  860                 return (count); /* nothing to do */
  861         }
  862                                                 /* write the word(s) */
  863         *idt->reg_cmd = 0x40000000 | (address << 2) | count;
  864 
  865         return (0);
  866 }
  867 
  868 /*  05/31/2001:  Removed wait between data register(s) and write command.
  869  *       The docs do not state it is helpful, and the example only has one
  870  *       wait, before the data register load.  The wait time is very high -
  871  *       aproximately 6 microseconds per wait.
  872  *
  873  ******************************************************************************
  874  *
  875  *  Read one word from SRAM
  876  *
  877  *    reads one word of sram at "sram_location" and places the value
  878  *    in "answer_pointer"
  879  *
  880  *    returns -1 if sram location is out of range.
  881  *    returns 0 if parameters were acceptable
  882  */
  883 static int
  884 nicstar_sram_rd(nicstar_reg_t * const idt, u_long address, u_long *data0)
  885 {
  886         if (address >= 0x20000) /* bad address */
  887                 return (-1);
  888 
  889         if (idt_status_wait(idt))
  890                 return (-1);
  891 
  892         *idt->reg_cmd = 0x50000000 | (address << 2);    /* read a word */
  893 
  894         if (idt_status_wait(idt))
  895                 return (-1);
  896 
  897         *data0 = *idt->reg_data;/* save word */
  898 
  899         return (0);
  900 }
  901 
  902 /*******************************************************************************
  903  *
  904  *  Open or Close connection in IDT Receive Connection Table
  905  *
  906  *  in:  IDT device, VPI, VCI, opflag (0 = close, 1 = open)
  907  * out:  zero = success
  908  *
  909  *  Date first: 12/14/2000  last: 12/14/2000
  910  */
  911 
  912 int
  913 idt_connect_opencls(IDT * idt, CONNECTION * connection, int opflag)
  914 {
  915         int address;
  916         int word1;
  917 
  918         if (connection->vpi >= idt->conn_maxvpi ||
  919             connection->vci >= idt->conn_maxvci)
  920                 return (1);
  921 
  922         address = connection->vpi * idt->conn_maxvci + connection->vci;
  923         address <<= 2;          /* each entry is 4 words */
  924 
  925         if (opflag) {
  926                 switch (connection->aal) {
  927                 case ATM_AAL0:
  928                         word1 = 0x00038000;
  929                         break;  /* raw cell queue */
  930                 case ATM_AAL1:
  931                         word1 = 0x00008000;
  932                         break;  /* Nicstar "AAL0" */
  933                 case ATM_AAL3_4:
  934                         word1 = 0x00018000;
  935                         break;
  936                 case ATM_AAL5:
  937                         word1 = 0x00028000;
  938                         break;
  939                 default:
  940                         return (1);
  941                 }
  942                 nicstar_sram_wr(idt, address, 4, word1, 0, 0, 0xffffffff);
  943                 opflag = 0x00080000;    /* bit-19 set or clear */
  944         }
  945         if (idt_status_wait(idt))
  946                 return (1);
  947 
  948         *idt->reg_cmd = 0x20000000 | opflag | address << 2;
  949         return (0);
  950 }
  951 
  952 /*******************************************************************************
  953  *
  954  *    nicstar_add_buf    ( card, mbuf1, mbuf2, which_queue)
  955  *
  956  *    This adds two buffers to the specified queue. This uses the
  957  *    mbuf address as handle and the buffer physical address must be
  958  *    the DMA address.
  959  *
  960  *    returns -1 if queue is full, the address is not word aligned, or
  961  *    an invalid queue is specified.
  962  *    returns 0 if parameters were acceptable.
  963  */
  964 
  965 int
  966 nicstar_add_buf(nicstar_reg_t * const idt, struct mbuf * buf0,
  967     struct mbuf * buf1, u_long islrg)
  968 {
  969         u_long stat_val;
  970         u_long val0, val1, val2, val3;
  971 
  972         if (islrg > 1)                  /* bad buffer size */
  973                 return (-1);
  974 
  975         stat_val = *idt->reg_stat;
  976 
  977         if (islrg) {
  978                 if (stat_val & 0x80)    /* large queue is full */
  979                         return (-1);
  980         } else if (stat_val & 0x100)    /* small queue is full */
  981                 return (-1);
  982 
  983         if (!buf0 || !buf1 || ((u_long)(buf0->m_data) & 0x7)
  984             || ((u_long)(buf1->m_data) & 0x7)) {
  985                 return (-1);            /* buffers must word aligned */
  986         }
  987         if (idt->raw_headm == NULL)     /* raw cell buffer pointer not
  988                                          * initialized */
  989                 if (islrg) {
  990                         idt->raw_headm = buf0;
  991                         idt->raw_headp = vtophys(buf0->m_data);
  992                 }
  993         if (idt_status_wait(idt))       /* 12/06/2000 */
  994                 return (-1);
  995 
  996         val0 = (u_long)buf0;            /* mbuf address is handle */
  997         val1 = vtophys(buf0->m_data);   /* DMA addr of buff1 */
  998         val2 = (u_long)buf1;            /* mbuf address is handle */
  999         val3 = vtophys(buf1->m_data);   /* DMA addr of buff2 */
 1000 
 1001         *(idt->reg_data + 0) = val0;
 1002         *(idt->reg_data + 1) = val1;
 1003         *(idt->reg_data + 2) = val2;
 1004         *(idt->reg_data + 3) = val3;
 1005 
 1006         *idt->reg_cmd = 0x60000000 | islrg;
 1007 
 1008         idt_mcheck_add(idt, buf0);
 1009         idt_mcheck_add(idt, buf1);
 1010 
 1011         return (0);
 1012 }
 1013 
 1014 /******************************************************************************
 1015  *
 1016  *    nicstar_util_rd    ( card, util_location, answer_pointer )
 1017  *
 1018  *    reads one byte from the utility bus at "util_location" and places the
 1019  *    value in "answer_pointer"
 1020  *
 1021  *    returns -1 if util location is out of range.
 1022  *    returns 0 if parameters were acceptable
 1023  */
 1024 static int
 1025 nicstar_util_rd(nicstar_reg_t * const idt, u_long address, u_long *data)
 1026 {
 1027 
 1028         if (address >= 0x81)                    /* bad address */
 1029                 return (-1);
 1030 
 1031         if (idt_status_wait(idt))
 1032                 return (-1);
 1033 
 1034         *idt->reg_cmd = 0x80000200 | address;   /* read a word */
 1035 
 1036         if (idt_status_wait(idt))
 1037                 return (-1);
 1038 
 1039         *data = *idt->reg_data & 0xff;          /* save word */
 1040 
 1041         return (0);
 1042 }
 1043 
 1044 /******************************************************************************
 1045  *
 1046  *    nicstar_util_wr    ( card, util location, data )
 1047  *
 1048  *    writes one byte to the utility bus at "util_location"
 1049  *
 1050  *    returns -1 if util location is out of range.
 1051  *    returns 0 if parameters were acceptable
 1052  */
 1053 static int
 1054 nicstar_util_wr(nicstar_reg_t * const idt, int cs, u_long address, u_long data)
 1055 {
 1056 
 1057         if (address >= 0x81)    /* bad address */
 1058                 return (-1);
 1059         if (cs > 1)
 1060                 return (-1);
 1061 
 1062         if (idt_status_wait(idt))
 1063                 return (-1);
 1064 
 1065         *idt->reg_data = data & 0xff;   /* load last data item */
 1066 
 1067         if (cs == 0)
 1068                 *idt->reg_cmd = 0x90000100 | address;   /* write the byte, CS1 */
 1069         else
 1070                 *idt->reg_cmd = 0x90000200 | address;   /* write the byte, CS2 */
 1071 
 1072         return (0);
 1073 }
 1074 
 1075 /******************************************************************************
 1076  *
 1077  *    nicstar_eeprom_rd    ( card , byte_location )
 1078  *
 1079  *    reads one byte from the utility bus at "byte_location" and return the
 1080  *    value as an integer. this routint is only used to read the MAC address
 1081  *    from the EEPROM at boot time.
 1082  */
 1083 int
 1084 nicstar_eeprom_rd(nicstar_reg_t * const idt, u_long address)
 1085 {
 1086         volatile u_long *regGP = (volatile u_long *)(idt->virt_baseaddr + REGGP);
 1087         volatile u_long gp = *regGP & 0xfffffff0;
 1088         int i, value = 0;
 1089 
 1090         DELAY(5);               /* make sure idle */
 1091         *regGP = gp | 0x06;     /* CS and Clock high */
 1092         DELAY(5);
 1093         *regGP = gp;            /* CS and Clock low */
 1094         DELAY(5);
 1095         /* toggle in  READ CMD (00000011) */
 1096         *regGP = gp | 0x04;     /* Clock high (data 0) */
 1097         DELAY(5);
 1098         *regGP = gp;            /* CS and Clock low */
 1099         DELAY(5);
 1100         *regGP = gp | 0x04;     /* Clock high (data 0) */
 1101         DELAY(5);
 1102         *regGP = gp;            /* CS and Clock low */
 1103         DELAY(5);
 1104         *regGP = gp | 0x04;     /* Clock high (data 0) */
 1105         DELAY(5);
 1106         *regGP = gp;            /* CS and Clock low */
 1107         DELAY(5);
 1108         *regGP = gp | 0x04;     /* Clock high (data 0) */
 1109         DELAY(5);
 1110         *regGP = gp;            /* CS and Clock low */
 1111         DELAY(5);
 1112         *regGP = gp | 0x04;     /* Clock high (data 0) */
 1113         DELAY(5);
 1114         *regGP = gp;            /* CS and Clock low */
 1115         DELAY(5);
 1116         *regGP = gp | 0x04;     /* Clock high (data 0) */
 1117         DELAY(5);
 1118         *regGP = gp | 0x01;     /* CS and Clock low data 1 */
 1119         DELAY(5);
 1120         *regGP = gp | 0x05;     /* Clock high (data 1) */
 1121         DELAY(5);
 1122         *regGP = gp | 0x01;     /* CS and Clock low data 1 */
 1123         DELAY(5);
 1124         *regGP = gp | 0x05;     /* Clock high (data 1) */
 1125         DELAY(5);
 1126         /* toggle in the address */
 1127         for (i = 7; i >= 0; i--) {
 1128                 *regGP = (gp | ((address >> i) & 1));   /* Clock low */
 1129                 DELAY(5);
 1130                 *regGP = (gp | 0x04 | ((address >> i) & 1));    /* Clock high */
 1131                 DELAY(5);
 1132         }
 1133         /* read EEPROM data */
 1134         for (i = 7; i >= 0; i--) {
 1135                 *regGP = gp;    /* Clock low */
 1136                 DELAY(5);
 1137                 value |= ((*regGP & 0x10000) >> (16 - i));
 1138                 *regGP = gp | 0x04;     /* Clock high */
 1139                 DELAY(5);
 1140         }
 1141         *regGP = gp;            /* CS and Clock low */
 1142         return (value);
 1143 }
 1144 
 1145 /*******************************************************************************
 1146  *
 1147  *  Load the card receive buffers
 1148  *
 1149  *  in:  IDT device
 1150  *
 1151  *  Date first: 11/01/2000  last: 05/25/2000
 1152  */
 1153 
 1154 void
 1155 nicstar_ld_rcv_buf(IDT * idt)
 1156 {
 1157         struct mbuf *m1, *m2;
 1158         u_long stat_reg;
 1159         int card_small;
 1160         int card_large;
 1161         int s;
 1162 
 1163         s = splimp();
 1164 
 1165         stat_reg = *(volatile u_long *)idt->stat_reg;
 1166 
 1167         card_small = (stat_reg & 0xff000000) >> 23;     /* reg is number of
 1168                                                          * pairs */
 1169         card_large = (stat_reg & 0x00ff0000) >> 15;
 1170 
 1171         if (idt_sysctl_bufsmall > 510)
 1172                 idt_sysctl_bufsmall = 510;
 1173         if (idt_sysctl_buflarge > 510)
 1174                 idt_sysctl_buflarge = 510;
 1175         if (idt_sysctl_bufsmall < 10)
 1176                 idt_sysctl_bufsmall = 10;
 1177         if (idt_sysctl_buflarge < 10)
 1178                 idt_sysctl_buflarge = 10;
 1179 
 1180         while (card_small < idt_sysctl_bufsmall) {      /* 05/25/2001 from fixed */
 1181                 MGETHDR(m1, M_DONTWAIT, MT_DATA);
 1182                 if (m1 == NULL)
 1183                         break;
 1184                 MGETHDR(m2, M_DONTWAIT, MT_DATA);
 1185                 if (m2 == NULL) {
 1186                         m_free(m1);
 1187                         break;
 1188                 }
 1189                 MH_ALIGN(m1, 96);       /* word align & allow lots of
 1190                                          * prepending */
 1191                 MH_ALIGN(m2, 96);
 1192                 if (nicstar_add_buf(idt, m1, m2, 0)) {
 1193                         device_printf(idt->dev,
 1194                                 "Cannot add small buffers, size=%d.\n",
 1195                                 card_small);
 1196                         m_free(m1);
 1197                         m_free(m2);
 1198                         break;
 1199                 }
 1200                 card_small += 2;
 1201         }
 1202 
 1203         while (card_large < idt_sysctl_buflarge) {      /* 05/25/2001 from fixed */
 1204                 m1 = idt_mbufcl_get();
 1205                 if (m1 == NULL)
 1206                         break;
 1207                 m2 = idt_mbufcl_get();
 1208                 if (m2 == NULL) {
 1209                         m_free(m1);
 1210                         break;
 1211                 }
 1212                 if (nicstar_add_buf(idt, m1, m2, 1)) {
 1213                         device_printf(idt->dev,
 1214                                 "Cannot add large buffers, size=%d.\n",
 1215                                 card_large);
 1216                         m_free(m1);
 1217                         m_free(m2);
 1218                         break;
 1219                 }
 1220                 card_large += 2;
 1221         }
 1222         idt_sysctl_curlarge = card_large;
 1223         idt_sysctl_cursmall = card_small;
 1224 
 1225         splx(s);
 1226 }
 1227 
 1228 /*******************************************************************************
 1229  *
 1230  *  Wait for command to finish
 1231  *
 1232  *  in:  IDT device
 1233  * out:  zero = success
 1234  *
 1235  *  Date first: 12/06/2000  last: 12/16/2000
 1236  */
 1237 
 1238 int
 1239 idt_status_wait(IDT * idt)
 1240 {
 1241         int timeout;
 1242 
 1243         timeout = 33 * 100;     /* allow 100 microseconds timeout */
 1244 
 1245         while (*idt->reg_stat & 0x200)
 1246                 if (--timeout == 0) {
 1247                         device_printf(idt->dev,
 1248                                       "timeout waiting for device status.\n");
 1249                         idt->stats_cmderrors++;
 1250                         return (1);
 1251                 }
 1252         return (0);
 1253 }
 1254 
 1255 /*******************************************************************************
 1256  *
 1257  *  Log status of system buffers
 1258  *
 1259  *  in:  IDT device
 1260  *
 1261  *  Date first: 10/31/2000  last: 05/25/2001
 1262  */
 1263 
 1264 void
 1265 idt_status_bufs(IDT * idt)
 1266 {
 1267         u_long stat_reg;
 1268         int card_small;
 1269         int card_large;
 1270         int s;
 1271 
 1272         s = splimp();
 1273 
 1274         stat_reg = *(volatile u_long *)idt->stat_reg;
 1275 
 1276         card_small = (stat_reg & 0xff000000) >> 23;     /* reg is number of
 1277                                                          * pairs */
 1278         card_large = (stat_reg & 0x00ff0000) >> 15;
 1279 
 1280         splx(s);
 1281 
 1282         device_printf(idt->dev, "BUFFER STATUS: small=%d/%d, large=%d/%d.\n",
 1283             card_small, idt_sysctl_bufsmall,
 1284             card_large, idt_sysctl_buflarge);
 1285 }
 1286 
 1287 /*  Since this is called when the card timer wraps, we should only see
 1288  *  this 16 times (LE155) or 10 (LE25) per hour.
 1289  *
 1290  *******************************************************************************
 1291  *
 1292  *  Add mbuf into "owned" list
 1293  *
 1294  *  in:  IDT device, mbuf
 1295  * out:  zero = success
 1296  *
 1297  * Date first: 11/13/2000  last: 11/13/2000
 1298  */
 1299 
 1300 int
 1301 idt_mcheck_add(IDT * idt, struct mbuf * m)
 1302 {
 1303         int hpos;
 1304         int s;
 1305 
 1306         hpos = (((int)m) >> 8) & 1023;
 1307         s = splimp();
 1308 
 1309         m->m_next = idt->mcheck[hpos];
 1310         idt->mcheck[hpos] = m;
 1311 
 1312         splx(s);
 1313         return (0);
 1314 }
 1315 
 1316 /******************************************************************************
 1317  *
 1318  *  Remove mbuf from "owned" list
 1319  *
 1320  *  in:  IDT device, mbuf
 1321  * out:  zero = success
 1322  *
 1323  * Date first: 11/13/2000  last: 11/13/2000
 1324  */
 1325 
 1326 int
 1327 idt_mcheck_rem(IDT * idt, struct mbuf * m)
 1328 {
 1329         struct mbuf *nbuf;
 1330         int hpos;
 1331         int s;
 1332 
 1333         hpos = (((int)m) >> 8) & 1023;
 1334         s = splimp();
 1335 
 1336         nbuf = idt->mcheck[hpos];
 1337 
 1338         if (nbuf == m) {
 1339                 idt->mcheck[hpos] = m->m_next;
 1340                 splx(s);
 1341                 m->m_next = NULL;
 1342                 return (0);
 1343         }
 1344         while (nbuf != NULL) {
 1345                 if (nbuf->m_next != m) {
 1346                         nbuf = nbuf->m_next;
 1347                         continue;
 1348                 }
 1349                 nbuf->m_next = m->m_next;
 1350                 splx(s);
 1351                 m->m_next = NULL;
 1352                 return (0);
 1353         }
 1354 
 1355         splx(s);
 1356         device_printf(idt->dev, "Card should not have this mbuf! %x\n", (int)m);
 1357         return (1);
 1358 }
 1359 
 1360 /******************************************************************************
 1361  *
 1362  *  Initialize mbuf "owned" list
 1363  *
 1364  *  in:  IDT device
 1365  * out:  zero = success
 1366  *
 1367  * Date first: 11/13/2000  last: 05/26/2001
 1368  */
 1369 
 1370 int
 1371 idt_mcheck_init(IDT * idt)
 1372 {
 1373         int size;
 1374         int x;
 1375 
 1376         size = round_page(sizeof(struct mbuf *) * 1024);
 1377         idt->mcheck = contigmalloc(size, M_DEVBUF, M_NOWAIT,
 1378             0x100000, 0xffffffff, 0x2000, 0);
 1379         if (idt->mcheck == NULL)
 1380                 return (1);
 1381 
 1382         for (x = 0; x < 1024; x++)
 1383                 idt->mcheck[x] = NULL;
 1384 
 1385         return (0);
 1386 }
 1387 
 1388 /******************************************************************************
 1389  *
 1390  *  Allocate contiguous, fixed memory
 1391  *
 1392  *  in:  number of pages
 1393  * out:  pointer, NULL = failure
 1394  *
 1395  * Date first: 11/29/2000  last: 11/29/2000
 1396  */
 1397 
 1398 vm_offset_t
 1399 idt_malloc_contig(int pages)
 1400 {
 1401         vm_offset_t retval;
 1402 
 1403         retval = (vm_offset_t)contigmalloc(pages * PAGE_SIZE,
 1404             M_DEVBUF, M_NOWAIT, 0x100000, 0xffffffff, 0x2000, 0);
 1405 #ifdef UNDEF
 1406         printf("idt: vm_offset_t allocated %d pages at %x\n", pages, retval);
 1407 #endif
 1408 
 1409         return (retval);
 1410 }
 1411 
 1412 /*******************************************************************************
 1413  *
 1414  *  Initialize all TX_QUEUE structures
 1415  *
 1416  *  in:  IDT device
 1417  * out:  zero = succes
 1418  *
 1419  *  Date first: 11/29/2000  last: 11/29/2000
 1420  */
 1421 static int
 1422 idt_queue_init(IDT * idt)
 1423 {
 1424         TX_QUEUE *txqueue;
 1425         vm_offset_t scqbase;
 1426         int x;
 1427 
 1428         idt->cbr_size = IDT_MAX_CBRQUEUE * 16 * 64;
 1429         idt->cbr_base = idt_malloc_contig(idt->cbr_size / PAGE_SIZE);
 1430         scqbase = idt->cbr_base;
 1431         if (scqbase == 0)
 1432                 return (1);
 1433         idt->cbr_freect = idt->cbr_size / (16 * 64);
 1434 
 1435         for (x = 0; x < idt->cbr_freect; x++) {
 1436                 txqueue = &idt->cbr_txqb[x];
 1437                 txqueue->mget = NULL;
 1438                 txqueue->mput = NULL;
 1439                 txqueue->scd = IDT_SCD_START + x * 12;
 1440                 txqueue->scq_base = (u_long *)scqbase;
 1441                 txqueue->scq_next = txqueue->scq_base;
 1442                 txqueue->scq_last = txqueue->scq_next;
 1443                 txqueue->scq_len = 64;  /* all CBR queues use 64 entries */
 1444                 txqueue->scq_cur = 0;
 1445                 txqueue->rate = 0;
 1446                 txqueue->vbr_m = 0;     /* m & n set to zero for CBR */
 1447                 txqueue->vbr_n = 0;
 1448                 idt->cbr_free[x] = txqueue;
 1449                 scqbase += 64 * 16;
 1450                 nicstar_sram_wr(idt, txqueue->scd, 4,
 1451                     vtophys(txqueue->scq_base), 0, 0xffffffff, 0);
 1452         }
 1453 
 1454         txqueue = &idt->queue_vbr;      /* VBR queue */
 1455         txqueue->mget = NULL;
 1456         txqueue->mput = NULL;
 1457         txqueue->scd = 0x1e7f4;
 1458         txqueue->scq_base = (u_long *)(idt->fixbuf + 0x4000);
 1459         txqueue->scq_next = txqueue->scq_base;
 1460         txqueue->scq_last = txqueue->scq_next;
 1461         txqueue->scq_len = 512; /* all VBR queues use 512 entries */
 1462         txqueue->scq_cur = 0;
 1463         txqueue->rate = 0;
 1464         txqueue->vbr_m = 1;
 1465         txqueue->vbr_n = 1;
 1466         nicstar_sram_wr(idt, txqueue->scd, 4,
 1467             vtophys(txqueue->scq_base), 0, 0xffffffff, 0);
 1468 
 1469         txqueue = &idt->queue_abr;      /* ABR queue (not currently used) */
 1470         txqueue->mget = NULL;
 1471         txqueue->mput = NULL;
 1472         txqueue->scd = 0x1e7e8;
 1473         txqueue->scq_base = (u_long *)(idt->fixbuf + 0x6000);
 1474         txqueue->scq_next = txqueue->scq_base;
 1475         txqueue->scq_last = txqueue->scq_next;
 1476         txqueue->scq_len = 512;
 1477         txqueue->scq_cur = 0;
 1478         txqueue->rate = 0;
 1479         txqueue->vbr_m = 1;
 1480         txqueue->vbr_n = 1;
 1481         nicstar_sram_wr(idt, txqueue->scd, 4,
 1482             vtophys(txqueue->scq_base), 0, 0xffffffff, 0);
 1483 
 1484         txqueue = &idt->queue_ubr;      /* UBR queue */
 1485         txqueue->mget = NULL;
 1486         txqueue->mput = NULL;
 1487         txqueue->scd = 0x1e7dc;
 1488         txqueue->scq_base = (u_long *)(idt->fixbuf + 0x8000);
 1489         txqueue->scq_next = txqueue->scq_base;
 1490         txqueue->scq_last = txqueue->scq_next;
 1491         txqueue->scq_len = 512;
 1492         txqueue->scq_cur = 0;
 1493         txqueue->rate = 0;
 1494         txqueue->vbr_m = 1;     /* since the ABR queue is lowest priority, */
 1495         txqueue->vbr_n = 1;     /* these factors should never change */
 1496         nicstar_sram_wr(idt, txqueue->scd, 4,
 1497             vtophys(txqueue->scq_base), 0, 0xffffffff, 0);
 1498 
 1499         return (0);
 1500 }
 1501 
 1502 /*******************************************************************************
 1503  *
 1504  *  Get mbuf chain from TX_QUEUE
 1505  *
 1506  *  in:  CONNECTION
 1507  * out:  mbuf, NULL = empty
 1508  *
 1509  *  Date first: 12/03/2000  last: 12/03/2000
 1510  */
 1511 static struct mbuf *
 1512 idt_queue_get(TX_QUEUE * txqueue)
 1513 {
 1514         struct mbuf *m1, *m2;
 1515         int s;
 1516 
 1517         if (txqueue == NULL)
 1518                 return (NULL);
 1519 
 1520         s = splimp();
 1521 
 1522         m1 = txqueue->mget;
 1523         if (m1 != NULL) {
 1524                 m2 = m1->m_nextpkt;
 1525                 txqueue->mget = m2;
 1526                 if (m2 == NULL) /* is queue empty now? */
 1527                         txqueue->mput = NULL;
 1528         }
 1529         splx(s);
 1530 
 1531         return (m1);
 1532 }
 1533 
 1534 /*******************************************************************************
 1535  *
 1536  *  Add mbuf chain to connection TX_QUEUE
 1537  *
 1538  *  in:  CONNECTION, mbuf chain
 1539  * out:  zero = succes
 1540  *
 1541  *  Date first: 12/03/2000  last: 06/01/2001
 1542  */
 1543 static int
 1544 idt_queue_put(CONNECTION * connection, struct mbuf * m)
 1545 {
 1546         TX_QUEUE *txqueue;
 1547         int s;
 1548 
 1549         if (connection == NULL) {
 1550                 m_freem(m);
 1551                 return (1);
 1552         }
 1553         txqueue = connection->queue;
 1554         if (txqueue == NULL) {
 1555                 m_freem(m);
 1556                 return (1);
 1557         }
 1558         m->m_nextpkt = NULL;
 1559         m->m_pkthdr.rcvif = (struct ifnet *) connection;
 1560 
 1561         s = splimp();
 1562 
 1563         if (txqueue->mput != NULL) {
 1564                 *txqueue->mput = m;
 1565                 txqueue->mput = &m->m_nextpkt;
 1566         } else {                /* queue is empty */
 1567                 txqueue->mget = m;
 1568                 txqueue->mput = &m->m_nextpkt;
 1569         }
 1570         splx(s);
 1571 
 1572         return (0);
 1573 }
 1574 
 1575 /*******************************************************************************
 1576  *
 1577  *  Flush all connection mbufs from TX_QUEUE
 1578  *
 1579  *  in:  CONNECTION
 1580  * out:  zero = succes
 1581  *
 1582  *  Date first: 12/03/2000  last: 12/03/2000
 1583  */
 1584 static int
 1585 idt_queue_flush(CONNECTION * connection)
 1586 {
 1587         TX_QUEUE *txqueue;
 1588         struct mbuf **m0, *m1;
 1589         int s;
 1590 
 1591         if (connection == NULL)
 1592                 return (1);
 1593         txqueue = connection->queue;
 1594         if (txqueue == NULL)
 1595                 return (1);
 1596 
 1597         s = splimp();
 1598 
 1599         m0 = &txqueue->mget;
 1600         m1 = *m0;
 1601         while (m1 != NULL) {
 1602                 if (m1->m_pkthdr.rcvif == (struct ifnet *) connection) {
 1603                         *m0 = m1->m_nextpkt;
 1604                         m_freem(m1);
 1605                         m1 = *m0;
 1606                         continue;
 1607                 }
 1608                 m0 = &m1->m_nextpkt;
 1609                 m1 = *m0;
 1610         }
 1611         txqueue->mput = m0;
 1612         splx(s);
 1613 
 1614         return (0);
 1615 }
 1616 
 1617 /*******************************************************************************
 1618  *
 1619  *  Calculate number of table positions for CBR connection
 1620  *
 1621  *  in:  IDT device, PCR (cells/second)
 1622  * out:  table positions needed (minimum = 1)
 1623  *
 1624  *  Date first: 11/29/2000  last: 06/12/2001
 1625  */
 1626 int
 1627 idt_slots_cbr(IDT * idt, int pcr)
 1628 {
 1629         unsigned int bitrate;
 1630         unsigned int slots;
 1631         unsigned int rem;
 1632 
 1633         if (pcr == 171) {
 1634                 if (idt_sysctl_logvcs)
 1635                         device_printf(idt->dev,
 1636                                 "idt_slots_cbr:  CBR channel=64000, 1 slot\n");
 1637                 return (1);
 1638         }
 1639         if (pcr < 171) {
 1640                 if (idt_sysctl_logvcs)
 1641                         device_printf(idt->dev,
 1642                                 "idt_slots_cbr:  CBR pcr %d rounded up to 1 slot\n", pcr);
 1643                 return (1);
 1644         }
 1645         bitrate = pcr * 47 * 8;
 1646         slots = bitrate / 64000;
 1647         rem = bitrate % 64000;
 1648         if (rem && idt_sysctl_logvcs)
 1649                 device_printf(idt->dev,
 1650                         "idt_slots_cbr: CBR cell rate rounded down to %d from %d\n",
 1651                         ((slots * 64000) / 376), pcr);  /* slots++;  */
 1652 
 1653         if (idt_sysctl_logvcs)
 1654                 device_printf(idt->dev,
 1655                         "idt_slots_cbr:  CBR pcr=%d, slots=%d.\n", pcr, slots);
 1656         return (slots);
 1657 }
 1658 
 1659 /*  The original algorithm rounded up or down by 32k, the goal being to
 1660  *  map 64000 requests exactly.  Unfortunately, this caused one particular
 1661  *  SVC to be set one slot too low, causing mbuf cluster starvation.
 1662  *  We can still handle the single 64k channel with a special case, and
 1663  *  let all others fall where they may.
 1664  *
 1665  *******************************************************************************
 1666  *
 1667  *  Add TX QUEUE pointer to slots in CBR table
 1668  *
 1669  *  in:  IDT device, TX_QUEUE, number slots
 1670  * out:  zero = success
 1671  *
 1672  *  Date first: 11/29/2000  last: 06/11/2001
 1673  */
 1674 static int
 1675 idt_slots_add(IDT * idt, TX_QUEUE * queue, int slots)
 1676 {
 1677         TX_QUEUE *curval;
 1678         int p_max;              /* extra precision slots maximum */
 1679         int p_spc;              /* extra precision spacing value */
 1680         int p_ptr;              /* extra precision pointer */
 1681         int qptr, qmax;
 1682         int qlast;
 1683         int scdval;
 1684 
 1685         if (slots < 1)
 1686                 return (1);
 1687 
 1688         qmax = idt->txslots_max;
 1689         p_max = qmax << 8;
 1690         p_spc = p_max / slots;
 1691         p_ptr = p_spc >> 1;     /* use half spacing for start point */
 1692         qptr = p_ptr >> 8;
 1693         qlast = qptr;
 1694 
 1695         scdval = 0x20000000 | queue->scd;
 1696 
 1697         if (CBR_VERBOSE) {
 1698                 printf("idt_slots_add: p_max = %d\n", p_max);
 1699                 printf("idt_slots_add: p_spc = %d\n", p_spc);
 1700                 printf("idt_slots_add: p_ptr = %d\n", p_ptr);
 1701                 printf("idt_slots_add: qptr  = %d\n", qptr);
 1702         }
 1703         while (slots) {
 1704                 if (qptr >= qmax)       /* handle wrap for empty slot choosing */
 1705                         qptr -= qmax;
 1706                 curval = idt->cbr_slot[qptr];
 1707                 if (curval != NULL) {   /* this slot has CBR, so try next */
 1708                         qptr++; /* next slot */
 1709                         continue;
 1710                 }
 1711                 if (CBR_VERBOSE) {
 1712                         printf("idt_slots_add: using qptr %d (%d)\n", qptr, qptr - qlast);
 1713                         qlast = qptr;
 1714                 }
 1715                 idt->cbr_slot[qptr] = queue;
 1716                 nicstar_sram_wr(idt, qptr + IDT_TST_START, 1, scdval, 0, 0, 0);
 1717                 slots--;
 1718                 p_ptr += p_spc;
 1719                 if (p_ptr >= p_max)     /* main pointer wrap */
 1720                         p_ptr -= p_max;
 1721                 qptr = p_ptr >> 8;
 1722         }
 1723         return (0);
 1724 }
 1725 
 1726 /* 06/11/2001:  Extra precision pointer is used in order to handle cases where
 1727  *       fractional slot spacing causes a large area of slots to be filled.
 1728  *       This can cause further CBR circuits to get slots that have very
 1729  *       poor spacing.
 1730  *
 1731  *******************************************************************************
 1732  *
 1733  *  Remove TX QUEUE pointer from slots in CBR table
 1734  *
 1735  *  in:  IDT device, TX_QUEUE
 1736  * out:  number of CBR slots released
 1737  *
 1738  *  Date first: 12/03/2000  last: 12/03/2000
 1739  */
 1740 static int
 1741 idt_slots_rem(IDT * idt, TX_QUEUE * queue)
 1742 {
 1743         int qptr, qmax;
 1744         int slots;
 1745 
 1746         qmax = idt->txslots_max;
 1747         slots = 0;
 1748 
 1749         for (qptr = 0; qptr < qmax; qptr++) {
 1750                 if (idt->cbr_slot[qptr] != queue)
 1751                         continue;
 1752                 idt->cbr_slot[qptr] = NULL;
 1753                 nicstar_sram_wr(idt, qptr + IDT_TST_START, 1, 0x40000000, 0, 0, 0);
 1754                 slots++;
 1755         }
 1756         return (slots);
 1757 }
 1758 
 1759 /*******************************************************************************
 1760  *
 1761  *  Initialize slots in CBR table
 1762  *
 1763  *  in:  IDT device
 1764  * out:  zero = success
 1765  *
 1766  *  Date first: 11/29/2000  last: 11/29/2000
 1767  */
 1768 static int
 1769 idt_slots_init(IDT * idt)
 1770 {
 1771         int start;              /* table start pointer */
 1772         int qptr;
 1773 
 1774         start = IDT_TST_START;
 1775 
 1776         /* first, fill up the TX CBR table with 'VBR' entries  */
 1777 
 1778         for (qptr = 0; qptr < idt->txslots_max; qptr++) {
 1779                 idt->cbr_slot[qptr] = NULL;
 1780                 nicstar_sram_wr(idt, qptr + start, 1, 0x40000000, 0, 0, 0);
 1781         }
 1782 
 1783         /* now write the jump back to the table start */
 1784 
 1785         nicstar_sram_wr(idt, qptr + start, 1, 0x60000000 | start, 0, 0, 0);
 1786 
 1787         return (0);
 1788 }
 1789 
 1790 /*******************************************************************************
 1791  *
 1792  *  Open output queue for connection
 1793  *
 1794  *  in:  IDT device, connection (class, traf_pcr, & traf_scr fields valid)
 1795  * out:  zero = success
 1796  *
 1797  *  Date first: 11/29/2000  last: 06/13/2001
 1798  */
 1799 
 1800 int
 1801 idt_connect_txopen(IDT * idt, CONNECTION * connection)
 1802 {
 1803         TX_QUEUE *txqueue;
 1804         int cellrate;
 1805         int cbr_slots;
 1806         int s;
 1807 
 1808         cellrate = connection->traf_scr;        /* 06/13/2001 use SCR instead
 1809                                                  * of PCR */
 1810 
 1811         if (connection->class == T_ATM_UBR) {   /* UBR takes whatever is left
 1812                                                  * over */
 1813                 connection->queue = &idt->queue_ubr;
 1814                 if (idt_sysctl_logvcs)
 1815                         printf("idt_connect_txopen: UBR connection for %d/%d\n",
 1816                             connection->vpi, connection->vci);
 1817                 return (0);
 1818         }
 1819         if (connection->class == T_ATM_ABR) {   /* ABR treated as UBR-plus */
 1820                 connection->queue = &idt->queue_abr;
 1821                 if (idt_sysctl_logvcs)
 1822                         printf("idt_connect_txopen: UBR+ connection for %d/%d\n",
 1823                             connection->vpi, connection->vci);
 1824                 return (0);
 1825         }
 1826         if (connection->class == T_ATM_CBR) {
 1827                 cbr_slots = idt_slots_cbr(idt, cellrate);
 1828                 s = splimp();
 1829                 if (cbr_slots > (idt->txslots_max - idt->txslots_cur) ||
 1830                     idt->cbr_freect < 1) {
 1831                         splx(s);
 1832                         return (1);     /* requested rate not available */
 1833                 }
 1834                 idt->txslots_cur += cbr_slots;
 1835                 idt->cellrate_tcur += cellrate;
 1836                 idt->cbr_freect--;
 1837                 txqueue = idt->cbr_free[idt->cbr_freect];
 1838                 txqueue->rate = cellrate;       /* was connection->traf_pcr */
 1839 
 1840                 if (idt_slots_add(idt, txqueue, cbr_slots)) {
 1841                         idt->txslots_cur -= cbr_slots;  /* cannot add CBR slots */
 1842                         idt->cellrate_tcur -= cellrate;
 1843                         idt->cbr_free[idt->cbr_freect] = txqueue;
 1844                         idt->cbr_freect++;
 1845                         splx(s);
 1846                         return (1);
 1847                 }
 1848                 splx(s);
 1849                 if (idt_sysctl_logvcs)
 1850                         printf("idt_connect_txopen: CBR connection for %d/%d\n",
 1851                             connection->vpi, connection->vci);
 1852                 connection->queue = txqueue;
 1853         }
 1854         if (connection->class == T_ATM_VBR) {
 1855                 txqueue = &idt->queue_vbr;
 1856                 connection->queue = txqueue;
 1857                 txqueue->rate += connection->traf_scr;  /* from traf_pcr
 1858                                                          * 12/17/2000 */
 1859                 if (idt_sysctl_logvcs)
 1860                         printf("idt_connect_txopen: VBR connection for %d/%d\n",
 1861                             connection->vpi, connection->vci);
 1862         }
 1863         idt_connect_newvbr(idt);/* recalculate VBR divisor values */
 1864 
 1865         if (connection->class == T_ATM_CBR ||
 1866             connection->class == T_ATM_VBR)
 1867                 return (0);
 1868 
 1869         return (1);             /* unknown class */
 1870 }
 1871 
 1872 /*******************************************************************************
 1873  *
 1874  *  Close connection output queue
 1875  *
 1876  *  in:  IDT device, connection (class, traf_pcr, & traf_scr fields valid)
 1877  * out:  zero = success
 1878  *
 1879  *  Date first: 12/03/2000  last: 12/03/2000
 1880  */
 1881 int
 1882 idt_connect_txclose(IDT * idt, CONNECTION * connection)
 1883 {
 1884         TX_QUEUE *txqueue;
 1885         int cellrate;
 1886         int slots;
 1887         int s;
 1888 
 1889         cellrate = connection->traf_pcr;
 1890         txqueue = connection->queue;
 1891         if (idt_sysctl_logvcs)
 1892                 printf("idt_connect_txclose: closing connection for %d/%d\n",
 1893                     connection->vpi, connection->vci);
 1894 
 1895         idt_queue_flush(connection);    /* flush all connection mbufs */
 1896 
 1897         if (connection->class == T_ATM_UBR ||   /* UBR takes whatever is left
 1898                                                  * over */
 1899             connection->class == T_ATM_ABR) {   /* ABR not supported, use UBR */
 1900                 connection->queue = NULL;
 1901                 return (0);
 1902         }
 1903         if (connection->class == T_ATM_CBR) {
 1904                 slots = idt_slots_rem(idt, txqueue);    /* remove this queue
 1905                                                          * from CBR slots */
 1906                 s = splimp();
 1907                 idt->txslots_cur -= slots;
 1908                 idt->cellrate_tcur -= cellrate;
 1909                 if (txqueue != NULL) {  /* 06/12/2001 check for failure on
 1910                                          * open */
 1911                         idt->cbr_free[idt->cbr_freect] = txqueue;
 1912                         idt->cbr_freect++;
 1913                 }
 1914                 splx(s);
 1915                 connection->queue = NULL;
 1916         }
 1917         if (connection->class == T_ATM_VBR) {
 1918                 txqueue = &idt->queue_vbr;
 1919                 connection->queue = NULL;
 1920                 txqueue->rate -= connection->traf_scr;  /* from traf_pcr
 1921                                                          * 12/17/2000 */
 1922         }
 1923         idt_connect_newvbr(idt);/* recalculate VBR divisor values */
 1924 
 1925         if (connection->class == T_ATM_CBR ||
 1926             connection->class == T_ATM_VBR)
 1927                 return (0);
 1928 
 1929         return (1);             /* unknown class */
 1930 }
 1931 
 1932 /*******************************************************************************
 1933  *
 1934  *  Calculate new VBR divisor values
 1935  *
 1936  *  in:  IDT device
 1937  *
 1938  * Date first: 12/03/2000  last: 12/03/2000
 1939  */
 1940 static void
 1941 idt_connect_newvbr(IDT * idt)
 1942 {
 1943         TX_QUEUE *txqueue;
 1944         int rate_newvbr;
 1945         int rate_noncbr;
 1946         int divisor;
 1947 
 1948         txqueue = &idt->queue_vbr;
 1949 
 1950         rate_newvbr = txqueue->rate;
 1951         rate_noncbr = idt->cellrate_tmax - idt->cellrate_tcur;
 1952 
 1953         if (rate_newvbr < 1)    /* keep sane and prevent divide by zero */
 1954                 rate_newvbr = 1;
 1955 
 1956         if (rate_newvbr >= rate_noncbr) {
 1957                 txqueue->vbr_m = 1;
 1958                 txqueue->vbr_n = 1;
 1959                 return;
 1960         }
 1961         divisor = rate_newvbr * 1000;   /* size of lookup table */
 1962         divisor += rate_newvbr >> 1;    /* apply rounding to divide */
 1963         divisor /= rate_noncbr; /* always < 1000, since newvbr < noncbr */
 1964 
 1965         if (idt_sysctl_logvcs)
 1966                 printf("idt_connect_newvbr: divisor=%d\n", divisor);
 1967         txqueue->vbr_m = vbr_div_m[divisor];
 1968         txqueue->vbr_n = vbr_div_n[divisor];
 1969         if (idt_sysctl_logvcs)
 1970                 printf("idt_connect_newvbr: m=%d, n=%d\n", txqueue->vbr_m, txqueue->vbr_n);
 1971 }
 1972 
 1973 /*  For VBR, we track the sum of all the VBR peak cellrates, and divide
 1974  *  that from the "remaining" bandwidth, which is total minus current CBR.
 1975  *
 1976  *  We will need to adjust the VBR divisor whenever we add a CBR or VBR.
 1977  *
 1978  *  Because of the integer scalign (1000) preload, the cellrate for the
 1979  *  VBR channel should not exceed 2 million (aprox 5 OC3s).  This is
 1980  *  protected by the check for rate_newvbr >= rate_noncbr.
 1981  *
 1982  *******************************************************************************
 1983  *
 1984  *  Initialize large buffers, indexes, and reference counts
 1985  *
 1986  *  in:  IDT device
 1987  * out:  zero = success
 1988  *
 1989  * Date first: 11/01/2000  last: 05/25/2001
 1990  */
 1991 
 1992 int
 1993 idt_buffer_init(IDT * idt)
 1994 {
 1995 
 1996         idt->raw_headm = NULL;  /* nicstar_add_buf() will initialize */
 1997         idt->raw_headp = 0;
 1998 
 1999         return (0);
 2000 }
 2001 
 2002 /*******************************************************************************
 2003  *
 2004  *  Get large buffer from kernel pool
 2005  *
 2006  * out:  mbuf, NULL = error
 2007  *
 2008  * Date first: 05/25/2001  last: 05/25/2001
 2009  */
 2010 
 2011 struct mbuf *
 2012 idt_mbufcl_get(void)
 2013 {
 2014         struct mbuf *m;
 2015 
 2016         MGETHDR(m, M_DONTWAIT, MT_DATA);
 2017         if (m == NULL)
 2018                 return (NULL);
 2019 
 2020         MCLGET(m, M_DONTWAIT);
 2021         if (m->m_flags & M_EXT)
 2022                 return (m);
 2023 
 2024         m_freem(m);
 2025         return (NULL);
 2026 }
 2027 
 2028 /*******************************************************************************
 2029  *
 2030  *  Initialize connection table
 2031  *
 2032  *  in:  IDT, number of VPI bits (0, 1, or 2)
 2033  * out:  zero = success
 2034  *
 2035  * Date first: 10/29/2000  last: 12/10/2000
 2036  */
 2037 
 2038 int
 2039 idt_connect_init(IDT * idt, int vpibits)
 2040 {
 2041         CONNECTION *connection;
 2042         int pages;
 2043         int vpi;
 2044         int vci;
 2045 
 2046         switch (vpibits) {
 2047         case 1:
 2048                 idt->conn_maxvpi = 2;
 2049                 idt->conn_maxvci = 2048;
 2050                 break;
 2051         case 2:
 2052                 idt->conn_maxvpi = 4;
 2053                 idt->conn_maxvci = 1024;
 2054                 break;
 2055         default:
 2056                 idt->conn_maxvpi = 1;
 2057                 idt->conn_maxvci = 4096;
 2058         }
 2059 
 2060         pages = (sizeof(CONNECTION) * MAX_CONNECTION) + PAGE_SIZE - 1;
 2061         pages /= PAGE_SIZE;
 2062         idt->connection = contigmalloc(pages * PAGE_SIZE, M_DEVBUF, M_NOWAIT,
 2063             0x100000, 0xffffffff, 0x2000, 0);
 2064         if (idt->connection == NULL)
 2065                 return (1);
 2066 
 2067         for (vpi = 0; vpi < idt->conn_maxvpi; vpi++)
 2068                 for (vci = 0; vci < idt->conn_maxvci; vci++) {
 2069                         connection = &idt->connection[vpi * idt->conn_maxvci + vci];
 2070                         connection->vccinf = NULL;      /* may want to change to
 2071                                                          * "unclaimed" */
 2072                         connection->status = 0; /* closed */
 2073                         connection->vpi = vpi;
 2074                         connection->vci = vci;
 2075                         connection->queue = NULL;       /* no current TX queue */
 2076                         connection->recv = NULL;        /* no current receive
 2077                                                          * mbuf */
 2078                         connection->rlen = 0;
 2079                         connection->maxpdu = 0;
 2080                         connection->traf_pcr = 0;
 2081                         connection->traf_scr = 0;
 2082                         connection->aal = 0;
 2083                         connection->class = 0;
 2084                         connection->flg_mpeg2ts = 0;
 2085                         connection->flg_clp = 0;
 2086                 }
 2087 
 2088         return (0);
 2089 }
 2090 
 2091 /*******************************************************************************
 2092  *
 2093  *  Look up a connection
 2094  *
 2095  *  in:  IDT, vpi, vci
 2096  * out:  CONNECTION, NULL=invalid vpi/vci
 2097  *
 2098  * Date first: 10/29/2000  last: 10/29/2000
 2099  */
 2100 
 2101 CONNECTION *
 2102 idt_connect_find(IDT * idt, int vpi, int vci)
 2103 {
 2104         if (vpi >= idt->conn_maxvpi)
 2105                 return (NULL);
 2106         if (vci >= idt->conn_maxvci)
 2107                 return (NULL);
 2108 
 2109         return (&idt->connection[vpi * idt->conn_maxvci + vci]);
 2110 }
 2111 
 2112 /******************************************************************************
 2113  *
 2114  *                       MBUF SECTION
 2115  *
 2116  ******************************************************************************
 2117  *
 2118  *  Align data in mbuf (to 32-bit boundary)
 2119  *
 2120  *  in:  mbuf
 2121  * out:  zero = success
 2122  *
 2123  * Date first: 11/08/2000  last: 11/15/2000
 2124  */
 2125 
 2126 int
 2127 idt_mbuf_align(struct mbuf * m, struct mbuf * prev)
 2128 {
 2129         caddr_t buf_base;
 2130         int buf_size;
 2131         int offset;
 2132         int newlen;
 2133         int count;
 2134 
 2135         if (m == NULL)
 2136                 return (1);
 2137         if (((int)m->m_data & 3) == 0)
 2138                 return (0);
 2139 
 2140         if (m->m_flags & M_EXT) {       /* external storage */
 2141                 buf_base = m->m_ext.ext_buf;
 2142                 buf_size = m->m_ext.ext_size;
 2143 
 2144                 /*
 2145                  * we should really bail out at this point, since we cannot
 2146                  * just shift the data in an external mbuf
 2147                  */
 2148 
 2149         } else {
 2150                 if (m->m_flags & M_PKTHDR) {    /* internal storage, packet
 2151                                                  * header */
 2152                         buf_base = m->m_pktdat;
 2153                         buf_size = MHLEN;
 2154                 } else {
 2155                         buf_base = m->m_dat;    /* internal storage, no packet
 2156                                                  * header */
 2157                         buf_size = MLEN;
 2158                 }
 2159         }
 2160         offset = 4 - ((int)buf_base & 3);
 2161         offset &= 3;
 2162         buf_base += offset;     /* new (aligned) buffer base */
 2163 
 2164         if (m->m_len + offset > buf_size)       /* not enough space to just
 2165                                                  * move */
 2166                 if (prev != NULL)
 2167                         if (idt_mbuf_append4(prev, m->m_data) == 0) {   /* give word to prev
 2168                                                                          * mbuf */
 2169                                 m->m_data += 4;
 2170                                 m->m_len -= 4;
 2171                         }
 2172         if (m->m_len + offset > buf_size)       /* still not enough space */
 2173                 if (m->m_next != NULL) {
 2174                         newlen = buf_size - offset;     /* maximum new length */
 2175                         newlen &= 0xfffffc;     /* fix the length too... */
 2176                         count = buf_size - newlen;      /* bytes we have to get
 2177                                                          * rid of */
 2178                         if (idt_mbuf_prepend(m->m_next, m->m_data + newlen, count) == 0)
 2179                                 m->m_len = newlen;
 2180                 }
 2181         if (m->m_len + offset > buf_size)       /* we're stuck... */
 2182                 return (1);
 2183 
 2184         bcopy(m->m_data, buf_base, m->m_len);   /* move data to aligned
 2185                                                  * position */
 2186         m->m_data = buf_base;
 2187         return (0);
 2188 }
 2189 
 2190 /*******************************************************************************
 2191  *
 2192  *  Append 4 bytes to mbuf
 2193  *
 2194  *  in:  mbuf, data pointer
 2195  * out:  zero = success
 2196  *
 2197  * Date first: 11/08/2000  last: 12/13/2000
 2198  */
 2199 
 2200 int
 2201 idt_mbuf_append4(struct mbuf * m, char *newdata)
 2202 {
 2203         caddr_t buf_base;
 2204         int buf_size;
 2205         int align;
 2206         int space;
 2207 
 2208         if (m == NULL)
 2209                 return (1);
 2210 
 2211         if (m->m_flags & M_EXT) /* external storage */
 2212                 return (1);     /* 12/13/2000 we must not touch it */
 2213 
 2214         if (m->m_flags & M_PKTHDR) {    /* internal storage, packet header */
 2215                 buf_base = m->m_pktdat;
 2216                 buf_size = MHLEN;
 2217         } else {
 2218                 buf_base = m->m_dat;    /* internal storage, no packet header */
 2219                 buf_size = MLEN;
 2220         }
 2221 
 2222         align = (4 - ((int)buf_base & 3)) & 3;
 2223         buf_base += align;
 2224         buf_size -= align;
 2225         buf_size &= 0xfffffc;
 2226 
 2227         space = buf_size - m->m_len;
 2228         if (space < 4)          /* enough space to add 4 bytes? */
 2229                 return (1);
 2230 
 2231         space -= m->m_data - buf_base;  /* get space at end */
 2232 
 2233         if (space < 4) {
 2234                 bcopy(m->m_data, buf_base, m->m_len);
 2235                 m->m_data = buf_base;
 2236         }
 2237         bcopy(newdata, m->m_data + m->m_len, 4);
 2238         m->m_len += 4;
 2239 
 2240         return (0);
 2241 }
 2242 
 2243 /*******************************************************************************
 2244  *
 2245  *  Get current base of data storage
 2246  *
 2247  *  in:  mbuf
 2248  * out:  base
 2249  *
 2250  * Date first: 11/16/2000  last: 11/16/2000
 2251  */
 2252 
 2253 caddr_t
 2254 idt_mbuf_base(struct mbuf * m)
 2255 {
 2256         if (m == NULL)
 2257                 return (NULL);
 2258 
 2259         if (m->m_flags & M_EXT) /* external storage */
 2260                 return (m->m_ext.ext_buf);
 2261 
 2262         if (m->m_flags & M_PKTHDR)      /* internal storage, packet header */
 2263                 return (m->m_pktdat);
 2264 
 2265         return (m->m_dat);      /* internal storage, no packet header */
 2266 }
 2267 
 2268 /*******************************************************************************
 2269  *
 2270  *  Copy mbuf chain to new chain (aligned)
 2271  *
 2272  *  in:  mbuf
 2273  * out:  new mbuf chain, NULL=error
 2274  *
 2275  * Date first: 11/19/2000  last: 05/25/2001
 2276  */
 2277 
 2278 struct mbuf *
 2279 idt_mbuf_copy(IDT * idt, struct mbuf * m)
 2280 {
 2281         struct mbuf *nbuf, *dbuf, *sbuf;
 2282         u_char *sptr;
 2283         int slen;
 2284         int clen;
 2285 
 2286         nbuf = idt_mbufcl_get();
 2287         if (nbuf == NULL)
 2288                 return (NULL);
 2289         dbuf = nbuf;
 2290         dbuf->m_len = 0;
 2291 
 2292         for (sbuf = m; sbuf != NULL; sbuf = sbuf->m_next) {
 2293                 sptr = sbuf->m_data;
 2294                 slen = sbuf->m_len;
 2295                 while (slen) {
 2296                         clen = slen;
 2297                         if (clen > NICSTAR_LRG_SIZE - dbuf->m_len)
 2298                                 clen = NICSTAR_LRG_SIZE - dbuf->m_len;
 2299                         bcopy(sptr, dbuf->m_data + dbuf->m_len, clen);
 2300                         sptr += clen;
 2301                         slen -= clen;
 2302                         dbuf->m_len += clen;
 2303                         if (dbuf->m_len >= NICSTAR_LRG_SIZE) {
 2304                                 dbuf->m_next = idt_mbufcl_get();
 2305                                 if (dbuf->m_next == NULL) {
 2306                                         m_freem(nbuf);
 2307                                         return (NULL);
 2308                                 }
 2309                                 dbuf = dbuf->m_next;
 2310                                 dbuf->m_len = 0;
 2311                         }       /* if need dest buf */
 2312                 }               /* while(slen) */
 2313         }                       /* for... source buf */
 2314         m_freem(m);
 2315         return (nbuf);
 2316 }
 2317 
 2318 /*******************************************************************************
 2319  *
 2320  *  Prepend data to mbuf (no alignment done)
 2321  *
 2322  *  in:  mbuf, data pointer, data length
 2323  * out:  zero = success
 2324  *
 2325  * Date first: 11/15/2000  last: 12/13/2000
 2326  */
 2327 
 2328 int
 2329 idt_mbuf_prepend(struct mbuf * m, char *newdata, int newlen)
 2330 {
 2331         caddr_t buf_base;
 2332         int buf_size;
 2333         int space;
 2334 
 2335         if (m == NULL)
 2336                 return (1);
 2337 
 2338         if (m->m_flags & M_EXT) /* external storage */
 2339                 return (1);     /* 12/13/2000 we must not touch it */
 2340 
 2341         if (m->m_flags & M_PKTHDR) {    /* internal storage, packet header */
 2342                 buf_base = m->m_pktdat;
 2343                 buf_size = MHLEN;
 2344         } else {
 2345                 buf_base = m->m_dat;    /* internal storage, no packet header */
 2346                 buf_size = MLEN;
 2347         }
 2348 
 2349         space = m->m_data - buf_base;
 2350 
 2351         if (space >= newlen) {  /* already space at head of mbuf */
 2352                 m->m_data -= newlen;
 2353                 m->m_len += newlen;
 2354                 bcopy(newdata, m->m_data, newlen);
 2355                 return (0);
 2356         }
 2357         space = buf_size - m->m_len;    /* can we get the space by shifting? */
 2358         if (space < newlen)
 2359                 return (1);
 2360 
 2361         bcopy(m->m_data, m->m_data + newlen, m->m_len);
 2362         bcopy(newdata, m->m_data, newlen);
 2363         m->m_len += newlen;
 2364 
 2365         return (0);
 2366 }
 2367 
 2368 /*******************************************************************************
 2369  *
 2370  *  Get amount of data used in mbuf chain
 2371  *
 2372  *  in:  mbuf chain
 2373  * out:  used space
 2374  *
 2375  * Date first: 11/10/2000  last: 11/10/2000
 2376  */
 2377 
 2378 int
 2379 idt_mbuf_used(struct mbuf * mfirst)
 2380 {
 2381         struct mbuf *m1;
 2382         int mbuf_used;
 2383 
 2384         mbuf_used = 0;          /* used mbuf space */
 2385 
 2386         for (m1 = mfirst; m1 != NULL; m1 = m1->m_next)
 2387                 mbuf_used += m1->m_len;
 2388 
 2389         return (mbuf_used);
 2390 }
 2391 
 2392 /*******************************************************************************
 2393  *
 2394  *  Notes on transmit buffers:
 2395  *
 2396  *  According to the IDT Nicstar User Manual (version 1.0 2/26/1997), we must
 2397  *  follow these rules for the transmit buffers (page 66):
 2398  *
 2399  *  1.  The buffer length must not be zero.
 2400  *  2.  The buffer length must be a multiple of four bytes.
 2401  *  3.  The sum of the buffer lengths must be a multiple of 48 bytes if
 2402  *      it is a CS-PDU (eg AAL5).
 2403  *  4.  All buffers for a CS-PDU must be contiguous and grouped (no other
 2404  *      PDU buffers or even TSRs).
 2405  *  5.  For AAL5 PDUs, the buffer lengths must include 8 bytes for the
 2406  *      AAL5 length/control and CRC fields.
 2407  *  6.  For AAL5 PDUs, the buffer length of the last buffer must be > 8 bytes.
 2408  *  7.  For AAL5 PDUs, all buffers containing bytes for the last cell must
 2409  *      have the END_CS_PDU bit set to 1.
 2410  *
 2411  *  Also, from the IDT applications note ("FAQ") 77211_AN_97088.pdf file:
 2412  *    Page 5, under "General Technical Questions" (copied EXACTLY):
 2413  *
 2414  *  5).  Can the NicStar begin segmentation from a non-word aligned buffer?
 2415  *       No, the transmit buffer must point to a word aligned buffer.
 2416  *
 2417  *  Since the buffers MUST be word aligned and MUST be word lengths, we have
 2418  *  two potential problems with M_EXT mbufs:
 2419  *
 2420  *  1.  If the M_EXT mbuf has a non word aligned address, we have to copy
 2421  *      the whole thing to a fresh buffer.  Unless - the previous mbuf is
 2422  *      not M_EXT, and it is short by exactly the same amount.  Unlikely.
 2423  *
 2424  *  2.  If the M_EXT mbuf has a non word length, we have to push those bytes
 2425  *      to the next mbuf.  If the next mbuf is also M_EXT, we are stuck.
 2426  *      Unless - the extra bytes from both mbufs are exactly 4 bytes.  Then
 2427  *      we can MGET an empty buf to splice in between.
 2428  *
 2429  *  Also, these rules mean that if any buffer is not word-length, all of the
 2430  *  following buffers will need to be copied/shifted, unless one or more have
 2431  *  lengths off by the right amount to fix the earlier buffer.
 2432  *
 2433  *******************************************************************************
 2434  *
 2435  *  Put mbuf chain on transmit queue
 2436  *
 2437  *  in:  IDT device, mbuf chain, vpi, vci, flags (2 MPEG2 TS == 8 AAL5 cells)
 2438  * out:  (nothing)
 2439  *
 2440  * Date first: 11/08/2000  last: 05/30/2000
 2441  */
 2442 
 2443 void
 2444 idt_transmit(IDT * idt, struct mbuf * mfirst, int vpi, int vci, int flags)
 2445 {
 2446         CONNECTION *connection;
 2447         struct mbuf *m1, *m0, *malign, *msend;
 2448         int tot_size, tot_scq, x;
 2449         int this_len;
 2450         int padding;
 2451 
 2452         connection = idt_connect_find(idt, vpi, vci);
 2453         if (connection == NULL) {       /* this VPI/VCI not open */
 2454                 idt_transmit_drop(idt, mfirst);
 2455                 return;
 2456         }
 2457         if (connection->queue == NULL) {
 2458                 idt_transmit_drop(idt, mfirst);
 2459                 connection->vccinf->vc_oerrors++;
 2460                 return;
 2461         }
 2462         if (flags)
 2463                 connection->flg_mpeg2ts = 1;
 2464         else
 2465                 connection->flg_mpeg2ts = 0;
 2466 
 2467         /*
 2468          * New strategy:  assume that all the buffers are aligned and word
 2469          * length.  Drop out and handle exceptions below.
 2470          */
 2471 
 2472         tot_size = 0;
 2473         tot_scq = 1;
 2474         malign = NULL;
 2475 
 2476         for (m1 = mfirst; m1 != NULL; m1 = m1->m_next) {
 2477                 this_len = m1->m_len;
 2478                 tot_size += this_len;
 2479                 tot_scq++;
 2480                 if (malign != NULL)
 2481                         continue;
 2482                 if ((int)(m1->m_data) & 3) {    /* bad alignment */
 2483                         malign = m1;
 2484                         continue;
 2485                 }
 2486                 if ((this_len & 3) == 0)        /* mbuf length is ok */
 2487                         continue;
 2488                 if (m1->m_next != NULL) {       /* bad length (in middle) */
 2489                         malign = m1;
 2490                         continue;
 2491                 }
 2492                 padding = 4 - (this_len & 3);
 2493                 tot_size += padding;
 2494                 m1->m_len += padding;
 2495                 break;          /* last mbuf, so avoid the loop test */
 2496         }
 2497         if (malign == NULL) {   /* perfect packet, no copy needed */
 2498                 mfirst->m_pkthdr.len = tot_size;
 2499                 if (connection->flg_mpeg2ts)
 2500                         tot_scq += tot_size / 376;      /* more entries needed
 2501                                                          * for split */
 2502                 mfirst->m_pkthdr.csum_data = tot_scq;
 2503 
 2504                 if (idt_queue_put(connection, mfirst))  /* put packet on TX
 2505                                                          * queue */
 2506                         device_printf(idt->dev, "Cannot queue packet for %d/%d.\n", vpi, vci);
 2507                 if (connection->queue->mget == mfirst)  /* was the queue empty? */
 2508                         idt_transmit_top(idt, connection->queue);       /* IFF empty, prime it
 2509                                                                          * now */
 2510                 return;
 2511         }
 2512         /*
 2513          * Bad alignment or length, so fall through to old code... The first
 2514          * alignment problem is at 'malign'
 2515          */
 2516         if (idt_sysctl_logvcs)
 2517                 device_printf(idt->dev, "Bad TX buf alignment, len=%d.\n", tot_size);
 2518 
 2519         if (idt_mbuf_align(mfirst, NULL)) {
 2520                 printf("idt_transmit: cannot align first mbuf.\n");
 2521                 idt_transmit_drop(idt, mfirst);
 2522                 connection->vccinf->vc_oerrors++;
 2523                 return;
 2524         }
 2525         /* find first mbuf with bad alignment (if any) */
 2526 
 2527         m0 = mfirst;
 2528         for (m1 = mfirst->m_next; m1 != NULL; m0 = m1, m1 = m1->m_next) {
 2529                 if (m1->m_len & 3)
 2530                         break;
 2531                 if ((int)(m1->m_data) & 3)
 2532                         break;
 2533         }
 2534         if (m1 != NULL) {
 2535                 m1 = idt_mbuf_copy(idt, m1);    /* copy the rest into new
 2536                                                  * mbufs */
 2537                 m0->m_next = m1;
 2538                 if (m1 == NULL) {
 2539                         printf("idt_transmit: could not copy buffers.\n");
 2540                         idt_transmit_drop(idt, mfirst);
 2541                         connection->vccinf->vc_oerrors++;
 2542                         return; /* FIX THIS - this path has been taken */
 2543                 }
 2544         }
 2545         msend = mfirst;
 2546 
 2547         /* The mbuf chain is aligned, now we need to pad to word length */
 2548 
 2549         tot_size = idt_mbuf_used(msend);        /* forget the pkthdr length... */
 2550         msend->m_pkthdr.len = tot_size;
 2551 
 2552         padding = (4 - (tot_size & 3)) & 3;
 2553         if (padding) {
 2554                 for (m1 = msend; m1->m_next != NULL; m1 = m1->m_next);
 2555                 m1->m_len += padding;
 2556         }
 2557         x = 1;                  /* now calculate the SCQ entries needed */
 2558         for (m1 = msend; m1 != NULL; m1 = m1->m_next)
 2559                 x++;
 2560         if (connection->flg_mpeg2ts)
 2561                 x += tot_size / 376;    /* more entries needed for split */
 2562         msend->m_pkthdr.csum_data = x;
 2563 
 2564         /* now we have an mbuf chain, from *msend to *m1 ready to go */
 2565 
 2566         if (idt_queue_put(connection, msend))   /* put packet on TX queue */
 2567                 device_printf(idt->dev, "Cannot queue packet for %d/%d.\n", vpi, vci);
 2568 
 2569         if (connection->queue->mget == msend)   /* was the queue empty? */
 2570                 idt_transmit_top(idt, connection->queue);       /* IFF empty, prime it
 2571                                                                  * now */
 2572 }
 2573 
 2574 /*  Notes on mbuf usage in the transmit queue:
 2575  *
 2576  *  m_pkthdr.rcvif       Connection pointer (set by idt_queue_put)
 2577  *  m_pkthdr.len         Length of PDU
 2578  *  m_pkthdr.header      TX queue pointer (06/01/2001)
 2579  *  m_pkthdr.csum_flags  Unused, keep zero
 2580  *  m_pkthdr.csum_data   Number of SCQ entries needed or used
 2581  *
 2582  *******************************************************************************
 2583  *
 2584  *  Drop transmit mbuf chain and update counters
 2585  *
 2586  *  in:  IDT device, mbuf chain
 2587  * out:  (nothing)
 2588  *
 2589  * Date first: 11/08/2000  last: 11/08/2000
 2590  */
 2591 
 2592 void
 2593 idt_transmit_drop(IDT * idt, struct mbuf * mfirst)
 2594 {
 2595         struct mbuf *next;
 2596         int mesglen;
 2597 
 2598         mesglen = 0;
 2599         while (mfirst != NULL) {
 2600                 mesglen += mfirst->m_len;
 2601                 next = m_free(mfirst);
 2602                 mfirst = next;
 2603         }
 2604         device_printf(idt->dev, "dropping transmit packet, size=%d\n", mesglen);
 2605         idt->stats_oerrors++;   /* 12/15/2000 */
 2606 }
 2607 
 2608 /*******************************************************************************
 2609  *
 2610  *  Put mbuf chain on transmit queue
 2611  *
 2612  *  in:  IDT device, TX_QUEUE
 2613  * out:  (nothing)
 2614  *
 2615  * Date first: 12/03/2000  last: 06/01/2001
 2616  */
 2617 
 2618 void
 2619 idt_transmit_top(IDT * idt, TX_QUEUE * txqueue)
 2620 {
 2621         CONNECTION *connection;
 2622         struct mbuf *top, *m;
 2623         static int padding[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 2624         int scq_space;
 2625         int val, val1, val3, val4;
 2626         int count, mlen, tlen, pad;
 2627         char *mptr;
 2628         int pdulen;
 2629         int vci, vpi;
 2630         int s;
 2631 
 2632         if (txqueue == NULL)    /* 12/12/2000 */
 2633                 return;
 2634         if (txqueue->mget == NULL)      /* check for empty queue */
 2635                 return;
 2636 
 2637         s = splimp();
 2638 
 2639         scq_space = txqueue->scq_len - txqueue->scq_cur;
 2640 
 2641         /* Now we can add the queue entries for the PDUs */
 2642 
 2643         count = 0;
 2644 
 2645         for (;;) {
 2646                 top = txqueue->mget;    /* next available mbuf */
 2647                 if (top == NULL)
 2648                         break;
 2649 
 2650                 if (top->m_pkthdr.csum_data + 4 > scq_space)
 2651                         break;  /* not enough space for this PDU */
 2652 
 2653                 top = idt_queue_get(txqueue);
 2654                 if (top == NULL)
 2655                         break;
 2656                 connection = (CONNECTION *) top->m_pkthdr.rcvif;
 2657                 vpi = connection->vpi;
 2658                 vci = connection->vci;
 2659                 top->m_pkthdr.header = (void *)connection->queue;
 2660 
 2661                 top->m_pkthdr.csum_data = 0;    /* track actual number of SCQ
 2662                                                  * entries used */
 2663 
 2664                 tlen = top->m_pkthdr.len;
 2665                 switch (connection->aal) {
 2666                 case ATM_AAL0:
 2667                         val = 0;
 2668                         break;
 2669                 case ATM_AAL3_4:
 2670                         val = 0x04000000;
 2671                         break;
 2672                 case ATM_AAL5:
 2673                         val = 0x08000000;
 2674                         break;
 2675                 default:
 2676                         device_printf(idt->dev, "bad AAL for %d/%d\n", vpi, vci);
 2677                         m_freem(top);
 2678                         connection->vccinf->vc_oerrors++;
 2679                         continue;
 2680                 }
 2681                 val |= txqueue->vbr_m << 23;
 2682                 val |= txqueue->vbr_n << 16;
 2683                 val4 = (vpi << 20) | (vci << 4);
 2684                 if (connection->flg_clp)
 2685                         val4 |= 1;      /* set CLP flag */
 2686 
 2687                 /*
 2688                  * Now we are ready to start mapping the mbuf(s) to transmit
 2689                  * buffer descriptors.  If the MPEG2TS flag is set, we want
 2690                  * to create AAL5 PDUs of exactly 384 data bytes each.
 2691                  */
 2692 
 2693                 pdulen = top->m_pkthdr.len;     /* default case: don't split
 2694                                                  * PDU */
 2695                 pad = 0;
 2696                 if (connection->flg_mpeg2ts) {
 2697                         if ((pdulen % 376) == 0) {      /* correct multiple */
 2698                                 pdulen = 376;   /* cut off every pdu at 374
 2699                                                  * data bytes */
 2700                                 pad = 8;
 2701                         } else
 2702                                 device_printf(idt->dev, "Bad MPEG2 PDU buffer (%d bytes).\n", pdulen);
 2703                 }
 2704                 val3 = pdulen;  /* actual (unpadded) PDU length */
 2705 
 2706                 pdulen += (4 - (pdulen & 3)) & 3;
 2707 
 2708                 if (pad == 0) { /* normal padding (PDU not split) */
 2709                         pad = pdulen;
 2710                         if (connection->aal == ATM_AAL5)
 2711                                 pad += 8;
 2712                         pad = 48 - (pad % 48);
 2713                         if (pad == 48)
 2714                                 pad = 0;
 2715                         if (connection->aal == ATM_AAL5)
 2716                                 pad += 8;       /* pad of up to 52 is
 2717                                                  * possible/neccessary */
 2718                 }
 2719                 tlen = 0;
 2720                 for (m = top; m != NULL; m = m->m_next) {
 2721                         while ((mlen = m->m_len)) {
 2722                                 if (mlen + tlen > pdulen)
 2723                                         mlen = pdulen - tlen;   /* how much of this
 2724                                                                  * buffer can we use? */
 2725                                 mptr = m->m_data;
 2726                                 tlen += mlen;   /* length of this PDU */
 2727                                 m->m_len -= mlen;       /* bytes remaining in
 2728                                                          * mbuf */
 2729                                 m->m_data += mlen;      /* new data pointer */
 2730 
 2731                                 val1 = val;
 2732                                 if (tlen > pdulen + pad - 48)   /* is this buffer in the
 2733                                                                  * last cell? */
 2734                                         val1 |= 0x40000000;     /* last buffer in PDU */
 2735 
 2736                                 if (tlen == pdulen) {   /* end of PDU, so figure
 2737                                                          * padding needed */
 2738                                         idt->stats_opdus++;     /* 12/15/2000 */
 2739                                         idt->stats_obytes += pdulen;    /* 12/15/2000 */
 2740                                         connection->vccinf->vc_opdus++;
 2741                                         connection->vccinf->vc_obytes += pdulen;
 2742                                         tlen = 0;
 2743                                         if (pad <= 8)
 2744                                                 mlen += pad;    /* just "add" padding to
 2745                                                                  * this buffer */
 2746                                 }
 2747                                 *txqueue->scq_next++ = val1 | mlen;
 2748                                 *txqueue->scq_next++ = vtophys(mptr);
 2749                                 *txqueue->scq_next++ = val3;
 2750                                 *txqueue->scq_next++ = val4;
 2751                                 if (txqueue->scq_next - txqueue->scq_base >= txqueue->scq_len * 4)
 2752                                         txqueue->scq_next = txqueue->scq_base;
 2753                                 scq_space--;
 2754                                 top->m_pkthdr.csum_data++;      /* 12/22/2000 */
 2755 
 2756                                 /*
 2757                                  * if we need more than 8 bytes of padding,
 2758                                  * use the zero-filled buffer defined above.
 2759                                  */
 2760                                 if (tlen == 0 && pad > 8) {     /* end of PDU, do we
 2761                                                                  * need padding? */
 2762                                         val1 |= 0x40000000;     /* last buffer in PDU */
 2763                                         *txqueue->scq_next++ = val1 | pad;
 2764                                         *txqueue->scq_next++ = vtophys(padding);
 2765                                         *txqueue->scq_next++ = val3;
 2766                                         *txqueue->scq_next++ = val4;
 2767                                         if (txqueue->scq_next - txqueue->scq_base >= txqueue->scq_len * 4)
 2768                                                 txqueue->scq_next = txqueue->scq_base;
 2769                                         scq_space--;
 2770                                         top->m_pkthdr.csum_data++;      /* 12/22/2000 */
 2771                                 }
 2772                         }
 2773                 }
 2774 
 2775                 /*
 2776                  * Now that we have set up the descriptors, add the entry
 2777                  * for Transmit Status Request so we know when the PDU(s)
 2778                  * are done.
 2779                  */
 2780 
 2781                 *txqueue->scq_next++ = 0xa0000000;      /* TSR with interrupt */
 2782                 *txqueue->scq_next++ = (u_long)top;
 2783                 *txqueue->scq_next++ = 0;
 2784                 *txqueue->scq_next++ = 0;
 2785 
 2786                 if (txqueue->scq_next - txqueue->scq_base >= txqueue->scq_len * 4)
 2787                         txqueue->scq_next = txqueue->scq_base;
 2788                 scq_space--;
 2789                 top->m_pkthdr.csum_data++;      /* 12/22/2000 */
 2790                 count++;
 2791 
 2792                 txqueue->scq_cur += top->m_pkthdr.csum_data;
 2793         }
 2794 
 2795         /*
 2796          * 05/31/2001: Optimization: Since writing to SRAM is very
 2797          * expensive, we will only do this when the pointer is stale (half
 2798          * of the queue). If the queue is less than 1/4 full, then write the
 2799          * pointer anyway.
 2800          */
 2801 
 2802         if (idt_sysctl_qptrhold) {
 2803                 scq_space = txqueue->scq_next - txqueue->scq_last;      /* number pending */
 2804                 scq_space /= 4;
 2805                 if (scq_space < 0)
 2806                         scq_space += txqueue->scq_len;
 2807                 if (scq_space * 2 < txqueue->scq_len && /* less than half
 2808                                                          * pending */
 2809                     txqueue->scq_cur > txqueue->scq_len / 4)    /* and queue is active */
 2810                         count = 0;
 2811         }
 2812         if (count) {            /* we need to update the queue pointer */
 2813                 nicstar_sram_wr(idt, txqueue->scd, 1, vtophys(txqueue->scq_next), 0, 0, 0);
 2814                 txqueue->scq_last = txqueue->scq_next;
 2815         }
 2816         splx(s);
 2817 
 2818         return;
 2819 }
 2820 
 2821 /*  Once a packet has been put in the Segmentation Channel Queue, it will
 2822  *  be sent, and then the mbuf will harvested by idt_intr_tsq().  While it
 2823  *  is in the SCQ, m_pkthdr.header is the pointer to the TX queue.  This is
 2824  *  important because if the connection is closed while there are still
 2825  *  mbufs in the SCQ, idt_intr_tsq() still needs to update the TX queue.
 2826  *
 2827  ******************************************************************************
 2828  *
 2829  *  Handle entries in Transmit Status Queue (end of PDU interrupt or TSQ full)
 2830  *
 2831  *  in:  IDT device
 2832  *
 2833  *  Date first: 12/04/2000  last: 06/10/2001
 2834  */
 2835 static void
 2836 idt_intr_tsq(IDT * idt)
 2837 {
 2838         CONNECTION *connection;
 2839         TX_QUEUE *txqueue;
 2840         u_long *tsq_ptr;
 2841         u_long val;
 2842         struct mbuf *m;
 2843         int count, s;
 2844 
 2845         s = splimp();
 2846 
 2847         tsq_ptr = idt->tsq_head;
 2848 
 2849         count = 0;
 2850         while ((tsq_ptr[1] & 0x80000000) == 0) {
 2851                 m = (struct mbuf *) tsq_ptr[0];
 2852                 if (m != NULL) {/* first test for timer rollover entry */
 2853                         if (((int)m & 0x000000ff))      /* now do sanity check
 2854                                                          * on the mbuf ptr */
 2855                                 device_printf(idt->dev,
 2856                                         "DANGER! bad mbuf (%x), stamp=%x\n",
 2857                                         (int)m, (int)tsq_ptr[1]);
 2858                         else {
 2859                                 connection = (CONNECTION *) m->m_pkthdr.rcvif;
 2860                                 txqueue = (TX_QUEUE *) m->m_pkthdr.header;
 2861                                 txqueue->scq_cur -= m->m_pkthdr.csum_data;
 2862                                 if (txqueue->scq_cur < 0 || txqueue->scq_cur > txqueue->scq_len)
 2863                                         device_printf(idt->dev, "DANGER! scq_cur is %d\n", txqueue->scq_len);
 2864                                 m->m_pkthdr.header = NULL;
 2865                                 m_freem(m);
 2866                                 idt_transmit_top(idt, txqueue); /* move more into queue */
 2867                         }
 2868                 }
 2869                 tsq_ptr[0] = 0;
 2870                 tsq_ptr[1] = 0x80000000;        /* reset TSQ entry */
 2871                 tsq_ptr += 2;
 2872                 if (tsq_ptr >= idt->tsq_base + idt->tsq_size * 2)
 2873                         tsq_ptr = idt->tsq_base;
 2874                 count++;
 2875         }
 2876         idt->tsq_head = tsq_ptr;
 2877 
 2878         if (count) {
 2879                 val = (int)tsq_ptr - (int)idt->tsq_base;
 2880                 val -= 8;       /* always stay one behind */
 2881                 val &= 0x001ff8;
 2882                 *idt->reg_tsqh = val;
 2883         }
 2884         splx(s);
 2885 }
 2886 
 2887 /*  There is a problem with the pointer rollover where the SAR will think the
 2888  *  TSQ buffer is full (forever?) unless we hold the head pointer back.
 2889  *  This is not mentioned in the 77211 docs, but is a resolved issue in
 2890  *  revision D of the 77252 chips (see 77252 errata).
 2891  *
 2892  *  If a connection is closed while there are still mbufs in the TX queue,
 2893  *  the connection TX queue pointer will be NULL.  That is why we have a
 2894  *  special copy of the pointer in m_pkthdr.header.  Also, idt_transmit_top()
 2895  *  will allow the TX queue for that connection to empty properly.
 2896  *
 2897  *  It is possible for a TSQ entry to be 0x00ffffff/0x00ffffff, which is
 2898  *  obviously not an mbuf and not a timer rollover entry.  We now have an
 2899  *  mbuf sanity check for this.
 2900  *
 2901  ******************************************************************************
 2902  *
 2903  *    nicstar_itrx ( card )
 2904  *
 2905  *    service error in transmitting PDU interrupt.
 2906  *
 2907 */
 2908 static void
 2909 nicstar_itrx(nicstar_reg_t * idt)
 2910 {
 2911         /* trace mbuf and release */
 2912 }
 2913 
 2914 /******************************************************************************
 2915  *
 2916  *  Raw cell receive interrupt
 2917  *
 2918  *    service raw cell reception interrupt.
 2919  *
 2920  */
 2921 
 2922 static void
 2923 nicstar_rawc(nicstar_reg_t * idt)
 2924 {
 2925         u_long ptr_tail;
 2926         struct mbuf *qmbuf;
 2927         u_long *qptr;
 2928         u_long next_mbuf;
 2929         u_long next_phys;
 2930 
 2931         if (idt->raw_headm == NULL ||
 2932             idt->raw_headp == 0) {
 2933                 device_printf(idt->dev,
 2934                         "RAW cell received, buffers not ready (%x/%x).\n",
 2935                         (int)idt->raw_headm, (int)idt->raw_headp);
 2936                 return;
 2937         }
 2938         ptr_tail = *(volatile u_long *)(idt->virt_baseaddr + REGRAWT);
 2939         if ((ptr_tail & 0xfffff800) == idt->raw_headp)
 2940                 return;         /* still in the same large buffer */
 2941 
 2942         if ((ptr_tail & 0x7ff) < 64)    /* wait until something in new buffer */
 2943                 return;
 2944 
 2945         qmbuf = idt->raw_headm;
 2946         qptr = (u_long *)qmbuf->m_data;
 2947 
 2948         next_mbuf = qptr[31 * 16 + 1];  /* next handle (virtual) */
 2949         next_phys = qptr[31 * 16 + 0];  /* next physical address */
 2950 
 2951         /* if we want to do anything with the raw data, this is the place  */
 2952 
 2953         idt_mcheck_rem(idt, qmbuf);
 2954         m_free(qmbuf);
 2955 
 2956         idt->raw_headm = (struct mbuf *) next_mbuf;
 2957         idt->raw_headp = next_phys;
 2958 }
 2959 
 2960 /*****************************************************************************
 2961  *
 2962  *  Handle AAL5 PDU length
 2963  *
 2964  *  in:  IDT device, first mbuf in chain, last mbuf
 2965  * out:  zero = success, nz = failure (mbuf chain freed)
 2966  *
 2967  * Date first: 11/18/2000  last: 12/14/2000
 2968  */
 2969 
 2970 int
 2971 idt_receive_aal5(IDT * idt, struct mbuf * mfirst, struct mbuf * mdata)
 2972 {
 2973         struct mbuf *m2;
 2974         unsigned char *aal5len;
 2975         int plen;
 2976         int diff;
 2977 
 2978         aal5len = mdata->m_data + mdata->m_len - 6;     /* aal5 length = 16 bits */
 2979         plen = aal5len[0] * 256 + aal5len[1];
 2980         diff = mfirst->m_pkthdr.len - plen;     /* number of bytes to trim */
 2981 
 2982         if (diff == 0)
 2983                 return (0);
 2984 
 2985         if (diff < 0) {
 2986                 device_printf(idt->dev,
 2987                         "AAL5 PDU length (%d) greater than cells (%d), discarding\n",
 2988                         plen, mfirst->m_pkthdr.len);
 2989                 m_freem(mfirst);
 2990                 return (1);
 2991         }
 2992         while (mdata->m_len < diff) {   /* last mbuf not big enough */
 2993                 diff -= mdata->m_len;
 2994                 m2 = mdata;
 2995                 m_free(mdata);
 2996                 if (mdata == mfirst) {  /* we just tossed the whole PDU */
 2997                         device_printf(idt->dev, "AAL5 PDU length failed, discarding.\n");
 2998                         return (1);     /* the packetheadr length was bad! */
 2999                 }
 3000                 for (mdata = mfirst; mdata->m_next != m2; mdata = mdata->m_next);
 3001                 mdata->m_next = NULL;   /* remove old link to free'd mbuf */
 3002         }
 3003         mdata->m_len -= diff;   /* trim last mbuf */
 3004         mfirst->m_pkthdr.len = plen;
 3005 
 3006         return (0);
 3007 }
 3008 
 3009 /* 12/14/2000: Removed "pruning" log message.
 3010  *
 3011  *****************************************************************************
 3012  *
 3013  *    nicstar_recv ( card )
 3014  *
 3015  *    rebuilds PDUs from entries in the Recieve Status Queue.
 3016  *
 3017  */
 3018 struct rsq_entry {
 3019         u_long vpivci;
 3020         struct mbuf *mdata;
 3021         u_long crc;
 3022         u_long flags;
 3023 };
 3024 
 3025 static void
 3026 nicstar_recv(nicstar_reg_t * idt)
 3027 {
 3028         CONNECTION *connection;
 3029         volatile u_long *regh = (volatile u_long *)(idt->virt_baseaddr + REGRSQH);
 3030         struct rsq_entry *rsq;
 3031         struct mbuf *mdata, *mptr;
 3032         u_long flags;
 3033         u_long crc;
 3034         int vpi;
 3035         int vci;
 3036         int clen;
 3037         int x, s;
 3038 
 3039         s = splimp();
 3040 
 3041         rsq = (struct rsq_entry *) (idt->fixbuf + 0x2000 + (idt->rsqh & 0x1ffc));
 3042 
 3043         if ((rsq->flags & 0x80000000) == 0) {
 3044                 splx(s);
 3045                 return;
 3046         }
 3047         while (rsq->flags & 0x80000000) {
 3048                 vpi = rsq->vpivci >> 16;        /* first, grab the RSQ data */
 3049                 vci = rsq->vpivci & 0xffff;
 3050                 mdata = rsq->mdata;
 3051                 crc = rsq->crc;
 3052                 flags = rsq->flags;
 3053                 clen = (flags & 0x1ff) * 48;
 3054 
 3055                 rsq->vpivci = 0;/* now recycle the RSQ entry */
 3056                 rsq->mdata = NULL;
 3057                 rsq->crc = 0;
 3058                 rsq->flags = 0; /* turn off valid bit */
 3059                 rsq++;
 3060                 if (rsq == (struct rsq_entry *) (idt->fixbuf + 0x4000))
 3061                         rsq = (struct rsq_entry *) (idt->fixbuf + 0x2000);
 3062 
 3063                 idt_mcheck_rem(idt, mdata);
 3064 
 3065                 connection = idt_connect_find(idt, vpi, vci);
 3066                 if (connection == NULL) {       /* we don't want this PDU */
 3067                         printf("nicstar_recv: No connection %d/%d - discarding packet.\n",
 3068                             vpi, vci);
 3069                         m_free(mdata);  /* throw mbuf away */
 3070                         continue;
 3071                 }
 3072                 mdata->m_len = clen;
 3073 
 3074                 mptr = connection->recv;
 3075                 if (mptr == NULL) {
 3076                         if (mdata->m_flags & M_PKTHDR)
 3077                                 connection->recv = mdata;
 3078                         else {
 3079                                 idt->stats_ierrors++;   /* 12/15/2000 */
 3080                                 connection->vccinf->vc_ierrors++;
 3081                                 m_free(mdata);
 3082                                 continue;
 3083                         }
 3084                 } else {
 3085                         x = 0;
 3086                         while (mptr->m_next != NULL) {  /* find last mbuf in
 3087                                                          * chain */
 3088                                 mptr = mptr->m_next;
 3089                                 x++;
 3090                                 if (x > 25)
 3091                                         break;
 3092                         }
 3093                         if (x > 25) {
 3094                                 mptr = connection->recv;
 3095                                 printf("nicstar_recv: invalid mbuf chain - probable corruption!\n");
 3096                                 m_free(mdata);
 3097                                 idt->stats_ierrors++;   /* 12/15/2000 */
 3098                                 connection->vccinf->vc_ierrors++;
 3099                                 connection->recv = NULL;
 3100                                 connection->rlen = 0;
 3101                                 continue;
 3102                         }
 3103                         mptr->m_next = mdata;
 3104                 }
 3105                 connection->rlen += clen;
 3106 
 3107                 if (flags & 0x2000) {   /* end of PDU */
 3108                         mptr = connection->recv;        /* one or more mbufs
 3109                                                          * will be here */
 3110                         clen = connection->rlen;        /* length based on cell
 3111                                                          * count */
 3112                         connection->recv = NULL;
 3113                         connection->rlen = 0;
 3114 
 3115                         mptr->m_pkthdr.len = clen;
 3116                         mptr->m_pkthdr.rcvif = NULL;
 3117                         mptr->m_nextpkt = NULL;
 3118 
 3119                         if (mptr->m_pkthdr.csum_flags) {
 3120                                 device_printf(idt->dev,
 3121                                         "received pkthdr.csum_flags=%x\n",
 3122                                         mptr->m_pkthdr.csum_flags);
 3123                                 mptr->m_pkthdr.csum_flags = 0;
 3124                         }
 3125                         if (flags & 0x200 &&    /* bad CRC */
 3126                             idt->flg_igcrc == 0) {
 3127                                 printf("nicstar_recv: Bad CRC - discarding PDU: %d/%d\n", vpi, vci);
 3128                                 idt->stats_ierrors++;   /* 12/15/2000 */
 3129                                 connection->vccinf->vc_ierrors++;
 3130                                 m_freem(mptr);
 3131                                 continue;
 3132                         }
 3133                         if (connection->aal == ATM_AAL5) {
 3134                                 if (idt_receive_aal5(idt, mptr, mdata)) /* adjust for AAL5
 3135                                                                          * length */
 3136                                         continue;
 3137                         }
 3138                         idt->stats_ipdus++;     /* 12/15/2000 */
 3139                         idt->stats_ibytes += mptr->m_pkthdr.len;        /* 12/15/2000 */
 3140                         connection->vccinf->vc_ipdus++;
 3141                         connection->vccinf->vc_ibytes += mptr->m_pkthdr.len;
 3142                         idt_receive(idt, mptr, vpi, vci);
 3143                 } else if (connection->rlen > connection->maxpdu) {     /* this packet is insane */
 3144                         printf("nicstar_recv: Bad packet, len=%d - discarding.\n",
 3145                             connection->rlen);
 3146                         connection->recv = NULL;
 3147                         connection->rlen = 0;
 3148                         idt->stats_ierrors++;   /* 12/15/2000 */
 3149                         connection->vccinf->vc_ierrors++;
 3150                         m_freem(mptr);
 3151                 }               /* end of PDU */
 3152         }
 3153 
 3154         idt->rsqh = vtophys((u_long)rsq) & 0x1ffc;
 3155         *regh = (idt->rsqh - sizeof(struct rsq_entry)) & 0x1ff0;
 3156 
 3157         splx(s);
 3158 }
 3159 
 3160 /******************************************************************************
 3161  *
 3162  *  Physical Interrupt handler
 3163  *
 3164  *  service phyical interrupt.
 3165  *
 3166  */
 3167 
 3168 static void
 3169 nicstar_phys(nicstar_reg_t * idt)
 3170 {
 3171         u_long t;
 3172 
 3173         if (idt->flg_le25) {
 3174                 nicstar_util_rd(idt, 0x01, &t); /* get interrupt cause */
 3175                 if (t & 0x01) {
 3176                         nicstar_util_wr(idt, 1, 0x02, 0x10);    /* reset rx fifo */
 3177                         device_printf(idt->dev, "PHY cleared.\n");
 3178                 }
 3179         } else
 3180                 device_printf(idt->dev, "Physical interrupt.\n");
 3181 }
 3182 
 3183 /******************************************************************************
 3184  *
 3185  *  Status register values
 3186  */
 3187 
 3188 #define STAT_REG_RSQAF   0x0002 /* receive status queue almost full */
 3189 #define STAT_REG_LBMT    0x0004 /* large buffer queue empty */
 3190 #define STAT_REG_SBMT    0x0008 /* small buffer queue empty */
 3191 #define STAT_REG_RAWC    0x0010 /* raw cell interrupt */
 3192 #define STAT_REG_EPDU    0x0020 /* end of PDU interrupt */
 3193 #define STAT_REG_PHY     0x0400 /* physical interrupt */
 3194 #define STAT_REG_TIME    0x0800 /* timer overflow interrupt */
 3195 #define STAT_REG_TSQAF   0x1000 /* transmit status queue almost full */
 3196 #define STAT_REG_TXIN    0x4000 /* TX PDU incomplete */
 3197 #define STAT_REG_TXOK    0x8000 /* TX status indicator */
 3198 
 3199 /******************************************************************************
 3200  *
 3201  *  Interrupt handler
 3202  *
 3203  *    service card interrupt.
 3204  *
 3205  *    nicstar_intr ( card )
 3206  */
 3207 
 3208 void
 3209 nicstar_intr(void *arg)
 3210 {
 3211         IDT *idt;
 3212         volatile u_long stat_val, config_val;
 3213         int int_flags;
 3214         volatile int i;
 3215         int s;
 3216 
 3217         idt = (IDT *) arg;
 3218 
 3219         i = 0;
 3220 
 3221         s = splnet();
 3222 
 3223         config_val = *idt->reg_cfg;
 3224         stat_val = *idt->reg_stat;
 3225 
 3226         int_flags =
 3227             STAT_REG_TSQAF |    /* transmit status queue almost full */
 3228             STAT_REG_RSQAF |    /* receive status queue almost full */
 3229             STAT_REG_RAWC |     /* raw cell interrupt */
 3230             STAT_REG_EPDU |     /* end of PDU interrupt */
 3231             STAT_REG_TIME |     /* timer overflow interrupt */
 3232             STAT_REG_TXIN |     /* TX PDU incomplete */
 3233             STAT_REG_TXOK;      /* TX status indicator */
 3234 
 3235         if (idt->flg_le25)
 3236                 int_flags |= STAT_REG_PHY;      /* include flag for physical
 3237                                                  * interrupt */
 3238 
 3239         if (stat_val & (STAT_REG_LBMT | STAT_REG_SBMT)) {       /* buffer queue(s) empty */
 3240                 if (stat_val & STAT_REG_SBMT)
 3241                         device_printf(idt->dev, "small free buffer queue empty.\n");
 3242                 if (stat_val & STAT_REG_LBMT)
 3243                         device_printf(idt->dev, "large free buffer queue empty.\n");
 3244                 nicstar_ld_rcv_buf(idt);
 3245 
 3246                 if (*idt->reg_stat & STAT_REG_LBMT) {   /* still empty, so
 3247                                                          * disable IRQ */
 3248                         config_val &= ~0x01000000;
 3249                         *idt->reg_cfg = config_val;
 3250                 }
 3251         }
 3252         /* loop until no more interrupts to service */
 3253 
 3254         while (stat_val & int_flags) {
 3255                 i++;
 3256                 if (i < 0 || i > 100)
 3257                         break;
 3258 
 3259                 *idt->reg_stat = stat_val & int_flags;  /* clear status bits */
 3260 
 3261                 if (stat_val & STAT_REG_EPDU) { /* receive PDU */
 3262                         nicstar_recv(idt);
 3263                         nicstar_ld_rcv_buf(idt);        /* replace buffers,
 3264                                                          * moved here 11/14/2000 */
 3265                 }
 3266                 if (stat_val & STAT_REG_RAWC) { /* raw cell */
 3267                         nicstar_rawc(idt);
 3268                 }
 3269                 if (stat_val & STAT_REG_TXOK) { /* transmit complete */
 3270                         idt_intr_tsq(idt);
 3271                 }
 3272                 if (stat_val & STAT_REG_TXIN) { /* bad transmit */
 3273                         nicstar_itrx(idt);
 3274                         device_printf(idt->dev, "Bad transmit.\n");
 3275                 }
 3276                 if (stat_val & STAT_REG_TIME) { /* timer wrap */
 3277                         idt->timer_wrap++;
 3278                         idt_intr_tsq(idt);      /* check the TSQ */
 3279                         nicstar_recv(idt);      /* check the receive queue */
 3280                         if (idt_sysctl_logbufs)
 3281                                 idt_status_bufs(idt);   /* show the buffer
 3282                                                          * status */
 3283                 }
 3284                 if (stat_val & STAT_REG_PHY) {  /* physical interrupt */
 3285                         nicstar_phys(idt);
 3286                         *idt->reg_stat = STAT_REG_PHY;  /* clear the int flag */
 3287                 }
 3288                 if (stat_val & STAT_REG_RSQAF) {        /* RSQ almost full */
 3289                         nicstar_recv(idt);
 3290                         device_printf(idt->dev, "warning, RSQ almost full.\n");
 3291                         if (*idt->reg_stat & STAT_REG_RSQAF) {  /* RSQ full */
 3292                                 printf("RSQ is full, disabling interrupt.\n");
 3293                                 config_val &= 0x00000800;
 3294                                 *idt->reg_cfg = config_val;
 3295                         }
 3296                 }
 3297                 if (stat_val & STAT_REG_TSQAF) {        /* TSQ almost full */
 3298                         idt_intr_tsq(idt);
 3299                         device_printf(idt->dev, "warning, TSQ almost full.\n");
 3300                         if (*idt->reg_stat & STAT_REG_TSQAF) {
 3301                                 printf("TSQ is full, disabling interrupt.\n");
 3302                                 config_val &= ~0x00000002;
 3303                                 *idt->reg_cfg = config_val;
 3304                         }
 3305                 }
 3306                 stat_val = *idt->reg_stat;
 3307         }
 3308 
 3309         splx(s);
 3310         if (i < 1 || i > 50)
 3311                 device_printf(idt->dev, "i=%3d, status=%08x\n", i, (int)stat_val);
 3312 }

Cache object: 02f1ad81d7014b0b2f756a4707dd2c90


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.