OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [m68k/] [mvme167/] [network/] [network.c] - Blame information for rev 173

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.