Chameleon

Chameleon Svn Source Tree

Root/branches/JrCs/i386/libsaio/usb.c

1/*
2 * usb.c
3 *
4 *
5 * Created by mackerintel on 12/20/08.
6 * Copyright 2008 mackerintel. All rights reserved.
7 *
8 */
9
10#include "libsaio.h"
11#include "bootstruct.h"
12#include "pci.h"
13
14#ifndef DEBUG_USB
15#define DEBUG_USB 0
16#endif
17
18#if DEBUG_USB
19#define DBG(x...)printf(x)
20#else
21#define DBG(x...)
22#endif
23
24int ehci_acquire (pci_dt_t *pci_dev)
25{
26int j,k;
27
28uint32_tbase;
29uint8_teecp;
30uint8_tlegacy[8];
31
32bool isOwnershipConflict;
33bool alwaysHardBIOSReset;
34
35if (!getBoolForKey("EHCIhard", &alwaysHardBIOSReset, &bootInfo->bootConfig))
36alwaysHardBIOSReset = 1;
37
38pci_config_write16(pci_dev->dev.addr, 0x04, 0x0002);
39base = pci_config_read32(pci_dev->dev.addr, 0x10);
40
41verbose("EHCI controller [%04x:%04x] at %02x:%2x.%x DMA @%x\n",
42pci_dev->vendor_id, pci_dev->device_id,
43pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func,
44base);
45
46if (*((unsigned char*)base) < 0xc)
47{
48DBG("Config space too small: no legacy implementation\n");
49return 1;
50}
51eecp=*((unsigned char*)(base + 9));
52if (!eecp)
53{
54DBG("No extended capabilities: no legacy implementation\n");
55return 1;
56}
57
58DBG("eecp=%x\n",eecp);
59
60// bad way to do it
61//pci_conf_write(pci_dev->dev.addr, eecp, 4, 0x01000001);
62for (j = 0; j < 8; j++)
63{
64legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);
65DBG("%02x ",legacy[j]);
66}
67DBG("\n");
68
69//Real Job: based on orByte's AppleUSBEHCI.cpp
70//We try soft reset first - some systems hang on reboot with hard reset
71// Definitely needed during reboot on 10.4.6
72
73isOwnershipConflict = ((legacy[3] & 1 != 0) && (legacy[2] & 1 != 0));
74if (!alwaysHardBIOSReset && isOwnershipConflict)
75{
76DBG("EHCI - Ownership conflict - attempting soft reset ...\n");
77DBG("EHCI - toggle OS Ownership to 0\n");
78pci_config_write8(pci_dev->dev.addr, eecp + 3, 0);
79for (k = 0; k < 25; k++)
80{
81for (j = 0; j < 8; j++)
82legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);
83if (legacy[3] == 0)
84break;
85delay(10);
86}
87}
88
89DBG("Found USBLEGSUP_ID - value %x:%x - writing OSOwned\n", legacy[3],legacy[2]);
90pci_config_write8(pci_dev->dev.addr, eecp + 3, 1);
91
92// wait for kEHCI_USBLEGSUP_BIOSOwned bit to clear
93for (k = 0; k < 25; k++)
94{
95for (j = 0;j < 8; j++)
96legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);
97DBG ("%x:%x,",legacy[3],legacy[2]);
98if (legacy[2] == 0)
99break;
100delay(10);
101}
102
103for (j = 0;j < 8; j++)
104legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);
105isOwnershipConflict = ((legacy[2]) != 0);
106if (isOwnershipConflict)
107{
108// Soft reset has failed. Assume SMI being ignored
109// Hard reset
110// Force Clear BIOS BIT
111
112DBG("EHCI - Ownership conflict - attempting hard reset ...\n");
113DBG ("%x:%x\n",legacy[3],legacy[2]);
114DBG("EHCI - Force BIOS Ownership to 0\n");
115
116pci_config_write8(pci_dev->dev.addr, eecp + 2, 0);
117for (k = 0; k < 25; k++)
118{
119for (j = 0; j < 8; j++)
120legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);
121DBG ("%x:%x,",legacy[3],legacy[2]);
122
123if ((legacy[2]) == 0)
124break;
125delay(10);
126}
127// Disable further SMI events
128for (j = 4; j < 8; j++)
129pci_config_write8(pci_dev->dev.addr, eecp + j, 0);
130}
131
132for (j = 0; j < 8; j++)
133legacy[j] = pci_config_read8(pci_dev->dev.addr, eecp + j);
134
135DBG ("%x:%x\n",legacy[3],legacy[2]);
136
137// Final Ownership Resolution Check...
138if (legacy[2]&1)
139{
140DBG("EHCI controller unable to take control from BIOS\n");
141return 0;
142}
143
144DBG("EHCI Acquire OS Ownership done\n");
145return 1;
146}
147
148int uhci_reset (pci_dt_t *pci_dev)
149{
150uint32_t base, port_base;
151
152base = pci_config_read32(pci_dev->dev.addr, 0x20);
153port_base = (base >> 5) & 0x07ff;
154
155verbose("UHCI controller [%04x:%04x] at %02x:%2x.%x base %x(%x)\n",
156pci_dev->vendor_id, pci_dev->device_id,
157pci_dev->dev.bits.bus, pci_dev->dev.bits.dev, pci_dev->dev.bits.func,
158port_base, base);
159
160pci_config_write16(pci_dev->dev.addr, 0xc0, 0x8f00);
161
162outw (port_base, 0x0002);
163delay(10);
164outw (port_base+4,0);
165delay(10);
166outw (port_base,0);
167return 1;
168}
169

Archive Download this file

Revision: 21