📄 ftdi-elan.c
字号:
int packet_bytes = 0; int retval = usb_bulk_msg(ftdi->udev, usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr), ftdi->bulk_in_buffer, ftdi->bulk_in_size, &packet_bytes, msecs_to_jiffies(500)); char diag[30 *3 + 4]; char *d = diag; int m = packet_bytes; u8 *c = ftdi->bulk_in_buffer; int s = (sizeof(diag) - 1) / 3; diag[0] = 0; while (s-- > 0 && m-- > 0) { if (s > 0 || m == 0) { d += sprintf(d, " %02X", *c++); } else d += sprintf(d, " .."); } if (packet_bytes > 2) { ftdi->bulk_in_left = packet_bytes - 2; ftdi->bulk_in_last = 1; goto have; } else if (retval == -ETIMEDOUT) { if (retry_on_timeout-- > 0) { dev_err(&ftdi->udev->dev, "TIMED OUT with packe" "t_bytes = %d with total %d bytes%s\n", packet_bytes, bytes_read, diag); goto more; } else if (bytes_read > 0) { dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n", bytes_read, diag); return -ENOMEM; } else { dev_err(&ftdi->udev->dev, "TIMED OUT with packe" "t_bytes = %d with total %d bytes%s\n", packet_bytes, bytes_read, diag); return -ENOMEM; } } else if (retval == -EILSEQ) { dev_err(&ftdi->udev->dev, "error = %d with packet_bytes" " = %d with total %d bytes%s\n", retval, packet_bytes, bytes_read, diag); return retval; } else if (retval) { dev_err(&ftdi->udev->dev, "error = %d with packet_bytes" " = %d with total %d bytes%s\n", retval, packet_bytes, bytes_read, diag); return retval; } else if (packet_bytes == 2) { unsigned char s0 = ftdi->bulk_in_buffer[0]; unsigned char s1 = ftdi->bulk_in_buffer[1]; empty_packets += 1; if (s0 == 0x31 && s1 == 0x60) { if (retry_on_empty-- > 0) { goto more; } else return 0; } else if (s0 == 0x31 && s1 == 0x00) { if (retry_on_empty-- > 0) { goto more; } else return 0; } else { if (retry_on_empty-- > 0) { goto more; } else return 0; } } else if (packet_bytes == 1) { if (retry_on_empty-- > 0) { goto more; } else return 0; } else { if (retry_on_empty-- > 0) { goto more; } else return 0; } } more:{ goto read; } have:if (ftdi->bulk_in_left > 0) { u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last]; bytes_read += 1; ftdi->bulk_in_left -= 1; if (ftdi->recieved == 0 && c == 0xFF) { goto have; } else *b++ = c; if (++ftdi->recieved < ftdi->expected) { goto have; } else if (ftdi->ed_found) { int ed_number = (ftdi->response[0] >> 5) & 0x03; u16 ed_length = (ftdi->response[2] << 8) | ftdi->response[1]; struct u132_target *target = &ftdi->target[ed_number]; int payload = (ed_length >> 0) & 0x07FF; char diag[30 *3 + 4]; char *d = diag; int m = payload; u8 *c = 4 + ftdi->response; int s = (sizeof(diag) - 1) / 3; diag[0] = 0; while (s-- > 0 && m-- > 0) { if (s > 0 || m == 0) { d += sprintf(d, " %02X", *c++); } else d += sprintf(d, " .."); } ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response, payload); ftdi->recieved = 0; ftdi->expected = 4; ftdi->ed_found = 0; b = ftdi->response; goto have; } else if (ftdi->expected == 8) { u8 buscmd; int respond_head = ftdi->respond_head++; struct u132_respond *respond = &ftdi->respond[ RESPOND_MASK & respond_head]; u32 data = ftdi->response[7]; data <<= 8; data |= ftdi->response[6]; data <<= 8; data |= ftdi->response[5]; data <<= 8; data |= ftdi->response[4]; *respond->value = data; *respond->result = 0; complete(&respond->wait_completion); ftdi->recieved = 0; ftdi->expected = 4; ftdi->ed_found = 0; b = ftdi->response; buscmd = (ftdi->response[0] >> 0) & 0x0F; if (buscmd == 0x00) { } else if (buscmd == 0x02) { } else if (buscmd == 0x06) { } else if (buscmd == 0x0A) { } else dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) va" "lue = %08X\n", buscmd, data); goto have; } else { if ((ftdi->response[0] & 0x80) == 0x00) { ftdi->expected = 8; goto have; } else { int ed_number = (ftdi->response[0] >> 5) & 0x03; int ed_type = (ftdi->response[0] >> 0) & 0x03; u16 ed_length = (ftdi->response[2] << 8) | ftdi->response[1]; struct u132_target *target = &ftdi->target[ ed_number]; target->halted = (ftdi->response[0] >> 3) & 0x01; target->skipped = (ftdi->response[0] >> 2) & 0x01; target->toggle_bits = (ftdi->response[3] >> 6) & 0x03; target->error_count = (ftdi->response[3] >> 4) & 0x03; target->condition_code = (ftdi->response[ 3] >> 0) & 0x0F; if ((ftdi->response[0] & 0x10) == 0x00) { b = have_ed_set_response(ftdi, target, ed_length, ed_number, ed_type, b); goto have; } else { b = have_ed_get_response(ftdi, target, ed_length, ed_number, ed_type, b); goto have; } } } } else goto more;}/** create a urb, and a buffer for it, and copy the data to the urb**/static ssize_t ftdi_elan_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos){ int retval = 0; struct urb *urb; char *buf; struct usb_ftdi *ftdi = file->private_data; if (ftdi->disconnected > 0) { return -ENODEV; } if (count == 0) { goto exit; } urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; goto error_1; } buf = usb_buffer_alloc(ftdi->udev, count, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error_2; } if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; goto error_3; } usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev, ftdi->bulk_out_endpointAddr), buf, count, ftdi_elan_write_bulk_callback, ftdi); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { dev_err(&ftdi->udev->dev, "failed submitting write urb, error %" "d\n", retval); goto error_3; } usb_free_urb(urb);exit: return count;error_3: usb_buffer_free(ftdi->udev, count, buf, urb->transfer_dma);error_2: usb_free_urb(urb);error_1: return retval;}static const struct file_operations ftdi_elan_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .ioctl = ftdi_elan_ioctl, .read = ftdi_elan_read, .write = ftdi_elan_write, .open = ftdi_elan_open, .release = ftdi_elan_release,};/** usb class driver info in order to get a minor number from the usb core,* and to have the device registered with the driver core*/static struct usb_class_driver ftdi_elan_jtag_class = { .name = "ftdi-%d-jtag", .fops = &ftdi_elan_fops, .minor_base = USB_FTDI_ELAN_MINOR_BASE,};/** the following definitions are for the* ELAN FPGA state machgine processor that* lies on the other side of the FTDI chip*/#define cPCIu132rd 0x0#define cPCIu132wr 0x1#define cPCIiord 0x2#define cPCIiowr 0x3#define cPCImemrd 0x6#define cPCImemwr 0x7#define cPCIcfgrd 0xA#define cPCIcfgwr 0xB#define cPCInull 0xF#define cU132cmd_status 0x0#define cU132flash 0x1#define cPIDsetup 0x0#define cPIDout 0x1#define cPIDin 0x2#define cPIDinonce 0x3#define cCCnoerror 0x0#define cCCcrc 0x1#define cCCbitstuff 0x2#define cCCtoggle 0x3#define cCCstall 0x4#define cCCnoresp 0x5#define cCCbadpid1 0x6#define cCCbadpid2 0x7#define cCCdataoverrun 0x8#define cCCdataunderrun 0x9#define cCCbuffoverrun 0xC#define cCCbuffunderrun 0xD#define cCCnotaccessed 0xFstatic int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data){ wait:if (ftdi->disconnected > 0) { return -ENODEV; } else { int command_size; mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { struct u132_command *command = &ftdi->command[ COMMAND_MASK & ftdi->command_next]; command->header = 0x00 | cPCIu132wr; command->length = 0x04; command->address = 0x00; command->width = 0x00; command->follows = 4; command->value = data; command->buffer = &command->value; ftdi->command_next += 1; ftdi_elan_kick_command_queue(ftdi); mutex_unlock(&ftdi->u132_lock); return 0; } else { mutex_unlock(&ftdi->u132_lock); msleep(100); goto wait; } }}static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset, u8 width, u32 data){ u8 addressofs = config_offset / 4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -