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

4.104.114.84.95
Last change on this file since ac45548 was ac45548, checked in by Joel Sherrill <joel.sherrill@…>, on 11/01/02 at 21:50:47

2002-11-01 Joel Sherrill <joel@…>

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