ip2main.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,945 行 · 第 1/5 页
C
1,945 行
{ int err; int i;#ifdef IP2DEBUG_INIT printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion );#endif /* Stop poll timer if we had one. */ if ( TimerOn ) { del_timer ( &PollTimer ); TimerOn = 0; } /* Reset the boards we have. */ for( i = 0; i < IP2_MAX_BOARDS; ++i ) { if ( i2BoardPtrTable[i] ) { iiReset( i2BoardPtrTable[i] ); } } /* The following is done at most once, if any boards were installed. */ for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if ( i2BoardPtrTable[i] ) { iiResetDelay( i2BoardPtrTable[i] ); /* free io addresses and Tibet */ release_region( ip2config.addr[i], 8 ); class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); devfs_remove("ip2/ipl%d", i); class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); devfs_remove("ip2/stat%d", i); } /* Disable and remove interrupt handler. */ if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { free_irq ( ip2config.irq[i], (void *)&pcName); clear_requested_irq( ip2config.irq[i]); } } class_destroy(ip2_class); devfs_remove("ip2"); if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) { printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); } put_tty_driver(ip2_tty_driver); if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) { printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err); } remove_proc_entry("ip2mem", &proc_root); // free memory for (i = 0; i < IP2_MAX_BOARDS; i++) { void *pB;#ifdef CONFIG_PCI if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { pci_disable_device(ip2config.pci_dev[i]); ip2config.pci_dev[i] = NULL; }#endif if ((pB = i2BoardPtrTable[i]) != 0 ) { kfree ( pB ); i2BoardPtrTable[i] = NULL; } if ((DevTableMem[i]) != NULL ) { kfree ( DevTableMem[i] ); DevTableMem[i] = NULL; } } /* Cleanup the iiEllis subsystem. */ iiEllisCleanup();#ifdef IP2DEBUG_INIT printk (KERN_DEBUG "IP2 Unloaded\n" );#endif}#endif /* MODULE */static struct tty_operations ip2_ops = { .open = ip2_open, .close = ip2_close, .write = ip2_write, .put_char = ip2_putchar, .flush_chars = ip2_flush_chars, .write_room = ip2_write_room, .chars_in_buffer = ip2_chars_in_buf, .flush_buffer = ip2_flush_buffer, .ioctl = ip2_ioctl, .throttle = ip2_throttle, .unthrottle = ip2_unthrottle, .set_termios = ip2_set_termios, .set_ldisc = ip2_set_line_discipline, .stop = ip2_stop, .start = ip2_start, .hangup = ip2_hangup, .read_proc = ip2_read_proc, .tiocmget = ip2_tiocmget, .tiocmset = ip2_tiocmset,};/******************************************************************************//* Function: ip2_loadmain() *//* Parameters: irq, io from command line of insmod et. al. *//* pointer to fip firmware and firmware size for boards *//* Returns: Success (0) *//* *//* Description: *//* This was the required entry point for all drivers (now in ip2.c) *//* It performs all *//* initialisation of the devices and driver structures, and registers itself *//* with the relevant kernel modules. *//******************************************************************************//* SA_INTERRUPT- if set blocks all interrupts else only this line *//* SA_SHIRQ - for shared irq PCI or maybe EISA only *//* SA_RANDOM - can be source for cert. random number generators */#define IP2_SA_FLAGS 0intip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) { int i, j, box; int err = 0; int status = 0; static int loaded; i2eBordStrPtr pB = NULL; int rc = -1; ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 ); /* process command line arguments to modprobe or insmod i.e. iop & irqp */ /* irqp and iop should ALWAYS be specified now... But we check them individually just to be sure, anyways... */ for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if (iop) { ip2config.addr[i] = iop[i]; if (irqp) { if( irqp[i] >= 0 ) { ip2config.irq[i] = irqp[i]; } else { ip2config.irq[i] = 0; } // This is a little bit of a hack. If poll_only=1 on command // line back in ip2.c OR all IRQs on all specified boards are // explicitly set to 0, then drop to poll only mode and override // PCI or EISA interrupts. This superceeds the old hack of // triggering if all interrupts were zero (like da default). // Still a hack but less prone to random acts of terrorism. // // What we really should do, now that the IRQ default is set // to -1, is to use 0 as a hard coded, do not probe. // // /\/\|=mhw=|\/\/ poll_only |= irqp[i]; } } } poll_only = !poll_only; Fip_firmware = firmware; Fip_firmware_size = firmsize; /* Announce our presence */ printk( KERN_INFO "%s version %s\n", pcName, pcVersion ); // ip2 can be unloaded and reloaded for no good reason // we can't let that happen here or bad things happen // second load hoses board but not system - fixme later if (loaded) { printk( KERN_INFO "Still loaded\n" ); return 0; } loaded++; ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); if (!ip2_tty_driver) return -ENOMEM; /* Initialise the iiEllis subsystem. */ iiEllisInit(); /* Initialize arrays. */ memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable ); memset( DevTable, 0, sizeof DevTable ); /* Initialise all the boards we can find (up to the maximum). */ for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { switch ( ip2config.addr[i] ) { case 0: /* skip this slot even if card is present */ break; default: /* ISA */ /* ISA address must be specified */ if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) { printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n", i, ip2config.addr[i] ); ip2config.addr[i] = 0; } else { ip2config.type[i] = ISA; /* Check for valid irq argument, set for polling if invalid */ if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) { printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]); ip2config.irq[i] = 0;// 0 is polling and is valid in that sense } } break; case PCI:#ifdef CONFIG_PCI { struct pci_dev *pci_dev_i = NULL; pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); if (pci_dev_i != NULL) { unsigned int addr; if (pci_enable_device(pci_dev_i)) { printk( KERN_ERR "IP2: can't enable PCI device at %s\n", pci_name(pci_dev_i)); break; } ip2config.type[i] = PCI; ip2config.pci_dev[i] = pci_dev_i; status = pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); if ( addr & 1 ) { ip2config.addr[i]=(USHORT)(addr&0xfffe); } else { printk( KERN_ERR "IP2: PCI I/O address error\n"); }// If the PCI BIOS assigned it, lets try and use it. If we// can't acquire it or it screws up, deal with it then.// if (!is_valid_irq(pci_irq)) {// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);// pci_irq = 0;// } ip2config.irq[i] = pci_dev_i->irq; } else { // ann error ip2config.addr[i] = 0; if (status == PCIBIOS_DEVICE_NOT_FOUND) { printk( KERN_ERR "IP2: PCI board %d not found\n", i ); } else { printk( KERN_ERR "IP2: PCI error 0x%x \n", status ); } } }#else printk( KERN_ERR "IP2: PCI card specified but PCI support not\n"); printk( KERN_ERR "IP2: configured in this kernel.\n"); printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n");#endif /* CONFIG_PCI */ break; case EISA: if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) { /* Eisa_irq set as side effect, boo */ ip2config.type[i] = EISA; } ip2config.irq[i] = Eisa_irq; break; } /* switch */ } /* for */ for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if ( ip2config.addr[i] ) { pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL); if ( pB != NULL ) { i2BoardPtrTable[i] = pB; memset( pB, 0, sizeof(i2eBordStr) ); iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer ); iiReset( pB ); } else { printk(KERN_ERR "IP2: board memory allocation error\n"); } } } for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if ( ( pB = i2BoardPtrTable[i] ) != NULL ) { iiResetDelay( pB ); break; } } for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { if ( i2BoardPtrTable[i] != NULL ) { ip2_init_board( i ); } } ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 ); ip2_tty_driver->owner = THIS_MODULE; ip2_tty_driver->name = "ttyF"; ip2_tty_driver->devfs_name = "tts/F"; ip2_tty_driver->driver_name = pcDriver_name; ip2_tty_driver->major = IP2_TTY_MAJOR; ip2_tty_driver->minor_start = 0; ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; ip2_tty_driver->init_termios = tty_std_termios; ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; tty_set_operations(ip2_tty_driver, &ip2_ops); ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 ); /* Register the tty devices. */ if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) { printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err); put_tty_driver(ip2_tty_driver); return -EINVAL; } else /* Register the IPL driver. */ if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) { printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); } else { /* create the sysfs class */ ip2_class = class_create(THIS_MODULE, "ip2"); if (IS_ERR(ip2_class)) { err = PTR_ERR(ip2_class); goto out_chrdev; } } /* Register the read_procmem thing */ if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) { printk(KERN_ERR "IP2: failed to register read_procmem\n"); } else { ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 ); /* Register the interrupt handler or poll handler, depending upon the * specified interrupt. */ for( i = 0; i < IP2_MAX_BOARDS; ++i ) { if ( 0 == ip2config.addr[i] ) { continue; } if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { class_device_create(ip2_class, NULL, MKDEV(IP2_IPL_MAJOR, 4 * i), NULL, "ipl%d", i); err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, "ip2/ipl%d", i); if (err) { class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); goto out_class; } class_device_create(ip2_class, NULL, MKDEV(IP2_IPL_MAJOR, 4 * i + 1), NULL, "stat%d", i); err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, "ip2/stat%d", i); if (err) { class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); goto out_class; } for ( box = 0; box < ABS_MAX_BOXES; ++box ) { for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) { if ( pB->i2eChannelMap[box] & (1 << j) ) { tty_register_device(ip2_tty_driver, j + ABS_BIGGEST_BOX * (box+i*ABS_MAX_BOXES), NULL); } } } } if (poll_only) {// Poll only forces driver to only use polling and// to ignore the probed PCI or EISA interrupts. ip2config.irq[i] = CIR_POLL; } if ( ip2config.irq[i] == CIR_POLL ) {retry: if (!TimerOn) { PollTimer.expires = POLL_TIMEOUT; add_timer ( &PollTimer ); TimerOn = 1; printk( KERN_INFO "IP2: polling\n"); } } else { if (have_requested_irq(ip2config.irq[i])) continue; rc = request_irq( ip2config.irq[i], ip2_interrupt,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?