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

4.104.115
Last change on this file since f6cef3a was f6cef3a, checked in by Joel Sherrill <joel.sherrill@…>, on 02/17/09 at 18:37:02

2009-02-17 Till Straumann <strauman@…>

PR 1371/bsps

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