📄 ip2main.c
字号:
/* Zero out the normal tty device structure. */ memset ( &ip2_tty_driver, 0, sizeof ip2_tty_driver ); /* Initialise the relevant fields. */ ip2_tty_driver.magic = TTY_DRIVER_MAGIC; ip2_tty_driver.name = pcTty;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) ip2_tty_driver.driver_name = pcDriver_name; ip2_tty_driver.read_proc = ip2_read_proc;#endif ip2_tty_driver.major = IP2_TTY_MAJOR; ip2_tty_driver.minor_start = 0; ip2_tty_driver.num = IP2_MAX_PORTS; 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;#ifdef CONFIG_DEVFS_FS ip2_tty_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;#else ip2_tty_driver.flags = TTY_DRIVER_REAL_RAW;#endif ip2_tty_driver.refcount = &ref_count; ip2_tty_driver.table = TtyTable; ip2_tty_driver.termios = Termios; ip2_tty_driver.termios_locked = TermiosLocked; /* Setup the pointers to the implemented functions. */ ip2_tty_driver.open = ip2_open; ip2_tty_driver.close = ip2_close; ip2_tty_driver.write = ip2_write; ip2_tty_driver.put_char = ip2_putchar; ip2_tty_driver.flush_chars = ip2_flush_chars; ip2_tty_driver.write_room = ip2_write_room; ip2_tty_driver.chars_in_buffer = ip2_chars_in_buf; ip2_tty_driver.flush_buffer = ip2_flush_buffer; ip2_tty_driver.ioctl = ip2_ioctl; ip2_tty_driver.throttle = ip2_throttle; ip2_tty_driver.unthrottle = ip2_unthrottle; ip2_tty_driver.set_termios = ip2_set_termios; ip2_tty_driver.set_ldisc = ip2_set_line_discipline; ip2_tty_driver.stop = ip2_stop; ip2_tty_driver.start = ip2_start; ip2_tty_driver.hangup = ip2_hangup; /* Initialise the callout driver structure from the tty driver, and * make the needed adjustments. */ ip2_callout_driver = ip2_tty_driver; ip2_callout_driver.name = pcCallout;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) ip2_callout_driver.driver_name = pcDriver_name; ip2_callout_driver.read_proc = NULL;#endif ip2_callout_driver.major = IP2_CALLOUT_MAJOR; ip2_callout_driver.subtype = SERIAL_TYPE_CALLOUT; 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); } else if ( ( err = tty_register_driver ( &ip2_callout_driver ) ) ) { printk(KERN_ERR "IP2: failed to register callout driver (%d)\n", err); } else /* Register the IPL driver. */#ifdef CONFIG_DEVFS_FS if (( err = devfs_register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl )))#else if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) )#endif { printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); } else /* 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. */#ifdef CONFIG_DEVFS_FS if (!devfs_handle) devfs_handle = devfs_mk_dir (NULL, "ip2", NULL);#endif for( i = 0; i < IP2_MAX_BOARDS; ++i ) {#ifdef CONFIG_DEVFS_FS char name[16];#endif if ( 0 == ip2config.addr[i] ) { continue; }#ifdef CONFIG_DEVFS_FS if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { sprintf( name, "ipl%d", i ); pB->devfs_ipl_handle = devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT, IP2_IPL_MAJOR, 4 * i, S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, &ip2_ipl, NULL); sprintf( name, "stat%d", i ); pB->devfs_stat_handle = devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT, IP2_IPL_MAJOR, 4 * i + 1, S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, &ip2_ipl, NULL); for ( box = 0; box < ABS_MAX_BOXES; ++box ) { for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) { if ( pB->i2eChannelMap[box] & (1 << j) ) { tty_register_devfs(&ip2_tty_driver, 0, j + ABS_BIGGEST_BOX * (box+i*ABS_MAX_BOXES)); tty_register_devfs(&ip2_callout_driver, 0, j + ABS_BIGGEST_BOX * (box+i*ABS_MAX_BOXES)); } } } }#endif 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, IP2_SA_FLAGS | (ip2config.type[i] == PCI ? SA_SHIRQ : 0), pcName, (void *)&pcName); if (rc) { printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc); ip2config.irq[i] = CIR_POLL; printk( KERN_INFO "IP2: Polling %ld/sec.\n", (POLL_TIMEOUT - jiffies)); goto retry; } mark_requested_irq(ip2config.irq[i]); /* Initialise the interrupt handler bottom half (aka slih). */ } } for( i = 0; i < IP2_MAX_BOARDS; ++i ) { if ( i2BoardPtrTable[i] ) { set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */ } } } ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 ); return 0;}/******************************************************************************//* Function: ip2_init_board() *//* Parameters: Index of board in configuration structure *//* Returns: Success (0) *//* *//* Description: *//* This function initializes the specified board. The loadware is copied to *//* the board, the channel structures are initialized, and the board details *//* are reported on the console. *//******************************************************************************/static void __initip2_init_board( int boardnum ){ int i,rc; int nports = 0, nboxes = 0; i2ChanStrPtr pCh; i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; if ( !iiInitialize ( pB ) ) { printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n", pB->i2eBase, pB->i2eError ); goto err_initialize; } printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1, ip2config.addr[boardnum], ip2config.irq[boardnum] ); if (0 != ( rc = check_region( ip2config.addr[boardnum], 8))) { printk(KERN_ERR "IP2: bad addr=0x%x rc = %d\n", ip2config.addr[boardnum], rc ); goto err_initialize; } request_region( ip2config.addr[boardnum], 8, pcName ); if ( iiDownloadAll ( pB, (loadHdrStrPtr)Fip_firmware, 1, Fip_firmware_size ) != II_DOWN_GOOD ) { printk ( KERN_ERR "IP2: failed to download loadware\n" ); goto err_release_region; } else { printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n", pB->i2ePom.e.porVersion, pB->i2ePom.e.porRevision, pB->i2ePom.e.porSubRev, pB->i2eLVersion, pB->i2eLRevision, pB->i2eLSub ); } switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) { default: printk( KERN_ERR "IP2: Unknown board type, ID = %x\n", pB->i2ePom.e.porID ); nports = 0; goto err_release_region; break; case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */ printk ( KERN_INFO "IP2: ISA-4\n" ); nports = 4; break; case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */ printk ( KERN_INFO "IP2: ISA-8 std\n" ); nports = 8; break; case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */ printk ( KERN_INFO "IP2: ISA-8 RJ11\n" ); nports = 8; break; case POR_ID_FIIEX: /* IntelliPort IIEX */ { int portnum = IP2_PORTS_PER_BOARD * boardnum; int box; for( box = 0; box < ABS_MAX_BOXES; ++box ) { if ( pB->i2eChannelMap[box] != 0 ) { ++nboxes; } for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { if ( pB->i2eChannelMap[box] & 1<< i ) { ++nports; } } } DevTableMem[boardnum] = pCh = kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL ); if ( !pCh ) { printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); goto err_release_region; } if ( !i2InitChannels( pB, nports, pCh ) ) { printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); kfree ( pCh ); goto err_release_region; } pB->i2eChannelPtr = &DevTable[portnum]; pB->i2eChannelCnt = ABS_MOST_PORTS; for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) { for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { if ( pB->i2eChannelMap[box] & (1 << i) ) { DevTable[portnum + i] = pCh; pCh->port_index = portnum + i; pCh++; } } } printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n", nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 ); } goto ex_exit; } DevTableMem[boardnum] = pCh = kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL ); if ( !pCh ) { printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); goto err_release_region; } pB->i2eChannelPtr = pCh; pB->i2eChannelCnt = nports; if ( !i2InitChannels( pB, nports, pCh ) ) { printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); kfree ( pCh ); goto err_release_region; } pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum]; for( i = 0; i < pB->i2eChannelCnt; ++i ) { DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh; pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i; pCh++; }ex_exit: pB->tqueue_interrupt.routine = (void(*)(void*)) ip2_interrupt_bh; pB->tqueue_interrupt.data = pB; return;err_release_region: release_region(ip2config.addr[boardnum], 8);err_initialize: kfree ( pB ); i2BoardPtrTable[boardnum] = NULL; return;}/******************************************************************************//* Function: find_eisa_board ( int start_slot ) *//* Parameters: First slot to check *//* Returns: Address of EISA IntelliPort II controller *//* *//* Description: *//* This function searches for an EISA IntelliPort controller, starting *//* from the specified slot number. If the motherboard is not identified as an *//* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise *//* it returns the base address of the controller. *//******************************************************************************/static unsigned short __initfind_eisa_board( int start_slot ){ int i, j; unsigned int idm = 0; unsigned int idp = 0; unsigned int base = 0; unsigned int value; int setup_address; int setup_irq; int ismine = 0; /* * First a check for an EISA motherboard, which we do by comparing the * EISA ID registers for the system board and the first couple of slots. * No slot ID should match the system board ID, but on an ISA or PCI * machine the odds are that an empty bus will return similar values for * each slot. */ i = 0x0c80; value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3); for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) { j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3); if ( value == j ) return 0; } /* * OK, so we are inclined to believe that this is an EISA machine. Find * an IntelliPort controller. */ for( i = start_slot; i < 16; i++ ) { base = i << 12; idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff); idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff); ismine = 0; if ( idm == 0x0e8e ) { if ( idp == 0x0281 || idp == 0x0218 ) { ismine = 1; } else if ( idp == 0x0282 || idp == 0x0283 ) { ismine = 3; /* Can do edge-trigger */ } if ( ismine ) { Eisa_slot = i; break; } } } if ( !ismine ) return 0; /* It's some sort of EISA card, but at what address is it configured? */ setup_address = base + 0xc88; value = inb(base + 0xc86); setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0; if ( (ismine & 2) && !(value & 0x10) ) { ismine = 1; /* Could be edging, but not */ } if ( Eisa_irq == 0 ) { Eisa_irq = setup_irq; } else if ( Eisa_irq != setup_irq ) { printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" ); }#ifdef IP2DEBUG_INITprintk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x", base >> 12, idm, idp, setup_address);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -