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

4.104.114.84.95
Last change on this file since df49c60 was df49c60, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/00 at 15:00:15

Merged from 4.5.0-beta3a

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