📄 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 EP/21 EP/22 EP/221 EP/42 EP/421 WATCHPORT * * For questions or problems with this driver, contact Inside Out * Networks technical support, or Peter Berger <pberger@brimson.com>, * or Al Borchers <alborchers@steinerpoint.com>. * * 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/jiffies.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 <asm/semaphore.h>#include <linux/usb.h>#include "usb-serial.h"#include "io_16654.h"#include "io_usbvend.h"#include "io_ti.h"/* * Version Information */#define DRIVER_VERSION "v0.7"#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/* read urb state */#define EDGE_READ_URB_RUNNING 0#define EDGE_READ_URB_STOPPING 1#define EDGE_READ_URB_STOPPED 2#define EDGE_LOW_LATENCY 1#define EDGE_CLOSING_WAIT 4000 /* in .01 sec */#define EDGE_OUT_BUF_SIZE 1024/* Product information read from the Edgeport */struct product_info{ int TiMode; // Current TI Mode __u8 hardware_type; // Type of hardware} __attribute__((packed));/* circular buffer */struct edge_buf { unsigned int buf_size; char *buf_buf; char *buf_get; char *buf_put;};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; __u8 bUartMode; /* Port type, 0: RS232, etc. */ spinlock_t ep_lock; int ep_read_urb_state; int ep_write_urb_in_use; struct edge_buf *ep_out_buf;};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 struct semaphore es_sem; 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) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) }, { }};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_2C) }, { 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_21) }, { 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_22I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },// The 4-port shows up as two 2-port devices { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, { }};/* Devices that this driver supports */static 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_TI3410_EDGEPORT_1) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROXIMITY) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOTION) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_MOISTURE) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_TEMPERATURE) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_HUMIDITY) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_POWER) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_LIGHT) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_RADIATION) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_DISTANCE) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_ACCELERATION) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_WP_PROX_DIST) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_HP4CD) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_PLUS_PWR_PCI) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) }, { 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_21) }, { 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_22I) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, { }};MODULE_DEVICE_TABLE (usb, id_table_combined);static struct usb_driver io_driver = { .owner = THIS_MODULE, .name = "io_ti", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined,};static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion;static int debug;static int TIStayInBootMode = 0;static int low_latency = EDGE_LOW_LATENCY;static int closing_wait = EDGE_CLOSING_WAIT;static int ignore_cpu_rev = 0;static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);static void stop_read(struct edgeport_port *edge_port);static int restart_read(struct edgeport_port *edge_port);static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);static void edge_send(struct usb_serial_port *port);/* circular buffer */static struct edge_buf *edge_buf_alloc(unsigned int size);static void edge_buf_free(struct edge_buf *eb);static void edge_buf_clear(struct edge_buf *eb);static unsigned int edge_buf_data_avail(struct edge_buf *eb);static unsigned int edge_buf_space_avail(struct edge_buf *eb);static unsigned int edge_buf_put(struct edge_buf *eb, const char *buf, unsigned int count);static unsigned int edge_buf_get(struct edge_buf *eb, char *buf, unsigned int count);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, 1000); 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, 1000); 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 * @start_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 */static int TIReadDownloadMemory(struct usb_device *dev, int start_address, int length, __u8 address_type, __u8 *buffer){ int status = 0; __u8 read_length; __be16 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) (__force __u16)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(debug, &dev->dev, __FUNCTION__, read_length, buffer); } /* Update pointers/length */ start_address += read_length; buffer += read_length; length -= read_length; } return status;}static 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(debug, &serial->serial->dev->dev, __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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -