source: rtems/c/src/lib/libbsp/m68k/mvme167/network/network.c @ 5a23ca84

4.104.114.84.95
Last change on this file since 5a23ca84 was 5a23ca84, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 5, 2000 at 1:01:21 PM

New files from John Cotton <John.Cotton@…> and Charles-Antoine
Gauthier <charles.gauthier@…>. The power supply in their
VMEbus cage died so it was submitted at this point. It passes ttcp
which is a really good sign but they would like to do more testing
and cleanup once their hardware is functional again. Please
contact them if you are interested in using or fixing this driver.
As their comments indicate, the performance is actually quite good
even at this point as indicated by the ttcp results.

Please note that this is by no means a final version. The code is still
fairly ugly, and will require some further fixing. On the bright side, what
is attached works. I finally ran the test programs successfully with
optimized code and data cache enabled:

netdemos worked, but failed on the UDP transfer (runs out of buffers).

ttcp worked, with something like 1036 KB/sec Rx, 952 KB/sec Tx.

tftp worked

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