⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smc91111.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
			continue;		}	} while (0);	db4_printf(">+Tx packet allocated %x (previous %x)\n",		   packet, cpd->txpacket);	cpd->txpacket = packet;	/* ############ assemble packet data ############ */	/* prepare send */	put_reg(cpd, LAN91CXX_PNR, packet);	/* Note: Check FIFO state here before continuing? */	put_reg(cpd, LAN91CXX_POINTER, LAN91CXX_POINTER_AUTO_INCR | 0x0000);	/* Pointer is now set, and the proper bank is selected for */	/* data writes. */	/* Prepare header: */	put_data(cpd, CYG_CPU_TO_LE16(0));	/* reserve space for status word */	/* packet length (includes status, byte-count and control shorts) */	put_data(cpd, CYG_CPU_TO_LE16(0x7FE & (plen + 6)));	/* Always even, always < 15xx(dec) */	/* Put data into buffer */	n = m;	while (n) {		sdata = (unsigned short *)n->m_data;		len = n->m_len;		CYG_ASSERT((0 == (len & 1)			    || !(n->m_next)), "!odd length");		CYG_ASSERT(sdata, "!No sg data pointer here");		while (len >= sizeof(*sdata)) {			put_data(cpd, *sdata++);			len -= sizeof(*sdata);		}		n = n->m_next;	}#if DEBUG & 64	n = m;	while (n) {		int lp = 0;		unsigned char *start = (unsigned char *)n->m_data;		len = n->m_len;		while (len > 0) {			unsigned char a = *(start++);			unsigned char b = *(start++);			db64_printf("%02x %02x ", a, b);			lp += 2;			if (lp >= 16) {				db64_printf("\n");				lp = 0;			}			len -= 2;		}		n = n->m_next;	}	db64_printf(" \n");#endif	m_freem(m);	CYG_ASSERT(sdata, "!No sg data pointer outside");	/* Lay down the control short unconditionally at the end. */	/* (or it might use random memory contents) */	control = 0;	if (1 & plen) {		/* Need to set ODD flag and insert the data */		unsigned char onebyte = *(unsigned char *)sdata;		control = onebyte;		control |= LAN91CXX_CONTROLBYTE_ODD;	}	control |= LAN91CXX_CONTROLBYTE_CRC;	/* Just in case... */	put_data(cpd, CYG_CPU_TO_LE16(control));	/* ############ start transmit ############ */	/* Ack TX empty int and unmask it. */	ints = get_reg(cpd, LAN91CXX_INTERRUPT) & 0xff00;	put_reg(cpd, LAN91CXX_INTERRUPT,		ints | LAN91CXX_INTERRUPT_TX_EMPTY_INT);	put_reg(cpd, LAN91CXX_INTERRUPT, ints | LAN91CXX_INTERRUPT_TX_INT_M);	/* notify on error only (Autorelease) */	/* Enqueue the packet */	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_enq_packet);	ints = get_reg(cpd, LAN91CXX_INTERRUPT);	db1_printf(">END: ints at TX: %04x\n", ints);	dbg_prefix = "";}void smc91111_txDaemon(void *arg){	struct lan91cxx_priv_data *cpd = arg;	struct ifnet *ifp = &cpd->arpcom.ac_if;	struct mbuf *m;	rtems_event_set events;	DEBUG_FUNCTION();	for (;;) {		/*		 * Wait for packet		 */		rtems_bsdnet_event_receive		    (SMC91111_START_TRANSMIT_EVENT,		     RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);		/*IF_DEQUEUE (&ifp->if_snd, m);		   if (m) {		   sendpacket (ifp, m);		   } */		for (;;) {			IF_DEQUEUE(&ifp->if_snd, m);			if (!m)				break;			sendpacket(ifp, m);		}		ifp->if_flags &= ~IFF_OACTIVE;	}}/* start transmit */static void smc91111_start(struct ifnet *ifp){	struct lan91cxx_priv_data *cpd = ifp->if_softc;	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)		return;	rtems_event_send(cpd->txDaemonTid, START_TRANSMIT_EVENT);	ifp->if_flags |= IFF_OACTIVE;}/* called after a tx error interrupt, freet the packet */static void lan91cxx_finish_sent(struct lan91cxx_priv_data *cpd){	unsigned short packet, tcr;	int success = 1;	int saved_packet;	DEBUG_FUNCTION();	INCR_STAT(cpd, tx_complete);	saved_packet = get_reg(cpd, LAN91CXX_PNR);	/* Ack and mask TX interrupt set */	/*ints = get_reg(cpd, LAN91CXX_INTERRUPT) & 0xff00;	   ints |= LAN91CXX_INTERRUPT_TX_SET_ACK;	   ints &= ~LAN91CXX_INTERRUPT_TX_SET_M;	   put_reg(cpd, LAN91CXX_INTERRUPT, ints); */	/* Get number of completed packet and read the status word */	packet = get_reg(cpd, LAN91CXX_FIFO_PORTS);	db1_printf("%s:START: fifo %04x \n", __FUNCTION__, packet);	{		unsigned short reg;		reg = get_reg(cpd, LAN91CXX_EPH_STATUS);		/* Covering each bit in turn... */		if (reg & LAN91CXX_STATUS_TX_UNRN)			INCR_STAT(cpd, tx_underrun);		if (reg & LAN91CXX_STATUS_LOST_CARR)			INCR_STAT(cpd, tx_carrier_loss);		if (reg & LAN91CXX_STATUS_LATCOL)			INCR_STAT(cpd, tx_late_collisions);		if (reg & LAN91CXX_STATUS_TX_DEFR)			INCR_STAT(cpd, tx_deferred);		if (reg & LAN91CXX_STATUS_SQET)			INCR_STAT(cpd, tx_sqetesterrors);		if (reg & LAN91CXX_STATUS_16COL)			INCR_STAT(cpd, tx_max_collisions);		if (reg & LAN91CXX_STATUS_MUL_COL)			INCR_STAT(cpd, tx_mult_collisions);		if (reg & LAN91CXX_STATUS_SNGL_COL)			INCR_STAT(cpd, tx_single_collisions);		if (reg & LAN91CXX_STATUS_TX_SUC)			INCR_STAT(cpd, tx_good);		cpd->stats.tx_total_collisions =		    cpd->stats.tx_late_collisions +		    cpd->stats.tx_max_collisions +		    cpd->stats.tx_mult_collisions +		    cpd->stats.tx_single_collisions;		/* We do not need to look in the Counter Register (LAN91CXX_COUNTER)		   because it just mimics the info we already have above. */	}	/* We do not really care about Tx failure.  Ethernet is not a reliable	   medium.  But we do care about the TX engine stopping. */	tcr = get_reg(cpd, LAN91CXX_TCR);	if (0 == (LAN91CXX_TCR_TXENA & tcr)) {		db1_printf("%s: ENGINE RESTART: tcr %x \n", __FUNCTION__, tcr);		tcr |= LAN91CXX_TCR_TXENA;		put_reg(cpd, LAN91CXX_TCR, tcr);		success = 0;	/* And treat this as an error... */	}	packet &= 0xff;	/* and then free the packet */	put_reg(cpd, LAN91CXX_PNR, cpd->txpacket);	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_rel_packet);	while (get_reg(cpd, LAN91CXX_MMU_COMMAND) & LAN91CXX_MMU_COMMAND_BUSY) ;	/* Don't change Packet Number Reg until busy bit is cleared */	/* Per LAN91C111 Spec, Page 50 */	put_reg(cpd, LAN91CXX_PNR, saved_packet);}/* \ ------------- Helpers ------------- \ *//* * Show interface statistics */static void smc91111_stats(struct lan91cxx_priv_data *priv){	printf("tx_good             :%-8d", priv->stats.tx_good);	printf("tx_max_collisions   :%-8d", priv->stats.tx_max_collisions);	printf("tx_late_collisions  :%-8d", priv->stats.tx_late_collisions);	printf("tx_underrun         :%-8d", priv->stats.tx_underrun);	printf("tx_carrier_loss     :%-8d", priv->stats.tx_carrier_loss);	printf("tx_deferred         :%-8d", priv->stats.tx_deferred);	printf("tx_sqetesterrors    :%-8d", priv->stats.tx_sqetesterrors);	printf("tx_single_collisions:%-8d", priv->stats.tx_single_collisions);	printf("tx_mult_collisions  :%-8d", priv->stats.tx_mult_collisions);	printf("tx_total_collisions :%-8d", priv->stats.tx_total_collisions);	printf("rx_good             :%-8d", priv->stats.rx_good);	printf("rx_crc_errors       :%-8d", priv->stats.rx_crc_errors);	printf("rx_align_errors     :%-8d", priv->stats.rx_align_errors);	printf("rx_resource_errors  :%-8d", priv->stats.rx_resource_errors);	printf("rx_overrun_errors   :%-8d", priv->stats.rx_overrun_errors);	printf("rx_collisions       :%-8d", priv->stats.rx_collisions);	printf("rx_short_frames     :%-8d", priv->stats.rx_short_frames);	printf("rx_too_long_frames  :%-8d", priv->stats.rx_too_long_frames);	printf("rx_symbol_errors    :%-8d", priv->stats.rx_symbol_errors);	printf("interrupts          :%-8d", priv->stats.interrupts);	printf("rx_count            :%-8d", priv->stats.rx_count);	printf("rx_deliver          :%-8d", priv->stats.rx_deliver);	printf("rx_resource         :%-8d", priv->stats.rx_resource);	printf("rx_restart          :%-8d", priv->stats.rx_restart);	printf("tx_count            :%-8d", priv->stats.tx_count);	printf("tx_complete         :%-8d", priv->stats.tx_complete);	printf("tx_dropped          :%-8d", priv->stats.tx_dropped);}/* * Driver ioctl handler */static int smc91111_ioctl(struct ifnet *ifp, int command, caddr_t data){	struct lan91cxx_priv_data *cpd = ifp->if_softc;	int error = 0;	DEBUG_FUNCTION();	switch (command) {	case SIOCGIFADDR:	case SIOCSIFADDR:		db_printf("SIOCSIFADDR\n");		ether_ioctl(ifp, command, data);		break;	case SIOCSIFFLAGS:		db_printf("SIOCSIFFLAGS\n");		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {		case IFF_RUNNING:			smc91111_stop(cpd);			break;		case IFF_UP:			smc91111_init(cpd);			break;		case IFF_UP | IFF_RUNNING:			smc91111_stop(cpd);			smc91111_init(cpd);			break;		default:			break;		}		break;	case SIO_RTEMS_SHOW_STATS:		db_printf("SIO_RTEMS_SHOW_STATS\n");		smc91111_stats(cpd);		break;		/*		 * FIXME: All sorts of multicast commands need to be added here!		 */	default:		error = EINVAL;		break;	}	return error;}/* * Attach an SMC91111 driver to the system */int _rtems_smc91111_driver_attach (struct rtems_bsdnet_ifconfig *config,                                  struct scmv91111_configuration * chip){	struct ifnet *ifp;	struct lan91cxx_priv_data *cpd;	int unitNumber;	char *unitName;	int mtu;	DEBUG_FUNCTION();/* 	/\* activate io area *\/ *//* 	switch (sparc_leon23_get_psr_version()) { *//* 	case 0: *//* 	case 2: *//* 		db_printf("Activating Leon2 io port\n"); *//* 		/\*configure pio *\/ *//* 		*((volatile unsigned int *)0x80000000) |= 0x10f80000; *//* 		*((volatile unsigned int *)0x800000A8) |= *//* 		    (0xe0 | chip->vector) << (8 * (chip->pio - 4)); *//* 		break; *//* 	default: *//* 		{ *//* 			unsigned long irq_pio, irq_mctrl, addr_pio, addr_mctrl; *//* 			if ((addr_pio = *//* 			     amba_find_apbslv_addr(VENDOR_GAISLER, *//* 						   GAISLER_PIOPORT, &irq_pio)) *//* 			    && (addr_mctrl = *//* 				amba_find_apbslv_addr(VENDOR_ESA, *//* 						      ESA_MCTRL, &irq_mctrl))) { *//* 				LEON3_IOPORT_Regs_Map *io = *//* 				    (LEON3_IOPORT_Regs_Map *) addr_pio; *//* 				db_printf *//* 				    ("Activating Leon3 io port for smsc_lan91cxx (pio:%x mctrl:%x)\n", *//* 				     (unsigned int)addr_pio, *//* 				     (unsigned int)addr_mctrl); *//* 				*((volatile unsigned int *)addr_mctrl) |= 0x10f80000;	/\*mctrl ctrl 1 *\/ *//* 				io->irqmask |= (1 << chip->pio); *//* 				io->irqpol |= (1 << chip->pio); *//* 				io->irqedge |= (1 << chip->pio); *//* 				io->iodir &= ~(1 << chip->pio); *//* 			} else { *//* 				return 0; *//* 			} *//* 		} *//* 	} */	/* parse driver name */	if ((unitNumber =	     rtems_bsdnet_parse_driver_name(config, &unitName)) < 0) {		db_printf("Unitnumber < 0: %d\n", unitNumber);		return 0;	}	db_printf("Unitnumber: %d, baseaddr: 0x%p\n", unitNumber, chip->baseaddr);	cpd = &smc91111;	ifp = &cpd->arpcom.ac_if;	memset(cpd, 0, sizeof(*cpd));	cpd->config = *chip;	cpd->base = chip->baseaddr;	if (smc_probe(cpd)) {		return 0;	}	if (config->hardware_address) {		memcpy(cpd->arpcom.ac_enaddr, config->hardware_address,		       ETHER_ADDR_LEN);	} else {		/* dummy default address */		cpd->arpcom.ac_enaddr[0] = 0x12;		cpd->arpcom.ac_enaddr[1] = 0x13;		cpd->arpcom.ac_enaddr[2] = 0x14;		cpd->arpcom.ac_enaddr[3] = 0x15;		cpd->arpcom.ac_enaddr[4] = 0x16;		cpd->arpcom.ac_enaddr[5] = 0x17;	}	cpd->enaddr[0] = cpd->arpcom.ac_enaddr[0];	cpd->enaddr[1] = cpd->arpcom.ac_enaddr[1];	cpd->enaddr[2] = cpd->arpcom.ac_enaddr[2];	cpd->enaddr[3] = cpd->arpcom.ac_enaddr[3];	cpd->enaddr[4] = cpd->arpcom.ac_enaddr[4];	cpd->enaddr[5] = cpd->arpcom.ac_enaddr[5];	cpd->rpc_cur_mode =	    LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK |	    LAN91CXX_RPCR_ANEG;	if (config->mtu)		mtu = config->mtu;	else		mtu = ETHERMTU;	/*	 * Set up network interface values	 */	ifp->if_softc = cpd;	ifp->if_unit = unitNumber;	ifp->if_name = unitName;	ifp->if_mtu = mtu;	ifp->if_init = smc91111_init;	ifp->if_ioctl = smc91111_ioctl;	ifp->if_start = smc91111_start;	ifp->if_output = ether_output;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;	if (ifp->if_snd.ifq_maxlen == 0)		ifp->if_snd.ifq_maxlen = ifqmaxlen;	/*	 * Attach the interface	 */	if_attach(ifp);	ether_ifattach(ifp);#ifdef DEBUG	printf("SMC91111 : driver has been attached\n");#endif	return 1;};/* \ ------------- Initialization ------------- \ *//* * Initialize and start the device */static void smc91111_init(void *arg){	struct lan91cxx_priv_data *cpd = arg;	struct ifnet *ifp = &cpd->arpcom.ac_if;	DEBUG_FUNCTION();	if (cpd->txDaemonTid == 0) {		lan91cxx_hardware_init(cpd);		lan91cxx_start(ifp);		cpd->rxDaemonTid = rtems_bsdnet_newproc("DCrx", 4096,							smc91111_rxDaemon, cpd);		cpd->txDaemonTid =		    rtems_bsdnet_newproc("DCtx", 4096, smc91111_txDaemon, cpd);	}	/*	 * Tell the world that we're running.	 */	ifp->if_flags |= IFF_RUNNING;}/* * Stop the device */static void smc91111_stop(struct lan91cxx_priv_data *cpd){	struct ifnet *ifp = &cpd->arpcom.ac_if;	DEBUG_FUNCTION();	ifp->if_flags &= ~IFF_RUNNING;	/* Reset chip */	put_reg(cpd, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST);	put_reg(cpd, LAN91CXX_RCR, 0);	cpd->txbusy = cpd->within_send = 0;}int lan91cxx_hardware_init(struct lan91cxx_priv_data *cpd){	unsigned short val;	int i;	DEBUG_FUNCTION();	cpd->txbusy = cpd->within_send = 0;	/* install interrupt vector */	db_printf("Install lan91cxx irqvector at %d\n", cpd->config.vector);	set_vector(lan91cxx_interrupt_handler, cpd->config.vector, 1);	/* Reset chip */	put_reg(cpd, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST);	put_reg(cpd, LAN91CXX_RCR, 0);	HAL_DELAY_US(100000);	put_reg(cpd, LAN91CXX_CONFIG, 0x9000);	put_reg(cpd, LAN91CXX_RCR, 0);	put_reg(cpd, LAN91CXX_TCR, 0);	put_reg(cpd, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu);	val = get_reg(cpd, LAN91CXX_EPH_STATUS);	/* probe chip by reading the signature in BS register */	val = get_banksel(cpd);	db9_printf("LAN91CXX - supposed BankReg @ %x = %04x\n",		   (unsigned int)(cpd->base + LAN91CXX_BS), val);	if ((0xff00 & val) != 0x3300) {		printf("No 91Cxx signature");		printf("smsc_lan91cxx_init: No 91Cxx signature found\n");		return 0;	}	val = get_reg(cpd, LAN91CXX_REVISION);	db9_printf("LAN91CXX - type: %01x, rev: %01x\n",		   (val >> 4) & 0xf, val & 0xf);	/* Set RevA flag for LAN91C111 so we can cope with the odd-bit bug. */	cpd->c111_reva = (val == 0x3390);	/* The controller may provide a function used to set up the ESA */	if (cpd->config_enaddr)		(*cpd->config_enaddr) (cpd);	db9_printf("LAN91CXX - status: %04x\n", val);	/* Use statically configured ESA from the private data */	db9_printf	    ("LAN91CXX - static ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",	     cpd->enaddr[0], cpd->enaddr[1], cpd->enaddr[2],

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -