📄 sx.c
字号:
static inline u8 read_sx_byte(struct sx_board *board, int offset){ return readb(board->base + offset);}static inline void write_sx_word(struct sx_board *board, int offset, u16 word){ writew(word, board->base + offset);}static inline u16 read_sx_word(struct sx_board *board, int offset){ return readw(board->base + offset);}static int sx_busy_wait_eq(struct sx_board *board, int offset, int mask, int correctval){ int i; func_enter(); for (i = 0; i < TIMEOUT_1; i++) if ((read_sx_byte(board, offset) & mask) == correctval) { func_exit(); return 1; } for (i = 0; i < TIMEOUT_2; i++) { if ((read_sx_byte(board, offset) & mask) == correctval) { func_exit(); return 1; } udelay(1); } func_exit(); return 0;}static int sx_busy_wait_neq(struct sx_board *board, int offset, int mask, int badval){ int i; func_enter(); for (i = 0; i < TIMEOUT_1; i++) if ((read_sx_byte(board, offset) & mask) != badval) { func_exit(); return 1; } for (i = 0; i < TIMEOUT_2; i++) { if ((read_sx_byte(board, offset) & mask) != badval) { func_exit(); return 1; } udelay(1); } func_exit(); return 0;}/* 5.6.4 of 6210028 r2.3 */static int sx_reset(struct sx_board *board){ func_enter(); if (IS_SX_BOARD(board)) { write_sx_byte(board, SX_CONFIG, 0); write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */ if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) { printk(KERN_INFO "sx: Card doesn't respond to " "reset...\n"); return 0; } } else if (IS_EISA_BOARD(board)) { outb(board->irq << 4, board->eisa_base + 0xc02); } else if (IS_SI1_BOARD(board)) { write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/ } else { /* Gory details of the SI/ISA board */ write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET); write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); } func_exit(); return 1;}/* This doesn't work on machines where "NULL" isn't 0 *//* If you have one of those, someone will need to write the equivalent of this, which will amount to about 3 lines. I don't want to complicate this right now. -- REW (See, I do write comments every now and then :-) */#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem))#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem))#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem))#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem))#define sx_write_channel_byte(port, elem, val) \ write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)#define sx_read_channel_byte(port, elem) \ read_sx_byte (port->board, CHAN_OFFSET (port, elem))#define sx_write_channel_word(port, elem, val) \ write_sx_word (port->board, CHAN_OFFSET (port, elem), val)#define sx_read_channel_word(port, elem) \ read_sx_word (port->board, CHAN_OFFSET (port, elem))#define sx_write_module_byte(board, addr, elem, val) \ write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)#define sx_read_module_byte(board, addr, elem) \ read_sx_byte (board, MODU_OFFSET (board, addr, elem))#define sx_write_module_word(board, addr, elem, val) \ write_sx_word (board, MODU_OFFSET (board, addr, elem), val)#define sx_read_module_word(board, addr, elem) \ read_sx_word (board, MODU_OFFSET (board, addr, elem))#define sx_write_board_byte(board, elem, val) \ write_sx_byte (board, BRD_OFFSET (board, elem), val)#define sx_read_board_byte(board, elem) \ read_sx_byte (board, BRD_OFFSET (board, elem))#define sx_write_board_word(board, elem, val) \ write_sx_word (board, BRD_OFFSET (board, elem), val)#define sx_read_board_word(board, elem) \ read_sx_word (board, BRD_OFFSET (board, elem))static int sx_start_board(struct sx_board *board){ if (IS_SX_BOARD(board)) { write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN); } else if (IS_EISA_BOARD(board)) { write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL); outb((board->irq << 4) | 4, board->eisa_base + 0xc02); } else if (IS_SI1_BOARD(board)) { write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0); write_sx_byte(board, SI1_ISA_INTCL, 0); } else { /* Don't bug me about the clear_set. I haven't the foggiest idea what it's about -- REW */ write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); } return 1;}#define SX_IRQ_REG_VAL(board) \ ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)/* Note. The SX register is write-only. Therefore, we have to enable the bus too. This is a no-op, if you don't mess with this driver... */static int sx_start_interrupts(struct sx_board *board){ /* Don't call this with board->irq == 0 */ if (IS_SX_BOARD(board)) { write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) | SX_CONF_BUSEN | SX_CONF_HOSTIRQ); } else if (IS_EISA_BOARD(board)) { inb(board->eisa_base + 0xc03); } else if (IS_SI1_BOARD(board)) { write_sx_byte(board, SI1_ISA_INTCL, 0); write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0); } else { switch (board->irq) { case 11: write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET); break; case 12: write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET); break; case 15: write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET); break; default: printk(KERN_INFO "sx: SI/XIO card doesn't support " "interrupt %d.\n", board->irq); return 0; } write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); } return 1;}static int sx_send_command(struct sx_port *port, int command, int mask, int newstat){ func_enter2(); write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command); func_exit(); return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask, newstat);}static char *mod_type_s(int module_type){ switch (module_type) { case TA4: return "TA4"; case TA8: return "TA8"; case TA4_ASIC: return "TA4_ASIC"; case TA8_ASIC: return "TA8_ASIC"; case MTA_CD1400: return "MTA_CD1400"; case SXDC: return "SXDC"; default: return "Unknown/invalid"; }}static char *pan_type_s(int pan_type){ switch (pan_type) { case MOD_RS232DB25: return "MOD_RS232DB25"; case MOD_RS232RJ45: return "MOD_RS232RJ45"; case MOD_RS422DB25: return "MOD_RS422DB25"; case MOD_PARALLEL: return "MOD_PARALLEL"; case MOD_2_RS232DB25: return "MOD_2_RS232DB25"; case MOD_2_RS232RJ45: return "MOD_2_RS232RJ45"; case MOD_2_RS422DB25: return "MOD_2_RS422DB25"; case MOD_RS232DB25MALE: return "MOD_RS232DB25MALE"; case MOD_2_PARALLEL: return "MOD_2_PARALLEL"; case MOD_BLANK: return "empty"; default: return "invalid"; }}static int mod_compat_type(int module_type){ return module_type >> 4;}static void sx_reconfigure_port(struct sx_port *port){ if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) { if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { printk(KERN_WARNING "sx: Sent reconfigure command, but " "card didn't react.\n"); } } else { sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: " "port isn't open (%02x).\n", sx_read_channel_byte(port, hi_hstat)); }}static void sx_setsignals(struct sx_port *port, int dtr, int rts){ int t; func_enter2(); t = sx_read_channel_byte(port, hi_op); if (dtr >= 0) t = dtr ? (t | OP_DTR) : (t & ~OP_DTR); if (rts >= 0) t = rts ? (t | OP_RTS) : (t & ~OP_RTS); sx_write_channel_byte(port, hi_op, t); sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); func_exit();}static int sx_getsignals(struct sx_port *port){ int i_stat, o_stat; o_stat = sx_read_channel_byte(port, hi_op); i_stat = sx_read_channel_byte(port, hi_ip); sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " "%02x/%02x\n", (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, port->c_dcd, sx_get_CD(port), sx_read_channel_byte(port, hi_ip), sx_read_channel_byte(port, hi_state)); return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) | ((o_stat & OP_RTS) ? TIOCM_RTS : 0) | ((i_stat & IP_CTS) ? TIOCM_CTS : 0) | ((i_stat & IP_DCD) ? TIOCM_CAR : 0) | ((i_stat & IP_DSR) ? TIOCM_DSR : 0) | ((i_stat & IP_RI) ? TIOCM_RNG : 0));}static void sx_set_baud(struct sx_port *port){ int t; if (port->board->ta_type == MOD_SXDC) { switch (port->gs.baud) { /* Save some typing work... */#define e(x) case x: t = BAUD_ ## x; break e(50); e(75); e(110); e(150); e(200); e(300); e(600); e(1200); e(1800); e(2000); e(2400); e(4800); e(7200); e(9600); e(14400); e(19200); e(28800); e(38400); e(56000); e(57600); e(64000); e(76800); e(115200); e(128000); e(150000); e(230400); e(256000); e(460800); e(921600); case 134: t = BAUD_134_5; break; case 0: t = -1; break; default: /* Can I return "invalid"? */ t = BAUD_9600; printk(KERN_INFO "sx: unsupported baud rate: %d.\n", port->gs.baud); break; }#undef e if (t > 0) {/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ sx_setsignals(port, 1, -1); /* XXX This is not TA & MTA compatible */ sx_write_channel_byte(port, hi_csr, 0xff); sx_write_channel_byte(port, hi_txbaud, t); sx_write_channel_byte(port, hi_rxbaud, t); } else { sx_setsignals(port, 0, -1); } } else { switch (port->gs.baud) {#define e(x) case x: t = CSR_ ## x; break e(75); e(150); e(300); e(600); e(1200); e(2400); e(4800); e(1800); e(9600); e(19200); e(57600); e(38400);/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ case 110: if (port->board->ta_type == MOD_TA) { t = CSR_110; break; } else { t = CSR_9600; printk(KERN_INFO "sx: Unsupported baud rate: " "%d.\n", port->gs.baud); break; } case 115200: if (port->board->ta_type == MOD_TA) { t = CSR_9600; printk(KERN_INFO "sx: Unsupported baud rate: " "%d.\n", port->gs.baud); break; } else { t = CSR_110; break; } case 0: t = -1; break; default: t = CSR_9600; printk(KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); break; }#undef e if (t >= 0) { sx_setsignals(port, 1, -1); sx_write_channel_byte(port, hi_csr, t * 0x11); } else { sx_setsignals(port, 0, -1); } }}/* Simon Allen's version of this routine was 225 lines long. 85 is a lot better. -- REW */static int sx_set_real_termios(void *ptr){ struct sx_port *port = ptr; func_enter2(); if (!port->gs.tty) return 0; /* What is this doing here? -- REW Ha! figured it out. It is to allow you to get DTR active again if you've dropped it with stty 0. Moved to set_baud, where it belongs (next to the drop dtr if baud == 0) -- REW */ /* sx_setsignals (port, 1, -1); */ sx_set_baud(port);#define CFLAG port->gs.tty->termios->c_cflag sx_write_channel_byte(port, hi_mr1, (C_PARENB(port->gs.tty) ? MR1_WITH : MR1_NONE) | (C_PARODD(port->gs.tty) ? MR1_ODD : MR1_EVEN) | (C_CRTSCTS(port->gs.tty) ? MR1_RTS_RXFLOW : 0) | (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) | (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) | (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) | (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0)); sx_write_channel_byte(port, hi_mr2, (C_CRTSCTS(port->gs.tty) ? MR2_CTS_TXFLOW : 0) | (C_CSTOPB(port->gs.tty) ? MR2_2_STOP : MR2_1_STOP)); switch (CFLAG & CSIZE) { case CS8: sx_write_channel_byte(port, hi_mask, 0xff); break; case CS7: sx_write_channel_byte(port, hi_mask, 0x7f); break; case CS6: sx_write_channel_byte(port, hi_mask, 0x3f); break; case CS5: sx_write_channel_byte(port, hi_mask, 0x1f); break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -