static int serial_write_room (struct tty_struct *tty) { /* Return the amount of room for writing. */ unsigned long flags; struct serproto_dev *device; int n = 0; dbg_tx (7, "entered"); if ((device = tty->driver_data) == NULL) { dbg_tx (1, "not presently connected -> FAIL"); return (-EINVAL); } read_lock_irqsave (&device->rwlock, flags); if (device->connected && (device->queued_bytes < device->max_queue_bytes) && (device->max_queue_entries == 0 || device->queued_entries < device->max_queue_entries)) { #if 0 if (device->tx_size < (n = device->max_queue_bytes - device->queued_bytes)) { n = device->tx_size; } #else n = device->max_queue_bytes - device->queued_bytes; #endif } read_unlock_irqrestore (&device->rwlock, flags); // Shouldn't really access these outside the lock, but only the dbg msg can go wrong. dbg_tx (6, "c:%c b=%u/%u e=%u/%u -> %d", (device->connected ? 'T' : 'F'), device->queued_bytes, device->max_queue_bytes, device->queued_entries, device->max_queue_entries, n); return (n); }
static inline int sio_xmit(int ch) { unsigned long flags; dbg_tx("%s: ch %02x (STA %02x)\n", __FUNCTION__, ch, rd_reg(OKI_SIOSTA)); local_irq_save(flags); /* decided wether we can write this directly to the uart * or wether we are going to have to buffer it */ printk(KERN_DEBUG "%s: ready %d, locked %d, xchar %02x\n", __FUNCTION__, sio_xmit_ready(), sio_xmit_locked(), x_char); if (sio_xmit_ready() && !sio_xmit_locked() && x_char == 0) { sio_xmit_do(ch); goto exit; } if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf)) { local_irq_restore(flags); return 0; } *putp = ch; if (++putp >= wbuf + sizeof(wbuf)) putp = wbuf; exit: local_irq_restore(flags); return 1; }
/** * bi_send_urb - start transmit * @urb: */ int bi_send_urb(struct usbd_urb *urb) { unsigned long flags; dbg_tx(4, "urb: %p", urb); local_irq_save(flags); if (urb && urb->endpoint && !urb->endpoint->tx_urb) { dbg_tx(2, "urb: %p endpoint: %x", urb, urb->endpoint->endpoint_address); usbd_tx_complete_irq(urb->endpoint, 0); udc_start_in_irq(urb->endpoint, urb->device); } local_irq_restore(flags); // Shouldn't need to make this atomic, all we need is a change indicator urb->device->usbd_rxtx_timestamp = jiffies; return 0; }
/** * usbd_cancel_urb - cancel an urb being sent * @urb: pointer to an urb structure * * Used by a USB Function driver to cancel an urb that is being * sent. */ int usbd_cancel_urb (struct usb_device_instance *device, struct urb *urb) { dbg_tx (3, "%p", urb); if (!device->bus->driver->ops->cancel_urb) { // XXX should we do usbd_dealloc_urb(urb); return 0; } //urb->device->urbs_queued++; return device->bus->driver->ops->cancel_urb (urb); }
static void sio_xmit_check(void) { unsigned int status; /* must be called with irqs disabled */ status = rd_reg(OKI_SIOSTA); dbg_tx("%s: status=%02x\n", __FUNCTION__, status); if (status & OKI_SIOSTA_TRIRQ) { sio_tx_inprogress = 0; wr_reg(OKI_SIOSTA, OKI_SIOSTA_TRIRQ); } else if (time_after(jiffies, sio_tx_last + HZ/10)) { printk(KERN_ERR "sio: tx timeout\n"); sio_tx_inprogress = 0; } }
static int serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count) { // Return the number of bytes (out of count) that get written, // or negative for error. unsigned long flags; struct serproto_dev *device; int cnt = count; int size; const unsigned char *currpos = buf; unsigned char *buffer; dbg_tx (3, "count=%d", count); if ((device = tty->driver_data) == NULL) { dbg_tx (1, "not presently connected -> FAIL"); return -EINVAL; } dbgPRINTmem (dbgflg_tx, 4, buf, count); // loop on data while (cnt > 0) { int length; // send at most tx_size bytes size = MIN (device->tx_size, cnt); write_lock_irqsave (&device->rwlock, flags); // Make sure we can send. if (!device->connected || (device->max_queue_entries > 0 && (device->queued_entries >= device->max_queue_entries)) || (device->queued_bytes >= device->max_queue_bytes)) { // Can't write any more, // return the number that we did manage to send. write_unlock_irqrestore (&device->rwlock, flags); dbg_tx (2, "->%d/%d", (count - cnt), count); return (count - cnt); } size = MIN ((device->max_queue_bytes - device->queued_bytes), size); // allocate a buffer length = (device->blocked ? device->tx_size : size) + 1 + device->trailer; dbg_tx (1, "------> blocked: %d tx_size: %d size: %d trailer: %d, length: %d", device->blocked, device->tx_size, size, device->trailer, length); if ((buffer = kmalloc (length, GFP_KERNEL)) == NULL) { write_unlock_irqrestore (&device->rwlock, flags); dbg_tx (2, "->ENOMEM"); return -ENOMEM; } memset (buffer, '\0', length); // copy data if (from_user) { copy_from_user ((void *) buffer, currpos, size); } else { memcpy ((void *) buffer, currpos, size); } currpos += size; cnt -= size; device->xmit_data (device->number, buffer, size); device->queued_entries++; device->queued_bytes += size; write_unlock_irqrestore (&device->rwlock, flags); } // Everything went out. dbg_tx (5, "->%d (all)", count); return count; }