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

4.104.114.84.95
Last change on this file since 0905e0f was e453d5c, checked in by Joel Sherrill <joel.sherrill@…>, on 09/12/00 at 12:37:19

2000-09-12 Joel Sherrill <joel@…>

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