static void z8530_rx_clear(struct z8530_channel *c) { /* * Data and status bytes */ u8 stat; read_zsdata(c); stat=read_zsreg(c, R1); if(stat&END_FR) write_zsctrl(c, RES_Rx_CRC); /* * Clear irq */ write_zsctrl(c, ERR_RES); write_zsctrl(c, RES_H_IUS); }
static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap) { struct tty_struct *tty = NULL; unsigned char ch, r1, drop, error, flag; int loops = 0; /* The interrupt can be enabled when the port isn't open, typically * that happens when using one port is open and the other closed (stale * interrupt) or when one port is used as a console. */ if (!ZS_IS_OPEN(uap)) { pmz_debug("pmz: draining input\n"); /* Port is closed, drain input data */ for (;;) { if ((++loops) > 1000) goto flood; (void)read_zsreg(uap, R1); write_zsreg(uap, R0, ERR_RES); (void)read_zsdata(uap); ch = read_zsreg(uap, R0); if (!(ch & Rx_CH_AV)) break; } return NULL; } /* Sanity check, make sure the old bug is no longer happening */ if (uap->port.info == NULL || uap->port.info->tty == NULL) { WARN_ON(1); (void)read_zsdata(uap); return NULL; } tty = uap->port.info->tty; while (1) { error = 0; drop = 0; r1 = read_zsreg(uap, R1); ch = read_zsdata(uap); if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { write_zsreg(uap, R0, ERR_RES); zssync(uap); } ch &= uap->parity_mask; if (ch == 0 && uap->flags & PMACZILOG_FLAG_BREAK) { uap->flags &= ~PMACZILOG_FLAG_BREAK; } #if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_SERIAL_CORE_CONSOLE) #ifdef USE_CTRL_O_SYSRQ /* Handle the SysRq ^O Hack */ if (ch == '\x0f') { uap->port.sysrq = jiffies + HZ*5; goto next_char; } #endif /* USE_CTRL_O_SYSRQ */ if (uap->port.sysrq) { int swallow; spin_unlock(&uap->port.lock); swallow = uart_handle_sysrq_char(&uap->port, ch); spin_lock(&uap->port.lock); if (swallow) goto next_char; } #endif /* CONFIG_MAGIC_SYSRQ && CONFIG_SERIAL_CORE_CONSOLE */ /* A real serial line, record the character and status. */ if (drop) goto next_char; flag = TTY_NORMAL; uap->port.icount.rx++; if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { error = 1; if (r1 & BRK_ABRT) { pmz_debug("pmz: got break !\n"); r1 &= ~(PAR_ERR | CRC_ERR); uap->port.icount.brk++; if (uart_handle_break(&uap->port)) goto next_char; } else if (r1 & PAR_ERR) uap->port.icount.parity++; else if (r1 & CRC_ERR) uap->port.icount.frame++; if (r1 & Rx_OVR) uap->port.icount.overrun++; r1 &= uap->port.read_status_mask; if (r1 & BRK_ABRT) flag = TTY_BREAK; else if (r1 & PAR_ERR) flag = TTY_PARITY; else if (r1 & CRC_ERR) flag = TTY_FRAME; } if (uap->port.ignore_status_mask == 0xff || (r1 & uap->port.ignore_status_mask) == 0) { tty_insert_flip_char(tty, ch, flag); } if (r1 & Rx_OVR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); next_char: /* We can get stuck in an infinite loop getting char 0 when the * line is in a wrong HW state, we break that here. * When that happens, I disable the receive side of the driver. * Note that what I've been experiencing is a real irq loop where * I'm getting flooded regardless of the actual port speed. * Something stange is going on with the HW */ if ((++loops) > 1000) goto flood; ch = read_zsreg(uap, R0); if (!(ch & Rx_CH_AV)) break; } return tty; flood: uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); write_zsreg(uap, R1, uap->curregs[R1]); zssync(uap); dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n"); return tty; }
/* * Set the irda codec on the imac to the specified baud rate. */ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) { u8 cmdbyte; int t, version; switch (*baud) { /* SIR modes */ case 2400: cmdbyte = 0x53; break; case 4800: cmdbyte = 0x52; break; case 9600: cmdbyte = 0x51; break; case 19200: cmdbyte = 0x50; break; case 38400: cmdbyte = 0x4f; break; case 57600: cmdbyte = 0x4e; break; case 115200: cmdbyte = 0x4d; break; /* The FIR modes aren't really supported at this point, how * do we select the speed ? via the FCR on KeyLargo ? */ case 1152000: cmdbyte = 0; break; case 4000000: cmdbyte = 0; break; default: /* 9600 */ cmdbyte = 0x51; *baud = 9600; break; } /* Wait for transmitter to drain */ t = 10000; while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 || (read_zsreg(uap, R1) & ALL_SNT) == 0) { if (--t <= 0) { dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n"); return; } udelay(10); } /* Drain the receiver too */ t = 100; (void)read_zsdata(uap); (void)read_zsdata(uap); (void)read_zsdata(uap); mdelay(10); while (read_zsreg(uap, R0) & Rx_CH_AV) { read_zsdata(uap); mdelay(10); if (--t <= 0) { dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n"); return; } } /* Switch to command mode */ uap->curregs[R5] |= DTR; write_zsreg(uap, R5, uap->curregs[R5]); zssync(uap); mdelay(1); /* Switch SCC to 19200 */ pmz_convert_to_zs(uap, CS8, 0, 19200); pmz_load_zsregs(uap, uap->curregs); mdelay(1); /* Write get_version command byte */ write_zsdata(uap, 1); t = 5000; while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { if (--t <= 0) { dev_err(&uap->dev->ofdev.dev, "irda_setup timed out on get_version byte\n"); goto out; } udelay(10); } version = read_zsdata(uap); if (version < 4) { dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n", version); goto out; } /* Send speed mode */ write_zsdata(uap, cmdbyte); t = 5000; while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { if (--t <= 0) { dev_err(&uap->dev->ofdev.dev, "irda_setup timed out on speed mode byte\n"); goto out; } udelay(10); } t = read_zsdata(uap); if (t != cmdbyte) dev_err(&uap->dev->ofdev.dev, "irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); dev_info(&uap->dev->ofdev.dev, "IrDA setup for %ld bps, dongle version: %d\n", *baud, version); (void)read_zsdata(uap); (void)read_zsdata(uap); (void)read_zsdata(uap); out: /* Switch back to data mode */ uap->curregs[R5] &= ~DTR; write_zsreg(uap, R5, uap->curregs[R5]); zssync(uap); (void)read_zsdata(uap); (void)read_zsdata(uap); (void)read_zsdata(uap); }
static void z8530_rx(struct z8530_channel *c) { u8 ch,stat; while(1) { /* FIFO empty ? */ if(!(read_zsreg(c, R0)&1)) break; ch=read_zsdata(c); stat=read_zsreg(c, R1); /* * Overrun ? */ if(c->count < c->max) { *c->dptr++=ch; c->count++; } if(stat&END_FR) { /* * Error ? */ if(stat&(Rx_OVR|CRC_ERR)) { /* Rewind the buffer and return */ if(c->skb) c->dptr=c->skb->data; c->count=0; if(stat&Rx_OVR) { printk(KERN_WARNING "%s: overrun\n", c->dev->name); c->rx_overrun++; } if(stat&CRC_ERR) { c->rx_crc_err++; /* printk("crc error\n"); */ } /* Shove the frame upstream */ } else { /* * Drop the lock for RX processing, or * there are deadlocks */ z8530_rx_done(c); write_zsctrl(c, RES_Rx_CRC); } } } /* * Clear irq */ write_zsctrl(c, ERR_RES); write_zsctrl(c, RES_H_IUS); }
static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, struct pt_regs *regs) { struct tty_struct *tty = NULL; unsigned char ch, r1, drop, error; int loops = 0; retry: /* The interrupt can be enabled when the port isn't open, typically * that happens when using one port is open and the other closed (stale * interrupt) or when one port is used as a console. */ if (!ZS_IS_OPEN(uap)) { pmz_debug("pmz: draining input\n"); /* Port is closed, drain input data */ for (;;) { if ((++loops) > 1000) goto flood; (void)read_zsreg(uap, R1); write_zsreg(uap, R0, ERR_RES); (void)read_zsdata(uap); ch = read_zsreg(uap, R0); if (!(ch & Rx_CH_AV)) break; } return NULL; } /* Sanity check, make sure the old bug is no longer happening */ if (uap->port.info == NULL || uap->port.info->tty == NULL) { WARN_ON(1); (void)read_zsdata(uap); return NULL; } tty = uap->port.info->tty; while (1) { error = 0; drop = 0; if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { /* Have to drop the lock here */ pmz_debug("pmz: flip overflow\n"); spin_unlock(&uap->port.lock); tty->flip.work.func((void *)tty); spin_lock(&uap->port.lock); if (tty->flip.count >= TTY_FLIPBUF_SIZE) drop = 1; if (ZS_IS_ASLEEP(uap)) return NULL; if (!ZS_IS_OPEN(uap)) goto retry; } r1 = read_zsreg(uap, R1); ch = read_zsdata(uap); if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { write_zsreg(uap, R0, ERR_RES); zssync(uap); } ch &= uap->parity_mask; if (ch == 0 && uap->prev_status & BRK_ABRT) r1 |= BRK_ABRT; /* A real serial line, record the character and status. */ if (drop) goto next_char; *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; uap->port.icount.rx++; if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { error = 1; if (r1 & BRK_ABRT) { pmz_debug("pmz: got break !\n"); r1 &= ~(PAR_ERR | CRC_ERR); uap->port.icount.brk++; if (uart_handle_break(&uap->port)) { pmz_debug("pmz: do handle break !\n"); goto next_char; } } else if (r1 & PAR_ERR) uap->port.icount.parity++; else if (r1 & CRC_ERR) uap->port.icount.frame++; if (r1 & Rx_OVR) uap->port.icount.overrun++; r1 &= uap->port.read_status_mask; if (r1 & BRK_ABRT) *tty->flip.flag_buf_ptr = TTY_BREAK; else if (r1 & PAR_ERR) *tty->flip.flag_buf_ptr = TTY_PARITY; else if (r1 & CRC_ERR) *tty->flip.flag_buf_ptr = TTY_FRAME; } if (uart_handle_sysrq_char(&uap->port, ch, regs)) { pmz_debug("pmz: sysrq swallowed the char\n"); goto next_char; } if (uap->port.ignore_status_mask == 0xff || (r1 & uap->port.ignore_status_mask) == 0) { tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; } if ((r1 & Rx_OVR) && tty->flip.count < TTY_FLIPBUF_SIZE) { *tty->flip.flag_buf_ptr = TTY_OVERRUN; tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; } next_char: /* We can get stuck in an infinite loop getting char 0 when the * line is in a wrong HW state, we break that here. * When that happens, I disable the receive side of the driver. * Note that what I've been experiencing is a real irq loop where * I'm getting flooded regardless of the actual port speed. * Something stange is going on with the HW */ if ((++loops) > 1000) goto flood; ch = read_zsreg(uap, R0); if (!(ch & Rx_CH_AV)) break; } return tty; flood: uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); write_zsreg(uap, R1, uap->curregs[R1]); zssync(uap); dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n"); return tty; }
int asdg_setup(void) { int i, line1, line2; struct SCC *scc=NULL; int dummy; struct ConfigDev *cd=NULL; struct serial_struct req; struct async_struct *info=NULL; int CardFound=0; if (!MACH_IS_AMIGA) return -ENODEV; #ifdef DEBUG printk("We are a miggy\n"); #endif nr_asdg = 0; while((i=zorro_find(MANUF_ASDG, PROD_TWIN_X,1, 0))) { CardFound=1; board_index[nr_asdg/2] = i; cd = zorro_get_board(i); scc = (struct SCC *)ZTWO_VADDR((((volatile u_char *)cd->cd_BoardAddr))); #ifdef DEBUG printk("Found ASDG DSB at %p\n", scc); #endif req.line = -1; /* first free ttyS? device */ req.type = SER_ASDG; req.port = (int) &(scc->B); if ((line1 = register_serial( &req )) < 0) { printk( "Cannot register ASDG serial port: no free device\n" ); return -EBUSY; } lines[nr_asdg++] = line1; info = &rs_table[line1]; info->sw = &asdg_ser_switch; info->nr_uarts = nr_asdg; info->board_base = scc; req.line = -1; /* first free ttyS? device */ req.type = SER_ASDG; req.port = (int) &(scc->A); if ((line2 = register_serial( &req )) < 0) { printk( "Cannot register ASDG serial port: no free device\n" ); unregister_serial( line1 ); return -EBUSY; } lines[nr_asdg++] = line2; info = &rs_table[line2]; info->sw = &asdg_ser_switch; info->nr_uarts = nr_asdg--; info->board_base = scc; nr_asdg++; zorro_config_board(i,1); /* Clear pointers */ dummy = scc->A.control; dummy = scc->B.control; #ifdef DEBUG printk("Pointers cleared \n"); #endif /* Reset card */ write_zsreg(&scc->A, R9, FHWRES | MIE); udelay(10); /* Give card time to reset */ write_zsreg(&scc->B, R9, FHWRES | MIE); udelay(10); /* Give card time to reset */ #ifdef DEBUG printk("Card reset - MIE on \n"); #endif /* Reset all potential interupt sources */ write_zsreg(&scc->A, R0, RES_EXT_INT); /* Ext ints (disabled anyways) */ write_zsreg(&scc->B, R0, RES_EXT_INT); #ifdef DEBUG printk("Ext ints cleared\n"); #endif write_zsreg(&scc->A, R0, RES_Tx_P); /* TBE int */ write_zsreg(&scc->B, R0, RES_Tx_P); #ifdef DEBUG printk("TBE Cleared\n"); #endif /* Clear Rx FIFO */ while( (read_zsreg(&scc->A, R0) & Rx_CH_AV) != 0) dummy=read_zsdata(&scc->A); while( (read_zsreg(&scc->B, R0) & Rx_CH_AV) != 0) dummy=read_zsdata(&scc->B); #ifdef DEBUG printk("Rx buffer empty\n"); #endif /* TBE and RX int off - we will turn them on in _init()*/ write_zsreg(&scc->A, R1, 0); write_zsreg(&scc->B, R1, 0); #ifdef DEBUG printk("Tx and Rx ints off \n"); #endif /* Interrupt vector */ write_zsreg(&scc->A, R2, 0); write_zsreg(&scc->B, R2, 0); #ifdef DEBUG printk("Int vector set (unused) \n"); #endif write_zsreg(&scc->A, R3, Rx8); write_zsreg(&scc->B, R3, Rx8); #ifdef DEBUG printk("Rx enabled\n"); #endif write_zsreg(&scc->A, R4, SB1 | X16CLK); write_zsreg(&scc->B, R4, SB1 | X16CLK); #ifdef DEBUG printk("1 stop bit, x16 clock\n"); #endif write_zsreg(&scc->A, R5, Tx8); write_zsreg(&scc->B, R5, Tx8); #ifdef DEBUG printk("Tx enabled \n"); #endif write_zsreg(&scc->A, R10, NRZ); write_zsreg(&scc->B, R10, NRZ); #ifdef DEBUG printk("NRZ mode\n"); #endif write_zsreg(&scc->A, R11, TCBR | RCBR | TRxCBR); write_zsreg(&scc->B, R11, TCBR | RCBR | TRxCBR); #ifdef DEBUG printk("Clock source setup\n"); #endif /*300 bps */ write_zsreg(&scc->A, R12, 0xfe); write_zsreg(&scc->A, R13, 2); write_zsreg(&scc->B, R12, 0xfe); write_zsreg(&scc->B, R13, 2); #ifdef DEBUG printk("Baud rate set - 300\n"); #endif write_zsreg(&scc->A, R14, BRENABL | BRSRC); write_zsreg(&scc->B, R14, BRENABL | BRSRC); #ifdef DEBUG printk("BRG enabled \n"); #endif write_zsreg(&scc->A, R15, 0); write_zsreg(&scc->A, R15, 0); #ifdef DEBUG printk("Ext INT IE bits cleared \n"); #endif } if(CardFound) { request_irq(IRQ_AMIGA_EXTER, asdg_interrupt, 0, "ASDG serial", asdg_interrupt); return 0; } else { printk("No ASDG Cards found\n"); return -ENODEV; } }
/* Interrupt Service Routine */ static void asdg_interrupt(int irq, void *data, struct pt_regs *fp) { int i; u_char ivec; /* Interrupt vector - not sure if it is needed */ u_char ip; /* IP bits from card */ int ch; /* Received or xmitted char */ struct SCC *scc; struct async_struct *infoA; struct async_struct *infoB; /* Check all cards */ for(i=0; i<nr_asdg; i+=2) { infoB = &rs_table[lines[i]]; infoA = &rs_table[lines[i+1]]; scc = (struct SCC *)infoA->board_base; ivec=read_zsreg(&scc->B, R2); /* Get Interrupt Vector and ignore it :-) */ ip=read_zsreg(&scc->A, R3); /* Get IP bits */ if(ip & CHBEXT) { /* Channel B ext/status */ #ifdef INTDEBUG printk("Channel B Ext/Stat"); #endif write_zsreg(&scc->B, R0, RES_EXT_INT); } if(ip & CHBTxIP) { /* Channel B TBE */ #ifdef INTDEBUG printk("Chan B TBE\n"); #endif if( (ch=rs_get_tx_char(infoB)) >=0 ) { #ifdef INTDEBUG // printk("{%x}", ch); #endif write_zsdata(&scc->B, ch); } else { #ifdef INTDEBUG // printk("{%x}", ch); #endif write_zsreg(&scc->B, R0, RES_Tx_P); } } if(ip & CHBRxIP) { /* Channel B Rx Char Avail */ #ifdef INTDEBUG printk("Channel B Rx char avail"); #endif while( (read_zsreg(&scc->B, R0) & Rx_CH_AV) != 0) { ch=read_zsdata(&scc->B); rs_receive_char(infoB, ch , 0); #ifdef INTDEBUG printk("Received Char Chan B: %c\n", ch); #endif } } if(ip & CHAEXT) { /* Channel A ext/status */ #ifdef INTDEBUG printk("Channel A Ext/Stat"); #endif write_zsreg(&scc->A, R0, RES_EXT_INT); } if(ip & CHATxIP) {/* Channel A TBE */ #ifdef INTDEBUG printk("Chan A TBE\n"); #endif if( (ch=rs_get_tx_char(infoA)) >=0) { #ifdef INTDEBUG // printk("{%x}", ch); #endif write_zsdata(&scc->A, ch); } else { #ifdef INTDEBUG // printk("{%x}", ch); #endif write_zsreg(&scc->A, R0, RES_Tx_P); } } if(ip & CHARxIP) { /* Channel A Rx Char Avail */ #ifdef INTDEBUG printk("Channel A Rx char avail"); #endif while( (read_zsreg(&scc->A, R0) & Rx_CH_AV) != 0) { ch=read_zsdata(&scc->A); rs_receive_char(infoA, ch , 0); #ifdef INTDEBUG printk("Received Char Chan A: %c\n", ch); #endif } } } }