📄 aurora.c
字号:
/* IRQ_to_board[bp->irq&0xf] = NULL;*/#endif /* Drop all DTR's */ for(i=0;i<16;i++){ sbus_writeb(i & 7, &bp->r[i>>3]->r[CD180_CAR]); udelay(1); sbus_writeb(0, &bp->r[i>>3]->r[CD180_MSVR]); udelay(1); } /* Board shutdown */ sbus_writeb(0, &bp->r0->r);#ifdef AURORA_DEBUG printk("aurora_shutdown_board: end\n");#endif}/* Setting up port characteristics. * Must be called with disabled interrupts */static void aurora_change_speed(struct Aurora_board *bp, struct Aurora_port *port){ struct tty_struct *tty; unsigned long baud; long tmp; unsigned char cor1 = 0, cor3 = 0; unsigned char mcor1 = 0, mcor2 = 0,chip; #ifdef AURORA_DEBUG printk("aurora_change_speed: start\n");#endif if (!(tty = port->tty) || !tty->termios) return; chip = AURORA_CD180(port_No(port)); port->SRER = 0; port->COR2 = 0; port->MSVR = MSVR_RTS|MSVR_DTR; baud = C_BAUD(tty); if (baud & CBAUDEX) { baud &= ~CBAUDEX; if (baud < 1 || baud > 2) port->tty->termios->c_cflag &= ~CBAUDEX; else baud += 15; } if (baud == 15) { if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) baud ++; if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) baud += 2; } /* Select port on the board */ sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); if (!baud_table[baud]) { /* Drop DTR & exit */ port->MSVR &= ~(bp->DTR|bp->RTS); sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); return; } else { /* Set DTR on */ port->MSVR |= bp->DTR; sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); } /* Now we must calculate some speed dependant things. */ /* Set baud rate for port. */ tmp = (((bp->oscfreq + baud_table[baud]/2) / baud_table[baud] + CD180_TPC/2) / CD180_TPC);/* tmp = (bp->oscfreq/7)/baud_table[baud]; if((tmp%10)>4)tmp=tmp/10+1;else tmp=tmp/10;*//* printk("Prescaler period: %d\n",tmp);*/ sbus_writeb((tmp >> 8) & 0xff, &bp->r[chip]->r[CD180_RBPRH]); sbus_writeb((tmp >> 8) & 0xff, &bp->r[chip]->r[CD180_TBPRH]); sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_RBPRL]); sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_TBPRL]); baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ /* Two timer ticks seems enough to wakeup something like SLIP driver */ tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO; port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? SERIAL_XMIT_SIZE - 1 : tmp); /* Receiver timeout will be transmission time for 1.5 chars */ tmp = (AURORA_TPS + AURORA_TPS/2 + baud/2) / baud; tmp = (tmp > 0xff) ? 0xff : tmp; sbus_writeb(tmp, &bp->r[chip]->r[CD180_RTPR]); switch (C_CSIZE(tty)) { case CS5: cor1 |= COR1_5BITS; break; case CS6: cor1 |= COR1_6BITS; break; case CS7: cor1 |= COR1_7BITS; break; case CS8: cor1 |= COR1_8BITS; break; } if (C_CSTOPB(tty)) cor1 |= COR1_2SB; cor1 |= COR1_IGNORE; if (C_PARENB(tty)) { cor1 |= COR1_NORMPAR; if (C_PARODD(tty)) cor1 |= COR1_ODDP; if (I_INPCK(tty)) cor1 &= ~COR1_IGNORE; } /* Set marking of some errors */ port->mark_mask = RCSR_OE | RCSR_TOUT; if (I_INPCK(tty)) port->mark_mask |= RCSR_FE | RCSR_PE; if (I_BRKINT(tty) || I_PARMRK(tty)) port->mark_mask |= RCSR_BREAK; if (I_IGNPAR(tty)) port->mark_mask &= ~(RCSR_FE | RCSR_PE); if (I_IGNBRK(tty)) { port->mark_mask &= ~RCSR_BREAK; if (I_IGNPAR(tty)) /* Real raw mode. Ignore all */ port->mark_mask &= ~RCSR_OE; } /* Enable Hardware Flow Control */ if (C_CRTSCTS(tty)) {/*#ifdef AURORA_BRAIN_DAMAGED_CTS port->SRER |= SRER_DSR | SRER_CTS; mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; tty->hw_stopped = !(aurora_in(bp, CD180_MSVR) & (MSVR_CTS|MSVR_DSR));#else*/ port->COR2 |= COR2_CTSAE;/*#endif*/ if (bp->flags&AURORA_BOARD_DTR_FLOW_OK) { mcor1 |= AURORA_RXTH; } } /* Enable Software Flow Control. FIXME: I'm not sure about this */ /* Some people reported that it works, but I still doubt */ if (I_IXON(tty)) { port->COR2 |= COR2_TXIBE; cor3 |= (COR3_FCT | COR3_SCDE); if (I_IXANY(tty)) port->COR2 |= COR2_IXM; sbus_writeb(START_CHAR(tty), &bp->r[chip]->r[CD180_SCHR1]); sbus_writeb(STOP_CHAR(tty), &bp->r[chip]->r[CD180_SCHR2]); sbus_writeb(START_CHAR(tty), &bp->r[chip]->r[CD180_SCHR3]); sbus_writeb(STOP_CHAR(tty), &bp->r[chip]->r[CD180_SCHR4]); } if (!C_CLOCAL(tty)) { /* Enable CD check */ port->SRER |= SRER_CD; mcor1 |= MCOR1_CDZD; mcor2 |= MCOR2_CDOD; } if (C_CREAD(tty)) /* Enable receiver */ port->SRER |= SRER_RXD; /* Set input FIFO size (1-8 bytes) */ cor3 |= AURORA_RXFIFO; /* Setting up CD180 channel registers */ sbus_writeb(cor1, &bp->r[chip]->r[CD180_COR1]); sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]); sbus_writeb(cor3, &bp->r[chip]->r[CD180_COR3]); /* Make CD180 know about registers change */ aurora_wait_CCR(bp->r[chip]); sbus_writeb(CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3, &bp->r[chip]->r[CD180_CCR]); /* Setting up modem option registers */ sbus_writeb(mcor1, &bp->r[chip]->r[CD180_MCOR1]); sbus_writeb(mcor2, &bp->r[chip]->r[CD180_MCOR2]); /* Enable CD180 transmitter & receiver */ aurora_wait_CCR(bp->r[chip]); sbus_writeb(CCR_TXEN | CCR_RXEN, &bp->r[chip]->r[CD180_CCR]); /* Enable interrupts */ sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); /* And finally set RTS on */ sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);#ifdef AURORA_DEBUG printk("aurora_change_speed: end\n");#endif}/* Must be called with interrupts enabled */static int aurora_setup_port(struct Aurora_board *bp, struct Aurora_port *port){ unsigned long flags; #ifdef AURORA_DEBUG printk("aurora_setup_port: start %d\n",port_No(port));#endif if (port->flags & ASYNC_INITIALIZED) return 0; if (!port->xmit_buf) { /* We may sleep in get_free_page() */ unsigned long tmp; if (!(tmp = get_free_page(GFP_KERNEL))) return -ENOMEM; if (port->xmit_buf) { free_page(tmp); return -ERESTARTSYS; } port->xmit_buf = (unsigned char *) tmp; } save_flags(flags); cli(); if (port->tty) clear_bit(TTY_IO_ERROR, &port->tty->flags); #ifdef MODULE if (port->count == 1) { MOD_INC_USE_COUNT; if((++bp->count) == 1) bp->flags |= AURORA_BOARD_ACTIVE; }#endif port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; aurora_change_speed(bp, port); port->flags |= ASYNC_INITIALIZED; restore_flags(flags);#ifdef AURORA_DEBUG printk("aurora_setup_port: end\n");#endif return 0;}/* Must be called with interrupts disabled */static void aurora_shutdown_port(struct Aurora_board *bp, struct Aurora_port *port){ struct tty_struct *tty; unsigned char chip;#ifdef AURORA_DEBUG printk("aurora_shutdown_port: start\n");#endif if (!(port->flags & ASYNC_INITIALIZED)) return; chip = AURORA_CD180(port_No(port)); #ifdef AURORA_REPORT_OVERRUN printk("aurora%d: port %d: Total %ld overruns were detected.\n", board_No(bp), port_No(port), port->overrun);#endif #ifdef AURORA_REPORT_FIFO { int i; printk("aurora%d: port %d: FIFO hits [ ", board_No(bp), port_No(port)); for (i = 0; i < 10; i++) { printk("%ld ", port->hits[i]); } printk("].\n"); }#endif if (port->xmit_buf) { free_page((unsigned long) port->xmit_buf); port->xmit_buf = NULL; } if (!(tty = port->tty) || C_HUPCL(tty)) { /* Drop DTR */ port->MSVR &= ~(bp->DTR|bp->RTS); sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); } /* Select port */ sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); /* Reset port */ aurora_wait_CCR(bp->r[chip]); sbus_writeb(CCR_SOFTRESET, &bp->r[chip]->r[CD180_CCR]); /* Disable all interrupts from this port */ port->SRER = 0; sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); if (tty) set_bit(TTY_IO_ERROR, &tty->flags); port->flags &= ~ASYNC_INITIALIZED;#ifdef MODULE if (--bp->count < 0) { printk(KERN_DEBUG "aurora%d: aurora_shutdown_port: " "bad board count: %d\n", board_No(bp), bp->count); bp->count = 0; } MOD_DEC_USE_COUNT; if (!bp->count) bp->flags &= ~AURORA_BOARD_ACTIVE;#endif#ifdef AURORA_DEBUG printk("aurora_shutdown_port: end\n");#endif} static int block_til_ready(struct tty_struct *tty, struct file * filp, struct Aurora_port *port){ DECLARE_WAITQUEUE(wait, current); struct Aurora_board *bp = port_Board(port); int retval; int do_clocal = 0; int CD; unsigned char chip; #ifdef AURORA_DEBUG printk("block_til_ready: start\n");#endif chip = AURORA_CD180(port_No(port)); /* If the device is in the middle of being closed, then block * until it's done, and then try again. */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { interruptible_sleep_on(&port->close_wait); if (port->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; else return -ERESTARTSYS; } /* If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { if (port->flags & ASYNC_CALLOUT_ACTIVE) return -EBUSY; port->flags |= ASYNC_NORMAL_ACTIVE; return 0; } if (port->flags & ASYNC_CALLOUT_ACTIVE) { if (port->normal_termios.c_cflag & CLOCAL) do_clocal = 1; } else { if (C_CLOCAL(tty)) do_clocal = 1; } /* Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in * this loop, info->count is dropped by one, so that * rs_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ retval = 0; add_wait_queue(&port->open_wait, &wait); cli(); if (!tty_hung_up_p(filp)) port->count--; sti(); port->blocked_open++; while (1) { cli(); sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); CD = sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD; if (!(port->flags & ASYNC_CALLOUT_ACTIVE)) { port->MSVR=bp->RTS; /* auto drops DTR */ sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); } sti(); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { if (port->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; break; } if (/*!(port->flags & ASYNC_CALLOUT_ACTIVE) &&*/ !(port->flags & ASYNC_CLOSING) && (do_clocal || CD)) break; if (signal_pending(current)) { retval = -ERESTARTSYS; break; } schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&port->open_wait, &wait); if (!tty_hung_up_p(filp)) port->count++; port->blocked_open--; if (retval) return retval; port->flags |= ASYNC_NORMAL_ACTIVE;#ifdef AURORA_DEBUG printk("block_til_ready: end\n");#endif return 0;} static int aurora_open(struct tty_struct * tty, struct file * filp){ int board; int error; struct Aurora_port * port; struct Aurora_board * bp; unsigned long flags; #ifdef AURORA_DEBUG printk("aurora_open: start\n");#endif board = AURORA_BOARD(MINOR(tty->device)); if (board > AURORA_NBOARD || !(aurora_board[board].flags & AURORA_BOARD_PRESENT)) {#ifdef AURORA_DEBUG printk("aurora_open: error board %d present %d\n", board, aurora_board[board].flags & AURORA_BOARD_PRESENT);#endif return -ENODEV; } bp = &aurora_board[board]; port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(MINOR(tty->device)); if (aurora_paranoia_check(port, tty->device, "aurora_open")) {#ifdef AURORA_DEBUG printk("aurora_open: error paranoia check\n");#endif return -ENODEV; } port->count++; tty->driver_data = port; port->tty = tty; if ((error = aurora_setup_port(bp, port))) {#ifdef AURORA_DEBUG printk("aurora_open: error aurora_setup_port ret %d\n",error);#endif return error; } if ((error = block_til_ready(tty, filp, port))) {#ifdef AURORA_DEBUG printk("aurora_open: error block_til_ready ret %d\n",error);#endif return error; } if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) { *tty->termios = port->normal_termios; save_flags(flags); cli(); aurora_change_speed(bp, port); restore_flags(flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -