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