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

4.104.114.84.95
Last change on this file since ed09fd77 was ed09fd77, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 11, 2000 at 7:26:31 PM

2000-08-11 Charles-Antoine Gauthier <charles.gauthier@…>

  • README: Updated
  • console/console.c: Fix polled input. Add support for shared printk. Add support for more flexible polled I/O with and without termios. I/O mode and console is selectable either from NVRAM or from mvme167.cfg. Clean up comments.

2000-08-11 Charles-Antoine Gauthier <charles.gauthier@…>

  • startup/page_table.c (page_table_init): Reorganize NVRAM parameters.
  • include/bsp.h: Reorganize NVRAM parameters. Add support for shared printk.
  • times: These are the times for the MVME167, not the MBX860-002.

2000-08-11 John Cotton <john.cotton@…>

  • network/network.c: Fix NVRAM configuration parameter handling from previous revision. Check J1-4, restructure NVRAM parameter handling.

2000-08-11 Charles-Antoine Gauthier <charles.gauthier@…>

  • network/network.c: Cleanup of network driver to reduce warnings. Addition of second parameter to uti596_attach.
  • 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 ( !(j1 & 0x10) ) {
1705        /* Jumper J1-4 is on, configure from NVRAM */
1706 
1707    if ( (addr = nvram->ipaddr) ) {
1708      /* We have a non-zero entry, copy the value */
1709      if ( (pAddr = malloc ( INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT )) )
1710        pConfig->ip_address = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1 );
1711      else
1712        rtems_panic("Can't allocate ip_address buffer!\n");
1713    }
1714   
1715    if ( (addr = nvram->netmask) ) {
1716      /* We have a non-zero entry, copy the value */
1717      if ( (pAddr = malloc ( INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT )) )
1718        pConfig->ip_netmask = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1 );
1719      else
1720        rtems_panic("Can't allocate ip_netmask buffer!\n");
1721    }
1722
1723    /* Ethernet address requires special handling -- it must be copied into
1724     * the arpcom struct. The following if construct serves only to give the
1725     * NVRAM parameter the highest priority if J1-4 indicates we are configuring
1726     * from NVRAM.
1727     *
1728     * If the ethernet address is specified in NVRAM, go ahead and copy it.
1729     * (ETHER_ADDR_LEN = 6 bytes).
1730     */
1731    if ( nvram->enaddr[0] || nvram->enaddr[1] || nvram->enaddr[2] ) {
1732      /* Anything in the first three bytes indicates a non-zero entry, copy value */
1733          memcpy ((void *)sc->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN);
1734    }
1735    else if ( pConfig->hardware_address) {
1736      /* There is no entry in NVRAM, but there is in the ifconfig struct, so use it. */
1737      memcpy ((void *)sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN);
1738    }
1739    else {
1740      /* There is no ethernet address provided, so it will be read
1741       * from BBRAM at $FFFC1F2C by default. [mvme167 manual p. 1-47]
1742       */
1743      memcpy ((void *)sc->arpcom.ac_enaddr, (char *)0xFFFC1F2C, ETHER_ADDR_LEN);
1744    }
1745  }
1746  else if ( pConfig->hardware_address) {
1747    /* We are not configuring from NVRAM (J1-4 is off), and the ethernet address
1748     * is given in the ifconfig structure. Copy it.
1749     */
1750    memcpy ((void *)sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN);
1751  }
1752  else {
1753    /* We are not configuring from NVRAM (J1-4 is off), and there is no ethernet
1754     * address provided in the ifconfig struct, so it will be read from BBRAM at
1755     * $FFFC1F2C by default. [mvme167 manual p. 1-47]
1756     */
1757    memcpy ((void *)sc->arpcom.ac_enaddr, (char *)0xFFFC1F2C, ETHER_ADDR_LEN);
1758  }
1759
1760  /* Possibly override default acceptance of broadcast packets */
1761  if (pConfig->ignore_broadcast)
1762        uti596initSetup[8] |= 0x02;
1763
1764  /* Assign requested receive buffer descriptor count */
1765  if (pConfig->rbuf_count)
1766    sc->rxBdCount = pConfig->rbuf_count;
1767  else
1768    sc->rxBdCount = RX_BUF_COUNT;
1769
1770  /* Assign requested tx buffer descriptor count */
1771  if (pConfig->xbuf_count)
1772    sc->txBdCount = pConfig->xbuf_count;
1773  else
1774    sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
1775
1776  /* Set up fields in the ifnet structure*/
1777  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1778  ifp->if_snd.ifq_maxlen = ifqmaxlen;
1779  ifp->if_init = uti596_init;
1780  ifp->if_ioctl = uti596_ioctl;
1781  ifp->if_start = uti596_start;
1782  ifp->if_output = ether_output;
1783
1784  /* uti596_softc housekeeping */
1785  sc->started = 1;
1786  sc->pInboundFrameQueue = I596_NULL;
1787  sc->scb.command = 0;
1788
1789  /*
1790   * Attach the interface
1791   */
1792  if_attach (ifp);
1793  ether_ifattach (ifp);
1794  return 1;
1795}
1796
1797/***********************************************************************
1798 *  Function:  uti596_start
1799 *
1800 *  Description:
1801 *             start the driver
1802 *
1803 *  Algorithm:
1804 *             send an event to the tx task
1805 *             set the if_flags
1806 *
1807 ***********************************************************************/
1808static void uti596_start(
1809  struct ifnet *ifp
1810)
1811{
1812  uti596_softc_ *sc = ifp->if_softc;
1813 
1814        #ifdef DBG_START
1815  printk(("uti596_start: begins\n"))
1816        #endif
1817       
1818  rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
1819  ifp->if_flags |= IFF_OACTIVE;
1820}
1821
1822/***********************************************************************
1823 *  Function:  uti596_init
1824 *
1825 *  Description:
1826 *             driver initialization
1827 *
1828 *  Algorithm:
1829 *             initialize the 82596
1830 *             start driver tx and rx tasks, and reset task
1831 *             send the RX_START command the the RU
1832 *             set if_flags
1833 *
1834 *
1835 ***********************************************************************/
1836void uti596_init(
1837  void * arg
1838)
1839{
1840  uti596_softc_ *sc = arg;
1841  struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if;
1842
1843  if (sc->txDaemonTid == 0) {
1844
1845    /*
1846     * Initialize the 82596
1847     */
1848    #ifdef DBG_INIT
1849    printk(("uti596_init: begins\nuti596_init: initializing the 82596...\n"))
1850    #endif
1851    uti596_initialize_hardware(sc);
1852
1853    /*
1854     * Start driver tasks
1855     */
1856    #ifdef DBG_INIT
1857    printk(("uti596_init: starting driver tasks...\n"))
1858    #endif
1859    sc->txDaemonTid = rtems_bsdnet_newproc ("UTtx", 2*4096, uti596_txDaemon, (void *)sc);
1860    sc->rxDaemonTid = rtems_bsdnet_newproc ("UTrx", 2*4096, uti596_rxDaemon, (void *)sc);
1861    sc->resetDaemonTid = rtems_bsdnet_newproc ("UTrt", 2*4096, uti596_resetDaemon, (void *)sc);
1862
1863    #ifdef DBG_INIT
1864    printk(("uti596_init: After attach, status of board = 0x%x\n", sc->scb.status ))
1865    #endif
1866  }
1867
1868  /*
1869   * Enable receiver
1870   */
1871  #ifdef DBG_INIT
1872  printk(("uti596_init: enabling the reciever...\n" ))
1873  #endif
1874  sc->scb.command = RX_START;
1875  uti596_issueCA ( sc, UTI596_WAIT_FOR_CU_ACCEPT );
1876 
1877  /*
1878   * Tell the world that we're running.
1879   */
1880  ifp->if_flags |= IFF_RUNNING;
1881  #ifdef DBG_INIT
1882  printk(("uti596_init: completed.\n"))
1883  #endif 
1884}
1885
1886/***********************************************************************
1887 *  Function:   uti596stop
1888 *
1889 *  Description:
1890 *             stop the driver
1891 *
1892 *  Algorithm:
1893 *             mark driver as not started,
1894 *             mark transmitter as busy
1895 *             abort any transmissions/receptions
1896 *             clean-up all buffers ( RFD's et. al. )
1897 *
1898 *
1899 ***********************************************************************/
1900
1901/* static */ void uti596_stop(
1902  uti596_softc_ *sc
1903)
1904{
1905  struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if;
1906
1907  ifp->if_flags &= ~IFF_RUNNING;
1908  sc->started = 0;
1909
1910  #ifdef DBG_STOP
1911  printk(("uti596stop: %s: Shutting down ethercard, status was %4.4x.\n",
1912           uti596_softc.arpcom.ac_if.if_name, uti596_softc.scb.status))
1913  #endif
1914
1915  printk(("Stopping interface\n"))
1916  sc->scb.command = CUC_ABORT | RX_ABORT;
1917  i82596->chan_attn = 0x00000000;
1918}
1919
1920
1921
1922/***********************************************************************
1923 *  Function:   void uti596_txDaemon
1924 *
1925 *  Description: Transmit task
1926 * 
1927 *  Algorithm: Get mbufs to be transmitted, stuff into RFDs, send
1928 * 
1929 ***********************************************************************/
1930
1931void uti596_txDaemon(
1932  void *arg
1933)
1934{
1935  uti596_softc_ *sc = (uti596_softc_ *)arg;
1936  struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if;
1937  struct mbuf *m;
1938  rtems_event_set events;
1939
1940  for (;;) {
1941   /*
1942    * Wait for packet from stack
1943    */
1944    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
1945                                RTEMS_EVENT_ANY | RTEMS_WAIT,
1946                                RTEMS_NO_TIMEOUT, &events);
1947
1948   /*
1949    * Send packets till queue is empty.
1950    * Ensure that irq is on before sending.
1951    */
1952    for (;;) {
1953     /* Get the next mbuf chain to transmit. */
1954      IF_DEQUEUE(&ifp->if_snd, m);
1955      if (!m)
1956        break;
1957
1958      send_packet (ifp, m); /* blocks */
1959    }
1960    ifp->if_flags &= ~IFF_OACTIVE; /* no more to send, mark output inactive  */
1961  }
1962}
1963
1964/***********************************************************************
1965 *  Function:   uti596_rxDaemon
1966 *
1967 *  Description: Receiver task
1968 *
1969 *  Algorithm: Extract the packet from an RFD, and place into an
1970 *             mbuf chain.  Place the mbuf chain in the network task
1971 *             queue. Assumes that the frame check sequence is removed
1972 *             by the 82596.
1973 *
1974 ***********************************************************************/
1975
1976/* static */ void uti596_rxDaemon(
1977  void *arg
1978)
1979{
1980  uti596_softc_ *sc = (uti596_softc_ *)arg;
1981  struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if;
1982  struct mbuf *m;
1983
1984  i596_rfd *pRfd;
1985  ISR_Level level;
1986  int tid;
1987  rtems_event_set events;
1988  struct ether_header *eh;
1989
1990  int frames = 0;
1991
1992        #ifdef DBG_RX
1993  printk(("uti596_rxDaemon: begin\n"))
1994  printk(("&scb = %p, pRfd = %p\n", &sc->scb,sc->scb.pRfd))
1995        #endif
1996
1997  rtems_task_ident (0, 0, &tid);
1998
1999  for(;;) {
2000    /*
2001     * Wait for packet.
2002     */
2003        #ifdef DBG_RX
2004     printk(("uti596_rxDaemon: Receiver sleeps\n"))
2005        #endif
2006
2007     rtems_bsdnet_event_receive (INTERRUPT_EVENT,
2008                                 RTEMS_WAIT|RTEMS_EVENT_ANY,
2009                                 RTEMS_NO_TIMEOUT,
2010                                 &events);
2011
2012                 #ifdef DBG_RX
2013     printk(("uti596_rxDaemon: Receiver wakes\n"))
2014                 #endif
2015     /*
2016      * While received frames are available. Note that the frame may be
2017      * a fragment, so it is NOT a complete packet.
2018      */
2019     pRfd = uti596_dequeue( (i596_rfd **)&sc->pInboundFrameQueue);
2020     while ( pRfd &&
2021             pRfd != I596_NULL &&
2022             pRfd -> stat & STAT_C )
2023     {
2024
2025       if ( pRfd->stat & STAT_OK) {                             /* a good frame */
2026         int pkt_len = pRfd->count & 0x3fff;    /* the actual # of bytes received */
2027
2028                                 #ifdef DBG_RX
2029         printk(("uti596_rxDaemon: Good frame, @%p, data @%p length %d\n", pRfd, pRfd -> data , pkt_len))
2030                                 #endif
2031         frames++;
2032
2033         /*
2034          * Allocate an mbuf to give to the stack
2035          * The format of the data portion of the RFD is:
2036          * <ethernet header, payload>.
2037          * The FRAME CHECK SEQUENCE / CRC is stripped by the uti596.
2038          * This is to be optimized later.... should not have to memcopy!
2039          */
2040         MGETHDR(m, M_WAIT, MT_DATA);
2041         MCLGET(m, M_WAIT);
2042
2043         m->m_pkthdr.rcvif = ifp;
2044         /* move everything into an mbuf */
2045         memcpy(m->m_data, (const char *)pRfd->data, pkt_len);
2046         m->m_len = m->m_pkthdr.len = pkt_len - sizeof(struct ether_header) - 4;
2047
2048         /* move the header to an mbuf */
2049         eh = mtod (m, struct ether_header *);
2050         m->m_data += sizeof(struct ether_header);
2051
2052                                 #ifdef DBG_PACKETS
2053                                 {
2054                                         int i;
2055                 printk(("uti596_rxDaemon: mbuf contains:\n"))
2056                 print_eth( (char *) (((int)m->m_data)-sizeof(struct ether_header)));
2057                 for ( i = 0; i<20; i++) {
2058                           printk(("."))
2059                 }
2060         }
2061                                 #endif
2062
2063         ether_input (ifp, eh, m);
2064
2065       } /* end if STAT_OK */
2066
2067       else {
2068         /*
2069          * A bad frame is present: Note that this could be the last RFD!
2070          */
2071                                 #ifdef DBG_RX
2072         printk(("uti596_rxDaemon: Bad frame\n"))
2073                                 #endif
2074         /*
2075          * FIX ME: use the statistics from the SCB
2076          */
2077         sc->stats.rx_errors++;
2078         if ((sc->scb.pRfd->stat) & 0x0001)
2079           sc->stats.collisions++;
2080         if ((sc->scb.pRfd->stat) & 0x0080)
2081           sc->stats.rx_length_errors++;
2082         if ((sc->scb.pRfd->stat) & 0x0100)
2083           sc->stats.rx_over_errors++;
2084         if ((sc->scb.pRfd->stat) & 0x0200)
2085           sc->stats.rx_fifo_errors++;
2086         if ((sc->scb.pRfd->stat) & 0x0400)
2087           sc->stats.rx_frame_errors++;
2088         if ((sc->scb.pRfd->stat) & 0x0800)
2089           sc->stats.rx_crc_errors++;
2090         if ((sc->scb.pRfd->stat) & 0x1000)
2091           sc->stats.rx_length_errors++;
2092       }
2093
2094       UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD\n")
2095
2096       _ISR_Disable(level);
2097       uti596_supplyFD ( pRfd );   /* Return RFD to RFA. */
2098       _ISR_Enable(level);
2099
2100       pRfd = uti596_dequeue( (i596_rfd **)&sc->pInboundFrameQueue); /* grab next frame */
2101
2102     } /* end while */
2103  } /* end for() */
2104
2105        #ifdef DBG_RX
2106  printk (("uti596_rxDaemon: frames ... %d\n", frames))
2107        #endif
2108}
2109
2110
2111/***********************************************************************
2112 *  Function:   void uti596_resetDaemon
2113 *
2114 *  Description:
2115 ***********************************************************************/
2116void uti596_resetDaemon(
2117  void *arg
2118)
2119{
2120  uti596_softc_ *sc = (uti596_softc_ *)arg;
2121  rtems_event_set events;
2122  rtems_time_of_day tm_struct;
2123
2124  /* struct ifnet *ifp = &sc->arpcom.ac_if; */
2125
2126  for (;;) {
2127   /* Wait for reset event from ISR */
2128    rtems_bsdnet_event_receive (NIC_RESET_EVENT,
2129                                RTEMS_EVENT_ANY | RTEMS_WAIT,
2130                                RTEMS_NO_TIMEOUT, &events);
2131
2132    rtems_clock_get(RTEMS_CLOCK_GET_TOD, &tm_struct);
2133    printk(("reset daemon: Resetting NIC @ %d:%d:%d \n",
2134           tm_struct.hour, tm_struct.minute, tm_struct.second))
2135
2136    sc->stats.nic_reset_count++;
2137    /* Reinitialize the LANC */
2138    rtems_bsdnet_semaphore_obtain ();
2139    uti596_reset();
2140    rtems_bsdnet_semaphore_release ();
2141  }
2142}
2143
2144
2145/***********************************************************************
2146 *  Function:   uti596_DynamicInterruptHandler
2147 *
2148 *  Description:
2149 *             This is the interrupt handler for the uti596 board
2150 *
2151 ***********************************************************************/
2152
2153/* static */ rtems_isr uti596_DynamicInterruptHandler(
2154  rtems_vector_number irq
2155)
2156{
2157        #ifdef DBG_ISR
2158  printk(("uti596_DynamicInterruptHandler: begins"))
2159        #endif
2160
2161 uti596_wait (&uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT);
2162
2163 scbStatus = uti596_softc.scb.status & 0xf000;
2164
2165 if ( scbStatus ) {
2166   /* acknowledge interrupts */
2167   
2168   /* Write to the ICLR bit in the PCCchip2 control registers to clear
2169    * the INT status bit. Clearing INT here *before* sending the CA signal
2170    * to the 82596 should ensure that interrupts won't be lost.
2171    */
2172    pccchip2->LANC_int_ctl |=0x08;
2173    pccchip2->LANC_berr_ctl |=0x08;
2174   
2175    /* printk(("***INFO: ACK %x\n", scbStatus))*/
2176   
2177    /* Send the CA signal to acknowledge interrupt */
2178    uti596_softc.scb.command = scbStatus;
2179    uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT );
2180
2181    if( uti596_softc.resetDone ) {
2182      /* stack is attached */
2183      uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT );
2184    }
2185    else {
2186      printk(("***INFO: ACK'd w/o processing. status = %x\n", scbStatus))
2187      return;
2188    }
2189  }
2190  else {
2191    printk(("\n***ERROR: Spurious interrupt. Resetting...\n"))
2192    uti596_softc.nic_reset = 1;
2193  }
2194
2195
2196  if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) ) {
2197    printk(("\n*****ERROR: Command Complete, and CNA available: 0x%x\nResetting...", scbStatus))
2198    uti596_softc.nic_reset = 1;
2199    return;
2200  }
2201
2202  if ( !(scbStatus & SCB_STAT_CX) && (scbStatus & SCB_STAT_CNA) ) {
2203    printk(("\n*****ERROR: CNA, NO CX:0x%x\nResetting...",scbStatus))
2204    uti596_softc.nic_reset = 1;
2205    return;
2206  }
2207
2208  if ( scbStatus & SCB_CUS_SUSPENDED ) {
2209    printk(("\n*****ERROR: Command unit suspended!:0x%x\nResetting...",scbStatus))
2210    uti596_softc.nic_reset = 1;
2211    return;
2212  }
2213
2214  if ( scbStatus & RU_SUSPENDED  ) {
2215    printk(("\n*****ERROR: Receive unit suspended!:0x%x\nResetting...",scbStatus))
2216    uti596_softc.nic_reset = 1;
2217    return;
2218  }
2219
2220  if ( scbStatus & SCB_STAT_RNR ) {
2221    printk(("\n*****WARNING: RNR %x\n",scbStatus))
2222    if (uti596_softc.pBeginRFA != I596_NULL) {
2223        printk(("*****INFO: RFD cmd: %x status:%x\n", uti596_softc.pBeginRFA->cmd,
2224                                        uti596_softc.pBeginRFA->stat))
2225    }
2226    else {
2227        printk(("*****WARNING: RNR condition with NULL BeginRFA\n"))
2228    }         
2229  }
2230
2231 /*
2232  * Receive Unit Control
2233  *   a frame is received
2234  */
2235  if ( scbStatus & SCB_STAT_FR ) {
2236    uti596_softc.rxInterrupts++;
2237 
2238                #ifdef DBG_ISR
2239    printk(("uti596_DynamicInterruptHandler: Frame received\n"))
2240                #endif
2241    if ( uti596_softc.pBeginRFA == I596_NULL ||
2242       !( uti596_softc.pBeginRFA -> stat & STAT_C)) {
2243      uti596_dump_scb();
2244      uti596_softc.nic_reset = 1;
2245    }
2246    else {
2247      while ( uti596_softc.pBeginRFA != I596_NULL &&
2248           ( uti596_softc.pBeginRFA -> stat & STAT_C)) {
2249
2250                                #ifdef DBG_ISR
2251        printk(("uti596_DynamicInterruptHandler: pBeginRFA != NULL\n"))
2252                                #endif
2253        count_rx ++;
2254        if ( count_rx > 1) {
2255          printk(("****WARNING: Received 2 frames on 1 interrupt \n"))
2256                                }
2257       /* Give Received Frame to the ULCS */
2258        uti596_softc.countRFD--;
2259
2260        if ( uti596_softc.countRFD < 0 ) {
2261          printk(("ISR: Count < 0 !!! count == %d, beginRFA = %p\n",
2262                 uti596_softc.countRFD, uti596_softc.pBeginRFA))
2263                                }
2264        uti596_softc.stats.rx_packets++;
2265        /* the rfd next link is stored with upper and lower words swapped so read it that way */
2266        pIsrRfd = (i596_rfd *) word_swap ((unsigned long)uti596_softc.pBeginRFA->next);
2267        /* the append destroys the link */
2268        uti596_append( (i596_rfd **)&uti596_softc.pInboundFrameQueue , uti596_softc.pBeginRFA );
2269
2270       /*
2271        * if we have just received the a frame in the last unknown RFD,
2272        * then it is certain that the RFA is empty.
2273        */
2274        if ( uti596_softc.pLastUnkRFD == uti596_softc.pBeginRFA ) {
2275          UTI_596_ASSERT(uti596_softc.pLastUnkRFD != I596_NULL,"****ERROR:LastUnk is NULL, begin ptr @ end!\n")
2276          uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD = I596_NULL;
2277        }
2278
2279                                #ifdef DBG_ISR
2280        printk(("uti596_DynamicInterruptHandler: Wake %#x\n",uti596_softc.rxDaemonTid))
2281                                #endif
2282        sc = rtems_event_send(uti596_softc.rxDaemonTid, INTERRUPT_EVENT);
2283        if ( sc != RTEMS_SUCCESSFUL ) {
2284          rtems_panic("Can't notify rxDaemon: %s\n",
2285                    rtems_status_text (sc));
2286        }
2287                                #ifdef DBG_ISR
2288        else {
2289          printk(("uti596_DynamicInterruptHandler: Rx Wake: %#x\n",uti596_softc.rxDaemonTid))
2290        }
2291                                #endif
2292
2293        uti596_softc.pBeginRFA = pIsrRfd;
2294      } /* end while */
2295    } /* end if */
2296
2297    if ( uti596_softc.pBeginRFA == I596_NULL ) {
2298      /* adjust the pEndRFA to reflect an empty list */
2299      if ( uti596_softc.pLastUnkRFD == I596_NULL && uti596_softc.countRFD != 0 ) {
2300        printk(("Last Unk is NULL, BeginRFA is null, and count == %d\n",
2301               uti596_softc.countRFD))
2302                        }
2303      uti596_softc.pEndRFA = I596_NULL;
2304      if ( uti596_softc.countRFD != 0 ) {
2305        printk(("****ERROR:Count is %d, but begin ptr is NULL\n",
2306               uti596_softc.countRFD ))
2307      }
2308    }
2309  } /* end if ( scbStatus & SCB_STAT_FR ) */
2310
2311
2312 /*
2313  * Command Unit Control
2314  *   a command is completed
2315  */
2316  if ( scbStatus & SCB_STAT_CX ) {
2317                #ifdef DBG_ISR
2318    printk(("uti596_DynamicInterruptHandler: CU\n"))
2319                #endif
2320
2321    pIsrCmd = uti596_softc.pCmdHead;
2322
2323   /* For ALL completed commands */
2324   if ( pIsrCmd !=  I596_NULL && pIsrCmd->status & STAT_C  ) {
2325
2326                         #ifdef DBG_ISR
2327       printk(("uti596_DynamicInterruptHandler: pIsrCmd != NULL\n"))
2328                         #endif
2329
2330      /* Adjust the command block list */
2331      uti596_softc.pCmdHead = (i596_cmd *) word_swap ((unsigned long)pIsrCmd->next);
2332
2333     /*
2334      * If there are MORE commands to process,
2335      * the serialization in the raw routine has failed.
2336      * ( Perhaps AddCmd is bad? )
2337      */
2338      UTI_596_ASSERT(uti596_softc.pCmdHead == I596_NULL, "****ERROR: command serialization failed\n")
2339                   
2340      /* What if the command did not complete OK? */
2341      switch ( pIsrCmd->command & 0x7) {
2342        case CmdConfigure:
2343
2344          uti596_softc.cmdOk = 1;
2345          break;
2346
2347        case CmdDump:
2348                                        #ifdef DBG_ISR
2349          printk(("uti596_DynamicInterruptHandler: dump!\n"))
2350                                        #endif
2351          uti596_softc.cmdOk = 1;
2352          break;
2353
2354        case CmdDiagnose:
2355                                        #ifdef DBG_ISR
2356          printk(("uti596_DynamicInterruptHandler: diagnose!\n"))
2357                                        #endif
2358          uti596_softc.cmdOk = 1;
2359          break;
2360
2361        case CmdSASetup:
2362          /* printk(("****INFO:Set address interrupt\n")) */
2363          if ( pIsrCmd -> status & STAT_OK ) {
2364            uti596_softc.cmdOk = 1;
2365          }
2366          else {
2367            printk(("****ERROR:SET ADD FAILED\n"))
2368                                        }
2369          break;
2370
2371        case CmdTx:
2372          UTI_596_ASSERT(uti596_softc.txDaemonTid, "****ERROR:Null txDaemonTid\n")
2373                                        #ifdef DBG_ISR
2374          printk(("uti596_DynamicInterruptHandler: wake TX:0x%x\n",uti596_softc.txDaemonTid))
2375                                        #endif
2376          if ( uti596_softc.txDaemonTid ) {
2377            /* Ensure that the transmitter is present */
2378            sc = rtems_event_send (uti596_softc.txDaemonTid,
2379                                 INTERRUPT_EVENT);
2380
2381            if ( sc != RTEMS_SUCCESSFUL ) {
2382              printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n",
2383                     uti596_softc.txDaemonTid, rtems_status_text (sc) ))
2384            }
2385                                                #ifdef DBG_ISR
2386            else {
2387              printk(("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid))
2388            }
2389                                                #endif
2390          }
2391          break;
2392
2393        case CmdMulticastList:
2394          printk(("***ERROR:Multicast?!\n"))
2395          pIsrCmd->next = I596_NULL;
2396          break;
2397
2398        case CmdTDR: {
2399                  unsigned long status = *( (unsigned long *)pIsrCmd)+1;
2400                  printk(("****ERROR:TDR?!\n"))
2401
2402                  if (status & STAT_C) {
2403                    /* mark the TDR command successful */
2404                    uti596_softc.cmdOk = 1;
2405                  }
2406                  else {
2407                    if (status & 0x4000) {
2408                      printk(("****WARNING:Transceiver problem.\n"))
2409                    }
2410                    if (status & 0x2000) {
2411                      printk(("****WARNING:Termination problem.\n"))
2412                    }
2413                    if (status & 0x1000) {
2414                      printk(("****WARNING:Short circuit.\n"))
2415                      /* printk(("****INFO:Time %ld.\n", status & 0x07ff)) */
2416                    }
2417                  }
2418          }
2419          break;
2420
2421        default: {
2422          /*
2423           * This should never be reached
2424           */
2425          printk(("CX but NO known command\n"))
2426        }
2427      } /* end switch */
2428
2429      pIsrCmd = uti596_softc.pCmdHead; /* next command */
2430      if ( pIsrCmd != I596_NULL ) {
2431        printk(("****WARNING: more commands in list, but no start to NIC\n"))
2432      }
2433    } /* end if pIsrCmd != NULL && pIsrCmd->stat & STAT_C  */
2434   
2435    else {
2436      if ( pIsrCmd != I596_NULL ) { 
2437        /* The command MAY be NULL from a RESET */
2438        /* Reset the ethernet card, and wake the transmitter (if necessary) */
2439        printk(("****INFO: Request board reset ( tx )\n"))
2440        uti596_softc.nic_reset = 1;
2441        if ( uti596_softc.txDaemonTid) {
2442          /* Ensure that a transmitter is present */
2443          sc = rtems_event_send (uti596_softc.txDaemonTid,
2444                                 INTERRUPT_EVENT);
2445          if ( sc != RTEMS_SUCCESSFUL ) {
2446            printk(("****ERROR:Could NOT send event to tid 0x%x : %s\n",
2447                                         uti596_softc.txDaemonTid, rtems_status_text (sc) ))
2448          }
2449                                        #ifdef DBG_ISR
2450          else {
2451            printk(("uti596_DynamicInterruptHandler: ****INFO:Tx wake: %#x\n",
2452                                         uti596_softc.txDaemonTid))
2453          }
2454                                        #endif
2455        }
2456      }
2457    }
2458  }  /* end if command complete */
2459
2460
2461 /*
2462  * If the receiver has stopped,
2463  * check if this is a No Resources scenario,
2464  * Try to add more RFD's ( no RBDs are used )
2465  */
2466  if ( uti596_softc.started ) {
2467    if ( scbStatus & SCB_STAT_RNR ) {
2468                        #ifdef DBG_ISR
2469      printk(("uti596_DynamicInterruptHandler: INFO:RNR: status %#x \n",
2470                                uti596_softc.scb.status ))
2471                        #endif
2472     /*
2473      * THE RECEIVER IS OFF!
2474      */
2475      if ( uti596_softc.pLastUnkRFD != I596_NULL  ) {
2476        /* We have an unknown RFD, it is not inbound */
2477        if ( uti596_softc.pLastUnkRFD -> stat & (STAT_C | STAT_B )) { /* in use */
2478          uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD;            /* update end */
2479        }
2480        else {
2481         /*
2482          *  It is NOT in use, and since RNR, we know EL bit of pEndRFA was read!
2483          *  So, unlink it from the RFA and move it to the saved queue.
2484          *  But pBegin can equal LastUnk!
2485          */
2486
2487          if ( uti596_softc.pEndRFA != I596_NULL ) {
2488            /* check added feb24. */
2489                                                #ifdef DBG_ISR
2490            if ((i596_rfd *)word_swap((unsigned long)uti596_softc.pEndRFA->next) != uti596_softc.pLastUnkRFD) {
2491              printk(("***ERROR:UNK: %p not end->next: %p, end: %p\n",
2492                     uti596_softc.pLastUnkRFD,
2493                     uti596_softc.pEndRFA -> next,
2494                     uti596_softc.pEndRFA))
2495              printk(("***INFO:countRFD now %d\n",
2496                     uti596_softc.countRFD))
2497              printk(("\n\n"))
2498            }
2499                                                #endif
2500            uti596_softc.pEndRFA -> next = I596_NULL;   /* added feb 16 */
2501          }
2502          uti596_append( (i596_rfd **)&uti596_softc.pSavedRfdQueue, uti596_softc.pLastUnkRFD );
2503          uti596_softc.savedCount++;
2504          uti596_softc.pEndSavedQueue = uti596_softc.pLastUnkRFD;
2505          uti596_softc.countRFD--;                    /* It was not in the RFA */
2506         /*
2507          * The Begin pointer CAN advance this far. We must resynch the CPU side
2508          * with the chip.
2509          */
2510          if ( uti596_softc.pBeginRFA == uti596_softc.pLastUnkRFD ) {
2511                                                #ifdef DBG_ISR
2512            if ( uti596_softc.countRFD != 0 ) {
2513              printk(("****INFO:About to set begin to NULL, with count == %d\n\n",
2514                     uti596_softc.countRFD ))
2515            }
2516                                                #endif
2517            uti596_softc.pBeginRFA = I596_NULL;
2518            UTI_596_ASSERT(uti596_softc.countRFD == 0, "****ERROR:Count must be zero here!\n")
2519          }
2520        }
2521        uti596_softc.pLastUnkRFD = I596_NULL;
2522      } /* end if exists UnkRFD */
2523
2524     /*
2525      * Append the saved queue to  the RFA.
2526      * Any further RFD's being supplied will be added to
2527      * this new list.
2528      */
2529      if ( uti596_softc.pSavedRfdQueue != I596_NULL ) {
2530        /* entries to add */
2531        if ( uti596_softc.pBeginRFA == I596_NULL ) {
2532          /* add at beginning to list */
2533                                        #ifdef DBG_ISR
2534          if(uti596_softc.countRFD != 0) {
2535            printk(("****ERROR:Begin pointer is NULL, but count == %d\n",
2536                   uti596_softc.countRFD))
2537          }
2538                                        #endif
2539          uti596_softc.pBeginRFA      = uti596_softc.pSavedRfdQueue;
2540          uti596_softc.pEndRFA        = uti596_softc.pEndSavedQueue;
2541          uti596_softc.pSavedRfdQueue = uti596_softc.pEndSavedQueue = I596_NULL;  /* Reset the End */
2542        }
2543        else {
2544                                        #ifdef DBG_ISR
2545          if ( uti596_softc.countRFD <= 0) {
2546            printk(("****ERROR:Begin pointer is not NULL, but count == %d\n",
2547                   uti596_softc.countRFD))
2548          }
2549                                        #endif
2550          UTI_596_ASSERT( uti596_softc.pEndRFA != I596_NULL, "****WARNING: END RFA IS NULL\n")
2551          UTI_596_ASSERT( uti596_softc.pEndRFA->next == I596_NULL, "****ERROR:END RFA -> next must be NULL\n")
2552
2553          uti596_softc.pEndRFA->next   = (i596_rfd *)word_swap((unsigned long)uti596_softc.pSavedRfdQueue);
2554          uti596_softc.pEndRFA->cmd   &= ~CMD_EOL;      /* clear the end of list */
2555          uti596_softc.pEndRFA         = uti596_softc.pEndSavedQueue;
2556          uti596_softc.pSavedRfdQueue  = uti596_softc.pEndSavedQueue = I596_NULL; /* Reset the End */
2557                                        #ifdef DBG_ISR
2558          printk(("uti596_DynamicInterruptHandler: count... %d, saved ... %d \n",
2559                 uti596_softc.countRFD,
2560                 uti596_softc.savedCount))
2561                                        #endif
2562        }
2563        /* printk(("Isr: countRFD = %d\n",uti596_softc.countRFD)) */
2564        uti596_softc.countRFD += uti596_softc.savedCount;
2565        /* printk(("Isr: after countRFD = %d\n",uti596_softc.countRFD)) */
2566        uti596_softc.savedCount = 0;
2567      }
2568
2569                        #ifdef DBG_ISR
2570      printk(("uti596_DynamicInterruptHandler: The list starts here %p\n",uti596_softc.pBeginRFA ))
2571                        #endif
2572
2573      if ( uti596_softc.countRFD > 1) {
2574        printk(("****INFO: pBeginRFA -> stat = 0x%x\n",uti596_softc.pBeginRFA -> stat))
2575        printk(("****INFO: pBeginRFA -> cmd = 0x%x\n",uti596_softc.pBeginRFA -> cmd))
2576        uti596_softc.pBeginRFA -> stat = 0;
2577        UTI_596_ASSERT(uti596_softc.scb.command == 0, "****ERROR:scb command must be zero\n")
2578        uti596_softc.scb.pRfd = uti596_softc.pBeginRFA;
2579        uti596_softc.scb.rfd_pointer = word_swap((unsigned long)uti596_softc.pBeginRFA);
2580        /* start RX here  */
2581        printk(("****INFO: ISR Starting receiver\n"))
2582        uti596_softc.scb.command = RX_START; /* should this also be CU start? */
2583        i82596->chan_attn = 0x00000000;
2584      }
2585    } /* end stat_rnr */
2586  } /* end if receiver started */
2587
2588        #ifdef DBG_ISR
2589  printk(("uti596_DynamicInterruptHandler: X\n"))
2590        #endif
2591  count_rx=0;
2592 
2593 
2594 /* Do this last, to ensure that the reset is called at the right time. */
2595  if ( uti596_softc.nic_reset ) {
2596    uti596_softc.nic_reset = 0;
2597    sc = rtems_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT);
2598    if ( sc != RTEMS_SUCCESSFUL )
2599      rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc));
2600  }
2601  return;
2602}
2603
2604
2605/***********************************************************************
2606 *  Function:  uti596_ioctl
2607 *
2608 *  Description:
2609 *             driver ioctl function
2610 *             handles SIOCGIFADDR, SIOCSIFADDR, SIOCSIFFLAGS
2611 *             
2612 ***********************************************************************/
2613 
2614static int uti596_ioctl(
2615  struct ifnet *ifp,
2616  int command,
2617  caddr_t data
2618)
2619{
2620  uti596_softc_ *sc = ifp->if_softc;
2621  int error = 0;
2622
2623        #ifdef DBG_IOCTL
2624  printk(("uti596_ioctl: begins\n", sc->pScp))
2625        #endif
2626
2627  switch (command) {
2628    case SIOCGIFADDR:
2629    case SIOCSIFADDR:
2630      printk(("SIOCSIFADDR\n"))
2631      ether_ioctl (ifp, command, data);
2632      break;
2633
2634    case SIOCSIFFLAGS:
2635      printk(("SIOCSIFFLAGS\n"))
2636      switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
2637        case IFF_RUNNING:
2638          printk(("IFF_RUNNING\n"))
2639          uti596_stop (sc);
2640          break;
2641
2642        case IFF_UP:
2643          printk(("IFF_UP\n"))
2644          uti596_init ( (void *)sc);
2645          break;
2646
2647        case IFF_UP | IFF_RUNNING:
2648          printk(("IFF_UP and RUNNING\n"))
2649          uti596_stop (sc);
2650          uti596_init ( (void *)sc);
2651          break;
2652
2653        default:
2654          printk(("default\n"))
2655          break;
2656      }
2657      break;
2658
2659    case SIO_RTEMS_SHOW_STATS:
2660      printk(("show stats\n"))
2661      uti596_stats (sc);
2662      break;
2663
2664    /* FIXME: All sorts of multicast commands need to be added here! */
2665    default:
2666      printk(("default: EINVAL\n"))
2667      error = EINVAL;
2668      break;
2669  }
2670 
2671  return error;
2672}
2673
2674
2675/***********************************************************************
2676 *  Function:   uti596_stats
2677 *
2678 *  Description:
2679 *             print out the collected data
2680 *
2681 *  Algorithm:
2682 *            use printf
2683 *
2684 ***********************************************************************/
2685
2686void uti596_stats(
2687  uti596_softc_ *sc
2688)
2689{
2690  printf ("CPU Reports:\n");
2691  printf ("  Tx raw send count:%-8lu",  sc->rawsndcnt);
2692  printf ("  Rx Interrupts:%-8lu",  sc->rxInterrupts);
2693  printf ("  Tx Interrupts:%-8lu\n",  sc->txInterrupts);
2694  printf ("  Rx Packets:%-8u",  sc->stats.rx_packets);
2695  printf ("  Tx Attempts:%-u\n",  sc->stats.tx_packets);
2696
2697  printf ("  Rx Dropped:%-8u",  sc->stats.rx_dropped);
2698  printf ("  Rx IP Packets:%-8u",  sc->stats.rx_packets);
2699  printf ("  Tx Errors:%-8u\n",  sc->stats.tx_errors);
2700  printf ("  Tx aborted:%-8u",  sc->stats.tx_aborted_errors);
2701  printf ("  Tx Dropped:%-8u\n",  sc->stats.tx_dropped);
2702  printf ("  Tx IP packets:%-8u",  sc->stats.tx_packets);
2703
2704  printf ("  Collisions Detected:%-8u\n",  sc->stats.collisions);
2705  printf ("  Tx Heartbeat Errors:%-8u",  sc->stats.tx_heartbeat_errors);
2706  printf ("  Tx Carrier Errors:%-8u\n",  sc->stats.tx_carrier_errors);
2707  printf ("  Tx Aborted Errors:%-8u",  sc->stats.tx_aborted_errors);
2708  printf ("  Rx Length Errors:%-8u\n",  sc->stats.rx_length_errors);
2709  printf ("  Rx Overrun Errors:%-8u",  sc->stats.rx_over_errors);
2710  printf ("  Rx Fifo Errors:%-8u\n",  sc->stats.rx_fifo_errors);
2711  printf ("  Rx Framing Errors:%-8u",  sc->stats.rx_frame_errors);
2712  printf ("  Rx crc errors:%-8u\n",  sc->stats.rx_crc_errors);
2713
2714  printf ("  TX WAITS: %-8lu\n",  sc->txRawWait);
2715
2716  printf ("  NIC resets: %-8u\n",  sc->stats.nic_reset_count);
2717
2718  printf ("  NIC reports\n");
2719
2720        #ifdef DBG_STAT
2721  uti596_dump_scb();
2722  #endif
2723}
2724
2725
2726
2727
2728/************************ PACKET DEBUG ROUTINES ************************/
2729
2730#ifdef DBG_PACKETS
2731
2732/*
2733 *  dumpQ
2734 *
2735 *  Dumps frame queues for debugging
2736 */
2737static void dumpQ( void )
2738{
2739  i596_rfd *pRfd;
2740
2741  printk(("savedQ:\n"))
2742 
2743  for( pRfd = uti596_softc.pSavedRfdQueue;
2744       pRfd != I596_NULL;
2745       pRfd = pRfd -> next) {
2746      printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd))
2747  }
2748     
2749  printk(("Inbound:\n"))
2750 
2751  for( pRfd = uti596_softc.pInboundFrameQueue;
2752       pRfd != I596_NULL;
2753       pRfd = pRfd -> next) {
2754    printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd))
2755  }
2756   
2757  printk(("Last Unk: %p\n", uti596_softc.pLastUnkRFD ))
2758  printk(("RFA:\n"))
2759 
2760  for( pRfd = uti596_softc.pBeginRFA;
2761       pRfd != I596_NULL;
2762       pRfd = pRfd -> next) {
2763    printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd))
2764  }
2765}
2766
2767
2768/*
2769 *  show_buffers
2770 * 
2771 *  Print out the RFA and frame queues
2772 */
2773static void show_buffers (void)
2774{
2775  i596_rfd *pRfd;
2776
2777  printk(("82596 cmd: 0x%x, status: 0x%x RFA len: %d\n",
2778         uti596_softc.scb.command,
2779         uti596_softc.scb.status,
2780         uti596_softc.countRFD))
2781
2782  printk(("\nRFA: \n"))
2783 
2784  for ( pRfd = uti596_softc.pBeginRFA;
2785        pRfd != I596_NULL;
2786        pRfd = pRfd->next) {
2787    printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2788            pRfd, pRfd->stat, pRfd->cmd))
2789        }
2790  printk(("\nInbound: \n"))
2791 
2792  for ( pRfd = uti596_softc.pInboundFrameQueue;
2793        pRfd != I596_NULL;
2794        pRfd = pRfd->next) {
2795    printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2796            pRfd, pRfd->stat, pRfd->cmd))
2797        }
2798
2799  printk(("\nSaved: \n"))
2800 
2801  for ( pRfd = uti596_softc.pSavedRfdQueue;
2802        pRfd != I596_NULL;
2803        pRfd = pRfd->next) {
2804    printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n",
2805             pRfd, pRfd->stat, pRfd->cmd))
2806  }
2807           
2808  printk(("\nUnknown: %p\n",uti596_softc.pLastUnkRFD))
2809}
2810
2811
2812/*
2813 *  show_queues
2814 *
2815 *  Print out the saved frame queue and the RFA
2816 */
2817static void show_queues(void)
2818{
2819  i596_rfd *pRfd;
2820
2821  printk(("CMD: 0x%x, Status: 0x%x\n",
2822         uti596_softc.scb.command,
2823         uti596_softc.scb.status))
2824  printk(("saved Q\n"))
2825
2826  for ( pRfd = uti596_softc.pSavedRfdQueue;
2827        pRfd != I596_NULL &&
2828        pRfd != NULL;
2829        pRfd = pRfd->next) {
2830    printk(("0x%p\n", pRfd))
2831  }
2832
2833  printk(("End saved Q 0x%p\n", uti596_softc.pEndSavedQueue))
2834
2835  printk(("\nRFA:\n"))
2836 
2837  for ( pRfd = uti596_softc.pBeginRFA;
2838        pRfd != I596_NULL &&
2839        pRfd != NULL;
2840        pRfd = pRfd->next) {
2841    printk(("0x%p\n", pRfd))
2842  }
2843
2844  printk(("uti596_softc.pEndRFA: %p\n",uti596_softc.pEndRFA))
2845}
2846
2847
2848/*
2849 *  print_eth
2850 *
2851 *  Print the contents of an ethernet packet
2852 *  CANNOT BE CALLED FROM ISR
2853 */
2854static void print_eth(
2855  unsigned char *add
2856)
2857{
2858  int i;
2859  short int length;
2860
2861  printk (("Packet Location %p\n", add))
2862  printk (("Dest  "))
2863
2864  for (i = 0; i < 6; i++) {
2865    printk ((" %2.2X", add[i]))
2866        }
2867  printk (("\n"))
2868  printk (("Source"))
2869
2870  for (i = 6; i < 12; i++) {
2871        printk ((" %2.2X", add[i]))
2872  }
2873 
2874  printk (("\n"))
2875  printk (("frame type %2.2X%2.2X\n", add[12], add[13]))
2876
2877  if ( add[12] == 0x08 && add[13] == 0x06 ) { 
2878    /* an ARP */
2879    printk (("Hardware type : %2.2X%2.2X\n", add[14],add[15]))
2880    printk (("Protocol type : %2.2X%2.2X\n", add[16],add[17]))
2881    printk (("Hardware size : %2.2X\n", add[18]))
2882    printk (("Protocol size : %2.2X\n", add[19]))
2883    printk (("op            : %2.2X%2.2X\n", add[20],add[21]))
2884    printk (("Sender Enet addr: "))
2885
2886    for ( i=0; i< 5 ; i++) {
2887      printk (("%x:", add[22 + i]))
2888                }
2889    printk (("%x\n", add[27]))
2890    printk (("Sender IP addr: "))
2891   
2892    for ( i=0; i< 3 ; i++) {
2893      printk (("%u.", add[28 + i]))
2894                }
2895    printk (("%u\n", add[31]))
2896    printk (("Target Enet addr: "))
2897   
2898    for ( i=0; i< 5 ; i++) {
2899      printk (( "%x:", add[32 + i]))
2900                }
2901    printk (("%x\n", add[37]))
2902    printk (("Target IP addr: "))
2903
2904    for ( i=0; i< 3 ; i++) {
2905      printk (( "%u.", add[38 + i]))
2906    }
2907    printk (("%u\n", add[41]))
2908  }
2909
2910
2911  if ( add[12] == 0x08 && add[13] == 0x00 ) {
2912        /* an IP packet */
2913    printk (("*********************IP HEADER******************\n"))
2914    printk (("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15]))
2915    printk (("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] )))
2916    printk (("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n",
2917            add[18],add[19], add[20], add[21]))
2918    printk (("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n",
2919             add[22],add[23],add[24],add[25]))
2920    printk (("IP packet type: %2.2X code %2.2X\n", add[34],add[35]))
2921    printk (("Source IP address: "))
2922   
2923    for ( i=0; i< 3 ; i++) {
2924      printk (("%u.", add[26 + i]))
2925    }
2926    printk (("%u\n", add[29]))
2927    printk (("Destination IP address: "))
2928   
2929    for ( i=0; i< 3 ; i++) {
2930      printk (("%u.", add[30 + i]))
2931    }
2932    printk (("%u\n", add[33]))
2933  }
2934}
2935
2936
2937/*
2938 *  print_hdr
2939 *
2940 *  Print the contents of an ethernet packet header
2941 *  CANNOT BE CALLED FROM ISR
2942 */
2943static  void print_hdr(
2944  unsigned char *add
2945)
2946{
2947  int i;
2948
2949  printk (("print_hdr: begins\n"))
2950  printk (("Header Location %p\n", add))
2951  printk (("Dest  "))
2952
2953  for (i = 0; i < 6; i++) {
2954    printk ((" %2.2X", add[i]))
2955        }
2956  printk (("\nSource"))
2957
2958  for (i = 6; i < 12; i++) {
2959    printk ((" %2.2X", add[i]))
2960        }
2961  printk (("\nframe type %2.2X%2.2X\n", add[12], add[13]))
2962  printk (("print_hdr: completed"))
2963}
2964
2965
2966/*
2967 *  Function:   print_pkt
2968 *
2969 *  Print the contents of an ethernet packet & data
2970 *  CANNOT BE CALLED FROM ISR
2971 */
2972static void print_pkt(
2973  unsigned char *add
2974)
2975{
2976  int i;
2977  short int length;
2978
2979  printk (("print_pkt: begins"))
2980  printk (("Data Location %p\n", add))
2981
2982  if ( add[0] == 0x08 && add[1] == 0x06 ) {
2983    /* an ARP */
2984    printk (("Hardware type : %2.2X%2.2X\n", add[14],add[15]))
2985    printk (("Protocol type : %2.2X%2.2X\n", add[16],add[17]))
2986    printk (("Hardware size : %2.2X\n", add[18]))
2987    printk (("Protocol size : %2.2X\n", add[19]))
2988    printk (("op            : %2.2X%2.2X\n", add[20],add[21]))
2989    printk (("Sender Enet addr: "))
2990
2991    for ( i=0; i< 5 ; i++) {
2992      printk (( "%x:", add[22 + i]))
2993                }
2994    printk (("%x\n", add[27]))
2995    printk (("Sender IP addr: "))
2996   
2997    for ( i=0; i< 3 ; i++) {
2998      printk (("%u.", add[28 + i]))
2999                }
3000    printk (("%u\n", add[31]))
3001    printk (("Target Enet addr: "))
3002   
3003    for ( i=0; i< 5 ; i++) {
3004      printk (( "%x:", add[32 + i]))   
3005    }
3006    printk (("%x\n", add[37]))
3007    printk (("Target IP addr: "))
3008
3009    for ( i=0; i< 3 ; i++) {
3010      printk (( "%u.", add[38 + i]))
3011    }
3012    printk (("%u\n", add[41]))
3013  }
3014
3015  if ( add[0] == 0x08 && add[1] == 0x00 ) {
3016    /* an IP packet */
3017    printk (("*********************IP HEADER******************\n"))
3018    printk (("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15]))
3019    printk (("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] )))
3020    printk (("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n",
3021            add[18],add[19], add[20], add[21]))
3022    printk (("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n",
3023            add[22],add[23],add[24],add[25]))
3024    printk (("IP packet type: %2.2X code %2.2X\n", add[34],add[35]))
3025    printk (("Source IP address: "))
3026   
3027    for ( i=0; i< 3 ; i++) {
3028      printk(( "%u.", add[26 + i]))
3029                }
3030    printk(("%u\n", add[29]))
3031    printk(("Destination IP address: "))
3032   
3033    for ( i=0; i< 3 ; i++) {
3034      printk(( "%u.", add[30 + i]))
3035    }
3036    printk(("%u\n", add[33]))
3037    printk(("********************IP Packet Data*******************\n"))
3038    length -=20;
3039   
3040    for ( i=0; i < length ; i++) {
3041      printk(("0x%2.2x ", add[34+i]))
3042    }
3043    printk(("\n"))
3044    printk(("ICMP checksum: %2.2x %2.2x\n", add[36], add[37]))
3045    printk(("ICMP identifier: %2.2x %2.2x\n", add[38], add[39]))
3046    printk(("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41]))
3047    printk(("print_pkt: completed"))
3048  }
3049}
3050
3051
3052/*
3053 *  print_echo
3054 *
3055 *  Print the contents of an echo packet
3056 *  CANNOT BE CALLED FROM ISR
3057 */
3058static void print_echo(
3059  unsigned char *add
3060)
3061{
3062  int i;
3063  short int length;
3064
3065  printk (("print_echo: begins"))
3066
3067  if ( add[12] == 0x08 && add[13] == 0x00 ) { 
3068    /* an IP packet */
3069    printk (("Packet Location %p\n", add))
3070    printk (("Dest  "))
3071
3072    for (i = 0; i < 6; i++) {
3073      printk ((" %2.2X", add[i]))
3074                }
3075    printk (("\n"))
3076    printk (("Source"))
3077
3078    for (i = 6; i < 12; i++) {
3079      printk ((" %2.2X", add[i]))
3080                }
3081    printk (("\n"))
3082    printk (("frame type %2.2X%2.2X\n", add[12], add[13]))
3083   
3084    printk (("*********************IP HEADER******************\n"))
3085    printk (("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15]))
3086    printk (("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] )))
3087    printk (("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n",
3088            add[18],add[19], add[20], add[21]))
3089    printk (("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n",
3090            add[22],add[23],add[24],add[25]))
3091    printk (("IP packet type: %2.2X code %2.2X\n", add[34],add[35]))
3092    printk (("Source IP address: "))
3093   
3094    for ( i=0; i< 3 ; i++) {
3095      printk (("%u.", add[26 + i]))
3096                }
3097    printk (("%u\n", add[29]))
3098    printk (("Destination IP address: "))
3099   
3100    for ( i=0; i< 3 ; i++) {
3101      printk (("%u.", add[30 + i]))
3102    }
3103    printk (("%u\n", add[33]))
3104    printk(("********************IP Packet Data*******************\n"))
3105    length -=20;
3106   
3107    for ( i=0; i < length ; i++) {
3108      printk(("0x%2.2x ", add[34+i]))
3109                }
3110    printk(("\n"))
3111    printk(("ICMP checksum: %2.2x %2.2x\n", add[36], add[37]))
3112    printk(("ICMP identifier: %2.2x %2.2x\n", add[38], add[39]))
3113    printk(("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41]))
3114    printk(("print_echo: completed"))
3115  }
3116}
3117
3118#endif
Note: See TracBrowser for help on using the repository browser.