1: /*
2:
3: File: WiFiControllerPCI.cpp
4: Program: GTDriver
5: Author: Michael Roßberg
6: mick@binaervarianz.de
7: Description: GTDriver is a free driver for PrismGT based cards under OS X.
8:
9: This file is part of GTDriver.
10:
11: GTDriver is free software; you can redistribute it and/or modify
12: it under the terms of the GNU General Public License as published by
13: the Free Software Foundation; either version 2 of the License, or
14: (at your option) any later version.
15:
16: GTDriver is distributed in the hope that it will be useful,
17: but WITHOUT ANY WARRANTY; without even the implied warranty of
18: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: GNU General Public License for more details.
20:
21: You should have received a copy of the GNU General Public License
22: along with GTDriver; if not, write to the Free Software
23: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24: */
25:
26: #include "WiFiControllerPCI.h"
27:
28: #define super WiFiController
29: OSDefineMetaClassAndStructors(WiFiControllerPCI, WiFiController)
30:
31: //---------------------------------------------------------------------------
32: // Function: pciConfigInit
33: //
34: // Update PCI command register to enable the memory-mapped range,
35: // and bus-master interface.
36:
37: bool WiFiControllerPCI::pciConfigInit(IOPCIDevice * provider) {
38: #define kPCIPMCSR (_pmPCICapPtr + 4)
39: UInt16 reg16;
40:
41: reg16 = provider->configRead16(kIOPCIConfigCommand);
42:
43: reg16 |= (kIOPCICommandBusMaster |
44: kIOPCICommandMemorySpace |
45: kIOPCICommandMemWrInvalidate);
46:
47: reg16 &= ~kIOPCICommandIOSpace; // disable I/O space
48:
49: //provider->configWrite16(kIOPCIConfigCommand, reg16);
50:
51: // To allow the device to use the PCI Memory Write and Invalidate
52: // command, it must know the correct cache line size. The only
53: // supported cache line sizes are 8 and 16 Dwords.
54: //
55: // Do not modify the cache line size register. Leave this up
56: // to the platform's firmware.
57: // provider->configWrite8( kIOPCIConfigCacheLineSize, 8 );
58:
59: // Locate the PM register block of this device in its PCI config space.
60:
61: /*provider->findPCICapability(kIOPCIPowerManagementCapability,
62: &_pmPCICapPtr);
63: if (_pmPCICapPtr) {
64: // Clear PME# and set power state to D0.
65: provider->configWrite16(kPCIPMCSR, 0x8000);
66: IOSleep(10);
67: }*/
68:
69: return true;
70: }
71:
72: #pragma mark provicer specific functions
73:
74: bool WiFiControllerPCI::startProvider(IOService *provider) {
75: bool ret = false;
76:
77: do {
78: // Cache our provider to an instance variable.
79: _nub = OSDynamicCast(IOPCIDevice, provider);
80: if (_nub == 0) break;
81:
82: // Retain provider, released in free().
83: _nub->retain();
84:
85: // Open our provider.
86: if (_nub->open(this) == false) break;
87:
88: // Request domain power.
89: // Without this, the PCIDevice may be in state 0, and the
90: // PCI config space may be invalid if the machine has been
91: // sleeping.
92: if (_nub->requestPowerDomainState(
93: /* power flags */ kIOPMPowerOn,
94: /* connection */ (IOPowerConnection *) getParentEntry(gIOPowerPlane),
95: /* spec */ IOPMLowestState ) != IOPMNoErr ) {
96: break;
97: }
98:
99: // Get the virtual address mapping of CSR registers located at
100: // Base Address Range 0 (0x10). The size of this range is 4K.
101: // This was changed to 32 bytes in 82558 A-Step, though only
102: // the first 32 bytes should be accessed, and the other bytes
103: // are considered reserved.
104: _map = _nub->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0);
105: if (_map == 0) break;
106:
107: _ioBase = _map->getVirtualAddress();
108:
109: // Setup our PCI config space.
110: if (pciConfigInit(_nub) == false) break;
111:
112: _mbufCursor = IOMbufLittleMemoryCursor::withSpecification(MAX_FRAGMENT_SIZE, 1);
113: if (!_mbufCursor) break;
114:
115: ret = true;
116: } while(false);
117:
118: return ret;
119: }
120:
121: bool WiFiControllerPCI::openProvider() {
122: if ((_nub == NULL) || (_nub->open(this) == false)) {
123: return false;
124: }
125:
126: return true;
127: }
128:
129: bool WiFiControllerPCI::closeProvider() {
130: if (_nub) _nub->close(this);
131:
132: return true;
133: }
134:
135: bool WiFiControllerPCI::freeProvider() {
136: #define RELEASE(x) do { if(x) { (x)->release(); (x) = 0; } } while(0)
137:
138: RELEASE(_mbufCursor);
139: RELEASE(_map);
140: RELEASE(_nub);
141:
142: return true;
143: }
144:
145: #pragma mark memory allocation
146:
147: //---------------------------------------------------------------------------
148: // Function: allocatePageBlock
149: //
150: // Purpose:
151: // Allocate a page of memory.
152:
153: bool WiFiControllerPCI::allocatePageBlock(pageBlock_t * p) {
154: UInt32 size = PAGE_SIZE;
155:
156: p->memory = IOBufferMemoryDescriptor::withOptions(kIOMemoryUnshared,
157: size, PAGE_SIZE);
158:
159: if (p->memory == 0) return false;
160:
161: if (p->memory->prepare() != kIOReturnSuccess)
162: {
163: p->memory->release();
164: p->memory = 0;
165: return false;
166: }
167:
168: p->freeStart = p->memory->getBytesNoCopy();
169: p->freeBytes = p->memory->getCapacity();
170: bzero(p->freeStart, p->freeBytes);
171:
172: return true;
173: }
174:
175: //---------------------------------------------------------------------------
176: // Function: freePageBlock
177: //
178: // Purpose:
179: // Deallocate a page of memory.
180: //
181: void WiFiControllerPCI::freePageBlock(pageBlock_t * p) {
182: if (p->memory) {
183: p->memory->complete();
184: p->memory->release();
185: p->memory = 0;
186: }
187: }
188:
189: //---------------------------------------------------------------------------
190: // Function: allocateMemoryFrom
191: //
192: // Purpose:
193: // Allocate the next aligned chunk of memory in a page block.
194:
195: void * WiFiControllerPCI::allocateMemoryFrom( pageBlock_t * p,
196: UInt32 size,
197: UInt32 align,
198: IOPhysicalAddress * paddr ) {
199: void * allocPtr;
200: IOByteCount segLength;
201:
202: if (align == 0)
203: return 0;
204:
205: // Locate next alignment boundary.
206: allocPtr = (void *)(((UInt32)p->freeStart + (align - 1)) & ~(align - 1));
207:
208: // Add alignment padding to the allocation size.
209: size += (UInt32) allocPtr - (UInt32) p->freeStart;
210:
211: if (size > p->freeBytes)
212: return 0;
213:
214: p->freeStart = (void *)((UInt32) p->freeStart + size);
215: p->freeBytes -= size;
216:
217: if (paddr) {
218: *paddr = p->memory->getPhysicalSegment(
219: (UInt32) allocPtr - (UInt32) p->memory->getBytesNoCopy(),
220: &segLength);
221: }
222:
223: return allocPtr;
224: }
225:
226: //---------------------------------------------------------------------------
227: // Function: getPhysAddress
228: //
229: // Purpose:
230: // Get the physical address for a location described by a pageBlock.
231: //
232: bool WiFiControllerPCI::getPhysAddress( pageBlock_t * pageBlock,
233: void * virtAddress,
234: IOPhysicalAddress * physAddress ) {
235: IOPhysicalAddress paddr = 0;
236: IOByteCount segLength;
237:
238: if (pageBlock && pageBlock->memory) {
239: paddr = pageBlock->memory->getPhysicalSegment(
240: (UInt32) virtAddress -
241: (UInt32) pageBlock->memory->getBytesNoCopy(),
242: &segLength);
243: }
244:
245: *physAddress = paddr;
246:
247: return (paddr != 0);
248: }
249: