xref: /haiku/src/add-ons/kernel/busses/mmc/sdhci.cpp (revision 9f3bdf3d039430b5172c424def20ce5d9f7367d4)
1 /*
2  * Copyright 2018-2024 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		B Krishnan Iyer, krishnaniyer97@gmail.com
7  *		Adrien Destugues, pulkomandy@pulkomandy.tk
8  *		Ron Ben Aroya, sed4906birdie@gmail.com
9  */
10 #include <algorithm>
11 #include <new>
12 #include <stdio.h>
13 #include <string.h>
14 
15 #include <bus/PCI.h>
16 #include <ACPI.h>
17 #include "acpi.h"
18 
19 #include <KernelExport.h>
20 
21 #include "IOSchedulerSimple.h"
22 #include "mmc.h"
23 #include "sdhci.h"
24 
25 
26 #define TRACE_SDHCI
27 #ifdef TRACE_SDHCI
28 #	define TRACE(x...) dprintf("\33[33msdhci:\33[0m " x)
29 #else
30 #	define TRACE(x...) ;
31 #endif
32 #define TRACE_ALWAYS(x...)	dprintf("\33[33msdhci:\33[0m " x)
33 #define ERROR(x...)			dprintf("\33[33msdhci:\33[0m " x)
34 #define CALLED(x...)		TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
35 
36 
37 #define SDHCI_DEVICE_MODULE_NAME "busses/mmc/sdhci/driver_v1"
38 #define SDHCI_ACPI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci/acpi/device/v1"
39 #define SDHCI_PCI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci/pci/device/v1"
40 
41 #define SLOT_NUMBER				"device/slot"
42 #define BAR_INDEX				"device/bar"
43 
44 device_manager_info* gDeviceManager;
45 device_module_info* gMMCBusController;
46 
47 static int32
48 sdhci_generic_interrupt(void* data)
49 {
50 	SdhciBus* bus = (SdhciBus*)data;
51 	return bus->HandleInterrupt();
52 }
53 
54 
55 SdhciBus::SdhciBus(struct registers* registers, uint8_t irq, bool poll)
56 	:
57 	fRegisters(registers),
58 	fIrq(irq),
59 	fSemaphore(0)
60 {
61 	if (irq == 0 || irq == 0xff) {
62 		ERROR("IRQ not assigned\n");
63 		fStatus = B_BAD_DATA;
64 		return;
65 	}
66 
67 	fSemaphore = create_sem(0, "SDHCI interrupts");
68 
69 	DisableInterrupts();
70 
71 	fStatus = install_io_interrupt_handler(fIrq,
72 		sdhci_generic_interrupt, this, 0);
73 
74 	if (fStatus != B_OK) {
75 		ERROR("can't install interrupt handler\n");
76 		return;
77 	}
78 
79 	// First of all, we have to make sure we are in a sane state. The easiest
80 	// way is to reset everything.
81 	Reset();
82 
83 	// Turn on the power supply to the card, if there is a card inserted
84 	if (PowerOn()) {
85 		// Then we configure the clock to the frequency needed for
86 		// initialization
87 		SetClock(400);
88 	}
89 
90 	// Finally, configure some useful interrupts
91 	EnableInterrupts(SDHCI_INT_CMD_CMP | SDHCI_INT_CARD_REM
92 		| SDHCI_INT_TRANS_CMP);
93 
94 	// We want to see the error bits in the status register, but not have an
95 	// interrupt trigger on them (we get a "command complete" interrupt on
96 	// errors already)
97 	fRegisters->interrupt_status_enable |= SDHCI_INT_ERROR
98 		| SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
99 		| SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
100 
101 	if (poll) {
102 		// Spawn a polling thread, as the interrupts won't currently work on ACPI.
103 		fWorkerThread = spawn_kernel_thread(_WorkerThread, "SD bus poller",
104 			B_NORMAL_PRIORITY, this);
105 		resume_thread(fWorkerThread);
106 	}
107 }
108 
109 
110 SdhciBus::~SdhciBus()
111 {
112 	DisableInterrupts();
113 
114 	if (fSemaphore != 0)
115 		delete_sem(fSemaphore);
116 
117 	if (fIrq != 0)
118 		remove_io_interrupt_handler(fIrq, sdhci_generic_interrupt, this);
119 
120 	area_id regs_area = area_for(fRegisters);
121 	delete_area(regs_area);
122 
123 	fStatus = B_SHUTTING_DOWN;
124 
125 	status_t result;
126 	if (fWorkerThread != 0)
127 		wait_for_thread(fWorkerThread, &result);
128 }
129 
130 
131 void
132 SdhciBus::EnableInterrupts(uint32_t mask)
133 {
134 	fRegisters->interrupt_status_enable |= mask;
135 	fRegisters->interrupt_signal_enable |= mask;
136 }
137 
138 
139 void
140 SdhciBus::DisableInterrupts()
141 {
142 	fRegisters->interrupt_status_enable = 0;
143 	fRegisters->interrupt_signal_enable = 0;
144 }
145 
146 
147 // #pragma mark -
148 /*
149 PartA2, SD Host Controller Simplified Specification, Version 4.20
150 §3.7.1.1 The sequence to issue an SD Command
151 */
152 status_t
153 SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
154 {
155 	TRACE("ExecuteCommand(%d, %x)\n", command, argument);
156 
157 	// First of all clear the result
158 	fCommandResult = 0;
159 
160 	// Check if it's possible to send a command right now.
161 	// It is not possible to send a command as long as the command line is busy.
162 	// The spec says we should wait, but we can't do that on kernel side, since
163 	// it leaves no chance for the upper layers to handle the problem. So we
164 	// just say we're busy and the caller can retry later.
165 	// Note that this should normally never happen: the command line is busy
166 	// only during command execution, and we don't leave this function with ac
167 	// command running.
168 	if (fRegisters->present_state.CommandInhibit()) {
169 		panic("Command execution impossible, command inhibit\n");
170 		return B_BUSY;
171 	}
172 	if (fRegisters->present_state.DataInhibit()) {
173 		panic("Command execution unwise, data inhibit\n");
174 		return B_BUSY;
175 	}
176 
177 	uint32_t replyType;
178 
179 	switch (command) {
180 		case SD_GO_IDLE_STATE:
181 			replyType = Command::kNoReplyType;
182 			break;
183 		case SD_ALL_SEND_CID:
184 		case SD_SEND_CSD:
185 			replyType = Command::kR2Type;
186 			break;
187 		case SD_SEND_RELATIVE_ADDR:
188 			replyType = Command::kR6Type;
189 			break;
190 		case SD_SELECT_DESELECT_CARD:
191 		case SD_ERASE:
192 			replyType = Command::kR1bType;
193 			break;
194 		case SD_SEND_IF_COND:
195 			replyType = Command::kR7Type;
196 			break;
197 		case SD_READ_SINGLE_BLOCK:
198 		case SD_READ_MULTIPLE_BLOCKS:
199 		case SD_WRITE_SINGLE_BLOCK:
200 		case SD_WRITE_MULTIPLE_BLOCKS:
201 			replyType = Command::kR1Type | Command::kDataPresent;
202 			break;
203 		case SD_APP_CMD:
204 		case SD_ERASE_WR_BLK_START:
205 		case SD_ERASE_WR_BLK_END:
206 		case SD_SET_BUS_WIDTH: // SD Application command
207 			replyType = Command::kR1Type;
208 			break;
209 		case SD_SEND_OP_COND: // SD Application command
210 			replyType = Command::kR3Type;
211 			break;
212 		default:
213 			ERROR("Unknown command %x\n", command);
214 			return B_BAD_DATA;
215 	}
216 
217 	// Check if DATA line is available (if needed)
218 	if ((replyType & Command::k32BitResponseCheckBusy) != 0
219 		&& command != SD_STOP_TRANSMISSION && command != SD_IO_ABORT) {
220 		if (fRegisters->present_state.DataInhibit()) {
221 			ERROR("Execution aborted, data inhibit\n");
222 			return B_BUSY;
223 		}
224 	}
225 
226 	if (fRegisters->present_state.CommandInhibit())
227 		panic("Command line busy at start of execute command\n");
228 
229 	if (replyType == Command::kR1bType)
230 		fRegisters->transfer_mode = 0;
231 
232 	fRegisters->argument = argument;
233 	fRegisters->command.SendCommand(command, replyType);
234 
235 	// Wait for command response to be available ("command complete" interrupt)
236 	TRACE("Wait for command complete...");
237 	do {
238 		//fCommandResult = fRegisters->interrupt_status;
239 		acquire_sem(fSemaphore);
240 		TRACE("command complete sem acquired, status: %x\n", fCommandResult);
241 		TRACE("real status = %x command line busy: %d\n",
242 			fRegisters->interrupt_status,
243 			fRegisters->present_state.CommandInhibit());
244 	} while (fCommandResult == 0);
245 
246 	TRACE("Command response available\n");
247 
248 	if (fCommandResult & SDHCI_INT_ERROR) {
249 		fRegisters->interrupt_status |= fCommandResult;
250 		if (fCommandResult & SDHCI_INT_TIMEOUT) {
251 			ERROR("Command execution timed out\n");
252 			if (fRegisters->present_state.CommandInhibit()) {
253 				TRACE("Command line is still busy, clearing it\n");
254 				// Clear the stall
255 				fRegisters->software_reset.ResetCommandLine();
256 			}
257 			return B_TIMED_OUT;
258 		}
259 		if (fCommandResult & SDHCI_INT_CRC) {
260 			ERROR("CRC error\n");
261 			return B_BAD_VALUE;
262 		}
263 		ERROR("Command execution failed %x\n", fCommandResult);
264 		// TODO look at errors in interrupt_status register for more details
265 		// and return a more appropriate error code
266 		return B_ERROR;
267 	}
268 
269 	if (fRegisters->present_state.CommandInhibit()) {
270 		TRACE("Command execution failed, card stalled\n");
271 		// Clear the stall
272 		fRegisters->software_reset.ResetCommandLine();
273 		return B_ERROR;
274 	}
275 
276 	switch (replyType & Command::kReplySizeMask) {
277 		case Command::k32BitResponse:
278 			*response = fRegisters->response[0];
279 			break;
280 		case Command::k128BitResponse:
281 			response[0] = fRegisters->response[0];
282 			response[1] = fRegisters->response[1];
283 			response[2] = fRegisters->response[2];
284 			response[3] = fRegisters->response[3];
285 			break;
286 
287 		default:
288 			// No response
289 			break;
290 	}
291 
292 	if (replyType == Command::kR1bType
293 			&& (fCommandResult & SDHCI_INT_TRANS_CMP) == 0) {
294 		// R1b commands may use the data line so we must wait for the
295 		// "transfer complete" interrupt here.
296 		TRACE("Waiting for data line...\n");
297 		do {
298 			acquire_sem(fSemaphore);
299 		} while (fRegisters->present_state.DataInhibit());
300 		TRACE("Dataline is released.\n");
301 	}
302 
303 	ERROR("Command execution %d complete\n", command);
304 	return B_OK;
305 }
306 
307 
308 status_t
309 SdhciBus::InitCheck()
310 {
311 	return fStatus;
312 }
313 
314 
315 void
316 SdhciBus::Reset()
317 {
318 	if (!fRegisters->software_reset.ResetAll())
319 		ERROR("SdhciBus::Reset: SoftwareReset timeout\n");
320 }
321 
322 
323 void
324 SdhciBus::SetClock(int kilohertz)
325 {
326 	int base_clock = fRegisters->capabilities.BaseClockFrequency();
327 	// Try to get as close to 400kHz as possible, but not faster
328 	int divider = base_clock * 1000 / kilohertz;
329 
330 	if (fRegisters->host_controller_version.specVersion <= 1) {
331 		// Old controller only support power of two dividers up to 256,
332 		// round to next power of two up to 256
333 		if (divider > 256)
334 			divider = 256;
335 
336 		divider--;
337 		divider |= divider >> 1;
338 		divider |= divider >> 2;
339 		divider |= divider >> 4;
340 		divider++;
341 	}
342 
343 	divider = fRegisters->clock_control.SetDivider(divider);
344 
345 	// Log the value after possible rounding by SetDivider (only even values
346 	// are allowed).
347 	TRACE("SDCLK frequency: %dMHz / %d = %dkHz\n", base_clock, divider,
348 		base_clock * 1000 / divider);
349 
350 	// We have set the divider, now we can enable the internal clock.
351 	fRegisters->clock_control.EnableInternal();
352 
353 	// wait until internal clock is stabilized
354 	while (!(fRegisters->clock_control.InternalStable()));
355 
356 	fRegisters->clock_control.EnablePLL();
357 	while (!(fRegisters->clock_control.InternalStable()));
358 
359 	// Finally, route the clock to the SD card
360 	fRegisters->clock_control.EnableSD();
361 }
362 
363 
364 status_t
365 SdhciBus::DoIO(uint8_t command, IOOperation* operation, bool offsetAsSectors)
366 {
367 	bool isWrite = operation->IsWrite();
368 
369 	static const uint32 kBlockSize = 512;
370 	off_t offset = operation->Offset();
371 	generic_size_t length = operation->Length();
372 
373 	TRACE("%s %" B_PRIu64 " bytes at %" B_PRIdOFF "\n",
374 		isWrite ? "Write" : "Read", length, offset);
375 
376 	// Check that the IO scheduler did its job in following our DMA restrictions
377 	// We can start a read only at a sector boundary
378 	ASSERT(offset % kBlockSize == 0);
379 	// We can only read complete sectors
380 	ASSERT(length % kBlockSize == 0);
381 
382 	const generic_io_vec* vecs = operation->Vecs();
383 	generic_size_t vecOffset = 0;
384 
385 	// FIXME can this be moved to the init function instead?
386 	//
387 	// For simplicity we use a transfer size equal to the sector size. We could
388 	// go up to 2K here if the length to read in each individual vec is a
389 	// multiple of 2K, but we have no easy way to know this (we would need to
390 	// iterate through the IOOperation vecs and check the size of each of them).
391 	// We could also do smaller transfers, but it is not possible to start a
392 	// transfer anywhere else than the start of a sector, so it's a lot simpler
393 	// to always work in complete sectors. We set the B_DMA_ALIGNMENT device
394 	// node property accordingly, making sure that we don't get asked to do
395 	// transfers that are not aligned with sectors.
396 	//
397 	// Additionnally, set SDMA buffer boundary aligment to 512K. This is the
398 	// largest possible size. We also set the B_DMA_BOUNDARY property on the
399 	// published device node, so that the DMA resource manager knows that it
400 	// must respect this boundary. As a result, we will never be asked to
401 	// do a transfer that crosses this boundary, and we don't need to handle
402 	// the DMA boundary interrupt (the transfer will be split in two at an
403 	// upper layer).
404 	fRegisters->block_size.ConfigureTransfer(kBlockSize,
405 		BlockSize::kDmaBoundary512K);
406 	status_t result = B_OK;
407 
408 	while (length > 0) {
409 		size_t toCopy = std::min((generic_size_t)length,
410 			vecs->length - vecOffset);
411 
412 		// If the current vec is empty, we can move to the next
413 		if (toCopy == 0) {
414 			vecs++;
415 			vecOffset = 0;
416 			continue;
417 		}
418 
419 		// With SDMA we can only transfer multiples of 1 sector
420 		ASSERT(toCopy % kBlockSize == 0);
421 
422 		fRegisters->system_address = vecs->base + vecOffset;
423 		// fRegisters->adma_system_address = fDmaMemory;
424 
425 		fRegisters->block_count = toCopy / kBlockSize;
426 
427 		uint16 direction;
428 		if (isWrite)
429 			direction = TransferMode::kWrite;
430 		else
431 			direction = TransferMode::kRead;
432 		fRegisters->transfer_mode = TransferMode::kMulti | direction
433 			| TransferMode::kAutoCmd12Enable
434 			| TransferMode::kBlockCountEnable | TransferMode::kDmaEnable;
435 
436 		uint32_t response;
437 		result = ExecuteCommand(command,
438 			offset / (offsetAsSectors ? kBlockSize : 1), &response);
439 		if (result != B_OK)
440 			break;
441 
442 		// Wait for DMA transfer to complete
443 		// In theory we could go on and send other commands as long as they
444 		// don't need the DAT lines, but it's overcomplicating things.
445 		TRACE("Wait for transfer complete...");
446 		//while ((fRegisters->interrupt_status & SDHCI_INT_TRANS_CMP) == 0);
447 		acquire_sem(fSemaphore);
448 		TRACE("transfer complete OK.\n");
449 
450 		length -= toCopy;
451 		vecOffset += toCopy;
452 		offset += toCopy;
453 	}
454 
455 	return result;
456 }
457 
458 
459 void
460 SdhciBus::SetScanSemaphore(sem_id sem)
461 {
462 	fScanSemaphore = sem;
463 
464 	// If there is already a card in, start a scan immediately
465 	if (fRegisters->present_state.IsCardInserted())
466 		release_sem(fScanSemaphore);
467 
468 	// We can now enable the card insertion interrupt for next time a card
469 	// is inserted
470 	EnableInterrupts(SDHCI_INT_CARD_INS);
471 }
472 
473 
474 void
475 SdhciBus::SetBusWidth(int width)
476 {
477 	uint8_t widthBits;
478 	switch(width) {
479 		case 1:
480 			widthBits = HostControl::kDataTransfer1Bit;
481 			break;
482 		case 4:
483 			widthBits = HostControl::kDataTransfer4Bit;
484 			break;
485 		case 8:
486 			widthBits = HostControl::kDataTransfer8Bit;
487 			break;
488 		default:
489 			panic("Incorrect bitwidth value");
490 			return;
491 	}
492 	fRegisters->host_control.SetDataTransferWidth(widthBits);
493 }
494 
495 
496 bool
497 SdhciBus::PowerOn()
498 {
499 	if (!fRegisters->present_state.IsCardInserted()) {
500 		TRACE("Card not inserted, not powering on for now\n");
501 		return false;
502 	}
503 
504 	uint8_t supportedVoltages = fRegisters->capabilities.SupportedVoltages();
505 	if ((supportedVoltages & Capabilities::k3v3) != 0)
506 		fRegisters->power_control.SetVoltage(PowerControl::k3v3);
507 	else if ((supportedVoltages & Capabilities::k3v0) != 0)
508 		fRegisters->power_control.SetVoltage(PowerControl::k3v0);
509 	else if ((supportedVoltages & Capabilities::k1v8) != 0)
510 		fRegisters->power_control.SetVoltage(PowerControl::k1v8);
511 	else {
512 		fRegisters->power_control.PowerOff();
513 		ERROR("No voltage is supported\n");
514 		return false;
515 	}
516 
517 	return true;
518 }
519 
520 
521 void
522 SdhciBus::RecoverError()
523 {
524 	fRegisters->interrupt_signal_enable &= ~(SDHCI_INT_CMD_CMP
525 		| SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM);
526 
527 	if (fRegisters->interrupt_status & 7)
528 		fRegisters->software_reset.ResetCommandLine();
529 
530 	int16_t error_status = fRegisters->interrupt_status;
531 	fRegisters->interrupt_status &= ~(error_status);
532 }
533 
534 
535 int32
536 SdhciBus::HandleInterrupt()
537 {
538 #if 0
539 	// We could use the slot register to quickly see for which slot the
540 	// interrupt is. But since we have an interrupt handler call for each slot
541 	// anyway, it's just as simple to let each of them scan its own interrupt
542 	// status register.
543 	if ( !(fRegisters->slot_interrupt_status & (1 << fSlot)) ) {
544 		TRACE("interrupt not for me.\n");
545 		return B_UNHANDLED_INTERRUPT;
546 	}
547 #endif
548 
549 	uint32_t intmask = fRegisters->interrupt_status;
550 
551 	// Shortcut: exit early if there is no interrupt or if the register is
552 	// clearly invalid.
553 	if ((intmask == 0) || (intmask == 0xffffffff)) {
554 		return B_UNHANDLED_INTERRUPT;
555 	}
556 
557 	TRACE("interrupt function called %x\n", intmask);
558 
559 	// handling card presence interrupts
560 	if ((intmask & SDHCI_INT_CARD_REM) != 0) {
561 		// We can get spurious interrupts as the card is inserted or removed,
562 		// so check the actual state before acting
563 		if (!fRegisters->present_state.IsCardInserted())
564 			fRegisters->power_control.PowerOff();
565 		else
566 			TRACE("Card removed interrupt, but card is inserted\n");
567 
568 		fRegisters->interrupt_status |= SDHCI_INT_CARD_REM;
569 		TRACE("Card removal interrupt handled\n");
570 	}
571 
572 	if ((intmask & SDHCI_INT_CARD_INS) != 0) {
573 		// We can get spurious interrupts as the card is inserted or removed,
574 		// so check the actual state before acting
575 		if (fRegisters->present_state.IsCardInserted()) {
576 			if (PowerOn())
577 				SetClock(400);
578 			release_sem_etc(fScanSemaphore, 1, B_DO_NOT_RESCHEDULE);
579 		} else
580 			TRACE("Card insertion interrupt, but card is removed\n");
581 
582 		fRegisters->interrupt_status |= SDHCI_INT_CARD_INS;
583 		TRACE("Card presence interrupt handled\n");
584 	}
585 
586 	// handling command interrupt
587 	if (intmask & SDHCI_INT_CMD_MASK) {
588 		fCommandResult = intmask;
589 			// Save the status before clearing so the thread can handle it
590 		fRegisters->interrupt_status |= (intmask & SDHCI_INT_CMD_MASK);
591 
592 		// Notify the thread
593 		release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE);
594 		TRACE("Command complete interrupt handled\n");
595 	}
596 
597 	if (intmask & SDHCI_INT_TRANS_CMP) {
598 		fCommandResult = intmask;
599 		fRegisters->interrupt_status |= SDHCI_INT_TRANS_CMP;
600 		release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE);
601 		TRACE("Transfer complete interrupt handled\n");
602 	}
603 
604 	// handling bus power interrupt
605 	if (intmask & SDHCI_INT_BUS_POWER) {
606 		fRegisters->interrupt_status |= SDHCI_INT_BUS_POWER;
607 		TRACE("card is consuming too much power\n");
608 	}
609 
610 	// Check that all interrupts have been cleared (we check all the ones we
611 	// enabled, so that should always be the case)
612 	intmask = fRegisters->interrupt_status;
613 	if (intmask != 0) {
614 		ERROR("Remaining interrupts at end of handler: %x\n", intmask);
615 	}
616 
617 	return B_HANDLED_INTERRUPT;
618 }
619 
620 status_t
621 SdhciBus::_WorkerThread(void* cookie) {
622 	SdhciBus* bus = (SdhciBus*)cookie;
623 	while (bus->fStatus != B_SHUTTING_DOWN) {
624 		uint32_t intmask = bus->fRegisters->interrupt_status;
625 		if (intmask & SDHCI_INT_CMD_CMP) {
626 			bus->fCommandResult = intmask;
627 			bus->fRegisters->interrupt_status |= (intmask & SDHCI_INT_CMD_MASK);
628 			release_sem(bus->fSemaphore);
629 		}
630 		if (intmask & SDHCI_INT_TRANS_CMP) {
631 			bus->fCommandResult = intmask;
632 			bus->fRegisters->interrupt_status |= SDHCI_INT_TRANS_CMP;
633 			release_sem(bus->fSemaphore);
634 		}
635 		snooze(100);
636 	}
637 	TRACE("poller thread terminating");
638 	return B_OK;
639 }
640 
641 // #pragma mark -
642 
643 void
644 uninit_bus(void* bus_cookie)
645 {
646 	SdhciBus* bus = (SdhciBus*)bus_cookie;
647 	delete bus;
648 
649 	// FIXME do we need to put() the PCI module here?
650 }
651 
652 
653 void
654 bus_removed(void* bus_cookie)
655 {
656 	return;
657 }
658 
659 static status_t
660 register_child_devices(void* cookie)
661 {
662 	CALLED();
663 	SdhciDevice* context = (SdhciDevice*)cookie;
664 	status_t status = B_OK;
665 	const char* bus;
666 	device_node* parent = gDeviceManager->get_parent_node(context->fNode);
667 	status = gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false);
668 	if (status != B_OK) {
669 		TRACE("Could not find required attribute device/bus\n");
670 		return status;
671 	}
672 
673 	if (strcmp(bus, "pci") == 0)
674 		status = register_child_devices_pci(cookie);
675 	else if (strcmp(bus, "acpi") == 0)
676 		status = register_child_devices_acpi(cookie);
677 	else
678 		status = B_BAD_VALUE;
679 
680 	return status;
681 }
682 
683 static status_t
684 init_device(device_node* node, void** device_cookie)
685 {
686 	CALLED();
687 
688 	SdhciDevice* context = new(std::nothrow)SdhciDevice;
689 	if (context == NULL)
690 		return B_NO_MEMORY;
691 	context->fNode = node;
692 	*device_cookie = context;
693 
694 	status_t status = B_OK;
695 	const char* bus;
696 	device_node* parent = gDeviceManager->get_parent_node(node);
697 	status = gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false);
698 	if (status != B_OK) {
699 		TRACE("Could not find required attribute device/bus\n");
700 		return status;
701 	}
702 
703 	if (strcmp(bus, "pci") == 0)
704 		return init_device_pci(node, context);
705 
706 	return B_OK;
707 }
708 
709 static void
710 uninit_device(void* device_cookie)
711 {
712 	SdhciDevice* context = (SdhciDevice*)device_cookie;
713 	device_node* parent = gDeviceManager->get_parent_node(context->fNode);
714 
715 	const char* bus;
716 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK) {
717 		TRACE("Could not find required attribute device/bus\n");
718 	}
719 
720 	if (strcmp(bus, "pci") == 0)
721 		uninit_device_pci(context, parent);
722 
723 	gDeviceManager->put_node(parent);
724 
725 	delete context;
726 }
727 
728 
729 static status_t
730 register_device(device_node* parent)
731 {
732 	device_attr attrs[] = {
733 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "SD Host Controller"}},
734 		{}
735 	};
736 
737 	return gDeviceManager->register_node(parent, SDHCI_DEVICE_MODULE_NAME,
738 		attrs, NULL, NULL);
739 }
740 
741 static float
742 supports_device(device_node* parent)
743 {
744 	const char* bus;
745 
746 	// make sure parent is either an ACPI or PCI SDHCI device node
747 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
748 		!= B_OK) {
749 		TRACE("Could not find required attribute device/bus\n");
750 		return -1;
751 	}
752 
753 	if (strcmp(bus, "pci") == 0)
754 		return supports_device_pci(parent);
755 	else if (strcmp(bus, "acpi") == 0)
756 		return supports_device_acpi(parent);
757 
758 	return 0.0f;
759 }
760 
761 
762 module_dependency module_dependencies[] = {
763 	{ MMC_BUS_MODULE_NAME, (module_info**)&gMMCBusController},
764 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
765 	{}
766 };
767 
768 status_t
769 set_clock(void* controller, uint32_t kilohertz)
770 {
771 	SdhciBus* bus = (SdhciBus*)controller;
772 	bus->SetClock(kilohertz);
773 	return B_OK;
774 }
775 
776 
777 status_t
778 execute_command(void* controller, uint8_t command, uint32_t argument,
779 	uint32_t* response)
780 {
781 	SdhciBus* bus = (SdhciBus*)controller;
782 	return bus->ExecuteCommand(command, argument, response);
783 }
784 
785 
786 status_t
787 do_io(void* controller, uint8_t command, IOOperation* operation,
788 	bool offsetAsSectors)
789 {
790 	SdhciBus* bus = (SdhciBus*)controller;
791 	return bus->DoIO(command, operation, offsetAsSectors);
792 }
793 
794 
795 void
796 set_scan_semaphore(void* controller, sem_id sem)
797 {
798 	SdhciBus* bus = (SdhciBus*)controller;
799 	return bus->SetScanSemaphore(sem);
800 }
801 
802 
803 void
804 set_bus_width(void* controller, int width)
805 {
806 	SdhciBus* bus = (SdhciBus*)controller;
807 	return bus->SetBusWidth(width);
808 }
809 
810 // Root device that binds to the ACPI or PCI bus. It will register an mmc_bus_interface
811 // node for each SD slot in the device.
812 static driver_module_info sSDHCIDevice = {
813 	{
814 		SDHCI_DEVICE_MODULE_NAME,
815 		0,
816 		NULL
817 	},
818 	supports_device,
819 	register_device,
820 	init_device,
821 	uninit_device,
822 	register_child_devices,
823 	NULL,	// rescan
824 	NULL,	// device removed
825 };
826 
827 
828 module_info* modules[] = {
829 	(module_info* )&sSDHCIDevice,
830 	(module_info* )&gSDHCIPCIDeviceModule,
831 	(module_info* )&gSDHCIACPIDeviceModule,
832 	NULL
833 };
834