/** * Get TX statistics * * @v smsc95xx SMSC95xx device * @v stats Statistics to fill in * @ret rc Return status code */ static int smsc95xx_get_tx_statistics ( struct smsc95xx_device *smsc95xx, struct smsc95xx_tx_statistics *stats ) { int rc; /* Get statistics */ if ( ( rc = usb_control ( smsc95xx->usb, SMSC95XX_GET_STATISTICS, 0, SMSC95XX_TX_STATISTICS, stats, sizeof ( *stats ) ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not get TX statistics: " "%s\n", smsc95xx, strerror ( rc ) ); return rc; } return 0; }
/** * Write register (without byte-swapping) * * @v smsc95xx SMSC95xx device * @v address Register address * @v value Register value * @ret rc Return status code */ static int smsc95xx_raw_writel ( struct smsc95xx_device *smsc95xx, unsigned int address, uint32_t value ) { int rc; /* Write register */ DBGCIO ( smsc95xx, "SMSC95XX %p [%03x] <= %08x\n", smsc95xx, address, le32_to_cpu ( value ) ); if ( ( rc = usb_control ( smsc95xx->usb, SMSC95XX_REGISTER_WRITE, 0, address, &value, sizeof ( value ) ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not write %03x: %s\n", smsc95xx, address, strerror ( rc ) ); return rc; } return 0; }
/** * Read register (without byte-swapping) * * @v smsc95xx SMSC95xx device * @v address Register address * @ret value Register value * @ret rc Return status code */ static int smsc95xx_raw_readl ( struct smsc95xx_device *smsc95xx, unsigned int address, uint32_t *value ) { int rc; /* Read register */ if ( ( rc = usb_control ( smsc95xx->usb, SMSC95XX_REGISTER_READ, 0, address, value, sizeof ( *value ) ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not read %03x: %s\n", smsc95xx, address, strerror ( rc ) ); return rc; } DBGCIO ( smsc95xx, "SMSC95XX %p [%03x] => %08x\n", smsc95xx, address, le32_to_cpu ( *value ) ); return 0; }
void usb_isr(void) { uint8_t status, stat, t; //serial_print("isr"); //status = USB0_ISTAT; //serial_phex(status); //serial_print("\n"); restart: status = USB0_ISTAT; if ((status & USB_INTEN_SOFTOKEN /* 04 */ )) { if (usb_configuration) { t = usb_reboot_timer; if (t) { usb_reboot_timer = --t; if (!t) _reboot_Teensyduino_(); } #ifdef CDC_DATA_INTERFACE t = usb_cdc_transmit_flush_timer; if (t) { usb_cdc_transmit_flush_timer = --t; if (t == 0) usb_serial_flush_callback(); } #endif #if SEREMU_INTERFACE t = usb_seremu_transmit_flush_timer; if (t) { usb_seremu_transmit_flush_timer = --t; if (t == 0) usb_seremu_flush_callback(); } #endif } USB0_ISTAT = USB_INTEN_SOFTOKEN; } if ((status & USB_ISTAT_TOKDNE /* 08 */ )) { uint8_t endpoint; stat = USB0_STAT; //serial_print("token: ep="); //serial_phex(stat >> 4); //serial_print(stat & 0x08 ? ",tx" : ",rx"); //serial_print(stat & 0x04 ? ",odd\n" : ",even\n"); endpoint = stat >> 4; if (endpoint == 0) { usb_control(stat); } else { bdt_t *b = stat2bufferdescriptor(stat); usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8); #if 0 serial_print("ep:"); serial_phex(endpoint); serial_print(", pid:"); serial_phex(BDT_PID(b->desc)); serial_print(((uint32_t)b & 8) ? ", odd" : ", even"); serial_print(", count:"); serial_phex(b->desc >> 16); serial_print("\n"); #endif endpoint--; // endpoint is index to zero-based arrays if (stat & 0x08) { // transmit usb_free(packet); packet = tx_first[endpoint]; if (packet) { //serial_print("tx packet\n"); tx_first[endpoint] = packet->next; b->addr = packet->buf; switch (tx_state[endpoint]) { case TX_STATE_BOTH_FREE_EVEN_FIRST: tx_state[endpoint] = TX_STATE_ODD_FREE; break; case TX_STATE_BOTH_FREE_ODD_FIRST: tx_state[endpoint] = TX_STATE_EVEN_FREE; break; case TX_STATE_EVEN_FREE: case TX_STATE_ODD_FREE: default: tx_state[endpoint] = TX_STATE_NONE_FREE; break; } b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0); } else { //serial_print("tx no packet\n"); switch (tx_state[endpoint]) { case TX_STATE_BOTH_FREE_EVEN_FIRST: case TX_STATE_BOTH_FREE_ODD_FIRST: break; case TX_STATE_EVEN_FREE: tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST; break; case TX_STATE_ODD_FREE: tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST; break; default: tx_state[endpoint] = ((uint32_t)b & 8) ? TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE; break; } } } else { // receive packet->len = b->desc >> 16; packet->index = 0; packet->next = NULL; if (rx_first[endpoint] == NULL) { //serial_print("rx 1st, epidx="); //serial_phex(endpoint); //serial_print(", packet="); //serial_phex32((uint32_t)packet); //serial_print("\n"); rx_first[endpoint] = packet; } else { //serial_print("rx Nth, epidx="); //serial_phex(endpoint); //serial_print(", packet="); //serial_phex32((uint32_t)packet); //serial_print("\n"); rx_last[endpoint]->next = packet; } rx_last[endpoint] = packet; // TODO: implement a per-endpoint maximum # of allocated packets // so a flood of incoming data on 1 endpoint doesn't starve // the others if the user isn't reading it regularly packet = usb_malloc(); if (packet) { b->addr = packet->buf; b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0); } else { //serial_print("starving "); //serial_phex(endpoint + 1); //serial_print(((uint32_t)b & 8) ? ",odd\n" : ",even\n"); b->desc = 0; usb_rx_memory_needed++; } } } USB0_ISTAT = USB_ISTAT_TOKDNE; goto restart; }