void sab8253x_startS(struct tty_struct *tty) { struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_start")) { return; } sab8253x_start_txS(port); }
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_send_xcharS(struct tty_struct *tty, char ch) { struct sab_port *port = (struct sab_port *)tty->driver_data; unsigned long flags; int stopped; int hw_stopped; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_send_xcharS")) { return; } if (!tty) { return; } if(port->sabnext2.transmit == NULL) { return; } save_flags(flags); cli(); if((port->sabnext2.transmit->Count & OWNER) == OWN_SAB) /* may overwrite a character * -- but putting subsequent * XONs or XOFFs later in the * stream could cause problems * with the XON and XOFF protocol */ { port->sabnext2.transmit->sendcrc = 1; port->sabnext2.transmit->crcindex = 3; port->sabnext2.transmit->crc = (ch << 24); /* LITTLE ENDIAN */ restore_flags(flags); } else { restore_flags(flags); sab8253x_writeS(tty, 0, &ch, 1); } stopped = tty->stopped; hw_stopped = tty->hw_stopped; tty->stopped = 0; tty->hw_stopped = 0; sab8253x_start_txS(port); tty->stopped = stopped; tty->hw_stopped = hw_stopped; }
void sab8253x_flush_charsS(struct tty_struct *tty) { struct sab_port *port = (struct sab_port *)tty->driver_data; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_flush_chars")) { return; } if ((Sab8253xCountTransmit(port) <= 0) || tty->stopped || tty->hw_stopped) { /* can't flush */ return; } sab8253x_start_txS(port); }
int sab8253x_writeS(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { struct sab_port *port = (struct sab_port *)tty->driver_data; struct sk_buff *skb; int truelength = 0; int do_queue = 1; if (sab8253x_serial_paranoia_check(port, tty->device, "sab8253x_write")) { return 0; } if(count == 0) { return 0; } if(port->active2.transmit == NULL) { return 0; } if((port->active2.transmit->Count & OWNER) == OWN_SAB) { sab8253x_start_txS(port); /* no descriptor slot */ return 0; } #ifndef FREEININTERRUPT skb = port->active2.transmit->HostVaddr; /* current slot value */ if(port->buffergreedy == 0) /* are we avoiding buffer free's */ { /* no */ if((skb != NULL) || /* not OWN_SAB from above */ (port->active2.transmit->crcindex != 0)) { register RING_DESCRIPTOR *freeme; freeme = port->active2.transmit; do { if((freeme->crcindex == 0) && (freeme->HostVaddr == NULL)) { break; } if(freeme->HostVaddr) { skb_unlink((struct sk_buff*)freeme->HostVaddr); dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr); freeme->HostVaddr = NULL; } freeme->sendcrc = 0; freeme->crcindex = 0; freeme = (RING_DESCRIPTOR*) freeme->VNext; } while((freeme->Count & OWNER) != OWN_SAB); } skb = NULL; /* buffer was freed */ } if(skb != NULL) /* potentially useful */ { truelength = (skb->end - skb->head); if(truelength >= count) { skb->data = skb->head; /* this buffer is already queued */ skb->tail = skb->head; do_queue = 0; } else { skb_unlink(skb); dev_kfree_skb_any(skb); skb = NULL; port->active2.transmit->HostVaddr = NULL; } } /* in all cases the following is allowed */ port->active2.transmit->sendcrc = 0; port->active2.transmit->crcindex = 0; #endif if(skb == NULL) { if(port->DoingInterrupt) { skb = alloc_skb(count, GFP_ATOMIC); } else { skb = alloc_skb(count, GFP_KERNEL); } } if(skb == NULL) { printk(KERN_ALERT "sab8253xs: no skbuffs available.\n"); return 0; } if(from_user) { copy_from_user(skb->data, buf, count); } else { memcpy(skb->data, buf, count); } skb->tail = (skb->data + count); skb->data_len = count; skb->len = count; if(do_queue) { skb_queue_head(port->sab8253xbuflist, skb); } port->active2.transmit->HostVaddr = skb; port->active2.transmit->sendcrc = 0; port->active2.transmit->crcindex = 0; port->active2.transmit->Count = (OWN_SAB|count); port->active2.transmit = port->active2.transmit->VNext; sab8253x_start_txS(port); return count; }
static void sab8253x_check_statusS(struct sab_port *port, union sab8253x_irq_status *stat) { struct tty_struct *tty = port->tty; int modem_change = 0; mctlsig_t *sig; if (!tty) { return; } /* check_modem:*/ /* 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) { wake_up_interruptible(&port->open_wait); } else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) && (port->flags & FLAG8253X_CALLOUT_NOHUP))) { #if 0 /* requires more investigation */ MOD_INC_USE_COUNT; if (schedule_task(&port->tqueue_hangup) == 0) { MOD_DEC_USE_COUNT; } #endif } } 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, SAB8253X_EVENT_WRITE_WAKEUP); sab8253x_start_txS(port); } } else { if(!(getccr2configS(port) & SAB82532_CCR2_TOE)) { if (!(sig->val)) { port->tty->hw_stopped = 1; } } } } }
/* not do -- makes minimum 64 bytes add crc, etc*/ int sab8253xn_write2(struct sk_buff *skb, struct net_device *dev) { size_t cnt; unsigned int flags; SAB_PORT *priv = (SAB_PORT*) dev->priv; struct sk_buff *substitute; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) if(dev->tbusy != 0) /* something of an error */ { ++(priv->Counters.tx_drops); dev_kfree_skb_any(skb); return -EBUSY; /* only during release */ } #endif if(priv->active2.transmit == NULL) { return -ENOMEM; } DEBUGPRINT((KERN_ALERT "sab8253x: sending IP packet(bytes):\n")); DEBUGPRINT((KERN_ALERT "sab8253x: start address is %p.\n", skb->data)); cnt = skb->tail - skb->data; cnt = MIN(cnt, sab8253xn_rbufsize); if(cnt < ETH_ZLEN) { if((skb->end - skb->data) >= ETH_ZLEN) { skb->tail = (skb->data + ETH_ZLEN); cnt = ETH_ZLEN; } else { substitute = dev_alloc_skb(ETH_ZLEN); if(substitute == NULL) { dev_kfree_skb_any(skb); return 0; } substitute->tail = (substitute->data + ETH_ZLEN); memcpy(substitute->data, skb->data, cnt); cnt = ETH_ZLEN; dev_kfree_skb_any(skb); skb = substitute; } } save_flags(flags); cli(); if((priv->active2.transmit->Count & OWNER) == OWN_SAB) { ++(priv->Counters.tx_drops); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) dev->tbusy = 1; #else netif_stop_queue (dev); #endif priv->tx_full = 1; restore_flags(flags); return 1; } restore_flags(flags); #ifndef FREEINTERRUPT if(priv->active2.transmit->HostVaddr != NULL) { register RING_DESCRIPTOR *freeme; freeme = priv->active2.transmit; do { skb_unlink((struct sk_buff*)freeme->HostVaddr); dev_kfree_skb_any((struct sk_buff*)freeme->HostVaddr); freeme->HostVaddr = NULL; freeme = (RING_DESCRIPTOR*) freeme->VNext; } while(((freeme->Count & OWNER) != OWN_SAB) && (freeme->HostVaddr != NULL)); } #endif dev->trans_start = jiffies; skb_queue_head(priv->sab8253xbuflist, skb); priv->active2.transmit->HostVaddr = skb; priv->active2.transmit->sendcrc = 1; priv->active2.transmit->crcindex = 0; priv->active2.transmit->crc = fn_calc_memory_crc32(skb->data, cnt); priv->active2.transmit->Count = (OWN_SAB|cnt); /* must be this order */ priv->active2.transmit = (RING_DESCRIPTOR*) priv->active2.transmit->VNext; priv->Counters.transmitbytes += cnt; sab8253x_start_txS(priv); return 0; }
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 }