Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define UHCI 0x00 // Universal Host Controller Interface. Supports USB1 and USB1.1.
- #define UHCI_REG_USBCMD 0x00
- #define UHCI_REG_USBSTS 0x02
- #define UHCI_REG_USBINTR 0x04
- #define UHCI_REG_FRNUM 0x06
- #define UHCI_REG_FRBASEADD 0x08
- #define UHCI_REG_SOFMOD 0x0C
- #define UHCI_REG_PORTBASE 0x10
- #define UHCI_USBLEGSUP 0xc0 /* legacy support */
- #define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
- #define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
- #define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */
- #define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */
- #define UHCI_USBCMD_GRESET 0x0004 /* Global Reset */
- #define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */
- #define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */
- #define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */
- #include <keypad.h>
- struct uhci_td {
- unsigned char T; // Termination (1: Link is not valid, 0: Link is valid).
- unsigned char QH; // Queue Head (1: Link is to a QH, 0: Link is to a TD).
- unsigned char Vf; // Depth/Breadth Select (1: Depth First, 0: Breadth First).
- unsigned int link; // 32-Bit Memory Address of next descriptor.
- unsigned short ActLen; // Actual Length.
- unsigned char status; // Status.
- unsigned char IOC; // Interrupt on Complete (1: Issue IOC after the current time frame).
- unsigned char ISO; // Isochronous Select (1: Isochronous TD, 0: Non-isochronous).
- unsigned char LS; // Low Speed Drive (1: Low Speed, 0: Full Speed).
- unsigned char C_ERR; // Error Counter.
- unsigned char SPD; // Short Packet Detect (1: Enable, 0: Disable).
- unsigned char PID; // Packet Identification (0x69: IN, 0xE1: OUT, 0x2D: Setup).
- unsigned char device; // Device Address.
- unsigned char EndPt; // End Point.
- unsigned char D; // Data Toggle Synchronization.
- unsigned short MaxLen; // Maximum Length.
- unsigned int buffer; // Buffer Pointer.
- };
- struct sixteenbytelen {
- unsigned int lng[4];
- };
- struct eightbytelen {
- unsigned int lng[2];
- };
- unsigned int *uhci_frlst; // Frame List.
- sixteenbytelen *uhci_tdlst; // TD List.
- eightbytelen *uhci_qhlst; // QH List.
- unsigned int uhci_ports; // Number of Ports.
- unsigned char uhci_buffer[0x200];
- unsigned short ds;
- void uhci_set_td(uhci_td td, unsigned int index) {
- uhci_tdlst[index].lng[0] = (td.T << 0)|
- (td.QH << 1)|
- (td.Vf << 2)|
- (td.link << 0);
- uhci_tdlst[index].lng[1] = (td.ActLen << 0)|
- (td.status << 16)|
- (td.IOC << 24)|
- (td.ISO << 25)|
- (td.LS << 26)|
- (td.C_ERR << 27)|
- (td.SPD << 29);
- uhci_tdlst[index].lng[2] = (td.PID << 0)|
- (td.device << 8)|
- (td.EndPt << 15)|
- (td.D << 19)|
- (td.MaxLen << 21);
- uhci_tdlst[index].lng[3] = (td.buffer << 0);
- }
- // Control Transfer:
- // ---------------------->
- // 1- Setup Stage [1 Transaction]:-
- // Token PID: SETUP
- // DATA PID: DATA0
- // Handshake:
- // 2- Data Stage [0 or more transactions]:
- // Token PID: IN/OUT
- // DATA PID: DATA0/DATA1
- // Handshake:
- // 3- Status Stage [1 Transaction]:
- // Token PID: OUT/IN
- // DATA PID: DATA1
- // Handshake:
- // PIDs of Token Packet
- #define UHCI_PID_SETUP 0x2D
- #define UHCI_PID_IN 0x69
- #define UHCI_PID_OUT 0xE1
- // PIDs of Data Packet
- #define UHCI_DATA0 0x00
- #define UHCI_DATA1 0x01
- // Hub Requests:
- #define CLEAR_FEATURE 0x01
- #define CLEAR_TT_BUFFER 0x08
- #define GET_DESCRIPTOR 0x06
- #define GET_STATUS 0x00
- #define RESET_TT 0x09
- #define SET_DESCRIPTOR 0x07
- #define SET_FEATURE 0x03
- #define GET_TT_STATE 0x0A
- #define STOP_TT 0x0B
- unsigned char uhci_root_hub_control_transfer(unsigned char bmRequestType, unsigned char bRequest, unsigned short wValue,
- unsigned short wIndex, unsigned short wLength, unsigned int buf) {
- // This is a special function for the root hub's control transfers
- switch (bRequest) {
- case CLEAR_FEATURE: if (bmRequestType == 0x20) {
- // ClearHubFeature
- } else if (bmRequestType == 0x23) {
- // ClearPortFeature
- }
- break;
- case CLEAR_TT_BUFFER: if (bmRequestType == 0x23) {
- // ClearTTBuffer
- }
- break;
- case GET_DESCRIPTOR: if (bmRequestType == 0xA0) {
- // GetHubDescriptor
- if (wValue == 0x2900) {
- if (wLength > 0) kwriteb(7, buf + 0);
- if (wLength > 1) kwriteb(0x29, buf + 1);
- if (wLength > 2) kwriteb(uhci_ports, buf + 2);
- if (wLength > 3) kwriteb(0, buf + 3);
- if (wLength > 4) kwriteb(0, buf + 4);
- if (wLength > 5) kwriteb(0, buf + 5);
- if (wLength > 6) kwriteb(0, buf + 6);
- }
- }
- break;
- case GET_STATUS: if (bmRequestType == 0xA0) {
- // GetHubStatus
- } else if (bmRequestType == 0xA3) {
- // GetPortStatus
- unsigned short PORTSC = usbio.readregw(((wIndex - 1) * 2) + 0x10);
- unsigned char CCS = (PORTSC>> 0) & 1; // Current Connect Status
- unsigned char CSC = (PORTSC>> 1) & 1; // Connect Status Change
- unsigned char PE = (PORTSC>> 2) & 1; // Port Enable
- unsigned char PEC = (PORTSC>> 3) & 1; // Port Enable Change
- unsigned char RD = (PORTSC>> 6) & 1; // Resume Detect
- unsigned char LS = (PORTSC>> 8) & 1; // Low Speed Device
- unsigned char PR = (PORTSC>> 9) & 1; // Port Reset
- unsigned char PS = (PORTSC>>12) & 1; // Port Suspend
- unsigned char PP = 1; // Port Power
- if (wLength > 0) kwriteb((CCS<<0) + (PE <<1) + (PS <<2) + (PR <<4), buf + 0);
- if (wLength > 1) kwriteb((PP <<0) + (LS <<1), buf + 1);
- if (wLength > 2) kwriteb((CSC<<0) + (PEC<<1) + (RD <<2), buf + 2);
- if (wLength > 3) kwriteb(0, buf + 3);
- }
- break;
- case RESET_TT: if (bmRequestType == 0x23) {
- // ResetTT
- }
- break;
- case SET_DESCRIPTOR: if (bmRequestType == 0x20) {
- // SetHubDescriptor
- }
- break;
- case SET_FEATURE: if (bmRequestType == 0x20) {
- // SetHubFeature
- } else if (bmRequestType == 0x23) {
- // SetPortFeature
- unsigned int PORTSC = ((wIndex - 1) * 2) + 0x10;
- if (wValue == 4) {
- usbio.writeregw(usbio.readregw(PORTSC) | 0x0200, PORTSC); // Reset
- while (!(usbio.readregw(PORTSC) & 0x0200)); // Wait until Bit 9 is set.
- sleep(100);
- usbio.writeregw(usbio.readregw(PORTSC) & 0xFDFF, PORTSC); // Stop Reset
- while ( (usbio.readregw(PORTSC) & 0x0200)); // Wait until Bit 9 is cleared.
- sleep(100);
- usbio.writeregw(usbio.readregw(PORTSC) | 0x0004, PORTSC); // Enable the Port
- while (!(usbio.readregw(PORTSC) & 0x0004)); // Wait until Bit 4 is set.
- }
- }
- break;
- case GET_TT_STATE: if (bmRequestType == 0xA3) {
- // GetTTState
- }
- break;
- case STOP_TT: if (bmRequestType == 0x23) {
- // StopTT
- }
- break;
- default: break;
- }
- return 0;
- }
- unsigned char uhci_control_transfer(unsigned char device, unsigned char bmRequestType, unsigned char bRequest, unsigned short wValue,
- unsigned short wIndex, unsigned short wLength, unsigned int buf) {
- if (device == 128) return uhci_root_hub_control_transfer(bmRequestType, bRequest, wValue, wIndex, wLength, buf);
- static uhci_td td;
- unsigned int i, status;
- unsigned char speed = devices[device].speed; // 0: Low Speed, 1: Full Speed.
- unsigned int Max_Packet_Size = devices[device].Max_Packet; // Max Packet Size for Endpoint Zero.
- unsigned int tds = ((wLength + Max_Packet_Size - 1) / Max_Packet_Size) + 2; // Number of needed TDs.
- unsigned char data_stage_tokens_pid = (bmRequestType & 0x80) ? UHCI_PID_IN : UHCI_PID_OUT;
- unsigned char status_stage_token_pid;
- if (tds == 2)
- status_stage_token_pid = UHCI_PID_IN;
- else
- status_stage_token_pid = (data_stage_tokens_pid == UHCI_PID_IN) ? UHCI_PID_OUT : UHCI_PID_IN;
- td.IOC = 0;
- td.ISO = 0;
- td.LS = 1-speed; // 1: Low Speed, 0: Full Speed.
- td.SPD = 0;
- td.ActLen = 0;
- td.C_ERR = 0;
- td.device = device;
- td.EndPt = 0; // Control Transfers always use Endpoint Zero.
- // I: Setup Stage:
- // -------------------
- // This Stage is done by sending 1 Transaction to the device containing the following packets:
- // A: Token Packet: With a PID of SETUP.
- // B: Data Packet: With a PID of DATA0. This Packet contains Setup Information.
- // C: Handshake Packet: This is sent by the device and tells us the results.
- unsigned static char setup_info[8];
- setup_info[0] = bmRequestType;
- setup_info[1] = bRequest;
- setup_info[2] = (wValue & 0x00FF)>>0;
- setup_info[3] = (wValue & 0xFF00)>>8;
- setup_info[4] = (wIndex & 0x00FF)>>0;
- setup_info[5] = (wIndex & 0xFF00)>>8;
- setup_info[6] = (wLength & 0x00FF)>>0;
- setup_info[7] = (wLength & 0xFF00)>>8;
- td.T = 0; // Link is valid
- td.QH = 0; // Link refers to a TD.
- td.Vf = 1; // Depth first.
- td.link = krnl_get_selector_base(ds) + ((int) &uhci_tdlst[2]); // Next TD.
- td.PID = UHCI_PID_SETUP; // Token Packet PID.
- td.D = UHCI_DATA0; // Data Packet PID.
- td.status = 0x80; // Handshake Packet PID will be set here.
- td.buffer = krnl_get_selector_base(ds) + ((int) setup_info);
- td.MaxLen = 7;
- uhci_set_td(td, 1);
- // II: Data Stage:
- // -----------------
- // This stage is optional, a transaction or more is/are sent in this stage containing the following packets:
- // A: Token Packet: With a PID of IN or OUT.
- // B: Data Packet: With a PID of DATA0 or DATA1, this packet is sent by the device if the token is OUT.
- // C: Handshake Packet: From the host or from the device.
- for (i = 2; i < tds; i++) {
- td.T = 0; // Link is valid
- td.QH = 0; // Link refers to a TD.
- td.Vf = 1; // Depth first.
- td.link = krnl_get_selector_base(ds) + ((int) &uhci_tdlst[i + 1]); // Next TD.
- td.PID = data_stage_tokens_pid; // Token PID.
- td.D = 1 - td.D; // Data PID.
- td.status = 0x80; // Handshake PID will be set here.
- td.buffer = buf;
- td.MaxLen = ((Max_Packet_Size < wLength) ? Max_Packet_Size : wLength) - 1;
- uhci_set_td(td, i);
- wLength -= Max_Packet_Size; // Calculate the size of the rest data.
- buf += Max_Packet_Size; // Update the pointer.
- }
- // III: Status Stage:
- // ----------------------
- // This stage doesn't send data, but it sends an IN or an OUT Token then receives a handshake:
- // Token Packet: With PID of OUT [If Data Stage's tokens are IN] and vice versa.
- // Handshake Packet: from the device or the Host, its PID confirming the success of the transfer.
- td.T = 1; // Link is not valid
- td.QH = 0;
- td.Vf = 0;
- td.link = 0;
- td.PID = status_stage_token_pid; // Token Packet PID.
- td.D = UHCI_DATA1; // Data Packet PID of a non existent Packet.
- td.status = 0x80; // Handshake will be set here.
- td.buffer = 0;
- td.MaxLen = 0x7FF; // No Data Packet.
- uhci_set_td(td, i);
- // Do the transfer:
- uhci_qhlst[0].lng[1] = ((unsigned int) &uhci_tdlst[1] + krnl_get_selector_base(ds));
- for (i = 1; i <= tds; i++) {
- //printk(" I: %x\n", i);
- while ((status = ((uhci_tdlst[i].lng[1] & 0x00FF0000)>>16)) & 0x80);
- if (status) break;
- }
- uhci_qhlst[0].lng[1] = 0x00000001;
- return status;
- }
- unsigned char uhci_interrupt_transfer (unsigned char device, unsigned char EndPt, unsigned int buffer) {
- if (device == 128) return 0;
- unsigned int i, j, status;
- for (i = 0; i < 10; i++) {
- for (j = 0; j < 16; j++)
- if ((devices[device].interfaces[i].endpoints[j].address & 0xF) == (EndPt & 0xF)) break;
- if (j != 16) break;
- }
- if (i == 10) return 1;
- EndPt = devices[device].interfaces[i].endpoints[j].address;
- static uhci_td td;
- unsigned char speed = devices[device].speed;
- unsigned char token_pid = (EndPt & 0x80) ? UHCI_PID_IN : UHCI_PID_OUT;
- unsigned char data_pid = devices[device].interfaces[i].endpoints[j].Data_Toggle;
- unsigned char Max_Packet = devices[device].interfaces[i].endpoints[j].Max_Packet;
- td.T = 1; // Link is not valid
- td.QH = 0;
- td.Vf = 0;
- td.link = 0;
- td.IOC = 0;
- td.ISO = 0;
- td.LS = 1-speed; // 1: Low Speed, 0: Full Speed.
- td.SPD = 0;
- td.ActLen = 0;
- td.C_ERR = 0;
- td.device = device;
- td.EndPt = EndPt & 0xF;
- td.PID = token_pid; // Token Packet PID.
- td.D = data_pid; // Data Packet PID.
- td.status = 0x80; // Handshake Packet PID will be set here.
- td.buffer = buffer;
- td.MaxLen = Max_Packet - 1;
- uhci_set_td(td, 1);
- // Do the transfer:
- uhci_qhlst[0].lng[1] = ((unsigned int) &uhci_tdlst[1] + krnl_get_selector_base(ds));
- while ((status = ((uhci_tdlst[1].lng[1] & 0x00FF0000)>>16)) & 0x80);
- if (status) printk(" Error: %x\n", status);
- uhci_qhlst[0].lng[1] = 0x00000001;
- return status;
- }
- unsigned char uhci_enumerate(unsigned char speed) {
- // This function is called when a new device is found. Any new device is normally in the default state.
- unsigned int buf = krnl_get_selector_base(ds) + (int) uhci_buffer;
- unsigned int i, j, k;
- unsigned int config_size, string_size;
- unsigned char iManufacturer, iProduct, iSerial, iConfiguration;
- // I: Clear the buffer
- // -----------------------
- for (i = 0; i < 0x200; i++) uhci_buffer[i] = 0;
- // II: Search for an empty device:
- // -------------------------------
- for (i = 1; i < 128; i++) if (!devices[i].Max_Packet) break;
- if (i == 128) return 1;
- // III: Set Necessary & Default Device Information:
- // --------------------------------------------------
- devices[0].speed = devices[i].speed = speed;
- devices[0].Max_Packet = devices[i].Max_Packet = 8; // The lowest Max Packet Size for EndPoint Zero.
- // IV: Set Address:
- // -------------------
- // The variable (i) is containing the new address of the device.
- if (uhci_control_transfer(0, 0x00, 0x05, i, 0x0000, 0x0000, 0x00)) {
- printk(" Error...\n");
- return 0;
- }
- // V: Get Device Descriptor:
- // -----------------------------
- uhci_control_transfer(i, 0x80, 0x06, 0x0100, 0x0000, 8, buf); // First 8 bytes of Device Descriptor.
- devices[i].Max_Packet = uhci_buffer[0x07]; // Get Max Packet Size for EndPoint Zero.
- uhci_control_transfer(i, 0x80, 0x06, 0x0100, 0x0000, 18, buf); // Read all of the Device Descriptor.
- // VI: Set Device Info:
- // ---------------------------
- devices[i].specs = (uhci_buffer[0x03]<<8) + uhci_buffer[0x02];
- devices[i].cls = (uhci_buffer[0x04]<<16) + (uhci_buffer[0x05]<<8) + uhci_buffer[0x06];
- iManufacturer = uhci_buffer[0x0E];
- iProduct = uhci_buffer[0x0F];
- iSerial = uhci_buffer[0x10];
- // VII: Get Config Descriptor & Enter Configured State:
- // --------------------------------------------------------
- uhci_control_transfer(i, 0x80, 0x06, 0x0100, 0x0000, 18, buf);
- uhci_control_transfer(i, 0x80, 0x06, 0x0200, 0, 8, buf); // Read First 8 Bytes of the Config Descriptor.
- config_size = (uhci_buffer[0x3]<<8) + uhci_buffer[0x2];
- uhci_control_transfer(i, 0x00, 0x09, uhci_buffer[0x5],0, 0, 0); // SET CONFIGURATION
- uhci_control_transfer(i, 0x80, 0x06, 0x0200, 0, config_size, buf); // Read the full descriptor.
- iConfiguration = uhci_buffer[0x6];
- // IIX: Analyse Config Desriptor:
- // -------------------------------
- unsigned int ptr = 0;
- unsigned char interface = 0xFF;
- unsigned char endpoint = 0;
- while (ptr < config_size) {
- // Ptr Refers to the start of a sub-descriptor;
- if (uhci_buffer[ptr + 1] == 4 && uhci_buffer[ptr + 2] != interface) {
- // a Non-Alternative Interface Descriptor
- interface = uhci_buffer[ptr + 2];
- endpoint = 0; // Start a new endpoints list.
- if (interface >= 10) break; // That's enough! we don't support more than 10 interfaces for a device.
- // Set Class Code:
- devices[i].interfaces[interface].cls = (uhci_buffer[ptr + 5]<<16) +
- (uhci_buffer[ptr + 6]<<8) + uhci_buffer[ptr + 7];
- if (!devices[i].interfaces[interface].cls) devices[i].interfaces[interface].cls = devices[i].cls;
- // String Desribes the Interface:
- devices[i].interfaces[interface].string[0] = uhci_buffer[ptr + 8];
- }
- if (uhci_buffer[ptr + 1] == 5) {
- // an Endpoint Descriptor
- // It is sure that the variable "interface" is reset before coming here...
- devices[i].interfaces[interface].endpoints[endpoint].address = uhci_buffer[ptr + 2];
- devices[i].interfaces[interface].endpoints[endpoint].attribs = uhci_buffer[ptr + 3];
- devices[i].interfaces[interface].endpoints[endpoint].Max_Packet =
- (uhci_buffer[ptr + 5]<<8) + uhci_buffer[ptr + 4];
- devices[i].interfaces[interface].endpoints[endpoint].interval = uhci_buffer[ptr + 6];
- endpoint++;
- }
- ptr += uhci_buffer[ptr]; // Next Descriptor
- }
- // IX: Get Strings:
- // ---------------------
- if (iManufacturer) {
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iManufacturer, 0x0409, 2, buf);
- if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iManufacturer, 0x0409, string_size, buf);
- k = 0;
- for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].manufacturer[k++] = uhci_buffer[j];
- }
- if (iProduct) {
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iProduct, 0x0409, 2, buf);
- if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iProduct, 0x0409, string_size, buf);
- k = 0;
- for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].product[k++] = uhci_buffer[j];
- }
- if (iSerial) {
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iSerial, 0x0409, 2, buf);
- if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iSerial, 0x0409, string_size, buf);
- k = 0;
- for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].serial[k++] = uhci_buffer[j];
- }
- if (iConfiguration) {
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iConfiguration, 0x0409, 2, buf);
- if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iConfiguration, 0x0409, string_size, buf);
- k = 0;
- for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].configuration[k++] = uhci_buffer[j];
- }
- for (unsigned int x = 0; devices[i].interfaces[x].cls; x++) {
- unsigned int str;
- if (!(str = devices[i].interfaces[x].string[0])) continue;
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + str, 0x0409, 2, buf);
- if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
- uhci_control_transfer(i, 0x80, 0x06, 0x0300 + str, 0x0409, string_size, buf);
- k = 0;
- for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].interfaces[x].string[k++] = uhci_buffer[j];
- }
- // X: Register device(s):
- // ---------------------------
- // Register Each Interface of the device in Device Manager
- for(j = 0; devices[i].interfaces[j].cls; j++) {
- unsigned static char id;
- unsigned static short sel1, sel2;
- unsigned static int off;
- krnl_devman_add(0xFFFF, 0x02000000 | devices[i].interfaces[j].cls, &id, &sel1, &sel2, &off);
- devices[i].interfaces[j].devid = id;
- unsigned static int packet[32];
- packet[0] = id; // Device ID.
- packet[1] = 1; // Initialization Function
- packet[2] = devid; // The ID of this hc device driver.
- packet[3] = id; // The ID of the device.
- packet[4] = i; // The Device Address of the hub. 128 means this is the root hub.
- packet[5] = j; // The ID of the interface.
- krnl_taskman_add_service(1, packet); // Execute this after returning from this function (uhci_init).
- }
- printk("\n");
- printk(" Manufacturer: %s\n", devices[i].manufacturer);
- printk(" Product: %s\n", devices[i].product);
- printk(" Serial: %s\n", devices[i].serial);
- printk(" Configuration: %s\n", devices[i].configuration);
- printk(" Device: %d, Class: %x, Speed: %x, EndPt0 Max Packet: %x\n",i,devices[i].cls,devices[i].speed,devices[i].Max_Packet);
- for(j = 0; devices[i].interfaces[j].cls; j++) {
- printk(" Interface: %d, Class: %x, Title: %s\n", j, devices[i].interfaces[j].cls, devices[i].interfaces[j].string);
- for (k = 0; devices[i].interfaces[j].endpoints[k].Max_Packet; k++)
- printk(" - Endpoint %d, Address: %x, Attribs: %x, Max Packet: %d\n", k,
- devices[i].interfaces[j].endpoints[k].address,
- devices[i].interfaces[j].endpoints[k].attribs,
- devices[i].interfaces[j].endpoints[k].Max_Packet);
- }
- printk("\n");
- getc();
- return i;
- }
- void uhci_init() {
- asm("movw %%ds, %%ax":"=a"(ds));
- unsigned int i, ehci;
- printk(" Initializing UHCI USB Device Driver ...\n");
- // I: Initialize UHCI Descriptors:
- // ------------------------------------
- // 1- Pointers:
- uhci_frlst = (unsigned int *)((unsigned int)(buffer + 0x0FFF) & 0xFFFFF000);
- uhci_qhlst = (eightbytelen *)((unsigned int) uhci_frlst + 0x1000);
- uhci_tdlst = (sixteenbytelen *)((unsigned int) uhci_qhlst + 0x0010);
- // 2- TDs:
- uhci_tdlst[0].lng[0] = 0x00000001;
- uhci_tdlst[0].lng[1] = 0x00000000;
- uhci_tdlst[0].lng[2] = 0x00000000;
- uhci_tdlst[0].lng[3] = 0x00000000;
- // 3- QHs:
- uhci_qhlst[0].lng[0] = ((unsigned int) &uhci_qhlst[1] + krnl_get_selector_base(ds)) | 0x00000002;
- uhci_qhlst[0].lng[1] = 0x00000001;
- uhci_qhlst[1].lng[0] = 0x00000001;
- uhci_qhlst[1].lng[1] = ((unsigned int) &uhci_tdlst[0] + krnl_get_selector_base(ds)) | 0x00000000;
- // 4- Frame List:
- for (i = 0; i < 0x400; i++)
- uhci_frlst[i] = ((unsigned int) &uhci_qhlst[0] + krnl_get_selector_base(ds)) | 0x00000002;
- // II: Setup PCI Registers:
- // ----------------------------
- // Search for the EHCI function in the bus\device...
- for (ehci = 0; ehci < 8; ehci++)
- if ((pci_readl(bus, dev, ehci, 8)>>8) == 0x0C0320) break;
- if (ehci < 8) {
- static iospace eio;
- unsigned int EECP, CAPID, CAPID_off;
- // There is a companion EHCI in the device, lets get its I/O or memory Base.
- for (i = 0x10; i < 0x28; i += 4)
- if (base = eio.configbase(pci_readl(bus, dev, ehci, i)))
- break;
- // The register [USBBASE + 8] is a dword. The second byte of it [EHCI Extended Capabilities Pointer]
- // refers to the first PCI USBLEGSUP Register.
- EECP = (eio.readregl(8) & 0x0000FF00) >> 8;
- if (EECP >= 0x40) {
- // The lowest bit of Byte 2 [Bit 16]: HCBIOSSEM [Host Controller BIOS Semaphore].
- // The lowest bit of Byte 3 [Bit 24]: HCOSSEM [Host Controller OS Semaphore].
- pci_writeb(pci_readb(bus, dev, ehci, EECP + 3) | 1, bus, dev, ehci, EECP + 3); // Set HCOSSEM
- // Wait for BIOS to update HCBIOSSEM, if timeout occures, we will clear the word [EECP + 4].
- timeout = tick_count() + 100; // 1sec.
- while ((pci_readb(bus, dev, ehci, EECP + 2) & 1) and (tick_count() < timeout));
- if (pci_readb(bus, dev, ehci, EECP + 2) & 1) pci_writew(0, bus, dev, ehci, EECP + 4);
- // Wait for HCOSSEM to be set.
- timeout = tick_count() + 100; // 1sec.
- while ((!(pci_readb(bus, dev, ehci, EECP + 3) & 1)) and (tick_count() < timeout));
- // After taking control over EHCI, delay for 10ms...
- sleep(10);
- // The lowest byte of this PCI register is called "Capability ID". it indicates whether another
- // PCI Register [EECP + 4] exists or not. Writing 0 to the word [EECP + 4] disables SMIs.
- if (pci_readb(bus, dev, ehci, EECP + 0) == 0x01)
- pci_writew(0, bus, dev, ehci, EECP + 4);
- // Now We have the full control...
- EECP = pci_readb(bus, dev, func, EECP + 1); // Next USBLEGSUP Register, if EECP = 0, the loop will stop.
- }
- // The lowest byte of the register [USBBASE + 0] is a dword contains the base address of Operational registers.
- // The first byte of the dword register at [OP + 0x40] of these operational register will be set to Zero, in order
- // to clear CF. clearing CF will make EHCI routes all its ports to UHCI.
- eio.writeregb(0, eio.readregb(0) + 0x40);
- }
- // Turn off UHCI PIRQ and disable SMI. this shall turn off BIOS's legacy support.
- pci_writew(0x8F00, bus, dev, func, 0xC0);
- // III: Initialize UHCI:
- // ------------------------
- // 1- Halt the HC:
- usbio.writeregw(0xFFFF, UHCI_REG_USBSTS); // Clear Status Register.
- unsigned int cmd = usbio.readregw(UHCI_REG_USBCMD);
- if (cmd & 1) {
- // the HC is running, we have to stop it.
- cmd = cmd & 0xFFFE;
- usbio.writeregw(cmd, UHCI_REG_USBCMD);
- while (!(usbio.readregw(UHCI_REG_USBSTS) & 0x0020));
- }
- // 2- Do a HCReset:
- cmd &= 2;
- usbio.writeregw(cmd, UHCI_REG_USBCMD);
- while ((cmd = usbio.readregw(UHCI_REG_USBCMD)) & 2);
- // 3- Do a GReset:
- cmd &= 4;
- usbio.writeregw(cmd, UHCI_REG_USBCMD);
- sleep(15); // 1.5 Times is the minimum.
- cmd &= 0xFFF8; // Make Sure the least three bits are clear. [RUN, HCRESET, and GRESET].
- usbio.writeregw(cmd, UHCI_REG_USBCMD);
- // 4- Make Devices Ready or Bus Activity:
- cmd |= 0x0018; // Enter Global Suspend Mode & Force Global Resume.
- usbio.writeregw(cmd, UHCI_REG_USBCMD);
- sleep(30); // In this period, Global Resume Signals are active.
- cmd = 0; // Clear Command Register.
- usbio.writeregw(cmd, UHCI_REG_USBCMD);
- while (usbio.readregw(UHCI_REG_USBCMD)); // Wait Until Cleared.
- // 5- Setup Registers:
- usbio.writeregw(0xFFFF, UHCI_REG_USBSTS);// Clear Status Register.
- usbio.writeregw(0x00, UHCI_REG_USBINTR); // No Interrupts
- usbio.writeregw(0x00, UHCI_REG_FRNUM); // Start from Frame Number 0.
- usbio.writeregl((unsigned int) uhci_frlst + krnl_get_selector_base(ds), UHCI_REG_FRBASEADD);
- usbio.writeregb(64, UHCI_REG_SOFMOD); // 64+11936=12000. (1ms for each frame).
- usbio.writeregw(1, UHCI_REG_USBCMD); // Change HC State to start.
- // IV: Initialize a Root Hub Driver:
- // ------------------------------------
- // 1- Set Information
- devices[128].speed = 1; // Full-Speed.
- devices[128].specs = 0x0101; // USB1.1.
- devices[128].cls = 0x090000; // Hub
- devices[128].Max_Packet = 8; // Max Packet For EndPt Zero.
- copystr("USB Root Hub", devices[128].product);
- devices[128].interfaces[0].cls = 0x090000; // Hub;
- devices[128].interfaces[0].endpoints[0].address = 0x81; // EndPt1 - IN
- devices[128].interfaces[0].endpoints[0].attribs = 0x03; // Interrupt
- devices[128].interfaces[0].endpoints[0].Max_Packet = 0x02; // Max Packet Size;
- devices[128].interfaces[0].endpoints[0].interval = 0x00; // Interval;
- // 2- Get the number of root ports:
- for (i = 0x10; (usbio.readregw(i) != 0xFFFF) && (usbio.readregw(i) & 0x0080) && (i < 0x32); i+=2);
- if (i == 0x30) i == 0x14;
- uhci_ports = (i - 0x10) / 2;
- // 3- Register a device driver for it:
- unsigned static char id;
- unsigned static short sel1, sel2;
- unsigned static int off;
- krnl_devman_add(0xFFFF, 0x02090000, &id, &sel1, &sel2, &off);
- devices[128].interfaces[0].devid = id;
- // 4- Initialize the root hub device driver:
- unsigned static int packet[32];
- packet[0] = id; // Device ID.
- packet[1] = 1; // Initialization Function
- packet[2] = devid; // The ID of this hc device driver.
- packet[3] = id; // The ID of the device.
- packet[4] = 128; // The Device Address of the hub. 128 means this is the root hub.
- packet[5] = 0; // The ID of the interface.
- krnl_taskman_add_service(1, packet); // Execute this after returning from this function (uhci_init).
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement