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

5
Last change on this file since 4c02385 was 4c02385, checked in by Christian Mauderer <Christian.Mauderer@…>, on 06/24/16 at 06:52:48

libnetworking: Import current <arpa/inet.h>

Import the <arpa/inet.h> from current FreeBSD. Necessary due to changes
in <netinet/in.h>. Remove BSD hack from <arpa/inet.h>.

Clean up problems with htonl(). These functions are defined in
<arpa/inet.h>. This lead to some problems because they are defined in
<rtems/endian.h> too. Add NTOHL, ... to
<rtems/rtems_bsdnet_internal.h>.

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