📄 sx.c
字号:
the card some time to breathe between accesses. (Otherwise the processor on the card might not be able to access its OWN bus... */#define TIMEOUT_1 30#define TIMEOUT_2 1000000#ifdef DEBUGstatic void my_hd (unsigned char *addr, int len){ int i, j, ch; for (i=0;i<len;i+=16) { printk ("%p ", addr+i); for (j=0;j<16;j++) { printk ("%02x %s", addr[j+i], (j==7)?" ":""); } for (j=0;j<16;j++) { ch = addr[j+i]; printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); } printk ("\n"); }}#endif/* This needs redoing for Alpha -- REW -- Done. */static inline void write_sx_byte (struct sx_board *board, int offset, u8 byte){ writeb (byte, board->base+offset);}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 does not 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -