1 /* 2 * Copyright 2006, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #ifndef EHCI_H 10 #define EHCI_H 11 12 #include "usb_p.h" 13 #include "ehci_hardware.h" 14 15 16 struct pci_info; 17 struct pci_module_info; 18 class EHCIRootHub; 19 20 21 typedef struct transfer_data_s { 22 Transfer *transfer; 23 ehci_qh *queue_head; 24 ehci_qtd *data_descriptor; 25 bool incoming; 26 bool canceled; 27 transfer_data_s *link; 28 } transfer_data; 29 30 31 class EHCI : public BusManager { 32 public: 33 EHCI(pci_info *info, Stack *stack); 34 ~EHCI(); 35 36 status_t Start(); 37 virtual status_t SubmitTransfer(Transfer *transfer); 38 virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force); 39 40 virtual status_t NotifyPipeChange(Pipe *pipe, 41 usb_change change); 42 43 static status_t AddTo(Stack *stack); 44 45 // Port operations for root hub 46 uint8 PortCount() { return fPortCount; }; 47 status_t GetPortStatus(uint8 index, usb_port_status *status); 48 status_t SetPortFeature(uint8 index, uint16 feature); 49 status_t ClearPortFeature(uint8 index, uint16 feature); 50 51 status_t ResetPort(uint8 index); 52 status_t SuspendPort(uint8 index); 53 54 private: 55 // Controller resets 56 status_t ControllerReset(); 57 status_t LightReset(); 58 59 // Interrupt functions 60 static int32 InterruptHandler(void *data); 61 int32 Interrupt(); 62 63 // Transfer management 64 status_t AddPendingTransfer(Transfer *transfer, 65 ehci_qh *queueHead, 66 ehci_qtd *dataDescriptor, 67 bool directionIn); 68 status_t CancelAllPendingTransfers(); 69 70 static int32 FinishThread(void *data); 71 void FinishTransfers(); 72 static int32 CleanupThread(void *data); 73 void Cleanup(); 74 75 // Queue Head functions 76 ehci_qh *CreateQueueHead(); 77 status_t InitQueueHead(ehci_qh *queueHead, 78 Pipe *pipe); 79 void FreeQueueHead(ehci_qh *queueHead); 80 81 status_t LinkQueueHead(ehci_qh *queueHead); 82 status_t LinkInterruptQueueHead(ehci_qh *queueHead, 83 Pipe *pipe); 84 status_t UnlinkQueueHead(ehci_qh *queueHead, 85 ehci_qh **freeList); 86 87 // Queue functions 88 status_t FillQueueWithRequest(Transfer *transfer, 89 ehci_qh *queueHead, 90 ehci_qtd **dataDescriptor, 91 bool *directionIn); 92 status_t FillQueueWithData(Transfer *transfer, 93 ehci_qh *queueHead, 94 ehci_qtd **dataDescriptor, 95 bool *directionIn); 96 97 // Descriptor functions 98 ehci_qtd *CreateDescriptor(size_t bufferSizeToAllocate, 99 uint8 pid); 100 status_t CreateDescriptorChain(Pipe *pipe, 101 ehci_qtd **firstDescriptor, 102 ehci_qtd **lastDescriptor, 103 ehci_qtd *strayDescriptor, 104 size_t bufferSizeToAllocate, 105 uint8 pid); 106 107 void FreeDescriptor(ehci_qtd *descriptor); 108 void FreeDescriptorChain(ehci_qtd *topDescriptor); 109 110 void LinkDescriptors(ehci_qtd *first, 111 ehci_qtd *last, ehci_qtd *alt); 112 113 size_t WriteDescriptorChain(ehci_qtd *topDescriptor, 114 iovec *vector, size_t vectorCount); 115 size_t ReadDescriptorChain(ehci_qtd *topDescriptor, 116 iovec *vector, size_t vectorCount, 117 bool *nextDataToggle); 118 size_t ReadActualLength(ehci_qtd *topDescriptor, 119 bool *nextDataToggle); 120 121 // Operational register functions 122 inline void WriteOpReg(uint32 reg, uint32 value); 123 inline uint32 ReadOpReg(uint32 reg); 124 125 // Capability register functions 126 inline uint8 ReadCapReg8(uint32 reg); 127 inline uint16 ReadCapReg16(uint32 reg); 128 inline uint32 ReadCapReg32(uint32 reg); 129 130 static pci_module_info *sPCIModule; 131 132 uint8 *fCapabilityRegisters; 133 uint8 *fOperationalRegisters; 134 area_id fRegisterArea; 135 pci_info *fPCIInfo; 136 Stack *fStack; 137 uint32 fEnabledInterrupts; 138 139 // Periodic transfer framelist and interrupt entries 140 area_id fPeriodicFrameListArea; 141 addr_t *fPeriodicFrameList; 142 interrupt_entry *fInterruptEntries; 143 144 // Async transfer queue management 145 ehci_qh *fAsyncQueueHead; 146 sem_id fAsyncAdvanceSem; 147 148 // Maintain a linked list of transfers 149 transfer_data *fFirstTransfer; 150 transfer_data *fLastTransfer; 151 sem_id fFinishTransfersSem; 152 thread_id fFinishThread; 153 sem_id fCleanupSem; 154 thread_id fCleanupThread; 155 bool fStopThreads; 156 ehci_qh *fFreeListHead; 157 158 // Root Hub 159 EHCIRootHub *fRootHub; 160 uint8 fRootHubAddress; 161 162 // Port management 163 uint8 fPortCount; 164 uint16 fPortResetChange; 165 uint16 fPortSuspendChange; 166 }; 167 168 169 class EHCIRootHub : public Hub { 170 public: 171 EHCIRootHub(Object *rootObject, 172 int8 deviceAddress); 173 174 static status_t ProcessTransfer(EHCI *ehci, 175 Transfer *transfer); 176 }; 177 178 179 #endif // !EHCI_H 180