icE1usb fw: Expose error conditions from E1 driver
This will allow the USB interface code to report the errors to the host PC. Related: OS#4674 Change-Id: Iba3e00a2b28a2fef6dbd986bfc706c1619c3a3ed
This commit is contained in:
parent
9469e046f1
commit
805f2cf16e
|
@ -232,6 +232,7 @@ static struct {
|
|||
int in_flight;
|
||||
enum e1_pipe_state state;
|
||||
} tx;
|
||||
struct e1_error_count errors;
|
||||
} g_e1;
|
||||
|
||||
|
||||
|
@ -360,6 +361,12 @@ e1_rx_level(void)
|
|||
return e1f_valid_frames(&g_e1.rx.fifo);
|
||||
}
|
||||
|
||||
const struct e1_error_count *
|
||||
e1_get_error_count(void)
|
||||
{
|
||||
return &g_e1.errors;
|
||||
}
|
||||
|
||||
void
|
||||
e1_poll(void)
|
||||
{
|
||||
|
@ -374,10 +381,12 @@ e1_poll(void)
|
|||
if (e1_regs->rx.csr & E1_RX_SR_ALIGNED) {
|
||||
e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_ON);
|
||||
led_color(0, 48, 0);
|
||||
g_e1.errors.flags &= ~(E1_ERR_F_LOS|E1_ERR_F_ALIGN_ERR);
|
||||
} else {
|
||||
e1_platform_led_set(0, E1P_LED_GREEN, E1P_LED_ST_BLINK);
|
||||
/* TODO: completely off if rx tick counter not incrementing */
|
||||
led_color(48, 0, 0);
|
||||
g_e1.errors.flags |= E1_ERR_F_ALIGN_ERR;
|
||||
/* TODO: completely off if rx tick counter not incrementing */
|
||||
}
|
||||
|
||||
/* Recover any done TX BD */
|
||||
|
@ -390,8 +399,10 @@ e1_poll(void)
|
|||
while ( (bd = e1_regs->rx.bd) & E1_BD_VALID ) {
|
||||
/* FIXME: CRC status ? */
|
||||
e1f_multiframe_write_commit(&g_e1.rx.fifo);
|
||||
if ((bd & (E1_BD_CRC0 | E1_BD_CRC1)) != (E1_BD_CRC0 | E1_BD_CRC1))
|
||||
if ((bd & (E1_BD_CRC0 | E1_BD_CRC1)) != (E1_BD_CRC0 | E1_BD_CRC1)) {
|
||||
printf("b: %03x\n", bd);
|
||||
g_e1.errors.crc++;
|
||||
}
|
||||
g_e1.rx.in_flight--;
|
||||
}
|
||||
|
||||
|
@ -410,6 +421,7 @@ e1_poll(void)
|
|||
if (!(e1_regs->rx.csr & E1_RX_SR_ALIGNED)) {
|
||||
printf("[!] E1 rx misalign\n");
|
||||
g_e1.rx.state = RECOVER;
|
||||
g_e1.errors.align++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,6 +430,7 @@ e1_poll(void)
|
|||
if (e1_regs->rx.csr & E1_RX_SR_OVFL) {
|
||||
printf("[!] E1 overflow %d\n", g_e1.rx.in_flight);
|
||||
g_e1.rx.state = RECOVER;
|
||||
g_e1.errors.ovfl++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,6 +462,7 @@ done_rx:
|
|||
if (e1_regs->tx.csr & E1_TX_SR_UNFL) {
|
||||
printf("[!] E1 underflow %d\n", g_e1.tx.in_flight);
|
||||
g_e1.tx.state = RECOVER;
|
||||
g_e1.errors.unfl++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,19 @@ void e1_debug_print(bool data);
|
|||
void e1_tx_config(uint16_t cr);
|
||||
void e1_rx_config(uint16_t cr);
|
||||
|
||||
#define E1_ERR_F_ALIGN_ERR 0x01
|
||||
#define E1_ERR_F_LOS 0x02
|
||||
|
||||
struct e1_error_count {
|
||||
uint16_t crc;
|
||||
uint16_t align;
|
||||
uint16_t ovfl;
|
||||
uint16_t unfl;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
const struct e1_error_count *e1_get_error_count(void);
|
||||
|
||||
volatile uint8_t *e1_data_ptr(int mf, int frame, int ts);
|
||||
unsigned int e1_data_ofs(int mf, int frame, int ts);
|
||||
|
||||
|
|
|
@ -75,3 +75,32 @@ enum ice1usb_rx_mode {
|
|||
struct ice1usb_rx_config {
|
||||
uint8_t mode; /*!< enum ice1usb_rx_mode */
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Interrupt Endpoint
|
||||
***********************************************************************/
|
||||
|
||||
enum ice1usb_irq_type {
|
||||
ICE1USB_IRQ_T_ERRCNT = 1,
|
||||
};
|
||||
|
||||
/* Ensue ro keep those in sync with e1.h */
|
||||
#define ICE1USB_ERR_F_ALIGN_ERR 0x01
|
||||
#define ICE1USB_ERR_F_LOS 0x02
|
||||
|
||||
struct ice1usb_irq_err {
|
||||
/* 16-bit little-endian counters */
|
||||
uint16_t crc;
|
||||
uint16_t align;
|
||||
uint16_t ovfl;
|
||||
uint16_t unfl;
|
||||
uint8_t flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ice1usb_irq {
|
||||
uint8_t type; /*!< enum ice1usb_irq_type */
|
||||
union {
|
||||
struct ice1usb_irq_err errors;
|
||||
} u;
|
||||
} __attribute__((packed));
|
||||
|
|
|
@ -28,12 +28,14 @@ static const struct {
|
|||
struct usb_ep_desc ep_data_in;
|
||||
struct usb_ep_desc ep_data_out;
|
||||
struct usb_ep_desc ep_fb;
|
||||
struct usb_ep_desc ep_interrupt;
|
||||
} __attribute__ ((packed)) off;
|
||||
struct {
|
||||
struct usb_intf_desc intf;
|
||||
struct usb_ep_desc ep_data_in;
|
||||
struct usb_ep_desc ep_data_out;
|
||||
struct usb_ep_desc ep_fb;
|
||||
struct usb_ep_desc ep_interrupt;
|
||||
} __attribute__ ((packed)) on;
|
||||
} __attribute__ ((packed)) e1;
|
||||
|
||||
|
@ -79,7 +81,7 @@ static const struct {
|
|||
.bDescriptorType = USB_DT_INTF,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 3,
|
||||
.bNumEndpoints = 4,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0xe1,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
|
@ -109,6 +111,14 @@ static const struct {
|
|||
.wMaxPacketSize = 0,
|
||||
.bInterval = 3,
|
||||
},
|
||||
.ep_interrupt = {
|
||||
.bLength = sizeof(struct usb_ep_desc),
|
||||
.bDescriptorType = USB_DT_EP,
|
||||
.bEndpointAddress = 0x83,
|
||||
.bmAttributes = 0x03,
|
||||
.wMaxPacketSize = 10,
|
||||
.bInterval = 3,
|
||||
},
|
||||
},
|
||||
.on = {
|
||||
.intf = {
|
||||
|
@ -116,7 +126,7 @@ static const struct {
|
|||
.bDescriptorType = USB_DT_INTF,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 1,
|
||||
.bNumEndpoints = 3,
|
||||
.bNumEndpoints = 4,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0xe1,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
|
@ -146,6 +156,14 @@ static const struct {
|
|||
.wMaxPacketSize = 8,
|
||||
.bInterval = 3,
|
||||
},
|
||||
.ep_interrupt = {
|
||||
.bLength = sizeof(struct usb_ep_desc),
|
||||
.bDescriptorType = USB_DT_EP,
|
||||
.bEndpointAddress = 0x83,
|
||||
.bmAttributes = 0x03,
|
||||
.wMaxPacketSize = 10,
|
||||
.bInterval = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
#if 0
|
||||
|
|
|
@ -25,6 +25,7 @@ struct {
|
|||
int in_bdi; /* buffer descriptor index for IN EP */
|
||||
struct ice1usb_tx_config tx_cfg;
|
||||
struct ice1usb_rx_config rx_cfg;
|
||||
struct e1_error_count last_err;
|
||||
} g_usb_e1;
|
||||
|
||||
/* default configuration at power-up */
|
||||
|
@ -87,6 +88,29 @@ usb_e1_run(void)
|
|||
if (!g_usb_e1.running)
|
||||
return;
|
||||
|
||||
/* EP3 IRQ */
|
||||
if ((usb_ep_regs[3].in.bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) {
|
||||
const struct e1_error_count *cur_err = e1_get_error_count();
|
||||
if (memcmp(cur_err, &g_usb_e1.last_err, sizeof(*cur_err))) {
|
||||
struct ice1usb_irq errmsg = {
|
||||
.type = ICE1USB_IRQ_T_ERRCNT,
|
||||
.u = {
|
||||
.errors = {
|
||||
.crc = cur_err->crc,
|
||||
.align = cur_err->align,
|
||||
.ovfl = cur_err->ovfl,
|
||||
.unfl = cur_err->unfl,
|
||||
.flags = cur_err->flags,
|
||||
}
|
||||
}
|
||||
};
|
||||
printf("E");
|
||||
usb_data_write(usb_ep_regs[3].in.bd[0].ptr, &errmsg, sizeof(errmsg));
|
||||
usb_ep_regs[3].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg));
|
||||
g_usb_e1.last_err = *cur_err;
|
||||
}
|
||||
}
|
||||
|
||||
/* EP2 IN */
|
||||
bdi = g_usb_e1.in_bdi;
|
||||
|
||||
|
@ -213,6 +237,7 @@ _e1_set_conf(const struct usb_conf_desc *conf)
|
|||
usb_ep_boot(intf, 0x01, true);
|
||||
usb_ep_boot(intf, 0x81, true);
|
||||
usb_ep_boot(intf, 0x82, true);
|
||||
usb_ep_boot(intf, 0x83, true);
|
||||
|
||||
return USB_FND_SUCCESS;
|
||||
}
|
||||
|
@ -274,6 +299,11 @@ _e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
|
|||
/* EP1 IN: Queue buffer */
|
||||
_usb_fill_feedback_ep();
|
||||
|
||||
/* EP3 IN: Interrupt */
|
||||
usb_ep_regs[3].in.status = USB_EP_TYPE_INT;
|
||||
usb_ep_regs[3].in.bd[0].ptr = 68;
|
||||
usb_ep_regs[3].in.bd[0].csr = 0;
|
||||
|
||||
return USB_FND_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue