📄 io_ti.c
字号:
if (tty && urb->actual_length) { usb_serial_debug_data(debug, &edge_port->port->dev, __FUNCTION__, urb->actual_length, data); if (edge_port->close_pending) { dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__); } else { edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length); } edge_port->icount.rx += urb->actual_length; }exit: /* continue read unless stopped */ spin_lock(&edge_port->ep_lock); if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) { urb->dev = edge_port->port->serial->dev; status = usb_submit_urb(urb, GFP_ATOMIC); } else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) { edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED; } spin_unlock(&edge_port->ep_lock); if (status) dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", __FUNCTION__, status);}static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length){ int cnt; do { if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length); return; } } cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count); memcpy(tty->flip.char_buf_ptr, data, cnt); memset(tty->flip.flag_buf_ptr, 0, cnt); tty->flip.char_buf_ptr += cnt; tty->flip.flag_buf_ptr += cnt; tty->flip.count += cnt; data += cnt; length -= cnt; } while (length > 0); tty_flip_buffer_push(tty);}static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct edgeport_port *edge_port = usb_get_serial_port_data(port); dbg ("%s - port %d", __FUNCTION__, port->number); edge_port->ep_write_urb_in_use = 0; switch (urb->status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n", __FUNCTION__, urb->status); } /* send any buffered data */ edge_send(port);}static int edge_open (struct usb_serial_port *port, struct file * filp){ struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct edgeport_serial *edge_serial; struct usb_device *dev; struct urb *urb; int port_number; int status; u16 open_settings; u8 transaction_timeout; dbg("%s - port %d", __FUNCTION__, port->number); if (edge_port == NULL) return -ENODEV; if (port->tty) port->tty->low_latency = low_latency; port_number = port->number - port->serial->minor; switch (port_number) { case 0: edge_port->uart_base = UMPMEM_BASE_UART1; edge_port->dma_address = UMPD_OEDB1_ADDRESS; break; case 1: edge_port->uart_base = UMPMEM_BASE_UART2; edge_port->dma_address = UMPD_OEDB2_ADDRESS; break; default: dev_err (&port->dev, "Unknown port number!!!\n"); return -ENODEV; } dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x", __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address); dev = port->serial->dev; memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount)); init_waitqueue_head (&edge_port->delta_msr_wait); /* turn off loopback */ status = TIClearLoopBack (edge_port); if (status) { dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n", __FUNCTION__, status); return status; } /* set up the port settings */ edge_set_termios (port, NULL); /* open up the port */ /* milliseconds to timeout for DMA transfer */ transaction_timeout = 2; edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) ); // milliseconds to timeout for DMA transfer open_settings = (u8)(UMP_DMA_MODE_CONTINOUS | UMP_PIPE_TRANS_TIMEOUT_ENA | (transaction_timeout << 2)); dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__); /* Tell TI to open and start the port */ status = TIWriteCommandSync (dev, UMPC_OPEN_PORT, (u8)(UMPM_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { dev_err(&port->dev,"%s - cannot send open command, %d\n", __FUNCTION__, status); return status; } /* Start the DMA? */ status = TIWriteCommandSync (dev, UMPC_START_PORT, (u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); if (status) { dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __FUNCTION__, status); return status; } /* Clear TX and RX buffers in UMP */ status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN); if (status) { dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __FUNCTION__, status); return status; } /* Read Initial MSR */ status = TIReadVendorRequestSync (dev, UMPC_READ_MSR, // Request 0, // wValue (__u16)(UMPM_UART1_PORT + port_number), // wIndex (Address) &edge_port->shadow_msr, // TransferBuffer 1); // TransferBufferLength if (status) { dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __FUNCTION__, status); return status; } dbg ("ShadowMSR 0x%X", edge_port->shadow_msr); /* Set Initial MCR */ edge_port->shadow_mcr = MCR_RTS | MCR_DTR; dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr); edge_serial = edge_port->edge_serial; if (down_interruptible(&edge_serial->es_sem)) return -ERESTARTSYS; if (edge_serial->num_ports_open == 0) { /* we are the first port to be opened, let's post the interrupt urb */ urb = edge_serial->serial->port[0]->interrupt_in_urb; if (!urb) { dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__); status = -EINVAL; goto up_es_sem; } urb->complete = edge_interrupt_callback; urb->context = edge_serial; urb->dev = dev; status = usb_submit_urb (urb, GFP_KERNEL); if (status) { dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status); goto up_es_sem; } } /* * reset the data toggle on the bulk endpoints to work around bug in * host controllers where things get out of sync some times */ usb_clear_halt (dev, port->write_urb->pipe); usb_clear_halt (dev, port->read_urb->pipe); /* start up our bulk read urb */ urb = port->read_urb; if (!urb) { dev_err (&port->dev, "%s - no read urb present, exiting\n", __FUNCTION__); status = -EINVAL; goto unlink_int_urb; } edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; urb->complete = edge_bulk_in_callback; urb->context = edge_port; urb->dev = dev; status = usb_submit_urb (urb, GFP_KERNEL); if (status) { dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status); goto unlink_int_urb; } ++edge_serial->num_ports_open; dbg("%s - exited", __FUNCTION__); goto up_es_sem;unlink_int_urb: if (edge_port->edge_serial->num_ports_open == 0) usb_kill_urb(port->serial->port[0]->interrupt_in_urb);up_es_sem: up(&edge_serial->es_sem); return status;}static void edge_close (struct usb_serial_port *port, struct file *filp){ struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; int port_number; int status; dbg("%s - port %d", __FUNCTION__, port->number); edge_serial = usb_get_serial_data(port->serial); edge_port = usb_get_serial_port_data(port); if ((edge_serial == NULL) || (edge_port == NULL)) return; /* The bulkreadcompletion routine will check * this flag and dump add read data */ edge_port->close_pending = 1; /* chase the port close and flush */ TIChasePort (edge_port, (HZ*closing_wait)/100, 1); usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); edge_port->ep_write_urb_in_use = 0; /* assuming we can still talk to the device, * send a close port command to it */ dbg("%s - send umpc_close_port", __FUNCTION__); port_number = port->number - port->serial->minor; status = TIWriteCommandSync (port->serial->dev, UMPC_CLOSE_PORT, (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); down(&edge_serial->es_sem); --edge_port->edge_serial->num_ports_open; if (edge_port->edge_serial->num_ports_open <= 0) { /* last port is now closed, let's shut down our interrupt urb */ usb_kill_urb(port->serial->port[0]->interrupt_in_urb); edge_port->edge_serial->num_ports_open = 0; } up(&edge_serial->es_sem); edge_port->close_pending = 0; dbg("%s - exited", __FUNCTION__);}static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count){ struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); if (count == 0) { dbg("%s - write request of 0 bytes", __FUNCTION__); return 0; } if (edge_port == NULL) return -ENODEV; if (edge_port->close_pending == 1) return -ENODEV; spin_lock_irqsave(&edge_port->ep_lock, flags); count = edge_buf_put(edge_port->ep_out_buf, data, count); spin_unlock_irqrestore(&edge_port->ep_lock, flags); edge_send(port); return count;}static void edge_send(struct usb_serial_port *port){ int count, result; struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&edge_port->ep_lock, flags); if (edge_port->ep_write_urb_in_use) { spin_unlock_irqrestore(&edge_port->ep_lock, flags); return; } count = edge_buf_get(edge_port->ep_out_buf, port->write_urb->transfer_buffer, port->bulk_out_size); if (count == 0) { spin_unlock_irqrestore(&edge_port->ep_lock, flags); return; } edge_port->ep_write_urb_in_use = 1; spin_unlock_irqrestore(&edge_port->ep_lock, flags); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); /* set up our urb */ usb_fill_bulk_urb (port->write_urb, port->serial->dev, usb_sndbulkpipe (port->serial->dev, port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, count, edge_bulk_out_callback, port); /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); edge_port->ep_write_urb_in_use = 0; // TODO: reschedule edge_send } else { edge_port->icount.tx += count; } /* wakeup any process waiting for writes to complete */ /* there is now more room in the buffer for new writes */ if (tty) { /* let the tty driver wakeup if it has a special write_wakeup function */ tty_wakeup(tty); }}static int edge_write_room (struct usb_serial_port *port){ struct edgeport_port *edge_port = usb_get_serial_port_data(port); int room = 0; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); if (edge_port == NULL) return -ENODEV; if (edge_port->close_pending == 1) return -ENODEV; spin_lock_irqsave(&edge_port->ep_lock, flags); room = edge_buf_space_avail(edge_port->ep_out_buf); spin_unlock_irqrestore(&edge_port->ep_lock, flags); dbg("%s - returns %d", __FUNCTION__, room); return room;}static int edge_chars_in_buffer (struct usb_serial_port *port){ struct edgeport_port *edge_port = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); if (edge_port == NULL) return -ENODEV; if (edge_port->close_pending == 1) return -ENODEV; spin_lock_irqsave(&edge_port->ep_lock, flags); chars = edge_buf_data_avail(edge_port->ep_out_buf); spin_unlock_irqrestore(&edge_port->ep_lock, flags); dbg ("%s - returns %d", __FUNCTION__, chars); return chars;}static void edge_throttle (struct usb_serial_port *port){ struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty; int status; dbg("%s - port %d", __FUNCTION__, port->number); if (edge_port == NULL) return; tty = port->tty; if (!tty) { dbg ("%s - no tty available", __FUNCTION__); return; } /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); status = edge_write (port, &stop_char, 1); if (status <= 0) { dev_err(&port->dev, "%s - failed to write stop character, %d\n", __FUNCTION__, status); } } /* if w
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -