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

4.104.114.84.95
Last change on this file since c39ecd73 was c39ecd73, checked in by Ralf Corsepius <ralf.corsepius@…>, on Oct 22, 2004 at 3:38:05 AM

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

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