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

4.115
Last change on this file since c499856 was 26e90fb1, checked in by Sebastian Huber <sebastian.huber@…>, on 10/30/12 at 16:42:17

libnetworking: Use system events

Add reserved system events RTEMS_EVENT_SYSTEM_NETWORK_SBWAIT and
RTEMS_EVENT_SYSTEM_NETWORK_SOSLEEP.

Add and use rtems_bsdnet_event_send().

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