📄 io_ti.c
字号:
} status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); if (status) { kfree (ti_manuf_desc); goto StayInBootMode; } // Check for version 2 if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) { dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__, TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev)); kfree (ti_manuf_desc); goto StayInBootMode; } kfree (ti_manuf_desc); // In order to update the I2C firmware we must change the type 2 record to type 0xF2. // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver // will download the latest firmware (padded to 15.5k) into the UMP ram. // And finally when the device comes back up in download mode the driver will cause // the new firmware to be copied from the UMP Ram to I2C and the firmware will update // the record type from 0xf2 to 0x02. /* * Do we really have to copy the whole firmware image, * or could we do this in place! */ // Allocate a 15.5k buffer + 3 byte header buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header)); buffer = kmalloc (buffer_size, GFP_KERNEL); if (!buffer) { dev_err (dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } // Initialize the buffer to 0xff (pad the buffer) memset (buffer, 0xff, buffer_size); memcpy (buffer, &PagableOperationalCodeImage[0], PagableOperationalCodeSize); for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) { cs = (__u8)(cs + buffer[i]); } header = (struct ti_i2c_image_header *)buffer; // update length and checksum after padding header->Length = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_i2c_image_header))); header->CheckSum = cs; // Download the operational code dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__); status = TIDownloadCodeImage (serial, buffer, buffer_size); kfree (buffer); if (status) { dbg ("%s - Error downloading operational code image", __FUNCTION__); return status; } // Device will reboot serial->product_info.TiMode = TI_MODE_TRANSITIONING; dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__); /* return an error on purpose */ return -ENODEV; }StayInBootMode: // Eprom is invalid or blank stay in boot mode dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__); serial->product_info.TiMode = TI_MODE_BOOT; return 0;}static int TISetDtr (struct edgeport_port *port){ int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); port->shadow_mcr |= MCR_DTR; return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_DTR, (__u8)(UMPM_UART1_PORT + port_number), 1, /* set */ NULL, 0);}static int TIClearDtr (struct edgeport_port *port){ int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); port->shadow_mcr &= ~MCR_DTR; return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_DTR, (__u8)(UMPM_UART1_PORT + port_number), 0, /* clear */ NULL, 0);}static int TISetRts (struct edgeport_port *port){ int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); port->shadow_mcr |= MCR_RTS; return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_RTS, (__u8)(UMPM_UART1_PORT + port_number), 1, /* set */ NULL, 0);}static int TIClearRts (struct edgeport_port *port){ int port_number = port->port->number - port->port->serial->minor; dbg ("%s", __FUNCTION__); port->shadow_mcr &= ~MCR_RTS; return TIWriteCommandSync (port->port->serial->dev, UMPC_SET_CLR_RTS, (__u8)(UMPM_UART1_PORT + port_number), 0, /* clear */ NULL, 0);}static int TISetLoopBack (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), 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; struct tty_struct *tty; 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; tty = edge_port->port->tty; /* handle CTS flow control */ if (tty && C_CRTSCTS(tty)) { if (msr & EDGEPORT_MSR_CTS) { tty->hw_stopped = 0; tty_wakeup(tty); } else { tty->hw_stopped = 1; } } 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) edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1); /* 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 pt_regs *regs){ 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; int status; __u8 lsr; __u8 msr; dbg("%s", __FUNCTION__); 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 urb status received: %d\n", __FUNCTION__, urb->status); goto exit; } if (!length) { dbg ("%s - no data in urb", __FUNCTION__); goto exit; } usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __FUNCTION__, length, data); if (length != 2) { dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length); goto exit; } 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]; edge_port = usb_get_serial_port_data(port); 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: dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n", __FUNCTION__, data[1]); break; }exit: status = usb_submit_urb (urb, GFP_ATOMIC); if (status) dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", __FUNCTION__, status);}static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs){ struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; unsigned char *data = urb->transfer_buffer; struct tty_struct *tty; int status = 0; int port_number; dbg("%s", __FUNCTION__); 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 read bulk status received: %d\n", __FUNCTION__, urb->status ); } if (urb->status == -EPIPE) goto exit; if (urb->status) { dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -