if_hpp.c

来自「GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目」· C语言 代码 · 共 691 行 · 第 1/2 页

C
691
字号
{	int s, unit = minor(dev);	struct bus_device 	*bd;	struct hppsoftc 	*hpp;	struct nssoftc		*ns = &hppnssoftc[unit];	int ioaddr = ns->sc_port - HPP_NIC_OFFSET;	int option_reg;	if (unit < 0 || unit >= NHPP ||	    (bd = hpp_info[unit]) == 0 || !(bd->alive))		return ENXIO;	/*	 * Start watchdog.	 */	if (!hppwstart) {		hppwstart++;		timeout(hppwatch, 0, hz);	}	hpp = &hppsoftc[unit];	ns->sc_if.if_flags |= IFF_UP;	s = splimp();	/* Reset the 8390 and HP chip. */	option_reg = inw(ioaddr + HPP_OPTION);	outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) );	IO_DELAY; IO_DELAY;	/* Unreset the board and enable interrupts. */	outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset));	/* Set the wrap registers for programmed-I/O operation.   */	outw( ioaddr + HP_PAGING, HW_Page );	outw( ioaddr + 14, (HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8) );	/* Select the operational page. */	outw( ioaddr + HP_PAGING, Perf_Page );	nsinit(ns);	splx(s);	return (0);}/*  * needs to be called at splimp()? * */voidhpp_reset_8390(ns)	struct nssoftc *ns;{	int ioaddr = ns->sc_port - HPP_NIC_OFFSET;	int option_reg = inw(ioaddr + HPP_OPTION);	outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) );	/* Pause a few cycles for the hardware reset to take place. */	IO_DELAY;	IO_DELAY;	ns->sc_txing = 0;	outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset) );	/*  	 * XXX - I'm not sure there needs to be this many IO_DELAY's...	 */	IO_DELAY; IO_DELAY;	IO_DELAY; IO_DELAY;	if ((inb_p(ioaddr + HPP_NIC_OFFSET + EN0_ISR) & ENISR_RESET) == 0)		printf("%s: hp_reset_8390() did not complete.\n", ns->sc_name);	return;}/*  * Block input and output, similar to the Crynwr packet driver. * Note that transfer with the EtherTwist+ must be on word boundaries.  */voidhpp_io_block_input(ns, count, buf, ring_offset)	struct nssoftc *ns;	int count;	char *buf;	int ring_offset;{	int ioaddr = ns->sc_port - HPP_NIC_OFFSET;	outw(ioaddr + HPP_IN_ADDR, ring_offset);	insw(ioaddr + HP_DATAPORT, buf, count >> 1 );	if (count & 0x01)		  buf[count-1] = (char) inw(ioaddr + HP_DATAPORT);}voidhpp_mem_block_input(ns, count, buf, ring_offset)	struct nssoftc *ns;	int count;	char *buf;	int ring_offset;{	int ioaddr = ns->sc_port - HPP_NIC_OFFSET;	int option_reg = inw(ioaddr + HPP_OPTION);	char *mem_start = (char *)phystokv(hppsoftc[ns->sc_unit].mem_start);		outw(ioaddr + HPP_IN_ADDR, ring_offset);	outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb));	/* copy as much as we can straight through */	bcopy16(mem_start, buf, count & ~1);	/* Now we copy that last byte. */	if (count & 0x01) {	  	u_short savebyte[2];	  	bcopy16(mem_start + (count & ~1), savebyte, 2);	 	buf[count-1] = savebyte[0];	}	outw(ioaddr + HPP_OPTION, option_reg);}/* * output data into NIC buffers. * * NOTE: All transfers must be on word boundaries. */inthpp_io_block_output(ns, count, buf, start_page)	struct nssoftc *ns;	int count;	char *buf;	int start_page;{	int ioaddr = ns->sc_port - HPP_NIC_OFFSET;	outw(ioaddr + HPP_OUT_ADDR, start_page << 8) ;	if (count > 1) {		outsw(ioaddr + HP_DATAPORT, buf, count >> 1);	}	if ( (count & 1) == 1 ) {	  	u_char savebyte[2];		savebyte[1] = 0;		savebyte[0] = buf[count - 1];		outw(ioaddr + HP_DATAPORT, *(u_short *)savebyte); 	}	if (count < (ETHERMIN + sizeof( struct ether_header )))		count = ETHERMIN + sizeof( struct ether_header );	return (count) ;}/* XXX * * I take great pains to not try and bcopy past the end of the buffer, * does this matter?  Are the io request buffers the exact byte size? */inthpp_mem_block_output(ns, count, buf, start_page )	struct nssoftc *ns;	int count;	char *buf;	int start_page;{	int ioaddr = ns->sc_port - HPP_NIC_OFFSET;	int option_reg = inw(ioaddr + HPP_OPTION);	struct hppsoftc *hpp = &hppsoftc[ns->sc_unit];	char *shmem;	outw(ioaddr + HPP_OUT_ADDR, start_page << 8);	outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb));	shmem = (char *)phystokv(hpp->mem_start);	bcopy16(buf, shmem, count & ~1);	if ( (count & 1) == 1 ) {	  	u_char savebyte[2];				savebyte[1] = 0;		savebyte[0] = buf[count - 1];		bcopy16(savebyte, shmem + (count & ~1), 2);	}	while (count < ETHERMIN + sizeof(struct ether_header)) {		*(shmem + count) = 0;		count++;	}	outw(ioaddr + HPP_OPTION, option_reg);	return count;}inthppintr(unit)	int unit;{	nsintr(&hppnssoftc[unit]);		return(0);}voidhppstart(unit)	int unit;{	nsstart(&hppnssoftc[unit]);}int hppoutput();inthppoutput(dev, ior)	dev_t dev;	io_req_t ior;{	int unit = minor(dev);	struct bus_device *ui;	if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)		return (ENXIO);	return (net_write(&hppnssoftc[unit].sc_if, hppstart, ior));}inthppsetinput(dev, receive_port, priority, filter, filter_count)	dev_t dev;	mach_port_t receive_port;	int priority;	filter_t *filter;	unsigned filter_count;{	int unit = minor(dev);	struct bus_device *ui;	if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)		return (ENXIO);	return (net_set_filter(&hppnssoftc[unit].sc_if, receive_port,			       priority, filter, filter_count));}inthppgetstat(dev, flavor, status, count)	dev_t dev;	int flavor;	dev_status_t status;	unsigned *count;{	int unit = minor(dev);	struct bus_device *ui;	if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)		return (ENXIO);	return (net_getstat(&hppnssoftc[unit].sc_if, flavor, status, count));}inthppsetstat(dev, flavor, status, count)	dev_t dev;	int flavor;	dev_status_t status;	unsigned count;{	int unit = minor(dev), oflags, s;	struct bus_device *ui;	struct ifnet *ifp;	struct net_status *ns;	if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)		return (ENXIO);	ifp = &hppnssoftc[unit].sc_if;	switch (flavor) {	case NET_STATUS:		if (count < NET_STATUS_COUNT)			return (D_INVALID_SIZE);		ns = (struct net_status *)status;		oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC);		ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC);		ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC);		if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) {			s = splimp();			nsinit(&hppnssoftc[unit]);			splx(s);		}		break;	default:		return (D_INVALID_OPERATION);	}	return (D_SUCCESS);}/* * Watchdog. * Check for hung transmissions. */voidhppwatch(){	int unit, s;	struct nssoftc *ns;	timeout(hppwatch, 0, hz);	s = splimp();	for (unit = 0; unit < NHPP; unit++) {		if (hpp_info[unit] == 0 || hpp_info[unit]->alive == 0)			continue;		ns = &hppnssoftc[unit];		if (ns->sc_timer && --ns->sc_timer == 0) {			printf("hpp%d: transmission timeout\n", unit);			(*ns->sc_reset)(ns);			nsinit(ns);		}	}	splx(s);}#endif /* NHPP > 0 */

⌨️ 快捷键说明

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