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

4.104.114.84.95
Last change on this file since 80d4330 was 80d4330, checked in by Joel Sherrill <joel.sherrill@…>, on 01/08/06 at 18:07:33

2006-01-08 Joel Sherrill <joel@…>

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