]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
24 | * | |
25 | * AppleATAPIIX.cpp - ATA controller driver for Intel PIIX/PIIX3/PIIX4. | |
26 | * | |
27 | * HISTORY | |
28 | * | |
29 | */ | |
30 | ||
31 | #include <architecture/i386/pio.h> | |
32 | #include <IOKit/IOService.h> | |
33 | #include <IOKit/assert.h> | |
34 | #include "AppleATAPIIX.h" | |
35 | #include "AppleATAPIIXTiming.h" | |
36 | ||
37 | extern pmap_t kernel_pmap; // for pmap_extract() | |
38 | ||
39 | // Resources shared between the two IDE channels are protected | |
40 | // by this mutex. | |
41 | // | |
42 | static IOLock * gPIIXLock = 0; | |
43 | #define PIIX_LOCK IOLockLock(gPIIXLock) | |
44 | #define PIIX_UNLOCK IOLockUnlock(gPIIXLock) | |
45 | ||
46 | #define IOREG(x) (ioBMRange + PIIX_IO_ ## x) | |
47 | ||
48 | #define CHECK_UNIT(drv) assert(drv < 2) | |
49 | ||
50 | #ifdef DEBUG_XXX | |
51 | #define DLOG(fmt, args...) IOLog(fmt, ## args) | |
52 | #else | |
53 | #define DLOG(fmt, args...) | |
54 | #endif | |
55 | ||
56 | //-------------------------------------------------------------------------- | |
57 | // Metaclass macro. | |
58 | // | |
59 | #undef super | |
60 | #define super IOATAStandardDriver | |
61 | ||
62 | OSDefineMetaClassAndStructorsWithInit( AppleATAPIIX, IOATAStandardDriver, | |
63 | AppleATAPIIX::initialize() ) | |
64 | ||
65 | //-------------------------------------------------------------------------- | |
66 | // PIIX class initializer. | |
67 | // | |
68 | void AppleATAPIIX::initialize() | |
69 | { | |
70 | gPIIXLock = IOLockAlloc(); | |
71 | assert(gPIIXLock); | |
72 | } | |
73 | ||
74 | //-------------------------------------------------------------------------- | |
75 | // Defines a table of supported PIIX device types, listing their | |
76 | // PCI ID, and a name string. Also supply some utility functions | |
77 | // to locate a table entry based on an arbitrary PCI ID. | |
78 | // | |
79 | static struct { | |
80 | UInt32 CFID; | |
81 | const char * name; | |
82 | } piixDeviceTable[] = {{ PCI_ID_PIIX, "PIIX" }, | |
83 | { PCI_ID_PIIX3, "PIIX3" }, | |
84 | { PCI_ID_PIIX4, "PIIX4" }, | |
85 | { PCI_ID_ICH, "ICH" }, | |
86 | { PCI_ID_ICH0, "ICH0" }, | |
87 | { PCI_ID_ICH2_M, "ICH2-M" }, | |
88 | { PCI_ID_ICH2, "ICH2" }, | |
89 | { PCI_ID_NONE, NULL }}; | |
90 | ||
91 | static const char * | |
92 | PIIXGetName(UInt32 pciID) | |
93 | { | |
94 | for (int i = 0; piixDeviceTable[i].name; i++) { | |
95 | if (piixDeviceTable[i].CFID == pciID) | |
96 | return piixDeviceTable[i].name; | |
97 | } | |
98 | return 0; | |
99 | } | |
100 | ||
101 | static bool | |
102 | PIIXVerifyID(UInt32 pciID) | |
103 | { | |
104 | return (PIIXGetName(pciID) == 0) ? false : true; | |
105 | } | |
106 | ||
107 | //-------------------------------------------------------------------------- | |
108 | // A hack to modify our PCI nub to have two interrupts. | |
109 | // This code was borrowed from the setupIntelPIC() function | |
110 | // in iokit/Families/IOPCIBus/IOPCIBridge.cpp. | |
111 | // | |
112 | static void setupProviderInterrupts(IOPCIDevice * nub, long irq_p, long irq_s) | |
113 | { | |
114 | OSArray * controller; | |
115 | OSArray * specifier; | |
116 | OSData * tmpData; | |
117 | extern OSSymbol * gIntelPICName; | |
118 | ||
119 | do { | |
120 | // Create the interrupt specifer array. | |
121 | specifier = OSArray::withCapacity(2); | |
122 | if (!specifier) | |
123 | break; | |
124 | ||
125 | tmpData = OSData::withBytes(&irq_p, sizeof(irq_p)); | |
126 | if (tmpData) { | |
127 | specifier->setObject(tmpData); | |
128 | tmpData->release(); | |
129 | } | |
130 | tmpData = OSData::withBytes(&irq_s, sizeof(irq_s)); | |
131 | if (tmpData) { | |
132 | specifier->setObject(tmpData); | |
133 | tmpData->release(); | |
134 | } | |
135 | ||
136 | controller = OSArray::withCapacity(2); | |
137 | if (controller) { | |
138 | controller->setObject(gIntelPICName); | |
139 | controller->setObject(gIntelPICName); | |
140 | ||
141 | // Put the two arrays into the property table. | |
142 | nub->setProperty(gIOInterruptControllersKey, controller); | |
143 | controller->release(); | |
144 | } | |
145 | nub->setProperty(gIOInterruptSpecifiersKey, specifier); | |
146 | specifier->release(); | |
147 | ||
148 | } while( false ); | |
149 | } | |
150 | ||
151 | //-------------------------------------------------------------------------- | |
152 | // A static member function that returns the IDE channel for the | |
153 | // current driver instance, and also registers the interrupts in | |
154 | // the IOPCIDevice nub. | |
155 | // | |
156 | int AppleATAPIIX::PIIXGetChannel(IOPCIDevice * provider) | |
157 | { | |
158 | static bool primaryRegistered = false; | |
159 | int rc; | |
160 | extern OSSymbol * gIntelPICName; | |
161 | ||
162 | PIIX_LOCK; | |
163 | ||
164 | if (primaryRegistered == false) { | |
165 | rc = PIIX_CHANNEL_PRIMARY; | |
166 | primaryRegistered = true; | |
167 | ||
168 | // Is this necessary? | |
169 | waitForService(resourceMatching(gIntelPICName)); | |
170 | ||
171 | setupProviderInterrupts(provider, PIIX_P_IRQ, PIIX_S_IRQ); | |
172 | } | |
173 | else { | |
174 | rc = PIIX_CHANNEL_SECONDARY; | |
175 | } | |
176 | ||
177 | PIIX_UNLOCK; | |
178 | ||
179 | if (rc == PIIX_CHANNEL_SECONDARY) IOSleep(20); | |
180 | ||
181 | return rc; | |
182 | } | |
183 | ||
184 | //-------------------------------------------------------------------------- | |
185 | // Private function: _getIDERanges | |
186 | // | |
187 | // Setup the variables that stores the start of the Command and Control | |
188 | // block in I/O space. The variable 'channel' must have been previously | |
189 | // set. These ISA I/O ranges are implicit and does not show up in PCI | |
190 | // config space. | |
191 | // | |
192 | bool AppleATAPIIX::_getIDERanges(IOPCIDevice * provider) | |
193 | { | |
194 | ioCmdRange = (channel == PIIX_CHANNEL_PRIMARY) ? | |
195 | PIIX_P_CMD_ADDR : PIIX_S_CMD_ADDR; | |
196 | ||
197 | ioCtlRange = (channel == PIIX_CHANNEL_PRIMARY) ? | |
198 | PIIX_P_CTL_ADDR : PIIX_S_CTL_ADDR; | |
199 | ||
200 | DLOG("%s: ioCmdRange - %04x\n", getName(), ioCmdRange); | |
201 | DLOG("%s: ioCtlRange - %04x\n", getName(), ioCtlRange); | |
202 | ||
203 | return true; | |
204 | } | |
205 | ||
206 | //-------------------------------------------------------------------------- | |
207 | // Private function: _getBMRange | |
208 | // | |
209 | // Determine the start of the I/O mapped Bus-Master registers. | |
210 | // This range is defined by PCI config space register PIIX_PCI_BMIBA. | |
211 | // | |
212 | bool AppleATAPIIX::_getBMRange(IOPCIDevice * provider) | |
213 | { | |
214 | UInt32 bmiba; | |
215 | ||
216 | bmiba = provider->configRead32(PIIX_PCI_BMIBA); | |
217 | if ((bmiba & PIIX_PCI_BMIBA_RTE) == 0) { | |
218 | IOLog("%s: PCI memory range 0x%02x (0x%08lx) is not an I/O range\n", | |
219 | getName(), PIIX_PCI_BMIBA, bmiba); | |
220 | return false; | |
221 | } | |
222 | ||
223 | bmiba &= PIIX_PCI_BMIBA_MASK; // get the address portion | |
224 | ||
225 | // If bmiba is zero, it is likely that the user has elected to | |
226 | // turn off PCI IDE support in the BIOS. | |
227 | // | |
228 | if (bmiba == 0) | |
229 | return false; | |
230 | ||
231 | if (channel == PIIX_CHANNEL_SECONDARY) | |
232 | bmiba += PIIX_IO_BM_OFFSET; | |
233 | ||
234 | ioBMRange = (UInt16) bmiba; | |
235 | ||
236 | DLOG("%s: ioBMRange - %04x\n", getName(), ioBMRange); | |
237 | ||
238 | return true; | |
239 | } | |
240 | ||
241 | //-------------------------------------------------------------------------- | |
242 | // Private function: _resetTimings() | |
243 | // | |
244 | // Reset all timing registers to the slowest (most compatible) timing. | |
245 | // UDMA modes are disabled. We take a lock to prevent the other IDE | |
246 | // channel from modifying the shared PCI config space. | |
247 | // | |
248 | bool AppleATAPIIX::_resetTimings() | |
249 | { | |
250 | union { | |
251 | UInt32 b32; | |
252 | struct { | |
253 | UInt16 pri; | |
254 | UInt16 sec; | |
255 | } b16; | |
256 | } timing; | |
257 | ||
258 | UInt32 udmaControl; | |
259 | ||
260 | PIIX_LOCK; | |
261 | ||
262 | timing.b32 = provider->configRead32(PIIX_PCI_IDETIM); | |
263 | udmaControl = provider->configRead32(PIIX_PCI_UDMACTL); | |
264 | ||
265 | // Set slowest timing, and disable UDMA. Only modify the flags | |
266 | // associated with the local channel. | |
267 | // | |
268 | switch (channel) { | |
269 | case PIIX_CHANNEL_PRIMARY: | |
270 | timing.b16.pri &= PIIX_PCI_IDETIM_IDE; | |
271 | udmaControl &= ~(PIIX_PCI_UDMACTL_PSDE0 | PIIX_PCI_UDMACTL_PSDE1); | |
272 | break; | |
273 | ||
274 | case PIIX_CHANNEL_SECONDARY: | |
275 | timing.b16.sec &= PIIX_PCI_IDETIM_IDE; | |
276 | udmaControl &= ~(PIIX_PCI_UDMACTL_SSDE0 | PIIX_PCI_UDMACTL_SSDE1); | |
277 | break; | |
278 | } | |
279 | ||
280 | provider->configWrite32(PIIX_PCI_UDMACTL, udmaControl); | |
281 | provider->configWrite32(PIIX_PCI_IDETIM, timing.b32); | |
282 | ||
283 | // FIXME | |
284 | // No support for ATA/66 or ATA/100 modes. Set this register | |
285 | // to 0 (new in ICH2) to disable those faster timings. | |
286 | // | |
287 | provider->configWrite32(PIIX_PCI_IDECONFIG, 0); | |
288 | ||
289 | PIIX_UNLOCK; | |
290 | ||
291 | return true; | |
292 | } | |
293 | ||
294 | //-------------------------------------------------------------------------- | |
295 | // Private function: _allocatePRDTable() | |
296 | // | |
297 | // Allocate the physical region descriptor (PRD) table. The physical | |
298 | // address of this table is stored in 'prdTablePhys'. Look at Intel | |
299 | // documentation for the alignment requirements. | |
300 | // | |
301 | bool AppleATAPIIX::_allocatePRDTable() | |
302 | { | |
303 | prdTable = (prdEntry_t *) IOMallocAligned(PRD_TABLE_SIZE, PAGE_SIZE); | |
304 | if (!prdTable) | |
305 | return false; | |
306 | ||
307 | prdTablePhys = (UInt32) pmap_extract(kernel_pmap, (vm_offset_t) prdTable); | |
308 | ||
309 | bzero(prdTable, PRD_TABLE_SIZE); | |
310 | ||
311 | return true; | |
312 | } | |
313 | ||
314 | //-------------------------------------------------------------------------- | |
315 | // Private function: _deallocatePRDTable() | |
316 | // | |
317 | void AppleATAPIIX::_deallocatePRDTable() | |
318 | { | |
319 | IOFreeAligned(prdTable, PRD_TABLE_SIZE); | |
320 | prdTable = NULL; | |
321 | prdTablePhys = 0; | |
322 | } | |
323 | ||
324 | //-------------------------------------------------------------------------- | |
325 | // Function inherited from IOATAController. | |
326 | // | |
327 | // Configure the driver/controller. This is the first function called by | |
328 | // our superclass, in its start() function, to initialize the controller | |
329 | // hardware. | |
330 | // | |
331 | bool | |
332 | AppleATAPIIX::configure(IOService * forProvider, | |
333 | ATAControllerInfo * controllerInfo) | |
334 | { | |
335 | UInt32 reg; | |
336 | ||
337 | // IOSleep(1000); | |
338 | ||
0b4e3aa0 | 339 | provider = (IOPCIDevice *)forProvider->metaCast("IOPCIDevice"); |
1c79356b A |
340 | if (!provider) |
341 | return false; | |
342 | ||
343 | // Superclass performs an exclusive open on the provider, we close | |
344 | // it to allow more than one instance of this driver to attach to | |
345 | // the same PCI nub. We should maintain an non-exclusive open on | |
346 | // the provider. | |
347 | // | |
348 | provider->close(this); | |
349 | ||
350 | // Determine the type of PIIX controller. Save the controller's | |
351 | // PCI ID in pciCFID. | |
352 | // | |
353 | pciCFID = provider->configRead32(PIIX_PCI_CFID); | |
354 | if (PIIXVerifyID(pciCFID) == false) { | |
355 | IOLog("%s: Unknown PCI IDE controller (0x%08lx)\n", | |
356 | getName(), | |
357 | pciCFID); | |
358 | return false; | |
359 | } | |
360 | ||
361 | // Determine our IDE channel, primary or secondary. | |
362 | // | |
363 | channel = PIIXGetChannel(provider); | |
364 | ||
365 | _getIDERanges(provider); | |
366 | ||
367 | IOLog("%s: %s %s IDE controller, 0x%x, irq %d\n", | |
368 | getName(), | |
369 | (channel == PIIX_CHANNEL_PRIMARY) ? "Primary" : "Secondary", | |
370 | PIIXGetName(pciCFID), | |
371 | ioCmdRange, | |
372 | (channel == PIIX_CHANNEL_PRIMARY) ? PIIX_P_IRQ : PIIX_S_IRQ); | |
373 | ||
374 | // Check the I/O Space Enable bit in the PCI command register. | |
375 | // This is the master enable bit for the PIIX controller. | |
376 | // Each IDE channel also has its own enable bit, which is | |
377 | // checked later. | |
378 | // | |
379 | reg = provider->configRead32(PIIX_PCI_PCICMD); | |
380 | if ((reg & PIIX_PCI_PCICMD_IOSE) == 0) { | |
381 | IOLog("%s: PCI IDE controller is not enabled\n", getName()); | |
382 | return false; | |
383 | } | |
384 | ||
385 | // Set BME bit to enable bus-master. | |
386 | // | |
387 | if ((reg & PIIX_PCI_PCICMD_BME) == 0) { | |
388 | reg |= PIIX_PCI_PCICMD_BME; | |
389 | PIIX_LOCK; | |
390 | provider->configWrite32(PIIX_PCI_PCICMD, reg); | |
391 | PIIX_UNLOCK; | |
392 | } | |
393 | ||
394 | // Fetch the corresponding primary/secondary IDETIM register and | |
395 | // check the individual channel enable bit. | |
396 | // | |
397 | reg = provider->configRead32(PIIX_PCI_IDETIM); | |
398 | if (channel == PIIX_CHANNEL_SECONDARY) | |
399 | reg >>= 16; // PIIX_PCI_IDETIM + 2 for secondary channel | |
400 | ||
401 | if ((reg & PIIX_PCI_IDETIM_IDE) == 0) { | |
402 | IOLog("%s: %s PCI IDE channel is not enabled\n", | |
403 | getName(), | |
404 | (channel == PIIX_CHANNEL_PRIMARY) ? "Primary" : "Secondary"); | |
405 | return false; | |
406 | } | |
407 | ||
408 | // Locate and add the I/O mapped bus-master registers to | |
409 | // ioRange[] array. | |
410 | // | |
411 | if (_getBMRange(provider) == false) { | |
412 | IOLog("%s: Bus master I/O range is invalid\n", getName()); | |
413 | return false; | |
414 | } | |
415 | ||
416 | // Allocate page-aligned memory for the PRD table. | |
417 | // | |
418 | if (_allocatePRDTable() == false) { | |
419 | IOLog("%s: unable to allocate descriptor table\n", getName()); | |
420 | return false; | |
421 | } | |
422 | ||
423 | // Allocate a cursor object to generate the scatter-gather list | |
424 | // for each transfer request. Maximum segment size is set to 64K. | |
425 | // However, there is no way to indicate our requirement that each | |
426 | // memory segment cannot cross a 64K boundary. We have to do this | |
427 | // manually. | |
428 | // | |
429 | prdCursor = IOLittleMemoryCursor::withSpecification(64 * 1024, 0xffffffff); | |
430 | if (prdCursor == 0) | |
431 | return false; | |
432 | ||
433 | // Attach an interruptEventSource to handle HW interrupts. | |
434 | // Must do this after PIIXGetChannel(), since thats where the | |
435 | // provider's interrupt property is set by setupProviderInterrupts(). | |
436 | ||
437 | interruptEventSource = IOInterruptEventSource::interruptEventSource( | |
438 | (OSObject *) this, | |
439 | (IOInterruptEventAction) &AppleATAPIIX::interruptOccurred, | |
440 | (IOService *) provider, | |
441 | (channel == PIIX_CHANNEL_PRIMARY) ? 0 : 1); | |
442 | if (interruptEventSource == 0) { | |
443 | IOLog("%s: unable to create an IOInterruptEventSource object\n", | |
444 | getName()); | |
445 | return false; | |
446 | } | |
447 | ||
448 | disableControllerInterrupts(); | |
449 | ||
450 | getWorkLoop()->addEventSource(interruptEventSource); | |
451 | ||
452 | // Revert to default (compatible) timing. | |
453 | // | |
454 | _resetTimings(); | |
455 | ||
456 | controllerInfo->maxDevicesSupported = 2; | |
457 | controllerInfo->devicePrivateDataSize = 0; | |
458 | controllerInfo->commandPrivateDataSize = 0; | |
459 | controllerInfo->disableCancelCommands = false; | |
460 | ||
461 | ||
462 | DLOG("AppleATAPIIX::%s() completed successfully\n", __FUNCTION__); | |
463 | ||
464 | return true; | |
465 | } | |
466 | ||
467 | //-------------------------------------------------------------------------- | |
468 | // | |
469 | // | |
470 | bool AppleATAPIIX::provideProtocols(enum ATAProtocol * protocolsSupported) | |
471 | { | |
472 | return false; | |
473 | } | |
474 | ||
475 | //-------------------------------------------------------------------------- | |
476 | // | |
477 | // | |
478 | bool AppleATAPIIX::provideTimings(UInt32 * numTimings, | |
479 | ATATiming * timingsSupported) | |
480 | { | |
481 | return false; | |
482 | } | |
483 | ||
484 | //-------------------------------------------------------------------------- | |
485 | // Determine the timing selection based on the ATATiming structure given. | |
486 | // | |
487 | bool AppleATAPIIX::calculateTiming(UInt32 unit, ATATiming * pTiming) | |
488 | { | |
489 | int i; | |
490 | PIIXProtocol protocol = ataToPIIXProtocol(pTiming->timingProtocol); | |
491 | ||
492 | DLOG("AppleATAPIIX::%s() - unit:%ld protocol:%d minCycles:%ld\n", | |
493 | __FUNCTION__, unit, protocol, pTiming->minDataCycle); | |
494 | ||
495 | CHECK_UNIT(unit); | |
496 | ||
497 | timings[unit].validTimings[protocol] = 0; | |
498 | ||
499 | switch (protocol) { | |
500 | ||
501 | case kPIIXProtocolPIO: | |
502 | ||
503 | for (i = 0; i < PIIXPIOTimingTableSize; i++) | |
504 | { | |
505 | if (PIIXPIOTimingTable[i].pioMode == _NVM_) | |
506 | continue; | |
507 | ||
508 | if (PIIXPIOTimingTable[i].cycle < pTiming->minDataCycle) | |
509 | break; | |
510 | ||
511 | timings[unit].validTimings[protocol] = i; | |
512 | } | |
513 | break; | |
514 | ||
515 | case kPIIXProtocolDMA: | |
516 | ||
517 | for (i = 0; i < PIIXPIOTimingTableSize; i++) | |
518 | { | |
519 | if (PIIXPIOTimingTable[i].mwDMAMode == _NVM_) | |
520 | continue; | |
521 | ||
522 | if (PIIXPIOTimingTable[i].cycle < pTiming->minDataCycle) | |
523 | break; | |
524 | ||
525 | timings[unit].validTimings[protocol] = i; | |
526 | } | |
527 | break; | |
528 | ||
529 | case kPIIXProtocolUDMA33: | |
530 | ||
531 | for (i = 0; i < PIIXUDMATimingTableSize; i++) | |
532 | { | |
533 | if (PIIXUDMATimingTable[i].strobe < pTiming->minDataCycle) | |
534 | break; | |
535 | ||
536 | timings[unit].validTimings[protocol] = i; | |
537 | } | |
538 | break; | |
539 | ||
540 | default: | |
541 | return false; | |
542 | } | |
543 | ||
544 | timings[unit].validFlag |= (1 << protocol); | |
545 | ||
546 | return true; | |
547 | } | |
548 | ||
549 | //-------------------------------------------------------------------------- | |
550 | // Setup the timing register for the given timing protocol. | |
551 | // | |
552 | bool AppleATAPIIX::selectTiming(UInt32 unit, | |
553 | ATATimingProtocol timingProtocol) | |
554 | { | |
555 | bool ret = false; | |
556 | UInt8 pciConfig[256]; | |
557 | PIIXProtocol protocol = ataToPIIXProtocol(timingProtocol); | |
558 | ||
559 | DLOG("AppleATAPIIX::%s() - unit:%ld protocol:%d\n", | |
560 | __FUNCTION__, unit, protocol); | |
561 | ||
562 | CHECK_UNIT(unit); | |
563 | ||
564 | PIIX_LOCK; | |
565 | ||
566 | do { | |
567 | if (protocol >= kPIIXProtocolLast) | |
568 | break; | |
569 | ||
570 | if (PIIX_PROTOCOL_IS_VALID(protocol) == 0) { | |
571 | ||
572 | // superclass error, calculateTiming() was not called | |
573 | // before calling selectTiming(). | |
574 | ||
575 | IOLog("%s: timing protocol selected is invalid\n", getName()); | |
576 | break; | |
577 | } | |
578 | ||
579 | if (!_readPCIConfigSpace(pciConfig) || | |
580 | !_selectTiming(unit, protocol, pciConfig) || | |
581 | !_writePCIConfigSpace(pciConfig)) | |
582 | break; | |
583 | ||
584 | ret = true; | |
585 | } | |
586 | while (0); | |
587 | ||
588 | PIIX_UNLOCK; | |
589 | ||
590 | return ret; | |
591 | } | |
592 | ||
593 | //-------------------------------------------------------------------------- | |
594 | // Setup the timing registers. | |
595 | // | |
596 | bool AppleATAPIIX::_selectTiming(UInt32 unit, | |
597 | PIIXProtocol protocol, | |
598 | UInt8 * pciConfig) | |
599 | { | |
600 | UInt8 isp, rtc; | |
601 | UInt8 index, dma, pio; | |
602 | bool dmaActive; | |
603 | bool pioActive; | |
604 | bool useCompatiblePIOTiming = false; | |
605 | bool ret = true; | |
606 | UInt16 * idetim; | |
607 | UInt8 * sidetim = (UInt8 *) &pciConfig[PIIX_PCI_SIDETIM]; | |
608 | UInt8 * udmactl = (UInt8 *) &pciConfig[PIIX_PCI_UDMACTL]; | |
609 | UInt16 * udmatim = (UInt16 *) &pciConfig[PIIX_PCI_UDMATIM]; | |
610 | ||
611 | idetim = (channel == PIIX_CHANNEL_PRIMARY) ? | |
612 | (UInt16 *) &pciConfig[PIIX_PCI_IDETIM] : | |
613 | (UInt16 *) &pciConfig[PIIX_PCI_IDETIM_S]; | |
614 | ||
615 | switch (protocol) { | |
616 | case kPIIXProtocolUDMA66: | |
617 | // Not yet! | |
618 | return false; | |
619 | ||
620 | case kPIIXProtocolUDMA33: | |
621 | if ((pciCFID == PCI_ID_PIIX) || (pciCFID == PCI_ID_PIIX3)) { | |
622 | // Only PIIX4 (and newer devices) supports UDMA. | |
623 | return false; | |
624 | } | |
625 | PIIX_DEACTIVATE_PROTOCOL(kPIIXProtocolDMA); | |
626 | break; | |
627 | ||
628 | case kPIIXProtocolDMA: | |
629 | PIIX_DEACTIVATE_PROTOCOL(kPIIXProtocolUDMA33); | |
630 | break; | |
631 | ||
632 | case kPIIXProtocolPIO: | |
633 | break; | |
634 | ||
635 | default: | |
636 | IOLog("%s: PIIX protocol not handled (%d)\n", getName(), | |
637 | protocol); | |
638 | return false; | |
639 | } | |
640 | PIIX_ACTIVATE_PROTOCOL(protocol); | |
641 | ||
642 | ||
643 | if (PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolUDMA33)) { | |
644 | ||
645 | index = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolUDMA33); | |
646 | ||
647 | if (unit == 0) { | |
648 | if (channel == PIIX_CHANNEL_PRIMARY) { | |
649 | *udmactl |= PIIX_PCI_UDMACTL_PSDE0; | |
650 | SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_PCT0, | |
651 | PIIXUDMATimingTable[index].bits); | |
652 | } | |
653 | else { | |
654 | *udmactl |= PIIX_PCI_UDMACTL_SSDE0; | |
655 | SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_SCT0, | |
656 | PIIXUDMATimingTable[index].bits); | |
657 | } | |
658 | } | |
659 | else { | |
660 | if (channel == PIIX_CHANNEL_PRIMARY) { | |
661 | *udmactl |= PIIX_PCI_UDMACTL_PSDE1; | |
662 | SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_PCT1, | |
663 | PIIXUDMATimingTable[index].bits); | |
664 | } | |
665 | else { | |
666 | *udmactl |= PIIX_PCI_UDMACTL_SSDE1; | |
667 | SET_REG_FIELD(*udmatim, PIIX_PCI_UDMATIM_SCT1, | |
668 | PIIXUDMATimingTable[index].bits); | |
669 | } | |
670 | } | |
671 | } | |
672 | else { | |
673 | if (unit == 0) { | |
674 | if (channel == PIIX_CHANNEL_PRIMARY) { | |
675 | *udmactl &= ~PIIX_PCI_UDMACTL_PSDE0; | |
676 | } | |
677 | else { | |
678 | *udmactl &= ~PIIX_PCI_UDMACTL_SSDE0; | |
679 | } | |
680 | } | |
681 | else { | |
682 | if (channel == PIIX_CHANNEL_PRIMARY) { | |
683 | *udmactl &= ~PIIX_PCI_UDMACTL_PSDE1; | |
684 | } | |
685 | else { | |
686 | *udmactl &= ~PIIX_PCI_UDMACTL_SSDE1; | |
687 | } | |
688 | } | |
689 | } | |
690 | ||
691 | dmaActive = PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolDMA); | |
692 | pioActive = PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolPIO); | |
693 | ||
694 | if (dmaActive || pioActive) { | |
695 | ||
696 | dma = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolDMA); | |
697 | pio = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolPIO); | |
698 | ||
699 | // Early PIIX devices does not have a slave timing register. | |
700 | // Rather than switching timing registers whenever a new | |
701 | // drive was selected, We program in a (slower) timing that | |
702 | // is acceptable for both drive0 and drive1. | |
703 | ||
704 | if (pciCFID == PCI_ID_PIIX) { | |
705 | ||
706 | unit = (unit ^ 1) & 1; // unit <- other drive unit | |
707 | ||
708 | if (PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolPIO)) { | |
709 | if (!pioActive || | |
710 | (PIIX_GET_ACTIVE_TIMING(kPIIXProtocolPIO) < pio)) { | |
711 | pio = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolPIO); | |
712 | } | |
713 | pioActive = true; | |
714 | } | |
715 | ||
716 | if (PIIX_PROTOCOL_IS_ACTIVE(kPIIXProtocolDMA)) { | |
717 | if (!dmaActive || | |
718 | (PIIX_GET_ACTIVE_TIMING(kPIIXProtocolDMA) < dma)) { | |
719 | dma = PIIX_GET_ACTIVE_TIMING(kPIIXProtocolDMA); | |
720 | } | |
721 | dmaActive = true; | |
722 | } | |
723 | ||
724 | *idetim &= ~PIIX_PCI_IDETIM_SITRE; // disable slave timing | |
725 | unit = 0; | |
726 | } | |
727 | else { | |
728 | *idetim |= PIIX_PCI_IDETIM_SITRE; // enable slave timing | |
729 | } | |
730 | ||
731 | // Pick an index to the PIIXPIOTimingTable[] for the new | |
732 | // timing selection. | |
733 | // | |
734 | if (dmaActive && pioActive) { | |
735 | ||
736 | // Both PIO and DMA are active, select DMA timing to | |
737 | // optimize DMA transfer. | |
738 | ||
739 | index = dma; // pick DMA timing | |
740 | ||
741 | if (pio < dma) | |
742 | useCompatiblePIOTiming = true; | |
743 | } | |
744 | else if (dmaActive) { | |
745 | index = dma; | |
746 | } | |
747 | else { | |
748 | index = pio; | |
749 | } | |
750 | ||
751 | isp = PIIX_CLK_TO_ISP(PIIXPIOTimingTable[index].isp); | |
752 | rtc = PIIX_CLK_TO_RTC(PIIXPIOTimingTable[index].rtc); | |
753 | ||
754 | if (unit == 0) { | |
755 | SET_REG_FIELD(*idetim, PIIX_PCI_IDETIM_ISP, isp); | |
756 | SET_REG_FIELD(*idetim, PIIX_PCI_IDETIM_RTC, rtc); | |
757 | if (useCompatiblePIOTiming) | |
758 | *idetim |= PIIX_PCI_IDETIM_DTE0; | |
759 | else | |
760 | *idetim &= ~PIIX_PCI_IDETIM_DTE0; | |
761 | ||
762 | if (pciCFID == PCI_ID_PIIX) { | |
763 | if (useCompatiblePIOTiming) | |
764 | *idetim |= PIIX_PCI_IDETIM_DTE1; | |
765 | else | |
766 | *idetim &= ~PIIX_PCI_IDETIM_DTE1; | |
767 | } | |
768 | } | |
769 | else { | |
770 | if (channel == PIIX_CHANNEL_PRIMARY) { | |
771 | SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_PISP1, isp); | |
772 | SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_PRTC1, rtc); | |
773 | } | |
774 | else { | |
775 | SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_SISP1, isp); | |
776 | SET_REG_FIELD(*sidetim, PIIX_PCI_SIDETIM_SRTC1, rtc); | |
777 | } | |
778 | if (useCompatiblePIOTiming) | |
779 | *idetim |= PIIX_PCI_IDETIM_DTE1; | |
780 | else | |
781 | *idetim &= ~PIIX_PCI_IDETIM_DTE1; | |
782 | } | |
783 | ||
784 | *idetim |= (PIIX_PCI_IDETIM_TIME0 | | |
785 | PIIX_PCI_IDETIM_PPE0 | | |
786 | PIIX_PCI_IDETIM_IE0 | | |
787 | PIIX_PCI_IDETIM_TIME1 | | |
788 | PIIX_PCI_IDETIM_PPE1 | | |
789 | PIIX_PCI_IDETIM_IE1); | |
790 | } | |
791 | ||
792 | #ifdef DEBUG_XXX | |
793 | IOLog("\n%s: %s channel\n", getName(), | |
794 | (channel == PIIX_CHANNEL_PRIMARY) ? "Primary" : "Secondary"); | |
795 | IOLog("%s: IDETIM : %04x\n", getName(), *idetim); | |
796 | IOLog("%s: SIDETIM: %02x\n", getName(), *sidetim); | |
797 | IOLog("%s: UDMACTL: %02x\n", getName(), *udmactl); | |
798 | IOLog("%s: UDMATIM: %04x\n", getName(), *udmatim); | |
799 | IOLog("%s: Active : %04lx\n", getName(), timings[unit].activeFlag); | |
800 | IOLog("%s: Valid : %04lx\n", getName(), timings[unit].validFlag); | |
801 | IOLog("%s: PIO:%d DMA:%d UDMA:%d\n\n", getName(), | |
802 | timings[unit].activeTimings[kPIIXProtocolPIO], | |
803 | timings[unit].activeTimings[kPIIXProtocolDMA], | |
804 | timings[unit].activeTimings[kPIIXProtocolUDMA33]); | |
805 | #endif /* DEBUG */ | |
806 | ||
807 | return ret; | |
808 | } | |
809 | ||
810 | //-------------------------------------------------------------------------- | |
811 | // Setup the descriptor table to perform the transfer indicated by the | |
812 | // IOMemoryDescriptor in the IOATACommand object provided. | |
813 | // | |
814 | bool AppleATAPIIX::programDma(IOATAStandardCommand * cmd) | |
815 | { | |
816 | IOPhysicalSegment physSeg; | |
817 | IOByteCount offset = 0; | |
818 | IOMemoryDescriptor * memDesc; | |
819 | prdEntry_t * prd = prdTable; | |
820 | UInt32 startSeg; | |
821 | UInt32 endSeg; | |
822 | UInt32 partialCount; | |
823 | UInt32 bytesLeft; | |
824 | ||
825 | cmd->getPointers(&memDesc, &dmaReqLength, &dmaIsWrite); | |
826 | ||
827 | if (dmaReqLength == 0) | |
828 | return true; | |
829 | ||
830 | bytesLeft = dmaReqLength; | |
831 | ||
832 | // Setup the PRD entries in the descriptor table in memory. | |
833 | // | |
834 | for (UInt32 i = 0; i < (PRD_ENTRIES - 1); i++, prd++) | |
835 | { | |
836 | if (prdCursor->getPhysicalSegments(memDesc, offset, &physSeg, 1) != 1) | |
837 | break; | |
838 | ||
839 | startSeg = (physSeg.location & ~0xffff); | |
840 | endSeg = (physSeg.location + physSeg.length - 1) & ~0xffff; | |
841 | ||
842 | prd->base = physSeg.location; | |
843 | prd->flags = 0; | |
844 | ||
845 | if (startSeg == endSeg) { | |
846 | prd->count = PRD_COUNT(physSeg.length); | |
847 | } | |
848 | else { | |
849 | partialCount = (-physSeg.location & 0xffff); | |
850 | prd->count = PRD_COUNT(partialCount); | |
851 | prd++; | |
852 | i++; | |
853 | prd->base = physSeg.location + partialCount; | |
854 | prd->count = physSeg.length - partialCount; | |
855 | prd->flags = 0; | |
856 | } | |
857 | ||
858 | bytesLeft -= physSeg.length; | |
859 | offset += physSeg.length; | |
860 | } | |
861 | if (bytesLeft != 0) | |
862 | return false; | |
863 | ||
864 | // Set the 'end-of-table' bit on the last PRD entry. | |
865 | // | |
866 | prd--; | |
867 | prd->flags = PRD_FLAG_EOT; | |
868 | ||
869 | /* | |
870 | * Provide the starting address of the PRD table by loading the | |
871 | * PRD Table Pointer Register. | |
872 | */ | |
873 | outl(IOREG(BMIDTPX), prdTablePhys); | |
874 | ||
875 | return true; | |
876 | } | |
877 | ||
878 | //-------------------------------------------------------------------------- | |
879 | // Start the DMA engine. | |
880 | // | |
881 | bool AppleATAPIIX::startDma(IOATAStandardCommand * cmd) | |
882 | { | |
883 | /* | |
884 | * Clear interrupt and error bits in the Status Register. | |
885 | */ | |
886 | outb(IOREG(BMISX), PIIX_IO_BMISX_ERROR | | |
887 | PIIX_IO_BMISX_IDEINTS | | |
888 | PIIX_IO_BMISX_DMA0CAP | | |
889 | PIIX_IO_BMISX_DMA1CAP); | |
890 | ||
891 | /* | |
892 | * Engage the bus master by writing 1 to the start bit in the | |
893 | * Command Register. Also set the RWCON bit for the direction | |
894 | * of the data transfer. | |
895 | */ | |
896 | outb(IOREG(BMICX), (dmaIsWrite ? 0 : PIIX_IO_BMICX_RWCON) | | |
897 | PIIX_IO_BMICX_SSBM); | |
898 | ||
899 | return true; | |
900 | } | |
901 | ||
902 | //-------------------------------------------------------------------------- | |
903 | // Stop the DMA engine. | |
904 | // | |
905 | bool AppleATAPIIX::stopDma(IOATAStandardCommand * cmd, UInt32 * transferCount) | |
906 | { | |
907 | UInt8 bmisx; | |
908 | ||
909 | *transferCount = 0; | |
910 | ||
911 | if (dmaReqLength == 0) | |
912 | return true; | |
913 | ||
914 | outb(IOREG(BMICX), 0); // stop the bus-master | |
915 | ||
916 | bmisx = inb(IOREG(BMISX)); | |
917 | ||
918 | if ((bmisx & PIIX_IO_BMISX_STATUS) != PIIX_IO_BMISX_IDEINTS) { | |
919 | IOLog("AppleATAPIIX::%s() DMA error (0x%02x)\n", __FUNCTION__, bmisx); | |
920 | return false; | |
921 | } | |
922 | ||
923 | *transferCount = dmaReqLength; | |
924 | ||
925 | return true; | |
926 | } | |
927 | ||
928 | //-------------------------------------------------------------------------- | |
929 | // Perform a write to the ATA block registers. | |
930 | // | |
931 | void AppleATAPIIX::writeATAReg(UInt32 regIndex, UInt32 regValue) | |
932 | { | |
933 | if (regIndex == 0) { | |
934 | outw(ioCmdRange, (UInt16) regValue); | |
935 | } | |
936 | else if (regIndex < kATARegDeviceControl) { | |
937 | outb(ioCmdRange + regIndex, (UInt8) regValue); | |
938 | } | |
939 | else { | |
940 | outb(ioCtlRange + regIndex - kATARegDeviceControl + 2, | |
941 | (UInt8) regValue); | |
942 | } | |
943 | } | |
944 | ||
945 | //-------------------------------------------------------------------------- | |
946 | // Perform a read from the ATA block registers. | |
947 | // | |
948 | UInt32 AppleATAPIIX::readATAReg( UInt32 regIndex ) | |
949 | { | |
950 | if (regIndex == 0) { | |
951 | return inw(ioCmdRange); | |
952 | } | |
953 | else if (regIndex < kATARegDeviceControl) { | |
954 | return inb(ioCmdRange + regIndex); | |
955 | } | |
956 | return inb(ioCtlRange + regIndex - kATARegDeviceControl + 2); | |
957 | } | |
958 | ||
959 | //-------------------------------------------------------------------------- | |
960 | // Frees the drivers instance. Make sure all objects allocated during | |
961 | // our initialization are freed. | |
962 | // | |
963 | void AppleATAPIIX::free() | |
964 | { | |
965 | if (interruptEventSource) { | |
966 | interruptEventSource->disable(); | |
967 | interruptEventSource->release(); | |
968 | } | |
969 | ||
970 | if (prdCursor) | |
971 | prdCursor->release(); | |
972 | ||
973 | if (prdTable != 0) | |
974 | _deallocatePRDTable(); | |
975 | ||
976 | return super::free(); | |
977 | } | |
978 | ||
979 | //-------------------------------------------------------------------------- | |
980 | // This function is called when our interruptEventSource receives an | |
981 | // interrupt. Simply pass the action to our superclass to advance its | |
982 | // state machine. | |
983 | // | |
984 | void AppleATAPIIX::interruptOccurred() | |
985 | { | |
986 | super::interruptOccurred(); | |
987 | } | |
988 | ||
989 | //-------------------------------------------------------------------------- | |
990 | // This function is called by our superclass to disable controller | |
991 | // interrupts. | |
992 | // | |
993 | void AppleATAPIIX::disableControllerInterrupts() | |
994 | { | |
995 | interruptEventSource->disable(); | |
996 | } | |
997 | ||
998 | //-------------------------------------------------------------------------- | |
999 | // This function is called by our superclass to enable controller | |
1000 | // interrupts. | |
1001 | // | |
1002 | void AppleATAPIIX::enableControllerInterrupts() | |
1003 | { | |
1004 | interruptEventSource->enable(); | |
1005 | } | |
1006 | ||
1007 | //-------------------------------------------------------------------------- | |
1008 | // Private function: _readPCIConfigSpace | |
1009 | // | |
1010 | // Read the entire PCI config space and stores it to the buffer | |
1011 | // pointed by 'configSpace'. | |
1012 | // | |
1013 | bool AppleATAPIIX::_readPCIConfigSpace(UInt8 * configSpace) | |
1014 | { | |
1015 | UInt32 * dwordPtr = (UInt32 *) configSpace; | |
1016 | ||
1017 | for (int i = 0; i < 64; i++, dwordPtr++) | |
1018 | *dwordPtr = provider->configRead32(i * 4); | |
1019 | ||
1020 | return true; | |
1021 | } | |
1022 | ||
1023 | //-------------------------------------------------------------------------- | |
1024 | // Private function: _writePCIConfigSpace | |
1025 | // | |
1026 | // Write the entire PCI config space from the buffer pointed | |
1027 | // by 'configSpace'. | |
1028 | // | |
1029 | bool AppleATAPIIX::_writePCIConfigSpace(UInt8 * configSpace) | |
1030 | { | |
1031 | UInt32 * dwordPtr = (UInt32 *) configSpace; | |
1032 | ||
1033 | for (int i = 0; i < 64; i++, dwordPtr++) | |
1034 | provider->configWrite32(i * 4, *dwordPtr); | |
1035 | ||
1036 | return true; | |
1037 | } |