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

4.104.114.84.95
Last change on this file since db9ae70 was db9ae70, checked in by Joel Sherrill <joel.sherrill@…>, on Jul 26, 2000 at 9:15:27 PM

Patch from Charles-Antoine Gauthier <charles.gauthier@…> that
removes warnings from the network.c file and has slight additions
to the configuration file to support Java.

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