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

5
Last change on this file since d8d6a08 was d8d6a08, checked in by Sebastian Huber <sebastian.huber@…>, on 01/27/18 at 10:12:44

bsps: Move network define to source files

Define INSIDE_RTEMS_BSD_TCPIP_STACK in the network interface driver
source files to avoid some build system magic.

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