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

4.104.114.84.95
Last change on this file since 8ef3818 was 8ef3818, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/00 at 19:57:02

Patch from John Cotton <john.cotton@…>, Charles-Antoine Gauthier
<charles.gauthier@…>, and Darlene A. Stewart
<Darlene.Stewart@…> to add support for a number of very
significant things:

+ BSPs for many variations on the Motorola MBX8xx board series
+ Cache Manager including initial support for m68040

and PowerPC

+ Rework of mpc8xx libcpu code so all mpc8xx CPUs now use

same code base.

+ Rework of eth_comm BSP to utiltize above.

John reports this works on the 821 and 860

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