-int generic_write_port(ushort_t port,
- void * src,
- uint_t length,
- struct vm_device * dev)
+int generic_write_port_passthrough(ushort_t port,
+ void * src,
+ uint_t length,
+ struct vm_device * dev)
{
uint_t i;
for (i = 0; i < length; i++) {
GENERIC_DEBUG_PRINT("%x", ((uchar_t*)src)[i]);
}
-
+
GENERIC_DEBUG_PRINT(" to port 0x%x ... ", port);
- for (i = 0; i < length; i++) {
- Out_Byte(port, ((uchar_t*)src)[i]);
+ switch (length) {
+ case 1:
+ Out_Byte(port,((uchar_t*)src)[0]);
+ break;
+ case 2:
+ Out_Word(port,((ushort_t*)src)[0]);
+ break;
+ case 4:
+ Out_DWord(port,((uint_t*)src)[0]);
+ break;
+ default:
+ for (i = 0; i < length; i++) {
+ Out_Byte(port, ((uchar_t*)src)[i]);
+ }
}
GENERIC_DEBUG_PRINT(" done\n");
return length;
}
-int generic_read_port(ushort_t port,
- void * src,
- uint_t length,
- struct vm_device * dev)
+int generic_read_port_passthrough(ushort_t port,
+ void * src,
+ uint_t length,
+ struct vm_device * dev)
{
uint_t i;
GENERIC_DEBUG_PRINT("generic: reading 0x%x bytes from port 0x%x ...", length, port);
- for (i = 0; i < length; i++) {
- ((uchar_t*)src)[i] = In_Byte(port);
+ switch (length) {
+ case 1:
+ ((uchar_t*)src)[0] = In_Byte(port);
+ break;
+ case 2:
+ ((ushort_t*)src)[0] = In_Word(port);
+ break;
+ case 4:
+ ((uint_t*)src)[0] = In_DWord(port);
+ break;
+ default:
+ for (i = 0; i < length; i++) {
+ ((uchar_t*)src)[i] = In_Byte(port);
+ }
}
GENERIC_DEBUG_PRINT(" done ... read 0x");
return length;
}
+int generic_write_port_ignore(ushort_t port,
+ void * src,
+ uint_t length,
+ struct vm_device * dev)
+{
+ uint_t i;
+
+ GENERIC_DEBUG_PRINT("generic: writing 0x");
+
+ for (i = 0; i < length; i++) {
+ GENERIC_DEBUG_PRINT("%x", ((uchar_t*)src)[i]);
+ }
+
+ GENERIC_DEBUG_PRINT(" to port 0x%x ... ", port);
+
+ GENERIC_DEBUG_PRINT(" ignored\n");
+
+ return length;
+}
+
+int generic_read_port_ignore(ushort_t port,
+ void * src,
+ uint_t length,
+ struct vm_device * dev)
+{
+
+ GENERIC_DEBUG_PRINT("generic: reading 0x%x bytes from port 0x%x ...", length, port);
+
+ memset((char*)src,0,length);
+ GENERIC_DEBUG_PRINT(" ignored (return zeroed buffer)\n");
+
+ return length;
+}
+
int generic_interrupt(uint_t irq,
generic_reset_device(dev);
for (i = 0; i < state->num_port_ranges; i++) {
- GENERIC_DEBUG_PRINT("generic: hooking ports 0x%x to 0x%x\n", state->port_ranges[i][0], state->port_ranges[i][1]);
+ GENERIC_DEBUG_PRINT("generic: hooking ports 0x%x to 0x%x as %x\n", state->port_ranges[i][0], state->port_ranges[i][1], state->port_ranges[i][2]==GENERIC_PRINT_AND_PASSTHROUGH ? "print-and-passthrough" : "print-and-ignore");
#if PORT_HOOKS
for (j = state->port_ranges[i][0]; j <= state->port_ranges[i][1]; j++) {
- if (dev_hook_io(dev, j, &generic_read_port, &generic_write_port)) {
- GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n", j);
- }
+ if (state->port_ranges[i][2]==GENERIC_PRINT_AND_PASSTHROUGH) {
+ if (dev_hook_io(dev, j, &generic_read_port_passthrough, &generic_write_port_passthrough)) {
+ GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n", j);
+ }
+ } else if (state->port_ranges[i][2]==GENERIC_PRINT_AND_IGNORE) {
+ if (dev_hook_io(dev, j, &generic_read_port_ignore, &generic_write_port_ignore)) {
+ GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n", j);
+ }
+ }
}
#else
GENERIC_DEBUG_PRINT("generic: hooking ports not supported\n");
struct vm_device *create_generic(generic_port_range_type port_ranges[],
- uint_t num_port_ranges,
generic_address_range_type address_ranges[],
- uint_t num_address_ranges,
- generic_irq_range_type irq_ranges[],
- uint_t num_irq_ranges)
+ generic_irq_range_type irq_ranges[])
{
struct generic_internal * generic_state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
+ int i;
+ uint_t num_port_ranges, num_address_ranges, num_irq_ranges;
+
+ num_port_ranges=0;
+ if (port_ranges!=NULL) {
+ i=0;
+ while (port_ranges[i]!=NULL &&
+ !(port_ranges[i][0]==0 && port_ranges[i][1]==0 && port_ranges[i][2]==0))
+ { num_port_ranges++; i++; }
+ }
+
+ num_address_ranges=0;
+ if (address_ranges!=NULL) {
+ i=0;
+ while (address_ranges[i]!=NULL &&
+ !(address_ranges[i][0]==0 && address_ranges[i][1]==0 && address_ranges[i][2]==0))
+ { num_address_ranges++; i++; }
+ }
+
+ num_irq_ranges=0;
+ if (irq_ranges!=NULL) {
+ i=0;
+ while (irq_ranges[i]!=NULL &&
+ !(irq_ranges[i][0]==0 && irq_ranges[i][1]==0 && irq_ranges[i][2]==0) )
+ { num_irq_ranges++; i++; }
+ }
+
generic_state->num_port_ranges = num_port_ranges;