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

📄 cs8900.c

📁 QNX ADS BSP code for i.MX27 chips
💻 C
📖 第 1 页 / 共 2 页
字号:
										BUSCTL_ENBL_IRQ |										( ( i_cnf & I_CNF_ANY_ISA_DMA ) ? BUSCTL_RST_RXDMA : 0 ) |										BUSCTL_ENBL_MEM | 0x200 | /* Fix this								( ( i_cnf & I_CNF_SHARED ) ? BUSCTL_ENBL_MEM : 0 ) | */										( ( i_cnf & I_CNF_ISA_DMA_64K ) ? BUSCTL_RX_DMA_64K : 0 ) );	if (cs8900->cfg.duplex){		cs8900_wpktpage ( iobase, CS8900_TESTCTL, TESTCTL_FDX);	}	return( 0 );}int cs8900_register_device( void *handle, io_net_self_t *ion, void *dll_hdl){	cs8900_dev_t			*cs8900 = (cs8900_dev_t	*)handle;	pthread_attr_t			pattr;	pthread_mutexattr_t		mattr;	struct sched_param		param;	uint16_t				lan;#if 0	timer_t					timerid;	struct sigevent			event;	struct itimerspec		value;#endif	cs8900->ion = ion;	cs8900->dll_hdl = dll_hdl;	if (cs8900_config(cs8900))		return (-1);	if ((cs8900->chid = ChannelCreate(_NTO_CHF_DISCONNECT | _NTO_CHF_UNBLOCK)) == -1 ||	    (cs8900->coid = ConnectAttach(0, 0, cs8900->chid, _NTO_SIDE_CHANNEL, 0)) == -1) {		nic_slogf(_SLOGC_NETWORK, _SLOG_ERROR, "devn-crys8900:  Unable to attach channel and connection");		return (-1);	}#if 0	event.sigev_notify		= SIGEV_PULSE;	event.sigev_code		= NIC_TIMER_EVENT;	event.sigev_coid		= cs8900->coid;	event.sigev_priority	= NIC_PRIORITY;	if( timer_create( CLOCK_REALTIME, &event, &timerid ) == -1 ) {		return( -1 );	}	value.it_value.tv_sec	= value.it_interval.tv_sec	= 2;	value.it_value.tv_nsec	= value.it_interval.tv_nsec	= 0;	if( timer_settime( timerid, 0, &value, NULL ) == -1 ) {		return( -1 );	}#endif	pthread_mutexattr_init( &mattr );	mattr.flags = PTHREAD_RECURSIVE_ENABLE;	if (pthread_mutex_init(&cs8900->mutex, &mattr) == -1) {		nic_slogf(_SLOGC_NETWORK, _SLOG_ERROR, "devn-crys8900:  Unable to initialize mutex");		return (-1);	}	pthread_attr_init(&pattr);	pthread_attr_setschedpolicy(&pattr, SCHED_RR);	param.sched_priority = cs8900->cfg.priority;	pthread_attr_setschedparam(&pattr, &param);	pthread_attr_setinheritsched(&pattr, PTHREAD_EXPLICIT_SCHED);	cs8900->event.sigev_notify	= SIGEV_PULSE;	cs8900->event.sigev_coid	= cs8900->coid;	cs8900->event.sigev_code	= NIC_INTERRUPT_EVENT;	cs8900->event.sigev_priority	= cs8900->cfg.priority;	cs8900_initialize( cs8900 );	/* create the interface thread */	if (pthread_create(&cs8900->tid, &pattr, (void *)cs8900_driver_thread, cs8900)) {		nic_slogf(_SLOGC_NETWORK, _SLOG_ERROR, "devn-crys8900:  Unable to create driver thread");		return (-1);	}	cs8900_entry.func_hdl = (void *) cs8900;	cs8900_entry.top_type = cs8900->cfg.uptype;	if ( cs8900->cfg.lan != -1 ) {		cs8900_entry.flags |= _REG_ENDPOINT_ARG ;		lan = cs8900->cfg.lan;	}	if (ion_register(dll_hdl, &cs8900_entry, &cs8900->reg_hdl, &cs8900->cell, &lan) < 0)		return (-1);	if (!cs8900->max_pkts)		cs8900->max_pkts = 100;	cs8900->ion->devctl(cs8900->reg_hdl, DCMD_IO_NET_MAX_QUEUE,                          &cs8900->max_pkts, sizeof(cs8900->max_pkts), NULL);	cs8900->cfg.lan = lan;	if ((cs8900->iid = InterruptAttachEvent(cs8900->cfg.irq[0], &cs8900->event, _NTO_INTR_FLAGS_TRK_MSK)) == -1) {		nic_slogf(_SLOGC_NETWORK, _SLOG_ERROR, "devn-crys8900: InterruptAttachEvent failed");		perror("InterruptAttachEvent failed\n");		return (-1);	}	return (0);}void cs8900_process_interrupt( void *handle ){	int					status;	int					iobase;	nic_ethernet_stats_t	*estats;	cs8900_dev_t		*cs8900 = (cs8900_dev_t *)handle;	estats	= &cs8900->stats.un.estats;	iobase	= cs8900->iobase;	while( cs8900->istat = status = inle16( iobase + CS8900_PORT_ISQ ) ) {		switch( status & ISQ_EVENT_MASK ) {			case ISQ_RXEVENT:				cs8900_receive( cs8900 );				break;			case ISQ_TXEVENT:				cs8900_transmit_complete( cs8900 );				break;			case ISQ_BUFEVENT:				if( status & BUFEVENT_RXDMA ) {					cs8900_receive( cs8900 );				}				/* We check BusST Rdy4TxNow since revision B of the CS8920 */				/* has a problem where the Rdy4Tx interrupt may not occur */				/* every time when DMA is used for receive operation. */				if( ( status & BUFEVENT_RDY4TX ) || ( cs8900_rpktpage( iobase, CS8900_BUSST ) & BUSSTAT_RDY4TXNOW ) ) {					cs8900_variant_load( cs8900 );				}				if( status & BUFEVENT_TXUNDERRUN ) {					estats->internal_tx_errors++;					cs8900_transmit_complete( cs8900 );				}				break;			case ISQ_RXMISS:				estats->internal_rx_errors += ( status >> 6 );				break;			case ISQ_TXCOLL:				estats->single_collisions += ( status >> 6 );				break;		}	}	InterruptUnmask( cs8900->cfg.irq[0], cs8900->iid );}void cs8900_event_handler( void *handle ){	struct _pulse		pulse;	iov_t				iov;	int					rcvid;	cs8900_dev_t		*cs8900 = (cs8900_dev_t *)handle;	SETIOV( &iov, &pulse, sizeof( pulse ) );	while( 1 ) {		if( ( rcvid = MsgReceivev( cs8900->chid, &iov, 1, NULL ) ) == -1 ) {			if( errno == ESRCH ) {				pthread_exit( NULL );			}			continue;		}				pthread_mutex_lock( &cs8900->mutex );		switch( pulse.code ) {			case NIC_INTERRUPT_EVENT:				cs8900_process_interrupt( cs8900 );				break;/*			case NIC_TIMER_EVENT: *//*				cs8900_timer( cs8900 ); *//*				break; */			default:				if( rcvid ) {					MsgReplyv( rcvid, ENOTSUP, &iov, 1 );				}				break;		}		pthread_mutex_unlock( &cs8900->mutex );	}}void *cs8900_driver_thread( void *data ){	cs8900_event_handler( (cs8900_dev_t *)data );	return( NULL );}int cs8900_flush( int reg_hdl, void *hdl ){	cs8900_dev_t	*cs8900 = (cs8900_dev_t *)hdl;	npkt_t				*npkt;	npkt_t				*tmp;	pthread_mutex_lock( &cs8900->mutex );	npkt = cs8900->nhead;	cs8900->nhead = cs8900->ntail = NULL;	pthread_mutex_unlock( &cs8900->mutex );	for( ; npkt; npkt = tmp ) {		tmp = npkt->next;		ion_tx_complete(cs8900->reg_hdl, npkt);	}	return( 0 );}int cs8900_setup_multicast( void *handle ){	cs8900_dev_t	*cs8900 = (cs8900_dev_t *)handle;	uint8_t			hash_table[8];	int				linectl, iobase, i;    iobase = cs8900->iobase;    memset (hash_table, 0, sizeof(hash_table));    for (i = 0; i < CS8900_MULTICAST_ENTRIES; i++) {        if (cs8900->multicast_counts[i])            hash_table[i >> 3] |= (1 << (i & 7));    } 	/* Disable the receiver */	linectl = cs8900_rpktpage( iobase, CS8900_LINECTL );	linectl &= ~LINECTL_RXON;	cs8900_wpktpage( iobase, CS8900_LINECTL, linectl );	/* Program the Hash Table */	for (i = 0; i < 8; i++) {        outle16(iobase + CS8900_PORT_PKTPG, CS8900_LAF + i);        out8(iobase + CS8900_PORT_PKTPG_DATA, hash_table[i]);    }    /* Enable the receiver */    linectl |= LINECTL_RXON;    cs8900_wpktpage(iobase, CS8900_LINECTL, linectl);    return 0;}npkt_t *cs8900_alloc_npkt(void *handle, size_t size){	cs8900_dev_t	*cs8900 = (cs8900_dev_t *) handle;	npkt_t				*npkt;	net_buf_t			*nb;	net_iov_t			*iov;	char				*ptr;	if ((npkt = ion_alloc_npkt(sizeof(net_buf_t) + sizeof(net_iov_t), (void **) &nb)) == NULL)		return (NULL);	if ((ptr = ion_alloc(size, 0)) == NULL) {		ion_free(npkt);		return(NULL);	}	TAILQ_INSERT_HEAD(&npkt->buffers, nb, ptrs);	iov = (net_iov_t *)(nb + 1);	nb->niov        = 1;	nb->net_iov     = iov;	iov->iov_base   = (void *) ptr;	iov->iov_len    = size;	iov->iov_phys   = (paddr_t)(ion_mphys(iov->iov_base));	npkt->org_data  = ptr;	npkt->next      = NULL;	npkt->tot_iov	= 1;	return (npkt);}int cs8900_advertise(int reg_hdl, void *func_hdl){	npkt_t					*npkt;	net_buf_t				*nb;	net_iov_t				*iov;	cs8900_dev_t			*cs8900 = (cs8900_dev_t *) func_hdl;	io_net_msg_dl_advert_t	*ap;	if ((npkt = ion_alloc_npkt(sizeof(*nb) + sizeof *iov, (void **)&nb)) == NULL)		return(0);	if ((ap = ion_alloc(sizeof(*ap), 0)) == NULL) {		ion_free(npkt);		return (0);	}	TAILQ_INSERT_HEAD(&npkt->buffers, nb, ptrs);	iov = (net_iov_t *)(nb + 1);	nb->niov = 1;	nb->net_iov = iov;	iov->iov_base = ap;	iov->iov_len = sizeof *ap;	memset(ap, 0x00, sizeof *ap);	ap->type   = _IO_NET_MSG_DL_ADVERT;	ap->iflags = (IFF_SIMPLEX | IFF_BROADCAST | IFF_RUNNING);	if (cs8900->cfg.flags & NIC_FLAG_MULTICAST) 		ap->iflags |= IFF_MULTICAST;	ap->mtu_min       = 0;	ap->mtu_max       = cs8900->cfg.mtu;	ap->mtu_preferred = cs8900->cfg.mtu;	strcpy(ap->up_type, cs8900->cfg.uptype);	itoa(cs8900->cfg.lan, ap->up_type + 2, 10);	strcpy(ap->dl.sdl_data, ap->up_type);	ap->dl.sdl_len = sizeof(struct sockaddr_dl);	ap->dl.sdl_family = AF_LINK;	ap->dl.sdl_index  = cs8900->cfg.lan;	ap->dl.sdl_type = IFT_ETHER;	ap->dl.sdl_nlen = strlen(ap->dl.sdl_data); /* not null terminated */	ap->dl.sdl_alen = 6;	memcpy(ap->dl.sdl_data + ap->dl.sdl_nlen, cs8900->cfg.current_address, 6);	npkt->org_data = ap;	npkt->flags |= _NPKT_MSG;	npkt->iface = 0;	npkt->tot_iov = 1;	npkt->framelen = sizeof *ap;	if (ion_add_done( cs8900->reg_hdl, npkt, cs8900 ) == -1) {		ion_free(ap);		ion_free(npkt);		return(0);	}	atomic_add(&cs8900->rx_active, 1);	if (ion_rx_packets(cs8900->reg_hdl, npkt, 0, 0, cs8900->cell, cs8900->cfg.lan, 0) == 0)		ion_tx_complete(cs8900->reg_hdl, npkt);	return(0);}int cs8900_rpktpage( int iobase, int portno ){	outle16( iobase + CS8900_PORT_PKTPG, portno );	return( inle16( iobase + CS8900_PORT_PKTPG_DATA ) );}void cs8900_wpktpage( int iobase, int portno, int value ){	outle16( iobase + CS8900_PORT_PKTPG, portno );	outle16( iobase + CS8900_PORT_PKTPG_DATA, value );}#ifdef __X86__static const struct _8237_regs{	int  maddr;			/* memory address register */	int  tcount;		/* terminal count register */	int  pagereg;		/* dma page select register */	int  stat;			/* status register */	int  mask;			/* mask register */	int  mode;			/* mode register */	int  sync_cmd;		/* Synchronize HI/LOW register access */	int  reset_cmd;		/* Reset the 8237 */	int  enable_cmd;	/* enable all dma channels */	int  set_mask;		/* write mask register */} _8237_regtable[] = {	/*   addr  count page  stat/cmd mask  mode  sync  rst   enable wmask */	{    0x00, 0x01, 0x87, 0x08,    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },	{    0x02, 0x03, 0x83, 0x08,    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },	{    0x04, 0x05, 0x81, 0x08,    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },	{    0x06, 0x07, 0x82, 0x08,    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },	{    0xc0, 0xc2, 0x8f, 0xd0,    0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde },	{    0xc4, 0xc6, 0x8b, 0xd0,    0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde },	{    0xc8, 0xca, 0x89, 0xd0,    0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde },	{    0xcc, 0xce, 0x8a, 0xd0,    0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde }};#define DMA_READ			0x08		/* xfer memory to I/O device */#define DMA_WRITE			0x04		/* xfer I/O device to memory */void setup_8237( int mode, int chnl, paddr_t dptr, int cnt ){	const struct _8237_regs	*dp;	ushort_t				page;	ushort_t				addr;	dp		= _8237_regtable + chnl;    page	= dptr >> 16;	addr	= dptr >> 1;	if( chnl > 3 ) {		chnl &= 3;		cnt /= 2;	}    cnt--;	out8( dp->mask, 0x04 | chnl );	out8( dp->sync_cmd, 0 );					/* reset flip flop */	out8( dp->mode, mode | chnl );	out8( dp->maddr, addr );	out8( dp->maddr, addr >> 8 );	out8( dp->pagereg, page );	out8( dp->tcount, cnt );	out8( dp->tcount, cnt >> 8 );	out8( dp->mask, chnl );}#endif/***************************************************************************** All multicast processing.                                                ****************************************************************************/int cs8900_do_multicast (cs8900_dev_t *cs8900, struct _io_net_msg_mcast *msg, int *ret){	return (ENOTSUP);}

⌨️ 快捷键说明

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