📄 io_ti.c
字号:
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; status = TIChooseConfiguration (serial->serial->dev); if (status) return status; interface = serial->serial->dev->config->interface->altsetting; if (!interface) { err ("%s - no interface set, error!", __FUNCTION__); return -ENODEV; } // Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING // if we have more than one endpoint we are definitely in download mode if (interface->bNumEndpoints > 1) serial->product_info.TiMode = TI_MODE_DOWNLOAD; else // Otherwise we will remain in configuring mode serial->product_info.TiMode = TI_MODE_CONFIGURING; // Save Download Version Number OperationalCodeImageVersion.MajorVersion = PagableOperationalCodeImageVersion.MajorVersion; OperationalCodeImageVersion.MinorVersion = PagableOperationalCodeImageVersion.MinorVersion; OperationalCodeImageVersion.BuildNumber = PagableOperationalCodeImageVersion.BuildNumber; /********************************************************************/ /* Download Mode */ /********************************************************************/ if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { struct ti_i2c_desc *rom_desc; dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__); status = TiValidateI2cImage (serial); if (status) { dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>", __FUNCTION__); return status; } /* Validate Hardware version number * Read Manufacturing Descriptor from TI Based Edgeport */ ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); if (!ti_manuf_desc) { err ("%s - out of memory.", __FUNCTION__); return -ENOMEM; } status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); if (status) { kfree (ti_manuf_desc); return status; } // Check version number of ION descriptor 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); return -EINVAL; } rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); if (!rom_desc) { err ("%s - out of memory.", __FUNCTION__); kfree (ti_manuf_desc); return -ENOMEM; } // Search for type 2 record (firmware record) if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) { struct ti_i2c_firmware_rec *firmware_version; __u8 record; dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__); firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL); if (!firmware_version) { err ("%s - out of memory.", __FUNCTION__); kfree (rom_desc); kfree (ti_manuf_desc); return -ENOMEM; } // Validate version number // Read the descriptor data status = TIReadRom (serial, start_address+sizeof(struct ti_i2c_desc), sizeof(struct ti_i2c_firmware_rec), (__u8 *)firmware_version); if (status) { kfree (firmware_version); kfree (rom_desc); kfree (ti_manuf_desc); return status; } // Check version number of download with current version in I2c download_cur_ver = (firmware_version->Ver_Major << 8) + (firmware_version->Ver_Minor); download_new_ver = (OperationalCodeImageVersion.MajorVersion << 8) + (OperationalCodeImageVersion.MinorVersion); dbg ("%s - >>>Firmware Versions Device %d.%d Driver %d.%d", __FUNCTION__, firmware_version->Ver_Major, firmware_version->Ver_Minor, OperationalCodeImageVersion.MajorVersion, OperationalCodeImageVersion.MinorVersion); // Check if we have an old version in the I2C and update if necessary if (download_cur_ver != download_new_ver) { dbg ("%s - Update I2C Download from %d.%d to %d.%d", __FUNCTION__, firmware_version->Ver_Major, firmware_version->Ver_Minor, OperationalCodeImageVersion.MajorVersion, OperationalCodeImageVersion.MinorVersion); // 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. record = I2C_DESC_TYPE_FIRMWARE_BLANK; // Change the I2C Firmware record type to 0xf2 to trigger an update status = TIWriteRom (serial, start_address, sizeof(record), &record); if (status) { kfree (firmware_version); kfree (rom_desc); kfree (ti_manuf_desc); return status; } // verify the write -- must do this in order for write to // complete before we do the hardware reset status = TIReadRom (serial, start_address, sizeof(record), &record); if (status) { kfree (firmware_version); kfree (rom_desc); kfree (ti_manuf_desc); return status; } if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) { err ("%s - error resetting device", __FUNCTION__); kfree (firmware_version); kfree (rom_desc); kfree (ti_manuf_desc); return -ENODEV; } dbg ("%s - HARDWARE RESET", __FUNCTION__); // Reset UMP -- Back to BOOT MODE status = TISendVendorRequestSync (serial->serial->dev, UMPC_HARDWARE_RESET, // Request 0, // wValue 0, // wIndex NULL, // TransferBuffer 0); // TransferBufferLength dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status); /* return an error on purpose. */ return -ENODEV; } } // Search for type 0xF2 record (firmware blank record) else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { #define HEADER_SIZE (sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec)) __u8 *header; __u8 *vheader; header = kmalloc (HEADER_SIZE, GFP_KERNEL); if (!header) { err ("%s - out of memory.", __FUNCTION__); kfree (rom_desc); kfree (ti_manuf_desc); return -ENOMEM; } vheader = kmalloc (HEADER_SIZE, GFP_KERNEL); if (!vheader) { err ("%s - out of memory.", __FUNCTION__); kfree (header); kfree (rom_desc); kfree (ti_manuf_desc); return -ENOMEM; } dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__); // 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. status = BuildI2CFirmwareHeader(header); if (status) { kfree (vheader); kfree (header); kfree (rom_desc); kfree (ti_manuf_desc); return status; } // Update I2C with type 0xf2 record with correct size and checksum status = TIWriteRom (serial, start_address, HEADER_SIZE, header); if (status) { kfree (vheader); kfree (header); kfree (rom_desc); kfree (ti_manuf_desc); return status; } // verify the write -- must do this in order for write to // complete before we do the hardware reset status = TIReadRom (serial, start_address, HEADER_SIZE, vheader); if (status) { dbg ("%s - can't read header back", __FUNCTION__); kfree (vheader); kfree (header); kfree (rom_desc); kfree (ti_manuf_desc); return status; } if (memcmp(vheader, header, HEADER_SIZE)) { dbg ("%s - write download record failed", __FUNCTION__); kfree (vheader); kfree (header); kfree (rom_desc); kfree (ti_manuf_desc); return status; } kfree (vheader); kfree (header); dbg ("%s - Start firmware update", __FUNCTION__); // Tell firmware to copy download image into I2C status = TISendVendorRequestSync (serial->serial->dev, UMPC_COPY_DNLD_TO_I2C, // Request 0, // wValue 0, // wIndex NULL, // TransferBuffer 0); // TransferBufferLength dbg ("%s - Update complete 0x%x", __FUNCTION__, status); if (status) { dbg ("%s - UMPC_COPY_DNLD_TO_I2C failed", __FUNCTION__); kfree (rom_desc); kfree (ti_manuf_desc); return status; } } // The device is running the download code kfree (rom_desc); kfree (ti_manuf_desc); return 0; } /********************************************************************/ /* Boot Mode */ /********************************************************************/ dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>", __FUNCTION__); // Configure the TI device so we can use the BULK pipes for download status = TIConfigureBootDevice (serial->serial->dev); if (status) return status; if (serial->serial->dev->descriptor.idVendor != USB_VENDOR_ID_ION) { dbg ("%s - VID = 0x%x", __FUNCTION__, serial->serial->dev->descriptor.idVendor); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; goto StayInBootMode; } // We have an ION device (I2c Must be programmed) // Determine I2C image type if (TIGetI2cTypeInBootMode(serial)) { goto StayInBootMode; } // Registry variable set? if (TIStayInBootMode) { dbg ("%s - TIStayInBootMode", __FUNCTION__); goto StayInBootMode; } // Check for ION Vendor ID and that the I2C is valid if (!TiValidateI2cImage(serial)) { struct ti_i2c_image_header *header; int i; __u8 cs = 0; __u8 *buffer; int buffer_size; /* Validate Hardware version number * Read Manufacturing Descriptor from TI Based Edgeport */ ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); if (!ti_manuf_desc) { err ("%s - out of memory.", __FUNCTION__); return -ENOMEM; } 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) { err ("%s - out of memory", __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 = (__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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -