intterupt transfers done right now. however, the keyboard driver behave
[ppcskel.git] / usb / host / ohci.c
index 6feff77f4f0915ac34160bc4d5c59e3c0153e0ca..f243bcad9f56c7f6040eccc5c599cbb3fc4b4424 100644 (file)
@@ -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()
 {
@@ -154,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;
 
-       write32(reg+OHCI_HC_CTRL_HEAD_ED, virt_to_phys(edhead));
+               case USB_BULK:
+                       write32(reg+OHCI_HC_BULK_HEAD_ED, virt_to_phys(edhead));
+               break;
+
+               case USB_ISOC:
+               break;
+       }
 
        /* sync it all */
        sync_after_write(edhead, sizeof(struct endpoint_descriptor));
@@ -183,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 */
@@ -281,16 +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;
        }
 
-out:
-       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;
 
@@ -320,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();
@@ -403,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)
@@ -558,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));
+}