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

4.104.114.84.95
Last change on this file since 80d4330 was 80d4330, checked in by Joel Sherrill <joel.sherrill@…>, on 01/08/06 at 18:07:33

2006-01-08 Joel Sherrill <joel@…>

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