X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=usb%2Fhost%2Fohci.c;h=f243bcad9f56c7f6040eccc5c599cbb3fc4b4424;hb=dd7d06aa840f23f3447befc37ce1ddcbe3a10c29;hp=a1520d02d61481ba7ad251378924c46c9ebf1d9e;hpb=5e7b3fe7025e9b039c5ab8d4cd9b4af088b70303;p=ppcskel.git diff --git a/usb/host/ohci.c b/usb/host/ohci.c index a1520d0..f243bca 100644 --- a/usb/host/ohci.c +++ b/usb/host/ohci.c @@ -35,10 +35,11 @@ static struct general_td *allocate_general_td(); static void dbg_op_state(u32 reg); static void configure_ports(u8 from_init, u32 reg); static void setup_port(u32 ohci, u32 reg, u8 from_init); +static void set_target_hcca(u32 reg); static struct ohci_hcca hcca_oh0; static struct ohci_hcca hcca_oh1; - +struct ohci_hcca *hcca; static struct general_td *allocate_general_td() { @@ -116,11 +117,7 @@ static void general_td_fill(struct general_td *dest, const struct usb_transfer_d dest->flags |= LE(OHCI_TD_DIRECTION_PID_OUT); dest->flags |= LE(OHCI_TD_BUFFER_ROUNDING); - /* - * TODO: just temporary solution! (consider it with len?) - * there can be also regular PID_OUT pakets - */ - dest->flags |= LE(OHCI_TD_TOGGLE_1); + dest->flags |= src->togl ? LE(OHCI_TD_TOGGLE_1) : LE(OHCI_TD_TOGGLE_0); break; case USB_PID_IN: #ifdef _DU_OHCI_Q @@ -133,12 +130,7 @@ static void general_td_fill(struct general_td *dest, const struct usb_transfer_d printf("round buffer!\n"); #endif } - /* - * let the endpoint do the togglestuff! - * TODO: just temporary solution! - * there can be also inregular PID_IN pakets (@Status Stage) - */ - dest->flags |= LE(OHCI_TD_TOGGLE_CARRY); + dest->flags |= src->togl ? LE(OHCI_TD_TOGGLE_1) : LE(OHCI_TD_TOGGLE_0); break; } dest->flags |= LE(OHCI_TD_SET_DELAY_INTERRUPT(7)); @@ -163,12 +155,33 @@ void hcdi_fire(u32 reg) if(edhead == 0) return; + u8 itmp; + switch(edhead->type) { + case USB_CTRL: #ifdef _USE_C_Q - /* quirk... 11ms seems to be a minimum :O */ - udelay(11000); -#endif + /* quirk... 11ms seems to be a minimum :O */ + udelay(11000); +#endif + write32(reg+OHCI_HC_CTRL_HEAD_ED, virt_to_phys(edhead)); + break; + + case USB_INTR: + //udelay(11000); + set_target_hcca(reg); + sync_before_read(hcca, sizeof(struct ohci_hcca)); + for(itmp = 0; itmp < NUM_INITS; itmp++) { + hcca->int_table[itmp] = LE(virt_to_phys(edhead)); + } + sync_after_write(hcca, sizeof(struct ohci_hcca)); + break; + + case USB_BULK: + write32(reg+OHCI_HC_BULK_HEAD_ED, virt_to_phys(edhead)); + break; - write32(reg+OHCI_HC_CTRL_HEAD_ED, virt_to_phys(edhead)); + case USB_ISOC: + break; + } /* sync it all */ sync_after_write(edhead, sizeof(struct endpoint_descriptor)); @@ -192,9 +205,28 @@ void hcdi_fire(u32 reg) x = phys_to_virt(LE(x->nexttd)); } - /* trigger control list */ - set32(reg+OHCI_HC_CONTROL, OHCI_CTRL_CLE); - write32(reg+OHCI_HC_COMMAND_STATUS, OHCI_CLF); + /* start transfer */ + switch(edhead->type) { + case USB_CTRL: + /* trigger control list */ + set32(reg+OHCI_HC_CONTROL, OHCI_CTRL_CLE); + write32(reg+OHCI_HC_COMMAND_STATUS, OHCI_CLF); + break; + + case USB_INTR: + /* trigger periodic list */ + set32(reg+OHCI_HC_CONTROL, OHCI_CTRL_PLE); + break; + + case USB_BULK: + /* trigger bulk list */ + set32(reg+OHCI_HC_CONTROL, OHCI_CTRL_BLE); + write32(reg+OHCI_HC_COMMAND_STATUS, OHCI_BLF); + break; + + case USB_ISOC: + break; + } struct general_td *n=0, *prev = 0, *next = 0; /* poll until edhead->headp is null */ @@ -202,7 +234,6 @@ void hcdi_fire(u32 reg) sync_before_read(edhead, sizeof(struct endpoint_descriptor)); #ifdef _DU_OHCI_F printf("edhead->headp: 0x%08X\n", LE(edhead->headp)); - udelay(10000); #endif /* if halted, debug output plz. will break the transfer */ @@ -243,7 +274,7 @@ void hcdi_fire(u32 reg) dbg_td_flag(LE(prev->flags)); printf("halted end!\n"); #endif - return; + goto out; } prev = (struct general_td*) (LE(edhead->headp)&~0xf); } while(LE(edhead->headp)&~0xf); @@ -291,15 +322,33 @@ void hcdi_fire(u32 reg) free(prev); } - if(reg == OHCI0_REG_BASE) { - hcca_oh0.done_head = 0; - sync_after_write(&hcca_oh0, sizeof(hcca_oh0)); - } else if (reg == OHCI1_REG_BASE) { - hcca_oh1.done_head = 0; - sync_after_write(&hcca_oh1, sizeof(hcca_oh1)); +out: + set_target_hcca(reg); + sync_before_read(hcca, sizeof(struct ohci_hcca)); + + u8 jtmp; + switch(edhead->type) { + case USB_CTRL: + write32(reg+OHCI_HC_CONTROL, read32(reg+OHCI_HC_CONTROL)&~OHCI_CTRL_CLE); + break; + + case USB_INTR: + write32(reg+OHCI_HC_CONTROL, read32(reg+OHCI_HC_CONTROL)&~OHCI_CTRL_PLE); + for(jtmp = 0; jtmp < NUM_INITS; jtmp++) { + hcca->int_table[jtmp] = 0; + } + break; + + case USB_BULK: + write32(reg+OHCI_HC_CONTROL, read32(reg+OHCI_HC_CONTROL)&~OHCI_CTRL_BLE); + break; + + case USB_ISOC: + break; } - write32(reg+OHCI_HC_CONTROL, read32(reg+OHCI_HC_CONTROL)&~OHCI_CTRL_CLE); + hcca->done_head = 0; + sync_after_write(hcca, sizeof(struct ohci_hcca)); edhead = 0; @@ -329,6 +378,7 @@ u8 hcdi_enqueue(const struct usb_transfer_descriptor *td, u32 reg) { OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(td->endpoint) | OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(td->maxp)); edhead->tdcount = 0; + edhead->type = td->type; } struct general_td *tdhw = allocate_general_td(); @@ -412,13 +462,9 @@ void hcdi_init(u32 reg) write32(reg+OHCI_HC_BULK_HEAD_ED, 0); /* set hcca adress */ - if(reg == OHCI0_REG_BASE) { - sync_after_write(&hcca_oh0, 256); - write32(reg+OHCI_HC_HCCA, virt_to_phys(&hcca_oh0)); - } else { - sync_after_write(&hcca_oh1, 256); - write32(reg+OHCI_HC_HCCA, virt_to_phys(&hcca_oh1)); - } + set_target_hcca(reg); + sync_after_write(hcca, 256); + write32(reg+OHCI_HC_HCCA, virt_to_phys(hcca)); /* set periodicstart */ #define FIT (1<<31) @@ -567,13 +613,18 @@ void hcdi_irq(u32 reg) } } -void show_frame_no(u32 reg) +/* Before you access the HCCA structure in any way, call this to set the pointer correctly! */ +static void set_target_hcca(u32 reg) { - if(reg == OHCI0_REG_BASE) { - sync_before_read(&hcca_oh0, 256); - printf("***** frame_no: %d *****\n", LE(hcca_oh0.frame_no)); - } else if (reg == OHCI1_REG_BASE) { - sync_before_read(&hcca_oh1, 256); - printf("***** frame_no: %d *****\n", LE(hcca_oh1.frame_no)); + switch(reg) { + case OHCI0_REG_BASE: hcca = &hcca_oh0; break; + case OHCI1_REG_BASE: hcca = &hcca_oh1; break; } } + +void show_frame_no(u32 reg) +{ + set_target_hcca(reg); + sync_before_read(hcca, 256); + printf("***** frame_no: %d *****\n", LE(hcca->frame_no)); +}