static void asdg_enab_tx_int(struct async_struct *info, int enab_flag) { int ch; struct SCCHalf *port = (struct SCCHalf *)info->port; #ifdef DEBUG printk("asdg_enab_tx_int: enab_flag= %d\n", enab_flag); #endif if(enab_flag) { if( (ch=rs_get_tx_char(info)) >=0) { #ifdef DEBUG printk("{%x}", ch); #endif write_zsdata(port, ch); } else { #ifdef DEBUG printk("{%x}", ch); #endif write_zsreg(port, R0, RES_Tx_P); } } else write_zsreg(port, R0, RES_Tx_P); }
static _INLINE_ void status_handle(struct m68k_serial *info, unsigned short status) { #if 0 if(status & DCD) { if((info->tty->termios->c_cflag & CRTSCTS) && ((info->curregs[3] & AUTO_ENAB)==0)) { info->curregs[3] |= AUTO_ENAB; info->pendregs[3] |= AUTO_ENAB; write_zsreg(info->m68k_channel, 3, info->curregs[3]); } } else { if((info->curregs[3] & AUTO_ENAB)) { info->curregs[3] &= ~AUTO_ENAB; info->pendregs[3] &= ~AUTO_ENAB; write_zsreg(info->m68k_channel, 3, info->curregs[3]); } } #endif /* If this is console input and this is a * 'break asserted' status change interrupt * see if we can drop into the debugger */ if((status & URX_BREAK) && info->break_abort) batten_down_hatches(); return; }
int z8530_sync_open(struct net_device *dev, struct z8530_channel *c) { unsigned long flags; spin_lock_irqsave(c->lock, flags); c->sync = 1; c->mtu = dev->mtu+64; c->count = 0; c->skb = NULL; c->skb2 = NULL; c->irqs = &z8530_sync; /* This loads the double buffer up */ z8530_rx_done(c); /* Load the frame ring */ z8530_rx_done(c); /* Load the backup frame */ z8530_rtsdtr(c,1); c->dma_tx = 0; c->regs[R1]|=TxINT_ENAB; write_zsreg(c, R1, c->regs[R1]); write_zsreg(c, R3, c->regs[R3]|RxENABLE); spin_unlock_irqrestore(c->lock, flags); return 0; }
static void z8530_status(struct z8530_channel *chan) { u8 status, altered; status = read_zsreg(chan, R0); altered = chan->status ^ status; chan->status = status; if (status & TxEOM) { /* printk("%s: Tx underrun.\n", chan->dev->name); */ chan->netdevice->stats.tx_fifo_errors++; write_zsctrl(chan, ERR_RES); z8530_tx_done(chan); } if (altered & chan->dcdcheck) { if (status & chan->dcdcheck) { pr_info("%s: DCD raised\n", chan->dev->name); write_zsreg(chan, R3, chan->regs[3] | RxENABLE); if (chan->netdevice) netif_carrier_on(chan->netdevice); } else { pr_info("%s: DCD lost\n", chan->dev->name); write_zsreg(chan, R3, chan->regs[3] & ~RxENABLE); z8530_flush_fifo(chan); if (chan->netdevice) netif_carrier_off(chan->netdevice); } } write_zsctrl(chan, RES_EXT_INT); write_zsctrl(chan, RES_H_IUS); }
static void z8530_tx(struct z8530_channel *c) { while(c->txcount) { /* FIFO full ? */ if(!(read_zsreg(c, R0)&4)) return; c->txcount--; /* * Shovel out the byte */ write_zsreg(c, R8, *c->tx_ptr++); write_zsctrl(c, RES_H_IUS); /* We are about to underflow */ if(c->txcount==0) { write_zsctrl(c, RES_EOM_L); write_zsreg(c, R10, c->regs[10]&~ABUNDER); } } /* * End of frame TX - fire another one */ write_zsctrl(c, RES_Tx_P); z8530_tx_done(c); write_zsctrl(c, RES_H_IUS); }
int z8530_channel_load(struct z8530_channel *c, u8 *rtable) { unsigned long flags; spin_lock_irqsave(c->lock, flags); while(*rtable!=255) { int reg=*rtable++; if(reg>0x0F) write_zsreg(c, R15, c->regs[15]|1); write_zsreg(c, reg&0x0F, *rtable); if(reg>0x0F) write_zsreg(c, R15, c->regs[15]&~1); c->regs[reg]=*rtable++; } c->rx_function=z8530_null_rx; c->skb=NULL; c->tx_skb=NULL; c->tx_next_skb=NULL; c->mtu=1500; c->max=0; c->count=0; c->status=read_zsreg(c, R0); c->sync=1; write_zsreg(c, R3, c->regs[R3]|RxENABLE); spin_unlock_irqrestore(c->lock, flags); return 0; }
int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c) { u8 chk; unsigned long flags; c->irqs = &z8530_nop; c->max = 0; c->sync = 0; /* * Disable the PC DMA channels */ flags=claim_dma_lock(); disable_dma(c->rxdma); clear_dma_ff(c->rxdma); c->rxdma_on = 0; disable_dma(c->txdma); clear_dma_ff(c->txdma); release_dma_lock(flags); c->txdma_on = 0; c->tx_dma_used = 0; spin_lock_irqsave(c->lock, flags); /* * Disable DMA control mode */ c->regs[R1]&= ~WT_RDY_ENAB; write_zsreg(c, R1, c->regs[R1]); c->regs[R1]&= ~(WT_RDY_RT|WT_FN_RDYFN|INT_ERR_Rx); c->regs[R1]|= INT_ALL_Rx; write_zsreg(c, R1, c->regs[R1]); c->regs[R14]&= ~DTRREQ; write_zsreg(c, R14, c->regs[R14]); if(c->rx_buf[0]) { free_page((unsigned long)c->rx_buf[0]); c->rx_buf[0]=NULL; } if(c->tx_dma_buf[0]) { free_page((unsigned long)c->tx_dma_buf[0]); c->tx_dma_buf[0]=NULL; } chk=read_zsreg(c,R0); write_zsreg(c, R3, c->regs[R3]); z8530_rtsdtr(c,0); spin_unlock_irqrestore(c->lock, flags); return 0; }
static void asdg_stop_receive(struct async_struct *info) { #ifdef DEBUG printk("asdg_stop_receive\n"); #endif write_zsreg((struct SCCHalf *)info->port, R3, Rx8); /* Turn off Rx */ write_zsreg((struct SCCHalf *)info->port, R1, 0); /* Turn off Tx */ }
static void pmz_irda_reset(struct uart_pmac_port *uap) { uap->curregs[R5] |= DTR; write_zsreg(uap, R5, uap->curregs[R5]); zssync(uap); mdelay(110); uap->curregs[R5] &= ~DTR; write_zsreg(uap, R5, uap->curregs[R5]); zssync(uap); mdelay(10); }
/* * Real startup routine, powers up the hardware and sets up * the SCC. Returns a delay in ms where you need to wait before * actually using the port, this is typically the internal modem * powerup delay. This routine expect the lock to be taken. */ static int __pmz_startup(struct uart_pmac_port *uap) { int pwr_delay = 0; memset(&uap->curregs, 0, sizeof(uap->curregs)); /* Power up the SCC & underlying hardware (modem/irda) */ pwr_delay = pmz_set_scc_power(uap, 1); /* Nice buggy HW ... */ pmz_fix_zero_bug_scc(uap); /* Reset the channel */ uap->curregs[R9] = 0; write_zsreg(uap, 9, ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB); zssync(uap); udelay(10); write_zsreg(uap, 9, 0); zssync(uap); /* Clear the interrupt registers */ write_zsreg(uap, R1, 0); write_zsreg(uap, R0, ERR_RES); write_zsreg(uap, R0, ERR_RES); write_zsreg(uap, R0, RES_H_IUS); write_zsreg(uap, R0, RES_H_IUS); /* Setup some valid baud rate */ uap->curregs[R4] = X16CLK | SB1; uap->curregs[R3] = Rx8; uap->curregs[R5] = Tx8 | RTS; if (!ZS_IS_IRDA(uap)) uap->curregs[R5] |= DTR; uap->curregs[R12] = 0; uap->curregs[R13] = 0; uap->curregs[R14] = BRENAB; /* Clear handshaking, enable BREAK interrupts */ uap->curregs[R15] = BRKIE; /* Master interrupt enable */ uap->curregs[R9] |= NV | MIE; pmz_load_zsregs(uap, uap->curregs); /* Enable receiver and transmitter. */ write_zsreg(uap, R3, uap->curregs[R3] |= RxENABLE); write_zsreg(uap, R5, uap->curregs[R5] |= TxENABLE); /* Remember status for DCD/CTS changes */ uap->prev_status = read_zsreg(uap, R0); return pwr_delay; }
static void asdg_set_break(struct async_struct *info, int break_flag) { unsigned cflag, chsize; u_char val = TxENAB; #ifdef DEBUG printk("asdg_set_break: %d\n", break_flag); #endif if (!info->tty || !info->tty->termios) return; cflag = info->tty->termios->c_cflag; chsize = cflag & CSIZE; val |= (info->MCR & MCR_DTR) ? DTR : 0; val |= (info->MCR & MCR_RTS) ? RTS : 0; if(chsize==CS5) val |= Tx5; else if(chsize==CS6) val |= Tx6; else if(chsize==CS7) val |= Tx7; else val |= Tx8; if(break_flag) { val |= SND_BRK; info->MCR |= MCR_BREAK; } else info->MCR &= ~MCR_BREAK; #ifdef DEBUG printk("asdg_set_break: %x -> R5\n", val); #endif write_zsreg((struct SCCHalf *)info->port, R5, val); }
/* The port lock is not held. */ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); unsigned char set_bits, clear_bits, new_reg; unsigned long flags; set_bits = clear_bits = 0; if (break_state) set_bits |= SND_BRK; else clear_bits |= SND_BRK; spin_lock_irqsave(&port->lock, flags); new_reg = (up->curregs[R5] | set_bits) & ~clear_bits; if (new_reg != up->curregs[R5]) { up->curregs[R5] = new_reg; /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(channel, R5, up->curregs[R5]); } spin_unlock_irqrestore(&port->lock, flags); }
static void __ip22zilog_reset(struct uart_ip22zilog_port *up) { struct zilog_channel *channel; int i; if (up->flags & IP22ZILOG_FLAG_RESET_DONE) return; /* Let pending transmits finish. */ channel = ZILOG_CHANNEL_FROM_PORT(&up->port); for (i = 0; i < 1000; i++) { unsigned char stat = read_zsreg(channel, R1); if (stat & ALL_SNT) break; udelay(100); } if (!ZS_IS_CHANNEL_A(up)) { up++; channel = ZILOG_CHANNEL_FROM_PORT(&up->port); } write_zsreg(channel, R9, FHWRES); ZSDELAY_LONG(); (void) read_zsreg(channel, R0); up->flags |= IP22ZILOG_FLAG_RESET_DONE; up->next->flags |= IP22ZILOG_FLAG_RESET_DONE; }
/* * Control break state emission * The port lock is not held. */ static void pmz_break_ctl(struct uart_port *port, int break_state) { struct uart_pmac_port *uap = to_pmz(port); unsigned char set_bits, clear_bits, new_reg; unsigned long flags; if (uap->node == NULL) return; set_bits = clear_bits = 0; if (break_state) set_bits |= SND_BRK; else clear_bits |= SND_BRK; spin_lock_irqsave(&port->lock, flags); new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits; if (new_reg != uap->curregs[R5]) { uap->curregs[R5] = new_reg; /* NOTE: Not subject to 'transmitter active' rule. */ if (ZS_IS_ASLEEP(uap)) return; write_zsreg(uap, R5, uap->curregs[R5]); } spin_unlock_irqrestore(&port->lock, flags); }
static void pmz_status_handle(struct uart_pmac_port *uap) { unsigned char status; status = read_zsreg(uap, R0); write_zsreg(uap, R0, RES_EXT_INT); zssync(uap); if (ZS_IS_OPEN(uap) && ZS_WANTS_MODEM_STATUS(uap)) { if (status & SYNC_HUNT) uap->port.icount.dsr++; /* The Zilog just gives us an interrupt when DCD/CTS/etc. change. * But it does not tell us which bit has changed, we have to keep * track of this ourselves. * The CTS input is inverted for some reason. -- paulus */ if ((status ^ uap->prev_status) & DCD) uart_handle_dcd_change(&uap->port, (status & DCD)); if ((status ^ uap->prev_status) & CTS) uart_handle_cts_change(&uap->port, !(status & CTS)); wake_up_interruptible(&uap->port.info->delta_msr_wait); } if (status & BRK_ABRT) uap->flags |= PMACZILOG_FLAG_BREAK; uap->prev_status = status; }
static void z8530_dma_status(struct z8530_channel *chan) { u8 status, altered; status=read_zsreg(chan, R0); altered=chan->status^status; chan->status=status; if(chan->dma_tx) { if(status&TxEOM) { unsigned long flags; flags=claim_dma_lock(); disable_dma(chan->txdma); clear_dma_ff(chan->txdma); chan->txdma_on=0; release_dma_lock(flags); z8530_tx_done(chan); } } if(altered&chan->dcdcheck) { if(status&chan->dcdcheck) { printk(KERN_INFO "%s: DCD raised\n", chan->dev->name); write_zsreg(chan, R3, chan->regs[3]|RxENABLE); if(chan->netdevice && ((chan->netdevice->type == ARPHRD_HDLC) || (chan->netdevice->type == ARPHRD_PPP))) sppp_reopen(chan->netdevice); } else { printk(KERN_INFO "%s:DCD lost\n", chan->dev->name); write_zsreg(chan, R3, chan->regs[3]&~RxENABLE); z8530_flush_fifo(chan); } } write_zsctrl(chan, RES_EXT_INT); write_zsctrl(chan, RES_H_IUS); }
static void z8530_rtsdtr(struct z8530_channel *c, int set) { if (set) c->regs[5] |= (RTS | DTR); else c->regs[5] &= ~(RTS | DTR); write_zsreg(c, R5, c->regs[5]); }
void cleanup_module(void) { int i; for (i = 0; i < nr_asdg; i += 2) { struct SCC *scc = (struct SCC *)rs_table[lines[i]].board_base; write_zsreg(&scc->A, R9, FHWRES); udelay(10); /* Give card time to reset */ write_zsreg(&scc->B, R9, FHWRES); udelay(10); /* Give card time to reset */ unregister_serial(lines[i]); unregister_serial(lines[i+1]); zorro_unconfig_board(board_index[i/2], 1); } free_irq(IRQ_AMIGA_EXTER, asdg_interrupt); }
/* * Print a string to the serial port trying not to disturb * any possible real use of the port... */ static void pmz_console_write(struct console *con, const char *s, unsigned int count) { struct uart_pmac_port *uap = &pmz_ports[con->index]; unsigned long flags; if (ZS_IS_ASLEEP(uap)) return; spin_lock_irqsave(&uap->port.lock, flags); /* Turn of interrupts and enable the transmitter. */ write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR); uart_console_write(&uap->port, s, count, pmz_console_putchar); /* Restore the values in the registers. */ write_zsreg(uap, R1, uap->curregs[1]); /* Don't disable the transmitter. */ spin_unlock_irqrestore(&uap->port.lock, flags); }
static void pmz_shutdown(struct uart_port *port) { struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; pmz_debug("pmz: shutdown()\n"); if (uap->node == NULL) return; mutex_lock(&pmz_irq_mutex); /* Release interrupt handler */ free_irq(uap->port.irq, uap); spin_lock_irqsave(&port->lock, flags); uap->flags &= ~PMACZILOG_FLAG_IS_OPEN; if (!ZS_IS_OPEN(uap->mate)) pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON; /* Disable interrupts */ if (!ZS_IS_ASLEEP(uap)) { uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); write_zsreg(uap, R1, uap->curregs[R1]); zssync(uap); } if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) { spin_unlock_irqrestore(&port->lock, flags); mutex_unlock(&pmz_irq_mutex); return; } /* Disable receiver and transmitter. */ uap->curregs[R3] &= ~RxENABLE; uap->curregs[R5] &= ~TxENABLE; /* Disable all interrupts and BRK assertion. */ uap->curregs[R5] &= ~SND_BRK; pmz_maybe_update_regs(uap); /* Shut the chip down */ pmz_set_scc_power(uap, 0); spin_unlock_irqrestore(&port->lock, flags); mutex_unlock(&pmz_irq_mutex); pmz_debug("pmz: shutdown() done.\n"); }
static int asdg_set_modem_info(struct async_struct *info, int new_dtr, int new_rts) { unsigned cflag, chsize; u_char val = TxENAB; #ifdef DEBUG printk("asdg_set_modem_info dtr: %d, rts %d\n", new_dtr, new_rts); #endif if (!info->tty || !info->tty->termios) return 0; cflag = info->tty->termios->c_cflag; chsize = cflag & CSIZE; if(chsize==CS5) val|=Tx5; else if(chsize==CS6) val|=Tx6; else if(chsize==CS7) val|=Tx7; else val|=Tx8; if(new_dtr == 1) { info->MCR |= MCR_DTR; val |= DTR; } else if(new_dtr == 0) { info->MCR &= ~MCR_DTR; val &= ~DTR; } else if(new_dtr == -1) { val |= (info->MCR & MCR_DTR)?DTR:0; } if(new_rts == 1) { info->MCR |= MCR_RTS; val |= RTS; } else if(new_rts == 0) { info->MCR &= ~MCR_RTS; } else if(new_rts == -1) { val |= (info->MCR & MCR_RTS)?RTS:0; } if(info->MCR & MCR_BREAK) val |= SND_BRK; #ifdef DEBUG printk("asdg_set_modem_info: %x -> R5\n", val); #endif write_zsreg((struct SCCHalf *)info->port, R5, val); return 0; }
static void __init ip22zilog_init_hw(void) { int i; for (i = 0; i < NUM_CHANNELS; i++) { struct uart_ip22zilog_port *up = &ip22zilog_port_table[i]; struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); unsigned long flags; int baud, brg; spin_lock_irqsave(&up->port.lock, flags); if (ZS_IS_CHANNEL_A(up)) { write_zsreg(channel, R9, FHWRES); ZSDELAY_LONG(); (void) read_zsreg(channel, R0); } /* Normal serial TTY. */ up->parity_mask = 0xff; up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; up->curregs[R4] = PAR_EVEN | X16CLK | SB1; up->curregs[R3] = RxENAB | Rx8; up->curregs[R5] = TxENAB | Tx8; up->curregs[R9] = NV | MIE; up->curregs[R10] = NRZ; up->curregs[R11] = TCBR | RCBR; baud = 9600; brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; up->curregs[R14] = BRENAB; __load_zsregs(channel, up->curregs); /* set master interrupt enable */ write_zsreg(channel, R9, up->curregs[R9]); spin_unlock_irqrestore(&up->port.lock, flags); } }
static void z8530_status(struct z8530_channel *chan) { u8 status, altered; status=read_zsreg(chan, R0); altered=chan->status^status; chan->status=status; if(status&TxEOM) { /* printk("%s: Tx underrun.\n", chan->dev->name); */ chan->stats.tx_fifo_errors++; write_zsctrl(chan, ERR_RES); z8530_tx_done(chan); } if(altered&chan->dcdcheck) { if(status&chan->dcdcheck) { printk(KERN_INFO "%s: DCD raised\n", chan->dev->name); write_zsreg(chan, R3, chan->regs[3]|RxENABLE); if(chan->netdevice && ((chan->netdevice->type == ARPHRD_HDLC) || (chan->netdevice->type == ARPHRD_PPP))) sppp_reopen(chan->netdevice); } else { printk(KERN_INFO "%s: DCD lost\n", chan->dev->name); write_zsreg(chan, R3, chan->regs[3]&~RxENABLE); z8530_flush_fifo(chan); } } write_zsctrl(chan, RES_EXT_INT); write_zsctrl(chan, RES_H_IUS); }
/* The port lock is held. */ static void ip22zilog_enable_ms(struct uart_port *port) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); unsigned char new_reg; new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); if (new_reg != up->curregs[R15]) { up->curregs[R15] = new_reg; /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(channel, R15, up->curregs[R15]); } }
/* Shutdown the port - turn off ints */ static void asdg_deinit(struct async_struct *info, int leave_dtr) { struct SCCHalf *port= (struct SCCHalf *)info->port; #ifdef DEBUG printk("asdg_deinit: %p\n", port); #endif /* Turn off interrupts */ #ifdef DEBUG printk("Port %p Interrupts off\n", port); #endif write_zsreg(port, R1, 0); /* Drop RTS, DTR */ asdg_set_modem_info(info, 0, 0); write_zsreg(port, R5, Tx8); #ifdef DEBUG printk("asdg_deinit: %x -> R5\n", Tx8); #endif write_zsreg(port, R3, Rx8); }
int z8530_shutdown(struct z8530_dev *dev) { unsigned long flags; /* Reset the chip */ spin_lock_irqsave(&dev->lock, flags); dev->chanA.irqs=&z8530_nop; dev->chanB.irqs=&z8530_nop; write_zsreg(&dev->chanA, R9, 0xC0); /* We must lock the udelay, the chip is offlimits here */ udelay(100); spin_unlock_irqrestore(&dev->lock, flags); return 0; }
/* The port lock is not held. */ static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; spin_lock_irqsave(&port->lock, flags); /* Disable IRQs on the port */ uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); write_zsreg(uap, R1, uap->curregs[R1]); /* Setup new port configuration */ __pmz_set_termios(port, termios, old); /* Re-enable IRQs on the port */ if (ZS_IS_OPEN(uap)) { uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB; if (!ZS_IS_EXTCLK(uap)) uap->curregs[R1] |= EXT_INT_ENAB; write_zsreg(uap, R1, uap->curregs[R1]); } spin_unlock_irqrestore(&port->lock, flags); }
/* * Enable modem status change interrupts * The port lock is held. */ static void pmz_enable_ms(struct uart_port *port) { struct uart_pmac_port *uap = to_pmz(port); unsigned char new_reg; if (ZS_IS_IRDA(uap) || uap->node == NULL) return; new_reg = uap->curregs[R15] | (DCDIE | SYNCIE | CTSIE); if (new_reg != uap->curregs[R15]) { uap->curregs[R15] = new_reg; if (ZS_IS_ASLEEP(uap)) return; /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(uap, R15, uap->curregs[R15]); } }
int z8530_sync_close(struct net_device *dev, struct z8530_channel *c) { u8 chk; unsigned long flags; spin_lock_irqsave(c->lock, flags); c->irqs = &z8530_nop; c->max = 0; c->sync = 0; chk=read_zsreg(c,R0); write_zsreg(c, R3, c->regs[R3]); z8530_rtsdtr(c,0); spin_unlock_irqrestore(c->lock, flags); return 0; }
static void __ip22zilog_startup(struct uart_ip22zilog_port *up) { struct zilog_channel *channel; channel = ZILOG_CHANNEL_FROM_PORT(&up->port); __ip22zilog_reset(up); __load_zsregs(channel, up->curregs); /* set master interrupt enable */ write_zsreg(channel, R9, up->curregs[R9]); up->prev_status = readb(&channel->control); /* Enable receiver and transmitter. */ up->curregs[R3] |= RxENAB; up->curregs[R5] |= TxENAB; up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; ip22zilog_maybe_update_regs(up, channel); }