📄 io_ti.c
字号:
return status; } dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length); usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, length, buffer); return status;}/* Write edgeport I2C memory to TI chip */static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer){ int status = 0; int write_length; __be16 be_start_address; /* We can only send a maximum of 1 aligned byte page at a time */ /* calulate the number of bytes left in the first page */ write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1)); if (write_length > length) write_length = length; dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length); usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer); /* Write first page */ be_start_address = cpu_to_be16 (start_address); status = TISendVendorRequestSync (serial->serial->dev, UMPC_MEMORY_WRITE, // Request (__u16)address_type, // wValue (__force __u16)be_start_address, // wIndex buffer, // TransferBuffer write_length); if (status) { dbg ("%s - ERROR %d", __FUNCTION__, status); return status; } length -= write_length; start_address += write_length; buffer += write_length; /* We should be aligned now -- can write max page size bytes at a time */ while (length) { if (length > EPROM_PAGE_SIZE) write_length = EPROM_PAGE_SIZE; else write_length = length; dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length); usb_serial_debug_data(debug, &serial->serial->dev->dev, __FUNCTION__, write_length, buffer); /* Write next page */ be_start_address = cpu_to_be16 (start_address); status = TISendVendorRequestSync (serial->serial->dev, UMPC_MEMORY_WRITE, // Request (__u16)address_type, // wValue (__force __u16)be_start_address, // wIndex buffer, // TransferBuffer write_length); // TransferBufferLength if (status) { dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __FUNCTION__, status); return status; } length -= write_length; start_address += write_length; buffer += write_length; } return status;}/* Examine the UMP DMA registers and LSR * * Check the MSBit of the X and Y DMA byte count registers. * A zero in this bit indicates that the TX DMA buffers are empty * then check the TX Empty bit in the UART. */static int TIIsTxActive (struct edgeport_port *port){ int status; struct out_endpoint_desc_block *oedb; __u8 *lsr; int bytes_left = 0; oedb = kmalloc (sizeof (* oedb), GFP_KERNEL); if (!oedb) { dev_err (&port->port->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } lsr = kmalloc (1, GFP_KERNEL); /* Sigh, that's right, just one byte, as not all platforms can do DMA from stack */ if (!lsr) { kfree(oedb); return -ENOMEM; } /* Read the DMA Count Registers */ status = TIReadRam (port->port->serial->dev, port->dma_address, sizeof( *oedb), (void *)oedb); if (status) goto exit_is_tx_active; dbg ("%s - XByteCount 0x%X", __FUNCTION__, oedb->XByteCount); /* and the LSR */ status = TIReadRam (port->port->serial->dev, port->uart_base + UMPMEM_OFFS_UART_LSR, 1, lsr); if (status) goto exit_is_tx_active; dbg ("%s - LSR = 0x%X", __FUNCTION__, *lsr); /* If either buffer has data or we are transmitting then return TRUE */ if ((oedb->XByteCount & 0x80 ) != 0 ) bytes_left += 64; if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 ) bytes_left += 1; /* We return Not Active if we get any kind of error */exit_is_tx_active: dbg ("%s - return %d", __FUNCTION__, bytes_left ); kfree(lsr); kfree(oedb); return bytes_left;}static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int flush){ int baud_rate; struct tty_struct *tty = port->port->tty; wait_queue_t wait; unsigned long flags; if (!timeout) timeout = (HZ*EDGE_CLOSING_WAIT)/100; /* wait for data to drain from the buffer */ spin_lock_irqsave(&port->ep_lock, flags); init_waitqueue_entry(&wait, current); add_wait_queue(&tty->write_wait, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (edge_buf_data_avail(port->ep_out_buf) == 0 || timeout == 0 || signal_pending(current) || !usb_get_intfdata(port->port->serial->interface)) /* disconnect */ break; spin_unlock_irqrestore(&port->ep_lock, flags); timeout = schedule_timeout(timeout); spin_lock_irqsave(&port->ep_lock, flags); } set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); if (flush) edge_buf_clear(port->ep_out_buf); spin_unlock_irqrestore(&port->ep_lock, flags); /* wait for data to drain from the device */ timeout += jiffies; while ((long)(jiffies - timeout) < 0 && !signal_pending(current) && usb_get_intfdata(port->port->serial->interface)) { /* not disconnected */ if (!TIIsTxActive(port)) break; msleep(10); } /* disconnected */ if (!usb_get_intfdata(port->port->serial->interface)) return; /* wait one more character time, based on baud rate */ /* (TIIsTxActive doesn't seem to wait for the last byte) */ if ((baud_rate=port->baud_rate) == 0) baud_rate = 50; msleep(max(1,(10000+baud_rate-1)/baud_rate));}static int TIChooseConfiguration (struct usb_device *dev){ // There may be multiple configurations on this device, in which case // we would need to read and parse all of them to find out which one // we want. However, we just support one config at this point, // configuration # 1, which is Config Descriptor 0. dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->desc.bNumInterfaces); dbg ("%s - MAX Power = %d", __FUNCTION__, dev->config->desc.bMaxPower*2); if (dev->config->desc.bNumInterfaces != 1) { dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __FUNCTION__); return -ENODEV; } return 0;}static int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer){ int status; if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { status = TIReadDownloadMemory (serial->serial->dev, start_address, length, serial->TI_I2C_Type, buffer); } else { status = TIReadBootMemory (serial, start_address, length, buffer); } return status;}static int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer){ if (serial->product_info.TiMode == TI_MODE_BOOT) return TIWriteBootMemory (serial, start_address, length, buffer); if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) return TIWriteDownloadI2C (serial, start_address, length, serial->TI_I2C_Type, buffer); return -EINVAL;}/* Read a descriptor header from I2C based on type */static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc){ int start_address; int status; /* Search for requested descriptor in I2C */ start_address = 2; do { status = TIReadRom (serial, start_address, sizeof(struct ti_i2c_desc), (__u8 *)rom_desc ); if (status) return 0; if (rom_desc->Type == desc_type) return start_address; start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); return 0;}/* Validate descriptor checksum */static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer){ __u16 i; __u8 cs = 0; for (i=0; i < rom_desc->Size; i++) { cs = (__u8)(cs + buffer[i]); } if (cs != rom_desc->CheckSum) { dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs); return -EINVAL; } return 0;}/* Make sure that the I2C image is good */static int TiValidateI2cImage (struct edgeport_serial *serial){ struct device *dev = &serial->serial->dev->dev; int status = 0; struct ti_i2c_desc *rom_desc; int start_address = 2; __u8 *buffer; __u16 ttype; rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); if (!rom_desc) { dev_err (dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL); if (!buffer) { dev_err (dev, "%s - out of memory when allocating buffer\n", __FUNCTION__); kfree (rom_desc); return -ENOMEM; } // Read the first byte (Signature0) must be 0x52 or 0x10 status = TIReadRom (serial, 0, 1, buffer); if (status) goto ExitTiValidateI2cImage; if (*buffer != UMP5152 && *buffer != UMP3410) { dev_err (dev, "%s - invalid buffer signature\n", __FUNCTION__); status = -ENODEV; goto ExitTiValidateI2cImage; } do { // Validate the I2C status = TIReadRom (serial, start_address, sizeof(struct ti_i2c_desc), (__u8 *)rom_desc); if (status) break; if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) { status = -ENODEV; dbg ("%s - structure too big, erroring out.", __FUNCTION__); break; } dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type); // Skip type 2 record ttype = rom_desc->Type & 0x0f; if ( ttype != I2C_DESC_TYPE_FIRMWARE_BASIC && ttype != I2C_DESC_TYPE_FIRMWARE_AUTO ) { // Read the descriptor data status = TIReadRom(serial, start_address+sizeof(struct ti_i2c_desc), rom_desc->Size, buffer); if (status) break; status = ValidChecksum(rom_desc, buffer); if (status) break; } start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE)); if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE)) status = -ENODEV;ExitTiValidateI2cImage: kfree (buffer); kfree (rom_desc); return status;}static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer){ int status; int start_address; struct ti_i2c_desc *rom_desc; struct edge_ti_manuf_descriptor *desc; rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); if (!rom_desc) { dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc); if (!start_address) { dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__); status = -ENODEV; goto exit; } // Read the descriptor data status = TIReadRom (serial, start_address+sizeof(struct ti_i2c_desc), rom_desc->Size, buffer); if (status) goto exit; status = ValidChecksum(rom_desc, buffer); desc = (struct edge_ti_manuf_descriptor *)buffer; dbg ( "%s - IonConfig 0x%x", __FUNCTION__, desc->IonConfig ); dbg ( "%s - Version %d", __FUNCTION__, desc->Version ); dbg ( "%s - Cpu/Board 0x%x", __FUNCTION__, desc->CpuRev_BoardRev ); dbg ( "%s - NumPorts %d", __FUNCTION__, desc->NumPorts ); dbg ( "%s - NumVirtualPorts %d", __FUNCTION__, desc->NumVirtualPorts ); dbg ( "%s - TotalPorts %d", __FUNCTION__, desc->TotalPorts ); exit: kfree (rom_desc); return status;}/* Build firmware header used for firmware update */static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev){ __u8 *buffer; int buffer_size; int i; __u8 cs = 0; struct ti_i2c_desc *i2c_header; struct ti_i2c_image_header *img_header; struct ti_i2c_firmware_rec *firmware_rec; // 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. // Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record) buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec)); buffer = kmalloc (buffer_size, GFP_KERNEL); if (!buffer) { dev_err (dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } // Set entire image of 0xffs memset (buffer, 0xff, buffer_size); // Copy version number into firmware record firmware_rec = (struct ti_i2c_firmware_rec *)buffer; firmware_rec->Ver_Major = OperationalCodeImageVersion.MajorVersion; firmware_rec->Ver_Minor = OperationalCodeImageVersion.MinorVersion; // Pointer to fw_down memory image img_header = (struct ti_i2c_image_header *)&PagableOperationalCodeImage[0]; memcpy (buffer + sizeof(struct ti_i2c_firmware_rec), &PagableOperationalCodeImage[sizeof(struct ti_i2c_image_header)], le16_to_cpu(img_header->Length)); for (i=0; i < buffer_size; i++) { cs = (__u8)(cs + buffer[i]); } kfree (buffer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -