hrev52171 adds 1 changeset to branch 'master'
old head: 42cc463169541d13948b6a9d43231f7343c995f7
new head: 25b6a6f19b13680a759cffecebf60d0b7e76d3d3
overview:
https://git.haiku-os.org/haiku/log/?qt=range&q=25b6a6f19b13+%5E42cc46316954
----------------------------------------------------------------------------
25b6a6f19b13: SDHCI MMC Driver
1. SDHCI PCI Bus: Discovering SDHC device from the PCI bus
and registers a child node(MMC bus) to which slots
are attached. SDHC registers are mapped by MMUIO,
they are binded in a structure(struct* registers).
A pin based interrupt handler is also installed,
which triggers the handler function and interrupts
are being taken care of. Added API's to set-up and
the clock for SD/MMC card, change frequency and
reset the registers.
2. Device Manager: Currently, busses subdir lists are har-
dcoded and in order to load the driver. We hard
coded the bus dir under PCI devices.
3. MMC Disk Driver: In order to register the slots under
/dev/disk/mmc and hence data transfer and other
operations can be done.
4. MMC Bus Manager: Setted up a bus manager to create an object
to do a particular for eg certain data transfer and
get freed until another operation is requested.
Change-Id: I369354da6b79adc6b6dfb08fe160334af1392a34
Reviewed-on: https://review.haiku-os.org/318
Reviewed-by: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
[ krish_iyer <krishnaniyer97@xxxxxxxxx> ]
----------------------------------------------------------------------------
Revision: hrev52171
Commit: 25b6a6f19b13680a759cffecebf60d0b7e76d3d3
URL: https://git.haiku-os.org/haiku/commit/?id=25b6a6f19b13
Author: krish_iyer <krishnaniyer97@xxxxxxxxx>
Date: Sat Apr 28 13:54:09 2018 UTC
Committer: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx>
Commit-Date: Sun Aug 5 20:56:54 2018 UTC
----------------------------------------------------------------------------
14 files changed, 1118 insertions(+), 3 deletions(-)
src/add-ons/kernel/bus_managers/Jamfile | 1 +
src/add-ons/kernel/bus_managers/mmc/Jamfile | 8 +
src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp | 43 ++
src/add-ons/kernel/bus_managers/mmc/mmc_bus.h | 53 ++
.../kernel/bus_managers/mmc/mmc_module.cpp | 137 +++++
src/add-ons/kernel/busses/Jamfile | 1 +
src/add-ons/kernel/busses/mmc/Jamfile | 7 +
src/add-ons/kernel/busses/mmc/sdhci_pci.cpp | 534 +++++++++++++++++++
src/add-ons/kernel/busses/mmc/sdhci_pci.h | 129 +++++
src/add-ons/kernel/drivers/disk/Jamfile | 3 +-
src/add-ons/kernel/drivers/disk/mmc/Jamfile | 8 +
src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp | 157 ++++++
src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h | 24 +
.../kernel/device_manager/device_manager.cpp | 16 +-
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/bus_managers/Jamfile
b/src/add-ons/kernel/bus_managers/Jamfile
index e997c36156..386b887d09 100644
--- a/src/add-ons/kernel/bus_managers/Jamfile
+++ b/src/add-ons/kernel/bus_managers/Jamfile
@@ -7,6 +7,7 @@ SubInclude HAIKU_TOP src add-ons kernel bus_managers fdt ;
SubInclude HAIKU_TOP src add-ons kernel bus_managers firewire ;
SubInclude HAIKU_TOP src add-ons kernel bus_managers ata ;
SubInclude HAIKU_TOP src add-ons kernel bus_managers isa ;
+SubInclude HAIKU_TOP src add-ons kernel bus_managers mmc ;
SubInclude HAIKU_TOP src add-ons kernel bus_managers pci ;
SubInclude HAIKU_TOP src add-ons kernel bus_managers ps2 ;
SubInclude HAIKU_TOP src add-ons kernel bus_managers random ;
diff --git a/src/add-ons/kernel/bus_managers/mmc/Jamfile
b/src/add-ons/kernel/bus_managers/mmc/Jamfile
new file mode 100644
index 0000000000..fbf3722826
--- /dev/null
+++ b/src/add-ons/kernel/bus_managers/mmc/Jamfile
@@ -0,0 +1,8 @@
+SubDir HAIKU_TOP src add-ons kernel bus_managers mmc ;
+
+UsePrivateKernelHeaders ;
+
+KernelAddon mmc_bus :
+ mmc_module.cpp
+ mmc_bus.cpp
+ ;
diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp
b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp
new file mode 100644
index 0000000000..ffdc09cdb8
--- /dev/null
+++ b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * B Krishnan Iyer, krishnaniyer97@xxxxxxxxx
+ */
+#include "mmc_bus.h"
+
+
+MMCBus::MMCBus(device_node* node)
+ :
+ fNode(node),
+ fController(NULL),
+ fCookie(NULL),
+ fStatus(B_OK),
+ fDriverCookie(NULL)
+{
+ CALLED();
+ device_node* parent = gDeviceManager->get_parent_node(node);
+ fStatus = gDeviceManager->get_driver(parent,
+ (driver_module_info**)&fController, &fCookie);
+ gDeviceManager->put_node(parent);
+
+ if (fStatus != B_OK) {
+ ERROR("Not able to establish the bus %s\n",
+ strerror(fStatus));
+ return;
+ }
+}
+
+
+MMCBus::~MMCBus()
+{
+ CALLED();
+}
+
+
+status_t
+MMCBus::InitCheck()
+{
+ return fStatus;
+}
diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h
b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h
new file mode 100644
index 0000000000..efdc97efec
--- /dev/null
+++ b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * B Krishnan Iyer, krishnaniyer97@xxxxxxxxx
+ */
+#ifndef MMC_BUS_H
+#define MMC_BUS_H
+
+
+#include <new>
+#include <stdio.h>
+#include <string.h>
+
+#include <lock.h>
+#include <util/AutoLock.h>
+#include "../../busses/mmc/sdhci_pci.h"
+
+
+#define MMCBUS_TRACE
+#ifdef MMCBUS_TRACE
+# define TRACE(x...) dprintf("\33[33mmmc_bus:\33[0m " x)
+#else
+# define TRACE(x...)
+#endif
+#define TRACE_ALWAYS(x...) dprintf("\33[33mmmc_bus:\33[0m " x)
+#define ERROR(x...) dprintf("\33[33mmmc_bus:\33[0m " x)
+#define CALLED() TRACE("CALLED %s\n",
__PRETTY_FUNCTION__)
+
+extern device_manager_info *gDeviceManager;
+
+
+class MMCBus;
+
+class MMCBus {
+public:
+
+ MMCBus(device_node *node);
+ ~MMCBus();
+ status_t InitCheck();
+
+private:
+
+ device_node* fNode;
+ sdhci_mmc_bus_interface* fController;
+ void* fCookie;
+ status_t fStatus;
+ void* fDriverCookie;
+};
+
+
+#endif /*MMC_BUS_H*/
\ No newline at end of file
diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_module.cpp
b/src/add-ons/kernel/bus_managers/mmc/mmc_module.cpp
new file mode 100644
index 0000000000..7ada05ce64
--- /dev/null
+++ b/src/add-ons/kernel/bus_managers/mmc/mmc_module.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2018 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * B Krishnan Iyer, krishnaniyer97@xxxxxxxxx
+ */
+#include "mmc_bus.h"
+
+
+device_manager_info* gDeviceManager = NULL;
+
+
+static status_t
+mmc_bus_init(device_node* node, void** _device)
+{
+ CALLED();
+ MMCBus* device = new(std::nothrow) MMCBus(node);
+ if (device == NULL) {
+ ERROR("Unable to allocate MMC bus\n");
+ return B_NO_MEMORY;
+ }
+
+ status_t result = device->InitCheck();
+ if (result != B_OK) {
+ TRACE("failed to set up mmc bus device object\n");
+ return result;
+ }
+ TRACE("MMC bus object created\n");
+
+ *_device = device;
+ return B_OK;
+}
+
+
+static void
+mmc_bus_uninit(void* _device)
+{
+ CALLED();
+ MMCBus* device = (MMCBus*)_device;
+ delete device;
+}
+
+
+static void
+mmc_bus_removed(void* _device)
+{
+ CALLED();
+}
+
+
+status_t
+mmc_bus_added_device(device_node* parent)
+{
+ CALLED();
+ uint16 deviceType;
+ if (gDeviceManager->get_attr_uint16(parent,
+ SDHCI_DEVICE_TYPE_ITEM, &deviceType, true) != B_OK) {
+ TRACE("device is missing\n");
+ return B_ERROR;
+ }
+
+ TRACE("MMC bus device added\n");
+
+ device_attr attributes[] = {
+ { B_DEVICE_BUS, B_STRING_TYPE, { string: "mmc bus"}},
+ { SDHCI_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
+ { ui16: deviceType }},
+ { NULL }
+ };
+
+ return gDeviceManager->register_node(parent, MMC_BUS_MODULE_NAME,
+ attributes, NULL, NULL);
+}
+
+
+static status_t
+std_ops(int32 op, ...)
+{
+ switch (op) {
+ case B_MODULE_INIT:
+ // Nothing to do
+ case B_MODULE_UNINIT:
+ return B_OK;
+
+ default:
+ break;
+ }
+
+ return B_ERROR;
+}
+
+
+driver_module_info mmc_bus_device_module = {
+ {
+ MMC_BUS_MODULE_NAME,
+ 0,
+ std_ops
+ },
+ NULL, // supported devices
+ NULL, // register node
+ mmc_bus_init,
+ mmc_bus_uninit,
+ NULL, // register child devices
+ NULL, // rescan
+ mmc_bus_removed,
+ NULL, // suspend
+ NULL // resume
+};
+
+
+driver_module_info mmc_bus_controller_module = {
+ {
+ SDHCI_BUS_CONTROLLER_MODULE_NAME,
+ 0,
+ &std_ops
+ },
+
+ NULL, // supported devices
+ mmc_bus_added_device,
+ NULL,
+ NULL,
+ NULL
+};
+
+
+module_dependency module_dependencies[] = {
+ { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
+ {}
+};
+
+
+module_info* modules[] = {
+ (module_info*)&mmc_bus_controller_module,
+ (module_info*)&mmc_bus_device_module,
+ NULL
+};
diff --git a/src/add-ons/kernel/busses/Jamfile
b/src/add-ons/kernel/busses/Jamfile
index 402cbec5f8..7b549f0e04 100644
--- a/src/add-ons/kernel/busses/Jamfile
+++ b/src/add-ons/kernel/busses/Jamfile
@@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel busses ;
SubInclude HAIKU_TOP src add-ons kernel busses ata ;
SubInclude HAIKU_TOP src add-ons kernel busses agp_gart ;
+SubInclude HAIKU_TOP src add-ons kernel busses mmc ;
SubInclude HAIKU_TOP src add-ons kernel busses random ;
SubInclude HAIKU_TOP src add-ons kernel busses scsi ;
SubInclude HAIKU_TOP src add-ons kernel busses usb ;
diff --git a/src/add-ons/kernel/busses/mmc/Jamfile
b/src/add-ons/kernel/busses/mmc/Jamfile
new file mode 100644
index 0000000000..ef5298fb2f
--- /dev/null
+++ b/src/add-ons/kernel/busses/mmc/Jamfile
@@ -0,0 +1,7 @@
+SubDir HAIKU_TOP src add-ons kernel busses mmc ;
+
+SubDirC++Flags -fno-rtti ;
+
+KernelAddon sdhci_pci :
+ sdhci_pci.cpp
+;
diff --git a/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp
b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp
new file mode 100644
index 0000000000..35f31d3557
--- /dev/null
+++ b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp
@@ -0,0 +1,534 @@
+/*
+ * Copyright 2018 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * B Krishnan Iyer, krishnaniyer97@xxxxxxxxx
+ */
+#include <new>
+#include <stdio.h>
+#include <string.h>
+
+#include <bus/PCI.h>
+#include <PCI_x86.h>
+
+#include <KernelExport.h>
+
+#include "sdhci_pci.h"
+
+
+#define TRACE_SDHCI
+#ifdef TRACE_SDHCI
+# define TRACE(x...) dprintf("\33[33msdhci_pci:\33[0m " x)
+#else
+# define TRACE(x...) ;
+#endif
+#define TRACE_ALWAYS(x...) dprintf("\33[33msdhci_pci:\33[0m " x)
+#define ERROR(x...) dprintf("\33[33msdhci_pci:\33[0m " x)
+#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
+
+
+#define SDHCI_PCI_DEVICE_MODULE_NAME "busses/mmc/sdhci_pci/driver_v1"
+#define SDHCI_PCI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci_pci/device/v1"
+
+#define SDHCI_PCI_CONTROLLER_TYPE_NAME "sdhci pci controller"
+
+#define SLOTS_COUNT "device/slots_count"
+#define SLOT_NUMBER "device/slot"
+#define BAR_INDEX "device/bar"
+
+typedef struct {
+ pci_device_module_info* pci;
+ pci_device* device;
+ addr_t base_addr;
+ uint8 irq;
+ sdhci_mmc_bus mmc_bus;
+ area_id regs_area;
+ device_node* node;
+ pci_info info;
+ struct registers* _regs;
+
+} sdhci_pci_mmc_bus_info;
+
+
+device_manager_info* gDeviceManager;
+device_module_info* gSDHCIDeviceController;
+static pci_x86_module_info* sPCIx86Module;
+
+
+static void
+sdhci_register_dump(uint8_t slot, struct registers* regs)
+{
+ TRACE("Register values for slot: %d\n", slot);
+ TRACE("system_address: %d\n", regs->system_address);
+ TRACE("block_size: %d\n", regs->block_size);
+ TRACE("block_count: %d\n", regs->block_count);
+ TRACE("argument: %d\n", regs->argument);
+ TRACE("transfer_mode: %d\n", regs->transfer_mode);
+ TRACE("command: %d\n", regs->command);
+ TRACE("response0: %d\n", regs->response0);
+ TRACE("response2: %d\n", regs->response2);
+ TRACE("response4: %d\n", regs->response4);
+ TRACE("response6: %d\n", regs->response6);
+ TRACE("buffer_data_port: %d\n", regs->buffer_data_port);
+ TRACE("present_state: %d\n", regs->present_state);
+ TRACE("power_control: %d\n", regs->power_control);
+ TRACE("host_control: %d\n", regs->host_control);
+ TRACE("wakeup_control: %d\n", regs->wakeup_control);
+ TRACE("block_gap_control: %d\n", regs->block_gap_control);
+ TRACE("clock_control: %d\n", regs->clock_control);
+ TRACE("software_reset: %d\n", regs->software_reset);
+ TRACE("timeout_control: %d\n", regs->timeout_control);
+ TRACE("interrupt_status: %d\n", regs->interrupt_status);
+ TRACE("interrupt_status_enable: %d\n", regs->interrupt_status_enable);
+ TRACE("interrupt_signal_enable: %d\n", regs->interrupt_signal_enable);
+ TRACE("auto_cmd12_error_status: %d\n", regs->auto_cmd12_error_status);
+ TRACE("capabilities: %d\n", regs->capabilities);
+ TRACE("capabilities_rsvd: %d\n", regs->capabilities_rsvd);
+ TRACE("max_current_capabilities: %d\n",
+ regs->max_current_capabilities);
+ TRACE("max_current_capabilities_rsvd: %d\n",
+ regs->max_current_capabilities_rsvd);
+ TRACE("slot_interrupt_status: %d\n", regs->slot_interrupt_status);
+ TRACE("host_control_version %d\n", regs->host_control_version);
+}
+
+
+static void
+sdhci_reset(struct registers* regs)
+{
+ // if card is not present then no point of reseting the registers
+ if (!(regs->present_state & SDHCI_CARD_DETECT))
+ return;
+
+ // enabling software reset all
+ regs->software_reset |= SDHCI_SOFTWARE_RESET_ALL;
+
+ // waiting for clock and power to get off
+ while (regs->clock_control != 0 && regs->power_control != 0);
+}
+
+
+static void
+sdhci_set_clock(struct registers* regs, uint16_t base_clock_div)
+{
+ uint32_t clock_control = regs->clock_control;
+ int base_clock = SDHCI_BASE_CLOCK_FREQ(regs->capabilities);
+
+ TRACE("SDCLK frequency: %dMHz\n", base_clock);
+
+ // clearing previous frequency
+ clock_control &= SDHCI_CLR_FREQ_SEL;
+ clock_control |= base_clock_div;
+
+ // enabling internal clock
+ clock_control |= SDHCI_INTERNAL_CLOCK_ENABLE;
+ regs->clock_control = clock_control;
+
+ // waiting till internal clock gets stable
+ while (!(regs->clock_control & SDHCI_INTERNAL_CLOCK_STABLE));
+
+ regs->clock_control |= SDHCI_SD_CLOCK_ENABLE; // enabling the SD clock
+}
+
+
+static void
+sdhci_stop_clock(struct registers* regs)
+{
+ regs->clock_control &= SDHCI_SD_CLOCK_DISABLE;
+}
+
+
+static void
+sdhci_set_power(struct registers* _regs)
+{
+ uint16_t command = _regs->command;
+
+ if (SDHCI_VOLTAGE_SUPPORTED(_regs->capabilities))
+ if (SDHCI_VOLTAGE_SUPPORTED_33(_regs->capabilities))
+ _regs->power_control |= SDHCI_VOLTAGE_SUPPORT_33;
+ else if (SDHCI_VOLTAGE_SUPPORTED_30(_regs->capabilities))
+ _regs->power_control |= SDHCI_VOLTAGE_SUPPORT_30;
+ else
+ _regs->power_control |= SDHCI_VOLTAGE_SUPPORT_18;
+ else
+ TRACE("No voltage is supported\n");
+
+ if (SDHCI_CARD_INSERTED(_regs->present_state) == 0) {
+ TRACE("Card not inserted\n");
+ return;
+ }
+
+ _regs->power_control |= SDHCI_BUS_POWER_ON;
+ TRACE("Executed CMD0\n");
+
+ command = SDHCI_RESPONSE_R1 | SDHCI_CMD_CRC_EN
+ | SDHCI_CMD_INDEX_EN | SDHCI_CMD_0;
+ _regs->command |= command;
+
+ DELAY(1000);
+}
+
+
+static status_t
+init_bus(device_node* node, void** bus_cookie)
+{
+ CALLED();
+ status_t status = B_OK;
+ area_id regs_area;
+ volatile uint32_t* regs;
+ uint8_t bar, slot;
+
+ sdhci_pci_mmc_bus_info* bus = new(std::nothrow) sdhci_pci_mmc_bus_info;
+ if (bus == NULL)
+ return B_NO_MEMORY;
+
+ pci_info* pciInfo = &bus->info;
+ pci_device_module_info* pci;
+ pci_device* device;
+
+ device_node* parent = gDeviceManager->get_parent_node(node);
+ device_node* pciParent = gDeviceManager->get_parent_node(parent);
+ gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
+ (void**)&device);
+ gDeviceManager->put_node(pciParent);
+ gDeviceManager->put_node(parent);
+
+ if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&sPCIx86Module)
+ != B_OK) {
+ sPCIx86Module = NULL;
+ TRACE("PCIx86Module not loaded\n");
+ }
+
+ int msiCount = sPCIx86Module->get_msi_count(pciInfo->bus,
+ pciInfo->device, pciInfo->function);
+
+ TRACE("interrupts count: %d\n",msiCount);
+
+ if (gDeviceManager->get_attr_uint8(node, SLOT_NUMBER, &slot, false) <
B_OK
+ || gDeviceManager->get_attr_uint8(node, BAR_INDEX, &bar, false)
< B_OK)
+ return -1;
+
+ bus->node = node;
+ bus->pci = pci;
+ bus->device = device;
+
+ pci->get_pci_info(device, pciInfo);
+
+ // legacy interrupt
+ bus->base_addr = pciInfo->u.h0.base_registers[bar];
+
+ // enable bus master and io
+ uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
+ pcicmd &= ~(PCI_command_int_disable | PCI_command_io);
+ pcicmd |= PCI_command_master | PCI_command_memory;
+ pci->write_pci_config(device, PCI_command, 2, pcicmd);
+
+ TRACE("init_bus() %p node %p pci %p device %p\n", bus, node,
+ bus->pci, bus->device);
+
+ // mapping the registers by MMUIO method
+ int bar_size = pciInfo->u.h0.base_register_sizes[bar];
+
+ regs_area = map_physical_memory("sdhc_regs_map",
+ pciInfo->u.h0.base_registers[bar],
+ pciInfo->u.h0.base_register_sizes[bar],
B_ANY_KERNEL_BLOCK_ADDRESS,
+ B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)®s);
+
+ if (regs_area < B_OK) {
+ TRACE("mapping failed");
+ return B_BAD_VALUE;
+ }
+
+ bus->regs_area = regs_area;
+ struct registers* _regs = (struct registers*)regs;
+ bus->_regs = _regs;
+ sdhci_reset(_regs);
+ bus->irq = pciInfo->u.h0.interrupt_line;
+
+ TRACE("irq interrupt line: %d\n",bus->irq);
+
+ if (bus->irq == 0 || bus->irq == 0xff) {
+ TRACE("PCI IRQ not assigned\n");
+ if (sPCIx86Module != NULL) {
+ put_module(B_PCI_X86_MODULE_NAME);
+ sPCIx86Module = NULL;
+ }
+ delete bus;
+ return B_ERROR;
+ }
+
+ status = install_io_interrupt_handler(bus->irq,
+ sdhci_generic_interrupt, bus, 0);
+
+ if (status != B_OK) {
+ TRACE("can't install interrupt handler\n");
+ return status;
+ }
+ TRACE("interrupt handler installed\n");
+
+ _regs->interrupt_status_enable = SDHCI_INT_CMD_CMP
+ | SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM
+ | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
+ | SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
+ _regs->interrupt_signal_enable = SDHCI_INT_CMD_CMP
+ | SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM
+ | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
+ | SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
+
+ sdhci_register_dump(slot, _regs);
+ sdhci_set_clock(_regs, SDHCI_BASE_CLOCK_DIV_128);
+ sdhci_set_power(_regs);
+ sdhci_register_dump(slot, _regs);
+
+ *bus_cookie = bus;
+ return status;
+}
+
+
+void
+sdhci_error_interrupt_recovery(struct registers* _regs)
+{
+ _regs->interrupt_signal_enable &= ~(SDHCI_INT_CMD_CMP
+ | SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS |
SDHCI_INT_CARD_REM);
+
+ if (_regs->interrupt_status & 7) {
+ _regs->software_reset |= 1 << 1;
+ while (_regs->command);
+ }
+
+ int16_t erorr_status = _regs->interrupt_status;
+ _regs->interrupt_status &= ~(erorr_status);
+}
+
+
+int32
+sdhci_generic_interrupt(void* data)
+{
+ TRACE("interrupt function called\n");
+ sdhci_pci_mmc_bus_info* bus = (sdhci_pci_mmc_bus_info*)data;
+
+ uint16_t intmask, card_present;
+
+ intmask = bus->_regs->slot_interrupt_status;
+
+ if (intmask == 0 || intmask == 0xffffffff) {
+ TRACE("invalid command interrupt\n");
+
+ return B_UNHANDLED_INTERRUPT;
+ }
+
+ // handling card presence interrupt
+ if (intmask & (SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM)) {
+ card_present = ((intmask & SDHCI_INT_CARD_INS) != 0);
+ bus->_regs->interrupt_status_enable &= ~(SDHCI_INT_CARD_INS
+ | SDHCI_INT_CARD_REM);
+ bus->_regs->interrupt_signal_enable &= ~(SDHCI_INT_CARD_INS
+ | SDHCI_INT_CARD_REM);
+
+ bus->_regs->interrupt_status_enable |= card_present
+ ? SDHCI_INT_CARD_REM : SDHCI_INT_CARD_INS;
+ bus->_regs->interrupt_signal_enable |= card_present
+ ? SDHCI_INT_CARD_REM : SDHCI_INT_CARD_INS;
+
+ bus->_regs->interrupt_status |= (intmask &
+ (SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM));
+ TRACE("Card presence interrupt handled\n");
+
+ return B_HANDLED_INTERRUPT;
+ }
+
+ // handling command interrupt
+ if (intmask & SDHCI_INT_CMD_MASK) {
+ TRACE("interrupt status error: %d\n",
bus->_regs->interrupt_status);
+ bus->_regs->interrupt_status |= (intmask & SDHCI_INT_CMD_MASK);
+ TRACE("Command interrupt handled\n");
+
+ return B_HANDLED_INTERRUPT;
+ }
+
+ // handling bus power interrupt
+ if (intmask & SDHCI_INT_BUS_POWER) {
+ bus->_regs->interrupt_status |= SDHCI_INT_BUS_POWER;
+ TRACE("card is consuming too much power\n");
+
+ return B_HANDLED_INTERRUPT;
+ }
+
+ intmask &= ~(SDHCI_INT_BUS_POWER | SDHCI_INT_CARD_INS
+ |SDHCI_INT_CARD_REM | SDHCI_INT_CMD_MASK);
+
+}
+
+
+static void
+uninit_bus(void* bus_cookie)
+{
+ sdhci_pci_mmc_bus_info* bus = (sdhci_pci_mmc_bus_info*)bus_cookie;
+ delete bus;
+}
+
+
+static void
+bus_removed(void* bus_cookie)
+{
+ return;
+}
+
+
+static status_t
+register_child_devices(void* cookie)
+{
+ CALLED();
+ device_node* node = (device_node*)cookie;
+ device_node* parent = gDeviceManager->get_parent_node(node);
+ pci_device_module_info* pci;
+ pci_device* device;
+ uint8 slots_count, bar, slotsInfo;
+
+ gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
+ (void**)&device);
+ uint16 pciSubDeviceId = pci->read_pci_config(device, PCI_subsystem_id,
2);
+ slotsInfo = pci->read_pci_config(device, SDHCI_PCI_SLOT_INFO, 1);
+ bar = SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(slotsInfo);
+ slots_count = SDHCI_PCI_SLOTS(slotsInfo);
+
+ char prettyName[25];
+
+ if (slots_count > 6 || bar > 5) {
+ TRACE("Invalid slots count: %d or BAR count: %d \n",
slots_count, bar);
+ return B_BAD_VALUE;
+ }
+
+ for (uint8_t slot = 0; slot <= slots_count; slot++) {
+
+ bar = bar + slot;
+ sprintf(prettyName, "SDHC bus %" B_PRIu16 " slot %"
+ B_PRIu8, pciSubDeviceId, slot);
+ device_attr attrs[] = {
+ // properties of this controller for SDHCI bus manager
+ { B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
+ { string: prettyName }},
+ { B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
+ {string: SDHCI_BUS_CONTROLLER_MODULE_NAME}},
+ {SDHCI_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
+ { ui16: pciSubDeviceId}},
+ {B_DEVICE_BUS, B_STRING_TYPE,{string: "mmc"}},
+ {SLOT_NUMBER, B_UINT8_TYPE,
+ { ui8: slot}},
+ {BAR_INDEX, B_UINT8_TYPE,
+ { ui8: bar}},
+ { NULL }
+ };
+ if (gDeviceManager->register_node(node,
SDHCI_PCI_MMC_BUS_MODULE_NAME,
+ attrs, NULL, &node) != B_OK)
+ return B_BAD_VALUE;
+ }
+ return B_OK;
+}
+
+
+static status_t
+init_device(device_node* node, void** device_cookie)
+{
+ CALLED();
+ *device_cookie = node;
+ return B_OK;
+}
+
+
+static status_t
+register_device(device_node* parent)
+{
+ device_attr attrs[] = {
+ {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "SDHC PCI
controller"}},
+ {}
+ };
+
+ return gDeviceManager->register_node(parent,
SDHCI_PCI_DEVICE_MODULE_NAME,
+ attrs, NULL, NULL);
+}
+
+
+static float
+supports_device(device_node* parent)
+{
+ CALLED();
+ const char* bus;
+ uint16 type, subType;
+ uint8 pciSubDeviceId;
+
+ // make sure parent is a PCI SDHCI device node
+ if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
+ != B_OK || gDeviceManager->get_attr_uint16(parent,
B_DEVICE_SUB_TYPE,
+ &subType, false) < B_OK ||
gDeviceManager->get_attr_uint16(parent,
+ B_DEVICE_TYPE, &type, false) < B_OK)
+ return -1;
+
+ if (strcmp(bus, "pci") != 0)
+ return 0.0f;
+
+ if (type == PCI_base_peripheral) {
+ if (subType != PCI_sd_host)
+ return 0.0f;
+
+ pci_device_module_info* pci;
+ pci_device* device;
+ gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
+ (void**)&device);
+ pciSubDeviceId = pci->read_pci_config(device, PCI_revision, 1);
+ TRACE("SDHCI Device found! Subtype: 0x%04x, type: 0x%04x\n",
+ subType, type);
+ return 0.8f;
+ }
+
+ return 0.0f;
+}
+
+
+module_dependency module_dependencies[] = {
+ { SDHCI_BUS_CONTROLLER_MODULE_NAME,
(module_info**)&gSDHCIDeviceController},
+ { B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
+ {}
+};
+
+
+static sdhci_mmc_bus_interface gSDHCIPCIDeviceModule = {
+ {
+ {
+ SDHCI_PCI_MMC_BUS_MODULE_NAME,
+ 0,
+ NULL
+ },
+ NULL, // supports device
+ NULL, // register device
+ init_bus,
+ uninit_bus,
+ NULL, // register child devices
+ NULL, // rescan
+ bus_removed,
+ }
+};
+
+
+static driver_module_info sSDHCIDevice = {
+ {
+ SDHCI_PCI_DEVICE_MODULE_NAME,
+ 0,
+ NULL
+ },
+ supports_device,
+ register_device,
+ init_device,
+ NULL, // uninit
+ register_child_devices,
+ NULL, // rescan
+ NULL, // device removed
+};
+
+
+module_info* modules[] = {
+ (module_info* )&sSDHCIDevice,
+ (module_info* )&gSDHCIPCIDeviceModule,
+ NULL
+};
diff --git a/src/add-ons/kernel/busses/mmc/sdhci_pci.h
b/src/add-ons/kernel/busses/mmc/sdhci_pci.h
new file mode 100644
index 0000000000..1d493f3906
--- /dev/null
+++ b/src/add-ons/kernel/busses/mmc/sdhci_pci.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2018 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * B Krishnan Iyer, krishnaniyer97@xxxxxxxxx
+ */
+#ifndef _SDHCI_PCI_H
+#define _SDHCI_PCI_H
+
+
+#include <device_manager.h>
+#include <KernelExport.h>
+
+
+#define SDHCI_PCI_SLOT_INFO
0x40
+#define SDHCI_PCI_SLOTS(x)
((( x >> 4) & 7))
+#define SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(x) (( x )
& 7)
+
+#define SDHCI_DEVICE_TYPE_ITEM
"sdhci/type"
+#define SDHCI_BUS_TYPE_NAME
"bus/sdhci/v1"
+
+#define SDHCI_CARD_DETECT
1 << 16
+
+#define SDHCI_SOFTWARE_RESET_ALL
1 << 0
+
+#define SDHCI_BASE_CLOCK_FREQ(x)
((x >> 8) & 63)
+#define SDHCI_VOLTAGE_SUPPORTED(x) ((x >> 24) & 7)
+#define SDHCI_VOLTAGE_SUPPORTED_33(x) ((x >> 24) & 1)
+#define SDHCI_VOLTAGE_SUPPORTED_30(x) ((x >> 24) & 3)
+#define SDHCI_VOLTAGE_SUPPORT_33
7 << 1
+#define SDHCI_VOLTAGE_SUPPORT_30
6 << 1
+#define SDHCI_VOLTAGE_SUPPORT_18
5 << 1
+#define SDHCI_CARD_INSERTED(x)
((x >> 16) & 1)
+#define SDHCI_BASE_CLOCK_DIV_1
0 << 8
+#define SDHCI_BASE_CLOCK_DIV_2
1 << 8
+#define SDHCI_BASE_CLOCK_DIV_4
2 << 8
+#define SDHCI_BASE_CLOCK_DIV_8
4 << 8
+#define SDHCI_BASE_CLOCK_DIV_16
8 << 8
+#define SDHCI_BASE_CLOCK_DIV_32
16 << 8
+#define SDHCI_BASE_CLOCK_DIV_64
32 << 8
+#define SDHCI_BASE_CLOCK_DIV_128
64 << 8
+#define SDHCI_BASE_CLOCK_DIV_256
128 << 8
+#define SDHCI_INTERNAL_CLOCK_ENABLE
1 << 0
+#define SDHCI_INTERNAL_CLOCK_STABLE
1 << 1
+#define SDHCI_SD_CLOCK_ENABLE
1 << 2
+#define SDHCI_SD_CLOCK_DISABLE
~(1 << 2)
+#define SDHCI_CLR_FREQ_SEL
~(255 << 8)
+#define SDHCI_BUS_POWER_ON
1
+#define SDHCI_RESPONSE_R1 2
+#define SDHCI_CMD_CRC_EN 1 << 3
+#define SDHCI_CMD_INDEX_EN 1 << 4
+#define SDHCI_CMD_0 ~(63 << 8)
+/* Interrupt registers */
+#define SDHCI_INT_CMD_CMP 0x00000001 // command
complete enable
+#define SDHCI_INT_TRANS_CMP 0x00000002 // transfer
complete enable
+#define SDHCI_INT_CARD_INS 0x00000040 // card
insertion enable
+#define SDHCI_INT_CARD_REM 0x00000080 // card removal
enable
+#define SDHCI_INT_TIMEOUT 0x00010000 // Timeout error
+#define SDHCI_INT_CRC 0x00020000 // CRC error
+#define SDHCI_INT_END_BIT 0x00040000 // end bit error
+#define SDHCI_INT_INDEX 0x00080000 // index error
+#define SDHCI_INT_BUS_POWER 0x00800000 // power fail
+
+#define SDHCI_INT_CMD_ERROR_MASK (SDHCI_INT_TIMEOUT | \
+ SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
+
+#define SDHCI_INT_CMD_MASK (SDHCI_INT_CMD_CMP | SDHCI_INT_CMD_ERROR_MASK)
+
+
+struct registers {
+ volatile uint32_t system_address;
+ volatile uint16_t block_size;
+ volatile uint16_t block_count;
+ volatile uint32_t argument;
+ volatile uint16_t transfer_mode;
+ volatile uint16_t command;
+ volatile uint32_t response0;
+ volatile uint32_t response2;
+ volatile uint32_t response4;
+ volatile uint32_t response6;
+ volatile uint32_t buffer_data_port;
+ volatile uint32_t present_state;
+ volatile uint8_t host_control;
+ volatile uint8_t power_control;
+ volatile uint8_t block_gap_control;
+ volatile uint8_t wakeup_control;
+ volatile uint16_t clock_control;
+ volatile uint8_t timeout_control;
+ volatile uint8_t software_reset;
+ volatile uint32_t interrupt_status;
+ volatile uint32_t interrupt_status_enable;
+ volatile uint32_t interrupt_signal_enable;
+ volatile uint16_t auto_cmd12_error_status;
+ volatile uint16_t : 16;
+ volatile uint32_t capabilities;
+ volatile uint32_t capabilities_rsvd;
+ volatile uint32_t max_current_capabilities;
+ volatile uint32_t max_current_capabilities_rsvd;
+ volatile uint64_t padding[21];
+ volatile uint32_t : 32;
+ volatile uint16_t slot_interrupt_status;
+ volatile uint16_t host_control_version;
+} __attribute__((packed));
+
+typedef void* sdhci_mmc_bus;
+
+#define DELAY(n) snooze(n)
+
+#define SDHCI_BUS_CONTROLLER_MODULE_NAME "bus_managers/mmc_bus/driver_v1"
+
+#define MMC_BUS_MODULE_NAME "bus_managers/mmc_bus/device/v1"
+
+static void sdhci_register_dump(uint8_t, struct registers*);
+static void sdhci_reset(struct registers*);
+static void sdhci_set_clock(struct registers*, uint16_t);
+static void sdhci_set_power(struct registers*);
+static void sdhci_stop_clock(struct registers*);
+void sdhci_error_interrupt_recovery(struct registers*);
+
+status_t sdhci_generic_interrupt(void*);
+
+typedef struct {
+ driver_module_info info;
+
+} sdhci_mmc_bus_interface;
+
+
+#endif /*_SDHCI_PCI_H*/
diff --git a/src/add-ons/kernel/drivers/disk/Jamfile
b/src/add-ons/kernel/drivers/disk/Jamfile
index d6ce88a04a..9dfc9029e1 100644
--- a/src/add-ons/kernel/drivers/disk/Jamfile
+++ b/src/add-ons/kernel/drivers/disk/Jamfile
@@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers disk ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk floppy ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk norflash ;
+SubInclude HAIKU_TOP src add-ons kernel drivers disk mmc ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk scsi ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk usb ;
-SubInclude HAIKU_TOP src add-ons kernel drivers disk virtual ;
+SubInclude HAIKU_TOP src add-ons kernel drivers disk virtual ;
\ No newline at end of file
diff --git a/src/add-ons/kernel/drivers/disk/mmc/Jamfile
b/src/add-ons/kernel/drivers/disk/mmc/Jamfile
new file mode 100644
index 0000000000..bb603575c9
--- /dev/null
+++ b/src/add-ons/kernel/drivers/disk/mmc/Jamfile
@@ -0,0 +1,8 @@
+SubDir HAIKU_TOP src add-ons kernel drivers disk mmc ;
+
+UsePrivateKernelHeaders ;
+SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
+
+KernelAddon mmc_disk :
+ mmc_disk.cpp
+;
diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
new file mode 100644
index 0000000000..ccccc3550a
--- /dev/null
+++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2018 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * B Krishnan Iyer, krishnaniyer97@xxxxxxxxx
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "mmc_disk.h"
+
+#include <drivers/device_manager.h>
+#include <drivers/KernelExport.h>
+#include <drivers/Drivers.h>
+#include <kernel/OS.h>
+
+// #include <fs/devfs.h>
+
+#define TRACE_MMC_DISK
+#ifdef TRACE_MMC_DISK
+# define TRACE(x...) dprintf("mmc_disk: " x)
+#else
+# define TRACE(x...) ;
+#endif
+#define ERROR(x...) dprintf("\33[33mmc_disk:\33[0m " x)
+#define CALLED() TRACE("CALLED %s\n",
__PRETTY_FUNCTION__)
+
+#define MMC_DISK_DRIVER_MODULE_NAME "drivers/disk/mmc/mmc_disk/driver_v1"
+#define MMC_DISK_DEVICE_MODULE_NAME "drivers/disk/mmc/mmc_disk/device_v1"
+#define MMC_DEVICE_ID_GENERATOR "mmc/device_id"
+
+static device_manager_info* sDeviceManager;
+
+
+static float
+mmc_disk_supports_device(device_node* parent)
+{
+ CALLED();
+ const char* bus;
+ // uint16 deviceType;
+
+ if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus,
+ true) != B_OK)
+ return -1;
+
+ if (strcmp(bus, "mmc") != 0) {
+ TRACE("bus value %s, parent: %p\n",bus, parent);
+ return 0.0;
+ }
+ // Used to check the device type but later we have attached an
+ // attribute(mmc) to the bus. Not a compulsion to use this condition
+ #if 0
+ if (sDeviceManager->get_attr_uint16(parent, SDHCI_DEVICE_TYPE_ITEM,
+ &deviceType, true) != B_OK)
+ {
+ TRACE(" Inavlid device type, bus found: %s and attr val %d\n",
+ bus, deviceType);
+ return 0.0;
+ }
+ #endif
+ TRACE("sdhci device found, parent: %p\n", parent);
+
+ return 0.8;
+}
+
+
+static status_t
+mmc_disk_register_device(device_node* node)
+{
+ CALLED();
+
+ device_attr attrs[] = {
+ { NULL }
+ };
+
+ return sDeviceManager->register_node(node
+ , MMC_DISK_DRIVER_MODULE_NAME, attrs, NULL, NULL);
+}
+
+
+static status_t
+mmc_disk_init_driver(device_node* node, void** cookie)
+{
+ CALLED();
+ mmc_disk_driver_info* info = (mmc_disk_driver_info*)malloc(
+ sizeof(mmc_disk_driver_info));
+
+ if (info == NULL)
+ return B_NO_MEMORY;
+
+ memset(info, 0, sizeof(*info));
+
+ info->node = node;
+
+ *cookie = info;
+ return B_OK;
+}
+
+
+static void
+mmc_disk_uninit_driver(void* _cookie)
+{
+ CALLED();
+ mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie;
+ free(info);
+}
+
+
+static status_t
+mmc_disk_register_child_devices(void* _cookie)
+{
+ CALLED();
+ mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie;
+ status_t status;
+
+ int32 id = sDeviceManager->create_id(MMC_DEVICE_ID_GENERATOR);
+ if (id < 0)
+ return id;
+
+ char name[64];
+ snprintf(name, sizeof(name), "disk/mmc/%" B_PRId32 "/raw", id);
+
+ status = sDeviceManager->publish_device(info->node, name,
+ MMC_DISK_DEVICE_MODULE_NAME);
+
+ return status;
+}
+
+
+module_dependency module_dependencies[] = {
+ {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager},
+ {}
+};
+
+
+struct driver_module_info sMMCDiskDriver = {
+ {
+ MMC_DISK_DRIVER_MODULE_NAME,
+ 0,
+ NULL
+ },
+ mmc_disk_supports_device,
+ mmc_disk_register_device,
+ mmc_disk_init_driver,
+ mmc_disk_uninit_driver,
+ mmc_disk_register_child_devices,
+ NULL, // mmc_disk_rescan_child_devices,
+ NULL,
+};
+
+
+module_info* modules[] = {
+ (module_info*)&sMMCDiskDriver,
+ NULL
+};
diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h
b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h
new file mode 100644
index 0000000000..990e104aff
--- /dev/null
+++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2018 Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ * B Krishnan Iyer, krishnaniyer97@xxxxxxxxx
+ */
+#ifndef _MMC_DISK_H
+#define _MMC_DISK_H
+
+
+#include <device_manager.h>
+#include <KernelExport.h>
+
+
+#define SDHCI_DEVICE_TYPE_ITEM "sdhci/type"
+
+typedef struct {
+ device_node* node;
+ status_t media_status;
+} mmc_disk_driver_info;
+
+
+#endif /*_MMC_DISK_H*/
\ No newline at end of file
diff --git a/src/system/kernel/device_manager/device_manager.cpp
b/src/system/kernel/device_manager/device_manager.cpp
index f42a03094d..233f9b6fd4 100644
--- a/src/system/kernel/device_manager/device_manager.cpp
+++ b/src/system/kernel/device_manager/device_manager.cpp
@@ -42,7 +42,6 @@
# define TRACE(a) ;
#endif
-
#define DEVICE_MANAGER_ROOT_NAME "system/devices_root/driver_v1"
#define DEVICE_MANAGER_GENERIC_NAME "system/devices_generic/driver_v1"
@@ -1538,7 +1537,9 @@ device_node::_GetNextDriverPath(void*& cookie, KPath&
_path)
if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK
|| get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType,
false)
!= B_OK)
+ {
generic = true;
+ }
get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false);
@@ -1599,6 +1600,16 @@ device_node::_GetNextDriverPath(void*& cookie, KPath&
_path)
break;
}
break;
+ case PCI_base_peripheral:
+ switch (subType) {
+ case PCI_sd_host:
+ _AddPath(*stack, "busses",
"mmc");
+ break;
+ default:
+ _AddPath(*stack, "drivers");
+ break;
+ }
+ break;
default:
if (sRootNode == this) {
_AddPath(*stack, "busses/pci");
@@ -1885,7 +1896,8 @@ device_node::Probe(const char* devicePath, uint32
updateCycle)
// Check if this node matches the device path
// TODO: maybe make this extendible via settings file?
if (!strcmp(devicePath, "disk")) {
- matches = type == PCI_mass_storage;
+ matches = type == PCI_mass_storage
+ && (type == PCI_base_peripheral ||
subType == PCI_sd_host);
} else if (!strcmp(devicePath, "audio")) {
matches = type == PCI_multimedia
&& (subType == PCI_audio || subType ==
PCI_hd_audio);