source: rtems/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.c @ f61731c

4.104.114.84.95
Last change on this file since f61731c was 7be6ad9, checked in by Eric Norum <WENorum@…>, on 10/20/04 at 15:21:05

Add MVME550 BSP

  • Property mode set to 100644
File size: 47.4 KB
Line 
1/* GT64260eth.c : GT64260 10/100 Mb ethernet MAC driver
2 *
3 * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
4 *
5 * Copyright (c) 2003,2004 RTEMS/Mvme5500 port by S. Kate Feng <feng1@bnl.gov>
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed for the NetBSD Project by
20 *      Allegro Networks, Inc., and Wasabi Systems, Inc.
21 * 4. The name of Allegro Networks, Inc. may not be used to endorse
22 *    or promote products derived from this software without specific prior
23 *    written permission.
24 * 5. The name of Wasabi Systems, Inc. may not be used to endorse
25 *    or promote products derived from this software without specific prior
26 *    written permission.
27 *
28 * S. Kate Feng, other notes in addition to porting to RTEMS :
29 *
30 * 1) Mvme5500 uses Eth0 (controller 0) of the GT64260 to implement
31 *    the 10/100 BaseT Ethernet with PCI Master Data Byte Swap\
32 *    control.
33 * 2) It implements hardware snoop instead of software snoop
34 *    to ensure SDRAM cache coherency.
35 * 3) The origianl ISR is optimized to minimize interrupt latencies,
36 *    and to reduce system overhead. The driver's work is done by one single
37 *    task who blocks on an event while it is idle.  This implemetation
38 *    is heavily inspired by the modification of SVGM network driver for
39 *    RTEMS port written by Till Straumann, whihc is licensed under the
40 *    EPICS open source. Ditto the GT64260eth_sendpacket().
41 *
42 */
43#define BYTE_ORDER BIG_ENDIAN
44
45#ifndef KERNEL
46#define KERNEL
47#endif
48
49#define INET
50
51#include <rtems.h>
52#include <rtems/bspIo.h>            /* printk */
53#include <stdio.h>                  /* printf for statistics */
54#include <string.h>
55
56#include <libcpu/io.h>              /* inp & friends */
57#include <libcpu/spr.h>             /* registers.h is included here */
58#include <bsp.h>
59
60#include <sys/param.h>
61#include <sys/systm.h>
62#include <sys/mbuf.h>
63
64#include <rtems/rtems_bsdnet.h>
65#include <rtems/rtems_bsdnet_internal.h>
66#include <rtems/error.h>           
67#include <errno.h>
68
69#include <rtems/rtems/types.h>
70
71#include <sys/queue.h>
72
73#include <sys/ioctl.h>
74#include <sys/socket.h>
75#include <sys/sockio.h>             /* SIOCADDMULTI, SIOC...     */
76#include <net/if.h>
77#include <net/if_dl.h>
78#include <netinet/in.h>
79#include <netinet/if_ether.h>
80
81#ifdef INET
82#include <netinet/in_var.h>
83#endif
84
85#include <bsp/irq.h>
86#include <bsp/GT64260ethreg.h>
87#include <bsp/GT64260eth.h>
88#include <bsp/VPD.h>
89
90#define GT_ETH_TASK_NAME  "Geth"
91#define PKT_BUF_SZ 1536
92#define SOFTC_ALIGN  31   
93#define HASH_ALIGN   15   
94
95#define TXQ_HiLmt_OFF 2
96
97/* <skf>
98 * 1. printk debug is for diagnosis only, which may cause
99 * unexpected result, especially if txq is under heavy load
100 * because CPU is fast with a decent cache.
101 */
102#define GTeth_debug 0
103#define GTeth_rx_debug 0
104
105#if 0
106#define GE_FORGOT
107#define GE_NORX
108#define GT_DEBUG
109#endif
110
111/* RTEMS event to kill the daemon */
112#define KILL_EVENT              RTEMS_EVENT_1
113/* RTEMS event to (re)start the transmitter */
114#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
115/* RTEMS events used by the ISR */
116#define RX_EVENT                RTEMS_EVENT_3
117#define TX_EVENT                RTEMS_EVENT_4
118#define ERR_EVENT               RTEMS_EVENT_5
119
120#define ALL_EVENTS (KILL_EVENT|START_TRANSMIT_EVENT|RX_EVENT|TX_EVENT|ERR_EVENT)
121
122enum GTeth_whack_op {
123        GE_WHACK_START,         GE_WHACK_RESTART,
124        GE_WHACK_CHANGE,        GE_WHACK_STOP
125};
126
127enum GTeth_hash_op {
128        GE_HASH_ADD,            GE_HASH_REMOVE,
129};
130
131#define ET_MINLEN 64            /* minimum message length */
132
133static int GTeth_ifioctl(struct ifnet *ifp,unsigned cmd, caddr_t data);
134static void GTeth_ifstart (struct ifnet *);
135static void GTeth_ifchange(struct GTeth_softc *sc);
136static void GTeth_init_rx_ring(struct GTeth_softc *sc);
137static void GT64260eth_daemon(void *arg);
138static int GT64260eth_sendpacket(struct GTeth_softc *sc,struct mbuf *m,enum GTeth_txprio);
139static unsigned GTeth_txq_done(struct GTeth_softc *sc, enum GTeth_txprio txprio);
140static void GTeth_tx_cleanup(struct GTeth_softc *sc, enum GTeth_txprio, int);
141static void GTeth_tx_start(struct GTeth_softc *sc, enum GTeth_txprio);
142static void GTeth_tx_stop(struct GTeth_softc *sc, enum GTeth_whack_op op);
143static void GTeth_rx_cleanup(struct GTeth_softc *sc, enum GTeth_rxprio);
144static int GT64260eth_rx(struct GTeth_softc *sc, enum GTeth_rxprio);
145static void GTeth_rx_setup(struct GTeth_softc *sc);
146static void GTeth_rxprio_setup(struct GTeth_softc *sc, enum GTeth_rxprio);
147static void GTeth_rx_stop(struct GTeth_softc *dc, enum GTeth_whack_op op);
148static void GT64260eth_isr();
149static int GTeth_hash_compute(struct GTeth_softc *sc,unsigned char eaddr[ETHER_ADDR_LEN]);
150static int GTeth_hash_entry_op(struct GTeth_softc *sc, enum GTeth_hash_op op,
151        enum GTeth_rxprio prio,unsigned char eaddr[ETHER_ADDR_LEN]);
152
153static int GTeth_hash_fill(struct GTeth_softc *sc);
154static void GTeth_hash_init(struct GTeth_softc *sc);
155
156static struct GTeth_softc *root_GT64260eth_dev = NULL;
157static int GTeth_MissedFrame_err=0; 
158
159/*
160 * Convert Ethernet address to printable (loggable) representation.
161 */
162static const char digits[] = "0123456789abcdef";
163char * ether_sprintf(unsigned char *ap)
164{
165  int i;
166  static char etherbuf[18];
167  char *cp = etherbuf;
168
169  for (i = 0; i < 6; i++) {
170      *cp++ = digits[*ap >> 4];
171      *cp++ = digits[*ap++ & 0xf];
172      *cp++ = ':';
173  }
174  *--cp = 0;
175  return (etherbuf);
176}
177
178/* We can hard code the address here if config->hardware_address failed */
179static int GTethGet_macaddr(int macno, char *hwaddr)
180{
181  hwaddr[0] = 0x00;
182  hwaddr[1] = 0x01;
183  hwaddr[2] = 0xaf;
184  hwaddr[3] = 0x0b;
185  hwaddr[4] = 0x75;
186  hwaddr[5] = 0x36;
187
188  return 0;
189}
190
191static void GT64260eth_irq_on(const rtems_irq_connect_data *irq)
192{
193  struct GTeth_softc *sc;
194
195  for (sc= root_GT64260eth_dev; sc; sc= sc-> next_module) {
196    printk("GT64260eth_irq_on\n");
197    outl(0x30883444,ETH0_EIMR); /* MOTLoad default interrupt mask */
198    return;
199  }
200}
201
202static void GT64260eth_irq_off(const rtems_irq_connect_data *irq)
203{
204  struct GTeth_softc *sc;
205
206  for (sc= root_GT64260eth_dev; sc; sc= sc-> next_module)
207      outl(0, ETH0_EIMR);
208}
209
210static int GT64260eth_irq_is_on(const rtems_irq_connect_data *irq)
211{
212  return(inl(ETH0_EICR) & ETH_IR_EtherIntSum);
213}
214
215static void GT64260eth_isr()
216{
217  struct GTeth_softc *sc = root_GT64260eth_dev;
218  rtems_event_set  events=0;
219  uint32_t cause;
220
221
222  cause = inl(ETH0_EICR);
223  outl( ~cause,ETH0_EICR);  /* clear the ICR */
224
225  if (cause & (ETH_IR_RxBuffer_3|ETH_IR_RxError_3)) {
226     sc->stats.rxInterrupts++;
227     events |= RX_EVENT;
228  }
229  /* If there is an error, we want to continue to next descriptor */
230  if (cause & (ETH_IR_TxBufferHigh|ETH_IR_TxEndHigh|ETH_IR_TxErrorHigh)) {
231       sc->stats.txInterrupts++;
232       events |= TX_EVENT;
233       if ((sc->txq_nactive) && ((inl(ETH0_ESDCMR)&ETH_ESDCMR_TXDH)==0))
234          outl(ETH_ESDCMR_TXDH | ETH_ESDCMR_ERD,ETH0_ESDCMR);
235  }
236  if ( (!cause) || (cause & 0x803d00)) {
237       sc->intr_errsts[sc->intr_err_ptr2++]=cause;
238       sc->intr_err_ptr2 %=INTR_ERR_SIZE;   /* Till Straumann */
239       events |= ERR_EVENT;
240  }
241
242  rtems_event_send(sc->daemonTid, events);
243}
244
245static rtems_irq_connect_data GT64260ethIrqData={
246        BSP_MAIN_ETH0_IRQ,
247        (rtems_irq_hdl) GT64260eth_isr,
248        (rtems_irq_enable) GT64260eth_irq_on,
249        (rtems_irq_disable) GT64260eth_irq_off,
250        (rtems_irq_is_enabled) GT64260eth_irq_is_on,
251};
252
253static void GT64260eth_init_hw(struct GTeth_softc *sc)
254{
255
256#ifdef GT_DEBUG
257  printk("GT64260eth_init_hw(");
258#endif
259  /* Kate Feng : Turn the hardware snoop on as MOTLoad did not have
260   * it on by default.
261   */
262  outl(RxBSnoopEn|TxBSnoopEn|RxDSnoopEn|TxDSnoopEn, GT_CUU_Eth0_AddrCtrlLow);
263  outl(HashSnoopEn, GT_CUU_Eth0_AddrCtrlHigh);
264
265  sc->rxq_intrbits=0;
266  sc->sc_flags=0;
267 
268#ifndef GE_NORX
269  GTeth_rx_setup(sc);
270#endif
271
272#ifndef GE_NOTX
273  GTeth_tx_start(sc, GE_TXPRIO_HI);
274#endif
275
276  sc->sc_pcr |= ETH_EPCR_HS_512;
277  outl(sc->sc_pcr, ETH0_EPCR);
278  outl(sc->sc_pcxr, ETH0_EPCXR); /* port config. extended reg. */
279  outl(0, ETH0_EICR); /* interrupt cause register */
280  outl(sc->sc_intrmask, ETH0_EIMR);
281#ifndef GE_NOHASH
282  /* Port Hash Table Pointer Reg*/
283  outl(((unsigned) sc->sc_hashtable),ETH0_EHTPR);
284#endif
285#ifndef GE_NORX
286  outl(ETH_ESDCMR_ERD,ETH0_ESDCMR); /* enable Rx DMA in SDMA Command Register */
287  sc->sc_flags |= GE_RXACTIVE;
288#endif
289#ifdef GT_DEBUG
290  printk("SDCMR 0x%x ", inl(ETH0_ESDCMR));
291#endif
292
293  /* connect the interrupt handler which should
294   * take care of enabling interrupts
295   */
296  if (!BSP_install_rtems_irq_handler(&GT64260ethIrqData))
297     rtems_panic("GT64260eth: unable to install ISR");
298   
299  /* The ethernet port is ready to transmit/receive */
300  outl(sc->sc_pcr | ETH_EPCR_EN, ETH0_EPCR);
301
302#ifdef GT_DEBUG
303  printk(")\n");
304#endif
305}
306
307static void GT64260eth_stop_hw(struct GTeth_softc *sc)
308{
309
310  printk("GT64260eth_stop_hw(");
311
312  /* remove our interrupt handler which will also
313  * disable interrupts at the MPIC and the device
314  * itself
315  */
316  if (!BSP_remove_rtems_irq_handler(&GT64260ethIrqData))
317     rtems_panic("Yellowfin: unable to remove IRQ handler!");
318
319  outl(sc->sc_pcr, ETH0_EPCR);
320  outl(0, ETH0_EIMR);
321
322  sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
323#ifndef GE_NOTX
324  GTeth_tx_stop(sc, GE_WHACK_STOP);
325#endif
326#ifndef GE_NORX
327  GTeth_rx_stop(sc, GE_WHACK_STOP);
328#endif
329  sc->sc_hashtable = NULL;
330  if (GTeth_debug>0) printk(")");
331}
332
333static void GT64260eth_stop(struct GTeth_softc *sc)
334{
335  if (GTeth_debug>0) printk("GT64260eth_stop(");
336
337  /* The hardware is shutdown in the daemon */
338  /* kill the daemon. We also must release the networking
339   * semaphore or there'll be a deadlock...
340   */
341  rtems_event_send(sc->daemonTid, KILL_EVENT);
342  rtems_bsdnet_semaphore_release();
343
344  sc->daemonTid=0;
345  /* now wait for it to die */
346  rtems_semaphore_obtain(sc->daemonSync,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
347
348  /* reacquire the bsdnet semaphore */
349  rtems_bsdnet_semaphore_obtain();
350  if (GTeth_debug>0) printk(")");
351}
352
353static void GT64260eth_ifinit(void *arg)
354{
355  struct GTeth_softc *sc = (struct GTeth_softc*)arg;
356  int i;
357
358#ifdef GT_DEBUG
359  printk("GT64260eth_ifinit(): daemon ID: 0x%08x)\n", sc->daemonTid);
360#endif
361  if (sc->daemonTid) {
362#ifdef GT_DEBUG
363     printk("GT64260eth: daemon already up, doing nothing\n");
364#endif
365     return;
366  }
367
368#ifndef GE_NOHASH
369  /* Mvme5500, the user must initialize the hash table before enabling the
370   * Ethernet controller
371   */
372  GTeth_hash_init(sc);
373  GTeth_hash_fill(sc);
374#endif
375
376  sc->intr_err_ptr1=0;
377  sc->intr_err_ptr2=0;
378  for (i=0; i< INTR_ERR_SIZE; i++) sc->intr_errsts[i]=0;
379
380  /* initialize the hardware (we are holding the network semaphore at this point) */
381  (void)GT64260eth_init_hw(sc);
382
383  /* launch network daemon */
384
385  /* NOTE:
386   * in ss-20011025 (and later) any task created by 'bsdnet_newproc' is
387   * wrapped by code which acquires the network semaphore...
388   */
389   sc->daemonTid = rtems_bsdnet_newproc(GT_ETH_TASK_NAME,4096,GT64260eth_daemon,arg);
390
391  /* Tell the world that we're running */
392  sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
393
394}
395
396/* attach parameter tells us whether to attach or to detach the driver */
397/* Attach this instance, and then all the sub-devices */
398int rtems_GT64260eth_driver_attach(struct rtems_bsdnet_ifconfig *config, int attach)
399{
400  struct GTeth_softc *sc;
401  struct ifnet *ifp;
402  unsigned sdcr, data;
403  unsigned char hwaddr[6];
404  int i, unit, phyaddr;
405  void     *softc_mem;
406  char     *name;
407
408  unit = rtems_bsdnet_parse_driver_name(config, &name);
409  if (unit < 0) return 0;
410 
411  printk("\nEthernet driver name %s unit %d \n",name, unit);
412  printk("Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.\n");
413  printk("(c) 2004, Brookhaven National Lab. <feng1@bnl.gov> (RTEMS/mvme5500 port)\n");
414
415  /* Make certain elements e.g. descriptor lists are aligned. */
416  softc_mem = rtems_bsdnet_malloc(sizeof(*sc) + SOFTC_ALIGN, M_FREE, M_NOWAIT);
417
418  /* Check for the very unlikely case of no memory. */
419  if (softc_mem == NULL)
420     rtems_panic("GT64260eth: OUT OF MEMORY");
421
422  sc = (void *)(((long)softc_mem + SOFTC_ALIGN) & ~SOFTC_ALIGN);
423  memset(sc, 0, sizeof(*sc));
424
425  if (GTeth_debug>0) printk("txq_desc[0] addr:%x, rxq_desc[0] addr:%x, sizeof sc %d\n",&sc->txq_desc[0], &sc->rxq_desc[0], sizeof(*sc));
426
427  sc->sc_macno = unit-1;
428
429  data = inl(ETH_EPAR);
430  phyaddr = ETH_EPAR_PhyAD_GET(data, sc->sc_macno);
431
432  /* try to read HW address from the device if not overridden
433   * by config
434   */
435  if (config->hardware_address) {
436     memcpy(hwaddr, config->hardware_address, ETHER_ADDR_LEN);
437  } else {
438    printk("Read EEPROM ");
439     for (i = 0; i < 6; i++)
440       hwaddr[i] = ConfVPD_buff[VPD_ENET0_OFFSET+i];
441  }
442
443#ifdef GT_DEBUG
444  printk("using MAC addr from device:");
445  for (i = 0; i < ETHER_ADDR_LEN; i++) printk("%x:", hwaddr[i]);
446  printk("\n");
447#endif
448
449  memcpy(sc->arpcom.ac_enaddr, hwaddr, ETHER_ADDR_LEN);
450
451  ifp = &sc->arpcom.ac_if;
452
453  sc->sc_pcr = inl(ETH0_EPCR);
454  sc->sc_pcxr = inl(ETH0_EPCXR);
455  sc->sc_intrmask = inl(ETH0_EIMR) | ETH_IR_MIIPhySTC;
456
457  printk("address %s\n", ether_sprintf(hwaddr));
458
459#ifdef GT_DEBUG
460  printk(", pcr %x, pcxr %x ", sc->sc_pcr, sc->sc_pcxr);
461#endif
462
463
464  sc->sc_pcxr |= ETH_EPCXR_PRIOrx_Override;
465  sc->sc_pcxr |= (3<<6); /* highest priority only */
466  sc->sc_pcxr &= ~ETH_EPCXR_RMIIEn;  /* MII mode */
467
468  /* Max. Frame Length (packet) allowed for reception is 1536 bytes,
469   * instead of 2048 (MOTLoad default) or 64K.
470   */
471  sc->sc_pcxr &= ~(3 << 14);
472  sc->sc_pcxr |= (ETH_EPCXR_MFL_1536 << 14);
473  sc->sc_max_frame_length = PKT_BUF_SZ;
474
475
476  if (sc->sc_pcr & ETH_EPCR_EN) {
477      int tries = 1000;
478      /* Abort transmitter and receiver and wait for them to quiese*/
479      outl(ETH_ESDCMR_AR|ETH_ESDCMR_AT,ETH0_ESDCMR);
480      do {
481        rtems_bsp_delay(100);
482      } while (tries-- > 0 && (inl(ETH0_ESDCMR) & (ETH_ESDCMR_AR|ETH_ESDCMR_AT)));
483  }
484#ifdef GT_DEBUG
485  printk(", phy %d (mii)\n", phyaddr);
486  printk("ETH0_ESDCMR %x ", inl(ETH0_ESDCMR));
487#endif
488
489  sc->sc_pcr &= ~(ETH_EPCR_EN | ETH_EPCR_RBM | ETH_EPCR_PM | ETH_EPCR_PBF);
490
491#ifdef GT_DEBUG
492        printk("Now sc_pcr %x,sc_pcxr %x", sc->sc_pcr, sc->sc_pcxr);
493#endif
494
495  /*
496   * Now turn off the GT.  If it didn't quiese, too ***ing bad.
497   */
498  outl(sc->sc_pcr, ETH0_EPCR);
499  outl(sc->sc_intrmask, ETH0_EIMR);
500  sdcr = inl(ETH0_ESDCR);
501  /* Burst size is limited to 4 64bit words */
502  ETH_ESDCR_BSZ_SET(sdcr, ETH_ESDCR_BSZ_4);
503  sdcr |= ETH_ESDCR_RIFB;/*limit interrupt on frame boundaries, instead of buffer*/
504#if 0
505  sdcr &= ~(ETH_ESDCR_BLMT|ETH_ESDCR_BLMR); /* MOTLoad defualt Big-endian */
506#endif
507  outl(sdcr, ETH0_ESDCR);
508
509#ifdef GT_DEBUG
510  printk("sdcr %x \n", sdcr);
511#endif
512
513  if (phyaddr== -1) rtems_panic("MII auto negotiation ?");
514
515  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
516
517  ifp->if_softc = sc;
518
519  /* set this interface's name and unit */
520  ifp->if_unit = unit;
521  ifp->if_name = name;
522
523  ifp->if_mtu = config->mtu ? config->mtu : ETHERMTU;
524
525  ifp->if_init = GT64260eth_ifinit;
526  ifp->if_ioctl = GTeth_ifioctl;
527  ifp->if_start = GTeth_ifstart;
528  ifp->if_output = ether_output;
529
530  /*  ifp->if_watchdog = GTeth_ifwatchdog;*/
531
532  if (ifp->if_snd.ifq_maxlen == 0)
533    ifp->if_snd.ifq_maxlen = ifqmaxlen;
534
535  /* create the synchronization semaphore */
536  if (RTEMS_SUCCESSFUL != rtems_semaphore_create(
537     rtems_build_name('G','e','t','h'),0,0,0,&sc->daemonSync))
538     rtems_panic("GT64260eth: semaphore creation failed");
539
540  sc->next_module = root_GT64260eth_dev;
541  root_GT64260eth_dev = sc;
542
543  /* Actually attach the interface */
544  if_attach(ifp);
545  ether_ifattach(ifp);
546
547#ifdef GT_DEBUG
548  printk("GT64260eth: Ethernet driver has been attached (handle 0x%08x,ifp 0x%08x)\n",sc, ifp);
549#endif
550
551  return(1);
552}
553
554static void GT64260eth_stats(struct GTeth_softc *sc)
555{
556  struct ifnet *ifp = &sc->arpcom.ac_if;
557
558  printf("       Rx Interrupts:%-8lu\n", sc->stats.rxInterrupts);
559  printf("     Receive Packets:%-8lu\n", ifp->if_ipackets);
560  printf("     Receive  errors:%-8lu\n", ifp->if_ierrors);
561  printf(" Missed Frame errors:%-8lu\n", GTeth_MissedFrame_err);
562  printf("      Framing Errors:%-8lu\n", sc->stats.frame_errors);
563  printf("          Crc Errors:%-8lu\n", sc->stats.crc_errors);
564  printf("    Oversized Frames:%-8lu\n", sc->stats.length_errors);
565  printf("         Active Rxqs:%-8lu\n", sc->rxq_active);
566  printf("       Tx Interrupts:%-8lu\n", sc->stats.txInterrupts);
567  printf("Multi-Buffer Packets:%-8lu\n", sc->stats.txMultiBuffPacket);
568  printf("   Transmitt Packets:%-8lu\n", ifp->if_opackets);
569  printf("   Transmitt  errors:%-8lu\n", ifp->if_oerrors);
570  printf("    Tx/Rx collisions:%-8lu\n", ifp->if_collisions);
571  printf("         Active Txqs:%-8lu\n", sc->txq_nactive);
572}
573
574GT64260eth_err()
575{
576  printf(" Missed Frame errors:%-8lu\n", GTeth_MissedFrame_err);
577}
578
579static int GTeth_ifioctl(struct ifnet *ifp,unsigned cmd, caddr_t data)
580{
581  struct GTeth_softc *sc = ifp->if_softc;
582  struct ifreq *ifr = (struct ifreq *) data;
583
584  int error = 0;
585
586#ifdef GT_DEBUG
587  printk("GTeth_ifioctl(");
588#endif
589
590  switch (cmd) {
591    default:
592      if (GTeth_debug >0) {
593         printk("etherioctl(");
594         if (cmd== SIOCSIFADDR) printk("SIOCSIFADDR ");
595      }
596      return ether_ioctl(ifp, cmd, data);
597
598    case SIOCSIFFLAGS:
599       switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
600            case IFF_RUNNING:   /* not up, so we stop */
601                 GT64260eth_stop(sc);
602                 break;
603            case IFF_UP:  /* not running, so we start */
604                 GT64260eth_ifinit(sc);
605                 break;
606            case IFF_UP|IFF_RUNNING:/* active->active, update */
607                 GT64260eth_stop(sc);
608                 GT64260eth_ifinit(sc);
609                 break;
610            default:                    /* idle->idle: do nothing */
611                 break;
612       }
613       break;
614    case SIO_RTEMS_SHOW_STATS:
615       GT64260eth_stats (sc);
616       break;
617    case SIOCADDMULTI:
618    case SIOCDELMULTI:
619       error = (cmd == SIOCADDMULTI)
620                  ? ether_addmulti(ifr, &sc->arpcom)
621                  : ether_delmulti(ifr, &sc->arpcom);
622       if (error == ENETRESET) {
623           if (ifp->if_flags & IFF_RUNNING)
624              GTeth_ifchange(sc);
625              error = 0;
626       }
627       break;
628    case SIOCSIFMTU:
629       if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
630          error = EINVAL;
631          break;
632       }
633       ifp->if_mtu = ifr->ifr_mtu;
634       break;
635  }
636
637#ifdef GT_DEBUG
638  printk("exit ioctl\n");
639#endif 
640  return error;
641}
642
643static void GTeth_ifstart(struct ifnet *ifp)
644{
645  struct GTeth_softc *sc = ifp->if_softc;
646
647#ifdef GT_DEBUG
648  printk("GTeth_ifstart(");
649#endif
650
651  if ((ifp->if_flags & IFF_RUNNING) == 0) {
652#ifdef GT_DEBUG
653     printk("IFF_RUNNING==0\n");
654#endif         
655     return;
656  }
657
658  ifp->if_flags |= IFF_OACTIVE;
659  rtems_event_send (sc->daemonTid, START_TRANSMIT_EVENT);
660#ifdef GT_DEBUG
661  printk(")\n");
662#endif
663}
664
665/* Initialize the Rx rings */
666static void GTeth_init_rx_ring(struct GTeth_softc *sc)
667{
668  int i;
669  volatile struct GTeth_desc *rxd;
670  unsigned nxtaddr;
671
672  sc->rxq_fi=0;
673  sc->rxq_head_desc = &sc->rxq_desc[0];
674  rxd = sc->rxq_head_desc;
675
676  sc->rxq_desc_busaddr = sc->rxq_head_desc;
677#ifdef GT_DEBUG
678  printk("rxq_desc_busaddr %x ,&sc->rxq_desc[0] %x\n",
679        sc->rxq_desc_busaddr, sc->rxq_head_desc);
680#endif
681
682  nxtaddr = sc->rxq_desc_busaddr + sizeof(*rxd);
683  sc->rx_buf_sz = (sc->arpcom.ac_if.if_mtu <= 1500 ? PKT_BUF_SZ : sc->arpcom.ac_if.if_mtu + 32);
684  sc->rxq_active = RX_RING_SIZE;
685
686  for (i = 0; i < RX_RING_SIZE; i++, rxd++, nxtaddr += sizeof(*rxd)) {
687    struct mbuf *m;
688 
689    rxd->ed_lencnt= sc->rx_buf_sz <<16;
690    rxd->ed_cmdsts = RX_CMD_F|RX_CMD_L|RX_CMD_O|RX_CMD_EI;
691
692    MGETHDR(m, M_WAIT, MT_DATA);
693    MCLGET(m, M_WAIT);
694    m->m_pkthdr.rcvif =  &sc->arpcom.ac_if;
695    sc->rxq_mbuf[i] = m;
696
697    /* convert mbuf pointer to data pointer of correct type */ 
698    rxd->ed_bufptr = mtod(m, void *);
699
700    /*
701     * update the nxtptr to point to the next txd.
702     */
703    if (i == RX_RING_SIZE - 1)
704        nxtaddr = sc->rxq_desc_busaddr;
705    rxd->ed_nxtptr = nxtaddr;
706
707#ifdef GT_DEBUG
708  printk("ed_lencnt %x, rx_buf_sz %x ",rxd->ed_lencnt, sc->rx_buf_sz);
709  printk("ed_cmdsts %x \n",rxd->ed_cmdsts);
710  printk("mbuf @ 0x%x, next desc. @ 0x%x\n",rxd->ed_bufptr,rxd->ed_nxtptr);
711#endif
712  }
713}
714
715static void GTeth_rxprio_setup(struct GTeth_softc *sc, enum GTeth_rxprio rxprio)
716{
717
718  if (GTeth_debug>0) printk("GTeth_rxprio_setup(\n");
719  GTeth_init_rx_ring(sc);
720
721  sc->rxq_intrbits = ETH_IR_RxBuffer | ETH_IR_RxError;
722
723  switch (rxprio) {
724    case GE_RXPRIO_HI:
725      sc->rxq_intrbits |= ETH_IR_RxBuffer_3|ETH_IR_RxError_3;
726         break;
727    case GE_RXPRIO_MEDHI:
728         sc->rxq_intrbits |= ETH_IR_RxBuffer_2|ETH_IR_RxError_2;
729         break;
730    case GE_RXPRIO_MEDLO:
731         sc->rxq_intrbits |= ETH_IR_RxBuffer_1|ETH_IR_RxError_1;
732         break;
733    case GE_RXPRIO_LO:
734         sc->rxq_intrbits |= ETH_IR_RxBuffer_0|ETH_IR_RxError_0;
735         break;
736  }
737  if (GTeth_debug>0) printk(")");
738}
739
740static int GT64260eth_rx(struct GTeth_softc *sc, enum GTeth_rxprio rxprio)
741{
742  struct ifnet *ifp = &sc->arpcom.ac_if;
743  struct mbuf *m;
744  int nloops=0;
745  unsigned int intr_status = sc->intr_errsts[sc->intr_err_ptr1];
746
747  if (GTeth_rx_debug>0) printk("GT64260eth_rx(");
748  if (GTeth_rx_debug>5) printk("(%d)", rxprio);
749
750  while (sc->rxq_active > 0) {
751    volatile struct GTeth_desc *rxd = &sc->rxq_desc[sc->rxq_fi];
752    struct ether_header *eh;
753    unsigned int cmdsts;
754    unsigned int byteCount;
755
756    cmdsts = rxd->ed_cmdsts;
757
758    /*
759     * Sometimes the GE "forgets" to reset the ownership bit.
760     * But if the length has been rewritten, the packet is ours
761     * so pretend the O bit is set.
762     *
763     */
764    byteCount = rxd->ed_lencnt & 0xffff;
765
766    if (cmdsts & RX_CMD_O) {
767      if (byteCount == 0)
768         return(0);
769
770     /* <Kate Feng> Setting command/status to be zero seems to eliminate
771      * the spurious interrupt associated with the GE_FORGOT issue.
772      */
773      rxd->ed_cmdsts=0;
774
775#ifdef GE_FORGOT
776      /*
777       * For dignosis purpose only. Not a good practice to turn it on
778       */
779      printk("Rxq %d %d %d\n", sc->rxq_fi, byteCount,nloops);
780#endif
781    }
782
783    /* GT gave the ownership back to the CPU or the length has
784     * been rewritten , which means there
785     * is new packet in the descriptor/buffer
786     */
787
788    if (GTeth_rx_debug>0) printk("desc%d: cmdsts=%x, len=%d\n",
789           sc->rxq_fi,cmdsts,byteCount);
790    nloops++;
791    /*
792     * If this is not a single buffer packet with no errors
793     * or for some reason it's bigger than our frame size,
794     * ignore it and go to the next packet.
795     */
796    if ((cmdsts & (RX_CMD_F|RX_CMD_L|RX_STS_ES)) !=
797                            (RX_CMD_F|RX_CMD_L) ||
798                    byteCount > sc->sc_max_frame_length) {
799        if (GTeth_rx_debug>0) printk("Rx Error");
800        --sc->rxq_active;
801        ifp->if_ipackets++;
802        ifp->if_ierrors++;
803        if (cmdsts & RX_STS_OR) sc->stats.or_errors++;
804        if (cmdsts & RX_STS_CE) sc->stats.crc_errors++;
805        if (cmdsts & RX_STS_MFL) sc->stats.length_errors++;
806        if (cmdsts & RX_STS_SF) sc->stats.frame_errors++;
807        /*      if (cmdsts & RX_STS_M) GTeth_MissedFrame_err++;*/
808        if ((cmdsts & RX_STS_LC) || (cmdsts & RX_STS_COL))
809           ifp->if_collisions++;
810        goto give_it_back;
811     }
812
813     m = sc->rxq_mbuf[sc->rxq_fi];
814     sc->rxq_mbuf[sc->rxq_fi] = NULL;
815     m->m_len = m->m_pkthdr.len = byteCount - sizeof(struct ether_header);
816     eh = mtod (m, struct ether_header *);
817     m->m_data += sizeof(struct ether_header);
818     ether_input (ifp, eh, m);
819     if (GTeth_rx_debug>20) {
820       if ( m->m_flags & M_BCAST ) printk("desc%d broadcast\n",sc->rxq_fi);
821       if ( m->m_flags & M_MCAST ) printk("multicast ");
822     }
823
824     ifp->if_ipackets++;
825     ifp->if_ibytes+=byteCount;
826     --sc->rxq_active;
827
828     give_it_back:
829     MGETHDR (m, M_WAIT, MT_DATA);
830     MCLGET (m, M_WAIT);
831     m->m_pkthdr.rcvif = ifp;
832     sc->rxq_mbuf[sc->rxq_fi]= m;
833     /* convert mbuf pointer to data pointer of correct type */
834     rxd->ed_bufptr = mtod(m, void*);
835     rxd->ed_lencnt = (unsigned long) sc->rx_buf_sz <<16;
836     rxd->ed_cmdsts = RX_CMD_F|RX_CMD_L|RX_CMD_O|RX_CMD_EI;
837
838     if (++sc->rxq_fi == RX_RING_SIZE) sc->rxq_fi = 0;
839
840     sc->rxq_active++;
841  } /* while (sc->rxq_active > 0) */
842  if (GTeth_rx_debug>0) printk(")");
843  return nloops;
844}
845
846static void GTeth_rx_setup(struct GTeth_softc *sc)
847{
848
849  if (GTeth_rx_debug>0) printk("GTeth_rx_setup(");
850
851  GTeth_rxprio_setup(sc, GE_RXPRIO_HI);
852
853  if ((sc->sc_flags & GE_RXACTIVE) == 0) {
854     /* First Rx Descriptor Pointer 3 */
855     outl( sc->rxq_desc_busaddr, ETH0_EFRDP3);
856     /* Current Rx Descriptor Pointer 3 */
857     outl( sc->rxq_desc_busaddr,ETH0_ECRDP3);
858#ifdef GT_DEBUG
859     printk("ETH0_EFRDP3 0x%x, ETH0_ECRDP3 0x%x \n", inl(ETH0_EFRDP3),
860            inl(ETH0_ECRDP3));
861#endif
862  }
863  sc->sc_intrmask |= sc->rxq_intrbits;
864
865  if (GTeth_rx_debug>0) printk(")\n");
866}
867
868static void GTeth_rx_cleanup(struct GTeth_softc *sc, enum GTeth_rxprio rxprio)
869{
870  int i;
871
872  if (GTeth_rx_debug>0) printk( "GTeth_rx_cleanup(");
873  if (sc->rxq_curpkt)
874     m_freem(sc->rxq_curpkt);
875
876  for (i=0; i< RX_RING_SIZE; i++) {
877    if (sc->rxq_mbuf[i]) {
878      m_freem(sc->rxq_mbuf[i]);
879      sc->rxq_mbuf[i]=0;
880    }
881  }
882  if (GTeth_rx_debug>0) printk(")");
883}
884
885static void GTeth_rx_stop(struct GTeth_softc *sc, enum GTeth_whack_op op)
886{
887  if (GTeth_rx_debug>0) printk( "GTeth_rx_stop(");
888  sc->sc_flags &= ~GE_RXACTIVE;
889  sc->sc_idlemask &= ~(ETH_IR_RxBits|ETH_IR_RxBuffer_3|ETH_IR_RxError_3);
890  sc->sc_intrmask &= ~(ETH_IR_RxBits|ETH_IR_RxBuffer_3|ETH_IR_RxError_3);
891  outl(sc->sc_intrmask, ETH0_EIMR);
892  outl(ETH_ESDCMR_AR, ETH0_ESDCMR); /* abort receive */
893  do {
894     rtems_bsp_delay(10);
895  } while (inl(ETH0_ESDCMR) & ETH_ESDCMR_AR);
896  GTeth_rx_cleanup(sc, GE_RXPRIO_HI);
897  if (GTeth_rx_debug>0) printk(")");
898}
899
900static void GTeth_txq_free(struct GTeth_softc *sc, unsigned cmdsts)
901{
902  struct ifnet *ifp = &sc->arpcom.ac_if;
903  volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_fi];
904
905  /* ownership is sent back to CPU */
906  if (GTeth_debug>0) printk("txq%d,active %d\n", sc->txq_fi, sc->txq_nactive);
907
908  txd->ed_cmdsts &= ~TX_CMD_O; /* <skf> in case GT forgot */
909
910  /* statistics */
911  ifp->if_opackets++;
912  ifp->if_obytes += sc->txq_mbuf[sc->txq_fi]->m_len;
913  if (cmdsts & TX_STS_ES) {
914       ifp->if_oerrors++;
915       if ((cmdsts & TX_STS_LC) || (cmdsts & TX_STS_COL))
916           ifp->if_collisions++;
917  }
918  /* Free the original mbuf chain */
919  m_freem(sc->txq_mbuf[sc->txq_fi]);
920  sc->txq_mbuf[sc->txq_fi] = 0;
921  ifp->if_timer = 5;
922
923  sc->txq_free++;
924  if (++sc->txq_fi == TX_RING_SIZE) sc->txq_fi = 0;
925  --sc->txq_nactive;
926}
927
928static int txq_high_limit(struct GTeth_softc *sc)
929{
930  /*
931   * Have we [over]consumed our limit of descriptors?
932   * Do we have enough free descriptors?
933   */
934  if ( TX_RING_SIZE == sc->txq_nactive + TXQ_HiLmt_OFF) {
935     volatile struct GTeth_desc *txd2 = &sc->txq_desc[sc->txq_fi];
936     unsigned cmdsts;
937
938     cmdsts = txd2->ed_cmdsts;
939     if (cmdsts & TX_CMD_O) {  /* Ownership (1=GT 0=CPU) */
940         int nextin;
941
942         /*
943          * Sometime the Discovery forgets to update the
944          * last descriptor.  See if CPU owned the descriptor
945          * after it (since we know we've turned that to
946          * the discovery and if CPU owned it, the Discovery
947          * gave it back).  If CPU does, we know the Discovery
948          * gave back this one but forgot to mark it back to CPU.
949          */
950         nextin = (sc->txq_fi + 1) % TX_RING_SIZE;
951         if (sc->txq_desc[nextin].ed_cmdsts & TX_CMD_O) {
952#if 0
953            printk("Overconsuming Tx descriptors!\n");
954#endif
955            return 1;
956         }
957         printk("Txq %d forgot\n", sc->txq_fi);
958     }
959    /* Txq ring is almost full, let's free the current buffer here */
960#if 0
961    printk("Txq ring near full, free desc%d\n",sc->txq_fi);
962#endif
963    GTeth_txq_free(sc, cmdsts);
964  } /* end if ( TX_RING_SIZE == sc->txq_nactive + TXQ_HiLmt_OFF) */
965  return 0;
966}
967
968static int GT64260eth_sendpacket(struct GTeth_softc *sc,struct mbuf *m, enum GTeth_txprio txprio)
969{
970  struct ifnet *ifp=&sc->arpcom.ac_if;
971  volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_lo];
972  unsigned intrmask = sc->sc_intrmask;
973  unsigned index= sc->txq_lo;
974
975  if (GTeth_debug>0) printk("sendpacket(");
976
977  /*
978   * The end-of-list descriptor we put on last time is the starting point
979   * for this packet.  The GT is supposed to terminate list processing on
980   * a NULL nxtptr but that currently is broken so a CPU-owned descriptor
981   * must terminate the list.
982   */
983  intrmask = sc->sc_intrmask;
984
985  if ( !(m->m_next)) /* single buffer packet */
986    sc->txq_mbuf[index]= m;
987  else /* multiple mbufs in this packet */
988  {
989    struct mbuf *mtp, *mdest;
990    volatile unsigned char *pt;
991    int len, y;
992
993#ifdef GT_DEBUG
994    printk("multi mbufs ");
995#endif   
996    MGETHDR(mdest, M_WAIT, MT_DATA);
997    MCLGET(mdest, M_WAIT);
998    pt = (volatile unsigned char *)mdest->m_data;
999    for (mtp=m,len=0;mtp;mtp=mtp->m_next) {
1000      if ( (y=(len+mtp->m_len)) > sizeof(union mcluster)) {
1001        /* GT64260 allows us to chain the remaining to the nex
1002         * free descriptors.
1003         */
1004        printk("packet size %x > mcluster %x\n", y,sizeof(union mcluster));
1005        rtems_panic("GT64260eth : packet too large ");
1006      }
1007      memcpy((void *)pt,(char *)mtp->m_data, mtp->m_len);
1008      pt += mtp->m_len;
1009#if 0
1010      printk("%d ",mtp->m_len);
1011#endif
1012      len += mtp->m_len;
1013    }
1014#if 0
1015    printk("\n");
1016#endif
1017    mdest->m_len=len;
1018    /* free old mbuf chain */
1019    m_freem(m);
1020    sc->txq_mbuf[index] = m = mdest;
1021    sc->stats.txMultiBuffPacket++;
1022  }
1023  if (m->m_len < ET_MINLEN) m->m_len = ET_MINLEN;
1024
1025  txd->ed_bufptr = mtod(m, void*);
1026  txd->ed_lencnt = m->m_len << 16;
1027  txd->ed_cmdsts = TX_CMD_L|TX_CMD_GC|TX_CMD_P|TX_CMD_O|TX_CMD_F|TX_CMD_EI;
1028
1029#ifdef GT_DEBUG
1030  printk("len = %d, cmdsts 0x%x ", m->m_len,txd->ed_cmdsts);
1031#endif
1032
1033  /*
1034   * Tell the SDMA engine to "Fetch!"
1035   * Start Tx high and Tx low.
1036   */
1037  outl(ETH_ESDCMR_TXDH,ETH0_ESDCMR);
1038  sc->txq_nactive++;
1039  if ( ++sc->txq_lo == TX_RING_SIZE) sc->txq_lo = 0;
1040  sc->txq_free--;
1041
1042  /*
1043   * Since we have put an item into the packet queue, we now want
1044   * an interrupt when the transmit queue finishes processing the
1045   * list.  But only update the mask if needs changing.
1046   */
1047  intrmask |= sc->txq_intrbits & ( ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh);
1048  if (sc->sc_intrmask != intrmask) {
1049      sc->sc_intrmask = intrmask;
1050      outl(sc->sc_intrmask, ETH0_EIMR);
1051  }
1052
1053#if 0
1054  printk("EICR= %x, EIMR= %x ", inl(ETH0_EICR), inl(ETH0_EIMR));
1055  printk("%s:transmit frame #%d queued in slot %d.\n",
1056              sc->arpcom.ac_if.if_name, sc->txq_lo, index);
1057  printk("pcr %x, pcxr %x DMA dcr %x cmr %x\n", inl(ETH0_EPCR), inl(ETH0_EPCXR), inl(ETH0_ESDCR), inl(ETH0_ESDCMR));
1058#endif
1059
1060  if (GTeth_debug>0) printk(")");
1061  return 1;
1062}
1063
1064static unsigned GTeth_txq_done(struct GTeth_softc *sc, enum GTeth_txprio txprio)
1065{
1066  if (GTeth_debug>0) printk("Txdone(" );
1067
1068  while (sc->txq_nactive > 0) {
1069    /* next to be returned to the CPU */
1070    volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_fi];
1071    unsigned cmdsts;
1072
1073    /* if GT64260 still owns it ....... */
1074    if ((cmdsts = txd->ed_cmdsts) & TX_CMD_O) {
1075       int nextin;
1076
1077       /* Someone quoted :
1078        * "Sometimes the Discovery forgets to update the
1079        * ownership bit in the descriptor."
1080        * <skf> More correctly, the last descriptor of each
1081        * transmitted frame is returned to CPU ownership and
1082        * status is updated only after the actual transmission
1083        * of the packet is completed.  Also, if there is an error
1084        * during transmission, we want to continue the
1085        * transmission of the next descriptor, in additions to
1086        * reporting the error.
1087        */
1088       /* The last descriptor */
1089       if (sc->txq_nactive == 1) return(0);
1090
1091       /*
1092        * Sometimes the Discovery forgets to update the
1093        * ownership bit in the descriptor.  See if CPU owned
1094        * the descriptor after it (since we know we've turned
1095        * that to the Discovery and if CPU owned it now then the
1096        * Discovery gave it back).  If we do, we know the
1097        * Discovery gave back this one but forgot to mark it
1098        * back to CPU.
1099        */
1100       nextin = (sc->txq_fi + 1) % TX_RING_SIZE;
1101
1102       if (sc->txq_desc[nextin].ed_cmdsts & TX_CMD_O) return(0);
1103       printk("Txq%d forgot\n",sc->txq_fi);
1104    } /* end checking GT64260eth owner */
1105    GTeth_txq_free(sc, cmdsts);   
1106  }  /* end while */
1107  if (GTeth_debug>0) printk(")\n");
1108  return(1);
1109}
1110
1111static void GTeth_tx_start(struct GTeth_softc *sc, enum GTeth_txprio txprio)
1112{
1113  int i;
1114  volatile struct GTeth_desc *txd;
1115  unsigned nxtaddr;
1116
1117#ifdef GT_DEBUG
1118  printk("GTeth_tx_start(");
1119#endif
1120  sc->sc_intrmask &= ~(ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh|
1121                             ETH_IR_TxEndLow |ETH_IR_TxBufferLow);
1122
1123  txd = &sc->txq_desc[0];
1124  sc->txq_desc_busaddr = &sc->txq_desc[0];
1125#ifdef GT_DEBUG
1126  printk("txq_desc_busaddr %x, &sc->txq_desc[0] %x \n",
1127         sc->txq_desc_busaddr,&sc->txq_desc[0]);
1128#endif
1129
1130  nxtaddr = sc->txq_desc_busaddr + sizeof(*txd);
1131
1132  sc->txq_pendq.ifq_maxlen = 10;
1133  sc->txq_pendq.ifq_head= NULL;
1134  sc->txq_pendq.ifq_tail= NULL;
1135  sc->txq_nactive = 0;
1136  sc->txq_fi = 0;
1137  sc->txq_lo = 0;
1138  sc->txq_inptr = PKT_BUF_SZ;
1139  sc->txq_outptr = 0;
1140  sc->txq_free = TX_RING_SIZE;
1141
1142  for (i = 0; i < TX_RING_SIZE;
1143       i++, txd++,  nxtaddr += sizeof(*txd)) {
1144      sc->txq_mbuf[i]=0;
1145      txd->ed_bufptr = 0;
1146
1147      /*
1148       * update the nxtptr to point to the next txd.
1149       */
1150      txd->ed_cmdsts = 0;
1151      if ( i== TX_RING_SIZE-1) nxtaddr = sc->txq_desc_busaddr;
1152      txd->ed_nxtptr =  nxtaddr;
1153#ifdef GT_DEBUG
1154      printk("next desc. @ 0x%x\n",txd->ed_nxtptr);
1155#endif
1156  }
1157
1158  switch (txprio) {
1159    case GE_TXPRIO_HI:
1160      sc->txq_intrbits = ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh;
1161         sc->txq_esdcmrbits = ETH_ESDCMR_TXDH; /* Start Tx high */
1162         sc->txq_epsrbits = ETH_EPSR_TxHigh;
1163         /* offset to current tx desc ptr reg */
1164         sc->txq_ectdp = ETH0_ECTDP1;
1165         /* Current Tx Desc Pointer 1 */
1166         outl(sc->txq_desc_busaddr,ETH0_ECTDP1);
1167#ifdef GT_DEBUG
1168         printk("ETH0_ECTDP1 %x",inl(ETH0_ECTDP1));
1169#endif
1170         break;
1171
1172    case GE_TXPRIO_LO:
1173         sc->txq_intrbits = ETH_IR_TxEndLow|ETH_IR_TxBufferLow;
1174         sc->txq_esdcmrbits = ETH_ESDCMR_TXDL; /* Start TX low */
1175         sc->txq_epsrbits = ETH_EPSR_TxLow;
1176         sc->txq_ectdp = ETH0_ECTDP0;
1177         /* Current Tx Desc Pointer 0 */
1178         outl(sc->txq_desc_busaddr,ETH0_ECTDP0);
1179#ifdef GT_DEBUG
1180         printk("ETH0_ECTDP1 %x",inl(ETH0_ECTDP0));
1181#endif
1182         break;
1183
1184    default:
1185         printk("Invalid Txq prio\n");
1186         break;
1187  }
1188 
1189#ifdef GT_DEBUG
1190  printk(")\n");
1191#endif
1192}
1193
1194static void GTeth_tx_cleanup(struct GTeth_softc *sc,enum GTeth_txprio txprio,int flush)
1195{
1196  int i;
1197
1198  if (GTeth_debug>0) printk( "GTeth_tx_cleanup(");
1199
1200  if (!flush) {
1201     if (GTeth_debug>0) printk("--");
1202     return;
1203  }
1204  for (i=0; i< TX_RING_SIZE; i++) {
1205    if (sc->txq_mbuf[i]) {
1206      m_freem(sc->txq_mbuf[i]);
1207      sc->txq_mbuf[i]=0;
1208    }
1209  }
1210  if (GTeth_debug>0) printk(")");
1211}
1212
1213static void GTeth_tx_stop(struct GTeth_softc *sc, enum GTeth_whack_op op)
1214{
1215  if (GTeth_debug>0) printk("GTeth_tx_stop( ");
1216
1217  /* SDMA command register : stop Tx high and low */
1218  outl(ETH_ESDCMR_STDH|ETH_ESDCMR_STDL, ETH0_ESDCMR);
1219
1220  GTeth_txq_done(sc, GE_TXPRIO_HI);
1221  sc->sc_intrmask &= ~(ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh|
1222                             ETH_IR_TxEndLow |ETH_IR_TxBufferLow);
1223  GTeth_tx_cleanup(sc, GE_TXPRIO_HI, op == GE_WHACK_STOP);
1224
1225  sc->arpcom.ac_if.if_timer = 0;
1226  if (GTeth_debug>0) printk(")");
1227}
1228
1229
1230/* TOCHECK : Should it be about rx or tx ? */
1231static void GTeth_ifchange(struct GTeth_softc *sc)
1232{
1233  if (GTeth_debug>0) printk("GTeth_ifchange(");
1234  if (GTeth_debug>5) printk("(pcr=%#x,imr=%#x)",inl(ETH0_EPCR),inl(ETH0_EIMR));
1235  printk("SIOCADDMULTI (SIOCDELMULTI): is it about rx or tx ?\n");
1236  outl(sc->sc_pcr | ETH_EPCR_EN, ETH0_EPCR);
1237  outl(sc->sc_intrmask, ETH0_EIMR);
1238  GTeth_ifstart(&sc->arpcom.ac_if);
1239  /* Current Tx Desc Pointer 0 and 1 */
1240  if (GTeth_debug>5) printk("(ectdp0=%#x, ectdp1=%#x)",
1241            inl(ETH0_ECTDP0), inl(ETH0_ECTDP1));
1242  if (GTeth_debug>0) printk(")");
1243}
1244
1245static int GTeth_hash_compute(struct GTeth_softc *sc,unsigned char eaddr[ETHER_ADDR_LEN])
1246{
1247  unsigned w0, add0, add1;
1248  unsigned result;
1249
1250  if (GTeth_debug>0) printk("GTeth_hash_compute(");
1251  add0 = ((unsigned) eaddr[5] <<  0) |
1252         ((unsigned) eaddr[4] <<  8) |
1253         ((unsigned) eaddr[3] << 16);
1254
1255  add0 = ((add0 & 0x00f0f0f0) >> 4) | ((add0 & 0x000f0f0f) << 4);
1256  add0 = ((add0 & 0x00cccccc) >> 2) | ((add0 & 0x00333333) << 2);
1257  add0 = ((add0 & 0x00aaaaaa) >> 1) | ((add0 & 0x00555555) << 1);
1258
1259  add1 = ((unsigned) eaddr[2] <<  0) |
1260         ((unsigned) eaddr[1] <<  8) |
1261         ((unsigned) eaddr[0] << 16);
1262
1263  add1 = ((add1 & 0x00f0f0f0) >> 4) | ((add1 & 0x000f0f0f) << 4);
1264  add1 = ((add1 & 0x00cccccc) >> 2) | ((add1 & 0x00333333) << 2);
1265  add1 = ((add1 & 0x00aaaaaa) >> 1) | ((add1 & 0x00555555) << 1);
1266
1267  if (GTeth_debug>0) printk("eaddr= %s add1:%x add0:%x\n", ether_sprintf(eaddr), add1, add0);
1268   
1269  /*
1270   * hashResult is the 15 bits Hash entry address.
1271   * ethernetADD is a 48 bit number, which is derived from the Ethernet
1272   * MAC address, by nibble swapping in every byte (i.e MAC address
1273   * of 0x123456789abc translates to ethernetADD of 0x21436587a9cb).
1274   */
1275  if ((sc->sc_pcr & ETH_EPCR_HM) == 0) {
1276     /*
1277      * hashResult[14:0] = hashFunc0(ethernetADD[47:0])
1278      *
1279      * hashFunc0 calculates the hashResult in the following manner:
1280      * hashResult[ 8:0] = ethernetADD[14:8,1,0]
1281      * XOR ethernetADD[23:15] XOR ethernetADD[32:24]
1282      */
1283     result = (add0 & 3) | ((add0 >> 6) & ~3);
1284     result ^= (add0 >> 15) ^ (add1 >>  0);
1285     result &= 0x1ff;
1286     /*
1287      *   hashResult[14:9] = ethernetADD[7:2]
1288      */
1289     result |= (add0 & ~3) << 7;        /* excess bits will be masked */
1290     if (GTeth_debug>0) printk("hash result %x  ", result & 0x7fff);
1291  } else {
1292#define TRIBITFLIP      073516240       /* yes its in octal */
1293     /*
1294      * hashResult[14:0] = hashFunc1(ethernetADD[47:0])
1295      *
1296      * hashFunc1 calculates the hashResult in the following manner:
1297      * hashResult[08:00] = ethernetADD[06:14]
1298      * XOR ethernetADD[15:23] XOR ethernetADD[24:32]
1299      */
1300     w0 = ((add0 >> 6) ^ (add0 >> 15) ^ (add1)) & 0x1ff;
1301     /*
1302      * Now bitswap those 9 bits
1303      */
1304     result = 0;
1305     result |= ((TRIBITFLIP >> (((w0 >> 0) & 7) * 3)) & 7) << 6;
1306     result |= ((TRIBITFLIP >> (((w0 >> 3) & 7) * 3)) & 7) << 3;
1307     result |= ((TRIBITFLIP >> (((w0 >> 6) & 7) * 3)) & 7) << 0;
1308
1309     /*
1310      *   hashResult[14:09] = ethernetADD[00:05]
1311      */
1312     result |= ((TRIBITFLIP >> (((add0 >> 0) & 7) * 3)) & 7) << 12;
1313     result |= ((TRIBITFLIP >> (((add0 >> 3) & 7) * 3)) & 7) << 9;
1314     if (GTeth_debug>5) printk("1(%#x)", result);
1315  }
1316  if (GTeth_debug>0) printk(")");
1317  /* 1/2K address filtering (MOTLoad default )? ->16KB memory required
1318   * or 8k address filtering ? -> 256KB memory required
1319   */
1320  return result & ((sc->sc_pcr & ETH_EPCR_HS_512) ? 0x7ff : 0x7fff);
1321}
1322
1323static int GTeth_hash_entry_op(struct GTeth_softc *sc, enum GTeth_hash_op op,
1324        enum GTeth_rxprio prio,unsigned char eaddr[ETHER_ADDR_LEN])
1325{
1326  unsigned long long he;
1327  unsigned long long *maybe_he_p = NULL;
1328  int limit;
1329  int hash;
1330  int maybe_hash = 0;
1331
1332  if (GTeth_debug>0) printk("GTeth_hash_entry_op(prio %d ", prio);
1333
1334  hash = GTeth_hash_compute(sc, eaddr);
1335
1336  if (sc->sc_hashtable == NULL) {
1337        rtems_panic("hashtable == NULL!");
1338  }
1339  if (GTeth_debug>0) printk("Hash computed %x eaddr %s\n", hash,ether_sprintf(eaddr));
1340
1341
1342  /*
1343   * Assume we are going to insert so create the hash entry we
1344   * are going to insert.  We also use it to match entries we
1345   * will be removing.  The datasheet is wrong for this.
1346   */
1347  he = (((unsigned long long) eaddr[5]) << 43) |
1348       (((unsigned long long) eaddr[4]) << 35) |
1349       (((unsigned long long) eaddr[3]) << 27) |
1350       (((unsigned long long) eaddr[2]) << 19) |
1351       (((unsigned long long) eaddr[1]) << 11) |
1352       (((unsigned long long) eaddr[0]) <<  3) |
1353       ((unsigned long long) HSH_PRIO_INS(prio) | HSH_V | HSH_R);
1354  /*   he = 0x1b1acd87d08005;*/
1355  /*
1356   * The GT will search upto 12 entries for a hit, so we must mimic that.
1357   */
1358  hash &= (sc->sc_hashmask / sizeof(he));
1359
1360  if (GTeth_debug>0) {
1361    unsigned val1, val2;
1362
1363    val1= he & 0xffffffff;
1364    val2= (he >>32) & 0xffffffff;
1365    printk("Hash addr value %x%x, entry %x\n",val2,val1, hash);
1366  }
1367
1368  for (limit = HSH_LIMIT; limit > 0 ; --limit) {
1369      /*
1370       * Does the GT wrap at the end, stop at the, or overrun the
1371       * end?  Assume it wraps for now.  Stash a copy of the
1372       * current hash entry.
1373       */
1374      unsigned long long *he_p = &sc->sc_hashtable[hash];
1375      unsigned long long thishe = *he_p;
1376
1377      /*
1378       * If the hash entry isn't valid, that break the chain.  And
1379       * this entry a good candidate for reuse.
1380       */
1381      if ((thishe & HSH_V) == 0) {
1382         maybe_he_p = he_p;
1383         break;
1384      }
1385
1386      /*
1387       * If the hash entry has the same address we are looking for
1388       * then ...  if we are removing and the skip bit is set, its
1389       * already been removed.  if are adding and the skip bit is
1390       * clear, then its already added.  In either return EBUSY
1391       * indicating the op has already been done.  Otherwise flip
1392       * the skip bit and return 0.
1393       */
1394      if (((he ^ thishe) & HSH_ADDR_MASK) == 0) {
1395         if (((op == GE_HASH_REMOVE) && (thishe & HSH_S)) ||
1396            ((op == GE_HASH_ADD) && (thishe & HSH_S) == 0))
1397            return EBUSY;
1398          *he_p = thishe ^ HSH_S;
1399
1400          if (GTeth_debug>0) {
1401             unsigned val1, val2;
1402
1403             val1= *he_p & 0xffffffff;
1404             val2= (*he_p >>32) & 0xffffffff;
1405             printk("flip skip bit result %x%x entry %x ",val2,val1, hash);
1406          }
1407          return 0;
1408       }
1409
1410       /*
1411        * If we haven't found a slot for the entry and this entry
1412        * is currently being skipped, return this entry.
1413        */
1414       if (maybe_he_p == NULL && (thishe & HSH_S)) {
1415          maybe_he_p = he_p;
1416          maybe_hash = hash;
1417       }               
1418       hash = (hash + 1) & (sc->sc_hashmask / sizeof(he));
1419  }
1420
1421  /*
1422   * If we got here, then there was no entry to remove.
1423   */
1424  if (op == GE_HASH_REMOVE) {
1425     printk("GT64260eth : No entry to remove\n");
1426     return ENOENT;
1427  }
1428
1429  /*
1430   * If we couldn't find a slot, return an error.
1431   */
1432  if (maybe_he_p == NULL) {
1433     rtems_panic("GT64260eth : No slot found");
1434     return ENOSPC;
1435  }
1436
1437  /* Update the entry.*/
1438  *maybe_he_p = he;
1439  if (GTeth_debug>0) {
1440    unsigned val1, val2;
1441#if 0
1442    unsigned long *pt= sc->sc_hashtable;
1443    int i, loop;
1444
1445  for (loop= 0; loop< 256; loop++) {
1446    printk("%d)", loop);
1447    for (i=0; i< 16; i++, pt++) printk("%x ",*pt);
1448    printk("\n");
1449  }
1450#endif
1451    val1= he & 0xffffffff;
1452    val2= (he >>32) & 0xffffffff;
1453    printk("Update Hash result %x%x, table addr %x entry %x )\n",val2, val1, maybe_he_p, hash);
1454  }
1455  return 0;
1456}
1457
1458static int GTeth_hash_fill(struct GTeth_softc *sc)
1459{
1460  struct ether_multistep step;
1461  struct ether_multi *enm;
1462  int error;
1463
1464  if (GTeth_debug>0) printk( "GTeth_hash_fill(");
1465  error = GTeth_hash_entry_op(sc,GE_HASH_ADD,GE_RXPRIO_HI,sc->arpcom.ac_enaddr);
1466
1467  if (error) {
1468     if (GTeth_debug>0) printk("!");
1469     return error;
1470  }
1471
1472  sc->sc_flags &= ~GE_ALLMULTI;
1473  if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) == 0)
1474     sc->sc_pcr &= ~ETH_EPCR_PM;
1475  /* see lib/include/netinet/if_ether.h */
1476  ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
1477  while (enm != NULL) {
1478    if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1479      /* Frames are received regardless of their destinatin address */
1480       sc->sc_flags |= GE_ALLMULTI;
1481       sc->sc_pcr |= ETH_EPCR_PM;
1482    } else {
1483      /* Frames are only received if the destinatin address is found
1484       * in the hash table
1485       */
1486       error = GTeth_hash_entry_op(sc, GE_HASH_ADD,
1487             GE_RXPRIO_MEDLO, enm->enm_addrlo);
1488       if (error == ENOSPC) break;
1489    }
1490    ETHER_NEXT_MULTI(step, enm);
1491  }
1492  if (GTeth_debug>0) printk(")\n");
1493  return error;
1494}
1495
1496static void GTeth_hash_init(struct GTeth_softc *sc)
1497{
1498  void *hash_mem;
1499
1500  if (GTeth_debug>0) printk("GTeth_hash_init(");
1501  /* MOTLoad defualt : 512 bytes of address filtering, which
1502   * requires 16KB of memory
1503   */
1504#if 1
1505  hash_mem = rtems_bsdnet_malloc(HASH_DRAM_SIZE + HASH_ALIGN, M_FREE, M_NOWAIT);
1506  sc->sc_hashtable  =(void *)(((long)hash_mem+ HASH_ALIGN) & ~HASH_ALIGN);
1507#else
1508  /* only for test */
1509  hash_mem = 0x68F000;
1510  sc->sc_hashtable  =(unsigned long long *)hash_mem;
1511#endif
1512  sc->sc_hashmask = HASH_DRAM_SIZE - 1;
1513
1514  memset((void *)sc->sc_hashtable, 0,HASH_DRAM_SIZE);
1515  if (GTeth_debug>0)
1516    printk("hashtable addr:%x, mask %x)\n", sc->sc_hashtable,sc->sc_hashmask);
1517}
1518
1519static void GT64260eth_error(struct GTeth_softc *sc)
1520{
1521  struct ifnet          *ifp = &sc->arpcom.ac_if;
1522  unsigned int          intr_status= sc->intr_errsts[sc->intr_err_ptr1];
1523
1524  /* read and reset the status; because this is written
1525   * by the ISR, we must disable interrupts here
1526   */
1527  if (intr_status) {
1528    printk("%s%d: ICR = 0x%x ",
1529           ifp->if_name, ifp->if_unit, intr_status);
1530#if 1
1531    if (intr_status & INTR_RX_ERROR) {
1532       printk("Rxq error, if_ierrors %d\n",
1533              ifp->if_ierrors);
1534    }
1535#endif
1536    /* Rx error is handled in GT64260eth_rx() */
1537    if (intr_status & INTR_TX_ERROR) {
1538       ifp->if_oerrors++;
1539       printk("Txq error,  if_oerrors %d\n",ifp->if_oerrors);
1540    }
1541  }
1542  else
1543    printk("%s%d: Ghost interrupt ?\n",ifp->if_name,
1544           ifp->if_unit);
1545  sc->intr_errsts[sc->intr_err_ptr1++]=0; 
1546  sc->intr_err_ptr1 %= INTR_ERR_SIZE;   /* Till Straumann */
1547}
1548
1549
1550/* The daemon does all of the work; RX, TX and cleaning up buffers/descriptors */
1551static void GT64260eth_daemon(void *arg)
1552{
1553  struct GTeth_softc *sc = (struct GTeth_softc*)arg;
1554  rtems_event_set       events;
1555  struct mbuf   *m=0;
1556  struct ifnet  *ifp=&sc->arpcom.ac_if;
1557
1558#if 0   
1559  /* see comments in GT64260eth_init(); in newer versions of
1560   * rtems, we hold the network semaphore at this point
1561   */
1562  rtems_semaphore_release(sc->daemonSync);
1563#endif
1564
1565  /* NOTE: our creator possibly holds the bsdnet_semaphore.
1566   *       since that has PRIORITY_INVERSION enabled, our
1567   *       subsequent call to bsdnet_event_receive() will
1568   *       _not_ release it. It's still in posession of our
1569   *       owner.
1570   *       This is different from how killing this task
1571   *       is handled.
1572   */
1573
1574  for (;;) {
1575     /* sleep until there's work to be done */
1576     /* Note: bsdnet_event_receive() acquires
1577      *       the global bsdnet semaphore for
1578      *       mutual exclusion.
1579      */
1580     rtems_bsdnet_event_receive(ALL_EVENTS,
1581                                RTEMS_WAIT | RTEMS_EVENT_ANY,
1582                                RTEMS_NO_TIMEOUT,
1583                                &events);
1584 
1585     if (KILL_EVENT & events) break;
1586
1587#ifndef GE_NORX
1588     if (events & RX_EVENT) GT64260eth_rx(sc,GE_RXPRIO_HI);
1589#endif
1590
1591     /* clean up and try sending packets */
1592     do {
1593#if 1
1594        if (gpp_int_error!=0) {
1595           printk("GPP interrupt error %d\n", gpp_int_error);
1596           gpp_int_error=0;
1597        }
1598#endif
1599         if (sc->txq_nactive) GTeth_txq_done(sc, GE_TXPRIO_HI);
1600
1601         while (sc->txq_free>0) {
1602           if (sc->txq_free>TXQ_HiLmt_OFF) {
1603              m=0;
1604              IF_DEQUEUE(&ifp->if_snd,m);
1605              if (m==0) break;
1606              GT64260eth_sendpacket(sc, m, GE_TXPRIO_HI);
1607           }
1608           else {
1609             if (txq_high_limit(sc))
1610                 break;
1611           }
1612         }
1613         /* we leave this loop
1614          *  - either because there's no free buffer
1615          *    (m=0 initializer && !sc->txq_free)
1616          *  - or there's nothing to send (IF_DEQUEUE
1617          *    returned 0
1618          */
1619       } while (m);
1620
1621       ifp->if_flags &= ~IFF_OACTIVE;
1622
1623       /* Log errors and other uncommon events. */
1624       if (events & ERR_EVENT) GT64260eth_error(sc);
1625  } /* end for(;;) { rtems_bsdnet_event_receive() .....*/
1626
1627  ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1628
1629  /* shut down the hardware */
1630  GT64260eth_stop_hw(sc);
1631  /* flush the output queue */
1632  for (;;) {
1633      IF_DEQUEUE(&ifp->if_snd,m);
1634      if (!m) break;
1635      m_freem(m);
1636  }
1637  /* as of 'rtems_bsdnet_event_receive()' we own the
1638   * networking semaphore
1639   */
1640  rtems_bsdnet_semaphore_release();
1641  rtems_semaphore_release(sc->daemonSync);
1642
1643  /* Note that I dont use sc->daemonTid here -
1644   * theoretically, that variable could already
1645   * hold a newly created TID
1646   */
1647  rtems_task_delete(RTEMS_SELF);
1648}
1649
Note: See TracBrowser for help on using the repository browser.