1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#ifndef HW_ISA_H
#define HW_ISA_H
/* ISA bus */
#include "exec/ioport.h"
#include "exec/memory.h"
#include "hw/qdev.h"
#define ISA_NUM_IRQS 16
#define TYPE_ISA_DEVICE "isa-device"
#define ISA_DEVICE(obj) \
OBJECT_CHECK(ISADevice, (obj), TYPE_ISA_DEVICE)
#define ISA_DEVICE_CLASS(klass) \
OBJECT_CLASS_CHECK(ISADeviceClass, (klass), TYPE_ISA_DEVICE)
#define ISA_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE)
#define TYPE_ISA_BUS "ISA"
#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS)
#define TYPE_APPLE_SMC "isa-applesmc"
#define APPLESMC_MAX_DATA_LENGTH 32
#define APPLESMC_PROP_IO_BASE "iobase"
static inline uint16_t applesmc_port(void)
{
Object *obj = object_resolve_path_type("", TYPE_APPLE_SMC, NULL);
if (obj) {
return object_property_get_int(obj, APPLESMC_PROP_IO_BASE, NULL);
}
return 0;
}
#define TYPE_ISADMA "isa-dma"
#define ISADMA_CLASS(klass) \
OBJECT_CLASS_CHECK(IsaDmaClass, (klass), TYPE_ISADMA)
#define ISADMA_GET_CLASS(obj) \
OBJECT_GET_CLASS(IsaDmaClass, (obj), TYPE_ISADMA)
#define ISADMA(obj) \
INTERFACE_CHECK(IsaDma, (obj), TYPE_ISADMA)
struct IsaDma {
Object parent;
};
typedef enum {
ISADMA_TRANSFER_VERIFY,
ISADMA_TRANSFER_READ,
ISADMA_TRANSFER_WRITE,
ISADMA_TRANSFER_ILLEGAL,
} IsaDmaTransferMode;
typedef int (*IsaDmaTransferHandler)(void *opaque, int nchan, int pos,
int size);
typedef struct IsaDmaClass {
InterfaceClass parent;
IsaDmaTransferMode (*get_transfer_mode)(IsaDma *obj, int nchan);
bool (*has_autoinitialization)(IsaDma *obj, int nchan);
int (*read_memory)(IsaDma *obj, int nchan, void *buf, int pos, int len);
int (*write_memory)(IsaDma *obj, int nchan, void *buf, int pos, int len);
void (*hold_DREQ)(IsaDma *obj, int nchan);
void (*release_DREQ)(IsaDma *obj, int nchan);
void (*schedule)(IsaDma *obj);
void (*register_channel)(IsaDma *obj, int nchan,
IsaDmaTransferHandler transfer_handler,
void *opaque);
} IsaDmaClass;
typedef struct ISADeviceClass {
DeviceClass parent_class;
} ISADeviceClass;
struct ISABus {
/*< private >*/
BusState parent_obj;
/*< public >*/
MemoryRegion *address_space;
MemoryRegion *address_space_io;
qemu_irq *irqs;
IsaDma *dma[2];
};
struct ISADevice {
/*< private >*/
DeviceState parent_obj;
/*< public >*/
uint32_t isairq[2];
int nirqs;
int ioport_id;
};
ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space,
MemoryRegion *address_space_io, Error **errp);
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
qemu_irq isa_get_irq(ISADevice *dev, int isairq);
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16);
IsaDma *isa_get_dma(ISABus *bus, int nchan);
MemoryRegion *isa_address_space(ISADevice *dev);
MemoryRegion *isa_address_space_io(ISADevice *dev);
ISADevice *isa_create(ISABus *bus, const char *name);
ISADevice *isa_try_create(ISABus *bus, const char *name);
ISADevice *isa_create_simple(ISABus *bus, const char *name);
ISADevice *isa_vga_init(ISABus *bus);
/**
* isa_register_ioport: Install an I/O port region on the ISA bus.
*
* Register an I/O port region via memory_region_add_subregion
* inside the ISA I/O address space.
*
* @dev: the ISADevice against which these are registered; may be NULL.
* @io: the #MemoryRegion being registered.
* @start: the base I/O port.
*/
void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start);
/**
* isa_register_portio_list: Initialize a set of ISA io ports
*
* Several ISA devices have many dis-joint I/O ports. Worse, these I/O
* ports can be interleaved with I/O ports from other devices. This
* function makes it easy to create multiple MemoryRegions for a single
* device and use the legacy portio routines.
*
* @dev: the ISADevice against which these are registered; may be NULL.
* @start: the base I/O port against which the portio->offset is applied.
* @portio: the ports, sorted by offset.
* @opaque: passed into the portio callbacks.
* @name: passed into memory_region_init_io.
*/
void isa_register_portio_list(ISADevice *dev, uint16_t start,
const MemoryRegionPortio *portio,
void *opaque, const char *name);
static inline ISABus *isa_bus_from_device(ISADevice *d)
{
return ISA_BUS(qdev_get_parent_bus(DEVICE(d)));
}
/* i8257.c */
void DMA_init(ISABus *bus, int high_page_enable);
#endif
|