diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-03-14 21:46:48 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-03-14 21:46:48 +0000 |
commit | b41a2cd1e4228c765e3b82ec6c89096528b4d7d9 (patch) | |
tree | 7f2180a4dbb0ca207e8c47ab07d03bcb00960730 /hw | |
parent | c4b1fcc0f9594cae64d5bf172548a522db0c2545 (diff) |
io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@664 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r-- | hw/i8254.c | 10 | ||||
-rw-r--r-- | hw/i8259.c | 22 | ||||
-rw-r--r-- | hw/mc146818rtc.c | 12 | ||||
-rw-r--r-- | hw/ne2000.c | 90 | ||||
-rw-r--r-- | hw/pc.c | 100 | ||||
-rw-r--r-- | hw/pckbd.c | 36 | ||||
-rw-r--r-- | hw/serial.c | 81 |
7 files changed, 193 insertions, 158 deletions
diff --git a/hw/i8254.c b/hw/i8254.c index 7dc5f3c25..6e9682501 100644 --- a/hw/i8254.c +++ b/hw/i8254.c @@ -201,7 +201,7 @@ static inline void pit_load_count(PITChannelState *s, int val) } } -void pit_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) { int channel, access; PITChannelState *s; @@ -246,7 +246,7 @@ void pit_ioport_write(CPUState *env, uint32_t addr, uint32_t val) } } -uint32_t pit_ioport_read(CPUState *env, uint32_t addr) +static uint32_t pit_ioport_read(void *opaque, uint32_t addr) { int ret, count; PITChannelState *s; @@ -279,7 +279,7 @@ uint32_t pit_ioport_read(CPUState *env, uint32_t addr) return ret; } -void pit_init(void) +void pit_init(int base) { PITChannelState *s; int i; @@ -291,7 +291,7 @@ void pit_init(void) pit_load_count(s, 0); } - register_ioport_write(0x40, 4, pit_ioport_write, 1); - register_ioport_read(0x40, 3, pit_ioport_read, 1); + register_ioport_write(base, 4, 1, pit_ioport_write, NULL); + register_ioport_read(base, 3, 1, pit_ioport_read, NULL); } diff --git a/hw/i8259.c b/hw/i8259.c index 08c7be394..5ef1fa070 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -46,6 +46,8 @@ /* debug PIC */ //#define DEBUG_PIC +//#define DEBUG_IRQ_LATENCY + typedef struct PicState { uint8_t last_irr; /* edge detection */ uint8_t irr; /* interrupt request register */ @@ -220,15 +222,14 @@ int cpu_x86_get_pic_interrupt(CPUState *env) return intno; } -void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - PicState *s; + PicState *s = opaque; int priority, cmd, irq; #ifdef DEBUG_PIC printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val); #endif - s = &pics[addr >> 7]; addr &= 1; if (addr == 0) { if (val & 0x10) { @@ -334,14 +335,13 @@ static uint32_t pic_poll_read (PicState *s, uint32_t addr1) return ret; } -uint32_t pic_ioport_read(CPUState *env, uint32_t addr1) +static uint32_t pic_ioport_read(void *opaque, uint32_t addr1) { - PicState *s; + PicState *s = opaque; unsigned int addr; int ret; addr = addr1; - s = &pics[addr >> 7]; addr &= 1; if (s->poll) { ret = pic_poll_read(s, addr1); @@ -378,11 +378,9 @@ uint32_t pic_intack_read(CPUState *env) void pic_init(void) { -#if defined (TARGET_I386) || defined (TARGET_PPC) - register_ioport_write(0x20, 2, pic_ioport_write, 1); - register_ioport_read(0x20, 2, pic_ioport_read, 1); - register_ioport_write(0xa0, 2, pic_ioport_write, 1); - register_ioport_read(0xa0, 2, pic_ioport_read, 1); -#endif + register_ioport_write(0x20, 2, 1, pic_ioport_write, &pics[0]); + register_ioport_read(0x20, 2, 1, pic_ioport_read, &pics[0]); + register_ioport_write(0xa0, 2, 1, pic_ioport_write, &pics[1]); + register_ioport_read(0xa0, 2, 1, pic_ioport_read, &pics[1]); } diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index cab76cfab..7d94b25f5 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -69,9 +69,9 @@ RTCState rtc_state; -static void cmos_ioport_write(CPUState *env, uint32_t addr, uint32_t data) +static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) { - RTCState *s = &rtc_state; + RTCState *s = opaque; if ((addr & 1) == 0) { s->cmos_index = data & 0x7f; @@ -134,9 +134,9 @@ static void cmos_update_time(RTCState *s) s->cmos_data[REG_IBM_PS2_CENTURY_BYTE] = s->cmos_data[REG_IBM_CENTURY_BYTE]; } -static uint32_t cmos_ioport_read(CPUState *env, uint32_t addr) +static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) { - RTCState *s = &rtc_state; + RTCState *s = opaque; int ret; if ((addr & 1) == 0) { return 0xff; @@ -197,7 +197,7 @@ void rtc_init(int base, int irq) s->cmos_data[RTC_REG_C] = 0x00; s->cmos_data[RTC_REG_D] = 0x80; - register_ioport_write(base, 2, cmos_ioport_write, 1); - register_ioport_read(base, 2, cmos_ioport_read, 1); + register_ioport_write(base, 2, 1, cmos_ioport_write, s); + register_ioport_read(base, 2, 1, cmos_ioport_read, s); } diff --git a/hw/ne2000.c b/hw/ne2000.c index 0b35495f9..3bb55171a 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -46,8 +46,7 @@ /* debug NE2000 card */ //#define DEBUG_NE2000 -/***********************************************************/ -/* ne2000 emulation */ +#define MAX_ETH_FRAME_SIZE 1514 #define E8390_CMD 0x00 /* The command register (for all pages) */ /* Page 0 register offsets. */ @@ -143,23 +142,16 @@ typedef struct NE2000State { uint8_t curpag; uint8_t mult[8]; /* multicast mask array */ int irq; + NetDriverState *nd; uint8_t mem[NE2000_MEM_SIZE]; } NE2000State; -static NE2000State ne2000_state; -int net_fd = -1; - static void ne2000_reset(NE2000State *s) { int i; s->isr = ENISR_RESET; - s->mem[0] = 0x52; - s->mem[1] = 0x54; - s->mem[2] = 0x00; - s->mem[3] = 0x12; - s->mem[4] = 0x34; - s->mem[5] = 0x56; + memcpy(s->mem, s->nd->macaddr, 6); s->mem[14] = 0x57; s->mem[15] = 0x57; @@ -180,10 +172,10 @@ static void ne2000_update_irq(NE2000State *s) pic_set_irq(s->irq, 0); } -/* return true if the NE2000 can receive more data */ -int ne2000_can_receive(void) +/* return the max buffer size if the NE2000 can receive more data */ +static int ne2000_can_receive(void *opaque) { - NE2000State *s = &ne2000_state; + NE2000State *s = opaque; int avail, index, boundary; if (s->cmd & E8390_STOP) @@ -196,19 +188,30 @@ int ne2000_can_receive(void) avail = (s->stop - s->start) - (index - boundary); if (avail < (MAX_ETH_FRAME_SIZE + 4)) return 0; - return 1; + return MAX_ETH_FRAME_SIZE; } -void ne2000_receive(uint8_t *buf, int size) +#define MIN_BUF_SIZE 60 + +static void ne2000_receive(void *opaque, const uint8_t *buf, int size) { - NE2000State *s = &ne2000_state; + NE2000State *s = opaque; uint8_t *p; int total_len, next, avail, len, index; - + uint8_t buf1[60]; + #if defined(DEBUG_NE2000) printf("NE2000: received len=%d\n", size); #endif + /* if too small buffer, then expand it */ + if (size < MIN_BUF_SIZE) { + memcpy(buf1, buf, size); + memset(buf1 + size, 0, MIN_BUF_SIZE - size); + buf = buf1; + size = MIN_BUF_SIZE; + } + index = s->curpag << 8; /* 4 bytes for header */ total_len = size + 4; @@ -244,9 +247,9 @@ void ne2000_receive(uint8_t *buf, int size) ne2000_update_irq(s); } -static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - NE2000State *s = &ne2000_state; + NE2000State *s = opaque; int offset, page; addr &= 0xf; @@ -264,7 +267,7 @@ static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val) ne2000_update_irq(s); } if (val & E8390_TRANS) { - net_send_packet(net_fd, s->mem + (s->tpsr << 8), s->tcnt); + net_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt); /* signal end of transfert */ s->tsr = ENTSR_PTX; s->isr |= ENISR_TX; @@ -329,9 +332,9 @@ static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val) } } -static uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr) +static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr) { - NE2000State *s = &ne2000_state; + NE2000State *s = opaque; int offset, page, ret; addr &= 0xf; @@ -370,9 +373,9 @@ static uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr) return ret; } -static void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - NE2000State *s = &ne2000_state; + NE2000State *s = opaque; uint8_t *p; #ifdef DEBUG_NE2000 @@ -401,9 +404,9 @@ static void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) } } -static uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr) +static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr) { - NE2000State *s = &ne2000_state; + NE2000State *s = opaque; uint8_t *p; int ret; @@ -433,33 +436,40 @@ static uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr) return ret; } -static void ne2000_reset_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val) { /* nothing to do (end of reset pulse) */ } -static uint32_t ne2000_reset_ioport_read(CPUState *env, uint32_t addr) +static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr) { - NE2000State *s = &ne2000_state; + NE2000State *s = opaque; ne2000_reset(s); return 0; } -void ne2000_init(int base, int irq) +void ne2000_init(int base, int irq, NetDriverState *nd) { - NE2000State *s = &ne2000_state; + NE2000State *s; - register_ioport_write(base, 16, ne2000_ioport_write, 1); - register_ioport_read(base, 16, ne2000_ioport_read, 1); + s = qemu_mallocz(sizeof(NE2000State)); + if (!s) + return; + + register_ioport_write(base, 16, 1, ne2000_ioport_write, s); + register_ioport_read(base, 16, 1, ne2000_ioport_read, s); - register_ioport_write(base + 0x10, 1, ne2000_asic_ioport_write, 1); - register_ioport_read(base + 0x10, 1, ne2000_asic_ioport_read, 1); - register_ioport_write(base + 0x10, 2, ne2000_asic_ioport_write, 2); - register_ioport_read(base + 0x10, 2, ne2000_asic_ioport_read, 2); + register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s); + register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s); + register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s); + register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s); - register_ioport_write(base + 0x1f, 1, ne2000_reset_ioport_write, 1); - register_ioport_read(base + 0x1f, 1, ne2000_reset_ioport_read, 1); + register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s); + register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s); s->irq = irq; + s->nd = nd; ne2000_reset(s); + + add_fd_read_handler(nd->fd, ne2000_can_receive, ne2000_receive, s); } @@ -43,6 +43,9 @@ #include "cpu.h" #include "vl.h" +/* output Bochs bios info messages */ +//#define DEBUG_BIOS + #define BIOS_FILENAME "bios.bin" #define VGABIOS_FILENAME "vgabios.bin" #define LINUX_BOOT_FILENAME "linux_boot.bin" @@ -55,7 +58,7 @@ int speaker_data_on; int dummy_refresh_clock; -static void ioport80_write(CPUState *env, uint32_t addr, uint32_t data) +static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) { } @@ -65,6 +68,7 @@ static void cmos_init(int ram_size, int boot_device) { RTCState *s = &rtc_state; int val; + int fd0, fd1, nb; /* various important CMOS locations needed by PC/Bochs bios */ @@ -99,12 +103,11 @@ static void cmos_init(int ram_size, int boot_device) s->cmos_data[0x3d] = 0x03; /* CD-ROM boot */ break; } -} -void cmos_register_fd (uint8_t fd0, uint8_t fd1) -{ - RTCState *s = &rtc_state; - int nb = 0; + /* floppy type */ + + fd0 = fdctrl_get_drive_type(0); + fd1 = fdctrl_get_drive_type(1); s->cmos_data[0x10] = 0; switch (fd0) { @@ -135,6 +138,7 @@ void cmos_register_fd (uint8_t fd0, uint8_t fd1) s->cmos_data[0x10] |= 0x02; break; } + nb = 0; if (fd0 < 3) nb++; if (fd1 < 3) @@ -151,13 +155,13 @@ void cmos_register_fd (uint8_t fd0, uint8_t fd1) } } -void speaker_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) { speaker_data_on = (val >> 1) & 1; pit_set_gate(&pit_channels[2], val & 1); } -uint32_t speaker_ioport_read(CPUState *env, uint32_t addr) +static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) { int out; out = pit_get_out(&pit_channels[2]); @@ -167,27 +171,9 @@ uint32_t speaker_ioport_read(CPUState *env, uint32_t addr) } /***********************************************************/ -/* PC floppy disk controler emulation glue */ -#define PC_FDC_DMA 0x2 -#define PC_FDC_IRQ 0x6 -#define PC_FDC_BASE 0x3F0 - -static void fdctrl_register (unsigned char **disknames, int ro, - char boot_device) -{ - int i; - - fdctrl_init(PC_FDC_IRQ, PC_FDC_DMA, 0, PC_FDC_BASE, boot_device); - for (i = 0; i < MAX_FD; i++) { - if (disknames[i] != NULL) - fdctrl_disk_change(i, disknames[i], ro); - } -} - -/***********************************************************/ /* Bochs BIOS debug ports */ -void bochs_bios_write(CPUX86State *env, uint32_t addr, uint32_t val) +void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) { switch(addr) { /* Bochs BIOS messages */ @@ -218,15 +204,15 @@ void bochs_bios_write(CPUX86State *env, uint32_t addr, uint32_t val) void bochs_bios_init(void) { - register_ioport_write(0x400, 1, bochs_bios_write, 2); - register_ioport_write(0x401, 1, bochs_bios_write, 2); - register_ioport_write(0x402, 1, bochs_bios_write, 1); - register_ioport_write(0x403, 1, bochs_bios_write, 1); - - register_ioport_write(0x501, 1, bochs_bios_write, 2); - register_ioport_write(0x502, 1, bochs_bios_write, 2); - register_ioport_write(0x500, 1, bochs_bios_write, 1); - register_ioport_write(0x503, 1, bochs_bios_write, 1); + register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL); + register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL); + + register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL); + register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); } @@ -261,6 +247,15 @@ int load_kernel(const char *filename, uint8_t *addr, return -1; } +static const int ide_iobase[2] = { 0x1f0, 0x170 }; +static const int ide_iobase2[2] = { 0x3f6, 0x376 }; +static const int ide_irq[2] = { 14, 15 }; + +#define NE2000_NB_MAX 6 + +static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; +static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; + /* PC hardware initialisation */ void pc_init(int ram_size, int vga_ram_size, int boot_device, DisplayState *ds, const char **fd_filename, int snapshot, @@ -268,7 +263,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, const char *initrd_filename) { char buf[1024]; - int ret, linux_boot, initrd_size; + int ret, linux_boot, initrd_size, i, nb_nics1, fd; linux_boot = (kernel_filename != NULL); @@ -344,25 +339,38 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, } /* init basic PC hardware */ - register_ioport_write(0x80, 1, ioport80_write, 1); + register_ioport_write(0x80, 1, 1, ioport80_write, NULL); vga_initialize(ds, phys_ram_base + ram_size, ram_size, vga_ram_size); rtc_init(0x70, 8); - cmos_init(ram_size, boot_device); - register_ioport_read(0x61, 1, speaker_ioport_read, 1); - register_ioport_write(0x61, 1, speaker_ioport_write, 1); + register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL); + register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL); pic_init(); - pit_init(); - serial_init(0x3f8, 4); - ne2000_init(0x300, 9); - ide_init(); + pit_init(0x40); + + fd = serial_open_device(); + serial_init(0x3f8, 4, fd); + + nb_nics1 = nb_nics; + if (nb_nics1 > NE2000_NB_MAX) + nb_nics1 = NE2000_NB_MAX; + for(i = 0; i < nb_nics1; i++) { + ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]); + } + + for(i = 0; i < 2; i++) { + ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], + bs_table[2 * i], bs_table[2 * i + 1]); + } kbd_init(); AUD_init(); DMA_init(); SB16_init(); - fdctrl_register((unsigned char **)fd_filename, snapshot, boot_device); + fdctrl_init(6, 2, 0, 0x3f0, fd_table); + + cmos_init(ram_size, boot_device); } diff --git a/hw/pckbd.c b/hw/pckbd.c index 8c0d3a72c..21524c8f4 100644 --- a/hw/pckbd.c +++ b/hw/pckbd.c @@ -189,7 +189,7 @@ static void kbd_update_irq(KBDState *s) static void kbd_queue(KBDState *s, int b, int aux) { - KBDQueue *q = &kbd_state.queues[aux]; + KBDQueue *q = &s->queues[aux]; #if defined(DEBUG_MOUSE) || defined(DEBUG_KBD) if (aux) @@ -214,9 +214,9 @@ void kbd_put_keycode(int keycode) kbd_queue(s, keycode, 0); } -static uint32_t kbd_read_status(CPUState *env, uint32_t addr) +static uint32_t kbd_read_status(void *opaque, uint32_t addr) { - KBDState *s = &kbd_state; + KBDState *s = opaque; int val; val = s->status; #if defined(DEBUG_KBD) @@ -225,9 +225,9 @@ static uint32_t kbd_read_status(CPUState *env, uint32_t addr) return val; } -static void kbd_write_command(CPUState *env, uint32_t addr, uint32_t val) +static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val) { - KBDState *s = &kbd_state; + KBDState *s = opaque; #ifdef DEBUG_KBD printf("kbd: write cmd=0x%02x\n", val); @@ -285,10 +285,10 @@ static void kbd_write_command(CPUState *env, uint32_t addr, uint32_t val) break; #ifdef TARGET_I386 case KBD_CCMD_ENABLE_A20: - cpu_x86_set_a20(env, 1); + cpu_x86_set_a20(cpu_single_env, 1); break; case KBD_CCMD_DISABLE_A20: - cpu_x86_set_a20(env, 0); + cpu_x86_set_a20(cpu_single_env, 0); break; #endif case KBD_CCMD_RESET: @@ -304,9 +304,9 @@ static void kbd_write_command(CPUState *env, uint32_t addr, uint32_t val) } } -static uint32_t kbd_read_data(CPUState *env, uint32_t addr) +static uint32_t kbd_read_data(void *opaque, uint32_t addr) { - KBDState *s = &kbd_state; + KBDState *s = opaque; KBDQueue *q; int val, index; @@ -605,9 +605,9 @@ static void kbd_write_mouse(KBDState *s, int val) } } -void kbd_write_data(CPUState *env, uint32_t addr, uint32_t val) +void kbd_write_data(void *opaque, uint32_t addr, uint32_t val) { - KBDState *s = &kbd_state; + KBDState *s = opaque; #ifdef DEBUG_KBD printf("kbd: write data=0x%02x\n", val); @@ -629,7 +629,7 @@ void kbd_write_data(CPUState *env, uint32_t addr, uint32_t val) break; case KBD_CCMD_WRITE_OUTPORT: #ifdef TARGET_I386 - cpu_x86_set_a20(env, (val >> 1) & 1); + cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1); #endif if (!(val & 1)) { reset_requested = 1; @@ -664,9 +664,11 @@ void kbd_reset(KBDState *s) void kbd_init(void) { - kbd_reset(&kbd_state); - register_ioport_read(0x60, 1, kbd_read_data, 1); - register_ioport_write(0x60, 1, kbd_write_data, 1); - register_ioport_read(0x64, 1, kbd_read_status, 1); - register_ioport_write(0x64, 1, kbd_write_command, 1); + KBDState *s = &kbd_state; + + kbd_reset(s); + register_ioport_read(0x60, 1, 1, kbd_read_data, s); + register_ioport_write(0x60, 1, 1, kbd_write_data, s); + register_ioport_read(0x64, 1, 1, kbd_read_status, s); + register_ioport_write(0x64, 1, 1, kbd_write_command, s); } diff --git a/hw/serial.c b/hw/serial.c index e1225ec40..60c311e55 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -90,7 +90,7 @@ #define UART_LSR_OE 0x02 /* Overrun error indicator */ #define UART_LSR_DR 0x01 /* Receiver data ready */ -typedef struct SerialState { +struct SerialState { uint8_t divider; uint8_t rbr; /* receive register */ uint8_t ier; @@ -104,14 +104,11 @@ typedef struct SerialState { it can be reset while reading iir */ int thr_ipending; int irq; -} SerialState; + int out_fd; +}; -SerialState serial_ports[1]; - -void serial_update_irq(void) +static void serial_update_irq(SerialState *s) { - SerialState *s = &serial_ports[0]; - if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { s->iir = UART_IIR_RDI; } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) { @@ -126,9 +123,9 @@ void serial_update_irq(void) } } -void serial_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - SerialState *s = &serial_ports[0]; + SerialState *s = opaque; unsigned char ch; int ret; @@ -144,16 +141,16 @@ void serial_ioport_write(CPUState *env, uint32_t addr, uint32_t val) } else { s->thr_ipending = 0; s->lsr &= ~UART_LSR_THRE; - serial_update_irq(); + serial_update_irq(s); ch = val; do { - ret = write(1, &ch, 1); + ret = write(s->out_fd, &ch, 1); } while (ret != 1); s->thr_ipending = 1; s->lsr |= UART_LSR_THRE; s->lsr |= UART_LSR_TEMT; - serial_update_irq(); + serial_update_irq(s); } break; case 1: @@ -161,7 +158,7 @@ void serial_ioport_write(CPUState *env, uint32_t addr, uint32_t val) s->divider = (s->divider & 0x00ff) | (val << 8); } else { s->ier = val; - serial_update_irq(); + serial_update_irq(s); } break; case 2: @@ -183,9 +180,9 @@ void serial_ioport_write(CPUState *env, uint32_t addr, uint32_t val) } } -uint32_t serial_ioport_read(CPUState *env, uint32_t addr) +static uint32_t serial_ioport_read(void *opaque, uint32_t addr) { - SerialState *s = &serial_ports[0]; + SerialState *s = opaque; uint32_t ret; addr &= 7; @@ -197,7 +194,7 @@ uint32_t serial_ioport_read(CPUState *env, uint32_t addr) } else { ret = s->rbr; s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); - serial_update_irq(); + serial_update_irq(s); } break; case 1: @@ -212,7 +209,7 @@ uint32_t serial_ioport_read(CPUState *env, uint32_t addr) /* reset THR pending bit */ if ((ret & 0x7) == UART_IIR_THRI) s->thr_ipending = 0; - serial_update_irq(); + serial_update_irq(s); break; case 3: ret = s->lcr; @@ -244,38 +241,58 @@ uint32_t serial_ioport_read(CPUState *env, uint32_t addr) return ret; } -int serial_can_receive(void) +int serial_can_receive(SerialState *s) { - SerialState *s = &serial_ports[0]; return !(s->lsr & UART_LSR_DR); } -void serial_receive_byte(int ch) +void serial_receive_byte(SerialState *s, int ch) { - SerialState *s = &serial_ports[0]; - s->rbr = ch; s->lsr |= UART_LSR_DR; - serial_update_irq(); + serial_update_irq(s); } -void serial_receive_break(void) +void serial_receive_break(SerialState *s) { - SerialState *s = &serial_ports[0]; - s->rbr = 0; s->lsr |= UART_LSR_BI | UART_LSR_DR; - serial_update_irq(); + serial_update_irq(s); } -void serial_init(int base, int irq) +static int serial_can_receive1(void *opaque) { - SerialState *s = &serial_ports[0]; + SerialState *s = opaque; + return serial_can_receive(s); +} + +static void serial_receive1(void *opaque, const uint8_t *buf, int size) +{ + SerialState *s = opaque; + serial_receive_byte(s, buf[0]); +} +/* If fd is zero, it means that the serial device uses the console */ +SerialState *serial_init(int base, int irq, int fd) +{ + SerialState *s; + + s = qemu_mallocz(sizeof(SerialState)); + if (!s) + return NULL; s->irq = irq; s->lsr = UART_LSR_TEMT | UART_LSR_THRE; s->iir = UART_IIR_NO_INT; - - register_ioport_write(base, 8, serial_ioport_write, 1); - register_ioport_read(base, 8, serial_ioport_read, 1); + + register_ioport_write(base, 8, 1, serial_ioport_write, s); + register_ioport_read(base, 8, 1, serial_ioport_read, s); + + if (fd != 0) { + add_fd_read_handler(fd, serial_can_receive1, serial_receive1, s); + s->out_fd = fd; + } else { + serial_console = s; + s->out_fd = 1; + } + return s; } |