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

Last change on this file since ce70a16 was ce70a16, checked in by cvs2git <rtems-devel@…>, on 04/05/00 at 13:27:53

This commit was manufactured by cvs2svn to create branch 'rtems-4-5-branch'.

Cherrypick from master 2000-04-05 13:27:52 UTC Joel Sherrill <joel.sherrill@…> 'New file. Copied from i386ex BSP as missing from submission.':

c/src/lib/libbsp/m68k/mvme167/network/Makefile.am
c/src/lib/libbsp/m68k/mvme167/network/netexterns.h
c/src/lib/libbsp/m68k/mvme167/network/network.c
c/src/lib/libbsp/m68k/mvme167/network/uti596.h
make/custom/Cygwin-posix.cfg

  • 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.