fore_load.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,621 行 · 第 1/3 页

C
1,621
字号
/* * * =================================== * HARP  |  Host ATM Research Platform * =================================== * * * This Host ATM Research Platform ("HARP") file (the "Software") is * made available by Network Computing Services, Inc. ("NetworkCS") * "AS IS".  NetworkCS does not provide maintenance, improvements or * support of any kind. * * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. * In no event shall NetworkCS be responsible for any damages, including * but not limited to consequential damages, arising from or relating to * any use of the Software or related support. * * Copyright 1994-1998 Network Computing Services, Inc. * * Copies of this Software may be made, however, the above copyright * notice must be reproduced on all copies. * *	@(#) $Id: fore_load.c,v 1.5 1998/12/14 06:37:37 dillon Exp $ * *//* * FORE Systems 200-Series Adapter Support * --------------------------------------- * * Loadable kernel module and device identification support * */#include <dev/hfa/fore_include.h>#ifndef lint__RCSID("@(#) $Id: fore_load.c,v 1.5 1998/12/14 06:37:37 dillon Exp $");#endif/* * Local functions */static int	fore_start __P((void));#ifdef sunstatic int	fore_stop __P((void));static int	fore_doload __P((void));static int	fore_dounload __P((void));static int	fore_identify __P((char *));static int	fore_attach __P((struct devinfo *));#endif#ifdef __FreeBSD__static const char *	fore_pci_probe __P((pcici_t, pcidi_t));static void	fore_pci_attach __P((pcici_t, int));#if BSD < 199506static int	fore_pci_shutdown __P((struct kern_devconf *, int));#elsestatic void	fore_pci_shutdown __P((int, void *));#endif#endifstatic void	fore_unattach __P((Fore_unit *));static void	fore_reset __P((Fore_unit *));/* * Local variables */static int	fore_inited = 0;/* * Driver entry points */#ifdef sunstatic struct dev_ops	fore_ops = {	1,		/* revision */	fore_identify,	/* identify */	fore_attach,	/* attach */	NULL,		/* open */	NULL,		/* close */	NULL,		/* read */	NULL,		/* write */	NULL,		/* strategy */	NULL,		/* dump */	NULL,		/* psize */	NULL,		/* ioctl */	NULL,		/* reset */	NULL		/* mmap */};#endif#ifdef __FreeBSD__static	u_long	fore_pci_count = 0;static struct pci_device fore_pci_device = {	FORE_DEV_NAME,	fore_pci_probe,	fore_pci_attach,	&fore_pci_count,#if BSD < 199506	fore_pci_shutdown#else	NULL#endif};DATA_SET(pcidevice_set, fore_pci_device);#endif/* * Initialize driver processing *  * This will be called during module loading.  Not much to do here, as * we must wait for our identify/attach routines to get called before * we know what we're in for. * * Arguments: *	none * * Returns: *	0 	startup was successful  *	errno	startup failed - reason indicated * */static intfore_start(){	/*	 * Verify software version	 */	if (atm_version != ATM_VERSION) {		log(LOG_ERR, "version mismatch: fore=%d.%d kernel=%d.%d\n",			ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),			ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));		return (EINVAL);	}	/*	 * Initialize DMA mapping	 */	DMA_INIT();	/*	 * Start up watchdog timer	 */	atm_timeout(&fore_timer, ATM_HZ * FORE_TIME_TICK, fore_timeout);	fore_inited = 1;	return (0);}#ifdef sun/* * Halt driver processing  *  * This will be called just prior to unloading the module from memory. * Everything we've setup since we've been loaded must be undone here. * * Arguments: *	none * * Returns: *	0 	shutdown was successful  *	errno	shutdown failed - reason indicated * */static intfore_stop(){	int	err = 0;	int	s = splimp();	int	i;	/*	 * Stop the watchdog timer	 */	(void) atm_untimeout(&fore_timer);	/*	 * Clean up each device (if any)	 */	for ( i = 0; i < fore_nunits; i++ ) {		Fore_unit	*fup = fore_units[i];		if (fup == NULL)			continue;		/*		 * Deregister device from kernel services		 */		if (err = atm_physif_deregister((Cmn_unit *)fup)) {			(void) splx(s);			return (err);		}		/*		 * Unattach the device from the system		 */		fore_unattach(fup);		/*		 * Free any Fore-specific device resources		 */		fore_interface_free(fup);		/*		 * Free the unit structure		 */		atm_dev_free(fup);		fore_units[i] = NULL;	}	fore_nunits = 0;	/*	 * Now free our global resources	 */	/*	 * Release our storage pools	 */	atm_release_pool(&fore_vcc_pool);	atm_release_pool(&fore_nif_pool);	/*	 * Release all DMA mappings	 */	DMA_RELEASE();	fore_inited = 0;	(void) splx(s);	return (0);}/* * Device identify routine *  * Determine if this driver will support the named device.  If we claim to * support the device, our attach routine will (later) be called for the * device. * * Arguments: *	name	pointer to identifier string from device * * Returns: *	1 	driver claims support for this device *	0	device not claimed by this driver * */static intfore_identify(name)	char	*name;{	int	ret = 0;	int	i = 0;	/*	 * Initialize driver stuff	 */	if (fore_inited == 0) {		if (fore_start())			return (0);	}	while (fore_devices[i].fd_name) {		if (strcmp(fore_devices[i].fd_name, name) == 0) {			/*			 * We support this device!!			 */			if (fore_nunits < FORE_MAX_UNITS) {				fore_nunits++;				ret = 1;			} else {				log(LOG_ERR,					"fore_identify: Too many devices\n");			}			break;		}		i++;	}	return (ret);}/* * Device attach routine *  * Attach a device we've previously claimed to support.  Walk through its * register set and map, as required.  Determine what level the device will * be interrupting at and then register an interrupt handler for it.  If we * succeed, then reset the adapter and read useful info from its PROM. * Last, register the interface with the kernel ATM services. * * Arguments: *	devinfo_p	pointer to device information structure * * Returns: *	0 	attach was successful *	-1	attach failed * */static intfore_attach(devinfo_p)	struct dev_info	*devinfo_p;{	struct dev_reg	*dev_reg_p;	struct dev_intr	*dev_intr_p;	Fore_unit	*fup;	Atm_config	*fcp;	addr_t		valp;	int		val;	int		i;	int		err_count = BOOT_LOOPS;	static int	unit = 0;	/*	 * Sanity check	 */	if (devinfo_p == NULL)		return (-1);	/*	 * Make sure this isn't a duplicate unit	 */	if (fore_units[unit] != NULL)		return (-1);	/*	 * Allocate a new unit structure	 */	fup = (Fore_unit *) atm_dev_alloc(sizeof(Fore_unit), sizeof(int), 0);	if (fup == NULL)		return (-1);	/*	 * Start initializing it	 */	fup->fu_unit = unit;	fup->fu_mtu = FORE_IFF_MTU;	fup->fu_devinfo = devinfo_p;	fup->fu_vcc_pool = &fore_vcc_pool;	fup->fu_nif_pool = &fore_nif_pool;	fup->fu_ioctl = fore_atm_ioctl;	fup->fu_instvcc = fore_instvcc;	fup->fu_openvcc = fore_openvcc;	fup->fu_closevcc = fore_closevcc;	fup->fu_output = fore_output;	/*	 * Consider this unit assigned	 */	fore_units[unit] = fup;	unit++;	ATM_DEBUG1("fore_attach: fup=%p\n", fup);	ATM_DEBUG2("\tfu_xmit_q=%p fu_xmit_head=%p\n",		fup->fu_xmit_q, &fup->fu_xmit_head);	ATM_DEBUG2("\tfu_recv_q=%p fu_recv_head=%p\n",		fup->fu_recv_q, &fup->fu_recv_head);	ATM_DEBUG2("\tfu_buf1s_q=%p fu_buf1s_head=%p\n",		fup->fu_buf1s_q, &fup->fu_buf1s_head);	ATM_DEBUG2("\tfu_buf1l_q=%p fu_buf1l_head=%p\n",		fup->fu_buf1l_q, &fup->fu_buf1l_head);	ATM_DEBUG2("\tfu_cmd_q=%p fu_cmd_head=%p\n",		fup->fu_cmd_q, &fup->fu_cmd_head);	ATM_DEBUG1("\tfu_stats=%p\n",		&fup->fu_stats);	/*	 * Tell kernel our unit number	 */	devinfo_p->devi_unit = fup->fu_unit;	/*	 * Figure out what type of device we've got.  This should always	 * work since we've already done this at identify time!	 */	i = 0;	while (fore_devices[i].fd_name) {		if (strcmp(fore_devices[i].fd_name, devinfo_p->devi_name) == 0)			break;		i++;	}	if (fore_devices[i].fd_name == NULL)		return (-1);	fup->fu_config.ac_device = fore_devices[i].fd_devtyp;	/*	 * Walk through the OPENPROM register information	 * mapping register banks as they are found.	 */	for ( dev_reg_p = devinfo_p->devi_reg, i = 1;		i <= devinfo_p->devi_nreg; i++, ++dev_reg_p )	{		if ( dev_reg_p == NULL )		{			/*			 * Can't happen...			 */			return ( -1 );		}		/*		 * Each device type has different register sets		 */		switch (fup->fu_config.ac_device) {#ifdef FORE_SBUS		case DEV_FORE_SBA200E:			switch ( i )			{			/*			 * Host Control Register (HCR)			 */			case 1:				if ( sizeof(Fore_reg) != dev_reg_p->reg_size )				{					return ( -1 );				}				fup->fu_ctlreg = (Fore_reg *)					map_regs ( dev_reg_p->reg_addr,						sizeof(Fore_reg),						dev_reg_p->reg_bustype );				if ( fup->fu_ctlreg == NULL )				{					return ( -1 );				}				break;			/*			 * SBus Burst Transfer Configuration Register			 */			case 2:				/*				 * Not used				 */				break;			/*			 * SBus Interrupt Level Select Register			 */			case 3:				if ( sizeof (Fore_reg) != dev_reg_p->reg_size )				{					return ( -1 );				}				fup->fu_intlvl = (Fore_reg *)					map_regs ( dev_reg_p->reg_addr,						sizeof(Fore_reg),						dev_reg_p->reg_bustype );				if ( fup->fu_intlvl == NULL )				{					return ( -1 );				}				break;			/*			 * i960 RAM			 */			case 4:				fup->fu_ram = (Fore_mem *)					map_regs ( dev_reg_p->reg_addr,						dev_reg_p->reg_size,						dev_reg_p->reg_bustype );				if ( fup->fu_ram == NULL )				{					return ( -1 );				}				fup->fu_ramsize = dev_reg_p->reg_size;				/*				 * Various versions of the Sun PROM mess with 				 * the reg_addr value in unpredictable (to me,				 * at least) ways, so just use the "memoffset"				 * property, which should give us the RAM 				 * offset directly.				 */				val = getprop(devinfo_p->devi_nodeid, 							"memoffset", -1);				if (val == -1) {					return (-1);				}				fup->fu_config.ac_ram = val;				fup->fu_config.ac_ramsize = fup->fu_ramsize;				/*				 * Set monitor interface for initializing				 */				fup->fu_mon = (Mon960 *)					(fup->fu_ram + MON960_BASE);				break;			default:				log(LOG_ERR, 					"fore_attach: Too many registers\n");				return ( -1 );			}			break;		case DEV_FORE_SBA200:			switch ( i )			{			/*			 * Board Control Register (BCR)			 */			case 1:				if ( sizeof(Fore_reg) != dev_reg_p->reg_size )				{					return ( -1 );				}				fup->fu_ctlreg = (Fore_reg *)					map_regs ( dev_reg_p->reg_addr,						sizeof(Fore_reg),						dev_reg_p->reg_bustype );				if ( fup->fu_ctlreg == NULL )				{					return ( -1 );				}				break;			/*			 * i960 RAM			 */			case 2:				fup->fu_ram = (Fore_mem *)					map_regs ( dev_reg_p->reg_addr,						dev_reg_p->reg_size,

⌨️ 快捷键说明

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