📄 io_ti.c
字号:
int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_LOOPBACK, (__u8)(UMPM_UART1_PORT + port_number), 1, /* set */ NULL, 0);}static int TIClearLoopBack (struct edgeport_port *port){ int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_LOOPBACK, (__u8)(UMPM_UART1_PORT + port_number), 0, /* clear */ NULL, 0);}static int TISetBreak (struct edgeport_port *port){ int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_BREAK, (__u8)(UMPM_UART1_PORT + port_number), 1, /* set */ NULL, 0);}static int TIClearBreak (struct edgeport_port *port){ int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_BREAK, (__u8)(UMPM_UART1_PORT + port_number), 0, /* clear */ NULL, 0);}static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr){ int status = 0; dbg ("%s - %x", __FUNCTION__, mcr); if (mcr & MCR_DTR) status = TISetDtr (port); else status = TIClearDtr (port); if (status) return status; if (mcr & MCR_RTS) status = TISetRts (port); else status = TIClearRts (port); if (status) return status; if (mcr & MCR_LOOPBACK) status = TISetLoopBack (port); else status = TIClearLoopBack (port); return status;}/* Convert TI LSR to standard UART flags */static __u8 MapLineStatus (__u8 ti_lsr){ __u8 lsr = 0;#define MAP_FLAG(flagUmp, flagUart) \ if (ti_lsr & flagUmp) lsr |= flagUart; MAP_FLAG(UMP_UART_LSR_OV_MASK, LSR_OVER_ERR) /* overrun */ MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR) /* parity error */ MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR) /* framing error */ MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK) /* break detected */ MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* receive data available */ MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* transmit holding register empty */#undef MAP_FLAG return lsr;}static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr){ struct async_icount *icount; dbg ("%s - %02x", __FUNCTION__, msr); if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { icount = &edge_port->icount; /* update input line counters */ if (msr & EDGEPORT_MSR_DELTA_CTS) icount->cts++; if (msr & EDGEPORT_MSR_DELTA_DSR) icount->dsr++; if (msr & EDGEPORT_MSR_DELTA_CD) icount->dcd++; if (msr & EDGEPORT_MSR_DELTA_RI) icount->rng++; wake_up_interruptible (&edge_port->delta_msr_wait); } /* Save the new modem status */ edge_port->shadow_msr = msr & 0xf0; return;}static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data){ struct async_icount *icount; __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); dbg ("%s - %02x", __FUNCTION__, new_lsr); edge_port->shadow_lsr = lsr; if (new_lsr & LSR_BREAK) { /* * Parity and Framing errors only count if they * occur exclusive of a break being received. */ new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); } /* Place LSR data byte into Rx buffer */ if (lsr_data && edge_port->port->tty) { tty_insert_flip_char(edge_port->port->tty, data, 0); tty_flip_buffer_push(edge_port->port->tty); } /* update input line counters */ icount = &edge_port->icount; if (new_lsr & LSR_BREAK) icount->brk++; if (new_lsr & LSR_OVER_ERR) icount->overrun++; if (new_lsr & LSR_PAR_ERR) icount->parity++; if (new_lsr & LSR_FRM_ERR) icount->frame++;}static void edge_interrupt_callback (struct urb *urb){ struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; struct usb_serial_port *port; struct edgeport_port *edge_port; unsigned char *data = urb->transfer_buffer; int length = urb->actual_length; int port_number; int function; __u8 lsr; __u8 msr; dbg("%s", __FUNCTION__); if (serial_paranoia_check (edge_serial->serial, __FUNCTION__)) { return; } if (urb->status) { dbg("%s - nonzero control read status received: %d", __FUNCTION__, urb->status); return; } if (!length) { dbg ("%s - no data in urb", __FUNCTION__); return; } usb_serial_debug_data (__FILE__, __FUNCTION__, length, data); if (length != 2) { dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length); return; } port_number = TIUMP_GET_PORT_FROM_CODE (data[0]); function = TIUMP_GET_FUNC_FROM_CODE (data[0]); dbg ("%s - port_number %d, function %d, info 0x%x", __FUNCTION__, port_number, function, data[1]); port = &edge_serial->serial->port[port_number]; if (port_paranoia_check (port, __FUNCTION__)) { dbg ("%s - change found for port that is not present", __FUNCTION__); return; } edge_port = port->private; if (!edge_port) { dbg ("%s - edge_port not found", __FUNCTION__); return; } switch (function) { case TIUMP_INTERRUPT_CODE_LSR: lsr = MapLineStatus(data[1]); if (lsr & UMP_UART_LSR_DATA_MASK) { /* Save the LSR event for bulk read completion routine */ dbg ("%s - LSR Event Port %u LSR Status = %02x", __FUNCTION__, port_number, lsr); edge_port->lsr_event = 1; edge_port->lsr_mask = lsr; } else { dbg ("%s - ===== Port %d LSR Status = %02x ======", __FUNCTION__, port_number, lsr); handle_new_lsr (edge_port, 0, lsr, 0); } break; case TIUMP_INTERRUPT_CODE_MSR: // MSR /* Copy MSR from UMP */ msr = data[1]; dbg ("%s - ===== Port %u MSR Status = %02x ======\n", __FUNCTION__, port_number, msr); handle_new_msr (edge_port, msr); break; default: err ("%s - Unknown Interrupt code from UMP %x\n", __FUNCTION__, data[1]); break; }}static void edge_bulk_in_callback (struct urb *urb){ struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; unsigned char *data = urb->transfer_buffer; struct tty_struct *tty; int status; int i; int port_number; dbg("%s", __FUNCTION__); if (port_paranoia_check (edge_port->port, __FUNCTION__)) return; if (urb->status) { dbg ("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); if (urb->status == -EPIPE) { /* clear any problem that might have happened on this pipe */ usb_clear_halt (edge_port->port->serial->dev, urb->pipe); goto exit; } return; } port_number = edge_port->port->number - edge_port->port->serial->minor; if (edge_port->lsr_event) { edge_port->lsr_event = 0; dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======", __FUNCTION__, port_number, edge_port->lsr_mask, *data); handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data); /* Adjust buffer length/pointer */ --urb->actual_length; ++data; } tty = edge_port->port->tty; if (tty && urb->actual_length) { usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); if (edge_port->close_pending) { dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__); } else { for (i = 0; i < urb->actual_length ; ++i) { /* if we insert more than TTY_FLIPBUF_SIZE characters, * we drop them. */ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); } /* this doesn't actually push the data through unless * tty->low_latency is set */ tty_insert_flip_char(tty, data[i], 0); } tty_flip_buffer_push(tty); } edge_port->icount.rx += urb->actual_length; }exit: /* continue always trying to read */ urb->dev = edge_port->port->serial->dev; status = usb_submit_urb (urb); if (status) err ("%s - usb_submit_urb failed with result %d", __FUNCTION__, status);}static void edge_bulk_out_callback (struct urb *urb){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); struct tty_struct *tty; dbg ("%s - port %d", __FUNCTION__, port->number); if (!serial) { dbg ("%s - bad serial pointer, exiting", __FUNCTION__); return; } if (urb->status) { dbg ("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); if (urb->status == -EPIPE) { /* clear any problem that might have happened on this pipe */ usb_clear_halt (serial->dev, urb->pipe); } return; } tty = port->tty; if (tty) { /* let the tty driver wakeup if it has a special write_wakeup function */ tty_wakeup(tty); }}static int edge_open (struct usb_serial_port *port, struct file * filp){ struct edgeport_port *edge_port = (struct edgeport_port *)port->private; struct edgeport_serial *edge_serial; struct usb_device *dev; struct urb *urb; int port_number; int status; u16 open_settings; u8 transaction_timeout; if (port_paranoia_check (port, __FUNCTION__)) return -ENODEV; dbg("%s - port %d", __FUNCTION__, port->number); if (edge_port == NULL) return -ENODEV; /* force low_latency on so that our tty_push actually forces the data through, otherwise it is scheduled, and with high data rates (like with OHCI) data can get lost. */ if (port->tty) port->tty->low_latency = 1; 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: err ("Unknown port number!!!"); 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) 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) return status; /* Start the DMA? */ status = TIWriteCommandSync (dev, UMPC_START_PORT, (u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); if (status) return status; /* Clear TX and RX buffers in UMP */ status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN); if (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) return status; dbg ("ShadowMSR 0x%X", edge_port->shadow_msr); edge_serial = edge_port->edge_serial; if (edge_serial->num_ports_open == 0) { dbg ("%s - setting up bulk in urb", __FUNCTION__); /* 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) { err ("%s - no interrupt urb present, exiting", __FUNCTION__); return -EINVAL; } urb->complete = edge_interrupt_callback; urb->context = edge_serial; urb->dev = dev; status = usb_submit_urb (urb); if (status) { err ("%s - usb_submit_urb failed with value %d", __FUNCTION__, status); return status; } } /* * 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -