source: rtems/bsps/m68k/mvme167/net/network.c @ cb68253

5
Last change on this file since cb68253 was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/18 at 04:19:02

network: Use kernel/user space header files

Add and use <machine/rtems-bsd-kernel-space.h> and
<machine/rtems-bsd-user-space.h> similar to the libbsd to avoid command
line defines and defines scattered throught the code base.

Simplify cpukit/libnetworking/Makefile.am.

Update #3375.

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