void sab8253x_transmit_charsS(struct sab_port *port, union sab8253x_irq_status *stat) { if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) { port->interrupt_mask1 |= SAB82532_IMR1_ALLS; WRITEB(port, imr1, port->interrupt_mask1); port->all_sent = 1; } sab8253x_start_txS(port); }
void sab8253x_init_lineS(struct sab_port *port) { unsigned char stat; if(port->chip->c_cim) { if(port->chip->c_cim->ci_type == CIM_SP502) { aura_sp502_program(port, SP502_OFF_MODE); } } /* * Wait for any commands or immediate characters */ sab8253x_cec_wait(port); #if 0 sab8253x_tec_wait(port); /* I have to think about this one * should I assume the line was * previously in async mode*/ #endif /* * Clear the FIFO buffers. */ WRITEB(port, cmdr, SAB82532_CMDR_RHR); sab8253x_cec_wait(port); WRITEB(port,cmdr,SAB82532_CMDR_XRES); /* * Clear the interrupt registers. */ stat = READB(port, isr0); /* acks ints */ stat = READB(port, isr1); /* * Now, initialize the UART */ WRITEB(port, ccr0, 0); /* power-down */ WRITEB(port, ccr0, getccr0configS(port)); WRITEB(port, ccr1, getccr1configS(port)); WRITEB(port, ccr2, getccr2configS(port)); WRITEB(port, ccr3, getccr3configS(port)); WRITEB(port, ccr4, getccr4configS(port)); /* 32 byte receive fifo */ WRITEB(port, mode, getmodeS(port)); WRITEB(port, tic /* really rlcr */, getrlcrconfigS(port)); /* power-up */ switch(port->ccontrol.ccr4 & SAB82532_CCR4_RF02) { case SAB82532_CCR4_RF32: port->recv_fifo_size = 32; break; case SAB82532_CCR4_RF16: port->recv_fifo_size = 16; break; case SAB82532_CCR4_RF04: port->recv_fifo_size = 4; break; case SAB82532_CCR4_RF02: port->recv_fifo_size = 2; break; default: port->recv_fifo_size = 32; port->ccontrol.ccr4 &= ~SAB82532_CCR4_RF02; break; } if(port->ccontrol.ccr2 & SAB82532_CCR2_TOE) { RAISE(port, txclkdir); } else { LOWER(port, txclkdir); } SET_REG_BIT(port,ccr0,SAB82532_CCR0_PU); if(port->chip->c_cim) { if(port->chip->c_cim->ci_type == CIM_SP502) { aura_sp502_program(port, port->sigmode); } } }
void sab8253x_start_txS(struct sab_port *port) { unsigned long flags; register int count; register int total; register int offset; char temporary[32]; register unsigned int slopspace; register int sendsize; unsigned int totaltransmit; unsigned fifospace; unsigned loadedcount; struct tty_struct *tty = port->tty; /* a little gross tty flags whether invoked from a tty or the network */ fifospace = port->xmit_fifo_size; /* This code can handle fragmented frames although currently none are generated*/ loadedcount = 0; if(port->sabnext2.transmit == NULL) { return; } save_flags(flags); cli(); if(count = port->sabnext2.transmit->Count, (count & OWNER) == OWN_SAB) { count &= ~OWN_SAB; /* OWN_SAB is really 0 but cannot guarantee in the future */ if(port->sabnext2.transmit->HostVaddr) { total = (port->sabnext2.transmit->HostVaddr->tail - port->sabnext2.transmit->HostVaddr->data); /* packet size */ } else { total = 0; /* the data is only the crc/trailer */ } if(tty && (tty->stopped || tty->hw_stopped) && (count == total)) { /* works for frame that only has a trailer (crc) */ port->interrupt_mask1 |= SAB82532_IMR1_XPR; WRITEB(port, imr1, port->interrupt_mask1); restore_flags(flags); /* can't send */ return; } offset = (total - count); /* offset to data still to send */ port->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS); WRITEB(port, imr1, port->interrupt_mask1); port->all_sent = 0; if(READB(port,star) & SAB82532_STAR_XFW) { if(count <= fifospace) { port->xmit_cnt = count; slopspace = 0; sendsize = 0; if(port->sabnext2.transmit->sendcrc) /* obviously should not happen for async but might use for priority transmission */ { slopspace = fifospace - count; } if(slopspace) { if(count) { memcpy(temporary, &port->sabnext2.transmit->HostVaddr->data[offset], count); } sendsize = MIN(slopspace, (4 - port->sabnext2.transmit->crcindex)); /* how many bytes to send */ memcpy(&temporary[count], &((unsigned char*)(&port->sabnext2.transmit->crc)) [port->sabnext2.transmit->crcindex], sendsize); port->sabnext2.transmit->crcindex += sendsize; if(port->sabnext2.transmit->crcindex >= 4) { port->sabnext2.transmit->sendcrc = 0; } port->xmit_buf = temporary; } else { port->xmit_buf = /* set up wrifefifo variables */ &port->sabnext2.transmit->HostVaddr->data[offset]; } port->xmit_cnt += sendsize; count = 0; } else { count -= fifospace; port->xmit_cnt = fifospace; port->xmit_buf = /* set up wrifefifo variables */ &port->sabnext2.transmit->HostVaddr->data[offset]; } port->xmit_tail= 0; loadedcount = port->xmit_cnt; (*port->writefifo)(port); totaltransmit = Sab8253xCountTransmitDescriptors(port); if(tty && (totaltransmit < (sab8253xs_listsize/2))) /* only makes sense on a TTY */ { sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP); } if((sab8253xt_listsize - totaltransmit) > (sab8253xt_listsize/2)) { port->buffergreedy = 0; } else { port->buffergreedy = 1; } port->xmit_buf = NULL; /* this var is used to indicate whether to call kfree */ /* fifospace -= loadedcount;*/ /* Here to make mods to handle arbitrarily fragmented frames look to 8253xtty.c for help */ if ((count <= 0) && (port->sabnext2.transmit->sendcrc == 0)) { port->sabnext2.transmit->Count = OWN_DRIVER; if(!tty) { /* called by network driver */ ++(port->Counters.transmitpacket); } #ifdef FREEININTERRUPT /* treat this routine as if taking place in interrupt */ if(port->sabnext2.transmit->HostVaddr) { skb_unlink(port->sabnext2.transmit->HostVaddr); dev_kfree_skb_any(port->sabnext2.transmit->HostVaddr); port->sabnext2.transmit->HostVaddr = 0; /* no skb */ } port->sabnext2.transmit->crcindex = 0; /* no single byte */ #endif sab8253x_cec_wait(port); WRITEB(port, cmdr, SAB82532_CMDR_XME|SAB82532_CMDR_XTF); /* Terminate the frame */ port->sabnext2.transmit = port->sabnext2.transmit->VNext; if(!tty && port->tx_full) /* invoked from the network driver */ { port->tx_full = 0; /* there is a free slot */ switch(port->open_type) { case OPEN_SYNC_NET: #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) port->dev->start = 1; port->dev->tbusy = 0; /* maybe need mark_bh here */ #else netif_start_queue(port->dev); #endif break; case OPEN_SYNC_CHAR: wake_up_interruptible(&port->write_wait); break; default: break; } } if((port->sabnext2.transmit->Count & OWNER) == OWN_SAB) { /* new frame to send */ port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); WRITEB(port, imr1, port->interrupt_mask1); } else { port->interrupt_mask1 |= SAB82532_IMR1_XPR; WRITEB(port, imr1, port->interrupt_mask1); if((port->open_type == OPEN_SYNC_CHAR) && port->async_queue) { /* if indication of transmission is needed by the */ /* application on a per-frame basis kill_fasync */ /* can provide it */ kill_fasync(&port->async_queue, SIGIO, POLL_OUT); } } restore_flags(flags); return; } /* Issue a Transmit FIFO command. */ sab8253x_cec_wait(port); WRITEB(port, cmdr, SAB82532_CMDR_XTF); port->sabnext2.transmit->Count = (count|OWN_SAB); } port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); /* more to send */ WRITEB(port, imr1, port->interrupt_mask1); } else { /* nothing to send */ port->interrupt_mask1 |= SAB82532_IMR1_XPR; WRITEB(port, imr1, port->interrupt_mask1); } restore_flags(flags); return; }
void sab8253x_closeS(struct tty_struct *tty, struct file * filp) { struct sab_port *port = (struct sab_port *)tty->driver_data; unsigned long flags; MOD_DEC_USE_COUNT; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_closeS")) { return; } if(port->open_type == OPEN_SYNC_NET) { /* port->tty field should already be NULL */ return; } save_flags(flags); cli(); --(port->count); if (tty_hung_up_p(filp)) { if(port->count == 0) /* I think the reason for the weirdness relates to freeing of structures in the tty driver */ { port->open_type = OPEN_NOT; } else if(port->count < 0) { printk(KERN_ALERT "XX20: port->count went negative.\n"); port->count = 0; port->open_type = OPEN_NOT; } restore_flags(flags); return; } #if 0 if ((tty->count == 1) && (port->count != 0)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. port->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk("sab8253x_close: bad serial port count; tty->count is 1," " port->count is %d\n", port->count); port->count = 0; } #endif if (port->count < 0) { printk(KERN_ALERT "sab8253x_close: bad serial port count for ttys%d: %d\n", port->line, port->count); port->count = 0; } if (port->count) { restore_flags(flags); return; } port->flags |= FLAG8253X_CLOSING; /* * Save the termios structure, since this port may have * separate termios for callout and dialin. */ if (port->flags & FLAG8253X_NORMAL_ACTIVE) { port->normal_termios = *tty->termios; } if (port->flags & FLAG8253X_CALLOUT_ACTIVE) { port->callout_termios = *tty->termios; } /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; if (port->closing_wait != SAB8253X_CLOSING_WAIT_NONE) { tty_wait_until_sent(tty, port->closing_wait); } /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and turn off * the receiver. */ #if 0 port->interrupt_mask0 |= SAB82532_IMR0_TCD; /* not needed for sync */ #endif WRITEB(port,imr0,port->interrupt_mask0); CLEAR_REG_BIT(port, mode, SAB82532_MODE_RAC); /* turn off receiver */ if (port->flags & FLAG8253X_INITIALIZED) { /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially * important if there is a transmit FIFO! */ sab8253x_wait_until_sent(tty, port->timeout); } sab8253x_shutdownS(port); Sab8253xCleanUpTransceiveN(port); if (tty->driver.flush_buffer) { tty->driver.flush_buffer(tty); } tty_ldisc_flush(tty); tty->closing = 0; port->event = 0; port->tty = 0; if (port->blocked_open) { if (port->close_delay) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(port->close_delay); } wake_up_interruptible(&port->open_wait); } port->flags &= ~(FLAG8253X_NORMAL_ACTIVE|FLAG8253X_CALLOUT_ACTIVE| FLAG8253X_CLOSING); wake_up_interruptible(&port->close_wait); port->open_type = OPEN_NOT; restore_flags(flags); }
static int sab8253x_startupS(struct sab_port *port) { unsigned long flags; int retval = 0; save_flags(flags); cli(); port->msgbufindex = 0; port->xmit_buf = NULL; port->buffergreedy = 0; if (port->flags & FLAG8253X_INITIALIZED) { goto errout; } if (!port->regs) { if (port->tty) { set_bit(TTY_IO_ERROR, &port->tty->flags); } retval = -ENODEV; goto errout; } /* * Initialize the Hardware */ sab8253x_init_lineS(port); #if 0 /* maybe should be conditional */ if (port->tty->termios->c_cflag & CBAUD) { #endif /* Activate RTS */ RAISE(port,rts); /* Activate DTR */ RAISE(port,dtr); #if 0 } #endif /* * Initialize the modem signals values */ port->dcd.val=ISON(port,dcd); port->cts.val=ISON(port,cts); port->dsr.val=ISON(port,dsr); /* * Finally, enable interrupts */ port->interrupt_mask0 = SAB82532_IMR0_RFS | SAB82532_IMR0_PCE | SAB82532_IMR0_PLLA | SAB82532_IMR0_RSC | SAB82532_IMR0_CDSC; /*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? SAB82532_IMR0_CDSC : 0); */ WRITEB(port,imr0,port->interrupt_mask0); port->interrupt_mask1 = SAB82532_IMR1_EOP | SAB82532_IMR1_XMR | SAB82532_IMR1_TIN | SAB82532_IMR1_XPR; WRITEB(port, imr1, port->interrupt_mask1); port->all_sent = 1; if (port->tty) { clear_bit(TTY_IO_ERROR, &port->tty->flags); } port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; /* * and set the speed of the serial port */ sab8253x_change_speedS(port); port->flags |= FLAG8253X_INITIALIZED; port->receive_chars = sab8253x_receive_charsS; port->transmit_chars = sab8253x_transmit_charsS; port->check_status = sab8253x_check_statusS; port->receive_test = (SAB82532_ISR0_RME | SAB82532_ISR0_RFO | SAB82532_ISR0_RPF); port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_RDO | SAB82532_ISR1_XPR | SAB82532_ISR1_XDU | SAB82532_ISR1_CSC); port->check_status_test = (SAB82532_ISR1_CSC); /*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? 0 : SAB82532_ISR0_CDSC));*/ restore_flags(flags); return 0; errout: restore_flags(flags); return retval; }
static void sab8253x_shutdownS(struct sab_port *port) { unsigned long flags; if (!(port->flags & FLAG8253X_INITIALIZED)) { return; } save_flags(flags); cli(); /* Disable interrupts */ /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq * here so the queue might never be waken up */ wake_up_interruptible(&port->delta_msr_wait); if (port->xmit_buf) { port->xmit_buf = 0; } #ifdef XCONFIG_SERIAL_CONSOLE if (port->is_console) { port->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR | /*SAB82532_IMR0_TIME |*/ SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC; WRITEB(port,imr0,port->interrupt_mask0); port->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS | SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN | SAB82532_IMR1_CSC | SAB82532_IMR1_XON | SAB82532_IMR1_XPR; WRITEB(port,imr1,port->interrupt_mask1); if (port->tty) { set_bit(TTY_IO_ERROR, &port->tty->flags); } port->flags &= ~FLAG8253X_INITIALIZED; restore_flags(flags); return; } #endif /* Disable Interrupts */ port->interrupt_mask0 = 0xff; WRITEB(port, imr0, port->interrupt_mask0); port->interrupt_mask1 = 0xff; WRITEB(port, imr1, port->interrupt_mask1); if (!port->tty || (port->tty->termios->c_cflag & HUPCL)) { LOWER(port,rts); LOWER(port,dtr); } /* Disable Receiver */ CLEAR_REG_BIT(port,mode,SAB82532_MODE_RAC); /* Power Down */ CLEAR_REG_BIT(port,ccr0,SAB82532_CCR0_PU); if (port->tty) { set_bit(TTY_IO_ERROR, &port->tty->flags); } port->flags &= ~FLAG8253X_INITIALIZED; restore_flags(flags); }
/* * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ static void sab8253x_change_speedS(struct sab_port *port) { unsigned long flags,baud; tcflag_t cflag; u8 ccr2=0,ccr4=0,ebrg=0; int i, bits; #ifdef DEBUGGING printk("Change speed! "); #endif if (!port->tty || !port->tty->termios) { #ifdef DEBUGGING printk("NOT!\n"); #endif return; } #ifdef DEBUGGING printk(" for real.\n"); #endif cflag = port->tty->termios->c_cflag; /* Byte size and parity */ switch (cflag & CSIZE) { case CS5: bits = 7; break; case CS6: bits = 8; break; case CS7: bits = 9; break; default: case CS8: bits = 10; break; } if (cflag & CSTOPB) { bits++; } if (cflag & PARENB) { bits++; } /* Determine EBRG values based on the "encoded"baud rate */ i = cflag & CBAUD; switch(i) { case B0: baud=0; break; case B50: baud=100; break; case B75: baud=150; break; case B110: baud=220; break; case B134: baud=269; break; case B150: baud=300; break; case B200: baud=400; break; case B300: baud=600; break; case B600: baud=1200; break; case B1200: baud=2400; break; case B1800: baud=3600; break; case B2400: baud=4800; break; case B4800: baud=9600; break; case B9600: baud=19200; break; case B19200: baud=38400; break; case B38400: if(port->custspeed) { baud=port->custspeed<<1; } else { baud=76800; } break; case B57600: baud=115200; break; #ifdef SKIPTHIS case B76800: baud=153600; break; case B153600: baud=307200; break; #endif case B230400: baud=460800; break; case B460800: baud=921600; break; case B115200: default: baud=230400; break; } if(!sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud))) { printk("Aurora Warning. baudrate %ld could not be set! Using 115200",baud); baud=230400; sab8253x_baud(port,baud,&ebrg,&ccr2,&ccr4,&(port->baud)); } if (port->baud) port->timeout = (port->xmit_fifo_size * HZ * bits) / port->baud; else port->timeout = 0; port->timeout += HZ / 50; /* Add .02 seconds of slop */ /* CTS flow control flags */ if (cflag & CRTSCTS) port->flags |= FLAG8253X_CTS_FLOW; else port->flags &= ~(FLAG8253X_CTS_FLOW); if (cflag & CLOCAL) port->flags &= ~(FLAG8253X_CHECK_CD); else port->flags |= FLAG8253X_CHECK_CD; if (port->tty) port->tty->hw_stopped = 0; /* * Set up parity check flag * XXX: not implemented, yet. */ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) /* * Characters to ignore * XXX: not implemented, yet. */ /* * !!! ignore all characters if CREAD is not set * XXX: not implemented, yet. */ if ((cflag & CREAD) == 0) port->ignore_status_mask |= SAB82532_ISR0_RPF; save_flags(flags); cli(); sab8253x_cec_wait(port); WRITEB(port, bgr, ebrg); WRITEB(port, ccr2, READB(port, ccr2) & ~(0xc0)); /* clear out current baud rage */ WRITEB(port, ccr2, READB(port, ccr2) | ccr2); WRITEB(port, ccr4, (READB(port,ccr4) & ~SAB82532_CCR4_EBRG) | ccr4); if (port->flags & FLAG8253X_CTS_FLOW) { WRITEB(port, mode, READB(port,mode) & ~(SAB82532_MODE_RTS)); port->interrupt_mask1 &= ~(SAB82532_IMR1_CSC); WRITEB(port, imr1, port->interrupt_mask1); } else { WRITEB(port, mode, READB(port,mode) | SAB82532_MODE_RTS); port->interrupt_mask1 |= SAB82532_IMR1_CSC; WRITEB(port, imr1, port->interrupt_mask1); } WRITEB(port, mode, READB(port, mode) | SAB82532_MODE_RAC); restore_flags(flags); }
static void sab8253x_receive_charsS(struct sab_port *port, union sab8253x_irq_status *stat) { struct tty_struct *tty = port->tty; unsigned char buf[32]; int free_fifo = 0; int reset_fifo = 0; int msg_done = 0; int msg_bad = 0; int count = 0; int total_size = 0; int rstatus = 0; struct sk_buff *skb; /* Read number of BYTES (Character + Status) available. */ if((stat->images[ISR1_IDX] & SAB82532_ISR1_RDO) || (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) ) { ++msg_bad; ++free_fifo; ++reset_fifo; } else { if (stat->images[ISR0_IDX] & SAB82532_ISR0_RPF) { count = port->recv_fifo_size; ++free_fifo; } if (stat->images[ISR0_IDX] & SAB82532_ISR0_RME) { count = READB(port, rbcl); count &= (port->recv_fifo_size - 1); ++msg_done; ++free_fifo; total_size = READB(port, rbch); if(total_size & SAB82532_RBCH_OV) /* need to revisit for 4096 byte frames */ { msg_bad++; } rstatus = READB(port, rsta); if((rstatus & SAB82532_RSTA_VFR) == 0) { msg_bad++; } if(rstatus & SAB82532_RSTA_RDO) { msg_bad++; } if((rstatus & SAB82532_RSTA_CRC) == 0) { msg_bad++; } if(rstatus & SAB82532_RSTA_RAB) { msg_bad++; } } } /* Read the FIFO. */ (*port->readfifo)(port, buf, count); /* Issue Receive Message Complete command. */ if (free_fifo) { sab8253x_cec_wait(port); WRITEB(port, cmdr, SAB82532_CMDR_RMC); } if(reset_fifo) { sab8253x_cec_wait(port); WRITEB(port, cmdr, SAB82532_CMDR_RHR); } if(msg_bad) { port->msgbufindex = 0; return; } memcpy(&port->msgbuf[port->msgbufindex], buf, count); port->msgbufindex += count; #ifdef CONSOLE_SUPPORT if (port->is_console) { wake_up(&keypress_wait); } #endif if(msg_done) { if(port->msgbufindex <= 3) /* min is 1 char + 2 CRC + status byte */ { port->msgbufindex = 0; return; } total_size = port->msgbufindex - 3; /* strip off the crc16 and the status byte */ port->msgbufindex = 0; /* ignore the receive buffer waiting -- we know the correct size here */ if (!tty) { return; } if(skb = dev_alloc_skb(total_size), skb) { memcpy(skb->data, &port->msgbuf[0], total_size); skb->tail = (skb->data + total_size); skb->data_len = total_size; skb->len = total_size; skb_queue_tail(port->sab8253xc_rcvbuflist, skb); } queue_task(&tty->flip.tqueue, &tq_timer); /* clear out flip buffer as fast as possible * maybe should not be done unconditionally hear * but should be within the above consequence * clause */ } }
int sab8253x_startupN(struct sab_port *port) { unsigned long flags; int retval = 0; save_flags(flags); cli(); if (port->flags & FLAG8253X_INITIALIZED) { goto errout; } if (!port->regs) { retval = -ENODEV; goto errout; } /* * Initialize the Hardware */ sab8253x_init_lineS(port); /* nothing in this function * refers to tty structure */ /* Activate RTS */ RAISE(port,rts); /* Activate DTR */ RAISE(port,dtr); /* * Initialize the modem signals values */ port->dcd.val=ISON(port,dcd); port->cts.val=ISON(port,cts); port->dsr.val=ISON(port,dsr); /* * Finally, enable interrupts */ port->interrupt_mask0 = SAB82532_IMR0_RFS | SAB82532_IMR0_PCE | SAB82532_IMR0_PLLA | SAB82532_IMR0_RSC | SAB82532_IMR0_CDSC; /*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? SAB82532_IMR0_CDSC : 0); */ WRITEB(port,imr0,port->interrupt_mask0); port->interrupt_mask1 = SAB82532_IMR1_EOP | SAB82532_IMR1_XMR | SAB82532_IMR1_TIN | SAB82532_IMR1_XPR; WRITEB(port, imr1, port->interrupt_mask1); port->all_sent = 1; /* * and set the speed of the serial port */ sab8253x_change_speedN(port); port->flags |= FLAG8253X_INITIALIZED; /* bad name for indicating to other functionalities status */ port->receive_chars = sab8253x_receive_charsN; port->transmit_chars = sab8253x_transmit_charsS; port->check_status = sab8253x_check_statusN; port->receive_test = (SAB82532_ISR0_RME | SAB82532_ISR0_RFO | SAB82532_ISR0_RPF); port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_RDO | SAB82532_ISR1_XPR | SAB82532_ISR1_XDU | SAB82532_ISR1_CSC); port->check_status_test = (SAB82532_ISR1_CSC); /*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? 0 : SAB82532_ISR0_CDSC));*/ restore_flags(flags); return 0; errout: restore_flags(flags); return retval; }
static void sab8253x_check_statusN(struct sab_port *port, union sab8253x_irq_status *stat) { int modem_change = 0; mctlsig_t *sig; if (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) { port->icount.buf_overrun++; } /* Checking DCD */ sig = &port->dcd; if (stat->images[sig->irq] & sig->irqmask) { sig->val = ISON(port,dcd); port->icount.dcd++; modem_change++; } /* Checking CTS */ sig = &port->cts; if (stat->images[sig->irq] & sig->irqmask) { sig->val = ISON(port,cts); port->icount.cts++; modem_change++; } /* Checking DSR */ sig = &port->dsr; if (stat->images[sig->irq] & sig->irqmask) { sig->val = ISON(port,dsr); port->icount.dsr++; modem_change++; } if (modem_change) { wake_up_interruptible(&port->delta_msr_wait); } sig = &port->dcd; if ((port->flags & FLAG8253X_CHECK_CD) && (stat->images[sig->irq] & sig->irqmask)) { if (sig->val) { netif_carrier_on(port->dev); } else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) && (port->flags & FLAG8253X_CALLOUT_NOHUP))) { netif_carrier_off(port->dev); } } #if 0 /* need to think about CTS/RTS stuff for a network driver */ sig = &port->cts; if (port->flags & FLAG8253X_CTS_FLOW) { /* not setting this yet */ if (port->tty->hw_stopped) { if (sig->val) { port->tty->hw_stopped = 0; sab8253x_sched_event(port, RS_EVENT_WRITE_WAKEUP); port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR); WRITEB(port, imr1, port->interrupt_mask1); sab8253x_start_txS(port); } } else { if (!(sig->val)) { port->tty->hw_stopped = 1; } } } #endif }
/* stream */ static void sab8253x_receive_charsN(struct sab_port *port, union sab8253x_irq_status *stat) { unsigned char buf[32]; int free_fifo = 0; int reset_fifo = 0; int msg_done = 0; int msg_bad = 0; int count = 0; int total_size = 0; int rstatus = 0; struct sk_buff *skb; /* Read number of BYTES (Character + Status) available. */ if((stat->images[ISR1_IDX] & SAB82532_ISR1_RDO) || (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) ) { ++msg_bad; ++free_fifo; ++reset_fifo; } else { if (stat->images[ISR0_IDX] & SAB82532_ISR0_RPF) { count = port->recv_fifo_size; ++free_fifo; } if (stat->images[ISR0_IDX] & SAB82532_ISR0_RME) { count = READB(port,rbcl); count &= (port->recv_fifo_size - 1); ++msg_done; ++free_fifo; total_size = READB(port, rbch); if(total_size & SAB82532_RBCH_OV) { msg_bad++; } rstatus = READB(port, rsta); if((rstatus & SAB82532_RSTA_VFR) == 0) { msg_bad++; } if(rstatus & SAB82532_RSTA_RDO) { msg_bad++; } if((rstatus & SAB82532_RSTA_CRC) == 0) { msg_bad++; } if(rstatus & SAB82532_RSTA_RAB) { msg_bad++; } } } /* Read the FIFO. */ (*port->readfifo)(port, buf, count); /* Issue Receive Message Complete command. */ if (free_fifo) { sab8253x_cec_wait(port); WRITEB(port, cmdr, SAB82532_CMDR_RMC); } if(reset_fifo) { sab8253x_cec_wait(port); WRITEB(port, cmdr, SAB82532_CMDR_RHR); } if(port->active2.receive == NULL) { return; } if(msg_bad) { ++(port->Counters.rx_drops); port->active2.receive->HostVaddr->tail = port->active2.receive->HostVaddr->data; /* clear the buffer */ port->active2.receive->Count = sab8253xn_rbufsize|OWN_SAB; return; } memcpy(port->active2.receive->HostVaddr->tail, buf, count); port->active2.receive->HostVaddr->tail += count; if(msg_done) { port->active2.receive->Count = (port->active2.receive->HostVaddr->tail - port->active2.receive->HostVaddr->data); if((port->active2.receive->Count < (ETH_ZLEN+4+3)) || /* 4 is the CRC32 size 3 bytes from the SAB part */ (skb = dev_alloc_skb(sab8253xn_rbufsize), skb == NULL)) { ++(port->Counters.rx_drops); port->active2.receive->HostVaddr->tail = port->active2.receive->HostVaddr->data; /* clear the buffer */ port->active2.receive->Count = sab8253xn_rbufsize|OWN_SAB; } else { port->active2.receive->Count -= 3; port->active2.receive->HostVaddr->len = port->active2.receive->Count; port->active2.receive->HostVaddr->pkt_type = PACKET_HOST; port->active2.receive->HostVaddr->dev = port->dev; port->active2.receive->HostVaddr->protocol = eth_type_trans(port->active2.receive->HostVaddr, port->dev); port->active2.receive->HostVaddr->tail -= 3; ++(port->Counters.receivepacket); port->Counters.receivebytes += port->active2.receive->Count; skb_unlink(port->active2.receive->HostVaddr); netif_rx(port->active2.receive->HostVaddr); skb_queue_head(port->sab8253xbuflist, skb); port->active2.receive->HostVaddr = skb; port->active2.receive->Count = sab8253xn_rbufsize|OWN_SAB; } } }