📄 sx.c
字号:
rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK); else rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN); if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n", read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat)));}static int sx_ioctl (struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg){ int rc; struct sx_port *port = tty->driver_data; int ival; /* func_enter2(); */ rc = 0; switch (cmd) { case TIOCGSOFTCAR: rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg); break; case TIOCSSOFTCAR: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(int))) == 0) { Get_user(ival, (unsigned int *) arg); tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); } break; case TIOCGSERIAL: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) == 0) gs_getserial(&port->gs, (struct serial_struct *) arg); break; case TIOCSSERIAL: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(struct serial_struct))) == 0) rc = gs_setserial(&port->gs, (struct serial_struct *) arg); break; case TIOCMGET: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) == 0) { ival = sx_getsignals(port); put_user(ival, (unsigned int *) arg); } break; case TIOCMBIS: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { Get_user(ival, (unsigned int *) arg); sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1)); sx_reconfigure_port(port); } break; case TIOCMBIC: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { Get_user(ival, (unsigned int *) arg); sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1)); sx_reconfigure_port(port); } break; case TIOCMSET: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { Get_user(ival, (unsigned int *) arg); sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0)); sx_reconfigure_port(port); } break; default: rc = -ENOIOCTLCMD; break; } /* func_exit(); */ return rc;}/* The throttle/unthrottle scheme for the Specialix card is different * from other drivers and deserves some explanation. * The Specialix hardware takes care of XON/XOFF * and CTS/RTS flow control itself. This means that all we have to * do when signalled by the upper tty layer to throttle/unthrottle is * to make a note of it here. When we come to read characters from the * rx buffers on the card (sx_receive_chars()) we look to see if the * upper layer can accept more (as noted here in sx_rx_throt[]). * If it can't we simply don't remove chars from the cards buffer. * When the tty layer can accept chars, we again note that here and when * sx_receive_chars() is called it will remove them from the cards buffer. * The card will notice that a ports buffer has drained below some low * water mark and will unflow control the line itself, using whatever * flow control scheme is in use for that port. -- Simon Allen */static void sx_throttle (struct tty_struct * tty){ struct sx_port *port = (struct sx_port *)tty->driver_data; func_enter2(); /* If the port is using any type of input flow * control then throttle the port. */ if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) { port->gs.flags |= SX_RX_THROTTLE; } func_exit();}static void sx_unthrottle (struct tty_struct * tty){ struct sx_port *port = (struct sx_port *)tty->driver_data; func_enter2(); /* Always unthrottle even if flow control is not enabled on * this port in case we disabled flow control while the port * was throttled */ port->gs.flags &= ~SX_RX_THROTTLE; func_exit(); return;}/* ********************************************************************** * * Here are the initialization routines. * * ********************************************************************** */static int sx_init_board (struct sx_board *board){ int addr; int chans; int type; func_enter(); /* This is preceded by downloading the download code. */ board->flags |= SX_BOARD_INITIALIZED; if (read_sx_byte (board, 0)) /* CF boards may need this. */ write_sx_byte(board,0, 0); /* This resets the processor again, to make sure it didn't do any foolish things while we were downloading the image */ if (!sx_reset (board)) return 0; sx_start_board (board); udelay (10); if (!sx_busy_wait_neq (board, 0, 0xff, 0)) { printk (KERN_ERR "sx: Ooops. Board won't initialize.\n"); return 0; } /* Ok. So now the processor on the card is running. It gathered some info for us... */ sx_dprintk (SX_DEBUG_INIT, "The sxcard structure:\n"); if (sx_debug & SX_DEBUG_INIT) my_hd ((char *)(board->base), 0x10); sx_dprintk (SX_DEBUG_INIT, "the first sx_module structure:\n"); if (sx_debug & SX_DEBUG_INIT) my_hd ((char *)(board->base + 0x80), 0x30); sx_dprintk (SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware V%x.%02x,\n", read_sx_byte (board, 0), read_sx_byte(board, 1), read_sx_byte (board, 5), read_sx_byte(board, 4)); if (read_sx_byte (board, 0) == 0xff) { printk (KERN_INFO "sx: No modules found. Sorry.\n"); board->nports = 0; return 0; } chans = 0; if (IS_SX_BOARD(board)) { sx_write_board_word (board, cc_int_count, sx_maxints); } else { if (sx_maxints) sx_write_board_word (board, cc_int_count, SI_PROCESSOR_CLOCK/8/sx_maxints); } /* grab the first module type... */ /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ board->ta_type = mod_compat_type (sx_read_module_byte (board, 0x80, mc_chip)); /* XXX byteorder */ for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) { type = sx_read_module_byte (board, addr, mc_chip); sx_dprintk (SX_DEBUG_INIT, "Module at %x: %d channels\n", addr, read_sx_byte (board, addr + 2)); chans += sx_read_module_byte (board, addr, mc_type); sx_dprintk (SX_DEBUG_INIT, "module is an %s, which has %s/%s panels\n", mod_type_s (type), pan_type_s (sx_read_module_byte (board, addr, mc_mods) & 0xf), pan_type_s (sx_read_module_byte (board, addr, mc_mods) >> 4)); sx_dprintk (SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC version: %x\n", sx_read_module_byte (board, addr, mc_rev1), sx_read_module_byte (board, addr, mc_rev2), sx_read_module_byte (board, addr, mc_mtaasic_rev)); /* The following combinations are illegal: It should theoretically work, but timing problems make the bus HANG. */ if (mod_compat_type (type) != board->ta_type) { printk (KERN_ERR "sx: This is an invalid configuration.\n" "Don't mix TA/MTA/SXDC on the same hostadapter.\n"); chans=0; break; } if ((IS_EISA_BOARD(board) || IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) { printk (KERN_ERR "sx: This is an invalid configuration.\n" "Don't use SXDCs on an SI/XIO adapter.\n"); chans=0; break; }#if 0 /* Problem fixed: firmware 3.05 */ if (IS_SX_BOARD(board) && (type == TA8)) { /* There are some issues with the firmware and the DCD/RTS lines. It might work if you tie them together or something. It might also work if you get a newer sx_firmware. Therefore this is just a warning. */ printk (KERN_WARNING "sx: The SX host doesn't work too well " "with the TA8 adapters.\nSpecialix is working on it.\n"); }#endif } if (chans) { /* board->flags |= SX_BOARD_PRESENT; */ if(board->irq > 0) { /* fixed irq, probably PCI */ if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ if(request_irq(board->irq, sx_interrupt, SA_SHIRQ | SA_INTERRUPT, "sx", board)) { printk(KERN_ERR "sx: Cannot allocate irq %d.\n", board->irq); board->irq = 0; } } else board->irq = 0; } else if(board->irq < 0 && sx_irqmask) { /* auto-allocate irq */ int irqnr; int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); for(irqnr = 15; irqnr > 0; irqnr--) if(irqmask & (1 << irqnr)) if(! request_irq(irqnr, sx_interrupt, SA_SHIRQ | SA_INTERRUPT, "sx", board)) break; if(! irqnr) printk(KERN_ERR "sx: Cannot allocate IRQ.\n"); board->irq = irqnr; } else board->irq = 0; if (board->irq) { /* Found a valid interrupt, start up interrupts! */ sx_dprintk (SX_DEBUG_INIT, "Using irq %d.\n", board->irq); sx_start_interrupts (board); board->poll = sx_slowpoll; board->flags |= SX_IRQ_ALLOCATED; } else { /* no irq: setup board for polled operation */ board->poll = sx_poll; sx_dprintk (SX_DEBUG_INIT, "Using poll-interval %d.\n", board->poll); } /* The timer should be initialized anyway: That way we can safely del_timer it when the module is unloaded. */ init_timer (&board->timer); if (board->poll) { board->timer.data = (unsigned long) board; board->timer.function = sx_pollfunc; board->timer.expires = jiffies + board->poll; add_timer (&board->timer); } } else { board->irq = 0; } board->nports = chans; sx_dprintk (SX_DEBUG_INIT, "returning %d ports.", board->nports); func_exit(); return chans;}static void printheader(void){ static int header_printed; if (!header_printed) { printk (KERN_INFO "Specialix SX driver " "(C) 1998/1999 R.E.Wolff@BitWizard.nl \n"); printk (KERN_INFO "sx: version %s\n", RCS_ID); header_printed = 1; }}static int probe_sx (struct sx_board *board){ struct vpd_prom vpdp; char *p; int i; func_enter(); if (!IS_CF_BOARD (board)) { sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %lx.\n", board->base + SX_VPD_ROM); if (sx_debug & SX_DEBUG_PROBE) my_hd ((char *)(board->base + SX_VPD_ROM), 0x40); p = (char *) &vpdp; for (i=0;i< sizeof (struct vpd_prom);i++) *p++ = read_sx_byte (board, SX_VPD_ROM + i*2); if (sx_debug & SX_DEBUG_PROBE) my_hd ((char *)&vpdp, 0x20); sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n"); if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", vpdp.identifier); return 0; } } printheader (); if (!IS_CF_BOARD (board)) { printk (KERN_DEBUG "sx: Found an SX board at %lx\n", board->hw_base); printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", vpdp.hwrev, vpdp.hwass, vpdp.uniqid); printk ( "Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek); if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { /* This might be a bit harsh. This was the primary reason the SX/ISA card didn't work at first... */ printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n"); return (0); } if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) { if (board->base & 0x8000) { printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->base); printk (KERN_WARNING "sx: Read sx.txt for more info.\n"); } } } board->nports = -1; /* This resets the processor, and keeps it off the bus. */ if (!sx_reset (board)) return 0; sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); board->flags |= SX_BOARD_PRESENT; func_exit(); return 1;}/* Specialix probes for this card at 32k increments from 640k to 16M. I consider machines with less than 16M unlikely nowadays, so I'm not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */static int probe_si (struct sx_board *board){ int i; func_enter(); sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature %lx.\n", board->base + SI2_ISA_ID_BASE); if (sx_debug & SX_DEBUG_PROBE) my_hd ((char *)(board->base + SI2_ISA_ID_BASE), 0x8); if (!IS_EISA_BOARD(board)) { for (i=0;i<8;i++) { if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) { return 0; } } } printheader (); printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); /* Compared to the SX boards, it is a complete guess as to what this card is up to... */ board->nports = -1; /* This resets the processor, and keeps it off the bus. */ if (!sx_reset (board)) return 0; sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); board->flags |= SX_BOARD_PRESENT; func_exit(); return 1;}static int sx_init_drivers(void){ int error; func_enter(); memset(&sx_driver, 0, sizeof(sx_driver)); sx_driver.magic = TTY_DRIVER_MAGIC; sx_driver.driver_name = "specialix_sx"; sx_driver.name = "ttyX"; sx_driver.major = SX_NORMAL_MAJOR; sx_driver.num = sx_nports; sx_driver.ty
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -