source: rtems/c/src/lib/libbsp/i386/i386ex/network/network.c @ c27b2d0d

4.104.114.84.95
Last change on this file since c27b2d0d was c27b2d0d, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 20, 1999 at 6:55:50 PM

Update of network driver from Erik Ivanenko <erik.ivanenko@…>.
Comments follow:

Here is the contents of the network directory of the i386ex BSP. The
reset function has been recently added, and tested through a command
line interface. A reset event to the reset thread to reset the NIC.
This is done when the ISR detects that the NIC is in an invalid state.
It has not been tested "in real life" since the board has not seen an
invalid state since the reset function was implemented.

  • Property mode set to 100644
File size: 71.4 KB
Line 
1/* uti596.c: An 82596 ethernet driver for rtems-bsd.
2 *
3 *  $Id$
4 */
5
6void dump_scb(void);
7
8#ifdef DBG_VERSION
9#define BREAKPOINT()  asm("   int $3");
10#else
11#define BREAKPOINT()
12#endif
13
14#define KERNEL
15
16
17/*
18   
19  EII: Oct 16 : Version 0.0
20
21*/
22
23#define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only */
24#define DMA_MASK_REG     0x0A
25#define DMA_MODE_REG     0x0B
26#define DMA_ENABLE       0x0
27#define DMA_DISABLE      0x4   
28
29struct i596_rfd *pISR_Rfd; 
30
31void show_buffers (void);
32void show_queues(void);
33
34void outbyte(char);
35void dumpQ(void);
36
37#define UTI_596_ASSERT( condition, str )
38/*
39 * {  if (!( condition ) ) printf(str); }
40 */
41int count_rx = 0;
42
43/* static char *version = "uti596.c:v0.0 11/13/97\n"; */
44
45#include <bsp.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <rtems/error.h>
49#include <rtems/rtems_bsdnet.h>
50
51#include <sys/param.h>
52#include <sys/mbuf.h>
53#include <sys/socket.h>
54#include <sys/sockio.h>
55
56#include <net/if.h>
57
58#include <netinet/in.h>
59#include <netinet/if_ether.h>
60
61#include "uti596.h"
62#include "netexterns.h"
63
64#include <asm.h>
65
66
67/* #include "../misc/utils.h" */
68
69static struct uti596_softc uti596_softc;
70
71int uti596packetNumber = 0;
72
73static    int scbStatus;
74static    rtems_status_code sc;
75static    struct i596_cmd *pIsrCmd;
76static    struct i596_rfd *pIsrRfd;
77
78/*
79 * Initial 596 configuration
80 */
81char uti596initSetup[] = {
82        0x0E,   /* length, prefetch off ( no RBD's ) */
83        0xC8,   /* fifo to 8, monitor off */
84        0x40,   /* don't save bad frames ( was save= 80, use intel's 40 )*/
85        0x2E,   /* No source address insertion, 8 byte preamble */
86        0x00,   /* priority and backoff defaults */
87        0x60,   /* interframe spacing */
88        0x00,   /* slot time LSB */
89        0xf2,   /* slot time and retries */
90        0x0C,   /* */
91        0x08,   /* collision detect */
92        0x40,   /* minimum frame length */
93        0xfb,   /* tried C8 same as byte 1 in bits 6-7, else ignored*/
94        0x00,
95        0x3f    /*  no multi IA */ };
96/*
97 *  Externally defined symbols
98 */
99#define RX_BUF_COUNT     15
100#define TX_BUF_COUNT     4
101#define TX_BD_PER_BUF    4
102
103#define INTERRUPT_EVENT         RTEMS_EVENT_1
104#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
105#define NIC_RESET_EVENT         RTEMS_EVENT_3
106
107#define RBUF_SIZE       1520
108
109#define UTI_596_RFD_NUMBER 4
110
111/*
112 * Local Routines
113 */
114
115/* These are extern, and non-inline  for testing purposes */
116
117void        uti596addCmd                  (struct i596_cmd *pCmd);
118void        uti596_initMem                (struct uti596_softc *); 
119void        uti596_init                   (void * );
120int         uti596initRxBufs              (int num);
121int         uti596_initRFA                (int num);
122int         uti596initRxBufs              (int num);
123static int  uti596_ioctl                  (struct ifnet *, int, caddr_t);
124rtems_isr   uti596DynamicInterruptHandler (rtems_vector_number);
125
126void        uti596_txDaemon               (void *);
127void        uti596_rxDaemon               (void *);
128void        uti596_resetDaemon            (void *);
129
130void        uti596_stop                   (struct uti596_softc *);
131static void uti596_start                  (struct ifnet *);
132
133void        uti596reset            (void);
134
135void         uti596_stats      (struct uti596_softc *);
136
137void uti596_initialize_hardware(struct uti596_softc *);
138void uti596_reset_hardware(struct uti596_softc *);
139
140void uti596clearListStatus(struct i596_rfd *);
141void uti596addPolledCmd(struct i596_cmd *);
142
143void uti596supplyFD(struct i596_rfd *);
144
145struct i596_rfd * uti596dequeue( struct i596_rfd ** );
146void uti596append( struct i596_rfd ** , struct i596_rfd * ); 
147
148#ifdef DEBUG_INIT
149static void         print_eth              (unsigned char *);
150static void         print_hdr              (unsigned char *);
151static void         print_pkt              (unsigned char *);
152#endif
153
154void send_packet(struct ifnet *, struct mbuf *);
155
156#define UTI_596_IRQ 5
157#define UTI_596_ETH_MIN_SIZE 60
158
159/* Waits for the command word to clear.  The command word is cleared AFTER the interrupt is
160 * generated. This allows the CPU to issue the next command
161 */
162#define  UTI_WAIT_COMMAND_ACCEPTED(duration,function)\
163{   int waitcount = duration; \
164    while (  uti596_softc.scb.command ) \
165      if (--waitcount == 0) \
166        { \
167          printk("%s: i82596 timed out with status %x, cmd %x.\n", function, \
168                  uti596_softc.scb.status,  uti596_softc.scb.command); \
169          break; \
170        } \
171}
172/*************************************************************************/
173
174void 
175uti596_request_reset(void){
176   uti596_softc.nic_reset = 0;
177   sc = rtems_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT);
178   if ( sc != RTEMS_SUCCESSFUL )
179     rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc));
180}
181
182
183
184static void uti596_maskOn(const rtems_irq_connect_data* irq)
185{
186  /*
187   * code should be moved from initialize_hardware
188   * to this location ?
189   */
190  (void) BSP_irq_enable_at_i8259s (irq->name);
191}
192
193static void uti596_maskOff(const rtems_irq_connect_data* irq)
194{
195  /*
196   * code should be moved from initialize_hardware
197   * to this location ?
198   */
199  (void) BSP_irq_disable_at_i8259s (irq->name);
200}
201
202static int uti596_isOn(const rtems_irq_connect_data* irq)
203{
204  return BSP_irq_enabled_at_i8259s (irq->name);
205}
206
207
208/***********************************************************************
209 *  Function:   uti596initRFA(int num) ( New )
210 *
211 *  Description:
212 *              attempts to allocate and initialize ( chain together )
213 *              the requested number of FD's
214 *
215 *  Algorithm:
216 *
217 ***********************************************************************/
218
219
220int uti596_initRFA(int num)
221{
222    struct i596_rfd *pRfd;
223    int i = 0;
224
225
226#ifdef DBG_596
227    printf ("%s: uti596_initRFA %d.\n", num);
228#endif
229
230    /*
231     * Initialize the first rfd in the rfa
232     */
233    pRfd = (struct i596_rfd *) calloc (1,sizeof (struct i596_rfd));
234    if ( !pRfd ) {
235      printf("Can't allocate all buffers: only %d allocated\n", i);
236      return 0;
237    }
238    else {
239      uti596_softc.countRFD = 1;
240      uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd;
241    printf ( "First Rfd allocated is: %p\n", 
242             uti596_softc.pBeginRFA);
243    }
244
245    for (i = 1; i < num; i++) {
246      pRfd = (struct i596_rfd *) calloc (1,sizeof (struct i596_rfd) );
247      if ( pRfd != NULL ) {
248        uti596_softc.countRFD++;
249        uti596_softc.pEndRFA -> next = pRfd; /* link it in   */   
250        uti596_softc.pEndRFA         = pRfd; /* move the end */
251#ifdef DBG_596_RFA
252        printf("Allocated RFD @ %p\n", pRfd);
253#endif
254      }
255      else {   
256        printf("Can't allocate all buffers: only %d allocated\n", i);
257        break;
258      }
259    } /* end for */
260   
261    uti596_softc.pEndRFA -> next = I596_NULL;
262    UTI_596_ASSERT(uti596_softc.countRFD == UTI_596_RFD_NUMBER,"INIT:WRONG RFD COUNT\n" ); 
263   
264#ifdef DBG_596_RFA
265    printf ( "Head of RFA is buffer %p\nEnd of RFA is buffer %p \n", 
266             uti596_softc.pBeginRFA, 
267             uti596_softc.pEndRFA );
268#endif
269    /* initialize the Rfd's */
270    for ( pRfd = uti596_softc.pBeginRFA;
271          pRfd != I596_NULL;
272          pRfd = pRfd -> next ) {
273         
274      pRfd->cmd = 0x0000;
275      pRfd->stat = 0x0000;
276      pRfd->pRbd =  I596_NULL;
277      pRfd->count = 0;  /* number of bytes in buffer: usually less than size */
278      pRfd->size = 1532;      /* was 1532;  buffer size ( All RBD ) */
279      if ( pRfd -> data == NULL )
280        printf("Can't allocate the RFD data buffer\n");
281    }
282
283    /* mark the last FD */ 
284    uti596_softc.pEndRFA -> cmd = CMD_EOL; /* moved jan 13 from before the init stuff */
285
286#ifdef DBG_596_RFA
287    printf ( "Head of RFA is buffer @ %p \n", uti596_softc.pBeginRFA );
288#endif
289
290
291    uti596_softc.pSavedRfdQueue = 
292      uti596_softc.pEndSavedQueue = I596_NULL;   /* initially empty */
293   
294    uti596_softc.savedCount = 0;
295
296    uti596_softc.nop.cmd.command = CmdNOp; /* initialize the nop command */
297
298    return (i); /* the number of allocated buffers */
299   
300}
301/***********************************************************************
302 *  Function:   uti596supplyFD
303 *
304 *  Description: returns a buffer to the receive frame pool.
305 *               call this with Inetrrupts disabled!
306 *
307 *  Algorithm:
308 *
309 ***********************************************************************/
310void uti596supplyFD(struct i596_rfd * pRfd )
311{
312 struct i596_rfd *pLastRfd;
313
314
315 UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD!\n");
316 pRfd -> cmd  = CMD_EOL;
317 pRfd -> pRbd = I596_NULL;
318 pRfd -> next = I596_NULL;
319 pRfd -> stat = 0x0000;      /* clear STAT_C and STAT_B bits */
320
321 /*
322  * Check if the list is empty:
323  */
324 if ( uti596_softc.pBeginRFA == I596_NULL ) { 
325   /* Init a list w/ one entry */
326   uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd;
327   UTI_596_ASSERT(uti596_softc.countRFD == 0, "Null begin, but non-zero count\n");
328   if ( uti596_softc.pLastUnkRFD != I596_NULL )
329     printf("LastUnkRFD is NOT NULL!!\n");
330   uti596_softc.countRFD = 1;
331   return;
332 }
333 /*
334  * Check if the last RFD is used/read by the 596.
335  */
336 pLastRfd = uti596_softc.pEndRFA;
337 
338 if (    pLastRfd != I596_NULL && 
339      ! (pLastRfd -> stat & ( STAT_C | STAT_B ) )) { /* C = complete, B = busy (prefetched) */
340   
341   /*
342    * Not yet too late to add it
343    */
344   pLastRfd -> next = pRfd;
345   pLastRfd -> cmd &= ~CMD_EOL;  /* RESET_EL : reset EL bit to 0  */
346   uti596_softc.countRFD++;  /* Lets assume we add it successfully
347                                If not, the RFD may be used, and may decrement countRFD < 0 !!*/
348   /*
349    * Check if the last RFD was used while appending.
350    */
351   if ( pLastRfd -> stat & ( STAT_C | STAT_B ) ) { /* completed or was prefetched */
352     /*
353      * Either the EL bit of the last rfd has been read by the 82596,
354      * and it will stop after reception,( true when RESET_EL not reached ) or
355      * the EL bit was NOT read by the 82596 and it will use the linked
356      * RFD for the next reception. ( true is RESET_EL was reached )
357      * So, it is unknown whether or not the linked rfd will be used.
358      * Therefore, the end of list CANNOT be updated.
359      */
360     UTI_596_ASSERT ( uti596_softc.pLastUnkRFD == I596_NULL, "Too many Unk RFD's\n" );
361     uti596_softc.pLastUnkRFD = pRfd;             
362     return;
363   }
364   else {
365     /*
366      * The RFD being added was not touched by the 82596
367      */
368     if (uti596_softc.pLastUnkRFD != I596_NULL ) {
369   
370       uti596append(&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */
371       uti596_softc.pEndSavedQueue = pRfd;
372       uti596_softc.savedCount++;
373       uti596_softc.countRFD--;
374       
375     }
376     else {
377       uti596_softc.pEndRFA = pRfd;           /* the RFA has been extended */
378       if ( ( uti596_softc.scb.status & SCB_STAT_RNR || 
379              uti596_softc.scb.status & RU_NO_RESOURCES ) &&
380            uti596_softc.countRFD > 1 ) {   /* was == 2 */
381         uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL;  /* Ensure that beginRFA is not EOL */
382         
383         UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n");
384         UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n");
385         UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n");
386#ifdef DBG_START
387         printf("Supply FD: starting receiver");
388#endif
389         /* start the receiver */
390         UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n");
391         uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;
392         uti596_softc.scb.command = RX_START | SCB_STAT_RNR;  /* Don't ack RNR! The receiver should be stopped in this case */
393         UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n");
394         outport_byte(CHAN_ATTN, 0); 
395       }
396     }
397     return;
398     
399   }
400 } 
401 else {
402   /*
403    * too late , pLastRfd in use ( or NULL ),
404    * in either case, EL bit has been read, and RNR condition will occur
405    */
406   uti596append( &uti596_softc.pSavedRfdQueue, pRfd); /* save it for RNR */
407   
408   uti596_softc.pEndSavedQueue = pRfd;                /* reset end of saved queue */ 
409   uti596_softc.savedCount++;
410   
411   
412   return;
413 }
414}
415
416
417static void
418uti596_start (struct ifnet *ifp)
419{
420        struct uti596_softc *sc = ifp->if_softc;
421
422        rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
423        ifp->if_flags |= IFF_OACTIVE;
424}
425
426void
427uti596_initialize_hardware(struct uti596_softc *sc)
428{
429  int boguscnt = 1000;
430  rtems_status_code status_code;
431 
432  /* reset the board  */
433  outport_word( PORT_ADDR, 0 );
434  outport_word( PORT_ADDR, 0 );
435
436  sc->pScp = (struct i596_scp *)
437    calloc(1,sizeof(struct i596_scp) + 0xf);
438#ifdef DBG_INIT
439  printf("initialize_hardware:Scp address initially %p\n", sc->pScp);
440#endif
441  sc->pScp = (struct i596_scp *)
442    ((((int)uti596_softc.pScp) + 0xf) & 0xfffffff0);
443 
444
445#ifdef DBG_INIT
446  printf("initialize_hardware:change scp address to : %p\n",sc->pScp);
447#endif
448
449 
450  /* change the scp address */
451#ifdef DBG_INIT
452  printf("Change the SCP address\n");
453#endif
454 
455  /*
456   * Set the DMA mode to enable the 82596 to become a bus-master
457   */
458  outport_byte(DMA_MASK_REG,DMA_DISABLE);      /* disable_dma */
459  outport_byte(DMA_MODE_REG,DMA_MODE_CASCADE); /* set dma mode */
460  outport_byte(DMA_MASK_REG,DMA_ENABLE);       /* enable dma */
461
462  /* reset the board  */
463  outport_word( PORT_ADDR, 0 );
464  outport_word( PORT_ADDR, 0 );
465 
466  outport_word(PORT_ADDR, ((((int)uti596_softc.pScp) &  0xffff) | 2 ));
467  outport_word(PORT_ADDR, (( (int)uti596_softc.pScp) >> 16 ) & 0xffff );
468 
469  /* This is linear mode, LOCK function is disabled  */
470 
471  sc->pScp->sysbus = 0x00540000;
472  sc->pScp->iscp   = &sc->iscp;
473  sc->iscp.scb     = &sc->scb;
474  sc->iscp.stat    = 0x0001;
475 
476  sc->pCmdHead     = sc->scb.pCmd = I596_NULL;
477 
478#ifdef DBG_596
479  printf("Starting i82596.\n");
480#endif
481 
482  /* Pass the scb address to the 596 */
483  outport_word(CHAN_ATTN,0);
484 
485  while (sc->iscp.stat)
486    if (--boguscnt == 0)
487      {
488        printf("initialize_hardware: timed out with status %4.4lx\n", 
489               sc->iscp.stat );
490        break;
491      }
492 
493  /* clear the command word */
494  sc->scb.command = 0;
495     
496  /*
497   * Set up interrupts ( NEW irq style )
498   */
499  sc->irqInfo.name = UTI_596_IRQ;
500  sc->irqInfo.hdl  = ( void * ) uti596DynamicInterruptHandler;
501  sc->irqInfo.on   = uti596_maskOn;
502  sc->irqInfo.off  = uti596_maskOff;
503  sc->irqInfo.isOn = uti596_isOn;
504 
505  status_code = BSP_install_rtems_irq_handler (&sc->irqInfo);
506  if (!status_code)
507    rtems_panic ("Can't attach uti596 interrupt handler for irq %d\n",
508                  sc->irqInfo.name);
509
510  /* Initialize the 82596 memory ( Transmit buffers ) */
511  uti596_initMem(sc);
512 
513#ifdef DBG_INIT
514  printf("After attach, status of board = 0x%x\n", sc->scb.status );
515#endif
516  outport_word(0x380, 0xf); /* reset the LED's */
517}
518
519
520void
521uti596_reset_hardware(struct uti596_softc *sc)
522{
523  int boguscnt = 1000;
524 
525  /* reset the board  */
526  outport_word( PORT_ADDR, 0 );
527  outport_word( PORT_ADDR, 0 );
528
529#ifdef DBG_RESET
530  printf("reset_hardware:Scp address %p\n", sc->pScp);
531#endif
532  sc->pScp = (struct i596_scp *)
533    ((((int)uti596_softc.pScp) + 0xf) & 0xfffffff0);
534 
535#ifdef DBG_RESET
536  printf("reset_hardware:change scp address to : %p\n",sc->pScp);
537#endif
538
539 
540  /* change the scp address */
541#ifdef DBG_RESET
542  printf("Change the SCP address\n");
543#endif
544 
545  /*
546   * Set the DMA mode to enable the 82596 to become a bus-master
547   */
548  outport_byte(DMA_MASK_REG,DMA_DISABLE);      /* disable_dma */
549  outport_byte(DMA_MODE_REG,DMA_MODE_CASCADE); /* set dma mode */
550  outport_byte(DMA_MASK_REG,DMA_ENABLE);       /* enable dma */
551
552  /* reset the board  */
553  outport_word( PORT_ADDR, 0 );
554  outport_word( PORT_ADDR, 0 );
555 
556  outport_word(PORT_ADDR, ((((int)uti596_softc.pScp) &  0xffff) | 2 ));
557  outport_word(PORT_ADDR, (( (int)uti596_softc.pScp) >> 16 ) & 0xffff );
558 
559  /* This is linear mode, LOCK function is disabled  */
560 
561  sc->pScp->sysbus = 0x00540000;
562  sc->pScp->iscp   = &sc->iscp;
563  sc->iscp.scb     = &sc->scb;
564  sc->iscp.stat    = 0x0001;
565 
566  sc->pCmdHead     = sc->scb.pCmd = I596_NULL;
567 
568#ifdef DBG_596
569  printf("reset_hardware: starting i82596.\n");
570#endif
571 
572  /* Pass the scb address to the 596 */
573  outport_word(CHAN_ATTN,0);
574 
575  while (sc->iscp.stat)
576    if (--boguscnt == 0)
577      {
578        printf("reset_hardware: timed out with status %4.4lx\n", 
579               sc->iscp.stat );
580        break;
581      }
582 
583  /* clear the command word */
584  sc->scb.command = 0;
585       
586#ifdef DBG_RESET
587  printf("After reset_hardware, status of board = 0x%x\n", sc->scb.status );
588#endif
589
590  outport_word(0x380, 0xf); /* reset the LED's */
591}
592
593
594/***********************************************************************
595 *  Function:   uti596_initMem
596 *
597 *  Description:
598 *             creates the necessary descriptors for the
599 *             uti596 board, hooks the interrupt, and starts the board.
600 *             Assumes that interrupts are hooked.
601 *
602 *  Algorithm:
603 *
604 ***********************************************************************/
605
606
607 void
608uti596_initMem(struct uti596_softc * sc)
609{
610    int i,count;
611    struct i596_tbd *pTbd;
612
613    sc->resetDone = 0; /* ??? */
614
615    /*
616     * Set up receive frame area (RFA)
617     */
618    i = uti596_initRFA( sc->rxBdCount );
619    if ( i < sc->rxBdCount  ) 
620      printf("init_rfd: only able to allocate %d receive frame descriptors\n", i);
621   
622    sc->scb.pRfd =  sc->pBeginRFA; 
623
624#ifdef DBG_INIT
625    printf(" IRQ %d.\n", sc->irqInfo.name);
626#endif   
627   
628    /*
629     * Diagnose the health of the board
630     */
631    uti596Diagnose(1);
632
633    /*
634     * set up the i596 config command
635     */
636#ifdef DBG_INIT
637    printf("Configuring\n");
638#endif
639
640    sc->set_conf.cmd.command = CmdConfigure;
641    memcpy (sc->set_conf.data, uti596initSetup, 14);
642    uti596addPolledCmd( (struct i596_cmd *) &sc->set_conf);
643
644    /****
645    * POLL
646    ****/
647
648    count = 2000;
649    while( !( sc->set_conf.cmd.status & STAT_C ) && --count )
650      printf(".");
651
652    if ( count )
653      printf("Configure OK, count = %d\n",count);
654    else
655      printf("***Configure failed\n");
656
657    /*******/
658
659    /*
660     * Create the IA setup command
661     */
662
663#ifdef DBG_INIT
664    printf("Setting Address\n");
665#endif
666    sc->set_add.cmd.command = CmdSASetup;
667    for ( i=0; i<6; i++)
668      sc->set_add.data[i]=sc->arpcom.ac_enaddr[i];
669
670    sc->cmdOk = 0;
671    uti596addPolledCmd((struct i596_cmd *)&sc->set_add);
672        /*******/
673   
674    count = 2000;
675    while( !(sc->set_add.cmd.status & STAT_C ) && --count)
676      printf(".");
677   
678    if ( count )
679      printf ("Set Address OK, count= %d\n",count);
680    else
681      printf("Set Address Failed\n");
682    /*******/
683
684#ifdef DBG_INIT
685    printf( "After initialization, status and command: 0x%x, 0x%x\n", 
686            sc->scb.status, sc->scb.status);
687     
688#endif
689
690    /* initialize transmit buffer descriptors*/
691    sc->pLastUnkRFD = I596_NULL;
692    sc->pTxCmd         = (struct tx_cmd *) calloc (1,sizeof (struct tx_cmd) );
693    sc->pTbd           = (struct i596_tbd *) calloc (1,sizeof (struct i596_tbd) );
694    sc->pTxCmd -> pTbd = sc->pTbd;
695    sc->pTxCmd->cmd.command  = CMD_FLEX|CmdTx;
696    sc->pTxCmd->pad          = 0;
697    sc->pTxCmd->size         = 0; /* all bytes are in list of TBD's */                         
698
699    pTbd = sc->pTbd;
700
701    for ( i=0; i<sc->txBdCount; i++)
702      pTbd = pTbd -> next = (struct i596_tbd *) calloc (1,sizeof (struct i596_tbd) );
703     
704    pTbd -> next = I596_NULL;
705
706    memset ( &sc->zeroes, 0, 64);   
707
708#ifdef DBG_596
709    printf( "After receiver start, status and command: 0x%x, 0x%x\n", 
710            sc->scb.status, sc->scb.status);
711#endif
712    printf("uti596_initMem allows ISR's\n");
713    sc->resetDone = 1; /* now need ISR  */
714
715}
716
717
718
719/***********************************************************************
720 *  Function:   uti596dump
721 *
722 *  Description: Dump 596 registers
723 *
724 *  Algorithm:
725 ***********************************************************************/
726/* static */ int
727uti596dump(char * pDumpArea)
728{
729  struct i596_dump dumpCmd;
730  int boguscnt = 25000000; /* over a second! */
731
732
733#ifdef DBG_596 
734printf("uti596dump:\n");
735#endif
736
737  dumpCmd.cmd.command = CmdDump;
738  dumpCmd.cmd.next    = I596_NULL;
739  dumpCmd.pData       = pDumpArea;
740  uti596_softc.cmdOk = 0;
741  uti596addCmd        ( (struct i596_cmd *)&dumpCmd);
742  while (1)
743    if ( --boguscnt == 0){
744      printf("Dump command was not processed within spin loop delay\n");
745      return 0;
746    }
747    else {
748      if ( uti596_softc.cmdOk )
749        return 1; /* successful completion */
750    }
751     
752 
753}
754
755/***********************************************************************
756 *  Function:   uti596_rxDaemon
757 *
758 *  Description: Receiver task
759 *
760 *  Algorithm: Extract the packet from an RFD, and place into an
761 *             mbuf chain.  Place the mbuf chain in the network task
762 *             queue. Assumes that the frame check sequence is removed
763 *             by the 82596.
764 *
765 ***********************************************************************/
766
767/* static */ void
768uti596_rxDaemon(void *arg)
769{
770  struct uti596_softc *sc = (struct uti596_softc *)arg;
771  struct ifnet *ifp = &sc->arpcom.ac_if;
772  struct mbuf *m;
773
774  struct i596_rfd *pRfd;
775  ISR_Level level;
776  int tid;
777  rtems_event_set events;
778  struct ether_header *eh;
779 
780  int frames = 0;
781 
782#ifdef DBG_596
783  printf ("uti596_rxDaemon\n");
784  printf("&scb = %p, pRfd = %p\n", &sc->scb,sc->scb.pRfd);
785#endif   
786
787  rtems_task_ident (0, 0, &tid);
788
789#ifdef DBG_596
790  printf("RX tid = 0x%x\n", tid);
791#endif   
792
793    for(;;) {
794      /*
795       * Wait for packet.
796       */
797#ifdef DBG_596
798      printf("Receiver sleeps\n");
799#endif
800
801      rtems_bsdnet_event_receive (INTERRUPT_EVENT,
802                                  RTEMS_WAIT|RTEMS_EVENT_ANY,
803                                  RTEMS_NO_TIMEOUT,
804                                  &events);
805     
806#ifdef DBG_596
807      printf("Receiver wakes\n");
808#endif
809      /*
810       * While received frames are available. Note that the frame may be
811       * a fragment, so it is NOT a complete packet.
812       */
813      pRfd = uti596dequeue( &sc->pInboundFrameQueue);
814      while ( pRfd && 
815              pRfd != I596_NULL &&
816              pRfd -> stat & STAT_C )
817        {
818
819#ifdef DEBUG_INIT
820          printf("\nReceived packet:\n");
821          print_eth( pRfd->data);
822#endif
823          if ( pRfd->stat & STAT_OK){
824            /*   a good frame. Allocate an mbuf to take it from the queue */
825
826            int pkt_len = pRfd->count & 0x3fff; /* the actual # of bytes received */
827
828#ifdef DBG_596
829            printf("Good frame, @%p, data @%p length %d\n", pRfd, pRfd -> data , pkt_len);
830#endif
831            frames++;
832
833           
834            /*
835             * Allocate an mbuf to give to the stack
836             * The format of the data portion of the RFD is:
837             * <ethernet header, payload>. 
838             * The FRAME CHECK SEQUENCE / CRC is stripped by the uti596.
839             * This is to be optimized later.... should not have to memcopy!
840             */
841            MGETHDR(m, M_WAIT, MT_DATA);
842            MCLGET(m, M_WAIT);
843
844            m->m_pkthdr.rcvif = ifp;
845            /* move everything into an mbuf */
846            memcpy(m->m_data, 
847                   pRfd->data, 
848                   pkt_len);
849
850            m->m_len = m->m_pkthdr.len = pkt_len - sizeof(struct ether_header) - 4;
851
852            /* move the header to an mbuf */
853            eh = mtod (m, struct ether_header *);
854            m->m_data += sizeof(struct ether_header);
855
856#ifdef DBG_596
857              printf("m->m_ext: %p pRfd -> data: %p\n",
858                     m->m_ext,  pRfd -> data);
859#endif
860#ifdef DEBUG_INIT_2
861            printf("mbuf contains:\n");
862            print_eth( (char *) (((int)m->m_data)-sizeof(struct ether_header)));
863            for ( i = 0; i<20; i++)
864              printf(".");
865
866#endif
867#ifdef DBG_VERSION
868          BREAKPOINT();
869#endif
870            ether_input (ifp, eh, m);
871
872          } /* end if STAT_OK */
873           
874          else {
875            /*
876             * A bad frame is present: Note that this could be the last RFD!
877             */
878#ifdef DBG_596
879            printf("Bad frame\n");
880#endif
881            /*
882             * FIX ME: use the statistics from the SCB
883             */
884            sc->stats.rx_errors++;
885            if ((sc->scb.pRfd->stat) & 0x0001) 
886              sc->stats.collisions++;
887            if ((sc->scb.pRfd->stat) & 0x0080) 
888              sc->stats.rx_length_errors++;
889            if ((sc->scb.pRfd->stat) & 0x0100) 
890              sc->stats.rx_over_errors++;
891            if ((sc->scb.pRfd->stat) & 0x0200) 
892              sc->stats.rx_fifo_errors++;
893            if ((sc->scb.pRfd->stat) & 0x0400) 
894              sc->stats.rx_frame_errors++;
895            if ((sc->scb.pRfd->stat) & 0x0800) 
896              sc->stats.rx_crc_errors++;
897            if ((sc->scb.pRfd->stat) & 0x1000) 
898              sc->stats.rx_length_errors++;
899          }
900
901          UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD\n");
902
903#ifdef DBG_SUPPLY_FD
904          printf("Supply FD Starting\n");
905#endif
906          _ISR_Disable(level);
907          uti596supplyFD ( pRfd );   /* Return RFD to RFA. CAN WE REALLY?*/
908          _ISR_Enable(level);
909#ifdef DBG_SUPPLY_FD
910          printf("Supply FD Complete\n");
911#endif
912#ifdef DBG_VERSION
913          BREAKPOINT();
914#endif
915
916          pRfd = uti596dequeue( &sc->pInboundFrameQueue); /* grab next frame */
917         
918        } /* end while */
919    } /* end for(;;)*/
920   
921#ifdef DBG_596
922    printf ("frames %d\n", frames);
923#endif
924   
925}
926
927 /***********************************************************************
928  *  Function:   uti596clearListStatus
929  *
930  *  Description:
931  *             Clear the stat fields for all rfd's
932  *  Algorithm:
933  *
934  ***********************************************************************/
935
936void
937uti596clearListStatus(struct i596_rfd *pRfd)
938{
939
940  while ( pRfd != I596_NULL ) {
941    pRfd -> stat = 0;           /* clear the status field */
942    pRfd = pRfd-> next; 
943  }
944}
945
946void uti596reset(void)
947 {
948   int i,count;
949   struct uti596_softc *sc = &uti596_softc;
950   /*   struct i596_rfd * pRfd; */
951
952#ifdef DBG_RESET
953     printf ("reset: begins\n");
954#endif
955
956  sc->resetDone = 0;
957  sc->irqInfo.off(&sc->irqInfo);
958
959  UTI_WAIT_COMMAND_ACCEPTED(10000, "reset: wait for previous command complete"); 
960
961  /* abort ALL of the current work */
962  sc->scb.command = CUC_ABORT | RX_ABORT;
963
964  outport_word(CHAN_ATTN,0);
965  UTI_WAIT_COMMAND_ACCEPTED(4000, "reset: abort requested");
966
967  uti596_reset_hardware(&uti596_softc); /* reset the ethernet hardware. must re-config */
968
969#ifdef DBG_RESET
970  uti596Diagnose(1);
971#endif
972
973  sc->set_conf.cmd.command = CmdConfigure;
974  memcpy (sc->set_conf.data, uti596initSetup, 14);
975  uti596addPolledCmd( (struct i596_cmd *) &sc->set_conf);
976 
977  /****
978   * POLL
979   ****/
980 
981  count = 2000;
982  while( !( sc->set_conf.cmd.status & STAT_C ) && --count )
983    printf(".");
984 
985  if ( count )
986    printf("Configure OK, count = %d\n",count);
987  else
988    printf("***reset: Configure failed\n");
989 
990  /*
991   * Create the IA setup command
992   */
993 
994#ifdef DBG_RESET
995  printf("reset: Setting Address\n");
996#endif
997  sc->set_add.cmd.command = CmdSASetup;
998  for ( i=0; i<6; i++)
999    sc->set_add.data[i]=sc->arpcom.ac_enaddr[i];
1000 
1001  sc->cmdOk = 0;
1002  uti596addPolledCmd((struct i596_cmd *)&sc->set_add);
1003 
1004  count = 2000;
1005  while( !(sc->set_add.cmd.status & STAT_C ) && --count)
1006    printf(".");
1007 
1008  if ( count )
1009    printf ("Reset Set Address OK, count= %d\n",count);
1010  else
1011    printf("Reset Set Address Failed\n");
1012  /*******/
1013 
1014#ifdef DBG_RESET
1015  printf( "After reset, status and command: 0x%x, 0x%x\n", 
1016          sc->scb.status, sc->scb.status);
1017 
1018#endif
1019 
1020
1021  /* restore the RFA */
1022
1023  dumpQ();
1024
1025  if ( sc->pLastUnkRFD != I596_NULL ) {
1026    sc-> pEndRFA =  sc->pLastUnkRFD; /* The end position can be updated */
1027    sc-> pLastUnkRFD = I596_NULL;           
1028  }
1029 
1030  sc->pEndRFA->next = sc->pSavedRfdQueue;
1031  if ( sc->pSavedRfdQueue != I596_NULL ) {
1032    sc->pEndRFA = sc->pEndSavedQueue;
1033    sc->pSavedRfdQueue = sc->pEndSavedQueue = I596_NULL;
1034    sc -> countRFD = sc->rxBdCount ;
1035  }
1036
1037  /*   if ( sc->pInboundFrameQueue != I596_NULL ){
1038    do {
1039      pRfd = sc->pInboundFrameQueue->next;
1040      sc->pEndRFA -> next = sc->pInboundFrameQueue;
1041      sc->pInboundFrameQueue = pRfd;
1042     } while( pRfd != I596_NULL ) ;
1043   
1044  }
1045  */
1046
1047  sc->scb.pRfd =  sc->pBeginRFA; /* readdress the head of the RFA in the SCB */
1048
1049  uti596clearListStatus(sc->pBeginRFA );
1050
1051  dumpQ(); /* purely for testing */
1052
1053  sc->irqInfo.on(&sc->irqInfo);  /* moved here. Was originally after command issued. */
1054  sc->scb.command = RX_START;
1055
1056  outport_word(CHAN_ATTN,0 ); 
1057  UTI_WAIT_COMMAND_ACCEPTED(4000, "reset");
1058   
1059  sc->resetDone = 1;
1060 
1061  sc->started = 1;
1062
1063  /* uti596addCmd(&uti506_softc.nop); */ /* just for fun */
1064 
1065#ifdef DBG_RESET
1066  printf("reset: complete\n");
1067#endif
1068 }
1069 
1070 /***********************************************************************
1071  *  Function:   uti596addCmd
1072  *
1073  *  Description:
1074  *             This routine adds a command onto the end of the
1075  *             command chain
1076  *
1077  *  Algorithm:
1078  *            Add the command to the end of and existing chain,
1079  *            or start the chain and issue a CUC_START
1080  *
1081  *
1082  ***********************************************************************/
1083
1084 /* static */ void uti596addCmd(struct i596_cmd *pCmd)
1085 {
1086     ISR_Level level;
1087
1088 #ifdef DBG_596
1089     printf("Adding command 0x%x\n", pCmd -> command );
1090 #endif
1091
1092#ifdef DEBUG_ADD
1093     
1094     switch ( pCmd -> command & 0x7 ){ /* check bottom 7 bits */
1095     case CmdConfigure:
1096       printf("ADD: Configure Command 0x%x\n", pCmd->command);
1097       break;
1098     case CmdSASetup:
1099       printf("ADD: Set Address Command 0x%x\n", pCmd->command);
1100       break;
1101     case CmdMulticastList:
1102       printf("ADD: Multi-cast list 0x%x\n", pCmd->command);
1103       break;
1104     case CmdNOp:
1105        printf("ADD: NO op 0x%x\n", pCmd->command);
1106        break;
1107     case CmdTDR:
1108        printf("ADD: TDR 0x%x\n", pCmd->command);
1109        break;
1110     case CmdDump:
1111       printf("ADD: Dump 0x%x\n", pCmd->command);
1112       break;
1113     case CmdDiagnose:
1114       printf("ADD: Diagnose 0x%x\n", pCmd->command);
1115       break;
1116     case CmdTx:
1117       break;
1118     default:
1119       printf("****Unknown Command encountered 0x%x\n", pCmd->command);
1120       break;
1121     } /* end switch */
1122       
1123#endif
1124
1125
1126
1127     pCmd->status = 0;
1128     pCmd->command |= (CMD_EOL | CMD_INTR ); /* all commands last in list & return an interrupt */
1129
1130     pCmd->next = I596_NULL;
1131
1132     _ISR_Disable(level);
1133     if (uti596_softc.pCmdHead == I596_NULL)
1134       {
1135         uti596_softc.pCmdHead =     
1136           uti596_softc.pCmdTail =
1137           uti596_softc.scb.pCmd = pCmd;
1138#ifdef DBG_596
1139         printf("First Cmd\n");
1140#endif
1141         UTI_WAIT_COMMAND_ACCEPTED(10000,"add command"); /* wait for acceptance of previous command */
1142         /* CHANGED TO |= Mar. 27 4:20 pm, was just =. changed back jun 18 1998. The wait assures command = 0 */
1143         uti596_softc.scb.command = CUC_START;
1144         outport_word (CHAN_ATTN,0);
1145     _ISR_Enable(level);
1146       }
1147     else 
1148       {
1149#ifdef DBG_596
1150         printf("Chained Cmd\n");
1151#endif
1152         uti596_softc.pCmdTail->next = pCmd; 
1153         uti596_softc.pCmdTail = pCmd;           /* added Jan 30 */
1154     _ISR_Enable(level);
1155       }
1156
1157
1158#ifdef DBG_596
1159         printf("Scb status & command 0x%x 0x%x\n", 
1160                uti596_softc.scb.status,
1161                uti596_softc.scb.command );
1162#endif
1163         
1164 }
1165 
1166 /***********************************************************************
1167  *  Function:   uti596addPolledCmd
1168  *
1169  *  Description:
1170  *             This routine issues a single command then polls for it's
1171  *             completion.  TO BE CALLED FROM ISR ONLY
1172  *
1173  *  Algorithm:
1174  *            Give the command to the driver. ( CUC_START is ALWAYS required )
1175  *            Poll for completion.
1176  *
1177  ***********************************************************************/
1178
1179void uti596addPolledCmd(struct i596_cmd *pCmd)
1180 {
1181
1182 #ifdef DBG_596
1183     printf("Adding command 0x%x\n", pCmd -> command );
1184 #endif
1185
1186#ifdef DEBUG_POLLED_CMD
1187     
1188     switch ( pCmd -> command & 0x7 ){ /* check bottom 7 bits */
1189     case CmdConfigure:
1190       printf("PolledCMD: Configure Command 0x%x\n", pCmd->command);
1191       break;
1192     case CmdSASetup:
1193       printf("PolledCMD: Set CMDress Command 0x%x\n", pCmd->command);
1194       break;
1195     case CmdMulticastList:
1196       printf("PolledCMD: Multi-cast list 0x%x\n", pCmd->command);
1197       break;
1198     case CmdNOp:
1199        printf("PolledCMD: NO op 0x%x\n", pCmd->command);
1200        break;
1201     case CmdTDR:
1202        printf("PolledCMD: TDR 0x%x\n", pCmd->command);
1203        break;
1204     case CmdDump:
1205       printf("PolledCMD: Dump 0x%x\n", pCmd->command);
1206       break;
1207     case CmdDiagnose:
1208       printf("PolledCMD: Diagnose 0x%x\n", pCmd->command);
1209       break;
1210     case CmdTx:
1211       break;
1212     default:
1213       printf("PolledCMD: ****Unknown Command encountered 0x%x\n", pCmd->command);
1214       break;
1215     } /* end switch */
1216       
1217#endif
1218
1219     pCmd->status = 0;
1220     pCmd->command |=  CMD_EOL ; /* only command in list*/
1221
1222     pCmd->next = I596_NULL;
1223
1224     uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd;
1225
1226     UTI_WAIT_COMMAND_ACCEPTED(10000,"Add Polled command: wait prev"); /* ensure prev command complete */
1227
1228     uti596_softc.scb.command = CUC_START;
1229     outport_word (CHAN_ATTN,0);
1230
1231     UTI_WAIT_COMMAND_ACCEPTED(2000000,"Add Polled command: start"); /* ensure previous command complete */
1232     /*     if ( !(pCmd -> status & STAT_C ) ){
1233            printf("****FAILED poll command\n");
1234            }
1235            */
1236     uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = I596_NULL;
1237
1238#ifdef DBG_596
1239     printf("Scb status & command 0x%x 0x%x\n", 
1240            uti596_softc.scb.status,
1241            uti596_softc.scb.command );
1242#endif
1243         
1244 }
1245/*
1246 * Driver transmit daemon
1247 */
1248void
1249uti596_txDaemon (void *arg)
1250{
1251        struct uti596_softc *sc = (struct uti596_softc *)arg;
1252        struct ifnet *ifp = &sc->arpcom.ac_if;
1253        struct mbuf *m;
1254        rtems_event_set events;
1255
1256        for (;;) {
1257          /*
1258           * Wait for packet from stack
1259           */
1260          rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, 
1261                                      RTEMS_EVENT_ANY | RTEMS_WAIT, 
1262                                      RTEMS_NO_TIMEOUT, &events);
1263         
1264          /*
1265           * Send packets till queue is empty
1266           */
1267          for (;;) { 
1268            /*
1269             * Get the next mbuf chain to transmit.
1270             */
1271            IF_DEQUEUE(&ifp->if_snd, m);
1272            if (!m)
1273              break;
1274           
1275            send_packet (ifp, m); /* blocks */
1276          } 
1277          ifp->if_flags &= ~IFF_OACTIVE; /* no more to send, mark output inactive  */
1278        }
1279}
1280
1281 
1282/*
1283 * NIC reset daemon.
1284 */
1285void
1286uti596_resetDaemon (void *arg)
1287{
1288        struct uti596_softc *sc = (struct uti596_softc *)arg;
1289        rtems_event_set events;
1290        /* struct ifnet *ifp = &sc->arpcom.ac_if; */
1291
1292        for (;;) {
1293          /*
1294           * Wait for reset event from ISR
1295           */
1296          rtems_bsdnet_event_receive (NIC_RESET_EVENT, 
1297                                      RTEMS_EVENT_ANY | RTEMS_WAIT, 
1298                                      RTEMS_NO_TIMEOUT, &events);
1299
1300          printf("reset daemon: Resetting NIC\n");
1301
1302          sc->stats.nic_reset_count++;
1303          /*
1304           * Reinitialize the network card
1305           */
1306          rtems_bsdnet_semaphore_obtain ();
1307          uti596reset();
1308          rtems_bsdnet_semaphore_release ();
1309        }
1310}
1311
1312 
1313 /***********************************************************************
1314  *  Function:   send_packet
1315  *
1316  *  Description: Send a raw ethernet packet
1317  *             
1318  *  Algorithm:
1319  *             increment some stats counters,
1320  *             create the transmit command,
1321  *             add the command to the CBL,
1322  *             wait for event
1323  *
1324  ***********************************************************************/
1325
1326void send_packet(struct ifnet *ifp, struct mbuf *m)
1327{
1328  struct i596_tbd *pPrev = I596_NULL,
1329    *pRemainingTbdList,
1330    *pTbd;
1331  struct mbuf *n, *input_m = m;
1332 
1333  struct uti596_softc *sc = ifp->if_softc; /* is this available from ifp ?*/
1334
1335  struct mbuf *l = NULL; 
1336  unsigned int length = 0;
1337  rtems_status_code status;
1338  int bd_count = 0;
1339  rtems_event_set events;
1340
1341  /*
1342   * For all mbufs in the chain,
1343   *  fill a transmit buffer descriptor
1344   */
1345  pTbd = sc->pTxCmd->pTbd;
1346
1347  do {             
1348    if (m->m_len) {
1349      /*
1350       * Fill in the buffer descriptor
1351       */
1352      length    += m->m_len;
1353      pTbd->data = mtod (m, void *);
1354      pTbd->size = m->m_len;
1355      pPrev      = pTbd;
1356      pTbd       = pTbd -> next;
1357      l          = m;
1358      m          = m->m_next;
1359    }
1360    else {
1361      /*
1362       * Just toss empty mbufs
1363       */
1364      MFREE (m, n);
1365      m = n;
1366      if (l != NULL)
1367        l->m_next = m;
1368    }
1369  } while( m != NULL && ++bd_count < 16 );
1370
1371
1372  /* This should never happen */
1373  if ( bd_count == 16 ) {
1374    printf("TX ERROR:Too many mbufs in the packet!!!\n");
1375    printf("Must coalesce!\n");
1376  }
1377 
1378 
1379  if ( length < UTI_596_ETH_MIN_SIZE ) {
1380    pTbd->data = sc->zeroes;       /* add padding to pTbd */
1381    pTbd->size = UTI_596_ETH_MIN_SIZE - length; /* zeroes have no effect on the CRC */
1382  }
1383  else
1384    pTbd = pPrev; /* Don't use pTbd in the send routine */
1385 
1386  /*  Disconnect the packet from the list of Tbd's  */
1387  pRemainingTbdList = pTbd->next;
1388  pTbd->next  = I596_NULL;     
1389  pTbd->size |= UTI_596_END_OF_FRAME;   
1390 
1391#ifdef DBG_RAW
1392  printf("RAW:Add cmd and sleep\n");
1393#endif
1394 
1395  sc->rawsndcnt++;     
1396   
1397#ifdef DBG_RAW
1398  printf ("sending packet\n");
1399#endif
1400 
1401  /* Sending Zero length packet: shouldn't happen */
1402  if (pTbd->size <= 0) return ;
1403
1404
1405#ifdef DEBUG_INIT_2
1406  printf("\nTransmitter adds packet\n");
1407  print_hdr    ( sc->pTxCmd->pTbd->data ); /* print the first part */
1408  print_pkt    ( sc->pTxCmd->pTbd->next->data ); /* print the first part */
1409  /*  print_echo(sc->pTxCmd->pTbd->data); */
1410#endif
1411#ifdef DBG_VERSION
1412          BREAKPOINT();
1413#endif
1414
1415
1416  /* add the command to the output command queue */
1417  uti596addCmd ( (struct i596_cmd *) sc->pTxCmd );
1418 
1419  /* sleep until the command has been processed or Timeout encountered. */
1420  status= rtems_bsdnet_event_receive (INTERRUPT_EVENT,
1421                                      RTEMS_WAIT|RTEMS_EVENT_ANY,
1422                                      RTEMS_NO_TIMEOUT,
1423                                      &events);
1424   
1425  if ( status != RTEMS_SUCCESSFUL ) {
1426    printf("Could not sleep %s\n", rtems_status_text(status)); 
1427  }
1428 
1429#ifdef DBG_RAW
1430  printf("RAW: wake\n");
1431#endif
1432 
1433  sc->txInterrupts++;
1434     
1435#ifdef DEBUG_INIT
1436  printf("\nTransmitter issued packet\n");
1437  print_hdr    ( sc->pTxCmd->pTbd -> data ); /* print the first part */
1438  print_pkt    ( sc->pTxCmd->pTbd ->next-> data ); /* print the first part */
1439#endif
1440
1441  if ( sc->pTxCmd -> cmd.status & STAT_OK )
1442    sc->stats.tx_packets++;
1443  else
1444    {
1445#ifdef DBG_RAW
1446      printf("******Driver Error 0x%x\n", sc->pTxCmd -> cmd.status );
1447#endif
1448      sc->stats.tx_errors++;
1449      if ( sc->pTxCmd->cmd.status  & 0x0020 ) 
1450        sc->stats.tx_retries_exceeded++;
1451      if (!(sc->pTxCmd->cmd.status & 0x0040)) 
1452        sc->stats.tx_heartbeat_errors++;
1453      if ( sc->pTxCmd->cmd.status  & 0x0400 ) 
1454        sc->stats.tx_carrier_errors++;
1455      if ( sc->pTxCmd->cmd.status  & 0x0800 ) 
1456        sc->stats.collisions++;
1457      if ( sc->pTxCmd->cmd.status  & 0x1000 ) 
1458        sc->stats.tx_aborted_errors++;
1459    } /* end if stat_ok */       
1460 
1461  /*
1462   * Restore the transmited buffer descriptor chain.
1463   */
1464  pTbd -> next = pRemainingTbdList;
1465 
1466  /*
1467   * Free the mbufs used by the sender.
1468   */
1469  m = input_m;
1470  while ( m != NULL ) {
1471    MFREE(m,n);
1472    m = n;
1473  }
1474
1475 
1476}
1477
1478 /***********************************************************************
1479  *  Function:   print_eth
1480  *
1481  *  Description:
1482  *              Print the contents of an ethernet packet header
1483  *              CANNOT BE CALLED FROM ISR
1484  *
1485  *  Algorithm:
1486  *            Print Destination, Src, and type of packet
1487  *
1488  ***********************************************************************/
1489
1490 /* static */ void print_eth(unsigned char *add)
1491 {
1492     int i;
1493     short int length;
1494
1495     printf("Packet Location %p\n", add);
1496
1497     printf ("Dest  ");
1498
1499     for (i = 0; i < 6; i++)
1500         printf(" %2.2X", add[i]);
1501
1502     printf ("\n");
1503
1504     printf ("Source");
1505
1506     for (i = 6; i < 12; i++)
1507         printf(" %2.2X", add[i]);
1508
1509     printf ("\n");
1510
1511     printf ("frame type %2.2X%2.2X\n", add[12], add[13]);
1512
1513     if ( add[12] == 0x08 && add[13] == 0x06 )
1514       { /* an ARP */
1515         printf("Hardware type : %2.2X%2.2X\n", add[14],add[15]);
1516         printf("Protocol type : %2.2X%2.2X\n", add[16],add[17]);
1517         printf("Hardware size : %2.2X\n", add[18]);
1518         printf("Protocol size : %2.2X\n", add[19]);
1519         printf("op            : %2.2X%2.2X\n", add[20],add[21]);
1520
1521         printf("Sender Enet addr: ");
1522
1523         for ( i=0; i< 5 ; i++)
1524           printf( "%x:", add[22 + i]);
1525
1526         printf("%x\n", add[27]);
1527
1528         printf("Sender IP addr: ");
1529         for ( i=0; i< 3 ; i++)
1530           printf( "%u.", add[28 + i]);
1531
1532         printf("%u\n", add[31]);
1533
1534         printf("Target Enet addr: ");
1535         for ( i=0; i< 5 ; i++)
1536           printf( "%x:", add[32 + i]);
1537         printf("%x\n", add[37]);
1538
1539         printf("Target IP addr: ");
1540
1541         for ( i=0; i< 3 ; i++)
1542           printf( "%u.", add[38 + i]);
1543         printf("%u\n", add[41]);
1544
1545        }
1546
1547     if ( add[12] == 0x08 && add[13] == 0x00 )
1548       { /* an IP packet */
1549         printf("*********************IP HEADER******************\n");
1550         printf("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15]);
1551         printf("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] )); 
1552         printf("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n",
1553                add[18],add[19], add[20], add[21]);
1554         printf("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n",
1555                add[22],add[23],add[24],add[25]);
1556         printf("IP packet type: %2.2X code %2.2X\n", add[34],add[35]);
1557
1558         printf("Source IP address: ");
1559         for ( i=0; i< 3 ; i++)
1560           printf( "%u.", add[26 + i]);
1561
1562         printf("%u\n", add[29]);
1563
1564         printf("Destination IP address: ");
1565         for ( i=0; i< 3 ; i++)
1566           printf( "%u.", add[30 + i]);
1567         printf("%u\n", add[33]);
1568
1569         /* printf("********************IP Packet Data*******************\n");
1570                 length -=20;
1571         for ( i=0; i < length ; i++)
1572           printf("0x%2.2x ", add[34+i]);
1573         printf("\n");
1574
1575         printf("ICMP checksum: %2.2x %2.2x\n", add[36], add[37]);
1576         printf("ICMP identifier: %2.2x %2.2x\n", add[38], add[39]);
1577         printf("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41]);
1578         */
1579        }
1580
1581
1582 }
1583#ifdef DEBUG_INIT
1584
1585 /***********************************************************************
1586  *  Function:   print_eth
1587  *
1588  *  Description:
1589  *              Print the contents of an ethernet packet header
1590  *              CANNOT BE CALLED FROM ISR
1591  *
1592  *  Algorithm:
1593  *            Print Destination, Src, and type of packet
1594  *
1595  ***********************************************************************/
1596
1597 /* static */ void print_hdr(unsigned char *add)
1598 {
1599     int i;
1600     short int length;
1601
1602     printf("Header Location %p\n", add);
1603
1604     printf ("Dest  ");
1605
1606     for (i = 0; i < 6; i++)
1607         printf(" %2.2X", add[i]);
1608
1609     printf ("\n");
1610
1611     printf ("Source");
1612
1613     for (i = 6; i < 12; i++)
1614         printf(" %2.2X", add[i]);
1615
1616     printf ("\n");
1617
1618     printf ("frame type %2.2X%2.2X\n", add[12], add[13]);
1619
1620
1621 }
1622 /***********************************************************************
1623  *  Function:   print_pkt
1624  *
1625  *  Description:
1626  *              Print the contents of an ethernet packet header
1627  *              CANNOT BE CALLED FROM ISR
1628  *
1629  *  Algorithm:
1630  *            Print Destination, Src, and type of packet
1631  *
1632  ***********************************************************************/
1633
1634 /* static */ void print_pkt(unsigned char *add)
1635 {
1636     int i;
1637     short int length;
1638
1639     printf("Data Location %p\n", add);
1640
1641     if ( add[0] == 0x08 && add[1] == 0x06 )
1642       { /* an ARP */
1643         printf("Hardware type : %2.2X%2.2X\n", add[14],add[15]);
1644         printf("Protocol type : %2.2X%2.2X\n", add[16],add[17]);
1645         printf("Hardware size : %2.2X\n", add[18]);
1646         printf("Protocol size : %2.2X\n", add[19]);
1647         printf("op            : %2.2X%2.2X\n", add[20],add[21]);
1648
1649         printf("Sender Enet addr: ");
1650
1651         for ( i=0; i< 5 ; i++)
1652           printf( "%x:", add[22 + i]);
1653
1654         printf("%x\n", add[27]);
1655
1656         printf("Sender IP addr: ");
1657         for ( i=0; i< 3 ; i++)
1658           printf( "%u.", add[28 + i]);
1659
1660         printf("%u\n", add[31]);
1661
1662         printf("Target Enet addr: ");
1663         for ( i=0; i< 5 ; i++)
1664           printf( "%x:", add[32 + i]);
1665         printf("%x\n", add[37]);
1666
1667         printf("Target IP addr: ");
1668
1669         for ( i=0; i< 3 ; i++)
1670           printf( "%u.", add[38 + i]);
1671         printf("%u\n", add[41]);
1672
1673        }
1674
1675     if ( add[0] == 0x08 && add[1] == 0x00 )
1676       { /* an IP packet */
1677         printf("*********************IP HEADER******************\n");
1678         printf("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15]);
1679         printf("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] )); 
1680         printf("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n",
1681                add[18],add[19], add[20], add[21]);
1682         printf("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n",
1683                add[22],add[23],add[24],add[25]);
1684         printf("IP packet type: %2.2X code %2.2X\n", add[34],add[35]);
1685
1686         printf("Source IP address: ");
1687         for ( i=0; i< 3 ; i++)
1688           printf( "%u.", add[26 + i]);
1689
1690         printf("%u\n", add[29]);
1691
1692         printf("Destination IP address: ");
1693         for ( i=0; i< 3 ; i++)
1694           printf( "%u.", add[30 + i]);
1695         printf("%u\n", add[33]);
1696
1697         printf("********************IP Packet Data*******************\n");
1698         length -=20;
1699         for ( i=0; i < length ; i++)
1700           printf("0x%2.2x ", add[34+i]);
1701         printf("\n");
1702
1703         printf("ICMP checksum: %2.2x %2.2x\n", add[36], add[37]);
1704         printf("ICMP identifier: %2.2x %2.2x\n", add[38], add[39]);
1705         printf("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41]);
1706        }
1707
1708
1709 }
1710 /***********************************************************************
1711  *  Function:   print_echo
1712  *
1713  *  Description:
1714  *              Print the contents of an ethernet packet header
1715  *              CANNOT BE CALLED FROM ISR
1716  *
1717  *  Algorithm:
1718  *            Prints only echo packets
1719  *
1720  ***********************************************************************/
1721
1722 /* static */ void print_echo(unsigned char *add)
1723 {
1724     int i;
1725     short int length;
1726
1727     if ( add[12] == 0x08 && add[13] == 0x00 ){ /* an IP packet */
1728       
1729       printf("Packet Location %p\n", add);
1730       
1731       printf ("Dest  ");
1732       
1733       for (i = 0; i < 6; i++)
1734         printf(" %2.2X", add[i]);
1735       
1736       printf ("\n");
1737       
1738       printf ("Source");
1739       
1740       for (i = 6; i < 12; i++)
1741         printf(" %2.2X", add[i]);
1742       
1743       printf ("\n");
1744       
1745       printf ("frame type %2.2X%2.2X\n", add[12], add[13]);
1746       
1747       printf("*********************IP HEADER******************\n");
1748       printf("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15]);
1749       printf("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] )); 
1750       printf("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n",
1751              add[18],add[19], add[20], add[21]);
1752       printf("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n",
1753              add[22],add[23],add[24],add[25]);
1754       printf("IP packet type: %2.2X code %2.2X\n", add[34],add[35]);
1755       
1756       printf("Source IP address: ");
1757       for ( i=0; i< 3 ; i++)
1758         printf( "%u.", add[26 + i]);
1759       
1760       printf("%u\n", add[29]);
1761       
1762       printf("Destination IP address: ");
1763       for ( i=0; i< 3 ; i++)
1764         printf( "%u.", add[30 + i]);
1765       printf("%u\n", add[33]);
1766       
1767       printf("********************IP Packet Data*******************\n");
1768       length -=20;
1769       for ( i=0; i < length ; i++)
1770         printf("0x%2.2x ", add[34+i]);
1771       printf("\n");
1772       
1773       printf("ICMP checksum: %2.2x %2.2x\n", add[36], add[37]);
1774       printf("ICMP identifier: %2.2x %2.2x\n", add[38], add[39]);
1775       printf("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41]);
1776     }   
1777 }
1778#endif
1779 
1780 /***********************************************************************
1781  *  Function:   uti596_attach
1782  *
1783  *  Description:
1784  *              User requested attach of driver to hardware
1785  *
1786  *  Algorithm:
1787  *
1788  *              Check that the board is present
1789  *              parse and store the command line parameters
1790  *                 argv[0]: interface label, e.g., "uti596"
1791  *                 argv[1]: maximum transmission unit, bytes, e.g., "1500"
1792  *                 argv[2]: IP address (optional)
1793  *              initialize required rx and tx buffers
1794  *              hook interrupt
1795  *              issue start command and some diagnostics
1796  *              return       
1797  *
1798  ***********************************************************************/
1799
1800
1801int uti596_attach(struct rtems_bsdnet_ifconfig * pConfig )
1802{
1803  struct uti596_softc *sc = &uti596_softc;          /* soft config */
1804  struct ifnet * ifp = &sc->arpcom.ac_if;
1805  int i = 0;
1806 
1807#ifdef DBG_ATTACH
1808  printf("attach");
1809#endif
1810
1811 
1812  sc->started = 0; /* The NIC is not started yet */
1813  sc->ioAddr = IO_ADDR;
1814
1815  /* Indicate to ULCS that this is initialized */ 
1816  ifp->if_softc = sc; 
1817 
1818  /* Assign the name */
1819  ifp->if_name = "uti";
1820 
1821  /* Assign the unit number */
1822  ifp->if_unit = 1;
1823 
1824  /* Assign mtu */
1825  if ( pConfig -> mtu )
1826    ifp->if_mtu = pConfig -> mtu;
1827  else
1828    ifp->if_mtu = ETHERMTU;
1829 
1830  /* Assign and possibly override the hw address */
1831
1832  if ( !pConfig->hardware_address) { /* Read the ethernet address from the board */
1833    for (i = 0; i < 8; i++)
1834      inport_byte(NIC_ADDR+i,sc->arpcom.ac_enaddr[i] );
1835  }
1836  else {
1837    /* hwaddr override */ 
1838    memcpy (sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN);
1839  }
1840 
1841  /* Test for valid hwaddr */
1842  if(memcmp(sc->arpcom.ac_enaddr,"\xAA\x55\x01",3)!= 0)/* b0 of byte 0 != 0 => multicast */
1843    return ENODEV;
1844 
1845  /* Assign requested receive buffer descriptor count */
1846  if (pConfig->rbuf_count)
1847    sc->rxBdCount = pConfig->rbuf_count;
1848  else
1849    sc->rxBdCount = RX_BUF_COUNT;
1850
1851  /* Assign requested tx buffer descriptor count */
1852  if (pConfig->xbuf_count)
1853    sc->txBdCount = pConfig->xbuf_count;
1854  else
1855    sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
1856
1857  /* ignore_broadcast is an unused feature... accept broadcast */
1858  /* sc->acceptBroadcast = !pConfig->ignore_broadcast; */
1859
1860  ifp->if_snd.ifq_maxlen = ifqmaxlen;
1861  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1862
1863  /* to init_hardware */
1864  sc->started = 1;
1865  sc->pInboundFrameQueue = I596_NULL;
1866 
1867 
1868  ifp->if_ioctl = uti596_ioctl;
1869  ifp->if_init  = uti596_init;
1870  ifp->if_start    = uti596_start;
1871  ifp->if_output   = ether_output;
1872 
1873  sc->scb.command = 0;
1874 
1875  /*
1876   * Attach the interface
1877   */
1878  if_attach (ifp);
1879  ether_ifattach (ifp);
1880  return 1;
1881
1882 }
1883 
1884
1885 /***********************************************************************
1886  *  Function:   uti596DynamicInterruptHandler
1887  *
1888  *  Description:
1889  *             This is the interrupt handler for the uti596 board
1890  *
1891  *  Algorithm:
1892  *
1893  ***********************************************************************/
1894
1895 /* static */ rtems_isr uti596DynamicInterruptHandler(rtems_vector_number irq)
1896 {
1897#ifdef DEBUG_ISR
1898 printk("I");
1899#endif
1900
1901 UTI_WAIT_COMMAND_ACCEPTED(20000, "****ERROR:on ISR entry");
1902
1903 scbStatus = uti596_softc.scb.status & 0xf000;
1904
1905 if ( scbStatus ){
1906   /* acknowledge interrupts */
1907   /*   printk("***INFO: ACK %x\n", scbStatus);*/
1908   uti596_softc.scb.command = scbStatus;
1909   outport_word(CHAN_ATTN, 0);
1910   
1911   if( uti596_softc.resetDone ) { 
1912     /* stack is attached */
1913     UTI_WAIT_COMMAND_ACCEPTED(20000, "****ERROR:ACK");
1914   }
1915   else {
1916     printk("\n***INFO:ISR won't process now\n");
1917     return;
1918   }
1919 }
1920 else {
1921   printk("\n***ERROR: Spurious interrupt. Resetting...\n");
1922   uti596_softc.nic_reset = 1;
1923 }
1924 
1925 if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) ){
1926   printk("\n*****ERROR: Command Complete, and CNA available: 0x%x\nResetting...", scbStatus);
1927   uti596_softc.nic_reset = 1;
1928   return;
1929 }
1930
1931 if ( !(scbStatus & SCB_STAT_CX) && (scbStatus & SCB_STAT_CNA) ) {
1932   printk("\n*****ERROR: CNA, NO CX:0x%x\nResetting...",scbStatus);
1933   uti596_softc.nic_reset = 1;
1934   return;
1935 }
1936
1937 if ( scbStatus & SCB_CUS_SUSPENDED ) {
1938   printk("\n*****ERROR: Command unit suspended!:0x%x\nResetting...",scbStatus);
1939   uti596_softc.nic_reset = 1;
1940   return;
1941 }
1942
1943 if ( scbStatus & RU_SUSPENDED  ) {
1944   printk("\n*****ERROR: Receive unit suspended!:0x%x\nResetting...",scbStatus);
1945   uti596_softc.nic_reset = 1;
1946   return;
1947 }
1948 
1949 if ( scbStatus & SCB_STAT_RNR ) {
1950   printk("\n*****WARNING: RNR %x\n",scbStatus);
1951 }
1952 
1953 /*
1954  * Receive Unit Control
1955  */
1956 if ( scbStatus & SCB_STAT_FR ) { /* a frame has been received */
1957   uti596_softc.rxInterrupts++;
1958   
1959#ifdef DBG_FR
1960   printk("\nISR:FR\n");
1961#endif
1962   if ( uti596_softc.pBeginRFA == I596_NULL ||  !( uti596_softc.pBeginRFA -> stat & STAT_C)){
1963     dump_scb();
1964     uti596_softc.nic_reset = 1;
1965   }
1966   else
1967     while ( uti596_softc.pBeginRFA != I596_NULL && 
1968             ( uti596_softc.pBeginRFA -> stat & STAT_C)) {
1969       
1970#ifdef DBG_ISR
1971       printk("ISR:pBeginRFA != NULL\n");
1972#endif
1973       count_rx ++;
1974       if ( count_rx > 1)
1975         printk("****WARNING: Received 2 frames on 1 interrupt \n");
1976
1977       /*
1978        * Give Received Frame to the ULCS
1979        */     
1980       uti596_softc.countRFD--;
1981       
1982       if ( uti596_softc.countRFD < 0 )
1983         printk("Count < 0 !!!: count == %d, beginRFA = %p\n",
1984                uti596_softc.countRFD, uti596_softc.pBeginRFA);
1985       
1986       uti596_softc.stats.rx_packets++;
1987       pIsrRfd = uti596_softc.pBeginRFA -> next; /* the append destroys the link */
1988       uti596append( &uti596_softc.pInboundFrameQueue , uti596_softc.pBeginRFA );
1989       
1990       /*
1991        * if we have just received the a frame int he last unknown RFD,
1992        * then it is certain that the RFA is empty.
1993        */
1994       if ( uti596_softc.pLastUnkRFD == uti596_softc.pBeginRFA ) {
1995         UTI_596_ASSERT(uti596_softc.pLastUnkRFD != I596_NULL,"****ERROR:LastUnk is NULL, begin ptr @ end!\n");
1996         uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD = I596_NULL;
1997       }
1998       
1999#ifdef DBG_ISR
2000       printk("Wake %#x\n",uti596_softc.rxDaemonTid);
2001#endif
2002       sc = rtems_event_send(uti596_softc.rxDaemonTid, INTERRUPT_EVENT);
2003       if ( sc != RTEMS_SUCCESSFUL )
2004         rtems_panic ("Can't notify rxDaemon: %s\n", 
2005                      rtems_status_text (sc)); 
2006#ifdef DBG_RAW_ISR
2007       else
2008         printk("Rx Wake: %#x\n",uti596_softc.rxDaemonTid);
2009#endif
2010       
2011       uti596_softc.pBeginRFA = pIsrRfd;
2012     } /* end while */
2013   
2014   if ( uti596_softc.pBeginRFA == I596_NULL ){ /* adjust the pEndRFA to reflect an empty list */
2015     if ( uti596_softc.pLastUnkRFD == I596_NULL && uti596_softc.countRFD != 0 )
2016       printk("Last Unk is NULL, BeginRFA is null, and count == %d\n",uti596_softc.countRFD);
2017     
2018     uti596_softc.pEndRFA = I596_NULL;
2019     if ( uti596_softc.countRFD != 0 ) {
2020       printk("****ERROR:Count is %d, but begin ptr is NULL\n",uti596_softc.countRFD );
2021       dumpQ();
2022     }
2023   }
2024   
2025 } /* end scb_stat_fr */
2026 
2027 /*
2028  * Check For Command Complete
2029  */
2030 if (  scbStatus & SCB_STAT_CX ){
2031#ifdef DBG_ISR
2032   printk("ISR:CU\n");
2033#endif   
2034   
2035   pIsrCmd = uti596_softc.pCmdHead;
2036   
2037   /*
2038    * For ALL completed commands
2039    */
2040   if ( pIsrCmd !=  I596_NULL && pIsrCmd->status & STAT_C  ){
2041     
2042#ifdef DBG_RAW_ISR
2043       printk("ISR:pIsrCmd != NULL\n");
2044#endif
2045     
2046     /*
2047      * Adjust the drivers command block list
2048      */
2049     uti596_softc.pCmdHead = pIsrCmd -> next;
2050     
2051     /*
2052      * If there are MORE commands to process,
2053      * the serialization in the raw routine has failed.
2054      * ( Perhaps AddCmd is bad? )
2055      */
2056     UTI_596_ASSERT(uti596_softc.pCmdHead == I596_NULL,
2057                    "****ERROR: command serialization failed\n");
2058     /*
2059      * What if the command did not complete OK?
2060      */
2061     switch ( pIsrCmd->command & 0x7)
2062       {
2063       case CmdConfigure:
2064
2065         /*      printk("****INFO:Configure OK\n"); */
2066         uti596_softc.cmdOk = 1;
2067         break;
2068         
2069       case CmdDump:
2070         
2071#ifdef DBG_ISR
2072           printk("dump!\n");
2073#endif
2074         uti596_softc.cmdOk = 1;
2075         break;
2076
2077       case CmdDiagnose:
2078         
2079#ifdef DBG_ISR
2080           printk("diagnose!\n");
2081#endif
2082         uti596_softc.cmdOk = 1;
2083         break;
2084         
2085       case CmdSASetup:
2086
2087         /*      printk("****INFO:Set address interrupt\n");     */
2088         if ( pIsrCmd -> status & STAT_OK )
2089           uti596_softc.cmdOk = 1;
2090         else
2091           printk("****ERROR:SET ADD FAILED\n");
2092         break;
2093         
2094       case CmdTx:
2095         {
2096           UTI_596_ASSERT(uti596_softc.txDaemonTid, "****ERROR:Null txDaemonTid\n");
2097#ifdef DBG_ISR
2098           printk("wake TX:0x%x\n",uti596_softc.txDaemonTid);
2099#endif
2100           if ( uti596_softc.txDaemonTid ){  /* Ensure that the transmitter is waiting */
2101             sc = rtems_event_send (uti596_softc.txDaemonTid, 
2102                                    INTERRUPT_EVENT);
2103
2104           if ( sc != RTEMS_SUCCESSFUL )
2105             printk("****ERROR:Could NOT send event to tid 0x%x : %s\n",
2106                    uti596_softc.txDaemonTid, rtems_status_text (sc) );
2107#ifdef DBG_RAW_ISR
2108           else
2109             printk("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid);
2110#endif     
2111           }
2112         } /* End case Cmd_Tx */
2113         break;
2114         
2115       case CmdMulticastList:
2116
2117         printk("***ERROR:Multicast?!\n");
2118         pIsrCmd->next = I596_NULL;
2119         break;
2120         
2121       case CmdTDR:
2122         {
2123           unsigned long status = *( (unsigned long *)pIsrCmd)+1;
2124           printk("****ERROR:TDR?!\n");
2125           
2126           if (status & STAT_C)
2127             {
2128               /*
2129                * mark the TDR command successful
2130                */
2131               uti596_softc.cmdOk = 1;
2132             }
2133           else
2134             {
2135               if (status & 0x4000)
2136                 printk("****WARNING:Transceiver problem.\n");
2137               if (status & 0x2000)
2138                 printk("****WARNING:Termination problem.\n");
2139               if (status & 0x1000)
2140                 printk("****WARNING:Short circuit.\n");
2141               
2142               /*              printk("****INFO:Time %ld.\n", status & 0x07ff); */
2143             }
2144         }
2145         break;
2146         
2147       default: 
2148         /*
2149          * This should never be reached
2150          */
2151         printk("CX but NO known command\n");
2152       } /* end switch */
2153     pIsrCmd = uti596_softc.pCmdHead; /* next command */ 
2154     if ( pIsrCmd != I596_NULL )
2155       printk("****WARNING: more commands in list, but no start to NIC\n");
2156   } /* end if pIsrCmd != NULL && pIsrCmd->stat & STAT_C  */
2157   else {
2158
2159     /* Reset the ethernet card, and wake the transmitter (if necessary) */
2160
2161     printk("****INFO: Resetting board ( tx )\n");
2162     uti596_softc.nic_reset = 1;
2163     if ( uti596_softc.txDaemonTid){  /* Ensure that a transmitter is waiting */
2164       /*  printk("*****INFO:Wake Transmitter\n"); */
2165       sc = rtems_event_send (uti596_softc.txDaemonTid, 
2166                              INTERRUPT_EVENT);
2167       
2168       if ( sc != RTEMS_SUCCESSFUL )
2169         printk("****ERROR:Could NOT send event to tid 0x%x : %s\n",uti596_softc.txDaemonTid, rtems_status_text (sc) );
2170#ifdef DBG_RAW_ISR
2171       else
2172         printk("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid);
2173#endif     
2174     }
2175   } 
2176 }  /* end if command complete */   
2177 
2178 
2179 /* if the receiver has stopped,
2180  * check if this is a No Resources scenario,
2181  * Try to add more RFD's ( no RBDs are used )
2182  */
2183 if ( uti596_softc.started ) {
2184   if ( scbStatus & SCB_STAT_RNR ){
2185#ifdef DBG_ISR
2186     printk("INFO:RNR: status %#x \n", uti596_softc.scb.status );
2187#endif
2188     /*
2189      * THE RECEIVER IS OFF!
2190      */
2191     if ( uti596_softc.pLastUnkRFD != I596_NULL  ){ /* We have an unknown RFD, it is not inbound*/ 
2192       if ( uti596_softc.pLastUnkRFD -> stat & (STAT_C | STAT_B )) /* in use */
2193         uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD;      /* update end */
2194       else {     
2195         /*
2196          *  It is NOT in use, and since RNR, we know EL bit of pEndRFA was read!
2197          *  So, unlink it from the RFA and move it to the saved queue.
2198          *  But pBegin can equal LastUnk!
2199          */
2200       
2201           if ( uti596_softc.pEndRFA != I596_NULL ){      /* check added feb24. */
2202#ifdef DEBUG_RFA
2203             if (uti596_softc.pEndRFA -> next != uti596_softc.pLastUnkRFD){
2204               printk("***ERROR:UNK: %p not end->next: %p, end: %p\n",
2205                      uti596_softc.pLastUnkRFD,uti596_softc.pEndRFA -> next,uti596_softc.pEndRFA);
2206               dumpQ();
2207               printk("***INFO:countRFD now %d\n",       uti596_softc.countRFD);
2208               printk("\n\n");
2209
2210             }
2211#endif
2212             uti596_softc.pEndRFA -> next = I596_NULL;   /* added feb 16 */
2213           }
2214         uti596append( &uti596_softc.pSavedRfdQueue, uti596_softc.pLastUnkRFD );
2215         uti596_softc.savedCount++;
2216         uti596_softc.pEndSavedQueue = uti596_softc.pLastUnkRFD;
2217         uti596_softc.countRFD--;                    /* It was not in the RFA */
2218         /*
2219          * The Begin pointer CAN advance this far. We must resynch the CPU side
2220          * with the chip.
2221          */
2222         if ( uti596_softc.pBeginRFA == uti596_softc.pLastUnkRFD ) {
2223#ifdef DEBUG_RFA
2224           if ( uti596_softc.countRFD != 0 ) {
2225             printk("****INFO:About to set begin to NULL, with count == %d\n", uti596_softc.countRFD );
2226             dumpQ();
2227             printk("\n\n");
2228           }
2229#endif
2230           uti596_softc.pBeginRFA = I596_NULL;
2231           UTI_596_ASSERT(uti596_softc.countRFD == 0,"****ERROR:Count must be zero here!\n");
2232         }
2233       }
2234
2235       uti596_softc.pLastUnkRFD = I596_NULL;
2236 
2237     } /* end if exists UnkRFD */
2238
2239     /*
2240      * Append the saved queue to  the RFA. 
2241      * Any further RFD's being supplied will be added to
2242      * this new list.
2243      */
2244     if ( uti596_softc.pSavedRfdQueue != I596_NULL ) { /* entries to add */
2245       if ( uti596_softc.pBeginRFA == I596_NULL ) {    /* add at beginning to list */
2246#ifdef DEBUG_RFA
2247         if(uti596_softc.countRFD != 0) {
2248           printk("****ERROR:Begin pointer is NULL, but count == %d\n",uti596_softc.countRFD);
2249           dumpQ();
2250         }
2251#endif
2252         uti596_softc.pBeginRFA      = uti596_softc.pSavedRfdQueue; 
2253         uti596_softc.pEndRFA        = uti596_softc.pEndSavedQueue;
2254         uti596_softc.pSavedRfdQueue = uti596_softc.pEndSavedQueue = I596_NULL;  /* Reset the End */
2255       }
2256       else { 
2257#ifdef DEBUG_RFA
2258         if ( uti596_softc.countRFD <= 0) {
2259           printk("****ERROR:Begin pointer is not NULL, but count == %d\n",uti596_softc.countRFD);
2260           dumpQ();
2261         }
2262#endif
2263         UTI_596_ASSERT( uti596_softc.pEndRFA != I596_NULL, "****WARNING: END RFA IS NULL\n");
2264         UTI_596_ASSERT( uti596_softc.pEndRFA->next == I596_NULL, "****ERROR:END RFA -> next must be NULL\n");
2265         
2266         uti596_softc.pEndRFA->next   = uti596_softc.pSavedRfdQueue; 
2267         uti596_softc.pEndRFA->cmd   &= ~CMD_EOL;      /* clear the end of list */ 
2268         uti596_softc.pEndRFA         = uti596_softc.pEndSavedQueue;
2269         uti596_softc.pSavedRfdQueue  = uti596_softc.pEndSavedQueue = I596_NULL; /* Reset the End */
2270#ifdef DEBUG_ISR
2271         printk("count: %d, saved: %d \n", uti596_softc.countRFD , uti596_softc.savedCount);
2272#endif
2273 
2274       }
2275       /*       printk("Isr: countRFD = %d\n",uti596_softc.countRFD); */
2276       uti596_softc.countRFD += uti596_softc.savedCount;
2277       /* printk("Isr: after countRFD = %d\n",uti596_softc.countRFD); */
2278       uti596_softc.savedCount = 0;
2279     }
2280
2281 
2282#ifdef DBG_596_RFD
2283     printk("The list starts here %p\n",uti596_softc.pBeginRFA );
2284#endif
2285     
2286     if ( uti596_softc.countRFD > 1 &&                              /* there is at least TWO */
2287          !( uti596_softc.pBeginRFA -> stat & (STAT_C | STAT_B ))) { /* restart when not in use !! */
2288       
2289       UTI_596_ASSERT(uti596_softc.scb.command == 0, "****ERROR:scb command must be zero\n");
2290       uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;
2291       /* start RX here  */
2292       printk("****INFO: ISR Starting receiver\n"); 
2293       uti596_softc.scb.command = RX_START; /* should this also be CU start? */
2294       outport_word(CHAN_ATTN, 0);
2295    }
2296     else {
2297       printk("****WARNING: Receiver NOT Started -- countRFD = %d\n", uti596_softc.countRFD);
2298       printk("82596 cmd: 0x%x, status: 0x%x RFA len: %d\n",
2299              uti596_softc.scb.command, 
2300              uti596_softc.scb.status,
2301              uti596_softc.countRFD);
2302       
2303       printk("\nRFA: \n");
2304       for ( pISR_Rfd = uti596_softc.pBeginRFA;
2305             pISR_Rfd != I596_NULL;
2306             pISR_Rfd = pISR_Rfd->next) 
2307         printk("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2308                pISR_Rfd, pISR_Rfd->stat, pISR_Rfd->cmd);
2309       
2310       printk("\nInbound: \n");
2311       for ( pISR_Rfd = uti596_softc.pInboundFrameQueue;
2312             pISR_Rfd != I596_NULL;
2313             pISR_Rfd = pISR_Rfd->next) 
2314         printk("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2315                pISR_Rfd, pISR_Rfd->stat, pISR_Rfd->cmd);
2316       
2317       
2318       printk("\nSaved: \n");
2319       for ( pISR_Rfd = uti596_softc.pSavedRfdQueue;
2320             pISR_Rfd != I596_NULL;
2321             pISR_Rfd = pISR_Rfd->next) 
2322         printk("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2323                pISR_Rfd, pISR_Rfd->stat, pISR_Rfd->cmd);
2324       printk("\nUnknown: %p\n",uti596_softc.pLastUnkRFD);
2325     }
2326   } /* end stat_rnr */ 
2327
2328 } /* end if receiver started */
2329 UTI_596_ASSERT(uti596_softc.scb.status == scbStatus, "****WARNING:scbStatus change!\n");
2330 
2331#ifdef DBG_ISR
2332   printk("X\n");
2333#endif
2334 count_rx=0;
2335
2336 /*
2337  * Do this last, to ensure that the reset is called at the right time.
2338  */
2339 if ( uti596_softc.nic_reset ){
2340   uti596_softc.nic_reset = 0;
2341   sc = rtems_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT);
2342   if ( sc != RTEMS_SUCCESSFUL )
2343     rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc));
2344 }
2345
2346 return;
2347 }
2348
2349
2350/***********************************************************************
2351 *  Function:   void uti596dequeue
2352 *
2353 *  Description:
2354 *              removes an RFD from the received frame queue,
2355 *
2356 *  Algorithm:
2357 *
2358 ***********************************************************************/
2359
2360struct i596_rfd * uti596dequeue( struct i596_rfd ** ppQ )
2361 {
2362   ISR_Level level;
2363
2364   struct i596_rfd * pRfd;
2365   _ISR_Disable(level);
2366   
2367   /* invalid address, or empty queue or emptied queue */
2368   if( ppQ == NULL || *ppQ == NULL || *ppQ == I596_NULL) {
2369     _ISR_Enable(level);
2370     return I596_NULL;
2371   }
2372   
2373     pRfd = *ppQ;            /* The dequeued buffer           */
2374     *ppQ = pRfd->next;      /* advance the queue pointer     */
2375     pRfd->next = I596_NULL; /* unlink the rfd being returned */
2376
2377
2378   _ISR_Enable(level);
2379   return pRfd;
2380}       
2381
2382/***********************************************************************
2383 *  Function:   void uti596append
2384 *
2385 *  Description:
2386 *              adds an RFD to the end of the received frame queue,
2387 *              for processing by the rxproc.
2388 *              Also removes this RFD from the RFA
2389 *
2390 *  Algorithm:
2391 *
2392 ***********************************************************************/
2393
2394void uti596append( struct i596_rfd ** ppQ , struct i596_rfd * pRfd ) 
2395{
2396
2397  struct i596_rfd *p;
2398
2399  if ( pRfd != NULL && pRfd != I596_NULL) {
2400    pRfd -> next = I596_NULL;
2401    pRfd -> cmd |= CMD_EOL;    /* set EL bit */
2402   
2403    if ( *ppQ == NULL || *ppQ == I596_NULL ) {
2404      /* Empty or emptied */
2405      *ppQ = pRfd;
2406    }
2407    else
2408      {
2409        for ( p=*ppQ; p -> next != I596_NULL; p=p->next)
2410          ;
2411       
2412        p->cmd &= ~CMD_EOL; /* Clear EL bit at end */
2413        p->next = pRfd;
2414      }
2415  }
2416  else
2417    printf("Illegal attempt to append: %p\n", pRfd);
2418}
2419
2420
2421/***********************************************************************
2422 *  Function:   uti596stop
2423 *
2424 *  Description:
2425 *             stop the driver
2426 *
2427 *  Algorithm:
2428 *             mark driver as not started,
2429 *             mark transmitter as busy
2430 *             abort any transmissions/receptions
2431 *             clean-up all buffers ( RFD's et. al. )
2432 *             
2433 *             
2434 *
2435 *
2436 ***********************************************************************/
2437
2438
2439/* static */ 
2440void uti596_stop(struct uti596_softc *sc)
2441{
2442    sc->started  = 0;
2443
2444#ifdef DBG_596
2445        printf("%s: Shutting down ethercard, status was %4.4x.\n",
2446               uti596_softc.pIface->name, uti596_softc.scb.status);
2447#endif
2448
2449    printf("Stopping interface\n");
2450    sc->scb.command = CUC_ABORT|RX_ABORT;
2451    outport_word( CHAN_ATTN, 0 );
2452
2453   
2454}
2455
2456
2457static int
2458uti596_ioctl (struct ifnet *ifp, int command, caddr_t data)
2459{
2460        struct uti596_softc *sc = ifp->if_softc;
2461        int error = 0;
2462
2463        switch (command) {
2464        case SIOCGIFADDR:
2465        case SIOCSIFADDR:
2466                printk("SIOCSIFADDR\n");
2467                ether_ioctl (ifp, command, data);
2468                break;
2469
2470        case SIOCSIFFLAGS:
2471                printk("SIOCSIFFLAGS\n");
2472                switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
2473                case IFF_RUNNING:
2474                printk("IFF_RUNNING\n");
2475                        uti596_stop (sc);
2476                        break;
2477
2478                case IFF_UP:
2479                printk("IFF_UP\n");
2480                        uti596_init (sc);
2481                        break;
2482
2483                case IFF_UP | IFF_RUNNING:
2484                printk("IFF_UP and RUNNING\n");
2485                        uti596_stop (sc);
2486                        uti596_init (sc);
2487                        break;
2488
2489                default:
2490                printk("default\n");
2491
2492                        break;
2493                }
2494                break;
2495
2496        case SIO_RTEMS_SHOW_STATS:
2497                printk("show stats\n");
2498                uti596_stats (sc);
2499                break;
2500               
2501        /*
2502         * FIXME: All sorts of multicast commands need to be added here!
2503         */
2504        default:
2505                printk("default: EINVAL\n");
2506                error = EINVAL;
2507                break;
2508        }
2509        return error;
2510}
2511
2512
2513/***********************************************************************
2514 *  Function:   uti596_stats
2515 *
2516 *  Description:
2517 *             print out the collected data
2518 *
2519 *  Algorithm:
2520 *            use printf
2521 *
2522 ***********************************************************************/
2523
2524
2525void 
2526uti596_stats(struct uti596_softc *sc)
2527      {
2528        printf(" CPU Reports:\n");
2529        printf ("Tx raw send count:%-8lu",  sc->rawsndcnt);
2530        printf ("Rx Interrupts:%-8lu",  sc->rxInterrupts);
2531        printf ("Tx Interrupts:%-8lu\n",  sc->txInterrupts);
2532        printf ("Rx Packets:%-8u",  sc->stats.rx_packets);
2533        printf ("Tx Attempts:%-u\n",  sc->stats.tx_packets);
2534       
2535        printf ("Rx Dropped:%-8u",     sc->stats.rx_dropped);
2536        printf ("Rx IP Packets:%-8u",  sc->stats.rx_packets);
2537        printf ("Tx Errors:%-8u\n",      sc->stats.tx_errors);
2538        printf ("Tx aborted:%-8u",     sc->stats.tx_aborted_errors);
2539        printf ("Tx Dropped:%-8u\n",     sc->stats.tx_dropped);
2540        printf ("Tx IP packets:%-8u",  sc->stats.tx_packets);
2541       
2542        printf ("Collisions Detected:%-8u\n",  sc->stats.collisions);
2543        printf ("Tx Heartbeat Errors:%-8u",  sc->stats.tx_heartbeat_errors);
2544        printf ("Tx Carrier Errors:%-8u\n",    sc->stats.tx_carrier_errors);
2545        printf ("Tx Aborted Errors:%-8u",    sc->stats.tx_aborted_errors);
2546        printf ("Rx Length Errors:%-8u\n",     sc->stats.rx_length_errors);
2547        printf ("Rx Overrun Errors:%-8u",    sc->stats.rx_over_errors);
2548        printf ("Rx Fifo Errors:%-8u\n",       sc->stats.rx_fifo_errors);
2549        printf ("Rx Framing Errors:%-8u",    sc->stats.rx_frame_errors);
2550        printf ("Rx crc errors:%-8u\n",        sc->stats.rx_crc_errors);
2551
2552        printf ("TX WAITS: %-8lu\n", sc->txRawWait);
2553
2554        printf ("NIC resets: %-8u\n", sc->stats.nic_reset_count);
2555
2556        printf("NIC reports\n");
2557
2558        dump_scb();
2559      }
2560
2561void dumpQ(void) {
2562
2563  struct i596_rfd *pRfd;
2564
2565           printf("savedQ:\n");
2566           for( pRfd = uti596_softc.pSavedRfdQueue;
2567                pRfd != I596_NULL;
2568                pRfd = pRfd -> next) 
2569             printf("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd);
2570           printf("Inbound:\n");
2571           for( pRfd = uti596_softc.pInboundFrameQueue;
2572                pRfd != I596_NULL;
2573                pRfd = pRfd -> next) 
2574             printf("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd);
2575            printf("Last Unk: %p\n", uti596_softc.pLastUnkRFD );
2576         
2577           printf("RFA:\n");
2578           for( pRfd = uti596_softc.pBeginRFA;
2579                pRfd != I596_NULL;
2580                pRfd = pRfd -> next) 
2581             printf("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd);
2582}
2583
2584void uti596Diagnose(int verbose){
2585  struct i596_cmd diagnose;
2586  int count=10000;
2587
2588  diagnose.command = CmdDiagnose;
2589  diagnose.status = 0;
2590  uti596addPolledCmd(&diagnose);
2591  while( !( diagnose.status & STAT_C ) && count ) {
2592    if(verbose)
2593      printf(".");
2594    count --;
2595  }
2596  if(verbose)
2597    printf("Status diagnostic: 0x%2.2x\n", diagnose.status);
2598
2599}
2600void show_buffers (void) 
2601{
2602    struct i596_rfd *pRfd;
2603
2604      printf("82596 cmd: 0x%x, status: 0x%x RFA len: %d\n",
2605             uti596_softc.scb.command, 
2606             uti596_softc.scb.status,
2607             uti596_softc.countRFD);
2608 
2609      printf("\nRFA: \n");
2610      for ( pRfd = uti596_softc.pBeginRFA;
2611            pRfd != I596_NULL;
2612            pRfd = pRfd->next) 
2613        printf("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2614               pRfd, pRfd->stat, pRfd->cmd);
2615     
2616      printf("\nInbound: \n");
2617      for ( pRfd = uti596_softc.pInboundFrameQueue;
2618            pRfd != I596_NULL;
2619            pRfd = pRfd->next) 
2620        printf("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2621               pRfd, pRfd->stat, pRfd->cmd);
2622     
2623
2624      printf("\nSaved: \n");
2625      for ( pRfd = uti596_softc.pSavedRfdQueue;
2626            pRfd != I596_NULL;
2627            pRfd = pRfd->next) 
2628        printf("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2629               pRfd, pRfd->stat, pRfd->cmd);
2630    printf("\nUnknown: %p\n",uti596_softc.pLastUnkRFD);
2631
2632}
2633void show_queues(void)
2634{
2635    struct i596_rfd *pRfd;
2636
2637
2638      printf("CMD: 0x%x, Status: 0x%x\n", 
2639             uti596_softc.scb.command,
2640             uti596_softc.scb.status);
2641      printf("saved Q\n");
2642     
2643      for ( pRfd = uti596_softc.pSavedRfdQueue;
2644            pRfd != I596_NULL &&
2645              pRfd != NULL;
2646            pRfd = pRfd->next)
2647        printf("0x%p\n", pRfd);
2648     
2649      printf("End saved Q 0x%p\n", uti596_softc.pEndSavedQueue);
2650     
2651      printf("\nRFA:\n");
2652      for ( pRfd = uti596_softc.pBeginRFA;
2653            pRfd != I596_NULL &&
2654              pRfd != NULL;
2655            pRfd = pRfd->next)
2656        printf("0x%p\n", pRfd);
2657     
2658      printf("uti596_softc.pEndRFA: %p\n",uti596_softc.pEndRFA);
2659}
2660
2661
2662void uti596_init(void * arg){
2663
2664  struct uti596_softc  *sc = arg;
2665  struct ifnet *ifp = &sc->arpcom.ac_if;
2666
2667  if (sc->txDaemonTid == 0) {
2668
2669    uti596_initialize_hardware(sc);
2670
2671    /*
2672     * Start driver tasks
2673     */
2674
2675    sc->txDaemonTid = rtems_bsdnet_newproc ("UTtx", 2*4096, uti596_txDaemon, sc);
2676    sc->rxDaemonTid = rtems_bsdnet_newproc ("UTrx", 2*4096, uti596_rxDaemon, sc);
2677    sc->resetDaemonTid = rtems_bsdnet_newproc ("UTrt", 2*4096, 
2678                                               uti596_resetDaemon, sc);
2679  }
2680  /*
2681   * Enable receiver
2682   */
2683  sc->scb.pRfd = sc -> pBeginRFA;
2684  sc->scb.command = RX_START;
2685  outport_word(CHAN_ATTN,0 ); 
2686  UTI_WAIT_COMMAND_ACCEPTED(4000, "init:RX_START"); 
2687  /*
2688   * Tell the world that we're running.
2689   */
2690  ifp->if_flags |= IFF_RUNNING;
2691 
2692}
2693void dump_scb(){
2694  printk("status 0x%x\n",uti596_softc.scb.status);
2695  printk("command 0x%x\n",uti596_softc.scb.command);
2696  printk("cmd 0x%x\n",(int)uti596_softc.scb.pCmd);
2697  printk("rfd 0x%x\n",(int)uti596_softc.scb.pRfd); 
2698  printk("crc_err 0x%x\n",uti596_softc.scb.crc_err);
2699  printk("align_err 0x%x\n",uti596_softc.scb.align_err);
2700  printk("resource_err 0x%x\n",uti596_softc.scb.resource_err );
2701  printk("over_err 0x%x\n",uti596_softc.scb.over_err);
2702  printk("rcvdt_err 0x%x\n",uti596_softc.scb.rcvdt_err);
2703  printk("short_err 0x%x\n",uti596_softc.scb.short_err);
2704  printk("t_on 0x%x\n",uti596_softc.scb.t_on);
2705  printk("t_off 0x%x\n",uti596_softc.scb.t_off);
2706}
2707
Note: See TracBrowser for help on using the repository browser.