📄 io_ti.c
字号:
/* * Edgeport USB Serial Converter driver * * Copyright(c) 2000-2002 Inside Out Networks, All rights reserved. * Copyright(c) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Supports the following devices: * EP/1 EP/2 EP/4 * * Version history: * * July 11, 2002 Removed 4 port device structure since all TI UMP * chips have only 2 ports * David Iacovelli (davidi@ionetworks.com) * */#include <linux/config.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/tty.h>#include <linux/tty_driver.h>#include <linux/tty_flip.h>#include <linux/module.h>#include <linux/spinlock.h>#include <linux/serial.h>#include <linux/ioctl.h>#include <asm/uaccess.h>#include <linux/usb.h>#ifdef CONFIG_USB_SERIAL_DEBUG static int debug = 1;#else static int debug;#endif#include "usb-serial.h"#include "io_16654.h"#include "io_usbvend.h"#include "io_ti.h"/* * Version Information */#define DRIVER_VERSION "v0.2"#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"#define DRIVER_DESC "Edgeport USB Serial Driver"/* firmware image code */#define IMAGE_VERSION_NAME PagableOperationalCodeImageVersion#define IMAGE_ARRAY_NAME PagableOperationalCodeImage#define IMAGE_SIZE PagableOperationalCodeSize#include "io_fw_down3.h" /* Define array OperationalCodeImage[] */#define EPROM_PAGE_SIZE 64struct edgeport_uart_buf_desc { __u32 count; // Number of bytes currently in buffer};/* different hardware types */#define HARDWARE_TYPE_930 0#define HARDWARE_TYPE_TIUMP 1// IOCTL_PRIVATE_TI_GET_MODE Definitions#define TI_MODE_CONFIGURING 0 // Device has not entered start device #define TI_MODE_BOOT 1 // Staying in boot mode#define TI_MODE_DOWNLOAD 2 // Made it to download mode#define TI_MODE_TRANSITIONING 3 // Currently in boot mode but transitioning to download mode/* Product information read from the Edgeport */struct product_info{ int TiMode; // Current TI Mode __u8 hardware_type; // Type of hardware} __attribute__((packed));struct edgeport_port { __u16 uart_base; __u16 dma_address; __u8 shadow_msr; __u8 shadow_mcr; __u8 shadow_lsr; __u8 lsr_mask; __u32 ump_read_timeout; /* Number of miliseconds the UMP will wait without data before completing a read short */ int baud_rate; int close_pending; int lsr_event; struct edgeport_uart_buf_desc tx; struct async_icount icount; wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ struct edgeport_serial *edge_serial; struct usb_serial_port *port;};struct edgeport_serial { struct product_info product_info; u8 TI_I2C_Type; // Type of I2C in UMP u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode int num_ports_open; struct usb_serial *serial;};/* Devices that this driver supports */static struct usb_device_id edgeport_1port_id_table [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, { }};static struct usb_device_id edgeport_2port_id_table [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) }, { }};/* Devices that this driver supports */static __devinitdata struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) }, { }};MODULE_DEVICE_TABLE (usb, id_table_combined);static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion;static int TIStayInBootMode = 0;static int ignore_cpu_rev = 0;static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);static int TIReadVendorRequestSync (struct usb_device *dev, __u8 request, __u16 value, __u16 index, u8 *data, int size){ int status; status = usb_control_msg (dev, usb_rcvctrlpipe(dev, 0), request, (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN), value, index, data, size, HZ); if (status < 0) return status; if (status != size) { dbg ("%s - wanted to write %d, but only wrote %d", __FUNCTION__, size, status); return -ECOMM; } return 0;}static int TISendVendorRequestSync (struct usb_device *dev, __u8 request, __u16 value, __u16 index, u8 *data, int size){ int status; status = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT), value, index, data, size, HZ); if (status < 0) return status; if (status != size) { dbg ("%s - wanted to write %d, but only wrote %d", __FUNCTION__, size, status); return -ECOMM; } return 0;}static int TIWriteCommandSync (struct usb_device *dev, __u8 command, __u8 moduleid, __u16 value, u8 *data, int size){ return TISendVendorRequestSync (dev, command, // Request value, // wValue moduleid, // wIndex data, // TransferBuffer size); // TransferBufferLength}/* clear tx/rx buffers and fifo in TI UMP */static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask){ int port_number = port->number - port->serial->minor; dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask); return TIWriteCommandSync (port->serial->dev, UMPC_PURGE_PORT, (__u8)(UMPM_UART1_PORT + port_number), mask, NULL, 0);}/** * TIReadDownloadMemory - Read edgeport memory from TI chip * @dev: usb device pointer * @address: Device CPU address at which to read * @length: Length of above data * @address_type: Can read both XDATA and I2C * @buffer: pointer to input data buffer */int TIReadDownloadMemory (struct usb_device *dev, int start_address, int length, __u8 address_type, __u8 *buffer){ int status = 0; __u8 read_length; __u16 be_start_address; dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length); /* Read in blocks of 64 bytes * (TI firmware can't handle more than 64 byte reads) */ while (length) { if (length > 64) read_length= 64; else read_length = (__u8)length; if (read_length > 1) { dbg ("%s - @ %x for %d", __FUNCTION__, start_address, read_length); } be_start_address = cpu_to_be16 (start_address); status = TIReadVendorRequestSync (dev, UMPC_MEMORY_READ, // Request (__u16)address_type, // wValue (Address type) be_start_address, // wIndex (Address to read) buffer, // TransferBuffer read_length); // TransferBufferLength if (status) { dbg ("%s - ERROR %x", __FUNCTION__, status); return status; } if (read_length > 1) { usb_serial_debug_data (__FILE__, __FUNCTION__, read_length, buffer); } /* Update pointers/length */ start_address += read_length; buffer += read_length; length -= read_length; } return status;}int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer){ return TIReadDownloadMemory (dev, start_address, length, DTK_ADDR_SPACE_XDATA, buffer);}/* Read edgeport memory to a given block */static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer){ int status = 0; int i; for (i=0; i< length; i++) { status = TIReadVendorRequestSync (serial->serial->dev, UMPC_MEMORY_READ, // Request serial->TI_I2C_Type, // wValue (Address type) (__u16)(start_address+i), // wIndex &buffer[i], // TransferBuffer 0x01); // TransferBufferLength if (status) { dbg ("%s - ERROR %x", __FUNCTION__, status); return status; } } dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length); usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer); serial->TiReadI2C = 1; return status;}/* Write given block to TI EPROM memory */static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer){ int status = 0; int i; __u8 temp; /* Must do a read before write */ if (!serial->TiReadI2C) { status = TIReadBootMemory(serial, 0, 1, &temp); if (status) return status; } for (i=0; i < length; ++i) { status = TISendVendorRequestSync (serial->serial->dev, UMPC_MEMORY_WRITE, // Request buffer[i], // wValue (__u16)(i+start_address), // wIndex NULL, // TransferBuffer 0); // TransferBufferLength if (status) return status; } dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length); usb_serial_debug_data (__FILE__, __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; __u16 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 (__FILE__, __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 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 (__FILE__, __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 be_start_address, // wIndex buffer, // TransferBuffer write_length); // TransferBufferLength if (status) { dbg ("%s - ERROR %d", __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) { err ("%s - out of memory", __FUNCTION__); 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -