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 + -
显示快捷键?