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

4.104.114.84.95
Last change on this file since 9d81380 was 9d81380, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 1, 1999 at 11:50:22 PM

Updated Ethernet driver from Erik Ivanenko <erik.ivanenko@…>.
Comments follow:

Please find attached, the updated network driver. I have verified
that it is working as expected, by timestamping the error messages
generated from the ISR.

If you've taken a look inside, the network driver has a reset thread
in addition to the RX and TX threads. It is possible to avoid the
additional reset thread by allowing the TX driver to time out and then
checking status bits set by the ISR. However, this approach demands
that a transmission is necessary for the NIC to be reset.

Due to Eric V's ISR handling, I suppose that the reset routine could
be called from the "ISR" itself, due to the 8259 interrupt mode, and
that the interrupt is acknowledged prior to running the "ISR".
(Providing that no NIC interrupts are generated during reset -- I
worry about re-entrancy. )

This would be a minor improvement, but you know, I don't want to make
this driver my lifes work.



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