The Pedigree Project  0.1
Ohci.h
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef OHCI_H
21 #define OHCI_H
22 
23 #include "modules/system/usb/Usb.h"
24 #include "modules/system/usb/UsbHub.h"
25 #include "pedigree/kernel/Spinlock.h"
26 #include "pedigree/kernel/compiler.h"
27 #include "pedigree/kernel/machine/IrqHandler.h"
28 #include "pedigree/kernel/machine/types.h"
29 #include "pedigree/kernel/process/Mutex.h"
30 #include "pedigree/kernel/process/Semaphore.h"
31 #include "pedigree/kernel/processor/MemoryRegion.h"
32 #include "pedigree/kernel/processor/state_forward.h"
33 #include "pedigree/kernel/processor/types.h"
34 #include "pedigree/kernel/utilities/ExtensibleBitmap.h"
35 #include "pedigree/kernel/utilities/List.h"
36 #include "pedigree/kernel/utilities/RequestQueue.h"
37 #include "pedigree/kernel/utilities/String.h"
38 #include "pedigree/kernel/utilities/new"
39 
40 class Device;
41 class IoBase;
42 
44 class Ohci : public UsbHub,
45 #ifdef X86_COMMON
46  public IrqHandler,
47 #else
48  public InterruptHandler,
49 #endif
50  public RequestQueue
51 {
52  private:
54  enum Lists
55  {
56  PeriodicList = 0x4,
57  IsochronousList = 0x8,
58  ControlList = 0x10,
59  BulkList = 0x20
60  };
61 
62  public:
63  Ohci(Device *pDev);
64  virtual ~Ohci();
65 
66  struct TD
67  {
68  uint32_t res0 : 18;
69  uint32_t bBuffRounding : 1;
70  uint32_t nPid : 2;
71  uint32_t nIntDelay : 3;
72  uint32_t bDataToggleSrc : 1;
73  uint32_t bDataToggle : 1;
74  uint32_t nErrorCount : 2;
75  uint32_t nStatus : 4;
76  uint32_t pBufferStart;
77  uint32_t res1 : 4;
78  uint32_t pNext : 28;
79  uint32_t pBufferEnd;
80 
81  // Custom TD fields
82  uint16_t nBufferSize;
83  uint16_t nNextTDIndex;
84  bool bLast;
85 
86  size_t id;
87 
88  // Possible values for status
89  enum StatusCodes
90  {
91  CrcError = 1,
92  Stall = 4
93  };
94 
95  UsbError getError()
96  {
97  switch (nStatus)
98  {
99  case CrcError:
100  return ::CrcError;
101  case Stall:
102  return ::Stall;
103  default:
104  return TransactionError;
105  }
106  }
107 
108  } PACKED ALIGN(16);
109 
110  struct ED
111  {
112  uint32_t nAddress : 7;
113  uint32_t nEndpoint : 4;
114  uint32_t bOut : 1;
115  uint32_t bIn : 1;
116  uint32_t bLoSpeed : 1;
117  uint32_t bSkip : 1;
118  uint32_t bIso : 1;
119  uint32_t nMaxPacketSize : 11;
120  uint32_t res0 : 9;
121  uint32_t pTailTD : 28;
122  uint32_t bHalted : 1;
123  uint32_t bToggleCarry : 1;
124  uint32_t res1 : 2;
125  uint32_t pHeadTD : 28;
126  uint32_t res2 : 4;
127  uint32_t pNext : 28;
128 
129  struct MetaData
130  {
131  void (*pCallback)(uintptr_t, ssize_t);
132  uintptr_t pParam;
133 
134  UsbEndpoint endpointInfo;
135 
136  bool bPeriodic;
137  TD *pFirstTD;
138  TD *pLastTD;
139  size_t nTotalBytes;
140 
141  ED *pPrev;
142  ED *pNext;
143 
144  List<TD *> tdList;
145  List<TD *> completedTdList;
146 
147  bool bIgnore;
148 
149  bool bLinked;
150 
151  Lists edType;
152 
153  size_t id;
154  } * pMetaData;
155  } PACKED ALIGN(16);
156 
157  struct Hcca
158  {
159  uint32_t pInterruptEDList[32];
160  uint16_t nFrameNumber;
161  uint16_t res0;
162  uint32_t pDoneHead;
163  } PACKED;
164 
165  virtual void getName(String &str)
166  {
167  str = "OHCI";
168  }
169 
170  virtual void addTransferToTransaction(
171  uintptr_t pTransaction, bool bToggle, UsbPid pid, uintptr_t pBuffer,
172  size_t nBytes);
173  virtual uintptr_t createTransaction(UsbEndpoint endpointInfo);
174 
175  virtual void doAsync(
176  uintptr_t pTransaction, void (*pCallback)(uintptr_t, ssize_t) = 0,
177  uintptr_t pParam = 0);
178  virtual void addInterruptInHandler(
179  UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes,
180  void (*pCallback)(uintptr_t, ssize_t), uintptr_t pParam = 0);
181 
183 #ifdef X86_COMMON
184  virtual bool irq(irq_id_t number, InterruptState &state);
185 #else
186  virtual void interrupt(size_t number, InterruptState &state);
187 #endif
188 
189  virtual bool portReset(uint8_t nPort, bool bErrorResponse = false);
190 
191  protected:
192  virtual uint64_t executeRequest(
193  uint64_t p1 = 0, uint64_t p2 = 0, uint64_t p3 = 0, uint64_t p4 = 0,
194  uint64_t p5 = 0, uint64_t p6 = 0, uint64_t p7 = 0, uint64_t p8 = 0);
195 
196  private:
198  void stop(Lists list);
199 
201  void start(Lists list);
202 
204  void removeED(ED *pED);
205 
207  inline physical_uintptr_t vtp_ed(ED *pED)
208  {
209  if (!pED || !pED->pMetaData)
210  return 0;
211 
212  size_t id = pED->pMetaData->id & 0xFFF;
213  Lists type = pED->pMetaData->edType;
214  switch (type)
215  {
216  case ControlList:
217  return m_pControlEDListPhys + (id * sizeof(ED));
218  case BulkList:
219  return m_pBulkEDListPhys + (id * sizeof(ED));
220  default:
221  return 0;
222  }
223  }
224 
226  inline ED *ptv_ed(physical_uintptr_t phys)
227  {
228  if (!phys)
229  return 0;
230 
231  // Figure out which list the ED was in.
234  if ((m_pControlEDListPhys <= phys) &&
235  (phys < (m_pControlEDListPhys + 0x1000)))
236  {
237  return &m_pControlEDList[phys & 0xFFF];
238  }
239  else if (
240  (m_pBulkEDListPhys <= phys) &&
241  (phys < (m_pBulkEDListPhys + 0x1000)))
242  {
243  return &m_pBulkEDList[phys & 0xFFF];
244  }
245  else
246  return 0;
247  }
248 
249  enum OhciConstants
250  {
251  OhciVersion = 0x00,
252  OhciControl = 0x04, // HcControl register
253  OhciCommandStatus = 0x08, // HcCommandStatus register
254  OhciInterruptStatus = 0x0c, // HcInterruptStatus register
255  OhciInterruptEnable = 0x10, // HcIntrerruptEnable register
256  OhciInterruptDisable = 0x14, // HcIntrerruptDisable register
257  OhciHcca = 0x18, // HcHCCA register
258  OhciControlHeadED = 0x20, // HcControlHeadED register
259  OhciControlCurrentED = 0x24, // HcControlCurrentED register
260  OhciBulkHeadED = 0x28, // HcBulkHeadED register
261  OhciBulkCurrentED = 0x2c, // HcBulkCurrentED register
262  OhciFmInterval = 0x34,
263  OhciRhDescriptorA = 0x48, // HcRhDescriptorA register
264  OhciRhStatus = 0x50,
265  OhciRhPortStatus = 0x54, // HcRhPortStatus registers
266 
267  OhciControlStateFunctionalMask = 0xC0,
268 
269  OhciControlInterruptRoute = 0x100,
270  OhciControlStateRunning =
271  0x80, // HostControllerFunctionalState bits for USBOPERATIONAL
272  OhciControlListsEnable = 0x30, // 0x34 // PeriodicListEnable,
273  // ControlListEnable and BulkListEnable
274  // bits
275 
276  OhciCommandRequestOwnership = 0x08, // Requests ownership change
277  OhciCommandBulkListFilled = 0x04, // BulkListFilled bit
278  OhciCommandControlListFilled = 0x02, // ControlListFilled bit
279  OhciCommandHcReset = 0x01, // HostControllerReset bit
280 
281  OhciInterruptMIE = 0x80000000, // MasterInterruptEnable bit
282  OhciInterruptRhStsChange = 0x40, // RootHubStatusChange bit
283  OhciInterruptUnrecoverableError = 0x10,
284  OhciInterruptWbDoneHead = 0x02, // WritebackDoneHead bit
285  OhciInterruptStartOfFrame = 0x04, // StartOfFrame interrupt
286 
287  OhciRhPortStsResCh = 0x100000, // PortResetStatusChange bit
288  OhciRhPortStsConnStsCh = 0x10000, // ConnectStatusChange bit
289  OhciRhPortStsLoSpeed = 0x200, // LowSpeedDeviceAttached bit
290  OhciRhPortStsPower = 0x100, // PortPowerStatus / SetPortPower bit
291  OhciRhPortStsReset = 0x10, // SetPortReset bit
292  OhciRhPortStsEnable = 0x02, // SetPortEnable bit
293  OhciRhPortStsConnected = 0x01, // CurrentConnectStatus bit
294  };
295 
296  IoBase *m_pBase;
297 
298  uint8_t m_nPorts;
299 
302 
303  Hcca *m_pHcca;
304  uintptr_t m_pHccaPhys;
305 
308 
311 
314 
317 
318  ED *m_pPeriodicEDList;
319  uintptr_t m_pPeriodicEDListPhys;
320  ExtensibleBitmap m_PeriodicEDBitmap;
321 
322  ED *m_pControlEDList;
323  uintptr_t m_pControlEDListPhys;
324  ExtensibleBitmap m_ControlEDBitmap;
325 
326  ED *m_pBulkEDList;
327  uintptr_t m_pBulkEDListPhys;
328  ExtensibleBitmap m_BulkEDBitmap;
329 
330  TD *m_pTDList;
331  uintptr_t m_pTDListPhys;
332  ExtensibleBitmap m_TDBitmap;
333 
334  // Pointers to the current bulk and control queue heads (can be null)
335  ED *m_pBulkQueueHead;
336  ED *m_pControlQueueHead;
337 
338  // Pointers to the current bulk and control queue tails
339  ED *m_pBulkQueueTail;
340  ED *m_pControlQueueTail;
341 
342  // Pointer to the current periodic queue tail
343  ED *m_pPeriodicQueueTail;
344 
347 
351 
354 
357 
358  MemoryRegion m_OhciMR;
359 
360  Ohci(const Ohci &);
361  void operator=(const Ohci &);
362 };
363 
364 #endif
Definition: Ohci.h:66
Spinlock m_PeriodicListChangeLock
Lock for changing the periodic list.
Definition: Ohci.h:310
virtual bool portReset(uint8_t nPort, bool bErrorResponse=false)
Gets a UsbDevice from a given vendor:product pair.
Definition: Ohci.cc:1089
virtual void addTransferToTransaction(uintptr_t pTransaction, bool bToggle, UsbPid pid, uintptr_t pBuffer, size_t nBytes)
Adds a new transfer to an existent transaction.
Definition: Ohci.cc:661
void stop(Lists list)
Stops the controller from processing the given list.
Definition: Ohci.cc:1143
List< ED * > m_FullSchedule
Definition: Ohci.h:350
ED * ptv_ed(physical_uintptr_t phys)
Converts a physical address to an ED pointer. Maybe.
Definition: Ohci.h:226
virtual void doAsync(uintptr_t pTransaction, void(*pCallback)(uintptr_t, ssize_t)=0, uintptr_t pParam=0)
Definition: Ohci.cc:842
virtual void addInterruptInHandler(UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes, void(*pCallback)(uintptr_t, ssize_t), uintptr_t pParam=0)
Adds a new handler for an interrupt IN transaction.
Definition: Ohci.cc:1014
virtual void getName(String &str)
Definition: Ohci.h:165
Definition: Mutex.h:58
physical_uintptr_t vtp_ed(ED *pED)
Converts a software ED pointer to a physical address.
Definition: Ohci.h:207
Definition: String.h:49
Spinlock m_ControlListChangeLock
Lock for changing the control list.
Definition: Ohci.h:313
Abstrace base class for hardware I/O capabilities.
Definition: IoBase.h:31
Spinlock m_DequeueListLock
Dequeue list lock.
Definition: Ohci.h:346
Spinlock m_ScheduleChangeLock
Lock for modifying the schedule list itself (m_FullSchedule)
Definition: Ohci.h:307
Definition: Device.h:43
Spinlock m_BulkListChangeLock
Lock for changing the bulk list.
Definition: Ohci.h:316
Special memory entity in the kernel&#39;s virtual address space.
Definition: MemoryRegion.h:35
Definition: Ohci.h:110
Definition: UsbHub.h:30
Mutex m_Mutex
Global lock.
Definition: Ohci.h:301
Semaphore m_DequeueCount
Semaphore for the dequeue list.
Definition: Ohci.h:356
virtual uint64_t executeRequest(uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)
Definition: Ohci.cc:1110
void removeED(ED *pED)
Prepares an ED to be reclaimed.
Definition: Ohci.cc:261
List< ED * > m_DequeueList
List of EDs ready for dequeue (reclaiming)
Definition: Ohci.h:353
Abstract base class for interrupt-handlers.
virtual uintptr_t createTransaction(UsbEndpoint endpointInfo)
Creates a new transaction with the given endpoint data.
Definition: Ohci.cc:778
void start(Lists list)
Starts processing of the given list.
Definition: Ohci.cc:1153
virtual bool irq(irq_id_t number, InterruptState &state)
IRQ handler.
Definition: Ohci.cc:376
Definition: Ohci.h:44
Lists
Enumeration of lists that can be stopped or started.
Definition: Ohci.h:54