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

4.104.114.84.95
Last change on this file since 04b7821 was 04b7821, checked in by Ralf Corsepius <ralf.corsepius@…>, on 10/26/04 at 03:45:12

2004-10-26 Ralf Corsepius <ralf_corsepius@…>

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