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

4.104.114.84.95
Last change on this file since 20ad9e9d was 20ad9e9d, checked in by Joel Sherrill <joel.sherrill@…>, on 11/23/98 at 14:28:09

New network driver from Erik Ivanenko <erik.ivanenko@…>.

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