source: rtems/c/src/lib/libbsp/lm32/shared/tsmac/tsmac.c @ 68049df

4.104.115
Last change on this file since 68049df was 68049df, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/24/09 at 06:42:40

2009-11-24 Ralf Corsépius <ralf.corsepius@…>

  • shared/tsmac/tsmac.c: Remove unused vars. Let rtems_tsmac_driver_attach return 1.
  • Property mode set to 100644
File size: 19.8 KB
Line 
1/*
2 *  This file contains definitions for LatticeMico32 TSMAC (Tri-Speed MAC)
3 *
4 *  COPYRIGHT (c) 1989-1999.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 *
13 *  Jukka Pietarinen <jukka.pietarinen@mrf.fi>, 2008,
14 *  Micro-Research Finland Oy
15 */
16
17#define _KERNEL
18
19#include <rtems.h>
20#include <bsp.h>
21#include <stdio.h>
22#include <errno.h>
23#include <rtems/error.h>
24#include <rtems/rtems_bsdnet.h>
25
26#include <sys/param.h>
27#include <sys/mbuf.h>
28#include <sys/socket.h>
29#include <sys/sockio.h>
30
31#include <net/if.h>
32
33#include <netinet/in.h>
34#include <netinet/if_ether.h>
35
36#include "../include/system_conf.h"
37#include "tsmac.h"
38#include "dp83848phy.h"
39
40struct tsmac_softc {
41  struct arpcom arpcom;
42  void *ioaddr;
43  rtems_id rxDaemonTid;
44  rtems_id txDaemonTid;
45
46  /*
47   * Statistics
48   */
49  int rxInterrupts;
50  int rxPktIgnore;
51  int rxLenCheckError;
52  int rxLongFrame;
53  int rxShortFrame;
54  int rxIPGViolation;
55  int rxCRCError;
56  int rxOKPackets;
57  int rxControlFrame;
58  int rxPauseFrame;
59  int rxMulticast;
60  int rxBroadcast;
61  int rxVLANTag;
62  int rxPreShrink;
63  int rxDribNib;
64  int rxUnsupOPCD;
65  int rxByteCnt;
66  int rxFifoFull;
67
68  int txInterrupts;
69  int txUnicast;
70  int txPauseFrame;
71  int txMulticast;
72  int txBroadcast;
73  int txVLANTag;
74  int txBadFCS;
75  int txJumboCnt;
76  int txByteCnt;
77  int txLostCarrier;
78  int txFifoFull;
79};
80
81/*
82 * Macros to access tsmac wrapper registers.
83 */
84
85static inline uint32_t tsmacread(unsigned int reg)
86{
87  return *((uint32_t *)(TS_MAC_CORE_BASE_ADDRESS + reg));
88}
89
90static inline void tsmacwrite(unsigned int reg, uint32_t value)
91{
92  *((uint32_t *)(TS_MAC_CORE_BASE_ADDRESS + reg)) = value;
93}
94
95/*
96 * tsmac is a wishbone to MAC wrapper.
97 * The macros below access to MAC registers.
98 */
99
100static inline uint16_t tsmacregread(unsigned int reg)
101{
102  tsmacwrite(LM32_TSMAC_MAC_REGS_ADDR_RW, reg);
103  return *((uint16_t *)(TS_MAC_CORE_BASE_ADDRESS + LM32_TSMAC_MAC_REGS_DATA + 2));
104}
105
106static inline void tsmacregwrite(unsigned int reg, uint16_t value)
107{
108  *((uint16_t *)(TS_MAC_CORE_BASE_ADDRESS + LM32_TSMAC_MAC_REGS_DATA + 2)) = value;
109  tsmacwrite(LM32_TSMAC_MAC_REGS_ADDR_RW, REGS_ADDR_WRITE | reg);
110}
111
112/*
113#define DEBUG 1
114*/
115
116/* We support one interface */
117
118#define TSMAC_NUM  1
119#define TSMAC_NAME "TSMAC"
120#define TSMAC_MAC0 0x00
121#define TSMAC_MAC1 0x0E
122#define TSMAC_MAC2 0xB2
123#define TSMAC_MAC3 0x00
124#define TSMAC_MAC4 0x00
125#define TSMAC_MAC5 0x01
126
127/*
128 *  The interrupt vector number associated with the tsmac device
129 *  driver.
130 */
131
132#define TSMAC_VECTOR    ( TS_MAC_CORE_IRQ )
133#define TSMAC_IRQMASK   ( 1 << TSMAC_VECTOR )
134
135rtems_isr tsmac_interrupt_handler(rtems_vector_number vector);
136
137extern lm32_isr_entry set_vector(rtems_isr_entry handler,
138                                 rtems_vector_number vector, int type);
139
140/*
141 * Macros to access PHY registers through the (G)MII
142 */
143
144uint16_t tsmacphyread(unsigned int reg)
145{
146  tsmacregwrite(LM32_TSMAC_GMII_MNG_CTL_BYTE0,
147                ((DEFAULT_PHY_ADDRESS & GMII_MNG_CTL_PHY_ADD_MASK) <<
148                 GMII_MNG_CTL_PHY_ADD_SHIFT) |
149                ((reg & GMII_MNG_CTL_REG_ADD_MASK) <<
150                 GMII_MNG_CTL_REG_ADD_SHIFT) |
151                GMII_MNG_CTL_READ_PHYREG);
152
153  /* Wait for management interface to be ready */
154  while(!(tsmacregread(LM32_TSMAC_GMII_MNG_CTL_BYTE0) & GMII_MNG_CTL_CMD_FIN));
155
156  return tsmacregread(LM32_TSMAC_GMII_MNG_DAT_BYTE0);
157}
158
159void tsmacphywrite(unsigned int reg, uint16_t value)
160{
161  tsmacregwrite(LM32_TSMAC_GMII_MNG_DAT_BYTE0, value);
162  tsmacregwrite(LM32_TSMAC_GMII_MNG_CTL_BYTE0,
163                ((DEFAULT_PHY_ADDRESS & GMII_MNG_CTL_PHY_ADD_MASK) <<
164                 GMII_MNG_CTL_PHY_ADD_SHIFT) |
165                ((reg & GMII_MNG_CTL_REG_ADD_MASK) <<
166                 GMII_MNG_CTL_REG_ADD_SHIFT) |
167                GMII_MNG_CTL_WRITE_PHYREG);
168
169  /* Wait for management interface to be ready */
170  while(!(tsmacregread(LM32_TSMAC_GMII_MNG_CTL_BYTE0) & GMII_MNG_CTL_CMD_FIN));
171}
172
173/*
174 * Event definitions
175 */
176#define INTERRUPT_EVENT      RTEMS_EVENT_1
177#define START_TRANSMIT_EVENT RTEMS_EVENT_2
178
179static struct tsmac_softc tsmac_softc[TSMAC_NUM];
180
181#ifdef CPU_U32_FIX
182
183/*
184 * Routine to align the received packet so that the ip header
185 * is on a 32-bit boundary. Necessary for cpu's that do not
186 * allow unaligned loads and stores and when the 32-bit DMA
187 * mode is used.
188 *
189 * Transfers are done on word basis to avoid possibly slow byte
190 * and half-word writes.
191 *
192 * Copied over from sonic.c driver
193 */
194
195void ipalign(struct mbuf *m)
196{
197  unsigned int *first, *last, data;
198  unsigned int tmp = 0;
199
200  if ((((int) m->m_data) & 2) && (m->m_len)) {
201    last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);
202    first = (unsigned int *) (((int) m->m_data) & ~3);
203    tmp = *first << 16;
204    first++;
205    do {
206      data = *first;
207      *first = tmp | (data >> 16);
208      tmp = data << 16;
209      first++;
210    } while (first <= last);
211
212    m->m_data = (caddr_t)(((int) m->m_data) + 2);
213  }
214}
215#endif
216
217/*
218 * Receive task
219 */
220static void tsmac_rxDaemon(void *arg)
221{
222  struct tsmac_softc *tsmac = (struct tsmac_softc *) arg;
223  struct ifnet *ifp = &tsmac->arpcom.ac_if;
224  rtems_event_set events;
225  int rxq, count, len, data;
226
227#ifdef DEBUG
228  printk(TSMAC_NAME ": tsmac_rxDaemon\n");
229#endif
230
231  for(;;)
232    {
233      rtems_bsdnet_event_receive( RTEMS_ALL_EVENTS,
234                                  RTEMS_WAIT | RTEMS_EVENT_ANY,
235                                  RTEMS_NO_TIMEOUT,
236                                  &events);
237     
238#ifdef DEBUG
239      printk(TSMAC_NAME ": tsmac_rxDaemon wakeup\n");
240#endif
241
242      for (;;)
243        {
244          struct mbuf* m;
245          struct ether_header* eh;
246          uint32_t *buf;
247
248          /* Get number of RX frames in RX FIFO */
249          rxq = tsmacread(LM32_TSMAC_RX_FRAMES_CNT);
250     
251          if (rxq == 0)
252            break;
253       
254          /* Get lenght of frame */
255          len = tsmacread(LM32_TSMAC_RX_LEN_FIFO);
256#ifdef DEBUG
257          printk(TSMAC_NAME ": Frames %d, len 0x%04x (%d)\n",
258                 rxq, len, len);
259#endif
260
261          /*
262           * Get memory for packet
263           */
264          MGETHDR(m, M_WAIT, MT_DATA);
265          MCLGET(m, M_WAIT);
266 
267          m->m_pkthdr.rcvif = ifp;
268
269          buf = (uint32_t *) mtod(m, uint32_t*);
270          for (count = 0; count < len; count += 4)
271            {
272              data = tsmacread(LM32_TSMAC_RX_DATA_FIFO);
273              *buf++ = data;
274#ifdef DEBUG
275              printk("%08x ", data);
276#endif
277            }
278#ifdef DEBUG
279          printk("\n");
280#endif
281
282          m->m_len = m->m_pkthdr.len =
283            len - sizeof(uint32_t) - sizeof(struct ether_header);
284          eh = mtod(m, struct ether_header*);
285          m->m_data += sizeof(struct ether_header);
286
287#ifdef CPU_U32_FIX
288      ipalign(m);       /* Align packet on 32-bit boundary */
289#endif
290
291          /* Notify the ip stack that there is a new packet */
292          ether_input(ifp, eh, m);
293         
294          /*
295           * Release RX frame
296           */
297        }
298    }
299}
300
301static unsigned char tsmac_txbuf[2048];
302
303static void tsmac_sendpacket(struct ifnet *ifp, struct mbuf *m)
304{
305  struct mbuf *nm = m;
306  int len = 0, i;
307  uint32_t *buf;
308
309#ifdef DEBUG
310  printk(TSMAC_NAME ": tsmac_sendpacket\n");
311#endif
312
313  do
314    {
315#ifdef DEBUG
316      printk("mbuf: 0x%08x len %03x: ", nm->m_data, nm->m_len);
317      for (i = 0; i < nm->m_len; i++)
318        {
319          printk("%02x", mtod(nm, unsigned char*)[i]);
320          if (i & 1)
321            printk(" ");
322        }
323      printk("\n");
324#endif
325               
326      if (nm->m_len > 0)
327        {
328          memcpy(&tsmac_txbuf[len], (char *)nm->m_data, nm->m_len);
329          len += nm->m_len;
330        }
331    }
332  while ((nm = nm->m_next) != 0);
333
334  buf = (uint32_t *) tsmac_txbuf;
335  for (i = 0; i < len; i += 4)
336    {
337#ifdef DEBUG
338      printk("%08x", *buf);
339#endif
340      tsmacwrite(LM32_TSMAC_TX_DATA_FIFO, *buf++);
341    }
342#ifdef DEBUG
343  printk("\n");
344#endif
345
346  /*
347   * Enqueue TX frame
348   */
349  tsmacwrite(LM32_TSMAC_TX_LEN_FIFO, len);
350}
351
352/*
353 * Transmit task
354 */
355static void tsmac_txDaemon(void *arg)
356{
357  struct tsmac_softc *tsmac = (struct tsmac_softc *) arg;
358  struct ifnet *ifp = &tsmac->arpcom.ac_if;
359  struct mbuf *m;
360  rtems_event_set events;
361  int txq;
362
363#ifdef DEBUG
364  printk(TSMAC_NAME ": tsmac_txDaemon\n");
365#endif
366
367  for (;;)
368    {
369      /*
370       * Wait for packet
371       */
372      rtems_bsdnet_event_receive (START_TRANSMIT_EVENT | INTERRUPT_EVENT,
373                                  RTEMS_EVENT_ANY | RTEMS_WAIT,
374                                  RTEMS_NO_TIMEOUT, &events);
375#ifdef DEBUG
376      printk(TSMAC_NAME ": tsmac_txDaemon event\n");
377#endif
378      for (;;)
379        {
380          /*
381           * Here we should read amount of transmit memory available
382           */
383
384          txq = 2048;
385
386          if (txq < ifp->if_mtu)
387            {
388              /*
389               * Here we need to enable transmit done IRQ
390               */
391#ifdef DEBUG
392              printk(TSMAC_NAME ": TXMA %d < MTU + CW%d\n", txq,
393                     ifp->if_mtu);
394#endif
395              break;
396            }
397         
398          /*
399           * Get the next mbuf chain to transmit.
400           */
401          IF_DEQUEUE(&ifp->if_snd, m);
402#ifdef DEBUG
403          printk(TSMAC_NAME ": mbuf %08x\n", (int) m);
404#endif
405          if (!m)
406            break;
407          tsmac_sendpacket(ifp, m);
408
409          m_freem(m);
410        }
411      ifp->if_flags &= ~IFF_OACTIVE;
412    }
413}
414
415/*
416 * Initialize TSMAC hardware
417 */
418void tsmac_init_hardware(struct tsmac_softc *tsmac)
419{
420  unsigned char *mac_addr;
421  int version_id, phyid, stat;
422
423#ifdef DEBUG
424  printk(TSMAC_NAME ": tsmac_init_hardware\n");
425#endif
426
427  version_id = tsmacread(LM32_TSMAC_VERID);
428#ifdef DEBUG
429  printk(TSMAC_NAME ": Version ID %08x\n", version_id);
430#endif
431
432#ifdef DEBUG
433  printk(TSMAC_NAME ": MAC MODE %04x\n", tsmacregread(LM32_TSMAC_MODE_BYTE0));
434  printk(TSMAC_NAME ": MAC TX_RX_CTL %04x\n", tsmacregread(LM32_TSMAC_TX_RX_CTL_BYTE0));
435  printk(TSMAC_NAME ": MAC MAX_PKT_SIZE %04x\n", tsmacregread(LM32_TSMAC_MAX_PKT_SIZE_BYTE0));
436  printk(TSMAC_NAME ": MAC IPG_VAL %04x\n", tsmacregread(LM32_TSMAC_IPG_VAL_BYTE0));
437  printk(TSMAC_NAME ": MAC MAC_ADDR0 %04x\n",
438         tsmacregread(LM32_TSMAC_MAC_ADDR_0_BYTE0));
439  printk(TSMAC_NAME ": MAC MAC_ADDR1 %04x\n",
440         tsmacregread(LM32_TSMAC_MAC_ADDR_1_BYTE0));
441  printk(TSMAC_NAME ": MAC MAC_ADDR2 %04x\n",
442         tsmacregread(LM32_TSMAC_MAC_ADDR_2_BYTE0));
443  printk(TSMAC_NAME ": MAC TX_RX_STS %04x\n",
444         tsmacregread(LM32_TSMAC_TX_RX_STS_BYTE0));
445#endif 
446
447  /*
448   * Set our physical address
449   */
450  mac_addr = tsmac->arpcom.ac_enaddr;
451  tsmacregwrite(LM32_TSMAC_MAC_ADDR_0_BYTE0, (mac_addr[0] << 8) | mac_addr[1]);
452  tsmacregwrite(LM32_TSMAC_MAC_ADDR_1_BYTE0, (mac_addr[2] << 8) | mac_addr[3]);
453  tsmacregwrite(LM32_TSMAC_MAC_ADDR_2_BYTE0, (mac_addr[4] << 8) | mac_addr[5]);
454
455#ifdef DEBUG
456  printk(TSMAC_NAME ": After setting MAC address.\n");
457  printk(TSMAC_NAME ": MAC MAC_ADDR0 %04x\n",
458         tsmacregread(LM32_TSMAC_MAC_ADDR_0_BYTE0));
459  printk(TSMAC_NAME ": MAC MAC_ADDR1 %04x\n",
460         tsmacregread(LM32_TSMAC_MAC_ADDR_1_BYTE0));
461  printk(TSMAC_NAME ": MAC MAC_ADDR2 %04x\n",
462         tsmacregread(LM32_TSMAC_MAC_ADDR_2_BYTE0));
463#endif 
464
465  /*
466   * Configure PHY
467   */
468 
469  phyid = tsmacphyread(PHY_PHYIDR1);
470#ifdef DEBUG
471  printk(TSMAC_NAME ": PHYIDR1 %08x\n", phyid);
472#endif
473  phyid = tsmacphyread(PHY_PHYIDR2);
474#ifdef DEBUG
475  printk(TSMAC_NAME ": PHYIDR2 %08x\n", phyid);
476#endif
477
478#ifdef TSMAC_FORCE_10BASET
479  /* Force 10baseT mode, no AN, full duplex */
480  tsmacphywrite(PHY_BMCR, PHY_BMCR_DUPLEX_MODE);
481  stat = tsmacphyread(PHY_BMCR);
482#ifdef DEBUG
483  printk(TSMAC_NAME ": PHY BMCR %04x, wrote %04x\n", stat,
484         PHY_BMCR_DUPLEX_MODE);
485#endif
486  stat = tsmacphyread(PHY_BMSR);
487#ifdef DEBUG
488  printk(TSMAC_NAME ": PHY BMSR %04x\n", stat);
489#endif
490  /* Support for 10baseT modes only */
491  tsmacphywrite(PHY_ANAR, PHY_ANAR_10_FD | PHY_ANAR_10 | PHY_ANAR_SEL_DEF);
492  stat = tsmacphyread(PHY_ANAR);
493#ifdef DEBUG
494  printk(TSMAC_NAME ": PHY ANAR %04x, wrote %04x\n", stat,
495         PHY_ANAR_10_FD | PHY_ANAR_10 | PHY_ANAR_SEL_DEF);
496#endif
497#endif /* TSMAC_FORCE_10BASET */
498  stat = tsmacphyread(PHY_PHYSTS);
499#ifdef DEBUG
500  printk(TSMAC_NAME ": PHY PHYSTS %04x\n", stat);
501#endif
502
503  /* Enable receive and transmit interrupts */
504  tsmacwrite(LM32_TSMAC_INTR_ENB, INTR_ENB |
505             INTR_RX_SMRY | INTR_TX_SMRY |
506             INTR_RX_PKT_RDY | INTR_TX_PKT_SENT);
507}
508
509/*
510 * Initialize and start the device
511 */
512void tsmac_init(void *arg)
513{
514  struct tsmac_softc *tsmac = &tsmac_softc[0];
515  struct ifnet *ifp = &tsmac->arpcom.ac_if;
516
517#ifdef DEBUG
518  printk(TSMAC_NAME ": tsmac_init, tsmac->txDaemonTid = 0x%x\n",
519         tsmac->txDaemonTid);
520#endif
521
522  if (tsmac->txDaemonTid == 0)
523    {
524      /*
525       * Initialize hardware
526       */
527      tsmac_init_hardware(tsmac);
528
529      /*
530       * Start driver tasks
531       */
532      tsmac->txDaemonTid = rtems_bsdnet_newproc ("TSMACtx", 4096,
533                                               tsmac_txDaemon, tsmac);
534      tsmac->rxDaemonTid = rtems_bsdnet_newproc ("TSMACrx", 4096,
535                                               tsmac_rxDaemon, tsmac);
536      /*
537       * Setup interrupt handler
538       */
539      set_vector( tsmac_interrupt_handler, TSMAC_VECTOR, 1 );
540
541      /* Interrupt line for TSMAC */
542      lm32_interrupt_unmask(TSMAC_IRQMASK);
543   }
544 
545  ifp->if_flags |= IFF_RUNNING;
546 
547  /*
548   * Receive broadcast
549   */
550 
551  tsmacregwrite(LM32_TSMAC_TX_RX_CTL_BYTE0, TX_RX_CTL_RECEIVE_BRDCST |
552                TX_RX_CTL_RECEIVE_PAUSE);
553
554  /*
555   * Enable transmitter
556   * Flow control enable
557   * Enable receiver
558   */
559
560  tsmacregwrite(LM32_TSMAC_MODE_BYTE0, MODE_TX_EN | MODE_RX_EN | MODE_FC_EN); 
561
562  /*
563   * Wake up receive task to receive packets in queue
564   */
565  rtems_event_send(tsmac->rxDaemonTid, INTERRUPT_EVENT);
566}
567
568void tsmac_stop(struct ifnet *ifp)
569{
570  /*
571   * Mask tsmac interrupts
572   */
573  lm32_interrupt_mask(TSMAC_IRQMASK);
574
575  ifp->if_flags &= ~IFF_RUNNING;
576
577  /*
578   * Disable transmitter and receiver
579   */
580  tsmacregwrite(LM32_TSMAC_MODE_BYTE0, 0);
581}
582
583/*
584 * Send packet
585 */
586void tsmac_start(struct ifnet *ifp)
587{
588  struct tsmac_softc *tsmac = ifp->if_softc;
589
590  rtems_event_send (tsmac->txDaemonTid, START_TRANSMIT_EVENT);
591  ifp->if_flags |= IFF_OACTIVE;
592}
593
594void tsmac_stats(struct tsmac_softc *tsmac)
595{
596  /*
597   * Update counters from TSMAC MIB counters
598   */
599
600  tsmac->rxPktIgnore = tsmacread(LM32_TSMAC_RX_PKT_IGNR_CNT);
601  tsmac->rxLenCheckError = tsmacread(LM32_TSMAC_RX_LEN_CHK_ERR_CNT);
602  tsmac->rxLongFrame = tsmacread(LM32_TSMAC_RX_LNG_FRM_CNT);
603  tsmac->rxShortFrame = tsmacread(LM32_TSMAC_RX_SHRT_FRM_CNT);
604  tsmac->rxIPGViolation = tsmacread(LM32_TSMAC_RX_IPG_VIOL_CNT);
605  tsmac->rxCRCError = tsmacread(LM32_TSMAC_RX_CRC_ERR_CNT);
606  tsmac->rxOKPackets = tsmacread(LM32_TSMAC_RX_OK_PKT_CNT);
607  tsmac->rxControlFrame = tsmacread(LM32_TSMAC_RX_CTL_FRM_CNT);
608  tsmac->rxPauseFrame = tsmacread(LM32_TSMAC_RX_PAUSE_FRM_CNT);
609  tsmac->rxMulticast = tsmacread(LM32_TSMAC_RX_MULTICAST_CNT);
610  tsmac->rxBroadcast = tsmacread(LM32_TSMAC_RX_BRDCAST_CNT);
611  tsmac->rxVLANTag = tsmacread(LM32_TSMAC_RX_VLAN_TAG_CNT);
612  tsmac->rxPreShrink = tsmacread(LM32_TSMAC_RX_PRE_SHRINK_CNT);
613  tsmac->rxDribNib = tsmacread(LM32_TSMAC_RX_DRIB_NIB_CNT);
614  tsmac->rxUnsupOPCD = tsmacread(LM32_TSMAC_RX_UNSUP_OPCD_CNT);
615  tsmac->rxByteCnt = tsmacread(LM32_TSMAC_RX_BYTE_CNT);
616
617  tsmac->txUnicast = tsmacread(LM32_TSMAC_TX_UNICAST_CNT);
618  tsmac->txPauseFrame = tsmacread(LM32_TSMAC_TX_PAUSE_FRM_CNT);
619  tsmac->txMulticast = tsmacread(LM32_TSMAC_TX_MULTICAST_CNT);
620  tsmac->txBroadcast = tsmacread(LM32_TSMAC_TX_BRDCAST_CNT);
621  tsmac->txVLANTag = tsmacread(LM32_TSMAC_TX_VLAN_TAG_CNT);
622  tsmac->txBadFCS = tsmacread(LM32_TSMAC_TX_BAD_FCS_CNT);
623  tsmac->txJumboCnt = tsmacread(LM32_TSMAC_TX_JUMBO_CNT);
624  tsmac->txByteCnt = tsmacread(LM32_TSMAC_TX_BYTE_CNT);
625
626  printk("RX Interrupts:    %8d", tsmac->rxInterrupts);
627  printk(" RX Len Chk Error: %8d", tsmac->rxLenCheckError);
628  printk(" RX Long Frame:    %8d\n", tsmac->rxLongFrame);
629  printk("RX Short Frame:   %8d", tsmac->rxShortFrame);
630  printk(" RX IPG Violation: %8d", tsmac->rxIPGViolation);
631  printk(" RX CRC Errors:    %8d\n", tsmac->rxCRCError);
632  printk("RX OK Packets:    %8d", tsmac->rxOKPackets);
633  printk(" RX Control Frame: %8d", tsmac->rxControlFrame);
634  printk(" RX Pause Frame:   %8d\n", tsmac->rxPauseFrame);
635  printk("RX Multicast:     %8d", tsmac->rxMulticast);
636  printk(" RX Broadcast:     %8d", tsmac->rxBroadcast);
637  printk(" RX VLAN Tag:      %8d\n", tsmac->rxVLANTag);
638  printk("RX Pre Shrink:    %8d", tsmac->rxPreShrink);
639  printk(" RX Dribb. Nibble: %8d", tsmac->rxDribNib);
640  printk(" RX Unsupp. OPCD:  %8d\n", tsmac->rxUnsupOPCD);
641  printk("RX Byte Count:    %8d", tsmac->rxByteCnt);
642  printk(" RX FIFO Full:     %8d\n", tsmac->rxFifoFull);
643
644  printk("TX Interrupts:    %8d", tsmac->txInterrupts);
645  printk(" TX Unicast:       %8d", tsmac->txUnicast);
646  printk(" TX Pause Frame:   %8d\n", tsmac->txPauseFrame);
647  printk("TX Multicast:     %8d", tsmac->txMulticast);
648  printk(" TX Broadcast:     %8d", tsmac->txBroadcast);
649  printk(" TX VLAN Tag:      %8d\n", tsmac->txVLANTag);
650  printk("TX Bad FSC:       %8d", tsmac->txBadFCS);
651  printk(" TX Jumbo Frame:   %8d", tsmac->txJumboCnt);
652  printk(" TX Byte Count:    %8d\n", tsmac->txByteCnt);
653  printk("TX FIFO Full:     %8d\n", tsmac->txFifoFull);
654}
655
656/*
657 * TSMAC ioctl handler
658 */
659
660int tsmac_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
661{
662  struct tsmac_softc *tsmac = ifp->if_softc;
663  int error = 0;
664
665  switch (command) {
666  case SIOCGIFADDR:
667  case SIOCSIFADDR:
668    ether_ioctl (ifp, command, data);
669    break;
670
671  case SIOCSIFFLAGS:
672    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
673    case IFF_RUNNING:
674      tsmac_stop ((struct ifnet *) tsmac);
675      break;
676
677    case IFF_UP:
678      tsmac_init ((struct ifnet *) tsmac);
679      break;
680
681    case IFF_UP | IFF_RUNNING:
682      tsmac_stop ((struct ifnet *) tsmac);
683      tsmac_init ((struct ifnet *) tsmac);
684      break;
685
686    default:
687      break;
688    }
689    break;
690
691  case SIO_RTEMS_SHOW_STATS:
692    tsmac_stats (tsmac);
693    break;
694
695  default:
696    error = EINVAL;
697    break;
698  }
699  return error;
700}
701
702/*
703 * Attach a TSMAC driver
704 */
705int rtems_tsmac_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching)
706{
707  struct tsmac_softc *tsmac;
708  struct ifnet *ifp;
709  int mtu, i;
710  int unit;
711  char *unitName;
712
713  if ((unit = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0)
714    {
715      printk(TSMAC_NAME ": Driver name parsing failed.\n");
716      return 0;
717    }
718
719  if ((unit < 0) || (unit >= TSMAC_NUM))
720    {
721      printk(TSMAC_NAME ": Bad unit number %d.\n", unit);
722      return 0;
723    }
724
725  tsmac = &tsmac_softc[unit];
726
727  ifp = &tsmac->arpcom.ac_if;
728  if (ifp->if_softc != NULL)
729    {
730      printk(TSMAC_NAME ": Driver already in use.\n");
731      return 0;
732    }
733
734  /* Base address for TSMAC */
735  if (config->bpar == 0)
736    {
737      printk(TSMAC_NAME ": Using default base address 0x%08x.\n", TS_MAC_CORE_BASE_ADDRESS);
738      config->bpar = TS_MAC_CORE_BASE_ADDRESS;
739    }
740  tsmac->ioaddr = config->bpar;
741
742  /* Hardware address for TSMAC */
743  if (config->hardware_address == 0)
744    {
745      printk(TSMAC_NAME ": Using default hardware address.\n");
746      tsmac->arpcom.ac_enaddr[0] = TSMAC_MAC0;
747      tsmac->arpcom.ac_enaddr[1] = TSMAC_MAC1;
748      tsmac->arpcom.ac_enaddr[2] = TSMAC_MAC2;
749      tsmac->arpcom.ac_enaddr[3] = TSMAC_MAC3;
750      tsmac->arpcom.ac_enaddr[4] = TSMAC_MAC4;
751      tsmac->arpcom.ac_enaddr[5] = TSMAC_MAC5;
752    }
753  else
754    memcpy(tsmac->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
755
756  printk(TSMAC_NAME ": MAC address ");
757  for (i = 0; i < ETHER_ADDR_LEN; i++)
758    {
759      printk("%02x", tsmac->arpcom.ac_enaddr[i]);
760      if (i != ETHER_ADDR_LEN-1)
761        printk(":");
762      else
763        printk("\n");
764    }
765
766  if (config->mtu)
767    mtu = config->mtu;
768  else
769    mtu = ETHERMTU;
770       
771  /*
772   * Set up network interface values
773   */
774  ifp->if_softc = tsmac;
775  ifp->if_unit = unit;
776  ifp->if_name = unitName;
777  ifp->if_mtu = mtu;
778  ifp->if_init = tsmac_init;
779  ifp->if_ioctl = tsmac_ioctl;
780  ifp->if_start = tsmac_start;
781  ifp->if_output = ether_output;
782  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
783
784  if (ifp->if_snd.ifq_maxlen == 0)
785    ifp->if_snd.ifq_maxlen = ifqmaxlen;
786
787  if_attach(ifp);
788  ether_ifattach(ifp);
789
790  return 1;
791}
792
793rtems_isr tsmac_interrupt_handler(rtems_vector_number vector)
794{
795  struct tsmac_softc *tsmac = &tsmac_softc[0];
796  uint32_t irq_stat, rx_stat, tx_stat;
797
798  irq_stat = tsmacread(LM32_TSMAC_INTR_SRC);
799  if (irq_stat & INTR_RX_PKT_RDY)
800    {
801      tsmac->rxInterrupts++;
802      rtems_event_send(tsmac->rxDaemonTid, INTERRUPT_EVENT);
803    }
804
805  if (irq_stat & INTR_TX_PKT_SENT)
806    {
807      tsmac->txInterrupts++;
808      rtems_event_send(tsmac->txDaemonTid, INTERRUPT_EVENT);
809    }
810
811  rx_stat = tsmacread(LM32_TSMAC_RX_STATUS);
812  if (rx_stat & STAT_RX_FIFO_FULL)
813    tsmac->rxFifoFull++;
814 
815  tx_stat = tsmacread(LM32_TSMAC_TX_STATUS);
816  if (tx_stat & STAT_TX_FIFO_FULL)
817    tsmac->txFifoFull++;
818
819  lm32_interrupt_ack(TSMAC_IRQMASK);
820}
821
Note: See TracBrowser for help on using the repository browser.