📄 io_edgeport.c
字号:
//static DIVISOR_TABLE_ENTRY DivisorTable[] = { { 75, 3072}, { 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */ { 134, 1713}, /* 1713.011152 => 230398.5 => .00065% under */ { 150, 1536}, { 300, 768}, { 600, 384}, { 1200, 192}, { 1800, 128}, { 2400, 96}, { 4800, 48}, { 7200, 32}, { 9600, 24}, { 14400, 16}, { 19200, 12}, { 38400, 6}, { 57600, 4}, { 115200, 2}, { 230400, 1},};/* local variables */static int CmdUrbs = 0; /* Number of outstanding Command Write Urbs *//* local function prototypes *//* function prototypes for all URB callbacks */static void edge_interrupt_callback (struct urb *urb);static void edge_bulk_in_callback (struct urb *urb);static void edge_bulk_out_data_callback (struct urb *urb);static void edge_bulk_out_cmd_callback (struct urb *urb);/* function prototypes for the usbserial callbacks */static int edge_open (struct usb_serial_port *port, struct file *filp);static void edge_close (struct usb_serial_port *port, struct file *filp);static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);static int edge_write_room (struct usb_serial_port *port);static int edge_chars_in_buffer (struct usb_serial_port *port);static void edge_throttle (struct usb_serial_port *port);static void edge_unthrottle (struct usb_serial_port *port);static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);static void edge_break (struct usb_serial_port *port, int break_state);static int edge_startup (struct usb_serial *serial);static void edge_shutdown (struct usb_serial *serial);#include "io_tables.h" /* all of the devices that this driver supports *//* function prototypes for all of our local functions */static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength);static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3);static void handle_new_msr (struct edgeport_port *edge_port, __u8 newMsr);static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data);static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param);static int calc_baud_rate_divisor (int baud_rate, int *divisor);static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate);static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios);static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);static void get_manufacturing_desc (struct edgeport_serial *edge_serial);static void get_boot_desc (struct edgeport_serial *edge_serial);static void load_application_firmware (struct edgeport_serial *edge_serial);static void unicode_to_ascii (char *string, short *unicode, int unicode_size);// ************************************************************************// ************************************************************************// ************************************************************************// ************************************************************************/************************************************************************ * * * update_edgeport_E2PROM() Compare current versions of * * Boot ROM and Manufacture * * Descriptors with versions * * embedded in this driver * * * ************************************************************************/static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial){ __u32 BootCurVer; __u32 BootNewVer; __u8 BootMajorVersion; __u8 BootMinorVersion; __u16 BootBuildNumber; __u8 *BootImage; __u32 BootSize; PEDGE_FIRMWARE_IMAGE_RECORD record; unsigned char *firmware; int response; switch (edge_serial->product_info.iDownloadFile) { case EDGE_DOWNLOAD_FILE_I930: BootMajorVersion = BootCodeImageVersion_GEN1.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN1.MinorVersion; BootBuildNumber = BootCodeImageVersion_GEN1.BuildNumber; BootImage = &BootCodeImage_GEN1[0]; BootSize = sizeof( BootCodeImage_GEN1 ); break; case EDGE_DOWNLOAD_FILE_80251: BootMajorVersion = BootCodeImageVersion_GEN2.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN2.MinorVersion; BootBuildNumber = BootCodeImageVersion_GEN2.BuildNumber; BootImage = &BootCodeImage_GEN2[0]; BootSize = sizeof( BootCodeImage_GEN2 ); break; default: return; } // Check Boot Image Version BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) + (edge_serial->boot_descriptor.MinorVersion << 16) + edge_serial->boot_descriptor.BuildNumber; BootNewVer = (BootMajorVersion << 24) + (BootMinorVersion << 16) + BootBuildNumber; dbg("Current Boot Image version %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, edge_serial->boot_descriptor.BuildNumber); if (BootNewVer > BootCurVer) { dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, edge_serial->boot_descriptor.BuildNumber, BootMajorVersion, BootMinorVersion, BootBuildNumber); dbg("Downloading new Boot Image"); firmware = BootImage; for (;;) { record = (PEDGE_FIRMWARE_IMAGE_RECORD)firmware; response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]); if (response < 0) { err("sram_write failed (%x, %x, %d)", record->ExtAddr, record->Addr, record->Len); break; } firmware += sizeof (EDGE_FIRMWARE_IMAGE_RECORD) + record->Len; if (firmware >= &BootImage[BootSize]) { break; } } } else { dbg("Boot Image -- already up to date"); }}/************************************************************************ * * * Get string descriptor from device * * * ************************************************************************/static int get_string (struct usb_device *dev, int Id, char *string){ struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; dbg(__FUNCTION__ " - USB String ID = %d", Id ); if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) { return 0; } pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL); if (!pStringDesc) { return 0; } if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) { kfree(pStringDesc); return 0; } unicode_to_ascii(string, pStringDesc->wData, pStringDesc->bLength/2-1); kfree(pStringDesc); return strlen(string);}#if 0/************************************************************************ * * Get string descriptor from device * ************************************************************************/static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc){ struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; dbg(__FUNCTION__ " - USB String ID = %d", Id ); if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) { return 0; } pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL); if (!pStringDesc) { return -1; } if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) { kfree(pStringDesc); return -1; } *pRetDesc = pStringDesc; return 0;}#endifstatic void get_product_info(struct edgeport_serial *edge_serial){ struct edgeport_product_info *product_info = &edge_serial->product_info; memset (product_info, 0, sizeof(struct edgeport_product_info)); product_info->ProductId = (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_GENERATION_2); product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts; product_info->ProdInfoVer = 0; product_info->RomSize = edge_serial->manuf_descriptor.RomSize; product_info->RamSize = edge_serial->manuf_descriptor.RamSize; product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev; product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev; product_info->BootMajorVersion = edge_serial->boot_descriptor.MajorVersion; product_info->BootMinorVersion = edge_serial->boot_descriptor.MinorVersion; product_info->BootBuildNumber = edge_serial->boot_descriptor.BuildNumber; memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate)); // check if this is 2nd generation hardware if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN2.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN2.MinorVersion; product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN2.BuildNumber; product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; } else { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN1.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN1.MinorVersion; product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN1.BuildNumber; product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; } // Determine Product type and set appropriate flags switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) { case ION_DEVICE_ID_EDGEPORT_COMPATIBLE: case ION_DEVICE_ID_EDGEPORT_4T: case ION_DEVICE_ID_EDGEPORT_4: case ION_DEVICE_ID_EDGEPORT_2: case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU: case ION_DEVICE_ID_EDGEPORT_8: case ION_DEVICE_ID_EDGEPORT_421: case ION_DEVICE_ID_EDGEPORT_21: case ION_DEVICE_ID_EDGEPORT_2_DIN: case ION_DEVICE_ID_EDGEPORT_4_DIN: case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU: product_info->IsRS232 = 1; break; case ION_DEVICE_ID_EDGEPORT_2I: // Edgeport/2 RS422/RS485 product_info->IsRS422 = 1; product_info->IsRS485 = 1; break; case ION_DEVICE_ID_EDGEPORT_8I: // Edgeport/4 RS422 case ION_DEVICE_ID_EDGEPORT_4I: // Edgeport/4 RS422 product_info->IsRS422 = 1; break; } // Dump Product Info structure dbg("**Product Information:"); dbg(" ProductId %x", product_info->ProductId ); dbg(" NumPorts %d", product_info->NumPorts ); dbg(" ProdInfoVer %d", product_info->ProdInfoVer ); dbg(" IsServer %d", product_info->IsServer); dbg(" IsRS232 %d", product_info->IsRS232 ); dbg(" IsRS422 %d", product_info->IsRS422 ); dbg(" IsRS485 %d", product_info->IsRS485 ); dbg(" RomSize %d", product_info->RomSize ); dbg(" RamSize %d", product_info->RamSize ); dbg(" CpuRev %x", product_info->CpuRev ); dbg(" BoardRev %x", product_info->BoardRev); dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, product_info->BootMinorVersion, product_info->BootBuildNumber); dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion, product_info->FirmwareMinorVersion, product_info->FirmwareBuildNumber); dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], product_info->ManufactureDescDate[1], product_info->ManufactureDescDate[2]+1900); dbg(" iDownloadFile 0x%x", product_info->iDownloadFile);}/************************************************************************//************************************************************************//* U S B C A L L B A C K F U N C T I O N S *//* U S B C A L L B A C K F U N C T I O N S *//************************************************************************//************************************************************************//***************************************************************************** * edge_interrupt_callback * this is the callback function for when we have received data on the * interrupt endpoint. *****************************************************************************/static void edge_interrupt_callback (struct urb *urb){ struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; struct edgeport_port *edge_port; struct usb_serial_port *port; unsigned char *data = urb->transfer_buffer; int length = urb->actual_length; int bytes_avail; int position; int txCredits; int portNumber; int result; dbg(__FUNCTION__); if (serial_paranoia_check (edge_serial->serial, __FUNCTION__)) { return; } if (urb->status) { dbg(__FUNCTION__" - nonzero control read status received: %d", urb->status); return; } // process this interrupt-read even if there are no ports open if (length) { usb_serial_debug_data (__FILE__, __FUNCTION__, length, data); if (length > 1) { bytes_avail = data[0] | (data[1] << 8); if (bytes_avail) { edge_serial->rxBytesAvail += bytes_avail; dbg(__FUNCTION__" - bytes_avail = %d, rxBytesAvail %d", bytes_avail, edge_serial->rxBytesAvail); if ((edge_serial->rxBytesAvail > 0) && (edge_serial->read_urb->status != -EINPROGRESS)) { dbg(" --- Posting a read"); /* we have pending bytes on the bulk in pipe, send a request */ edge_serial->read_urb->dev = edge_serial->serial->dev; result = usb_submit_urb(edge_serial->read_urb); if (result) { dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result); } } } } /* grab the txcredits for the ports if available */ position = 2; portNumber = 0; while ((position < length) && (portNumber < edge_serial->serial->num_ports)) { txCredits = data[position] | (data[position+1] << 8); if (txCredits) { port = &edge_serial->serial->port[portNumber]; if (port_paranoia_check (port, __FUNCTION__) == 0) { edge_port = (struct edgeport_port *)port->private; if (edge_port->open) { edge_port->txCredits += txCredits; dbg(__FUNCTION__" - txcredits for port%d = %d", portNumber, edge_port->txCredits); /* tell the tty driver that something has changed */ wake_up_interruptible(&edge_port->port->tty->write_wait); // Since we have more credit, check if more data can be sent send_more_port_data(edge_serial, edge_port); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -