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

4.104.114.84.95
Last change on this file since d2ae273 was d2ae273, checked in by Joel Sherrill <joel.sherrill@…>, on 03/05/04 at 18:06:46

2004-03-05 Joel Sherrill <joel@…>

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