diff --git a/headers/private/i2c/i2c.h b/headers/private/i2c/i2c.h index 1eb2fe0f75..b68780cf07 100644 --- a/headers/private/i2c/i2c.h +++ b/headers/private/i2c/i2c.h @@ -53,7 +53,8 @@ typedef struct { status_t (*exec_command)(i2c_device cookie, i2c_op op, const void *cmdBuffer, size_t cmdLength, void* dataBuffer, size_t dataLength); - + status_t (*acquire_bus)(i2c_device cookie); + void (*release_bus)(i2c_device cookie); } i2c_device_interface; @@ -76,6 +77,8 @@ typedef struct { status_t (*exec_command)(i2c_bus cookie, i2c_op op, i2c_addr slaveAddress, const void *cmdBuffer, size_t cmdLength, void* dataBuffer, size_t dataLength); + status_t (*acquire_bus)(i2c_bus cookie); + void (*release_bus)(i2c_bus cookie); } i2c_bus_interface; @@ -119,12 +122,14 @@ typedef struct { status_t (*scan_bus)(i2c_bus_cookie cookie); + status_t (*acquire_bus)(i2c_bus_cookie cookie); + void (*release_bus)(i2c_bus_cookie cookie); + status_t (*install_interrupt_handler)(i2c_bus_cookie cookie, i2c_intr_cookie intrCookie, interrupt_handler handler, void* data); status_t (*uninstall_interrupt_handler)(i2c_bus_cookie cookie, i2c_intr_cookie intrCookie); - } i2c_sim_interface; diff --git a/src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp b/src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp index 3940709ee0..af730c8e28 100644 --- a/src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp +++ b/src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp @@ -83,12 +83,31 @@ status_t I2CBus::Scan() { CALLED(); - - fController->scan_bus(fCookie); + if (fController->scan_bus != NULL) + fController->scan_bus(fCookie); return B_OK; } +status_t +I2CBus::AcquireBus() +{ + CALLED(); + if (fController->acquire_bus != NULL) + return fController->acquire_bus(fCookie); + return B_OK; +} + + +void +I2CBus::ReleaseBus() +{ + CALLED(); + if (fController->release_bus != NULL) + fController->release_bus(fCookie); +} + + static status_t i2c_init_bus(device_node *node, void **_bus) { @@ -127,7 +146,7 @@ i2c_uninit_bus(void *_bus) } -status_t +static status_t i2c_scan_bus(void *_bus) { I2CBus *bus = (I2CBus *)_bus; @@ -147,6 +166,24 @@ i2c_bus_exec_command(void* _bus, i2c_op op, i2c_addr slaveAddress, } +static status_t +i2c_bus_acquire_bus(void* _bus) +{ + CALLED(); + I2CBus* bus = (I2CBus*)_bus; + return bus->AcquireBus(); +} + + +static void +i2c_bus_release_bus(void* _bus) +{ + CALLED(); + I2CBus* bus = (I2CBus*)_bus; + return bus->ReleaseBus(); +} + + static status_t std_ops(int32 op, ...) { @@ -179,6 +216,8 @@ i2c_bus_interface gI2CBusModule = { NULL, // rescan }, - i2c_bus_exec_command + i2c_bus_exec_command, + i2c_bus_acquire_bus, + i2c_bus_release_bus, }; diff --git a/src/add-ons/kernel/bus_managers/i2c/I2CDevice.cpp b/src/add-ons/kernel/bus_managers/i2c/I2CDevice.cpp index ba398fdba5..d4ea49ab71 100644 --- a/src/add-ons/kernel/bus_managers/i2c/I2CDevice.cpp +++ b/src/add-ons/kernel/bus_managers/i2c/I2CDevice.cpp @@ -39,6 +39,21 @@ I2CDevice::ExecCommand(i2c_op op, const void *cmdBuffer, } +status_t +I2CDevice::AcquireBus() +{ + CALLED(); + return fBus->AcquireBus(); +} + + +void +I2CDevice::ReleaseBus() +{ + CALLED(); + fBus->ReleaseBus(); +} + static status_t i2c_init_device(device_node *node, void **_device) @@ -101,6 +116,22 @@ i2c_exec_command(i2c_device _device, i2c_op op, const void *cmdBuffer, } +static status_t +i2c_acquire_bus(i2c_device _device) +{ + I2CDevice *device = (I2CDevice *)_device; + return device->AcquireBus(); +} + + +static void +i2c_release_bus(i2c_device _device) +{ + I2CDevice *device = (I2CDevice *)_device; + return device->ReleaseBus(); +} + + static status_t std_ops(int32 op, ...) { @@ -140,4 +171,6 @@ i2c_device_interface gI2CDeviceModule = { (void (*)(void *)) i2c_device_removed }, i2c_exec_command, + i2c_acquire_bus, + i2c_release_bus, }; diff --git a/src/add-ons/kernel/bus_managers/i2c/I2CPrivate.h b/src/add-ons/kernel/bus_managers/i2c/I2CPrivate.h index f7fec54f73..9237c87374 100644 --- a/src/add-ons/kernel/bus_managers/i2c/I2CPrivate.h +++ b/src/add-ons/kernel/bus_managers/i2c/I2CPrivate.h @@ -51,6 +51,8 @@ public: status_t ExecCommand(i2c_op op, const void *cmdBuffer, size_t cmdLength, void* dataBuffer, size_t dataLength); + status_t AcquireBus(); + void ReleaseBus(); private: device_node* fNode; @@ -73,6 +75,8 @@ public: status_t RegisterDevice(i2c_addr slaveAddress, char* hid, char** cid, acpi_handle acpiHandle); + status_t AcquireBus(); + void ReleaseBus(); private: device_node* fNode; diff --git a/src/add-ons/kernel/bus_managers/i2c/bus_raw.cpp b/src/add-ons/kernel/bus_managers/i2c/bus_raw.cpp index 86e68d2a31..dfe3af8674 100644 --- a/src/add-ons/kernel/bus_managers/i2c/bus_raw.cpp +++ b/src/add-ons/kernel/bus_managers/i2c/bus_raw.cpp @@ -87,9 +87,15 @@ i2c_bus_raw_control(void *_cookie, uint32 op, void *data, size_t length) exec.buffer = buffer; } - status_t status = bus->ExecCommand(exec.op, exec.addr, + status_t status = bus->AcquireBus(); + if (status != B_OK) + return status; + + status = bus->ExecCommand(exec.op, exec.addr, &exec.cmdBuffer, exec.cmdLength, exec.buffer, exec.bufferLength); + bus->ReleaseBus(); + if (status != B_OK) return status; diff --git a/src/add-ons/kernel/busses/i2c/pch_i2c.cpp b/src/add-ons/kernel/busses/i2c/pch_i2c.cpp index f3eb0756c5..a7ad704d78 100644 --- a/src/add-ons/kernel/busses/i2c/pch_i2c.cpp +++ b/src/add-ons/kernel/busses/i2c/pch_i2c.cpp @@ -370,6 +370,24 @@ scan_bus(i2c_bus_cookie cookie) } +static status_t +acquire_bus(i2c_bus_cookie cookie) +{ + CALLED(); + pch_i2c_sim_info* bus = (pch_i2c_sim_info*)cookie; + return mutex_lock(&bus->lock); +} + + +static void +release_bus(i2c_bus_cookie cookie) +{ + CALLED(); + pch_i2c_sim_info* bus = (pch_i2c_sim_info*)cookie; + mutex_unlock(&bus->lock); +} + + // #pragma mark - @@ -467,6 +485,7 @@ init_bus(device_node* node, void** bus_cookie) goto err; } + mutex_init(&bus->lock, "pch_i2c"); *bus_cookie = bus; return status; @@ -482,6 +501,7 @@ uninit_bus(void* bus_cookie) { pch_i2c_sim_info* bus = (pch_i2c_sim_info*)bus_cookie; + mutex_destroy(&bus->lock); remove_io_interrupt_handler(bus->irq, (interrupt_handler)pch_i2c_interrupt_handler, bus); if (bus->registersArea >= 0) @@ -521,6 +541,8 @@ static i2c_sim_interface sPchI2cDeviceModule = { set_sim, exec_command, scan_bus, + acquire_bus, + release_bus, }; diff --git a/src/add-ons/kernel/busses/i2c/pch_i2c.h b/src/add-ons/kernel/busses/i2c/pch_i2c.h index 0c80ddca85..efd530317e 100644 --- a/src/add-ons/kernel/busses/i2c/pch_i2c.h +++ b/src/add-ons/kernel/busses/i2c/pch_i2c.h @@ -14,6 +14,7 @@ extern "C" { } #include +#include //#define TRACE_PCH_I2C @@ -105,6 +106,7 @@ typedef struct { uint32 flags; int32 error; + mutex lock; status_t (*scan_bus)(i2c_bus_cookie cookie); } pch_i2c_sim_info;