Add base address for IO ports to easily allow multiple instance of the same device.
This commit is contained in:
@@ -10,7 +10,9 @@
|
||||
#ifndef __DEVICE_H__
|
||||
#define __DEVICE_H__
|
||||
|
||||
typedef void (*device_init)(void *param);
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*device_init)(uint8_t baseAddress, void *param);
|
||||
typedef void (*device_reset)(void);
|
||||
typedef void (*device_free)(void);
|
||||
|
||||
@@ -31,11 +33,11 @@ typedef enum device_type_t
|
||||
|
||||
typedef struct device_t
|
||||
{
|
||||
device_init init; /***< Function called to init the device */
|
||||
device_reset reset; /***< Function called to reset the device */
|
||||
device_free free; /***< Function called to deinit the device */
|
||||
device_init init; /***< Function called to init the device - Non optional */
|
||||
device_reset reset; /***< Function called to reset the device - Optional */
|
||||
device_free free; /***< Function called to deinit the device - Optional */
|
||||
device_type_t deviceType; /***< Used to tell the type of device, could be useful to pass the
|
||||
* right parameters to init */
|
||||
* right parameters to init - Non optional */
|
||||
} device_t;
|
||||
|
||||
#endif /* __DEVICE_H__ */
|
||||
|
||||
@@ -35,7 +35,10 @@ void io_writeport(uint8_t port, uint8_t value);
|
||||
typedef uint8_t (*io_read)(void *pdata, uint8_t port);
|
||||
typedef void (*io_write)(void *pdata, uint8_t port, uint8_t value);
|
||||
|
||||
void register_io_hook(uint8_t port, io_read readHook, io_write writeHook, void *pdata);
|
||||
void register_io_hook_array(uint8_t *portList, uint8_t listLen, io_read readHook, io_write writeHook, void *pdata);
|
||||
void register_io_hook(uint8_t baseAddress, uint8_t port, io_read readHook, void *pdata, io_write writeHook);
|
||||
void register_io_hook_array(uint8_t baseAddress, const uint8_t *portList, uint8_t listLen, io_read readHook, io_write writeHook,
|
||||
void *pdata);
|
||||
|
||||
#define UNUSED_PARAMETER(_s) (void *)(_s)
|
||||
|
||||
#endif
|
||||
|
||||
37
source/io.c
37
source/io.c
@@ -29,9 +29,10 @@
|
||||
|
||||
typedef struct ioregistry_t
|
||||
{
|
||||
io_read read; /***< Read function for a specific IO port */
|
||||
io_write write; /***< Write function for a specific IO port */
|
||||
void *private; /***< Private data for the peripheral if needed. */
|
||||
io_read read; /***< Read function for a specific IO port */
|
||||
io_write write; /***< Write function for a specific IO port */
|
||||
void *private; /***< Private data for the peripheral if needed. */
|
||||
uint8_t base_address; /***< Base IO address. Used create a "local" value when calling the read/write function */
|
||||
} ioregistry_t;
|
||||
ioregistry_t io_registry[0x100];
|
||||
|
||||
@@ -92,36 +93,39 @@ void io_done(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void register_io_hook(uint8_t port, io_read readHook, io_write writeHook, void *pdata)
|
||||
void register_io_hook(uint8_t baseAddress, uint8_t port, io_read readHook, void *pdata, io_write writeHook)
|
||||
{
|
||||
io_registry[port].read = readHook;
|
||||
io_registry[port].write = writeHook;
|
||||
io_registry[port].private = pdata;
|
||||
io_registry[baseAddress + port].base_address = baseAddress;
|
||||
io_registry[baseAddress + port].read = readHook;
|
||||
io_registry[baseAddress + port].write = writeHook;
|
||||
io_registry[baseAddress + port].private = pdata;
|
||||
}
|
||||
|
||||
void register_io_hook_array(uint8_t *portList, uint8_t listLen, io_read readHook, io_write writeHook, void *pdata)
|
||||
void register_io_hook_array(uint8_t baseAddress, const uint8_t *portList, uint8_t listLen, io_read readHook, io_write writeHook,
|
||||
void *pdata)
|
||||
{
|
||||
uint16_t i;
|
||||
for(i = 0; i < listLen; i++)
|
||||
{
|
||||
io_registry[portList[i]].read = readHook;
|
||||
io_registry[portList[i]].write = writeHook;
|
||||
io_registry[portList[i]].private = pdata;
|
||||
io_registry[baseAddress + portList[i]].base_address = baseAddress;
|
||||
io_registry[baseAddress + portList[i]].read = readHook;
|
||||
io_registry[baseAddress + portList[i]].write = writeHook;
|
||||
io_registry[baseAddress + portList[i]].private = pdata;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t io_readport(uint8_t port)
|
||||
{
|
||||
uint8_t retVal = 0;
|
||||
|
||||
if (io_registry[port].read)
|
||||
{
|
||||
retVal = io_registry[port].read(io_registry[port].private, port);
|
||||
uint8_t localPort = port - io_registry[port].base_address;
|
||||
retVal = io_registry[port].read(io_registry[port].private, localPort);
|
||||
}
|
||||
|
||||
if (ioLogFp)
|
||||
{
|
||||
fprintf(ioLogFp, "%llu, R, %02X, %02X\n", nec_monotonicCycles, port, retVal);
|
||||
fprintf(ioLogFp, "%lu, R, %02X, %02X\n", nec_monotonicCycles, port, retVal);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@@ -131,11 +135,12 @@ void io_writeport(uint8_t port, uint8_t value)
|
||||
{
|
||||
if (ioLogFp)
|
||||
{
|
||||
fprintf(ioLogFp, "%llu, W, %02X, %02X\n", nec_monotonicCycles, port, value);
|
||||
fprintf(ioLogFp, "%lu, W, %02X, %02X\n", nec_monotonicCycles, port, value);
|
||||
}
|
||||
|
||||
if (io_registry[port].write)
|
||||
{
|
||||
io_registry[port].write(io_registry[port].private, port, value);
|
||||
uint8_t localPort = port - io_registry[port].base_address;
|
||||
io_registry[port].write(io_registry[port].private, localPort, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ static uint8_t IC_IO_read(void *pdata, uint8_t port)
|
||||
|
||||
switch(port)
|
||||
{
|
||||
case 0xB0: return params->address_base;
|
||||
case 0xB2: return params->int_enable_mask;
|
||||
case 0xB4: return params->int_status;
|
||||
case 0x0: return params->address_base;
|
||||
case 0x2: return params->int_enable_mask;
|
||||
case 0x4: return params->int_status;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
return 0x90;
|
||||
}
|
||||
|
||||
static void IC_IO_write(void *pdata, uint8_t port, uint8_t value)
|
||||
@@ -44,8 +44,8 @@ static void IC_IO_write(void *pdata, uint8_t port, uint8_t value)
|
||||
|
||||
switch(port)
|
||||
{
|
||||
case 0xB0: params->address_base = value; break;
|
||||
case 0xB2: params->int_enable_mask = value; break;
|
||||
case 0x0: params->address_base = value; break;
|
||||
case 0x2: params->int_enable_mask = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,14 +57,14 @@ static void IC_IO_write_ack(void *pdata, uint8_t port, uint8_t value)
|
||||
}
|
||||
|
||||
|
||||
static void IC_init(void *params)
|
||||
static void IC_init(uint8_t baseAddress, void *params)
|
||||
{
|
||||
UNUSED_PARAMETER(params);
|
||||
|
||||
register_io_hook(0xB0, IC_IO_read, IC_IO_write, &interrupt_controller);
|
||||
register_io_hook(0xB2, IC_IO_read, IC_IO_write, &interrupt_controller);
|
||||
register_io_hook(0xB4, IC_IO_read, NULL, &interrupt_controller);
|
||||
register_io_hook(0xB6, NULL, IC_IO_write_ack, &interrupt_controller);
|
||||
register_io_hook(baseAddress, 0x0, IC_IO_read, IC_IO_write, &interrupt_controller);
|
||||
register_io_hook(baseAddress, 0x2, IC_IO_read, IC_IO_write, &interrupt_controller);
|
||||
register_io_hook(baseAddress, 0x4, IC_IO_read, NULL, &interrupt_controller);
|
||||
register_io_hook(baseAddress, 0x6, NULL, IC_IO_write_ack, &interrupt_controller);
|
||||
}
|
||||
|
||||
static void IC_reset()
|
||||
@@ -73,16 +73,11 @@ static void IC_reset()
|
||||
interrupt_controller.address_base = 0;
|
||||
}
|
||||
|
||||
static void IC_free()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
device_t InterruptController =
|
||||
{
|
||||
.init = IC_init,
|
||||
.reset = IC_reset,
|
||||
.free = IC_free,
|
||||
.free = NULL,
|
||||
.deviceType = DT_INTERRUPT_CONTROLLER,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user