📄 aurora.c
字号:
count = min(port->break_length, 0xff); sbus_writeb(CD180_C_ESC, &bp->r[chip]->r[CD180_TDR]); sbus_writeb(CD180_C_DELAY, &bp->r[chip]->r[CD180_TDR]); sbus_writeb(count, &bp->r[chip]->r[CD180_TDR]); if (!(port->break_length -= count)) port->break_length--; } else { sbus_writeb(CD180_C_ESC, &bp->r[chip]->r[CD180_TDR]); sbus_writeb(CD180_C_EBRK, &bp->r[chip]->r[CD180_TDR]); sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]); aurora_wait_CCR(bp->r[chip]); sbus_writeb(CCR_CORCHG2, &bp->r[chip]->r[CD180_CCR]); port->break_length = 0; } return; } count = CD180_NFIFO; do { u8 byte = port->xmit_buf[port->xmit_tail++]; sbus_writeb(byte, &bp->r[chip]->r[CD180_TDR]); port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); if (--port->xmit_cnt <= 0) break; } while (--count > 0); if (port->xmit_cnt <= 0) { sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); port->SRER &= ~SRER_TXRDY; sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); } if (port->xmit_cnt <= port->wakeup_chars) aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);}static void aurora_check_modem(struct Aurora_board const * bp, int chip){ struct Aurora_port *port; struct tty_struct *tty; unsigned char mcr; if (!(port = aurora_get_port(bp, chip, "Modem"))) return; tty = port->tty; mcr = sbus_readb(&bp->r[chip]->r[CD180_MCR]); if (mcr & MCR_CDCHG) { if (sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD) wake_up_interruptible(&port->open_wait); else schedule_task(&port->tqueue_hangup); } /* We don't have such things yet. My aurora board has DTR and RTS swapped, but that doesn't count in this driver. Let's hope * Aurora didn't made any boards with CTS or DSR broken... *//* #ifdef AURORA_BRAIN_DAMAGED_CTS if (mcr & MCR_CTSCHG) { if (aurora_in(bp, CD180_MSVR) & MSVR_CTS) { tty->hw_stopped = 0; port->SRER |= SRER_TXRDY; if (port->xmit_cnt <= port->wakeup_chars) aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP); } else { tty->hw_stopped = 1; port->SRER &= ~SRER_TXRDY; } sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); } if (mcr & MCR_DSRCHG) { if (aurora_in(bp, CD180_MSVR) & MSVR_DSR) { tty->hw_stopped = 0; port->SRER |= SRER_TXRDY; if (port->xmit_cnt <= port->wakeup_chars) aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP); } else { tty->hw_stopped = 1; port->SRER &= ~SRER_TXRDY; } sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); }#endif AURORA_BRAIN_DAMAGED_CTS */ /* Clear change bits */ sbus_writeb(0, &bp->r[chip]->r[CD180_MCR]);}/* The main interrupt processing routine */static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs){ unsigned char status; unsigned char ack,chip/*,chip_id*/; struct Aurora_board * bp = (struct Aurora_board *) dev_id; unsigned long loop = 0;#ifdef AURORA_INT_DEBUG printk("IRQ%d %d\n",irq,++irqhit);#ifdef AURORA_FLOODPRO if (irqhit>=AURORA_FLOODPRO) sbus_writeb(8, &bp->r0->r);#endif#endif /* old bp = IRQ_to_board[irq&0x0f];*/ if (!bp || !(bp->flags & AURORA_BOARD_ACTIVE)) return IRQ_NONE;/* The while() below takes care of this. status = sbus_readb(&bp->r[0]->r[CD180_SRSR]);#ifdef AURORA_INT_DEBUG printk("mumu: %02x\n", status);#endif if (!(status&SRSR_ANYINT)) return IRQ_NONE; * Nobody has anything to say, so exit **/ while ((loop++ < 48) && (status = sbus_readb(&bp->r[0]->r[CD180_SRSR]) & SRSR_ANYINT)){#ifdef AURORA_INT_DEBUG printk("SRSR: %02x\n", status);#endif if (status & SRSR_REXT) { ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]);#ifdef AURORA_INT_DEBUG printk("R-ACK %02x\n", ack);#endif if ((ack >> 5) == board_No(bp)) { if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { if ((ack&GSVR_ITMASK)==GSVR_IT_RGD) { aurora_receive(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } else if ((ack & GSVR_ITMASK) == GSVR_IT_REXC) { aurora_receive_exc(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } } } } else if (status & SRSR_TEXT) { ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]);#ifdef AURORA_INT_DEBUG printk("T-ACK %02x\n", ack);#endif if ((ack >> 5) == board_No(bp)) { if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { if ((ack&GSVR_ITMASK)==GSVR_IT_TX) { aurora_transmit(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } } } } else if (status & SRSR_MEXT) { ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]);#ifdef AURORA_INT_DEBUG printk("M-ACK %02x\n", ack);#endif if ((ack >> 5) == board_No(bp)) { if ((chip = ((ack>>3)&3)-1) < AURORA_NCD180) { if ((ack&GSVR_ITMASK)==GSVR_IT_MDM) { aurora_check_modem(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } } } } }/* I guess this faster code can be used with CD1865, using AUROPRI and GLOBPRI. */#if 0 while ((loop++ < 48)&&(status=bp->r[0]->r[CD180_SRSR]&SRSR_ANYINT)){#ifdef AURORA_INT_DEBUG printk("SRSR: %02x\n",status);#endif ack = sbus_readb(&bp->r3->r[0]);#ifdef AURORA_INT_DEBUG printk("ACK: %02x\n",ack);#endif if ((ack>>5)==board_No(bp)) { if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { ack&=GSVR_ITMASK; if (ack==GSVR_IT_RGD) { aurora_receive(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } else if (ack==GSVR_IT_REXC) { aurora_receive_exc(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } else if (ack==GSVR_IT_TX) { aurora_transmit(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } else if (ack==GSVR_IT_MDM) { aurora_check_modem(bp,chip); sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } } } }#endif/* This is the old handling routine, used in riscom8 for only one CD180. I keep it here for reference. */#if 0 for(chip=0;chip<AURORA_NCD180;chip++){ chip_id=(board_No(bp)<<5)|((chip+1)<<3); loop=0; while ((loop++ < 1) && ((status = sbus_readb(&bp->r[chip]->r[CD180_SRSR])) & (SRSR_TEXT | SRSR_MEXT | SRSR_REXT))) { if (status & SRSR_REXT) { ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]); if (ack == (chip_id | GSVR_IT_RGD)) {#ifdef AURORA_INTMSG printk("RX ACK\n");#endif aurora_receive(bp,chip); } else if (ack == (chip_id | GSVR_IT_REXC)) {#ifdef AURORA_INTMSG printk("RXC ACK\n");#endif aurora_receive_exc(bp,chip); } else {#ifdef AURORA_INTNORM printk("aurora%d-%d: Bad receive ack 0x%02x.\n", board_No(bp), chip, ack);#endif } } else if (status & SRSR_TEXT) { ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]); if (ack == (chip_id | GSVR_IT_TX)){#ifdef AURORA_INTMSG printk("TX ACK\n");#endif aurora_transmit(bp,chip); } else {#ifdef AURORA_INTNORM printk("aurora%d-%d: Bad transmit ack 0x%02x.\n", board_No(bp), chip, ack);#endif } } else if (status & SRSR_MEXT) { ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]); if (ack == (chip_id | GSVR_IT_MDM)){#ifdef AURORA_INTMSG printk("MDM ACK\n");#endif aurora_check_modem(bp,chip); } else {#ifdef AURORA_INTNORM printk("aurora%d-%d: Bad modem ack 0x%02x.\n", board_No(bp), chip, ack);#endif } } sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); } }#endif return IRQ_HANDLED;}#ifdef AURORA_INT_DEBUGstatic void aurora_timer (unsigned long ignored);static DEFINE_TIMER(aurora_poll_timer, aurora_timer, 0, 0);static voidaurora_timer (unsigned long ignored){ unsigned long flags; int i; save_flags(flags); cli(); printk("SRSR: %02x,%02x - ", sbus_readb(&aurora_board[0].r[0]->r[CD180_SRSR]), sbus_readb(&aurora_board[0].r[1]->r[CD180_SRSR])); for (i = 0; i < 4; i++) { udelay(1); printk("%02x ", sbus_readb(&aurora_board[0].r3->r[i])); } printk("\n"); aurora_poll_timer.expires = jiffies + 300; add_timer (&aurora_poll_timer); restore_flags(flags);}#endif/* * Routines for open & close processing. *//* Called with disabled interrupts */static int aurora_setup_board(struct Aurora_board * bp){ int error; #ifdef AURORA_ALLIRQ int i; for (i = 0; i < AURORA_ALLIRQ; i++) { error = request_irq(allirq[i]|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp); if (error) printk(KERN_ERR "IRQ%d request error %d\n", allirq[i], error); }#else error = request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp); if (error) { printk(KERN_ERR "IRQ request error %d\n", error); return error; }#endif /* Board reset */ sbus_writeb(0, &bp->r0->r); udelay(1); if (bp->flags & AURORA_BOARD_TYPE_2) { /* unknown yet */ } else { sbus_writeb((AURORA_CFG_ENABLE_IO | AURORA_CFG_ENABLE_IRQ | (((bp->irq)&0x0f)>>2)), &bp->r0->r); } udelay(10000); if (aurora_init_CD180(bp,0))error=1;error=0; if (aurora_init_CD180(bp,1))error++; if (error == AURORA_NCD180) { printk(KERN_ERR "Both chips failed initialisation.\n"); return -EIO; }#ifdef AURORA_INT_DEBUG aurora_poll_timer.expires= jiffies + 1; add_timer(&aurora_poll_timer);#endif#ifdef AURORA_DEBUG printk("aurora_setup_board: end\n");#endif return 0;}/* Called with disabled interrupts */static void aurora_shutdown_board(struct Aurora_board *bp){ int i;#ifdef AURORA_DEBUG printk("aurora_shutdown_board: start\n");#endif#ifdef AURORA_INT_DEBUG del_timer(&aurora_poll_timer);#endif#ifdef AURORA_ALLIRQ for(i=0;i<AURORA_ALLIRQ;i++){ free_irq(allirq[i]|0x30, bp);/* IRQ_to_board[allirq[i]&0xf] = NULL;*/ }#else free_irq(bp->irq|0x30, bp);/* 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 = tty_get_baud_rate(tty); /* Select port on the board */ sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); if (!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 dependent things. */ /* Set baud rate for port. */ tmp = (((bp->oscfreq + baud/2) / baud + CD180_TPC/2) / CD180_TPC);/* tmp = (bp->oscfreq/7)/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 + 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_zeroed_page() */ unsigned long tmp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -