2 Copyright (C) 2006 by Michal Schulz
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include <aros/symbolsets.h>
23 #include <exec/types.h>
28 #include <hidd/hidd.h>
35 #include <proto/exec.h>
36 #include <proto/oop.h>
37 #include <aros/debug.h>
42 #define SD(x) (&LIBBASE->sd)
45 * usb_delay() stops waits for specified amount of miliseconds. It uses the timerequest
46 * of specified USB device. No pre-allocation of signals is required.
48 static void USBDelay(struct timerequest
*tr
, uint32_t msec
)
50 /* Allocate a signal within this task context */
51 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= AllocSignal(-1);
52 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= FindTask(NULL
);
54 /* Specify the request */
55 tr
->tr_node
.io_Command
= TR_ADDREQUEST
;
56 tr
->tr_time
.tv_secs
= msec
/ 1000;
57 tr
->tr_time
.tv_micro
= 1000 * (msec
% 1000);
60 DoIO((struct IORequest
*)tr
);
62 /* The signal is not needed anymore */
63 FreeSignal(tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
);
64 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigTask
= NULL
;
68 static struct timerequest
*USBCreateTimer()
70 struct timerequest
*tr
= NULL
;
71 struct MsgPort
*mp
= NULL
;
76 tr
= (struct timerequest
*)CreateIORequest(mp
, sizeof(struct timerequest
));
79 FreeSignal(mp
->mp_SigBit
);
80 if (!OpenDevice((STRPTR
)"timer.device", UNIT_MICROHZ
, (struct IORequest
*)tr
, 0))
83 DeleteIORequest((struct IORequest
*)tr
);
84 mp
->mp_SigBit
= AllocSignal(-1);
92 static void USBDeleteTimer(struct timerequest
*tr
)
96 tr
->tr_node
.io_Message
.mn_ReplyPort
->mp_SigBit
= AllocSignal(-1);
97 CloseDevice((struct IORequest
*)tr
);
98 DeleteMsgPort(tr
->tr_node
.io_Message
.mn_ReplyPort
);
99 DeleteIORequest((struct IORequest
*)tr
);
104 AROS_UFH3(void, Enumerator
,
105 AROS_UFHA(struct Hook
*, hook
, A0
),
106 AROS_UFHA(OOP_Object
*, pciDevice
, A2
),
107 AROS_UFHA(APTR
, message
, A1
))
113 if (counter
== MAX_DEVS
)
116 LIBBASETYPE
*LIBBASE
= (LIBBASETYPE
*)hook
->h_Data
;
118 struct TagItem attrs
[] = {
119 { aHidd_PCIDevice_isIO
, TRUE
},
120 { aHidd_PCIDevice_isMaster
, TRUE
},
124 OOP_SetAttrs(pciDevice
, (struct TagItem
*)attrs
);
125 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Base4
, &LIBBASE
->sd
.iobase
[counter
]);
126 OOP_GetAttr(pciDevice
, aHidd_PCIDevice_Driver
, (APTR
)&LIBBASE
->sd
.uhciPCIDriver
[counter
]);
127 LIBBASE
->sd
.uhciDevice
[counter
] = pciDevice
;
129 D(bug("[UHCI] Device %d @ %08x with IO @ %08x\n", counter
, pciDevice
, LIBBASE
->sd
.iobase
[counter
]));
131 D(bug("[UHCI] Performing full reset. Hopefull legacy USB will do it'S handoff at this time.\n"));
132 HIDD_PCIDevice_WriteConfigWord(pciDevice
, PCI_LEGSUP
, 0x8f00);
134 outw(UHCI_CMD_HCRESET
, LIBBASE
->sd
.iobase
[counter
] + UHCI_CMD
);
135 struct timerequest
*tr
= USBCreateTimer();
138 if (inw((uint16_t *)(LIBBASE
->sd
.iobase
[counter
] + UHCI_CMD
)) & UHCI_CMD_HCRESET
)
139 D(bug("[UHCI] Wrrr. Reset not yet completed\n"));
141 outw(0, LIBBASE
->sd
.iobase
[counter
] + UHCI_INTR
);
142 outw(0, LIBBASE
->sd
.iobase
[counter
] + UHCI_CMD
);
145 D(bug("[UHCI] 0xc0: %04x\n", HIDD_PCIDevice_ReadConfigWord(pciDevice
, 0xc0)));
147 LIBBASE
->sd
.num_devices
= ++counter
;
152 static int UHCI_Init(LIBBASETYPEPTR LIBBASE
)
154 D(bug("[UHCI] UHCI_Init()\n"));
156 LIBBASE
->sd
.usb
= OOP_NewObject(NULL
, (STRPTR
)CLID_Hidd_USB
, NULL
);
158 if (!LIBBASE
->sd
.usb
)
160 bug("[UHCI] Cannot create the instance of base USB class\n");
164 if ((LIBBASE
->sd
.pci
=OOP_NewObject(NULL
, (STRPTR
)IID_Hidd_PCI
, NULL
)))
166 struct TagItem tags
[] = {
167 { tHidd_PCI_Class
, PCI_BASE_CLASS_SERIAL
},
168 { tHidd_PCI_SubClass
, PCI_SUB_CLASS_USB
},
169 { tHidd_PCI_Interface
, PCI_INTERFACE_UHCI
},
173 struct OOP_ABDescr attrbases
[] = {
174 { (STRPTR
)IID_Hidd
, &HiddAttrBase
},
175 { (STRPTR
)IID_Hidd_PCIDevice
, &HiddPCIDeviceAttrBase
},
176 { (STRPTR
)IID_Hidd_USBDevice
, &HiddUSBDeviceAttrBase
},
177 { (STRPTR
)IID_Hidd_USBHub
, &HiddUSBHubAttrBase
},
178 { (STRPTR
)IID_Hidd_USBDrv
, &HiddUSBDrvAttrBase
},
182 struct Hook FindHook
= {
183 h_Entry
: (IPTR (*)())Enumerator
,
187 NEWLIST(&LIBBASE
->sd
.td_list
);
188 InitSemaphore(&LIBBASE
->sd
.global_lock
);
190 OOP_ObtainAttrBases(attrbases
);
192 D(bug("[UHCI] Searching for UHCI devices...\n"));
194 HIDD_PCI_EnumDevices(LIBBASE
->sd
.pci
, &FindHook
, (struct TagItem
*)&tags
);
196 D(bug("[UHCI] Done. UHCI devices found: %d\n", LIBBASE
->sd
.num_devices
));
198 if (LIBBASE
->sd
.num_devices
> 0)
200 LIBBASE
->sd
.MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
202 if (LIBBASE
->sd
.MemPool
)
210 static int UHCI_Expunge(LIBBASETYPEPTR LIBBASE
)
212 struct OOP_ABDescr attrbases
[] = {
213 { (STRPTR
)IID_Hidd
, &HiddAttrBase
},
214 { (STRPTR
)IID_Hidd_PCIDevice
, &HiddPCIDeviceAttrBase
},
215 { (STRPTR
)IID_Hidd_USBDevice
, &HiddUSBDeviceAttrBase
},
216 { (STRPTR
)IID_Hidd_USBHub
, &HiddUSBHubAttrBase
},
217 { (STRPTR
)IID_Hidd_USBDrv
, &HiddUSBDrvAttrBase
},
221 OOP_ReleaseAttrBases(attrbases
);
226 ADD2INITLIB(UHCI_Init
, 0)
227 ADD2EXPUNGELIB(UHCI_Expunge
, 0)
228 ADD2LIBS((STRPTR
)"usb.hidd", 0, static struct Library
*, __usbbase
)