aboutsummaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 (patch)
tree550ce922ea0e125ac6a9738210ce2939bf2fe901 /hw
parent413f05aaf54fa08c0ae7e997327a4f4a473c0a8d (diff)
downloadexternal_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.zip
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.gz
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.bz2
Initial Contribution
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi-dsdt.dsl559
-rw-r--r--hw/acpi-dsdt.hex278
-rw-r--r--hw/acpi.c615
-rw-r--r--hw/adb.c410
-rw-r--r--hw/adlib.c341
-rw-r--r--hw/android_arm.c149
-rw-r--r--hw/apb_pci.c232
-rw-r--r--hw/apic.c1042
-rw-r--r--hw/arm_pic.c43
-rw-r--r--hw/arm_pic.h6
-rw-r--r--hw/arm_timer.c383
-rw-r--r--hw/cirrus_vga.c3193
-rw-r--r--hw/cirrus_vga_rop.h78
-rw-r--r--hw/cirrus_vga_rop2.h281
-rw-r--r--hw/cuda.c656
-rw-r--r--hw/es1370.c1062
-rw-r--r--hw/esp.c571
-rw-r--r--hw/fdc.c1757
-rw-r--r--hw/fmopl.c1390
-rw-r--r--hw/fmopl.h174
-rw-r--r--hw/goldfish_audio.c521
-rw-r--r--hw/goldfish_battery.c261
-rw-r--r--hw/goldfish_device.c200
-rw-r--r--hw/goldfish_device.h58
-rw-r--r--hw/goldfish_events_device.c423
-rw-r--r--hw/goldfish_fb.c405
-rw-r--r--hw/goldfish_interrupt.c190
-rw-r--r--hw/goldfish_memlog.c78
-rw-r--r--hw/goldfish_mmc.c465
-rw-r--r--hw/goldfish_nand.c639
-rw-r--r--hw/goldfish_nand.h28
-rw-r--r--hw/goldfish_nand_reg.h54
-rw-r--r--hw/goldfish_switch.c172
-rw-r--r--hw/goldfish_timer.c255
-rw-r--r--hw/goldfish_trace.c252
-rw-r--r--hw/goldfish_trace.h78
-rw-r--r--hw/goldfish_tty.c225
-rw-r--r--hw/grackle_pci.c156
-rw-r--r--hw/heathrow_pic.c168
-rw-r--r--hw/i8254.c482
-rw-r--r--hw/i8259.c561
-rw-r--r--hw/ide.c2535
-rw-r--r--hw/integratorcp.c546
-rw-r--r--hw/iommu.c258
-rw-r--r--hw/irq.c71
-rw-r--r--hw/irq.h32
-rw-r--r--hw/lance.c462
-rw-r--r--hw/lsi53c895a.c1571
-rw-r--r--hw/m48t59.c614
-rw-r--r--hw/m48t59.h13
-rw-r--r--hw/mc146818rtc.c463
-rw-r--r--hw/mips_r4k.c291
-rw-r--r--hw/mmc.h214
-rw-r--r--hw/ne2000.c816
-rw-r--r--hw/openpic.c1027
-rw-r--r--hw/parallel.c183
-rw-r--r--hw/pc.c911
-rw-r--r--hw/pci.c40
-rw-r--r--hw/pckbd.c370
-rw-r--r--hw/pcnet.c1789
-rw-r--r--hw/pcspk.c147
-rw-r--r--hw/pflash_cfi02.c624
-rw-r--r--hw/piix_pci.c419
-rw-r--r--hw/pl011.c251
-rw-r--r--hw/pl050.c127
-rw-r--r--hw/pl080.c328
-rw-r--r--hw/pl110.c420
-rw-r--r--hw/pl110_template.h252
-rw-r--r--hw/pl190.c252
-rw-r--r--hw/power_supply.h109
-rw-r--r--hw/ppc.c428
-rw-r--r--hw/ppc_chrp.c566
-rw-r--r--hw/ppc_prep.c694
-rw-r--r--hw/prep_pci.c167
-rw-r--r--hw/ps2.c566
-rw-r--r--hw/rtl8139.c3471
-rw-r--r--hw/sb16.c1451
-rw-r--r--hw/sd.h83
-rw-r--r--hw/serial.c456
-rw-r--r--hw/sh7750.c836
-rw-r--r--hw/sh7750_regnames.c128
-rw-r--r--hw/sh7750_regnames.h6
-rw-r--r--hw/sh7750_regs.h1623
-rw-r--r--hw/shix.c111
-rw-r--r--hw/slavio_intctl.c400
-rw-r--r--hw/slavio_misc.c244
-rw-r--r--hw/slavio_serial.c545
-rw-r--r--hw/slavio_timer.c288
-rw-r--r--hw/smc91c111.c12
-rw-r--r--hw/sun4m.c324
-rw-r--r--hw/sun4u.c368
-rw-r--r--hw/tc58128.c181
-rw-r--r--hw/tcx.c330
-rw-r--r--hw/unin_pci.c261
-rw-r--r--hw/usb-hid.c18
-rw-r--r--hw/usb-hub.c12
-rw-r--r--hw/usb-msd.c16
-rw-r--r--hw/usb-uhci.c674
-rw-r--r--hw/usb.c5
-rw-r--r--hw/usb.h5
-rw-r--r--hw/versatile_pci.c119
-rw-r--r--hw/versatilepb.c473
-rw-r--r--hw/vga.c1945
-rw-r--r--hw/vga_int.h173
-rw-r--r--hw/vga_template.h525
105 files changed, 5022 insertions, 46508 deletions
diff --git a/hw/acpi-dsdt.dsl b/hw/acpi-dsdt.dsl
deleted file mode 100644
index fc4081f..0000000
--- a/hw/acpi-dsdt.dsl
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * QEMU ACPI DSDT ASL definition
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-DefinitionBlock (
- "acpi-dsdt.aml", // Output Filename
- "DSDT", // Signature
- 0x01, // DSDT Compliance Revision
- "QEMU", // OEMID
- "QEMUDSDT", // TABLE ID
- 0x1 // OEM Revision
- )
-{
- Scope (\)
- {
- /* CMOS memory access */
- OperationRegion (CMS, SystemIO, 0x70, 0x02)
- Field (CMS, ByteAcc, NoLock, Preserve)
- {
- CMSI, 8,
- CMSD, 8
- }
- Method (CMRD, 1, NotSerialized)
- {
- Store (Arg0, CMSI)
- Store (CMSD, Local0)
- Return (Local0)
- }
-
- /* Debug Output */
- OperationRegion (DBG, SystemIO, 0xb044, 0x04)
- Field (DBG, DWordAcc, NoLock, Preserve)
- {
- DBGL, 32,
- }
- }
-
-
- /* PCI Bus definition */
- Scope(\_SB) {
- Device(PCI0) {
- Name (_HID, EisaId ("PNP0A03"))
- Name (_ADR, 0x00)
- Name (_UID, 1)
- Name(_PRT, Package() {
- /* PCI IRQ routing table, example from ACPI 2.0a specification,
- section 6.2.8.1 */
- /* Note: we provide the same info as the PCI routing
- table of the Bochs BIOS */
-
- // PCI Slot 0
- Package() {0x0000ffff, 0, LNKD, 0},
- Package() {0x0000ffff, 1, LNKA, 0},
- Package() {0x0000ffff, 2, LNKB, 0},
- Package() {0x0000ffff, 3, LNKC, 0},
-
- // PCI Slot 1
- Package() {0x0001ffff, 0, LNKA, 0},
- Package() {0x0001ffff, 1, LNKB, 0},
- Package() {0x0001ffff, 2, LNKC, 0},
- Package() {0x0001ffff, 3, LNKD, 0},
-
- // PCI Slot 2
- Package() {0x0002ffff, 0, LNKB, 0},
- Package() {0x0002ffff, 1, LNKC, 0},
- Package() {0x0002ffff, 2, LNKD, 0},
- Package() {0x0002ffff, 3, LNKA, 0},
-
- // PCI Slot 3
- Package() {0x0003ffff, 0, LNKC, 0},
- Package() {0x0003ffff, 1, LNKD, 0},
- Package() {0x0003ffff, 2, LNKA, 0},
- Package() {0x0003ffff, 3, LNKB, 0},
-
- // PCI Slot 4
- Package() {0x0004ffff, 0, LNKD, 0},
- Package() {0x0004ffff, 1, LNKA, 0},
- Package() {0x0004ffff, 2, LNKB, 0},
- Package() {0x0004ffff, 3, LNKC, 0},
-
- // PCI Slot 5
- Package() {0x0005ffff, 0, LNKA, 0},
- Package() {0x0005ffff, 1, LNKB, 0},
- Package() {0x0005ffff, 2, LNKC, 0},
- Package() {0x0005ffff, 3, LNKD, 0},
- })
-
- Method (_CRS, 0, NotSerialized)
- {
- Name (MEMP, ResourceTemplate ()
- {
- WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
- 0x0000, // Address Space Granularity
- 0x0000, // Address Range Minimum
- 0x00FF, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0x0100, // Address Length
- ,, )
- IO (Decode16,
- 0x0CF8, // Address Range Minimum
- 0x0CF8, // Address Range Maximum
- 0x01, // Address Alignment
- 0x08, // Address Length
- )
- WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
- 0x0000, // Address Space Granularity
- 0x0000, // Address Range Minimum
- 0x0CF7, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0x0CF8, // Address Length
- ,, , TypeStatic)
- WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
- 0x0000, // Address Space Granularity
- 0x0D00, // Address Range Minimum
- 0xFFFF, // Address Range Maximum
- 0x0000, // Address Translation Offset
- 0xF300, // Address Length
- ,, , TypeStatic)
- DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0x000A0000, // Address Range Minimum
- 0x000BFFFF, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0x00020000, // Address Length
- ,, , AddressRangeMemory, TypeStatic)
- DWordMemory (ResourceProducer, PosDecode, MinNotFixed, MaxFixed, NonCacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0x00000000, // Address Range Minimum
- 0xFEBFFFFF, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0x00000000, // Address Length
- ,, MEMF, AddressRangeMemory, TypeStatic)
- })
- CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MIN, PMIN)
- CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MAX, PMAX)
- CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._LEN, PLEN)
- /* compute available RAM */
- Add(CMRD(0x34), ShiftLeft(CMRD(0x35), 8), Local0)
- ShiftLeft(Local0, 16, Local0)
- Add(Local0, 0x1000000, Local0)
- /* update field of last region */
- Store(Local0, PMIN)
- Subtract (PMAX, PMIN, PLEN)
- Increment (PLEN)
- Return (MEMP)
- }
- }
- }
-
- Scope(\_SB.PCI0) {
-
- /* PIIX3 ISA bridge */
- Device (ISA) {
- Name (_ADR, 0x00010000)
-
- /* PIIX PCI to ISA irq remapping */
- OperationRegion (P40C, PCI_Config, 0x60, 0x04)
-
-
- /* Keyboard seems to be important for WinXP install */
- Device (KBD)
- {
- Name (_HID, EisaId ("PNP0303"))
- Method (_STA, 0, NotSerialized)
- {
- Return (0x0f)
- }
-
- Method (_CRS, 0, NotSerialized)
- {
- Name (TMP, ResourceTemplate ()
- {
- IO (Decode16,
- 0x0060, // Address Range Minimum
- 0x0060, // Address Range Maximum
- 0x01, // Address Alignment
- 0x01, // Address Length
- )
- IO (Decode16,
- 0x0064, // Address Range Minimum
- 0x0064, // Address Range Maximum
- 0x01, // Address Alignment
- 0x01, // Address Length
- )
- IRQNoFlags ()
- {1}
- })
- Return (TMP)
- }
- }
-
- /* PS/2 mouse */
- Device (MOU)
- {
- Name (_HID, EisaId ("PNP0F13"))
- Method (_STA, 0, NotSerialized)
- {
- Return (0x0f)
- }
-
- Method (_CRS, 0, NotSerialized)
- {
- Name (TMP, ResourceTemplate ()
- {
- IRQNoFlags () {12}
- })
- Return (TMP)
- }
- }
-
- /* PS/2 floppy controller */
- Device (FDC0)
- {
- Name (_HID, EisaId ("PNP0700"))
- Method (_STA, 0, NotSerialized)
- {
- Return (0x0F)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
- IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
- IRQNoFlags () {6}
- DMA (Compatibility, NotBusMaster, Transfer8) {2}
- })
- Return (BUF0)
- }
- }
-
- /* Parallel port */
- Device (LPT)
- {
- Name (_HID, EisaId ("PNP0400"))
- Method (_STA, 0, NotSerialized)
- {
- Store (\_SB.PCI0.PX13.DRSA, Local0)
- And (Local0, 0x80000000, Local0)
- If (LEqual (Local0, 0))
- {
- Return (0x00)
- }
- Else
- {
- Return (0x0F)
- }
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
- IRQNoFlags () {7}
- })
- Return (BUF0)
- }
- }
-
- /* Serial Ports */
- Device (COM1)
- {
- Name (_HID, EisaId ("PNP0501"))
- Name (_UID, 0x01)
- Method (_STA, 0, NotSerialized)
- {
- Store (\_SB.PCI0.PX13.DRSC, Local0)
- And (Local0, 0x08000000, Local0)
- If (LEqual (Local0, 0))
- {
- Return (0x00)
- }
- Else
- {
- Return (0x0F)
- }
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
- IRQNoFlags () {4}
- })
- Return (BUF0)
- }
- }
-
- Device (COM2)
- {
- Name (_HID, EisaId ("PNP0501"))
- Name (_UID, 0x02)
- Method (_STA, 0, NotSerialized)
- {
- Store (\_SB.PCI0.PX13.DRSC, Local0)
- And (Local0, 0x80000000, Local0)
- If (LEqual (Local0, 0))
- {
- Return (0x00)
- }
- Else
- {
- Return (0x0F)
- }
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (BUF0, ResourceTemplate ()
- {
- IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
- IRQNoFlags () {3}
- })
- Return (BUF0)
- }
- }
- }
-
- /* PIIX4 PM */
- Device (PX13) {
- Name (_ADR, 0x00010003)
-
- OperationRegion (P13C, PCI_Config, 0x5c, 0x24)
- Field (P13C, DWordAcc, NoLock, Preserve)
- {
- DRSA, 32,
- DRSB, 32,
- DRSC, 32,
- DRSE, 32,
- DRSF, 32,
- DRSG, 32,
- DRSH, 32,
- DRSI, 32,
- DRSJ, 32
- }
- }
- }
-
- /* PCI IRQs */
- Scope(\_SB) {
- Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
- {
- PRQ0, 8,
- PRQ1, 8,
- PRQ2, 8,
- PRQ3, 8
- }
-
- Device(LNKA){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 1)
- Name(_PRS, ResourceTemplate(){
- IRQ (Level, ActiveLow, Shared)
- {3,4,5,6,7,9,10,11,12}
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ0, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ0, 0x80, PRQ0)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- IRQ (Level, ActiveLow, Shared)
- {1}
- })
- CreateWordField (PRR0, 0x01, TMP)
- Store (PRQ0, Local0)
- If (LLess (Local0, 0x80))
- {
- ShiftLeft (One, Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateWordField (Arg0, 0x01, TMP)
- FindSetRightBit (TMP, Local0)
- Decrement (Local0)
- Store (Local0, PRQ0)
- }
- }
- Device(LNKB){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 2)
- Name(_PRS, ResourceTemplate(){
- IRQ (Level, ActiveLow, Shared)
- {3,4,5,6,7,9,10,11,12}
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ1, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ1, 0x80, PRQ1)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- IRQ (Level, ActiveLow, Shared)
- {1}
- })
- CreateWordField (PRR0, 0x01, TMP)
- Store (PRQ1, Local0)
- If (LLess (Local0, 0x80))
- {
- ShiftLeft (One, Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateWordField (Arg0, 0x01, TMP)
- FindSetRightBit (TMP, Local0)
- Decrement (Local0)
- Store (Local0, PRQ1)
- }
- }
- Device(LNKC){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 3)
- Name(_PRS, ResourceTemplate(){
- IRQ (Level, ActiveLow, Shared)
- {3,4,5,6,7,9,10,11,12}
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ2, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ2, 0x80, PRQ2)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- IRQ (Level, ActiveLow, Shared)
- {1}
- })
- CreateWordField (PRR0, 0x01, TMP)
- Store (PRQ2, Local0)
- If (LLess (Local0, 0x80))
- {
- ShiftLeft (One, Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateWordField (Arg0, 0x01, TMP)
- FindSetRightBit (TMP, Local0)
- Decrement (Local0)
- Store (Local0, PRQ2)
- }
- }
- Device(LNKD){
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 4)
- Name(_PRS, ResourceTemplate(){
- IRQ (Level, ActiveLow, Shared)
- {3,4,5,6,7,9,10,11,12}
- })
- Method (_STA, 0, NotSerialized)
- {
- Store (0x0B, Local0)
- If (And (0x80, PRQ3, Local1))
- {
- Store (0x09, Local0)
- }
- Return (Local0)
- }
- Method (_DIS, 0, NotSerialized)
- {
- Or (PRQ3, 0x80, PRQ3)
- }
- Method (_CRS, 0, NotSerialized)
- {
- Name (PRR0, ResourceTemplate ()
- {
- IRQ (Level, ActiveLow, Shared)
- {1}
- })
- CreateWordField (PRR0, 0x01, TMP)
- Store (PRQ3, Local0)
- If (LLess (Local0, 0x80))
- {
- ShiftLeft (One, Local0, TMP)
- }
- Else
- {
- Store (Zero, TMP)
- }
- Return (PRR0)
- }
- Method (_SRS, 1, NotSerialized)
- {
- CreateWordField (Arg0, 0x01, TMP)
- FindSetRightBit (TMP, Local0)
- Decrement (Local0)
- Store (Local0, PRQ3)
- }
- }
- }
-
- /* S5 = power off state */
- Name (_S5, Package (4) {
- 0x00, // PM1a_CNT.SLP_TYP
- 0x00, // PM2a_CNT.SLP_TYP
- 0x00, // reserved
- 0x00, // reserved
- })
-}
diff --git a/hw/acpi-dsdt.hex b/hw/acpi-dsdt.hex
deleted file mode 100644
index f4f50bd..0000000
--- a/hw/acpi-dsdt.hex
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- *
- * Intel ACPI Component Architecture
- * ASL Optimizing Compiler version 20060421 [Apr 29 2006]
- * Copyright (C) 2000 - 2006 Intel Corporation
- * Supports ACPI Specification Revision 3.0a
- *
- * Compilation of "/usr/local/home/bellard/qemu-current/hw/acpi-dsdt.dsl" - Wed Jun 14 20:09:53 2006
- *
- * C source code output
- *
- */
-unsigned char AmlCode[] =
-{
- 0x44,0x53,0x44,0x54,0x32,0x08,0x00,0x00, /* 00000000 "DSDT2..." */
- 0x01,0x5B,0x51,0x45,0x4D,0x55,0x00,0x00, /* 00000008 ".[QEMU.." */
- 0x51,0x45,0x4D,0x55,0x44,0x53,0x44,0x54, /* 00000010 "QEMUDSDT" */
- 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
- 0x21,0x04,0x06,0x20,0x10,0x4F,0x04,0x5C, /* 00000020 "!.. .O.\" */
- 0x00,0x5B,0x80,0x43,0x4D,0x53,0x5F,0x01, /* 00000028 ".[.CMS_." */
- 0x0A,0x70,0x0A,0x02,0x5B,0x81,0x10,0x43, /* 00000030 ".p..[..C" */
- 0x4D,0x53,0x5F,0x01,0x43,0x4D,0x53,0x49, /* 00000038 "MS_.CMSI" */
- 0x08,0x43,0x4D,0x53,0x44,0x08,0x14,0x14, /* 00000040 ".CMSD..." */
- 0x43,0x4D,0x52,0x44,0x01,0x70,0x68,0x43, /* 00000048 "CMRD.phC" */
- 0x4D,0x53,0x49,0x70,0x43,0x4D,0x53,0x44, /* 00000050 "MSIpCMSD" */
- 0x60,0xA4,0x60,0x5B,0x80,0x44,0x42,0x47, /* 00000058 "`.`[.DBG" */
- 0x5F,0x01,0x0B,0x44,0xB0,0x0A,0x04,0x5B, /* 00000060 "_..D...[" */
- 0x81,0x0B,0x44,0x42,0x47,0x5F,0x03,0x44, /* 00000068 "..DBG_.D" */
- 0x42,0x47,0x4C,0x20,0x10,0x4E,0x25,0x5F, /* 00000070 "BGL .N%_" */
- 0x53,0x42,0x5F,0x5B,0x82,0x46,0x25,0x50, /* 00000078 "SB_[.F%P" */
- 0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44, /* 00000080 "CI0._HID" */
- 0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x41, /* 00000088 ".A...._A" */
- 0x44,0x52,0x00,0x08,0x5F,0x55,0x49,0x44, /* 00000090 "DR.._UID" */
- 0x01,0x08,0x5F,0x50,0x52,0x54,0x12,0x47, /* 00000098 ".._PRT.G" */
- 0x15,0x18,0x12,0x0B,0x04,0x0B,0xFF,0xFF, /* 000000A0 "........" */
- 0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0B, /* 000000A8 ".LNKD..." */
- 0x04,0x0B,0xFF,0xFF,0x01,0x4C,0x4E,0x4B, /* 000000B0 ".....LNK" */
- 0x41,0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF, /* 000000B8 "A......." */
- 0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 000000C0 "..LNKB.." */
- 0x0C,0x04,0x0B,0xFF,0xFF,0x0A,0x03,0x4C, /* 000000C8 ".......L" */
- 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000000D0 "NKC....." */
- 0xFF,0xFF,0x01,0x00,0x00,0x4C,0x4E,0x4B, /* 000000D8 ".....LNK" */
- 0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000000E0 "A......." */
- 0x01,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000000E8 "...LNKB." */
- 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 000000F0 "........" */
- 0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000000F8 "..LNKC.." */
- 0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A, /* 00000100 "........" */
- 0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000108 ".LNKD..." */
- 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00,0x4C, /* 00000110 ".......L" */
- 0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000118 "NKB....." */
- 0xFF,0xFF,0x02,0x00,0x01,0x4C,0x4E,0x4B, /* 00000120 ".....LNK" */
- 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000128 "C......." */
- 0x02,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000130 "....LNKD" */
- 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02, /* 00000138 "........" */
- 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000140 "...LNKA." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000148 "........" */
- 0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000150 ".LNKC..." */
- 0x04,0x0C,0xFF,0xFF,0x03,0x00,0x01,0x4C, /* 00000158 ".......L" */
- 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000160 "NKD....." */
- 0xFF,0xFF,0x03,0x00,0x0A,0x02,0x4C,0x4E, /* 00000168 "......LN" */
- 0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000170 "KA......" */
- 0xFF,0x03,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000178 ".....LNK" */
- 0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000180 "B......." */
- 0x04,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 00000188 "...LNKD." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 00000190 "........" */
- 0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000198 ".LNKA..." */
- 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x02, /* 000001A0 "........" */
- 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000001A8 "LNKB...." */
- 0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x03,0x4C, /* 000001B0 ".......L" */
- 0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000001B8 "NKC....." */
- 0xFF,0xFF,0x05,0x00,0x00,0x4C,0x4E,0x4B, /* 000001C0 ".....LNK" */
- 0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000001C8 "A......." */
- 0x05,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000001D0 "...LNKB." */
- 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 000001D8 "........" */
- 0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000001E0 "..LNKC.." */
- 0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A, /* 000001E8 "........" */
- 0x03,0x4C,0x4E,0x4B,0x44,0x00,0x14,0x4C, /* 000001F0 ".LNKD..L" */
- 0x0D,0x5F,0x43,0x52,0x53,0x00,0x08,0x4D, /* 000001F8 "._CRS..M" */
- 0x45,0x4D,0x50,0x11,0x42,0x07,0x0A,0x6E, /* 00000200 "EMP.B..n" */
- 0x88,0x0D,0x00,0x02,0x0C,0x00,0x00,0x00, /* 00000208 "........" */
- 0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x01, /* 00000210 "........" */
- 0x47,0x01,0xF8,0x0C,0xF8,0x0C,0x01,0x08, /* 00000218 "G......." */
- 0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00, /* 00000220 "........" */
- 0x00,0x00,0xF7,0x0C,0x00,0x00,0xF8,0x0C, /* 00000228 "........" */
- 0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00, /* 00000230 "........" */
- 0x00,0x0D,0xFF,0xFF,0x00,0x00,0x00,0xF3, /* 00000238 "........" */
- 0x87,0x17,0x00,0x00,0x0C,0x03,0x00,0x00, /* 00000240 "........" */
- 0x00,0x00,0x00,0x00,0x0A,0x00,0xFF,0xFF, /* 00000248 "........" */
- 0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000250 "........" */
- 0x02,0x00,0x87,0x17,0x00,0x00,0x08,0x01, /* 00000258 "........" */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000260 "........" */
- 0xFF,0xFF,0xBF,0xFE,0x00,0x00,0x00,0x00, /* 00000268 "........" */
- 0x00,0x00,0x00,0x00,0x79,0x00,0x8A,0x4D, /* 00000270 "....y..M" */
- 0x45,0x4D,0x50,0x0A,0x5C,0x50,0x4D,0x49, /* 00000278 "EMP.\PMI" */
- 0x4E,0x8A,0x4D,0x45,0x4D,0x50,0x0A,0x60, /* 00000280 "N.MEMP.`" */
- 0x50,0x4D,0x41,0x58,0x8A,0x4D,0x45,0x4D, /* 00000288 "PMAX.MEM" */
- 0x50,0x0A,0x68,0x50,0x4C,0x45,0x4E,0x72, /* 00000290 "P.hPLENr" */
- 0x43,0x4D,0x52,0x44,0x0A,0x34,0x79,0x43, /* 00000298 "CMRD.4yC" */
- 0x4D,0x52,0x44,0x0A,0x35,0x0A,0x08,0x00, /* 000002A0 "MRD.5..." */
- 0x60,0x79,0x60,0x0A,0x10,0x60,0x72,0x60, /* 000002A8 "`y`..`r`" */
- 0x0C,0x00,0x00,0x00,0x01,0x60,0x70,0x60, /* 000002B0 ".....`p`" */
- 0x50,0x4D,0x49,0x4E,0x74,0x50,0x4D,0x41, /* 000002B8 "PMINtPMA" */
- 0x58,0x50,0x4D,0x49,0x4E,0x50,0x4C,0x45, /* 000002C0 "XPMINPLE" */
- 0x4E,0x75,0x50,0x4C,0x45,0x4E,0xA4,0x4D, /* 000002C8 "NuPLEN.M" */
- 0x45,0x4D,0x50,0x10,0x42,0x26,0x2E,0x5F, /* 000002D0 "EMP.B&._" */
- 0x53,0x42,0x5F,0x50,0x43,0x49,0x30,0x5B, /* 000002D8 "SB_PCI0[" */
- 0x82,0x43,0x20,0x49,0x53,0x41,0x5F,0x08, /* 000002E0 ".C ISA_." */
- 0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,0x01, /* 000002E8 "_ADR...." */
- 0x00,0x5B,0x80,0x50,0x34,0x30,0x43,0x02, /* 000002F0 ".[.P40C." */
- 0x0A,0x60,0x0A,0x04,0x5B,0x82,0x44,0x04, /* 000002F8 ".`..[.D." */
- 0x4B,0x42,0x44,0x5F,0x08,0x5F,0x48,0x49, /* 00000300 "KBD_._HI" */
- 0x44,0x0C,0x41,0xD0,0x03,0x03,0x14,0x09, /* 00000308 "D.A....." */
- 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000310 "_STA...." */
- 0x14,0x29,0x5F,0x43,0x52,0x53,0x00,0x08, /* 00000318 ".)_CRS.." */
- 0x54,0x4D,0x50,0x5F,0x11,0x18,0x0A,0x15, /* 00000320 "TMP_...." */
- 0x47,0x01,0x60,0x00,0x60,0x00,0x01,0x01, /* 00000328 "G.`.`..." */
- 0x47,0x01,0x64,0x00,0x64,0x00,0x01,0x01, /* 00000330 "G.d.d..." */
- 0x22,0x02,0x00,0x79,0x00,0xA4,0x54,0x4D, /* 00000338 ""..y..TM" */
- 0x50,0x5F,0x5B,0x82,0x33,0x4D,0x4F,0x55, /* 00000340 "P_[.3MOU" */
- 0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000348 "_._HID.A" */
- 0xD0,0x0F,0x13,0x14,0x09,0x5F,0x53,0x54, /* 00000350 "....._ST" */
- 0x41,0x00,0xA4,0x0A,0x0F,0x14,0x19,0x5F, /* 00000358 "A......_" */
- 0x43,0x52,0x53,0x00,0x08,0x54,0x4D,0x50, /* 00000360 "CRS..TMP" */
- 0x5F,0x11,0x08,0x0A,0x05,0x22,0x00,0x10, /* 00000368 "_....".." */
- 0x79,0x00,0xA4,0x54,0x4D,0x50,0x5F,0x5B, /* 00000370 "y..TMP_[" */
- 0x82,0x47,0x04,0x46,0x44,0x43,0x30,0x08, /* 00000378 ".G.FDC0." */
- 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x07, /* 00000380 "_HID.A.." */
- 0x00,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000388 "..._STA." */
- 0xA4,0x0A,0x0F,0x14,0x2C,0x5F,0x43,0x52, /* 00000390 "....,_CR" */
- 0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11, /* 00000398 "S..BUF0." */
- 0x1B,0x0A,0x18,0x47,0x01,0xF2,0x03,0xF2, /* 000003A0 "...G...." */
- 0x03,0x00,0x04,0x47,0x01,0xF7,0x03,0xF7, /* 000003A8 "...G...." */
- 0x03,0x00,0x01,0x22,0x40,0x00,0x2A,0x04, /* 000003B0 "..."@.*." */
- 0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30, /* 000003B8 ".y..BUF0" */
- 0x5B,0x82,0x4B,0x05,0x4C,0x50,0x54,0x5F, /* 000003C0 "[.K.LPT_" */
- 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000003C8 "._HID.A." */
- 0x04,0x00,0x14,0x28,0x5F,0x53,0x54,0x41, /* 000003D0 "...(_STA" */
- 0x00,0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58, /* 000003D8 ".p^^^.PX" */
- 0x31,0x33,0x44,0x52,0x53,0x41,0x60,0x7B, /* 000003E0 "13DRSA`{" */
- 0x60,0x0C,0x00,0x00,0x00,0x80,0x60,0xA0, /* 000003E8 "`.....`." */
- 0x06,0x93,0x60,0x00,0xA4,0x00,0xA1,0x04, /* 000003F0 "..`....." */
- 0xA4,0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52, /* 000003F8 "....!_CR" */
- 0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11, /* 00000400 "S..BUF0." */
- 0x10,0x0A,0x0D,0x47,0x01,0x78,0x03,0x78, /* 00000408 "...G.x.x" */
- 0x03,0x08,0x08,0x22,0x80,0x00,0x79,0x00, /* 00000410 "..."..y." */
- 0xA4,0x42,0x55,0x46,0x30,0x5B,0x82,0x41, /* 00000418 ".BUF0[.A" */
- 0x06,0x43,0x4F,0x4D,0x31,0x08,0x5F,0x48, /* 00000420 ".COM1._H" */
- 0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 00000428 "ID.A...." */
- 0x5F,0x55,0x49,0x44,0x01,0x14,0x28,0x5F, /* 00000430 "_UID..(_" */
- 0x53,0x54,0x41,0x00,0x70,0x5E,0x5E,0x5E, /* 00000438 "STA.p^^^" */
- 0x2E,0x50,0x58,0x31,0x33,0x44,0x52,0x53, /* 00000440 ".PX13DRS" */
- 0x43,0x60,0x7B,0x60,0x0C,0x00,0x00,0x00, /* 00000448 "C`{`...." */
- 0x08,0x60,0xA0,0x06,0x93,0x60,0x00,0xA4, /* 00000450 ".`...`.." */
- 0x00,0xA1,0x04,0xA4,0x0A,0x0F,0x14,0x21, /* 00000458 ".......!" */
- 0x5F,0x43,0x52,0x53,0x00,0x08,0x42,0x55, /* 00000460 "_CRS..BU" */
- 0x46,0x30,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 00000468 "F0....G." */
- 0xF8,0x03,0xF8,0x03,0x00,0x08,0x22,0x10, /* 00000470 "......"." */
- 0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30, /* 00000478 ".y..BUF0" */
- 0x5B,0x82,0x42,0x06,0x43,0x4F,0x4D,0x32, /* 00000480 "[.B.COM2" */
- 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000488 "._HID.A." */
- 0x05,0x01,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 00000490 "..._UID." */
- 0x02,0x14,0x28,0x5F,0x53,0x54,0x41,0x00, /* 00000498 "..(_STA." */
- 0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58,0x31, /* 000004A0 "p^^^.PX1" */
- 0x33,0x44,0x52,0x53,0x43,0x60,0x7B,0x60, /* 000004A8 "3DRSC`{`" */
- 0x0C,0x00,0x00,0x00,0x80,0x60,0xA0,0x06, /* 000004B0 ".....`.." */
- 0x93,0x60,0x00,0xA4,0x00,0xA1,0x04,0xA4, /* 000004B8 ".`......" */
- 0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52,0x53, /* 000004C0 "...!_CRS" */
- 0x00,0x08,0x42,0x55,0x46,0x30,0x11,0x10, /* 000004C8 "..BUF0.." */
- 0x0A,0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02, /* 000004D0 "..G....." */
- 0x00,0x08,0x22,0x08,0x00,0x79,0x00,0xA4, /* 000004D8 ".."..y.." */
- 0x42,0x55,0x46,0x30,0x5B,0x82,0x40,0x05, /* 000004E0 "BUF0[.@." */
- 0x50,0x58,0x31,0x33,0x08,0x5F,0x41,0x44, /* 000004E8 "PX13._AD" */
- 0x52,0x0C,0x03,0x00,0x01,0x00,0x5B,0x80, /* 000004F0 "R.....[." */
- 0x50,0x31,0x33,0x43,0x02,0x0A,0x5C,0x0A, /* 000004F8 "P13C..\." */
- 0x24,0x5B,0x81,0x33,0x50,0x31,0x33,0x43, /* 00000500 "$[.3P13C" */
- 0x03,0x44,0x52,0x53,0x41,0x20,0x44,0x52, /* 00000508 ".DRSA DR" */
- 0x53,0x42,0x20,0x44,0x52,0x53,0x43,0x20, /* 00000510 "SB DRSC " */
- 0x44,0x52,0x53,0x45,0x20,0x44,0x52,0x53, /* 00000518 "DRSE DRS" */
- 0x46,0x20,0x44,0x52,0x53,0x47,0x20,0x44, /* 00000520 "F DRSG D" */
- 0x52,0x53,0x48,0x20,0x44,0x52,0x53,0x49, /* 00000528 "RSH DRSI" */
- 0x20,0x44,0x52,0x53,0x4A,0x20,0x10,0x4F, /* 00000530 " DRSJ .O" */
- 0x2E,0x5F,0x53,0x42,0x5F,0x5B,0x81,0x24, /* 00000538 "._SB_[.$" */
- 0x2F,0x03,0x50,0x43,0x49,0x30,0x49,0x53, /* 00000540 "/.PCI0IS" */
- 0x41,0x5F,0x50,0x34,0x30,0x43,0x01,0x50, /* 00000548 "A_P40C.P" */
- 0x52,0x51,0x30,0x08,0x50,0x52,0x51,0x31, /* 00000550 "RQ0.PRQ1" */
- 0x08,0x50,0x52,0x51,0x32,0x08,0x50,0x52, /* 00000558 ".PRQ2.PR" */
- 0x51,0x33,0x08,0x5B,0x82,0x4E,0x0A,0x4C, /* 00000560 "Q3.[.N.L" */
- 0x4E,0x4B,0x41,0x08,0x5F,0x48,0x49,0x44, /* 00000568 "NKA._HID" */
- 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000570 ".A...._U" */
- 0x49,0x44,0x01,0x08,0x5F,0x50,0x52,0x53, /* 00000578 "ID.._PRS" */
- 0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E,0x18, /* 00000580 "....#..." */
- 0x79,0x00,0x14,0x1A,0x5F,0x53,0x54,0x41, /* 00000588 "y..._STA" */
- 0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D,0x7B, /* 00000590 ".p..`..{" */
- 0x0A,0x80,0x50,0x52,0x51,0x30,0x61,0x70, /* 00000598 "..PRQ0ap" */
- 0x0A,0x09,0x60,0xA4,0x60,0x14,0x11,0x5F, /* 000005A0 "..`.`.._" */
- 0x44,0x49,0x53,0x00,0x7D,0x50,0x52,0x51, /* 000005A8 "DIS.}PRQ" */
- 0x30,0x0A,0x80,0x50,0x52,0x51,0x30,0x14, /* 000005B0 "0..PRQ0." */
- 0x3F,0x5F,0x43,0x52,0x53,0x00,0x08,0x50, /* 000005B8 "?_CRS..P" */
- 0x52,0x52,0x30,0x11,0x09,0x0A,0x06,0x23, /* 000005C0 "RR0....#" */
- 0x02,0x00,0x18,0x79,0x00,0x8B,0x50,0x52, /* 000005C8 "...y..PR" */
- 0x52,0x30,0x01,0x54,0x4D,0x50,0x5F,0x70, /* 000005D0 "R0.TMP_p" */
- 0x50,0x52,0x51,0x30,0x60,0xA0,0x0C,0x95, /* 000005D8 "PRQ0`..." */
- 0x60,0x0A,0x80,0x79,0x01,0x60,0x54,0x4D, /* 000005E0 "`..y.`TM" */
- 0x50,0x5F,0xA1,0x07,0x70,0x00,0x54,0x4D, /* 000005E8 "P_..p.TM" */
- 0x50,0x5F,0xA4,0x50,0x52,0x52,0x30,0x14, /* 000005F0 "P_.PRR0." */
- 0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 000005F8 "._SRS..h" */
- 0x01,0x54,0x4D,0x50,0x5F,0x82,0x54,0x4D, /* 00000600 ".TMP_.TM" */
- 0x50,0x5F,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000608 "P_`v`p`P" */
- 0x52,0x51,0x30,0x5B,0x82,0x4F,0x0A,0x4C, /* 00000610 "RQ0[.O.L" */
- 0x4E,0x4B,0x42,0x08,0x5F,0x48,0x49,0x44, /* 00000618 "NKB._HID" */
- 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000620 ".A...._U" */
- 0x49,0x44,0x0A,0x02,0x08,0x5F,0x50,0x52, /* 00000628 "ID..._PR" */
- 0x53,0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E, /* 00000630 "S....#.." */
- 0x18,0x79,0x00,0x14,0x1A,0x5F,0x53,0x54, /* 00000638 ".y..._ST" */
- 0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D, /* 00000640 "A.p..`.." */
- 0x7B,0x0A,0x80,0x50,0x52,0x51,0x31,0x61, /* 00000648 "{..PRQ1a" */
- 0x70,0x0A,0x09,0x60,0xA4,0x60,0x14,0x11, /* 00000650 "p..`.`.." */
- 0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,0x52, /* 00000658 "_DIS.}PR" */
- 0x51,0x31,0x0A,0x80,0x50,0x52,0x51,0x31, /* 00000660 "Q1..PRQ1" */
- 0x14,0x3F,0x5F,0x43,0x52,0x53,0x00,0x08, /* 00000668 ".?_CRS.." */
- 0x50,0x52,0x52,0x30,0x11,0x09,0x0A,0x06, /* 00000670 "PRR0...." */
- 0x23,0x02,0x00,0x18,0x79,0x00,0x8B,0x50, /* 00000678 "#...y..P" */
- 0x52,0x52,0x30,0x01,0x54,0x4D,0x50,0x5F, /* 00000680 "RR0.TMP_" */
- 0x70,0x50,0x52,0x51,0x31,0x60,0xA0,0x0C, /* 00000688 "pPRQ1`.." */
- 0x95,0x60,0x0A,0x80,0x79,0x01,0x60,0x54, /* 00000690 ".`..y.`T" */
- 0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00,0x54, /* 00000698 "MP_..p.T" */
- 0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52,0x30, /* 000006A0 "MP_.PRR0" */
- 0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B, /* 000006A8 ".._SRS.." */
- 0x68,0x01,0x54,0x4D,0x50,0x5F,0x82,0x54, /* 000006B0 "h.TMP_.T" */
- 0x4D,0x50,0x5F,0x60,0x76,0x60,0x70,0x60, /* 000006B8 "MP_`v`p`" */
- 0x50,0x52,0x51,0x31,0x5B,0x82,0x4F,0x0A, /* 000006C0 "PRQ1[.O." */
- 0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48,0x49, /* 000006C8 "LNKC._HI" */
- 0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F, /* 000006D0 "D.A...._" */
- 0x55,0x49,0x44,0x0A,0x03,0x08,0x5F,0x50, /* 000006D8 "UID..._P" */
- 0x52,0x53,0x11,0x09,0x0A,0x06,0x23,0xF8, /* 000006E0 "RS....#." */
- 0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F,0x53, /* 000006E8 "..y..._S" */
- 0x54,0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0, /* 000006F0 "TA.p..`." */
- 0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51,0x32, /* 000006F8 ".{..PRQ2" */
- 0x61,0x70,0x0A,0x09,0x60,0xA4,0x60,0x14, /* 00000700 "ap..`.`." */
- 0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000708 "._DIS.}P" */
- 0x52,0x51,0x32,0x0A,0x80,0x50,0x52,0x51, /* 00000710 "RQ2..PRQ" */
- 0x32,0x14,0x3F,0x5F,0x43,0x52,0x53,0x00, /* 00000718 "2.?_CRS." */
- 0x08,0x50,0x52,0x52,0x30,0x11,0x09,0x0A, /* 00000720 ".PRR0..." */
- 0x06,0x23,0x02,0x00,0x18,0x79,0x00,0x8B, /* 00000728 ".#...y.." */
- 0x50,0x52,0x52,0x30,0x01,0x54,0x4D,0x50, /* 00000730 "PRR0.TMP" */
- 0x5F,0x70,0x50,0x52,0x51,0x32,0x60,0xA0, /* 00000738 "_pPRQ2`." */
- 0x0C,0x95,0x60,0x0A,0x80,0x79,0x01,0x60, /* 00000740 "..`..y.`" */
- 0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00, /* 00000748 "TMP_..p." */
- 0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52, /* 00000750 "TMP_.PRR" */
- 0x30,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000758 "0.._SRS." */
- 0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F,0x82, /* 00000760 ".h.TMP_." */
- 0x54,0x4D,0x50,0x5F,0x60,0x76,0x60,0x70, /* 00000768 "TMP_`v`p" */
- 0x60,0x50,0x52,0x51,0x32,0x5B,0x82,0x4F, /* 00000770 "`PRQ2[.O" */
- 0x0A,0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48, /* 00000778 ".LNKD._H" */
- 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 00000780 "ID.A...." */
- 0x5F,0x55,0x49,0x44,0x0A,0x04,0x08,0x5F, /* 00000788 "_UID..._" */
- 0x50,0x52,0x53,0x11,0x09,0x0A,0x06,0x23, /* 00000790 "PRS....#" */
- 0xF8,0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F, /* 00000798 "...y..._" */
- 0x53,0x54,0x41,0x00,0x70,0x0A,0x0B,0x60, /* 000007A0 "STA.p..`" */
- 0xA0,0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51, /* 000007A8 "..{..PRQ" */
- 0x33,0x61,0x70,0x0A,0x09,0x60,0xA4,0x60, /* 000007B0 "3ap..`.`" */
- 0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 000007B8 ".._DIS.}" */
- 0x50,0x52,0x51,0x33,0x0A,0x80,0x50,0x52, /* 000007C0 "PRQ3..PR" */
- 0x51,0x33,0x14,0x3F,0x5F,0x43,0x52,0x53, /* 000007C8 "Q3.?_CRS" */
- 0x00,0x08,0x50,0x52,0x52,0x30,0x11,0x09, /* 000007D0 "..PRR0.." */
- 0x0A,0x06,0x23,0x02,0x00,0x18,0x79,0x00, /* 000007D8 "..#...y." */
- 0x8B,0x50,0x52,0x52,0x30,0x01,0x54,0x4D, /* 000007E0 ".PRR0.TM" */
- 0x50,0x5F,0x70,0x50,0x52,0x51,0x33,0x60, /* 000007E8 "P_pPRQ3`" */
- 0xA0,0x0C,0x95,0x60,0x0A,0x80,0x79,0x01, /* 000007F0 "...`..y." */
- 0x60,0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70, /* 000007F8 "`TMP_..p" */
- 0x00,0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52, /* 00000800 ".TMP_.PR" */
- 0x52,0x30,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 00000808 "R0.._SRS" */
- 0x01,0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F, /* 00000810 "..h.TMP_" */
- 0x82,0x54,0x4D,0x50,0x5F,0x60,0x76,0x60, /* 00000818 ".TMP_`v`" */
- 0x70,0x60,0x50,0x52,0x51,0x33,0x08,0x5F, /* 00000820 "p`PRQ3._" */
- 0x53,0x35,0x5F,0x12,0x06,0x04,0x00,0x00, /* 00000828 "S5_....." */
- 0x00,0x00,
-};
diff --git a/hw/acpi.c b/hw/acpi.c
deleted file mode 100644
index 6c20a4e..0000000
--- a/hw/acpi.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * ACPI implementation
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "vl.h"
-
-//#define DEBUG
-
-/* i82731AB (PIIX4) compatible power management function */
-#define PM_FREQ 3579545
-
-/* XXX: make them variable */
-#define PM_IO_BASE 0xb000
-#define SMI_CMD_IO_ADDR 0xb040
-#define ACPI_DBG_IO_ADDR 0xb044
-
-typedef struct PIIX4PMState {
- PCIDevice dev;
- uint16_t pmsts;
- uint16_t pmen;
- uint16_t pmcntrl;
- QEMUTimer *tmr_timer;
- int64_t tmr_overflow_time;
-} PIIX4PMState;
-
-#define RTC_EN (1 << 10)
-#define PWRBTN_EN (1 << 8)
-#define GBL_EN (1 << 5)
-#define TMROF_EN (1 << 0)
-
-#define SCI_EN (1 << 0)
-
-#define SUS_EN (1 << 13)
-
-/* Note: only used for ACPI bios init. Could be deleted when ACPI init
- is integrated in Bochs BIOS */
-static PIIX4PMState *piix4_pm_state;
-
-static uint32_t get_pmtmr(PIIX4PMState *s)
-{
- uint32_t d;
- d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
- return d & 0xffffff;
-}
-
-static int get_pmsts(PIIX4PMState *s)
-{
- int64_t d;
- int pmsts;
- pmsts = s->pmsts;
- d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
- if (d >= s->tmr_overflow_time)
- s->pmsts |= TMROF_EN;
- return pmsts;
-}
-
-static void pm_update_sci(PIIX4PMState *s)
-{
- int sci_level, pmsts;
- int64_t expire_time;
-
- pmsts = get_pmsts(s);
- sci_level = (((pmsts & s->pmen) &
- (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
- pci_set_irq(&s->dev, 0, sci_level);
- /* schedule a timer interruption if needed */
- if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
- expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
- qemu_mod_timer(s->tmr_timer, expire_time);
- } else {
- qemu_del_timer(s->tmr_timer);
- }
-}
-
-static void pm_tmr_timer(void *opaque)
-{
- PIIX4PMState *s = opaque;
- pm_update_sci(s);
-}
-
-static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- PIIX4PMState *s = opaque;
- addr &= 0x3f;
- switch(addr) {
- case 0x00:
- {
- int64_t d;
- int pmsts;
- pmsts = get_pmsts(s);
- if (pmsts & val & TMROF_EN) {
- /* if TMRSTS is reset, then compute the new overflow time */
- d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
- s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
- }
- s->pmsts &= ~val;
- pm_update_sci(s);
- }
- break;
- case 0x02:
- s->pmen = val;
- pm_update_sci(s);
- break;
- case 0x04:
- {
- int sus_typ;
- s->pmcntrl = val & ~(SUS_EN);
- if (val & SUS_EN) {
- /* change suspend type */
- sus_typ = (val >> 10) & 3;
- switch(sus_typ) {
- case 0: /* soft power off */
- qemu_system_shutdown_request();
- break;
- default:
- break;
- }
- }
- }
- break;
- default:
- break;
- }
-#ifdef DEBUG
- printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x3f;
- switch(addr) {
- case 0x00:
- val = get_pmsts(s);
- break;
- case 0x02:
- val = s->pmen;
- break;
- case 0x04:
- val = s->pmcntrl;
- break;
- default:
- val = 0;
- break;
- }
-#ifdef DEBUG
- printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
-#endif
- return val;
-}
-
-static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- // PIIX4PMState *s = opaque;
- addr &= 0x3f;
-#ifdef DEBUG
- printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
-#endif
-}
-
-static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
-{
- PIIX4PMState *s = opaque;
- uint32_t val;
-
- addr &= 0x3f;
- switch(addr) {
- case 0x08:
- val = get_pmtmr(s);
- break;
- default:
- val = 0;
- break;
- }
-#ifdef DEBUG
- printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
-#endif
- return val;
-}
-
-static void smi_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- PIIX4PMState *s = opaque;
-#ifdef DEBUG
- printf("SMI cmd val=0x%02x\n", val);
-#endif
- switch(val) {
- case 0xf0: /* ACPI disable */
- s->pmcntrl &= ~SCI_EN;
- break;
- case 0xf1: /* ACPI enable */
- s->pmcntrl |= SCI_EN;
- break;
- }
-}
-
-static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
-{
-#if defined(DEBUG)
- printf("ACPI: DBG: 0x%08x\n", val);
-#endif
-}
-
-/* XXX: we still add it to the PIIX3 and we count on the fact that
- OSes are smart enough to accept this strange configuration */
-void piix4_pm_init(PCIBus *bus, int devfn)
-{
- PIIX4PMState *s;
- uint8_t *pci_conf;
- uint32_t pm_io_base;
-
- s = (PIIX4PMState *)pci_register_device(bus,
- "PM", sizeof(PIIX4PMState),
- devfn, NULL, NULL);
- pci_conf = s->dev.config;
- pci_conf[0x00] = 0x86;
- pci_conf[0x01] = 0x80;
- pci_conf[0x02] = 0x13;
- pci_conf[0x03] = 0x71;
- pci_conf[0x08] = 0x00; // revision number
- pci_conf[0x09] = 0x00;
- pci_conf[0x0a] = 0x80; // other bridge device
- pci_conf[0x0b] = 0x06; // bridge device
- pci_conf[0x0e] = 0x00; // header_type
- pci_conf[0x3d] = 0x01; // interrupt pin 1
-
- pm_io_base = PM_IO_BASE;
- pci_conf[0x40] = pm_io_base | 1;
- pci_conf[0x41] = pm_io_base >> 8;
- register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
- register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
- register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
- register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
-
- register_ioport_write(SMI_CMD_IO_ADDR, 1, 1, smi_cmd_writeb, s);
- register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
-
- /* XXX: which specification is used ? The i82731AB has different
- mappings */
- pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
- pci_conf[0x63] = 0x60;
- pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
- (serial_hds[1] != NULL ? 0x90 : 0);
-
- s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
- piix4_pm_state = s;
-}
-
-/* ACPI tables */
-/* XXX: move them in the Bochs BIOS ? */
-
-/*************************************************/
-
-/* Table structure from Linux kernel (the ACPI tables are under the
- BSD license) */
-
-#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
- uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
- uint32_t length; /* Length of table, in bytes, including header */\
- uint8_t revision; /* ACPI Specification minor version # */\
- uint8_t checksum; /* To make sum of entire table == 0 */\
- uint8_t oem_id [6]; /* OEM identification */\
- uint8_t oem_table_id [8]; /* OEM table identification */\
- uint32_t oem_revision; /* OEM revision number */\
- uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
- uint32_t asl_compiler_revision; /* ASL compiler revision number */
-
-
-struct acpi_table_header /* ACPI common table header */
-{
- ACPI_TABLE_HEADER_DEF
-};
-
-struct rsdp_descriptor /* Root System Descriptor Pointer */
-{
- uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */
- uint8_t checksum; /* To make sum of struct == 0 */
- uint8_t oem_id [6]; /* OEM identification */
- uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
- uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
- uint32_t length; /* XSDT Length in bytes including hdr */
- uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
- uint8_t extended_checksum; /* Checksum of entire table */
- uint8_t reserved [3]; /* Reserved field must be 0 */
-};
-
-/*
- * ACPI 1.0 Root System Description Table (RSDT)
- */
-struct rsdt_descriptor_rev1
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t table_offset_entry [2]; /* Array of pointers to other */
- /* ACPI tables */
-};
-
-/*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
- */
-struct facs_descriptor_rev1
-{
- uint8_t signature[4]; /* ACPI Signature */
- uint32_t length; /* Length of structure, in bytes */
- uint32_t hardware_signature; /* Hardware configuration signature */
- uint32_t firmware_waking_vector; /* ACPI OS waking vector */
- uint32_t global_lock; /* Global Lock */
- uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */
- uint32_t reserved1 : 31; /* Must be 0 */
- uint8_t resverved3 [40]; /* Reserved - must be zero */
-};
-
-
-/*
- * ACPI 1.0 Fixed ACPI Description Table (FADT)
- */
-struct fadt_descriptor_rev1
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t firmware_ctrl; /* Physical address of FACS */
- uint32_t dsdt; /* Physical address of DSDT */
- uint8_t model; /* System Interrupt Model */
- uint8_t reserved1; /* Reserved */
- uint16_t sci_int; /* System vector of SCI interrupt */
- uint32_t smi_cmd; /* Port address of SMI command port */
- uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
- uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
- uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
- uint8_t reserved2; /* Reserved - must be zero */
- uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
- uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
- uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
- uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
- uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
- uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
- uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
- uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
- uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
- uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
- uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
- uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
- uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
- uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
- uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
- uint8_t reserved3; /* Reserved */
- uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
- uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
- uint16_t flush_size; /* Size of area read to flush caches */
- uint16_t flush_stride; /* Stride used in flushing caches */
- uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
- uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
- uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
- uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
- uint8_t century; /* Index to century in RTC CMOS RAM */
- uint8_t reserved4; /* Reserved */
- uint8_t reserved4a; /* Reserved */
- uint8_t reserved4b; /* Reserved */
-#if 0
- uint32_t wb_invd : 1; /* The wbinvd instruction works properly */
- uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
- uint32_t proc_c1 : 1; /* All processors support C1 state */
- uint32_t plvl2_up : 1; /* C2 state works on MP system */
- uint32_t pwr_button : 1; /* Power button is handled as a generic feature */
- uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
- uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
- uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
- uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
- uint32_t reserved5 : 23; /* Reserved - must be zero */
-#else
- uint32_t flags;
-#endif
-};
-
-/*
- * MADT values and structures
- */
-
-/* Values for MADT PCATCompat */
-
-#define DUAL_PIC 0
-#define MULTIPLE_APIC 1
-
-
-/* Master MADT */
-
-struct multiple_apic_table
-{
- ACPI_TABLE_HEADER_DEF /* ACPI common table header */
- uint32_t local_apic_address; /* Physical address of local APIC */
-#if 0
- uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */
- uint32_t reserved1 : 31;
-#else
- uint32_t flags;
-#endif
-};
-
-
-/* Values for Type in APIC_HEADER_DEF */
-
-#define APIC_PROCESSOR 0
-#define APIC_IO 1
-#define APIC_XRUPT_OVERRIDE 2
-#define APIC_NMI 3
-#define APIC_LOCAL_NMI 4
-#define APIC_ADDRESS_OVERRIDE 5
-#define APIC_IO_SAPIC 6
-#define APIC_LOCAL_SAPIC 7
-#define APIC_XRUPT_SOURCE 8
-#define APIC_RESERVED 9 /* 9 and greater are reserved */
-
-/*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
- */
-#define APIC_HEADER_DEF /* Common APIC sub-structure header */\
- uint8_t type; \
- uint8_t length;
-
-/* Sub-structures for MADT */
-
-struct madt_processor_apic
-{
- APIC_HEADER_DEF
- uint8_t processor_id; /* ACPI processor id */
- uint8_t local_apic_id; /* Processor's local APIC id */
-#if 0
- uint32_t processor_enabled: 1; /* Processor is usable if set */
- uint32_t reserved2 : 31; /* Reserved, must be zero */
-#else
- uint32_t flags;
-#endif
-};
-
-struct madt_io_apic
-{
- APIC_HEADER_DEF
- uint8_t io_apic_id; /* I/O APIC ID */
- uint8_t reserved; /* Reserved - must be zero */
- uint32_t address; /* APIC physical address */
- uint32_t interrupt; /* Global system interrupt where INTI
- * lines start */
-};
-
-#include "acpi-dsdt.hex"
-
-static int acpi_checksum(const uint8_t *data, int len)
-{
- int sum, i;
- sum = 0;
- for(i = 0; i < len; i++)
- sum += data[i];
- return (-sum) & 0xff;
-}
-
-static void acpi_build_table_header(struct acpi_table_header *h,
- char *sig, int len)
-{
- memcpy(h->signature, sig, 4);
- h->length = cpu_to_le32(len);
- h->revision = 0;
- memcpy(h->oem_id, "QEMU ", 6);
- memcpy(h->oem_table_id, "QEMU", 4);
- memcpy(h->oem_table_id + 4, sig, 4);
- h->oem_revision = cpu_to_le32(1);
- memcpy(h->asl_compiler_id, "QEMU", 4);
- h->asl_compiler_revision = cpu_to_le32(1);
- h->checksum = acpi_checksum((void *)h, len);
-}
-
-#define ACPI_TABLES_BASE 0x000e8000
-
-/* base_addr must be a multiple of 4KB */
-void acpi_bios_init(void)
-{
- struct rsdp_descriptor *rsdp;
- struct rsdt_descriptor_rev1 *rsdt;
- struct fadt_descriptor_rev1 *fadt;
- struct facs_descriptor_rev1 *facs;
- struct multiple_apic_table *madt;
- uint8_t *dsdt;
- uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr;
- uint32_t pm_io_base, acpi_tables_size, madt_addr, madt_size;
- int i;
-
- /* compute PCI I/O addresses */
- pm_io_base = (piix4_pm_state->dev.config[0x40] |
- (piix4_pm_state->dev.config[0x41] << 8)) & ~0x3f;
-
- base_addr = ACPI_TABLES_BASE;
-
- /* reserve memory space for tables */
- addr = base_addr;
- rsdp = (void *)(phys_ram_base + addr);
- addr += sizeof(*rsdp);
-
- rsdt_addr = addr;
- rsdt = (void *)(phys_ram_base + addr);
- addr += sizeof(*rsdt);
-
- fadt_addr = addr;
- fadt = (void *)(phys_ram_base + addr);
- addr += sizeof(*fadt);
-
- /* XXX: FACS should be in RAM */
- addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
- facs_addr = addr;
- facs = (void *)(phys_ram_base + addr);
- addr += sizeof(*facs);
-
- dsdt_addr = addr;
- dsdt = (void *)(phys_ram_base + addr);
- addr += sizeof(AmlCode);
-
- addr = (addr + 7) & ~7;
- madt_addr = addr;
- madt_size = sizeof(*madt) +
- sizeof(struct madt_processor_apic) * smp_cpus +
- sizeof(struct madt_io_apic);
- madt = (void *)(phys_ram_base + addr);
- addr += madt_size;
-
- acpi_tables_size = addr - base_addr;
-
- cpu_register_physical_memory(base_addr, acpi_tables_size,
- base_addr | IO_MEM_ROM);
-
- /* RSDP */
- memset(rsdp, 0, sizeof(*rsdp));
- memcpy(rsdp->signature, "RSD PTR ", 8);
- memcpy(rsdp->oem_id, "QEMU ", 6);
- rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
- rsdp->checksum = acpi_checksum((void *)rsdp, 20);
-
- /* RSDT */
- rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
- rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
- acpi_build_table_header((struct acpi_table_header *)rsdt,
- "RSDT", sizeof(*rsdt));
-
- /* FADT */
- memset(fadt, 0, sizeof(*fadt));
- fadt->firmware_ctrl = cpu_to_le32(facs_addr);
- fadt->dsdt = cpu_to_le32(dsdt_addr);
- fadt->model = 1;
- fadt->reserved1 = 0;
- fadt->sci_int = cpu_to_le16(piix4_pm_state->dev.config[0x3c]);
- fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
- fadt->acpi_enable = 0xf1;
- fadt->acpi_disable = 0xf0;
- fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
- fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
- fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
- fadt->pm1_evt_len = 4;
- fadt->pm1_cnt_len = 2;
- fadt->pm_tmr_len = 4;
- fadt->plvl2_lat = cpu_to_le16(50);
- fadt->plvl3_lat = cpu_to_le16(50);
- fadt->plvl3_lat = cpu_to_le16(50);
- /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
- fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
- acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
- sizeof(*fadt));
-
- /* FACS */
- memset(facs, 0, sizeof(*facs));
- memcpy(facs->signature, "FACS", 4);
- facs->length = cpu_to_le32(sizeof(*facs));
-
- /* DSDT */
- memcpy(dsdt, AmlCode, sizeof(AmlCode));
-
- /* MADT */
- {
- struct madt_processor_apic *apic;
- struct madt_io_apic *io_apic;
-
- memset(madt, 0, madt_size);
- madt->local_apic_address = cpu_to_le32(0xfee00000);
- madt->flags = cpu_to_le32(1);
- apic = (void *)(madt + 1);
- for(i=0;i<smp_cpus;i++) {
- apic->type = APIC_PROCESSOR;
- apic->length = sizeof(*apic);
- apic->processor_id = i;
- apic->local_apic_id = i;
- apic->flags = cpu_to_le32(1);
- apic++;
- }
- io_apic = (void *)apic;
- io_apic->type = APIC_IO;
- io_apic->length = sizeof(*io_apic);
- io_apic->io_apic_id = smp_cpus;
- io_apic->address = cpu_to_le32(0xfec00000);
- io_apic->interrupt = cpu_to_le32(0);
-
- acpi_build_table_header((struct acpi_table_header *)madt,
- "APIC", madt_size);
- }
-}
diff --git a/hw/adb.c b/hw/adb.c
deleted file mode 100644
index 8e08cb1..0000000
--- a/hw/adb.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * QEMU ADB support
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* ADB commands */
-#define ADB_BUSRESET 0x00
-#define ADB_FLUSH 0x01
-#define ADB_WRITEREG 0x08
-#define ADB_READREG 0x0c
-
-/* ADB device commands */
-#define ADB_CMD_SELF_TEST 0xff
-#define ADB_CMD_CHANGE_ID 0xfe
-#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
-#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
-
-/* ADB default device IDs (upper 4 bits of ADB command byte) */
-#define ADB_DONGLE 1
-#define ADB_KEYBOARD 2
-#define ADB_MOUSE 3
-#define ADB_TABLET 4
-#define ADB_MODEM 5
-#define ADB_MISC 7
-
-/* error codes */
-#define ADB_RET_NOTPRESENT (-2)
-
-int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
-{
- ADBDevice *d;
- int devaddr, cmd, i;
-
- cmd = buf[0] & 0xf;
- if (cmd == ADB_BUSRESET) {
- for(i = 0; i < s->nb_devices; i++) {
- d = &s->devices[i];
- if (d->devreset) {
- d->devreset(d);
- }
- }
- return 0;
- }
- devaddr = buf[0] >> 4;
- for(i = 0; i < s->nb_devices; i++) {
- d = &s->devices[i];
- if (d->devaddr == devaddr) {
- return d->devreq(d, obuf, buf, len);
- }
- }
- return ADB_RET_NOTPRESENT;
-}
-
-/* XXX: move that to cuda ? */
-int adb_poll(ADBBusState *s, uint8_t *obuf)
-{
- ADBDevice *d;
- int olen, i;
- uint8_t buf[1];
-
- olen = 0;
- for(i = 0; i < s->nb_devices; i++) {
- if (s->poll_index >= s->nb_devices)
- s->poll_index = 0;
- d = &s->devices[s->poll_index];
- buf[0] = ADB_READREG | (d->devaddr << 4);
- olen = adb_request(s, obuf + 1, buf, 1);
- /* if there is data, we poll again the same device */
- if (olen > 0) {
- obuf[0] = buf[0];
- olen++;
- break;
- }
- s->poll_index++;
- }
- return olen;
-}
-
-ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
- ADBDeviceRequest *devreq,
- ADBDeviceReset *devreset,
- void *opaque)
-{
- ADBDevice *d;
- if (s->nb_devices >= MAX_ADB_DEVICES)
- return NULL;
- d = &s->devices[s->nb_devices++];
- d->bus = s;
- d->devaddr = devaddr;
- d->devreq = devreq;
- d->devreset = devreset;
- d->opaque = opaque;
- return d;
-}
-
-/***************************************************************/
-/* Keyboard ADB device */
-
-typedef struct KBDState {
- uint8_t data[128];
- int rptr, wptr, count;
-} KBDState;
-
-static const uint8_t pc_to_adb_keycode[256] = {
- 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
- 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
- 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
- 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
- 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
- 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
- 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-static void adb_kbd_put_keycode(void *opaque, int keycode)
-{
- ADBDevice *d = opaque;
- KBDState *s = d->opaque;
-
- if (s->count < sizeof(s->data)) {
- s->data[s->wptr] = keycode;
- if (++s->wptr == sizeof(s->data))
- s->wptr = 0;
- s->count++;
- }
-}
-
-static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
-{
- static int ext_keycode;
- KBDState *s = d->opaque;
- int adb_keycode, keycode;
- int olen;
-
- olen = 0;
- for(;;) {
- if (s->count == 0)
- break;
- keycode = s->data[s->rptr];
- if (++s->rptr == sizeof(s->data))
- s->rptr = 0;
- s->count--;
-
- if (keycode == 0xe0) {
- ext_keycode = 1;
- } else {
- if (ext_keycode)
- adb_keycode = pc_to_adb_keycode[keycode | 0x80];
- else
- adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
- obuf[0] = adb_keycode | (keycode & 0x80);
- /* NOTE: could put a second keycode if needed */
- obuf[1] = 0xff;
- olen = 2;
- ext_keycode = 0;
- break;
- }
- }
- return olen;
-}
-
-static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
- const uint8_t *buf, int len)
-{
- KBDState *s = d->opaque;
- int cmd, reg, olen;
-
- if ((buf[0] & 0x0f) == ADB_FLUSH) {
- /* flush keyboard fifo */
- s->wptr = s->rptr = s->count = 0;
- return 0;
- }
-
- cmd = buf[0] & 0xc;
- reg = buf[0] & 0x3;
- olen = 0;
- switch(cmd) {
- case ADB_WRITEREG:
- switch(reg) {
- case 2:
- /* LED status */
- break;
- case 3:
- switch(buf[2]) {
- case ADB_CMD_SELF_TEST:
- break;
- case ADB_CMD_CHANGE_ID:
- case ADB_CMD_CHANGE_ID_AND_ACT:
- case ADB_CMD_CHANGE_ID_AND_ENABLE:
- d->devaddr = buf[1] & 0xf;
- break;
- default:
- /* XXX: check this */
- d->devaddr = buf[1] & 0xf;
- d->handler = buf[2];
- break;
- }
- }
- break;
- case ADB_READREG:
- switch(reg) {
- case 0:
- olen = adb_kbd_poll(d, obuf);
- break;
- case 1:
- break;
- case 2:
- obuf[0] = 0x00; /* XXX: check this */
- obuf[1] = 0x07; /* led status */
- olen = 2;
- break;
- case 3:
- obuf[0] = d->handler;
- obuf[1] = d->devaddr;
- olen = 2;
- break;
- }
- break;
- }
- return olen;
-}
-
-static int adb_kbd_reset(ADBDevice *d)
-{
- KBDState *s = d->opaque;
-
- d->handler = 1;
- d->devaddr = ADB_KEYBOARD;
- memset(s, 0, sizeof(KBDState));
-
- return 0;
-}
-
-void adb_kbd_init(ADBBusState *bus)
-{
- ADBDevice *d;
- KBDState *s;
- s = qemu_mallocz(sizeof(KBDState));
- d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
- adb_kbd_reset, s);
- adb_kbd_reset(d);
- qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
-}
-
-/***************************************************************/
-/* Mouse ADB device */
-
-typedef struct MouseState {
- int buttons_state, last_buttons_state;
- int dx, dy, dz;
-} MouseState;
-
-static void adb_mouse_event(void *opaque,
- int dx1, int dy1, int dz1, int buttons_state)
-{
- ADBDevice *d = opaque;
- MouseState *s = d->opaque;
-
- s->dx += dx1;
- s->dy += dy1;
- s->dz += dz1;
- s->buttons_state = buttons_state;
-}
-
-
-static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
-{
- MouseState *s = d->opaque;
- int dx, dy;
-
- if (s->last_buttons_state == s->buttons_state &&
- s->dx == 0 && s->dy == 0)
- return 0;
-
- dx = s->dx;
- if (dx < -63)
- dx = -63;
- else if (dx > 63)
- dx = 63;
-
- dy = s->dy;
- if (dy < -63)
- dy = -63;
- else if (dy > 63)
- dy = 63;
-
- s->dx -= dx;
- s->dy -= dy;
- s->last_buttons_state = s->buttons_state;
-
- dx &= 0x7f;
- dy &= 0x7f;
-
- if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
- dy |= 0x80;
- if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
- dx |= 0x80;
-
- obuf[0] = dy;
- obuf[1] = dx;
- return 2;
-}
-
-static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
- const uint8_t *buf, int len)
-{
- MouseState *s = d->opaque;
- int cmd, reg, olen;
-
- if ((buf[0] & 0x0f) == ADB_FLUSH) {
- /* flush mouse fifo */
- s->buttons_state = s->last_buttons_state;
- s->dx = 0;
- s->dy = 0;
- s->dz = 0;
- return 0;
- }
-
- cmd = buf[0] & 0xc;
- reg = buf[0] & 0x3;
- olen = 0;
- switch(cmd) {
- case ADB_WRITEREG:
- switch(reg) {
- case 2:
- break;
- case 3:
- switch(buf[2]) {
- case ADB_CMD_SELF_TEST:
- break;
- case ADB_CMD_CHANGE_ID:
- case ADB_CMD_CHANGE_ID_AND_ACT:
- case ADB_CMD_CHANGE_ID_AND_ENABLE:
- d->devaddr = buf[1] & 0xf;
- break;
- default:
- /* XXX: check this */
- d->devaddr = buf[1] & 0xf;
- break;
- }
- }
- break;
- case ADB_READREG:
- switch(reg) {
- case 0:
- olen = adb_mouse_poll(d, obuf);
- break;
- case 1:
- break;
- case 3:
- obuf[0] = d->handler;
- obuf[1] = d->devaddr;
- olen = 2;
- break;
- }
- break;
- }
- return olen;
-}
-
-static int adb_mouse_reset(ADBDevice *d)
-{
- MouseState *s = d->opaque;
-
- d->handler = 2;
- d->devaddr = ADB_MOUSE;
- memset(s, 0, sizeof(MouseState));
-
- return 0;
-}
-
-void adb_mouse_init(ADBBusState *bus)
-{
- ADBDevice *d;
- MouseState *s;
-
- s = qemu_mallocz(sizeof(MouseState));
- d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
- adb_mouse_reset, s);
- adb_mouse_reset(d);
- qemu_add_mouse_event_handler(adb_mouse_event, d, 0);
-}
diff --git a/hw/adlib.c b/hw/adlib.c
deleted file mode 100644
index b47bc3e..0000000
--- a/hw/adlib.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * QEMU Proxy for OPL2/3 emulation by MAME team
- *
- * Copyright (c) 2004-2005 Vassili Karpov (malc)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include <assert.h>
-#include "vl.h"
-
-#define ADLIB_KILL_TIMERS 1
-
-#define dolog(...) AUD_log ("adlib", __VA_ARGS__)
-#ifdef DEBUG
-#define ldebug(...) dolog (__VA_ARGS__)
-#else
-#define ldebug(...)
-#endif
-
-#ifdef HAS_YMF262
-#include "ymf262.h"
-void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
-#define SHIFT 2
-#else
-#include "fmopl.h"
-#define SHIFT 1
-#endif
-
-#define IO_READ_PROTO(name) \
- uint32_t name (void *opaque, uint32_t nport)
-#define IO_WRITE_PROTO(name) \
- void name (void *opaque, uint32_t nport, uint32_t val)
-
-static struct {
- int port;
- int freq;
-} conf = {0x220, 44100};
-
-typedef struct {
- QEMUSoundCard card;
- int ticking[2];
- int enabled;
- int active;
- int bufpos;
-#ifdef DEBUG
- int64_t exp[2];
-#endif
- int16_t *mixbuf;
- uint64_t dexp[2];
- SWVoiceOut *voice;
- int left, pos, samples;
- QEMUAudioTimeStamp ats;
-#ifndef HAS_YMF262
- FM_OPL *opl;
-#endif
-} AdlibState;
-
-static AdlibState glob_adlib;
-
-static void adlib_stop_opl_timer (AdlibState *s, size_t n)
-{
-#ifdef HAS_YMF262
- YMF262TimerOver (0, n);
-#else
- OPLTimerOver (s->opl, n);
-#endif
- s->ticking[n] = 0;
-}
-
-static void adlib_kill_timers (AdlibState *s)
-{
- size_t i;
-
- for (i = 0; i < 2; ++i) {
- if (s->ticking[i]) {
- uint64_t delta;
-
- delta = AUD_get_elapsed_usec_out (s->voice, &s->ats);
- ldebug (
- "delta = %f dexp = %f expired => %d\n",
- delta / 1000000.0,
- s->dexp[i] / 1000000.0,
- delta >= s->dexp[i]
- );
- if (ADLIB_KILL_TIMERS || delta >= s->dexp[i]) {
- adlib_stop_opl_timer (s, i);
- AUD_init_time_stamp_out (s->voice, &s->ats);
- }
- }
- }
-}
-
-static IO_WRITE_PROTO(adlib_write)
-{
- AdlibState *s = opaque;
- int a = nport & 3;
- int status;
-
- s->active = 1;
- AUD_set_active_out (s->voice, 1);
-
- adlib_kill_timers (s);
-
-#ifdef HAS_YMF262
- status = YMF262Write (0, a, val);
-#else
- status = OPLWrite (s->opl, a, val);
-#endif
-}
-
-static IO_READ_PROTO(adlib_read)
-{
- AdlibState *s = opaque;
- uint8_t data;
- int a = nport & 3;
-
- adlib_kill_timers (s);
-
-#ifdef HAS_YMF262
- data = YMF262Read (0, a);
-#else
- data = OPLRead (s->opl, a);
-#endif
- return data;
-}
-
-static void timer_handler (int c, double interval_Sec)
-{
- AdlibState *s = &glob_adlib;
- unsigned n = c & 1;
-#ifdef DEBUG
- double interval;
- int64_t exp;
-#endif
-
- if (interval_Sec == 0.0) {
- s->ticking[n] = 0;
- return;
- }
-
- s->ticking[n] = 1;
-#ifdef DEBUG
- interval = ticks_per_sec * interval_Sec;
- exp = qemu_get_clock (vm_clock) + interval;
- s->exp[n] = exp;
-#endif
-
- s->dexp[n] = interval_Sec * 1000000.0;
- AUD_init_time_stamp_out (s->voice, &s->ats);
-}
-
-static int write_audio (AdlibState *s, int samples)
-{
- int net = 0;
- int pos = s->pos;
-
- while (samples) {
- int nbytes, wbytes, wsampl;
-
- nbytes = samples << SHIFT;
- wbytes = AUD_write (
- s->voice,
- s->mixbuf + (pos << (SHIFT - 1)),
- nbytes
- );
-
- if (wbytes) {
- wsampl = wbytes >> SHIFT;
-
- samples -= wsampl;
- pos = (pos + wsampl) % s->samples;
-
- net += wsampl;
- }
- else {
- break;
- }
- }
-
- return net;
-}
-
-static void adlib_callback (void *opaque, int free)
-{
- AdlibState *s = opaque;
- int samples, net = 0, to_play, written;
-
- samples = free >> SHIFT;
- if (!(s->active && s->enabled) || !samples) {
- return;
- }
-
- to_play = audio_MIN (s->left, samples);
- while (to_play) {
- written = write_audio (s, to_play);
-
- if (written) {
- s->left -= written;
- samples -= written;
- to_play -= written;
- s->pos = (s->pos + written) % s->samples;
- }
- else {
- return;
- }
- }
-
- samples = audio_MIN (samples, s->samples - s->pos);
- if (!samples) {
- return;
- }
-
-#ifdef HAS_YMF262
- YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
-#else
- YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
-#endif
-
- while (samples) {
- written = write_audio (s, samples);
-
- if (written) {
- net += written;
- samples -= written;
- s->pos = (s->pos + written) % s->samples;
- }
- else {
- s->left = samples;
- return;
- }
- }
-}
-
-static void Adlib_fini (AdlibState *s)
-{
-#ifdef HAS_YMF262
- YMF262Shutdown ();
-#else
- if (s->opl) {
- OPLDestroy (s->opl);
- s->opl = NULL;
- }
-#endif
-
- if (s->mixbuf) {
- qemu_free (s->mixbuf);
- }
-
- s->active = 0;
- s->enabled = 0;
- AUD_remove_card (&s->card);
-}
-
-int Adlib_init (AudioState *audio)
-{
- AdlibState *s = &glob_adlib;
- audsettings_t as;
-
- if (!audio) {
- dolog ("No audio state\n");
- return -1;
- }
-
-#ifdef HAS_YMF262
- if (YMF262Init (1, 14318180, conf.freq)) {
- dolog ("YMF262Init %d failed\n", conf.freq);
- return -1;
- }
- else {
- YMF262SetTimerHandler (0, timer_handler, 0);
- s->enabled = 1;
- }
-#else
- s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, conf.freq);
- if (!s->opl) {
- dolog ("OPLCreate %d failed\n", conf.freq);
- return -1;
- }
- else {
- OPLSetTimerHandler (s->opl, timer_handler, 0);
- s->enabled = 1;
- }
-#endif
-
- as.freq = conf.freq;
- as.nchannels = SHIFT;
- as.fmt = AUD_FMT_S16;
- as.endianness = AUDIO_HOST_ENDIANNESS;
-
- AUD_register_card (audio, "adlib", &s->card);
-
- s->voice = AUD_open_out (
- &s->card,
- s->voice,
- "adlib",
- s,
- adlib_callback,
- &as
- );
- if (!s->voice) {
- Adlib_fini (s);
- return -1;
- }
-
- s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT;
- s->mixbuf = qemu_mallocz (s->samples << SHIFT);
-
- if (!s->mixbuf) {
- dolog ("Could not allocate mixing buffer, %d samples (each %d bytes)\n",
- s->samples, 1 << SHIFT);
- Adlib_fini (s);
- return -1;
- }
-
- register_ioport_read (0x388, 4, 1, adlib_read, s);
- register_ioport_write (0x388, 4, 1, adlib_write, s);
-
- register_ioport_read (conf.port, 4, 1, adlib_read, s);
- register_ioport_write (conf.port, 4, 1, adlib_write, s);
-
- register_ioport_read (conf.port + 8, 2, 1, adlib_read, s);
- register_ioport_write (conf.port + 8, 2, 1, adlib_write, s);
-
- return 0;
-}
diff --git a/hw/android_arm.c b/hw/android_arm.c
new file mode 100644
index 0000000..7b1d446
--- /dev/null
+++ b/hw/android_arm.c
@@ -0,0 +1,149 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "arm_pic.h"
+#include "goldfish_device.h"
+
+int android_audio_enabled;
+char* audio_input_source = NULL;
+
+void goldfish_memlog_init(uint32_t base);
+
+static struct goldfish_device event0_device = {
+ .name = "goldfish_events",
+ .id = 0,
+ .size = 0x1000,
+ .irq_count = 1
+};
+
+static struct goldfish_device nand_device = {
+ .name = "goldfish_nand",
+ .id = 0,
+ .size = 0x1000
+};
+
+static struct goldfish_device trace_device = {
+ .name = "qemu_trace",
+ .id = -1,
+ .size = 0x1000
+};
+
+/* Board init. */
+
+#define TEST_SWITCH 1
+#if TEST_SWITCH
+uint32_t switch_test_write(void *opaque, uint32_t state)
+{
+ goldfish_switch_set_state(opaque, state);
+ return state;
+}
+#endif
+
+static void android_arm_init(int ram_size, int vga_ram_size,
+ int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename)
+{
+ CPUState *env;
+ qemu_irq *cpu_pic;
+ qemu_irq *goldfish_pic;
+ int i;
+
+ env = cpu_init();
+ cpu_arm_set_model(env, ARM_CPUID_ARM926);
+
+ register_savevm( "cpu", 0, ARM_CPU_SAVE_VERSION, cpu_save, cpu_load, env );
+
+ cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+ cpu_pic = arm_pic_init_cpu(env);
+ goldfish_pic = goldfish_interrupt_init(0xff000000, cpu_pic[ARM_PIC_CPU_IRQ], cpu_pic[ARM_PIC_CPU_FIQ]);
+ goldfish_device_init(goldfish_pic, 0xff010000, 0x7f0000, 10, 22);
+
+ goldfish_device_bus_init(0xff001000, 1);
+
+ goldfish_timer_and_rtc_init(0xff003000, 3);
+
+ goldfish_tty_add(serial_hds[0], 0, 0xff002000, 4);
+ for(i = 1; i < MAX_SERIAL_PORTS; i++) {
+ //printf("android_arm_init serial %d %x\n", i, serial_hds[i]);
+ if(serial_hds[i]) {
+ goldfish_tty_add(serial_hds[i], i, 0, 0);
+ }
+ }
+
+ for(i = 0; i < MAX_NICS; i++) {
+ if (nd_table[i].vlan) {
+ if (nd_table[i].model == NULL
+ || strcmp(nd_table[i].model, "smc91c111") == 0) {
+ struct goldfish_device *smc_device;
+ smc_device = qemu_mallocz(sizeof(*smc_device));
+ smc_device->name = "smc91x";
+ smc_device->id = i;
+ smc_device->size = 0x1000;
+ smc_device->irq_count = 1;
+ goldfish_add_device_no_io(smc_device);
+ smc91c111_init(&nd_table[i], smc_device->base, goldfish_pic[smc_device->irq]);
+ } else {
+ fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
+ exit (1);
+ }
+ }
+ }
+
+ goldfish_fb_init(ds, 0);
+#ifdef HAS_AUDIO
+ if (android_audio_enabled) {
+ AUD_init();
+ goldfish_audio_init(0xff004000, 0, audio_input_source);
+ }
+#endif
+ if (bs_table[0])
+ goldfish_mmc_init(0xff005000, 0, bs_table[0]);
+
+ goldfish_memlog_init(0xff006000);
+
+ goldfish_battery_init();
+
+ goldfish_add_device_no_io(&event0_device);
+ events_dev_init(event0_device.base, goldfish_pic[event0_device.irq]);
+
+#ifdef CONFIG_NAND
+ goldfish_add_device_no_io(&nand_device);
+ nand_dev_init(nand_device.base);
+#endif
+#ifdef CONFIG_TRACE
+ extern const char *trace_filename;
+ if(trace_filename != NULL) {
+ goldfish_add_device_no_io(&trace_device);
+ trace_dev_init(trace_device.base);
+ }
+#endif
+
+#if TEST_SWITCH
+ {
+ void *sw;
+ sw = goldfish_switch_add("test", NULL, NULL, 0);
+ goldfish_switch_set_state(sw, 1);
+ goldfish_switch_add("test2", switch_test_write, sw, 1);
+ }
+#endif
+
+ arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
+ initrd_filename, 1441);
+}
+
+QEMUMachine android_arm_machine = {
+ "android_arm",
+ "ARM Android Emulator",
+ android_arm_init,
+};
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
deleted file mode 100644
index 02e9824..0000000
--- a/hw/apb_pci.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * QEMU Ultrasparc APB PCI host
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
-typedef PCIHostState APBState;
-
-static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- APBState *s = opaque;
- int i;
-
- for (i = 11; i < 32; i++) {
- if ((val & (1 << i)) != 0)
- break;
- }
- s->config_reg = (1 << 16) | (val & 0x7FC) | (i << 11);
-}
-
-static uint32_t pci_apb_config_readl (void *opaque,
- target_phys_addr_t addr)
-{
- APBState *s = opaque;
- uint32_t val;
- int devfn;
-
- devfn = (s->config_reg >> 8) & 0xFF;
- val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
- return val;
-}
-
-static CPUWriteMemoryFunc *pci_apb_config_write[] = {
- &pci_apb_config_writel,
- &pci_apb_config_writel,
- &pci_apb_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_apb_config_read[] = {
- &pci_apb_config_readl,
- &pci_apb_config_readl,
- &pci_apb_config_readl,
-};
-
-static void apb_config_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- //PCIBus *s = opaque;
-
- switch (addr & 0x3f) {
- case 0x00: // Control/Status
- case 0x10: // AFSR
- case 0x18: // AFAR
- case 0x20: // Diagnostic
- case 0x28: // Target address space
- // XXX
- default:
- break;
- }
-}
-
-static uint32_t apb_config_readl (void *opaque,
- target_phys_addr_t addr)
-{
- //PCIBus *s = opaque;
- uint32_t val;
-
- switch (addr & 0x3f) {
- case 0x00: // Control/Status
- case 0x10: // AFSR
- case 0x18: // AFAR
- case 0x20: // Diagnostic
- case 0x28: // Target address space
- // XXX
- default:
- val = 0;
- break;
- }
- return val;
-}
-
-static CPUWriteMemoryFunc *apb_config_write[] = {
- &apb_config_writel,
- &apb_config_writel,
- &apb_config_writel,
-};
-
-static CPUReadMemoryFunc *apb_config_read[] = {
- &apb_config_readl,
- &apb_config_readl,
- &apb_config_readl,
-};
-
-static CPUWriteMemoryFunc *pci_apb_write[] = {
- &pci_host_data_writeb,
- &pci_host_data_writew,
- &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc *pci_apb_read[] = {
- &pci_host_data_readb,
- &pci_host_data_readw,
- &pci_host_data_readl,
-};
-
-static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- cpu_outb(NULL, addr & 0xffff, val);
-}
-
-static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- cpu_outw(NULL, addr & 0xffff, val);
-}
-
-static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- cpu_outl(NULL, addr & 0xffff, val);
-}
-
-static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
-
- val = cpu_inb(NULL, addr & 0xffff);
- return val;
-}
-
-static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
-
- val = cpu_inw(NULL, addr & 0xffff);
- return val;
-}
-
-static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
-
- val = cpu_inl(NULL, addr & 0xffff);
- return val;
-}
-
-static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
- &pci_apb_iowriteb,
- &pci_apb_iowritew,
- &pci_apb_iowritel,
-};
-
-static CPUReadMemoryFunc *pci_apb_ioread[] = {
- &pci_apb_ioreadb,
- &pci_apb_ioreadw,
- &pci_apb_ioreadl,
-};
-
-/* ??? This is probably wrong. */
-static void pci_apb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
-{
- pic_set_irq_new(pic, d->config[PCI_INTERRUPT_LINE], level);
-}
-
-PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
- void *pic)
-{
- APBState *s;
- PCIDevice *d;
- int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
-
- s = qemu_mallocz(sizeof(APBState));
- /* Ultrasparc APB main bus */
- s->bus = pci_register_bus(pci_apb_set_irq, pic, 0);
-
- pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
- pci_apb_config_write, s);
- apb_config = cpu_register_io_memory(0, apb_config_read,
- apb_config_write, s);
- pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
- pci_apb_write, s);
- pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
- pci_apb_iowrite, s);
-
- cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
- cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, pci_mem_config);
- cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, pci_ioport);
- cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
-
- d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
- -1, NULL, NULL);
- d->config[0x00] = 0x8e; // vendor_id : Sun
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x00; // device_id
- d->config[0x03] = 0xa0;
- d->config[0x04] = 0x06; // command = bus master, pci mem
- d->config[0x05] = 0x00;
- d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
- d->config[0x07] = 0x03; // status = medium devsel
- d->config[0x08] = 0x00; // revision
- d->config[0x09] = 0x00; // programming i/f
- d->config[0x0A] = 0x00; // class_sub = pci host
- d->config[0x0B] = 0x06; // class_base = PCI_bridge
- d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
- return s->bus;
-}
-
-
diff --git a/hw/apic.c b/hw/apic.c
deleted file mode 100644
index 8f88cce..0000000
--- a/hw/apic.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*
- * APIC support
- *
- * Copyright (c) 2004-2005 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "vl.h"
-
-//#define DEBUG_APIC
-//#define DEBUG_IOAPIC
-
-/* APIC Local Vector Table */
-#define APIC_LVT_TIMER 0
-#define APIC_LVT_THERMAL 1
-#define APIC_LVT_PERFORM 2
-#define APIC_LVT_LINT0 3
-#define APIC_LVT_LINT1 4
-#define APIC_LVT_ERROR 5
-#define APIC_LVT_NB 6
-
-/* APIC delivery modes */
-#define APIC_DM_FIXED 0
-#define APIC_DM_LOWPRI 1
-#define APIC_DM_SMI 2
-#define APIC_DM_NMI 4
-#define APIC_DM_INIT 5
-#define APIC_DM_SIPI 6
-#define APIC_DM_EXTINT 7
-
-/* APIC destination mode */
-#define APIC_DESTMODE_FLAT 0xf
-#define APIC_DESTMODE_CLUSTER 1
-
-#define APIC_TRIGGER_EDGE 0
-#define APIC_TRIGGER_LEVEL 1
-
-#define APIC_LVT_TIMER_PERIODIC (1<<17)
-#define APIC_LVT_MASKED (1<<16)
-#define APIC_LVT_LEVEL_TRIGGER (1<<15)
-#define APIC_LVT_REMOTE_IRR (1<<14)
-#define APIC_INPUT_POLARITY (1<<13)
-#define APIC_SEND_PENDING (1<<12)
-
-#define IOAPIC_NUM_PINS 0x18
-
-#define ESR_ILLEGAL_ADDRESS (1 << 7)
-
-#define APIC_SV_ENABLE (1 << 8)
-
-#define MAX_APICS 255
-#define MAX_APIC_WORDS 8
-
-typedef struct APICState {
- CPUState *cpu_env;
- uint32_t apicbase;
- uint8_t id;
- uint8_t arb_id;
- uint8_t tpr;
- uint32_t spurious_vec;
- uint8_t log_dest;
- uint8_t dest_mode;
- uint32_t isr[8]; /* in service register */
- uint32_t tmr[8]; /* trigger mode register */
- uint32_t irr[8]; /* interrupt request register */
- uint32_t lvt[APIC_LVT_NB];
- uint32_t esr; /* error register */
- uint32_t icr[2];
-
- uint32_t divide_conf;
- int count_shift;
- uint32_t initial_count;
- int64_t initial_count_load_time, next_time;
- QEMUTimer *timer;
-} APICState;
-
-struct IOAPICState {
- uint8_t id;
- uint8_t ioregsel;
-
- uint32_t irr;
- uint64_t ioredtbl[IOAPIC_NUM_PINS];
-};
-
-static int apic_io_memory;
-static APICState *local_apics[MAX_APICS + 1];
-static int last_apic_id = 0;
-
-static void apic_init_ipi(APICState *s);
-static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
-static void apic_update_irq(APICState *s);
-
-/* Find first bit starting from msb. Return 0 if value = 0 */
-static int fls_bit(uint32_t value)
-{
- unsigned int ret = 0;
-
-#if defined(HOST_I386)
- __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value));
- return ret;
-#else
- if (value > 0xffff)
- value >>= 16, ret = 16;
- if (value > 0xff)
- value >>= 8, ret += 8;
- if (value > 0xf)
- value >>= 4, ret += 4;
- if (value > 0x3)
- value >>= 2, ret += 2;
- return ret + (value >> 1);
-#endif
-}
-
-/* Find first bit starting from lsb. Return 0 if value = 0 */
-static int ffs_bit(uint32_t value)
-{
- unsigned int ret = 0;
-
-#if defined(HOST_I386)
- __asm__ __volatile__ ("bsf %1, %0\n" : "+r" (ret) : "rm" (value));
- return ret;
-#else
- if (!value)
- return 0;
- if (!(value & 0xffff))
- value >>= 16, ret = 16;
- if (!(value & 0xff))
- value >>= 8, ret += 8;
- if (!(value & 0xf))
- value >>= 4, ret += 4;
- if (!(value & 0x3))
- value >>= 2, ret += 2;
- if (!(value & 0x1))
- ret++;
- return ret;
-#endif
-}
-
-static inline void set_bit(uint32_t *tab, int index)
-{
- int i, mask;
- i = index >> 5;
- mask = 1 << (index & 0x1f);
- tab[i] |= mask;
-}
-
-static inline void reset_bit(uint32_t *tab, int index)
-{
- int i, mask;
- i = index >> 5;
- mask = 1 << (index & 0x1f);
- tab[i] &= ~mask;
-}
-
-#define foreach_apic(apic, deliver_bitmask, code) \
-{\
- int __i, __j, __mask;\
- for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
- __mask = deliver_bitmask[__i];\
- if (__mask) {\
- for(__j = 0; __j < 32; __j++) {\
- if (__mask & (1 << __j)) {\
- apic = local_apics[__i * 32 + __j];\
- if (apic) {\
- code;\
- }\
- }\
- }\
- }\
- }\
-}
-
-static void apic_bus_deliver(const uint32_t *deliver_bitmask,
- uint8_t delivery_mode,
- uint8_t vector_num, uint8_t polarity,
- uint8_t trigger_mode)
-{
- APICState *apic_iter;
-
- switch (delivery_mode) {
- case APIC_DM_LOWPRI:
- /* XXX: search for focus processor, arbitration */
- {
- int i, d;
- d = -1;
- for(i = 0; i < MAX_APIC_WORDS; i++) {
- if (deliver_bitmask[i]) {
- d = i * 32 + ffs_bit(deliver_bitmask[i]);
- break;
- }
- }
- if (d >= 0) {
- apic_iter = local_apics[d];
- if (apic_iter) {
- apic_set_irq(apic_iter, vector_num, trigger_mode);
- }
- }
- }
- return;
-
- case APIC_DM_FIXED:
- break;
-
- case APIC_DM_SMI:
- case APIC_DM_NMI:
- break;
-
- case APIC_DM_INIT:
- /* normal INIT IPI sent to processors */
- foreach_apic(apic_iter, deliver_bitmask,
- apic_init_ipi(apic_iter) );
- return;
-
- case APIC_DM_EXTINT:
- /* handled in I/O APIC code */
- break;
-
- default:
- return;
- }
-
- foreach_apic(apic_iter, deliver_bitmask,
- apic_set_irq(apic_iter, vector_num, trigger_mode) );
-}
-
-void cpu_set_apic_base(CPUState *env, uint64_t val)
-{
- APICState *s = env->apic_state;
-#ifdef DEBUG_APIC
- printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
-#endif
- s->apicbase = (val & 0xfffff000) |
- (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
- /* if disabled, cannot be enabled again */
- if (!(val & MSR_IA32_APICBASE_ENABLE)) {
- s->apicbase &= ~MSR_IA32_APICBASE_ENABLE;
- env->cpuid_features &= ~CPUID_APIC;
- s->spurious_vec &= ~APIC_SV_ENABLE;
- }
-}
-
-uint64_t cpu_get_apic_base(CPUState *env)
-{
- APICState *s = env->apic_state;
-#ifdef DEBUG_APIC
- printf("cpu_get_apic_base: %016" PRIx64 "\n", (uint64_t)s->apicbase);
-#endif
- return s->apicbase;
-}
-
-void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
-{
- APICState *s = env->apic_state;
- s->tpr = (val & 0x0f) << 4;
- apic_update_irq(s);
-}
-
-uint8_t cpu_get_apic_tpr(CPUX86State *env)
-{
- APICState *s = env->apic_state;
- return s->tpr >> 4;
-}
-
-/* return -1 if no bit is set */
-static int get_highest_priority_int(uint32_t *tab)
-{
- int i;
- for(i = 7; i >= 0; i--) {
- if (tab[i] != 0) {
- return i * 32 + fls_bit(tab[i]);
- }
- }
- return -1;
-}
-
-static int apic_get_ppr(APICState *s)
-{
- int tpr, isrv, ppr;
-
- tpr = (s->tpr >> 4);
- isrv = get_highest_priority_int(s->isr);
- if (isrv < 0)
- isrv = 0;
- isrv >>= 4;
- if (tpr >= isrv)
- ppr = s->tpr;
- else
- ppr = isrv << 4;
- return ppr;
-}
-
-static int apic_get_arb_pri(APICState *s)
-{
- /* XXX: arbitration */
- return 0;
-}
-
-/* signal the CPU if an irq is pending */
-static void apic_update_irq(APICState *s)
-{
- int irrv, ppr;
- if (!(s->spurious_vec & APIC_SV_ENABLE))
- return;
- irrv = get_highest_priority_int(s->irr);
- if (irrv < 0)
- return;
- ppr = apic_get_ppr(s);
- if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
- return;
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
-}
-
-static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
-{
- set_bit(s->irr, vector_num);
- if (trigger_mode)
- set_bit(s->tmr, vector_num);
- else
- reset_bit(s->tmr, vector_num);
- apic_update_irq(s);
-}
-
-static void apic_eoi(APICState *s)
-{
- int isrv;
- isrv = get_highest_priority_int(s->isr);
- if (isrv < 0)
- return;
- reset_bit(s->isr, isrv);
- /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
- set the remote IRR bit for level triggered interrupts. */
- apic_update_irq(s);
-}
-
-static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
- uint8_t dest, uint8_t dest_mode)
-{
- APICState *apic_iter;
- int i;
-
- if (dest_mode == 0) {
- if (dest == 0xff) {
- memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t));
- } else {
- memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
- set_bit(deliver_bitmask, dest);
- }
- } else {
- /* XXX: cluster mode */
- memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
- for(i = 0; i < MAX_APICS; i++) {
- apic_iter = local_apics[i];
- if (apic_iter) {
- if (apic_iter->dest_mode == 0xf) {
- if (dest & apic_iter->log_dest)
- set_bit(deliver_bitmask, i);
- } else if (apic_iter->dest_mode == 0x0) {
- if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
- (dest & apic_iter->log_dest & 0x0f)) {
- set_bit(deliver_bitmask, i);
- }
- }
- }
- }
- }
-}
-
-
-static void apic_init_ipi(APICState *s)
-{
- int i;
-
- for(i = 0; i < APIC_LVT_NB; i++)
- s->lvt[i] = 1 << 16; /* mask LVT */
- s->tpr = 0;
- s->spurious_vec = 0xff;
- s->log_dest = 0;
- s->dest_mode = 0xf;
- memset(s->isr, 0, sizeof(s->isr));
- memset(s->tmr, 0, sizeof(s->tmr));
- memset(s->irr, 0, sizeof(s->irr));
- memset(s->lvt, 0, sizeof(s->lvt));
- s->esr = 0;
- memset(s->icr, 0, sizeof(s->icr));
- s->divide_conf = 0;
- s->count_shift = 0;
- s->initial_count = 0;
- s->initial_count_load_time = 0;
- s->next_time = 0;
-}
-
-/* send a SIPI message to the CPU to start it */
-static void apic_startup(APICState *s, int vector_num)
-{
- CPUState *env = s->cpu_env;
- if (!(env->hflags & HF_HALTED_MASK))
- return;
- env->eip = 0;
- cpu_x86_load_seg_cache(env, R_CS, vector_num << 8, vector_num << 12,
- 0xffff, 0);
- env->hflags &= ~HF_HALTED_MASK;
-}
-
-static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode,
- uint8_t delivery_mode, uint8_t vector_num,
- uint8_t polarity, uint8_t trigger_mode)
-{
- uint32_t deliver_bitmask[MAX_APIC_WORDS];
- int dest_shorthand = (s->icr[0] >> 18) & 3;
- APICState *apic_iter;
-
- switch (dest_shorthand) {
- case 0:
- apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
- break;
- case 1:
- memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask));
- set_bit(deliver_bitmask, s->id);
- break;
- case 2:
- memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
- break;
- case 3:
- memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask));
- reset_bit(deliver_bitmask, s->id);
- break;
- }
-
- switch (delivery_mode) {
- case APIC_DM_INIT:
- {
- int trig_mode = (s->icr[0] >> 15) & 1;
- int level = (s->icr[0] >> 14) & 1;
- if (level == 0 && trig_mode == 1) {
- foreach_apic(apic_iter, deliver_bitmask,
- apic_iter->arb_id = apic_iter->id );
- return;
- }
- }
- break;
-
- case APIC_DM_SIPI:
- foreach_apic(apic_iter, deliver_bitmask,
- apic_startup(apic_iter, vector_num) );
- return;
- }
-
- apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
- trigger_mode);
-}
-
-int apic_get_interrupt(CPUState *env)
-{
- APICState *s = env->apic_state;
- int intno;
-
- /* if the APIC is installed or enabled, we let the 8259 handle the
- IRQs */
- if (!s)
- return -1;
- if (!(s->spurious_vec & APIC_SV_ENABLE))
- return -1;
-
- /* XXX: spurious IRQ handling */
- intno = get_highest_priority_int(s->irr);
- if (intno < 0)
- return -1;
- reset_bit(s->irr, intno);
- if (s->tpr && intno <= s->tpr)
- return s->spurious_vec & 0xff;
- set_bit(s->isr, intno);
- apic_update_irq(s);
- return intno;
-}
-
-static uint32_t apic_get_current_count(APICState *s)
-{
- int64_t d;
- uint32_t val;
- d = (qemu_get_clock(vm_clock) - s->initial_count_load_time) >>
- s->count_shift;
- if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
- /* periodic */
- val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
- } else {
- if (d >= s->initial_count)
- val = 0;
- else
- val = s->initial_count - d;
- }
- return val;
-}
-
-static void apic_timer_update(APICState *s, int64_t current_time)
-{
- int64_t next_time, d;
-
- if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
- d = (current_time - s->initial_count_load_time) >>
- s->count_shift;
- if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
- d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * ((uint64_t)s->initial_count + 1);
- } else {
- if (d >= s->initial_count)
- goto no_timer;
- d = (uint64_t)s->initial_count + 1;
- }
- next_time = s->initial_count_load_time + (d << s->count_shift);
- qemu_mod_timer(s->timer, next_time);
- s->next_time = next_time;
- } else {
- no_timer:
- qemu_del_timer(s->timer);
- }
-}
-
-static void apic_timer(void *opaque)
-{
- APICState *s = opaque;
-
- if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
- apic_set_irq(s, s->lvt[APIC_LVT_TIMER] & 0xff, APIC_TRIGGER_EDGE);
- }
- apic_timer_update(s, s->next_time);
-}
-
-static uint32_t apic_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static uint32_t apic_mem_readw(void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static void apic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-}
-
-static void apic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-}
-
-static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- CPUState *env;
- APICState *s;
- uint32_t val;
- int index;
-
- env = cpu_single_env;
- if (!env)
- return 0;
- s = env->apic_state;
-
- index = (addr >> 4) & 0xff;
- switch(index) {
- case 0x02: /* id */
- val = s->id << 24;
- break;
- case 0x03: /* version */
- val = 0x11 | ((APIC_LVT_NB - 1) << 16); /* version 0x11 */
- break;
- case 0x08:
- val = s->tpr;
- break;
- case 0x09:
- val = apic_get_arb_pri(s);
- break;
- case 0x0a:
- /* ppr */
- val = apic_get_ppr(s);
- break;
- case 0x0d:
- val = s->log_dest << 24;
- break;
- case 0x0e:
- val = s->dest_mode << 28;
- break;
- case 0x0f:
- val = s->spurious_vec;
- break;
- case 0x10 ... 0x17:
- val = s->isr[index & 7];
- break;
- case 0x18 ... 0x1f:
- val = s->tmr[index & 7];
- break;
- case 0x20 ... 0x27:
- val = s->irr[index & 7];
- break;
- case 0x28:
- val = s->esr;
- break;
- case 0x30:
- case 0x31:
- val = s->icr[index & 1];
- break;
- case 0x32 ... 0x37:
- val = s->lvt[index - 0x32];
- break;
- case 0x38:
- val = s->initial_count;
- break;
- case 0x39:
- val = apic_get_current_count(s);
- break;
- case 0x3e:
- val = s->divide_conf;
- break;
- default:
- s->esr |= ESR_ILLEGAL_ADDRESS;
- val = 0;
- break;
- }
-#ifdef DEBUG_APIC
- printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
-#endif
- return val;
-}
-
-static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- CPUState *env;
- APICState *s;
- int index;
-
- env = cpu_single_env;
- if (!env)
- return;
- s = env->apic_state;
-
-#ifdef DEBUG_APIC
- printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
-#endif
-
- index = (addr >> 4) & 0xff;
- switch(index) {
- case 0x02:
- s->id = (val >> 24);
- break;
- case 0x03:
- break;
- case 0x08:
- s->tpr = val;
- apic_update_irq(s);
- break;
- case 0x09:
- case 0x0a:
- break;
- case 0x0b: /* EOI */
- apic_eoi(s);
- break;
- case 0x0d:
- s->log_dest = val >> 24;
- break;
- case 0x0e:
- s->dest_mode = val >> 28;
- break;
- case 0x0f:
- s->spurious_vec = val & 0x1ff;
- apic_update_irq(s);
- break;
- case 0x10 ... 0x17:
- case 0x18 ... 0x1f:
- case 0x20 ... 0x27:
- case 0x28:
- break;
- case 0x30:
- s->icr[0] = val;
- apic_deliver(s, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1,
- (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff),
- (s->icr[0] >> 14) & 1, (s->icr[0] >> 15) & 1);
- break;
- case 0x31:
- s->icr[1] = val;
- break;
- case 0x32 ... 0x37:
- {
- int n = index - 0x32;
- s->lvt[n] = val;
- if (n == APIC_LVT_TIMER)
- apic_timer_update(s, qemu_get_clock(vm_clock));
- }
- break;
- case 0x38:
- s->initial_count = val;
- s->initial_count_load_time = qemu_get_clock(vm_clock);
- apic_timer_update(s, s->initial_count_load_time);
- break;
- case 0x39:
- break;
- case 0x3e:
- {
- int v;
- s->divide_conf = val & 0xb;
- v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
- s->count_shift = (v + 1) & 7;
- }
- break;
- default:
- s->esr |= ESR_ILLEGAL_ADDRESS;
- break;
- }
-}
-
-static void apic_save(QEMUFile *f, void *opaque)
-{
- APICState *s = opaque;
- int i;
-
- qemu_put_be32s(f, &s->apicbase);
- qemu_put_8s(f, &s->id);
- qemu_put_8s(f, &s->arb_id);
- qemu_put_8s(f, &s->tpr);
- qemu_put_be32s(f, &s->spurious_vec);
- qemu_put_8s(f, &s->log_dest);
- qemu_put_8s(f, &s->dest_mode);
- for (i = 0; i < 8; i++) {
- qemu_put_be32s(f, &s->isr[i]);
- qemu_put_be32s(f, &s->tmr[i]);
- qemu_put_be32s(f, &s->irr[i]);
- }
- for (i = 0; i < APIC_LVT_NB; i++) {
- qemu_put_be32s(f, &s->lvt[i]);
- }
- qemu_put_be32s(f, &s->esr);
- qemu_put_be32s(f, &s->icr[0]);
- qemu_put_be32s(f, &s->icr[1]);
- qemu_put_be32s(f, &s->divide_conf);
- qemu_put_be32s(f, &s->count_shift);
- qemu_put_be32s(f, &s->initial_count);
- qemu_put_be64s(f, &s->initial_count_load_time);
- qemu_put_be64s(f, &s->next_time);
-}
-
-static int apic_load(QEMUFile *f, void *opaque, int version_id)
-{
- APICState *s = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- /* XXX: what if the base changes? (registered memory regions) */
- qemu_get_be32s(f, &s->apicbase);
- qemu_get_8s(f, &s->id);
- qemu_get_8s(f, &s->arb_id);
- qemu_get_8s(f, &s->tpr);
- qemu_get_be32s(f, &s->spurious_vec);
- qemu_get_8s(f, &s->log_dest);
- qemu_get_8s(f, &s->dest_mode);
- for (i = 0; i < 8; i++) {
- qemu_get_be32s(f, &s->isr[i]);
- qemu_get_be32s(f, &s->tmr[i]);
- qemu_get_be32s(f, &s->irr[i]);
- }
- for (i = 0; i < APIC_LVT_NB; i++) {
- qemu_get_be32s(f, &s->lvt[i]);
- }
- qemu_get_be32s(f, &s->esr);
- qemu_get_be32s(f, &s->icr[0]);
- qemu_get_be32s(f, &s->icr[1]);
- qemu_get_be32s(f, &s->divide_conf);
- qemu_get_be32s(f, &s->count_shift);
- qemu_get_be32s(f, &s->initial_count);
- qemu_get_be64s(f, &s->initial_count_load_time);
- qemu_get_be64s(f, &s->next_time);
- return 0;
-}
-
-static void apic_reset(void *opaque)
-{
- APICState *s = opaque;
- apic_init_ipi(s);
-}
-
-static CPUReadMemoryFunc *apic_mem_read[3] = {
- apic_mem_readb,
- apic_mem_readw,
- apic_mem_readl,
-};
-
-static CPUWriteMemoryFunc *apic_mem_write[3] = {
- apic_mem_writeb,
- apic_mem_writew,
- apic_mem_writel,
-};
-
-int apic_init(CPUState *env)
-{
- APICState *s;
-
- if (last_apic_id >= MAX_APICS)
- return -1;
- s = qemu_mallocz(sizeof(APICState));
- if (!s)
- return -1;
- env->apic_state = s;
- apic_init_ipi(s);
- s->id = last_apic_id++;
- s->cpu_env = env;
- s->apicbase = 0xfee00000 |
- (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
-
- /* XXX: mapping more APICs at the same memory location */
- if (apic_io_memory == 0) {
- /* NOTE: the APIC is directly connected to the CPU - it is not
- on the global memory bus. */
- apic_io_memory = cpu_register_io_memory(0, apic_mem_read,
- apic_mem_write, NULL);
- cpu_register_physical_memory(s->apicbase & ~0xfff, 0x1000,
- apic_io_memory);
- }
- s->timer = qemu_new_timer(vm_clock, apic_timer, s);
-
- register_savevm("apic", 0, 1, apic_save, apic_load, s);
- qemu_register_reset(apic_reset, s);
-
- local_apics[s->id] = s;
- return 0;
-}
-
-static void ioapic_service(IOAPICState *s)
-{
- uint8_t i;
- uint8_t trig_mode;
- uint8_t vector;
- uint8_t delivery_mode;
- uint32_t mask;
- uint64_t entry;
- uint8_t dest;
- uint8_t dest_mode;
- uint8_t polarity;
- uint32_t deliver_bitmask[MAX_APIC_WORDS];
-
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- mask = 1 << i;
- if (s->irr & mask) {
- entry = s->ioredtbl[i];
- if (!(entry & APIC_LVT_MASKED)) {
- trig_mode = ((entry >> 15) & 1);
- dest = entry >> 56;
- dest_mode = (entry >> 11) & 1;
- delivery_mode = (entry >> 8) & 7;
- polarity = (entry >> 13) & 1;
- if (trig_mode == APIC_TRIGGER_EDGE)
- s->irr &= ~mask;
- if (delivery_mode == APIC_DM_EXTINT)
- vector = pic_read_irq(isa_pic);
- else
- vector = entry & 0xff;
-
- apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
- apic_bus_deliver(deliver_bitmask, delivery_mode,
- vector, polarity, trig_mode);
- }
- }
- }
-}
-
-void ioapic_set_irq(void *opaque, int vector, int level)
-{
- IOAPICState *s = opaque;
-
- if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
- uint32_t mask = 1 << vector;
- uint64_t entry = s->ioredtbl[vector];
-
- if ((entry >> 15) & 1) {
- /* level triggered */
- if (level) {
- s->irr |= mask;
- ioapic_service(s);
- } else {
- s->irr &= ~mask;
- }
- } else {
- /* edge triggered */
- if (level) {
- s->irr |= mask;
- ioapic_service(s);
- }
- }
- }
-}
-
-static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- IOAPICState *s = opaque;
- int index;
- uint32_t val = 0;
-
- addr &= 0xff;
- if (addr == 0x00) {
- val = s->ioregsel;
- } else if (addr == 0x10) {
- switch (s->ioregsel) {
- case 0x00:
- val = s->id << 24;
- break;
- case 0x01:
- val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
- break;
- case 0x02:
- val = 0;
- break;
- default:
- index = (s->ioregsel - 0x10) >> 1;
- if (index >= 0 && index < IOAPIC_NUM_PINS) {
- if (s->ioregsel & 1)
- val = s->ioredtbl[index] >> 32;
- else
- val = s->ioredtbl[index] & 0xffffffff;
- }
- }
-#ifdef DEBUG_IOAPIC
- printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
-#endif
- }
- return val;
-}
-
-static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- IOAPICState *s = opaque;
- int index;
-
- addr &= 0xff;
- if (addr == 0x00) {
- s->ioregsel = val;
- return;
- } else if (addr == 0x10) {
-#ifdef DEBUG_IOAPIC
- printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
-#endif
- switch (s->ioregsel) {
- case 0x00:
- s->id = (val >> 24) & 0xff;
- return;
- case 0x01:
- case 0x02:
- return;
- default:
- index = (s->ioregsel - 0x10) >> 1;
- if (index >= 0 && index < IOAPIC_NUM_PINS) {
- if (s->ioregsel & 1) {
- s->ioredtbl[index] &= 0xffffffff;
- s->ioredtbl[index] |= (uint64_t)val << 32;
- } else {
- s->ioredtbl[index] &= ~0xffffffffULL;
- s->ioredtbl[index] |= val;
- }
- ioapic_service(s);
- }
- }
- }
-}
-
-static void ioapic_save(QEMUFile *f, void *opaque)
-{
- IOAPICState *s = opaque;
- int i;
-
- qemu_put_8s(f, &s->id);
- qemu_put_8s(f, &s->ioregsel);
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- qemu_put_be64s(f, &s->ioredtbl[i]);
- }
-}
-
-static int ioapic_load(QEMUFile *f, void *opaque, int version_id)
-{
- IOAPICState *s = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_8s(f, &s->id);
- qemu_get_8s(f, &s->ioregsel);
- for (i = 0; i < IOAPIC_NUM_PINS; i++) {
- qemu_get_be64s(f, &s->ioredtbl[i]);
- }
- return 0;
-}
-
-static void ioapic_reset(void *opaque)
-{
- IOAPICState *s = opaque;
- int i;
-
- memset(s, 0, sizeof(*s));
- for(i = 0; i < IOAPIC_NUM_PINS; i++)
- s->ioredtbl[i] = 1 << 16; /* mask LVT */
-}
-
-static CPUReadMemoryFunc *ioapic_mem_read[3] = {
- ioapic_mem_readl,
- ioapic_mem_readl,
- ioapic_mem_readl,
-};
-
-static CPUWriteMemoryFunc *ioapic_mem_write[3] = {
- ioapic_mem_writel,
- ioapic_mem_writel,
- ioapic_mem_writel,
-};
-
-IOAPICState *ioapic_init(void)
-{
- IOAPICState *s;
- int io_memory;
-
- s = qemu_mallocz(sizeof(IOAPICState));
- if (!s)
- return NULL;
- ioapic_reset(s);
- s->id = last_apic_id++;
-
- io_memory = cpu_register_io_memory(0, ioapic_mem_read,
- ioapic_mem_write, s);
- cpu_register_physical_memory(0xfec00000, 0x1000, io_memory);
-
- register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s);
- qemu_register_reset(ioapic_reset, s);
-
- return s;
-}
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index fbc2d67..c228c04 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -11,11 +11,6 @@
#include "arm_pic.h"
/* Stub functions for hardware that doesn't exist. */
-void pic_set_irq(int irq, int level)
-{
- cpu_abort(cpu_single_env, "pic_set_irq");
-}
-
void pic_info(void)
{
}
@@ -24,50 +19,30 @@ void irq_info(void)
{
}
-
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
- arm_pic_handler *p = (arm_pic_handler *)opaque;
- /* Call the real handler. */
- (*p)(opaque, irq, level);
-}
-
-/* Model the IRQ/FIQ CPU interrupt lines as a two input interrupt controller.
- Input 0 is IRQ and input 1 is FIQ. */
-typedef struct
-{
- arm_pic_handler handler;
- CPUState *cpu_env;
-} arm_pic_cpu_state;
-
+/* Input 0 is IRQ and input 1 is FIQ */
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
{
- arm_pic_cpu_state *s = (arm_pic_cpu_state *)opaque;
+ CPUState *env = (CPUState *)opaque;
switch (irq) {
case ARM_PIC_CPU_IRQ:
if (level)
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
else
- cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
break;
case ARM_PIC_CPU_FIQ:
if (level)
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+ cpu_interrupt(env, CPU_INTERRUPT_FIQ);
else
- cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+ cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
break;
default:
- cpu_abort(s->cpu_env, "arm_pic_cpu_handler: Bad interrput line %d\n",
+ cpu_abort(env, "arm_pic_cpu_handler: Bad interrput line %d\n",
irq);
}
}
-void *arm_pic_init_cpu(CPUState *env)
+qemu_irq *arm_pic_init_cpu(CPUState *env)
{
- arm_pic_cpu_state *s;
-
- s = (arm_pic_cpu_state *)malloc(sizeof(arm_pic_cpu_state));
- s->handler = arm_pic_cpu_handler;
- s->cpu_env = env;
- return s;
+ return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2);
}
diff --git a/hw/arm_pic.h b/hw/arm_pic.h
index b299149..7886bcf 100644
--- a/hw/arm_pic.h
+++ b/hw/arm_pic.h
@@ -14,14 +14,12 @@
#ifndef ARM_INTERRUPT_H
#define ARM_INTERRUPT_H 1
-/* The first element of an individual PIC state structures should
- be a pointer to the handler routine. */
-typedef void (*arm_pic_handler)(void *opaque, int irq, int level);
+#include "irq.h"
/* The CPU is also modeled as an interrupt controller. */
#define ARM_PIC_CPU_IRQ 0
#define ARM_PIC_CPU_FIQ 1
-void *arm_pic_init_cpu(CPUState *env);
+qemu_irq *arm_pic_init_cpu(CPUState *env);
#endif /* !ARM_INTERRUPT_H */
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
deleted file mode 100644
index a97d73e..0000000
--- a/hw/arm_timer.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * ARM PrimeCell Timer modules.
- *
- * Copyright (c) 2005-2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GPL.
- */
-
-#include "vl.h"
-#include "arm_pic.h"
-
-/* Common timer implementation. */
-
-#define TIMER_CTRL_ONESHOT (1 << 0)
-#define TIMER_CTRL_32BIT (1 << 1)
-#define TIMER_CTRL_DIV1 (0 << 2)
-#define TIMER_CTRL_DIV16 (1 << 2)
-#define TIMER_CTRL_DIV256 (2 << 2)
-#define TIMER_CTRL_IE (1 << 5)
-#define TIMER_CTRL_PERIODIC (1 << 6)
-#define TIMER_CTRL_ENABLE (1 << 7)
-
-typedef struct {
- int64_t next_time;
- int64_t expires;
- int64_t loaded;
- QEMUTimer *timer;
- uint32_t control;
- uint32_t count;
- uint32_t limit;
- int raw_freq;
- int freq;
- int int_level;
- void *pic;
- int irq;
-} arm_timer_state;
-
-/* Calculate the new expiry time of the given timer. */
-
-static void arm_timer_reload(arm_timer_state *s)
-{
- int64_t delay;
-
- s->loaded = s->expires;
- delay = muldiv64(s->count, ticks_per_sec, s->freq);
- if (delay == 0)
- delay = 1;
- s->expires += delay;
-}
-
-/* Check all active timers, and schedule the next timer interrupt. */
-
-static void arm_timer_update(arm_timer_state *s, int64_t now)
-{
- int64_t next;
-
- /* Ignore disabled timers. */
- if ((s->control & TIMER_CTRL_ENABLE) == 0)
- return;
- /* Ignore expired one-shot timers. */
- if (s->count == 0 && (s->control & TIMER_CTRL_ONESHOT))
- return;
- if (s->expires - now <= 0) {
- /* Timer has expired. */
- s->int_level = 1;
- if (s->control & TIMER_CTRL_ONESHOT) {
- /* One-shot. */
- s->count = 0;
- } else {
- if ((s->control & TIMER_CTRL_PERIODIC) == 0) {
- /* Free running. */
- if (s->control & TIMER_CTRL_32BIT)
- s->count = 0xffffffff;
- else
- s->count = 0xffff;
- } else {
- /* Periodic. */
- s->count = s->limit;
- }
- }
- }
- while (s->expires - now <= 0) {
- arm_timer_reload(s);
- }
- /* Update interrupts. */
- if (s->int_level && (s->control & TIMER_CTRL_IE)) {
- pic_set_irq_new(s->pic, s->irq, 1);
- } else {
- pic_set_irq_new(s->pic, s->irq, 0);
- }
-
- next = now;
- if (next - s->expires < 0)
- next = s->expires;
-
- /* Schedule the next timer interrupt. */
- if (next == now) {
- qemu_del_timer(s->timer);
- s->next_time = 0;
- } else if (next != s->next_time) {
- qemu_mod_timer(s->timer, next);
- s->next_time = next;
- }
-}
-
-/* Return the current value of the timer. */
-static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
-{
- int64_t elapsed;
- int64_t period;
-
- if (s->count == 0)
- return 0;
- if ((s->control & TIMER_CTRL_ENABLE) == 0)
- return s->count;
- elapsed = now - s->loaded;
- period = s->expires - s->loaded;
- /* If the timer should have expired then return 0. This can happen
- when the host timer signal doesnt occur immediately. It's better to
- have a timer appear to sit at zero for a while than have it wrap
- around before the guest interrupt is raised. */
- /* ??? Could we trigger the interrupt here? */
- if (elapsed > period)
- return 0;
- /* We need to calculate count * elapsed / period without overfowing.
- Scale both elapsed and period so they fit in a 32-bit int. */
- while (period != (int32_t)period) {
- period >>= 1;
- elapsed >>= 1;
- }
- return ((uint64_t)s->count * (uint64_t)(int32_t)elapsed)
- / (int32_t)period;
-}
-
-uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
-
- switch (offset >> 2) {
- case 0: /* TimerLoad */
- case 6: /* TimerBGLoad */
- return s->limit;
- case 1: /* TimerValue */
- return arm_timer_getcount(s, qemu_get_clock(vm_clock));
- case 2: /* TimerControl */
- return s->control;
- case 4: /* TimerRIS */
- return s->int_level;
- case 5: /* TimerMIS */
- if ((s->control & TIMER_CTRL_IE) == 0)
- return 0;
- return s->int_level;
- default:
- cpu_abort (cpu_single_env, "arm_timer_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void arm_timer_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
- int64_t now;
-
- now = qemu_get_clock(vm_clock);
- switch (offset >> 2) {
- case 0: /* TimerLoad */
- s->limit = value;
- s->count = value;
- s->expires = now;
- arm_timer_reload(s);
- break;
- case 1: /* TimerValue */
- /* ??? Linux seems to want to write to this readonly register.
- Ignore it. */
- break;
- case 2: /* TimerControl */
- if (s->control & TIMER_CTRL_ENABLE) {
- /* Pause the timer if it is running. This may cause some
- inaccuracy dure to rounding, but avoids a whole lot of other
- messyness. */
- s->count = arm_timer_getcount(s, now);
- }
- s->control = value;
- s->freq = s->raw_freq;
- /* ??? Need to recalculate expiry time after changing divisor. */
- switch ((value >> 2) & 3) {
- case 1: s->freq >>= 4; break;
- case 2: s->freq >>= 8; break;
- }
- if (s->control & TIMER_CTRL_ENABLE) {
- /* Restart the timer if still enabled. */
- s->expires = now;
- arm_timer_reload(s);
- }
- break;
- case 3: /* TimerIntClr */
- s->int_level = 0;
- break;
- case 6: /* TimerBGLoad */
- s->limit = value;
- break;
- default:
- cpu_abort (cpu_single_env, "arm_timer_write: Bad offset %x\n", offset);
- }
- arm_timer_update(s, now);
-}
-
-static void arm_timer_tick(void *opaque)
-{
- int64_t now;
-
- now = qemu_get_clock(vm_clock);
- arm_timer_update((arm_timer_state *)opaque, now);
-}
-
-static void *arm_timer_init(uint32_t freq, void *pic, int irq)
-{
- arm_timer_state *s;
-
- s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
- s->pic = pic;
- s->irq = irq;
- s->raw_freq = s->freq = 1000000;
- s->control = TIMER_CTRL_IE;
- s->count = 0xffffffff;
-
- s->timer = qemu_new_timer(vm_clock, arm_timer_tick, s);
- /* ??? Save/restore. */
- return s;
-}
-
-/* ARM PrimeCell SP804 dual timer module.
- Docs for this device don't seem to be publicly available. This
- implementation is based on gueswork, the linux kernel sources and the
- Integrator/CP timer modules. */
-
-typedef struct {
- /* Include a pseudo-PIC device to merge the two interrupt sources. */
- arm_pic_handler handler;
- void *timer[2];
- int level[2];
- uint32_t base;
- /* The output PIC device. */
- void *pic;
- int irq;
-} sp804_state;
-
-static void sp804_set_irq(void *opaque, int irq, int level)
-{
- sp804_state *s = (sp804_state *)opaque;
-
- s->level[irq] = level;
- pic_set_irq_new(s->pic, s->irq, s->level[0] || s->level[1]);
-}
-
-static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
-{
- sp804_state *s = (sp804_state *)opaque;
-
- /* ??? Don't know the PrimeCell ID for this device. */
- offset -= s->base;
- if (offset < 0x20) {
- return arm_timer_read(s->timer[0], offset);
- } else {
- return arm_timer_read(s->timer[1], offset - 0x20);
- }
-}
-
-static void sp804_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- sp804_state *s = (sp804_state *)opaque;
-
- offset -= s->base;
- if (offset < 0x20) {
- arm_timer_write(s->timer[0], offset, value);
- } else {
- arm_timer_write(s->timer[1], offset - 0x20, value);
- }
-}
-
-static CPUReadMemoryFunc *sp804_readfn[] = {
- sp804_read,
- sp804_read,
- sp804_read
-};
-
-static CPUWriteMemoryFunc *sp804_writefn[] = {
- sp804_write,
- sp804_write,
- sp804_write
-};
-
-void sp804_init(uint32_t base, void *pic, int irq)
-{
- int iomemtype;
- sp804_state *s;
-
- s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
- s->handler = sp804_set_irq;
- s->base = base;
- s->pic = pic;
- s->irq = irq;
- /* ??? The timers are actually configurable between 32kHz and 1MHz, but
- we don't implement that. */
- s->timer[0] = arm_timer_init(1000000, s, 0);
- s->timer[1] = arm_timer_init(1000000, s, 1);
- iomemtype = cpu_register_io_memory(0, sp804_readfn,
- sp804_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- /* ??? Save/restore. */
-}
-
-
-/* Integrator/CP timer module. */
-
-typedef struct {
- void *timer[3];
- uint32_t base;
-} icp_pit_state;
-
-static uint32_t icp_pit_read(void *opaque, target_phys_addr_t offset)
-{
- icp_pit_state *s = (icp_pit_state *)opaque;
- int n;
-
- /* ??? Don't know the PrimeCell ID for this device. */
- offset -= s->base;
- n = offset >> 8;
- if (n > 3)
- cpu_abort(cpu_single_env, "sp804_read: Bad timer %d\n", n);
-
- return arm_timer_read(s->timer[n], offset & 0xff);
-}
-
-static void icp_pit_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- icp_pit_state *s = (icp_pit_state *)opaque;
- int n;
-
- offset -= s->base;
- n = offset >> 8;
- if (n > 3)
- cpu_abort(cpu_single_env, "sp804_write: Bad timer %d\n", n);
-
- arm_timer_write(s->timer[n], offset & 0xff, value);
-}
-
-
-static CPUReadMemoryFunc *icp_pit_readfn[] = {
- icp_pit_read,
- icp_pit_read,
- icp_pit_read
-};
-
-static CPUWriteMemoryFunc *icp_pit_writefn[] = {
- icp_pit_write,
- icp_pit_write,
- icp_pit_write
-};
-
-void icp_pit_init(uint32_t base, void *pic, int irq)
-{
- int iomemtype;
- icp_pit_state *s;
-
- s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
- s->base = base;
- /* Timer 0 runs at the system clock speed (40MHz). */
- s->timer[0] = arm_timer_init(40000000, pic, irq);
- /* The other two timers run at 1MHz. */
- s->timer[1] = arm_timer_init(1000000, pic, irq + 1);
- s->timer[2] = arm_timer_init(1000000, pic, irq + 2);
-
- iomemtype = cpu_register_io_memory(0, icp_pit_readfn,
- icp_pit_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- /* ??? Save/restore. */
-}
-
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
deleted file mode 100644
index d186d79..0000000
--- a/hw/cirrus_vga.c
+++ /dev/null
@@ -1,3193 +0,0 @@
-/*
- * QEMU Cirrus CLGD 54xx VGA Emulator.
- *
- * Copyright (c) 2004 Fabrice Bellard
- * Copyright (c) 2004 Makoto Suzuki (suzu)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-/*
- * Reference: Finn Thogersons' VGADOC4b
- * available at http://home.worldonline.dk/~finth/
- */
-#include "vl.h"
-#include "vga_int.h"
-
-/*
- * TODO:
- * - destination write mask support not complete (bits 5..7)
- * - optimize linear mappings
- * - optimize bitblt functions
- */
-
-//#define DEBUG_CIRRUS
-//#define DEBUG_BITBLT
-
-/***************************************
- *
- * definitions
- *
- ***************************************/
-
-#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
-
-// ID
-#define CIRRUS_ID_CLGD5422 (0x23<<2)
-#define CIRRUS_ID_CLGD5426 (0x24<<2)
-#define CIRRUS_ID_CLGD5424 (0x25<<2)
-#define CIRRUS_ID_CLGD5428 (0x26<<2)
-#define CIRRUS_ID_CLGD5430 (0x28<<2)
-#define CIRRUS_ID_CLGD5434 (0x2A<<2)
-#define CIRRUS_ID_CLGD5436 (0x2B<<2)
-#define CIRRUS_ID_CLGD5446 (0x2E<<2)
-
-// sequencer 0x07
-#define CIRRUS_SR7_BPP_VGA 0x00
-#define CIRRUS_SR7_BPP_SVGA 0x01
-#define CIRRUS_SR7_BPP_MASK 0x0e
-#define CIRRUS_SR7_BPP_8 0x00
-#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02
-#define CIRRUS_SR7_BPP_24 0x04
-#define CIRRUS_SR7_BPP_16 0x06
-#define CIRRUS_SR7_BPP_32 0x08
-#define CIRRUS_SR7_ISAADDR_MASK 0xe0
-
-// sequencer 0x0f
-#define CIRRUS_MEMSIZE_512k 0x08
-#define CIRRUS_MEMSIZE_1M 0x10
-#define CIRRUS_MEMSIZE_2M 0x18
-#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
-
-// sequencer 0x12
-#define CIRRUS_CURSOR_SHOW 0x01
-#define CIRRUS_CURSOR_HIDDENPEL 0x02
-#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear
-
-// sequencer 0x17
-#define CIRRUS_BUSTYPE_VLBFAST 0x10
-#define CIRRUS_BUSTYPE_PCI 0x20
-#define CIRRUS_BUSTYPE_VLBSLOW 0x30
-#define CIRRUS_BUSTYPE_ISA 0x38
-#define CIRRUS_MMIO_ENABLE 0x04
-#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.
-#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
-
-// control 0x0b
-#define CIRRUS_BANKING_DUAL 0x01
-#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k
-
-// control 0x30
-#define CIRRUS_BLTMODE_BACKWARDS 0x01
-#define CIRRUS_BLTMODE_MEMSYSDEST 0x02
-#define CIRRUS_BLTMODE_MEMSYSSRC 0x04
-#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
-#define CIRRUS_BLTMODE_PATTERNCOPY 0x40
-#define CIRRUS_BLTMODE_COLOREXPAND 0x80
-#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
-#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
-#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
-#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
-#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
-
-// control 0x31
-#define CIRRUS_BLT_BUSY 0x01
-#define CIRRUS_BLT_START 0x02
-#define CIRRUS_BLT_RESET 0x04
-#define CIRRUS_BLT_FIFOUSED 0x10
-#define CIRRUS_BLT_AUTOSTART 0x80
-
-// control 0x32
-#define CIRRUS_ROP_0 0x00
-#define CIRRUS_ROP_SRC_AND_DST 0x05
-#define CIRRUS_ROP_NOP 0x06
-#define CIRRUS_ROP_SRC_AND_NOTDST 0x09
-#define CIRRUS_ROP_NOTDST 0x0b
-#define CIRRUS_ROP_SRC 0x0d
-#define CIRRUS_ROP_1 0x0e
-#define CIRRUS_ROP_NOTSRC_AND_DST 0x50
-#define CIRRUS_ROP_SRC_XOR_DST 0x59
-#define CIRRUS_ROP_SRC_OR_DST 0x6d
-#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
-#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
-#define CIRRUS_ROP_SRC_OR_NOTDST 0xad
-#define CIRRUS_ROP_NOTSRC 0xd0
-#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
-#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
-
-#define CIRRUS_ROP_NOP_INDEX 2
-#define CIRRUS_ROP_SRC_INDEX 5
-
-// control 0x33
-#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04
-#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02
-#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
-
-// memory-mapped IO
-#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword
-#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword
-#define CIRRUS_MMIO_BLTWIDTH 0x08 // word
-#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word
-#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word
-#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word
-#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword
-#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword
-#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte
-#define CIRRUS_MMIO_BLTMODE 0x18 // byte
-#define CIRRUS_MMIO_BLTROP 0x1a // byte
-#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte
-#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word?
-#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word?
-#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word
-#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word
-#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word
-#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word
-#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte
-#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte
-#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte
-#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte
-#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word
-#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word
-#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word
-#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word
-#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte
-#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte
-#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte
-
-// PCI 0x00: vendor, 0x02: device
-#define PCI_VENDOR_CIRRUS 0x1013
-#define PCI_DEVICE_CLGD5462 0x00d0
-#define PCI_DEVICE_CLGD5465 0x00d6
-
-// PCI 0x04: command(word), 0x06(word): status
-#define PCI_COMMAND_IOACCESS 0x0001
-#define PCI_COMMAND_MEMACCESS 0x0002
-#define PCI_COMMAND_BUSMASTER 0x0004
-#define PCI_COMMAND_SPECIALCYCLE 0x0008
-#define PCI_COMMAND_MEMWRITEINVALID 0x0010
-#define PCI_COMMAND_PALETTESNOOPING 0x0020
-#define PCI_COMMAND_PARITYDETECTION 0x0040
-#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080
-#define PCI_COMMAND_SERR 0x0100
-#define PCI_COMMAND_BACKTOBACKTRANS 0x0200
-// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
-#define PCI_CLASS_BASE_DISPLAY 0x03
-// PCI 0x08, 0x00ff0000
-#define PCI_CLASS_SUB_VGA 0x00
-// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
-#define PCI_CLASS_HEADERTYPE_00h 0x00
-// 0x10-0x3f (headertype 00h)
-// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
-// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
-#define PCI_MAP_MEM 0x0
-#define PCI_MAP_IO 0x1
-#define PCI_MAP_MEM_ADDR_MASK (~0xf)
-#define PCI_MAP_IO_ADDR_MASK (~0x3)
-#define PCI_MAP_MEMFLAGS_32BIT 0x0
-#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1
-#define PCI_MAP_MEMFLAGS_64BIT 0x4
-#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8
-// PCI 0x28: cardbus CIS pointer
-// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
-// PCI 0x30: expansion ROM base address
-#define PCI_ROMBIOS_ENABLED 0x1
-// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
-// PCI 0x38: reserved
-// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
-
-#define CIRRUS_PNPMMIO_SIZE 0x1000
-
-
-/* I/O and memory hook */
-#define CIRRUS_HOOK_NOT_HANDLED 0
-#define CIRRUS_HOOK_HANDLED 1
-
-struct CirrusVGAState;
-typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
- uint8_t * dst, const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight);
-typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
- uint8_t *dst, int dst_pitch, int width, int height);
-
-typedef struct CirrusVGAState {
- VGA_STATE_COMMON
-
- int cirrus_linear_io_addr;
- int cirrus_linear_bitblt_io_addr;
- int cirrus_mmio_io_addr;
- uint32_t cirrus_addr_mask;
- uint32_t linear_mmio_mask;
- uint8_t cirrus_shadow_gr0;
- uint8_t cirrus_shadow_gr1;
- uint8_t cirrus_hidden_dac_lockindex;
- uint8_t cirrus_hidden_dac_data;
- uint32_t cirrus_bank_base[2];
- uint32_t cirrus_bank_limit[2];
- uint8_t cirrus_hidden_palette[48];
- uint32_t hw_cursor_x;
- uint32_t hw_cursor_y;
- int cirrus_blt_pixelwidth;
- int cirrus_blt_width;
- int cirrus_blt_height;
- int cirrus_blt_dstpitch;
- int cirrus_blt_srcpitch;
- uint32_t cirrus_blt_fgcol;
- uint32_t cirrus_blt_bgcol;
- uint32_t cirrus_blt_dstaddr;
- uint32_t cirrus_blt_srcaddr;
- uint8_t cirrus_blt_mode;
- uint8_t cirrus_blt_modeext;
- cirrus_bitblt_rop_t cirrus_rop;
-#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */
- uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
- uint8_t *cirrus_srcptr;
- uint8_t *cirrus_srcptr_end;
- uint32_t cirrus_srccounter;
- /* hwcursor display state */
- int last_hw_cursor_size;
- int last_hw_cursor_x;
- int last_hw_cursor_y;
- int last_hw_cursor_y_start;
- int last_hw_cursor_y_end;
- int real_vram_size; /* XXX: suppress that */
- CPUWriteMemoryFunc **cirrus_linear_write;
-} CirrusVGAState;
-
-typedef struct PCICirrusVGAState {
- PCIDevice dev;
- CirrusVGAState cirrus_vga;
-} PCICirrusVGAState;
-
-static uint8_t rop_to_index[256];
-
-/***************************************
- *
- * prototypes.
- *
- ***************************************/
-
-
-static void cirrus_bitblt_reset(CirrusVGAState *s);
-static void cirrus_update_memory_access(CirrusVGAState *s);
-
-/***************************************
- *
- * raster operations
- *
- ***************************************/
-
-static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
- int bltwidth,int bltheight)
-{
-}
-
-static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
- uint8_t *dst,
- int dstpitch, int bltwidth,int bltheight)
-{
-}
-
-#define ROP_NAME 0
-#define ROP_OP(d, s) d = 0
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME src_and_dst
-#define ROP_OP(d, s) d = (s) & (d)
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME src_and_notdst
-#define ROP_OP(d, s) d = (s) & (~(d))
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME notdst
-#define ROP_OP(d, s) d = ~(d)
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME src
-#define ROP_OP(d, s) d = s
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME 1
-#define ROP_OP(d, s) d = ~0
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME notsrc_and_dst
-#define ROP_OP(d, s) d = (~(s)) & (d)
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME src_xor_dst
-#define ROP_OP(d, s) d = (s) ^ (d)
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME src_or_dst
-#define ROP_OP(d, s) d = (s) | (d)
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME notsrc_or_notdst
-#define ROP_OP(d, s) d = (~(s)) | (~(d))
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME src_notxor_dst
-#define ROP_OP(d, s) d = ~((s) ^ (d))
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME src_or_notdst
-#define ROP_OP(d, s) d = (s) | (~(d))
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME notsrc
-#define ROP_OP(d, s) d = (~(s))
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME notsrc_or_dst
-#define ROP_OP(d, s) d = (~(s)) | (d)
-#include "cirrus_vga_rop.h"
-
-#define ROP_NAME notsrc_and_notdst
-#define ROP_OP(d, s) d = (~(s)) & (~(d))
-#include "cirrus_vga_rop.h"
-
-static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
- cirrus_bitblt_rop_fwd_0,
- cirrus_bitblt_rop_fwd_src_and_dst,
- cirrus_bitblt_rop_nop,
- cirrus_bitblt_rop_fwd_src_and_notdst,
- cirrus_bitblt_rop_fwd_notdst,
- cirrus_bitblt_rop_fwd_src,
- cirrus_bitblt_rop_fwd_1,
- cirrus_bitblt_rop_fwd_notsrc_and_dst,
- cirrus_bitblt_rop_fwd_src_xor_dst,
- cirrus_bitblt_rop_fwd_src_or_dst,
- cirrus_bitblt_rop_fwd_notsrc_or_notdst,
- cirrus_bitblt_rop_fwd_src_notxor_dst,
- cirrus_bitblt_rop_fwd_src_or_notdst,
- cirrus_bitblt_rop_fwd_notsrc,
- cirrus_bitblt_rop_fwd_notsrc_or_dst,
- cirrus_bitblt_rop_fwd_notsrc_and_notdst,
-};
-
-static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = {
- cirrus_bitblt_rop_bkwd_0,
- cirrus_bitblt_rop_bkwd_src_and_dst,
- cirrus_bitblt_rop_nop,
- cirrus_bitblt_rop_bkwd_src_and_notdst,
- cirrus_bitblt_rop_bkwd_notdst,
- cirrus_bitblt_rop_bkwd_src,
- cirrus_bitblt_rop_bkwd_1,
- cirrus_bitblt_rop_bkwd_notsrc_and_dst,
- cirrus_bitblt_rop_bkwd_src_xor_dst,
- cirrus_bitblt_rop_bkwd_src_or_dst,
- cirrus_bitblt_rop_bkwd_notsrc_or_notdst,
- cirrus_bitblt_rop_bkwd_src_notxor_dst,
- cirrus_bitblt_rop_bkwd_src_or_notdst,
- cirrus_bitblt_rop_bkwd_notsrc,
- cirrus_bitblt_rop_bkwd_notsrc_or_dst,
- cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
-};
-
-#define ROP2(name) {\
- name ## _8,\
- name ## _16,\
- name ## _24,\
- name ## _32,\
- }
-
-#define ROP_NOP2(func) {\
- func,\
- func,\
- func,\
- func,\
- }
-
-static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = {
- ROP2(cirrus_patternfill_0),
- ROP2(cirrus_patternfill_src_and_dst),
- ROP_NOP2(cirrus_bitblt_rop_nop),
- ROP2(cirrus_patternfill_src_and_notdst),
- ROP2(cirrus_patternfill_notdst),
- ROP2(cirrus_patternfill_src),
- ROP2(cirrus_patternfill_1),
- ROP2(cirrus_patternfill_notsrc_and_dst),
- ROP2(cirrus_patternfill_src_xor_dst),
- ROP2(cirrus_patternfill_src_or_dst),
- ROP2(cirrus_patternfill_notsrc_or_notdst),
- ROP2(cirrus_patternfill_src_notxor_dst),
- ROP2(cirrus_patternfill_src_or_notdst),
- ROP2(cirrus_patternfill_notsrc),
- ROP2(cirrus_patternfill_notsrc_or_dst),
- ROP2(cirrus_patternfill_notsrc_and_notdst),
-};
-
-static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
- ROP2(cirrus_colorexpand_transp_0),
- ROP2(cirrus_colorexpand_transp_src_and_dst),
- ROP_NOP2(cirrus_bitblt_rop_nop),
- ROP2(cirrus_colorexpand_transp_src_and_notdst),
- ROP2(cirrus_colorexpand_transp_notdst),
- ROP2(cirrus_colorexpand_transp_src),
- ROP2(cirrus_colorexpand_transp_1),
- ROP2(cirrus_colorexpand_transp_notsrc_and_dst),
- ROP2(cirrus_colorexpand_transp_src_xor_dst),
- ROP2(cirrus_colorexpand_transp_src_or_dst),
- ROP2(cirrus_colorexpand_transp_notsrc_or_notdst),
- ROP2(cirrus_colorexpand_transp_src_notxor_dst),
- ROP2(cirrus_colorexpand_transp_src_or_notdst),
- ROP2(cirrus_colorexpand_transp_notsrc),
- ROP2(cirrus_colorexpand_transp_notsrc_or_dst),
- ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
-};
-
-static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
- ROP2(cirrus_colorexpand_0),
- ROP2(cirrus_colorexpand_src_and_dst),
- ROP_NOP2(cirrus_bitblt_rop_nop),
- ROP2(cirrus_colorexpand_src_and_notdst),
- ROP2(cirrus_colorexpand_notdst),
- ROP2(cirrus_colorexpand_src),
- ROP2(cirrus_colorexpand_1),
- ROP2(cirrus_colorexpand_notsrc_and_dst),
- ROP2(cirrus_colorexpand_src_xor_dst),
- ROP2(cirrus_colorexpand_src_or_dst),
- ROP2(cirrus_colorexpand_notsrc_or_notdst),
- ROP2(cirrus_colorexpand_src_notxor_dst),
- ROP2(cirrus_colorexpand_src_or_notdst),
- ROP2(cirrus_colorexpand_notsrc),
- ROP2(cirrus_colorexpand_notsrc_or_dst),
- ROP2(cirrus_colorexpand_notsrc_and_notdst),
-};
-
-static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = {
- ROP2(cirrus_colorexpand_pattern_transp_0),
- ROP2(cirrus_colorexpand_pattern_transp_src_and_dst),
- ROP_NOP2(cirrus_bitblt_rop_nop),
- ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst),
- ROP2(cirrus_colorexpand_pattern_transp_notdst),
- ROP2(cirrus_colorexpand_pattern_transp_src),
- ROP2(cirrus_colorexpand_pattern_transp_1),
- ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst),
- ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst),
- ROP2(cirrus_colorexpand_pattern_transp_src_or_dst),
- ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst),
- ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst),
- ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst),
- ROP2(cirrus_colorexpand_pattern_transp_notsrc),
- ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst),
- ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),
-};
-
-static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = {
- ROP2(cirrus_colorexpand_pattern_0),
- ROP2(cirrus_colorexpand_pattern_src_and_dst),
- ROP_NOP2(cirrus_bitblt_rop_nop),
- ROP2(cirrus_colorexpand_pattern_src_and_notdst),
- ROP2(cirrus_colorexpand_pattern_notdst),
- ROP2(cirrus_colorexpand_pattern_src),
- ROP2(cirrus_colorexpand_pattern_1),
- ROP2(cirrus_colorexpand_pattern_notsrc_and_dst),
- ROP2(cirrus_colorexpand_pattern_src_xor_dst),
- ROP2(cirrus_colorexpand_pattern_src_or_dst),
- ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst),
- ROP2(cirrus_colorexpand_pattern_src_notxor_dst),
- ROP2(cirrus_colorexpand_pattern_src_or_notdst),
- ROP2(cirrus_colorexpand_pattern_notsrc),
- ROP2(cirrus_colorexpand_pattern_notsrc_or_dst),
- ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),
-};
-
-static const cirrus_fill_t cirrus_fill[16][4] = {
- ROP2(cirrus_fill_0),
- ROP2(cirrus_fill_src_and_dst),
- ROP_NOP2(cirrus_bitblt_fill_nop),
- ROP2(cirrus_fill_src_and_notdst),
- ROP2(cirrus_fill_notdst),
- ROP2(cirrus_fill_src),
- ROP2(cirrus_fill_1),
- ROP2(cirrus_fill_notsrc_and_dst),
- ROP2(cirrus_fill_src_xor_dst),
- ROP2(cirrus_fill_src_or_dst),
- ROP2(cirrus_fill_notsrc_or_notdst),
- ROP2(cirrus_fill_src_notxor_dst),
- ROP2(cirrus_fill_src_or_notdst),
- ROP2(cirrus_fill_notsrc),
- ROP2(cirrus_fill_notsrc_or_dst),
- ROP2(cirrus_fill_notsrc_and_notdst),
-};
-
-static inline void cirrus_bitblt_fgcol(CirrusVGAState *s)
-{
- unsigned int color;
- switch (s->cirrus_blt_pixelwidth) {
- case 1:
- s->cirrus_blt_fgcol = s->cirrus_shadow_gr1;
- break;
- case 2:
- color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8);
- s->cirrus_blt_fgcol = le16_to_cpu(color);
- break;
- case 3:
- s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 |
- (s->gr[0x11] << 8) | (s->gr[0x13] << 16);
- break;
- default:
- case 4:
- color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) |
- (s->gr[0x13] << 16) | (s->gr[0x15] << 24);
- s->cirrus_blt_fgcol = le32_to_cpu(color);
- break;
- }
-}
-
-static inline void cirrus_bitblt_bgcol(CirrusVGAState *s)
-{
- unsigned int color;
- switch (s->cirrus_blt_pixelwidth) {
- case 1:
- s->cirrus_blt_bgcol = s->cirrus_shadow_gr0;
- break;
- case 2:
- color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8);
- s->cirrus_blt_bgcol = le16_to_cpu(color);
- break;
- case 3:
- s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 |
- (s->gr[0x10] << 8) | (s->gr[0x12] << 16);
- break;
- default:
- case 4:
- color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) |
- (s->gr[0x12] << 16) | (s->gr[0x14] << 24);
- s->cirrus_blt_bgcol = le32_to_cpu(color);
- break;
- }
-}
-
-static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
- int off_pitch, int bytesperline,
- int lines)
-{
- int y;
- int off_cur;
- int off_cur_end;
-
- for (y = 0; y < lines; y++) {
- off_cur = off_begin;
- off_cur_end = off_cur + bytesperline;
- off_cur &= TARGET_PAGE_MASK;
- while (off_cur < off_cur_end) {
- cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
- off_cur += TARGET_PAGE_SIZE;
- }
- off_begin += off_pitch;
- }
-}
-
-static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
- const uint8_t * src)
-{
- uint8_t *dst;
-
- dst = s->vram_ptr + s->cirrus_blt_dstaddr;
- (*s->cirrus_rop) (s, dst, src,
- s->cirrus_blt_dstpitch, 0,
- s->cirrus_blt_width, s->cirrus_blt_height);
- cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
- s->cirrus_blt_dstpitch, s->cirrus_blt_width,
- s->cirrus_blt_height);
- return 1;
-}
-
-/* fill */
-
-static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
-{
- cirrus_fill_t rop_func;
-
- rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr,
- s->cirrus_blt_dstpitch,
- s->cirrus_blt_width, s->cirrus_blt_height);
- cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
- s->cirrus_blt_dstpitch, s->cirrus_blt_width,
- s->cirrus_blt_height);
- cirrus_bitblt_reset(s);
- return 1;
-}
-
-/***************************************
- *
- * bitblt (video-to-video)
- *
- ***************************************/
-
-static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
-{
- return cirrus_bitblt_common_patterncopy(s,
- s->vram_ptr +
- (s->cirrus_blt_srcaddr & ~7));
-}
-
-static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
-{
- int sx, sy;
- int dx, dy;
- int width, height;
- int depth;
- int notify = 0;
-
- depth = s->get_bpp((VGAState *)s) / 8;
- s->get_resolution((VGAState *)s, &width, &height);
-
- /* extra x, y */
- sx = (src % (width * depth)) / depth;
- sy = (src / (width * depth));
- dx = (dst % (width *depth)) / depth;
- dy = (dst / (width * depth));
-
- /* normalize width */
- w /= depth;
-
- /* if we're doing a backward copy, we have to adjust
- our x/y to be the upper left corner (instead of the lower
- right corner) */
- if (s->cirrus_blt_dstpitch < 0) {
- sx -= (s->cirrus_blt_width / depth) - 1;
- dx -= (s->cirrus_blt_width / depth) - 1;
- sy -= s->cirrus_blt_height - 1;
- dy -= s->cirrus_blt_height - 1;
- }
-
- /* are we in the visible portion of memory? */
- if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
- (sx + w) <= width && (sy + h) <= height &&
- (dx + w) <= width && (dy + h) <= height) {
- notify = 1;
- }
-
- /* make to sure only copy if it's a plain copy ROP */
- if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
- *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
- notify = 0;
-
- /* we have to flush all pending changes so that the copy
- is generated at the appropriate moment in time */
- if (notify)
- vga_hw_update();
-
- (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
- s->vram_ptr + s->cirrus_blt_srcaddr,
- s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
- s->cirrus_blt_width, s->cirrus_blt_height);
-
- if (notify)
- s->ds->dpy_copy(s->ds,
- sx, sy, dx, dy,
- s->cirrus_blt_width / depth,
- s->cirrus_blt_height);
-
- /* we don't have to notify the display that this portion has
- changed since dpy_copy implies this */
-
- if (!notify)
- cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
- s->cirrus_blt_dstpitch, s->cirrus_blt_width,
- s->cirrus_blt_height);
-}
-
-static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
-{
- if (s->ds->dpy_copy) {
- cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
- s->cirrus_blt_srcaddr - s->start_addr,
- s->cirrus_blt_width, s->cirrus_blt_height);
- } else {
- (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
- s->vram_ptr + s->cirrus_blt_srcaddr,
- s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
- s->cirrus_blt_width, s->cirrus_blt_height);
-
- cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
- s->cirrus_blt_dstpitch, s->cirrus_blt_width,
- s->cirrus_blt_height);
- }
-
- return 1;
-}
-
-/***************************************
- *
- * bitblt (cpu-to-video)
- *
- ***************************************/
-
-static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
-{
- int copy_count;
- uint8_t *end_ptr;
-
- if (s->cirrus_srccounter > 0) {
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
- cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
- the_end:
- s->cirrus_srccounter = 0;
- cirrus_bitblt_reset(s);
- } else {
- /* at least one scan line */
- do {
- (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
- s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
- cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
- s->cirrus_blt_width, 1);
- s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
- s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
- if (s->cirrus_srccounter <= 0)
- goto the_end;
- /* more bytes than needed can be transfered because of
- word alignment, so we keep them for the next line */
- /* XXX: keep alignment to speed up transfer */
- end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
- copy_count = s->cirrus_srcptr_end - end_ptr;
- memmove(s->cirrus_bltbuf, end_ptr, copy_count);
- s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
- s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
- } while (s->cirrus_srcptr >= s->cirrus_srcptr_end);
- }
- }
-}
-
-/***************************************
- *
- * bitblt wrapper
- *
- ***************************************/
-
-static void cirrus_bitblt_reset(CirrusVGAState * s)
-{
- s->gr[0x31] &=
- ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
- s->cirrus_srcptr = &s->cirrus_bltbuf[0];
- s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
- s->cirrus_srccounter = 0;
- cirrus_update_memory_access(s);
-}
-
-static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
-{
- int w;
-
- s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
- s->cirrus_srcptr = &s->cirrus_bltbuf[0];
- s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
-
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
- s->cirrus_blt_srcpitch = 8;
- } else {
- /* XXX: check for 24 bpp */
- s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
- }
- s->cirrus_srccounter = s->cirrus_blt_srcpitch;
- } else {
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
- w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
- s->cirrus_blt_srcpitch = ((w + 31) >> 5);
- else
- s->cirrus_blt_srcpitch = ((w + 7) >> 3);
- } else {
- /* always align input size to 32 bits */
- s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3;
- }
- s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
- }
- s->cirrus_srcptr = s->cirrus_bltbuf;
- s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
- cirrus_update_memory_access(s);
- return 1;
-}
-
-static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
-{
- /* XXX */
-#ifdef DEBUG_BITBLT
- printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
-#endif
- return 0;
-}
-
-static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
-{
- int ret;
-
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
- ret = cirrus_bitblt_videotovideo_patterncopy(s);
- } else {
- ret = cirrus_bitblt_videotovideo_copy(s);
- }
- if (ret)
- cirrus_bitblt_reset(s);
- return ret;
-}
-
-static void cirrus_bitblt_start(CirrusVGAState * s)
-{
- uint8_t blt_rop;
-
- s->gr[0x31] |= CIRRUS_BLT_BUSY;
-
- s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
- s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
- s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
- s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
- s->cirrus_blt_dstaddr =
- (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
- s->cirrus_blt_srcaddr =
- (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
- s->cirrus_blt_mode = s->gr[0x30];
- s->cirrus_blt_modeext = s->gr[0x33];
- blt_rop = s->gr[0x32];
-
-#ifdef DEBUG_BITBLT
- printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
- blt_rop,
- s->cirrus_blt_mode,
- s->cirrus_blt_modeext,
- s->cirrus_blt_width,
- s->cirrus_blt_height,
- s->cirrus_blt_dstpitch,
- s->cirrus_blt_srcpitch,
- s->cirrus_blt_dstaddr,
- s->cirrus_blt_srcaddr,
- s->gr[0x2f]);
-#endif
-
- switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
- case CIRRUS_BLTMODE_PIXELWIDTH8:
- s->cirrus_blt_pixelwidth = 1;
- break;
- case CIRRUS_BLTMODE_PIXELWIDTH16:
- s->cirrus_blt_pixelwidth = 2;
- break;
- case CIRRUS_BLTMODE_PIXELWIDTH24:
- s->cirrus_blt_pixelwidth = 3;
- break;
- case CIRRUS_BLTMODE_PIXELWIDTH32:
- s->cirrus_blt_pixelwidth = 4;
- break;
- default:
-#ifdef DEBUG_BITBLT
- printf("cirrus: bitblt - pixel width is unknown\n");
-#endif
- goto bitblt_ignore;
- }
- s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
-
- if ((s->
- cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
- CIRRUS_BLTMODE_MEMSYSDEST))
- == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
-#ifdef DEBUG_BITBLT
- printf("cirrus: bitblt - memory-to-memory copy is requested\n");
-#endif
- goto bitblt_ignore;
- }
-
- if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
- (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST |
- CIRRUS_BLTMODE_TRANSPARENTCOMP |
- CIRRUS_BLTMODE_PATTERNCOPY |
- CIRRUS_BLTMODE_COLOREXPAND)) ==
- (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
- cirrus_bitblt_fgcol(s);
- cirrus_bitblt_solidfill(s, blt_rop);
- } else {
- if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND |
- CIRRUS_BLTMODE_PATTERNCOPY)) ==
- CIRRUS_BLTMODE_COLOREXPAND) {
-
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
- cirrus_bitblt_bgcol(s);
- else
- cirrus_bitblt_fgcol(s);
- s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- } else {
- cirrus_bitblt_fgcol(s);
- cirrus_bitblt_bgcol(s);
- s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- }
- } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
- cirrus_bitblt_bgcol(s);
- else
- cirrus_bitblt_fgcol(s);
- s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- } else {
- cirrus_bitblt_fgcol(s);
- cirrus_bitblt_bgcol(s);
- s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- }
- } else {
- s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
- }
- } else {
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
- s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
- s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
- s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
- } else {
- s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
- }
- }
-
- // setup bitblt engine.
- if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
- if (!cirrus_bitblt_cputovideo(s))
- goto bitblt_ignore;
- } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
- if (!cirrus_bitblt_videotocpu(s))
- goto bitblt_ignore;
- } else {
- if (!cirrus_bitblt_videotovideo(s))
- goto bitblt_ignore;
- }
- }
- return;
- bitblt_ignore:;
- cirrus_bitblt_reset(s);
-}
-
-static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
-{
- unsigned old_value;
-
- old_value = s->gr[0x31];
- s->gr[0x31] = reg_value;
-
- if (((old_value & CIRRUS_BLT_RESET) != 0) &&
- ((reg_value & CIRRUS_BLT_RESET) == 0)) {
- cirrus_bitblt_reset(s);
- } else if (((old_value & CIRRUS_BLT_START) == 0) &&
- ((reg_value & CIRRUS_BLT_START) != 0)) {
- cirrus_bitblt_start(s);
- }
-}
-
-
-/***************************************
- *
- * basic parameters
- *
- ***************************************/
-
-static void cirrus_get_offsets(VGAState *s1,
- uint32_t *pline_offset,
- uint32_t *pstart_addr)
-{
- CirrusVGAState * s = (CirrusVGAState *)s1;
- uint32_t start_addr;
- uint32_t line_offset;
-
- line_offset = s->cr[0x13]
- | ((s->cr[0x1b] & 0x10) << 4);
- line_offset <<= 3;
- *pline_offset = line_offset;
-
- start_addr = (s->cr[0x0c] << 8)
- | s->cr[0x0d]
- | ((s->cr[0x1b] & 0x01) << 16)
- | ((s->cr[0x1b] & 0x0c) << 15)
- | ((s->cr[0x1d] & 0x80) << 12);
- *pstart_addr = start_addr;
-}
-
-static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
-{
- uint32_t ret = 16;
-
- switch (s->cirrus_hidden_dac_data & 0xf) {
- case 0:
- ret = 15;
- break; /* Sierra HiColor */
- case 1:
- ret = 16;
- break; /* XGA HiColor */
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: invalid DAC value %x in 16bpp\n",
- (s->cirrus_hidden_dac_data & 0xf));
-#endif
- ret = 15; /* XXX */
- break;
- }
- return ret;
-}
-
-static int cirrus_get_bpp(VGAState *s1)
-{
- CirrusVGAState * s = (CirrusVGAState *)s1;
- uint32_t ret = 8;
-
- if ((s->sr[0x07] & 0x01) != 0) {
- /* Cirrus SVGA */
- switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
- case CIRRUS_SR7_BPP_8:
- ret = 8;
- break;
- case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
- ret = cirrus_get_bpp16_depth(s);
- break;
- case CIRRUS_SR7_BPP_24:
- ret = 24;
- break;
- case CIRRUS_SR7_BPP_16:
- ret = cirrus_get_bpp16_depth(s);
- break;
- case CIRRUS_SR7_BPP_32:
- ret = 32;
- break;
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
-#endif
- ret = 8;
- break;
- }
- } else {
- /* VGA */
- ret = 0;
- }
-
- return ret;
-}
-
-static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight)
-{
- int width, height;
-
- width = (s->cr[0x01] + 1) * 8;
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
- height = (height + 1);
- /* interlace support */
- if (s->cr[0x1a] & 0x01)
- height = height * 2;
- *pwidth = width;
- *pheight = height;
-}
-
-/***************************************
- *
- * bank memory
- *
- ***************************************/
-
-static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
-{
- unsigned offset;
- unsigned limit;
-
- if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */
- offset = s->gr[0x09 + bank_index];
- else /* single bank */
- offset = s->gr[0x09];
-
- if ((s->gr[0x0b] & 0x20) != 0)
- offset <<= 14;
- else
- offset <<= 12;
-
- if (s->real_vram_size <= offset)
- limit = 0;
- else
- limit = s->real_vram_size - offset;
-
- if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
- if (limit > 0x8000) {
- offset += 0x8000;
- limit -= 0x8000;
- } else {
- limit = 0;
- }
- }
-
- if (limit > 0) {
- s->cirrus_bank_base[bank_index] = offset;
- s->cirrus_bank_limit[bank_index] = limit;
- } else {
- s->cirrus_bank_base[bank_index] = 0;
- s->cirrus_bank_limit[bank_index] = 0;
- }
-}
-
-/***************************************
- *
- * I/O access between 0x3c4-0x3c5
- *
- ***************************************/
-
-static int
-cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
-{
- switch (reg_index) {
- case 0x00: // Standard VGA
- case 0x01: // Standard VGA
- case 0x02: // Standard VGA
- case 0x03: // Standard VGA
- case 0x04: // Standard VGA
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x06: // Unlock Cirrus extensions
- *reg_value = s->sr[reg_index];
- break;
- case 0x10:
- case 0x30:
- case 0x50:
- case 0x70: // Graphics Cursor X
- case 0x90:
- case 0xb0:
- case 0xd0:
- case 0xf0: // Graphics Cursor X
- *reg_value = s->sr[0x10];
- break;
- case 0x11:
- case 0x31:
- case 0x51:
- case 0x71: // Graphics Cursor Y
- case 0x91:
- case 0xb1:
- case 0xd1:
- case 0xf1: // Graphics Cursor Y
- *reg_value = s->sr[0x11];
- break;
- case 0x05: // ???
- case 0x07: // Extended Sequencer Mode
- case 0x08: // EEPROM Control
- case 0x09: // Scratch Register 0
- case 0x0a: // Scratch Register 1
- case 0x0b: // VCLK 0
- case 0x0c: // VCLK 1
- case 0x0d: // VCLK 2
- case 0x0e: // VCLK 3
- case 0x0f: // DRAM Control
- case 0x12: // Graphics Cursor Attribute
- case 0x13: // Graphics Cursor Pattern Address
- case 0x14: // Scratch Register 2
- case 0x15: // Scratch Register 3
- case 0x16: // Performance Tuning Register
- case 0x17: // Configuration Readback and Extended Control
- case 0x18: // Signature Generator Control
- case 0x19: // Signal Generator Result
- case 0x1a: // Signal Generator Result
- case 0x1b: // VCLK 0 Denominator & Post
- case 0x1c: // VCLK 1 Denominator & Post
- case 0x1d: // VCLK 2 Denominator & Post
- case 0x1e: // VCLK 3 Denominator & Post
- case 0x1f: // BIOS Write Enable and MCLK select
-#ifdef DEBUG_CIRRUS
- printf("cirrus: handled inport sr_index %02x\n", reg_index);
-#endif
- *reg_value = s->sr[reg_index];
- break;
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: inport sr_index %02x\n", reg_index);
-#endif
- *reg_value = 0xff;
- break;
- }
-
- return CIRRUS_HOOK_HANDLED;
-}
-
-static int
-cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
-{
- switch (reg_index) {
- case 0x00: // Standard VGA
- case 0x01: // Standard VGA
- case 0x02: // Standard VGA
- case 0x03: // Standard VGA
- case 0x04: // Standard VGA
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x06: // Unlock Cirrus extensions
- reg_value &= 0x17;
- if (reg_value == 0x12) {
- s->sr[reg_index] = 0x12;
- } else {
- s->sr[reg_index] = 0x0f;
- }
- break;
- case 0x10:
- case 0x30:
- case 0x50:
- case 0x70: // Graphics Cursor X
- case 0x90:
- case 0xb0:
- case 0xd0:
- case 0xf0: // Graphics Cursor X
- s->sr[0x10] = reg_value;
- s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5);
- break;
- case 0x11:
- case 0x31:
- case 0x51:
- case 0x71: // Graphics Cursor Y
- case 0x91:
- case 0xb1:
- case 0xd1:
- case 0xf1: // Graphics Cursor Y
- s->sr[0x11] = reg_value;
- s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5);
- break;
- case 0x07: // Extended Sequencer Mode
- case 0x08: // EEPROM Control
- case 0x09: // Scratch Register 0
- case 0x0a: // Scratch Register 1
- case 0x0b: // VCLK 0
- case 0x0c: // VCLK 1
- case 0x0d: // VCLK 2
- case 0x0e: // VCLK 3
- case 0x0f: // DRAM Control
- case 0x12: // Graphics Cursor Attribute
- case 0x13: // Graphics Cursor Pattern Address
- case 0x14: // Scratch Register 2
- case 0x15: // Scratch Register 3
- case 0x16: // Performance Tuning Register
- case 0x18: // Signature Generator Control
- case 0x19: // Signature Generator Result
- case 0x1a: // Signature Generator Result
- case 0x1b: // VCLK 0 Denominator & Post
- case 0x1c: // VCLK 1 Denominator & Post
- case 0x1d: // VCLK 2 Denominator & Post
- case 0x1e: // VCLK 3 Denominator & Post
- case 0x1f: // BIOS Write Enable and MCLK select
- s->sr[reg_index] = reg_value;
-#ifdef DEBUG_CIRRUS
- printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
- reg_index, reg_value);
-#endif
- break;
- case 0x17: // Configuration Readback and Extended Control
- s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7);
- cirrus_update_memory_access(s);
- break;
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
- reg_value);
-#endif
- break;
- }
-
- return CIRRUS_HOOK_HANDLED;
-}
-
-/***************************************
- *
- * I/O access at 0x3c6
- *
- ***************************************/
-
-static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
-{
- *reg_value = 0xff;
- if (++s->cirrus_hidden_dac_lockindex == 5) {
- *reg_value = s->cirrus_hidden_dac_data;
- s->cirrus_hidden_dac_lockindex = 0;
- }
-}
-
-static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
-{
- if (s->cirrus_hidden_dac_lockindex == 4) {
- s->cirrus_hidden_dac_data = reg_value;
-#if defined(DEBUG_CIRRUS)
- printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
-#endif
- }
- s->cirrus_hidden_dac_lockindex = 0;
-}
-
-/***************************************
- *
- * I/O access at 0x3c9
- *
- ***************************************/
-
-static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
-{
- if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
- return CIRRUS_HOOK_NOT_HANDLED;
- *reg_value =
- s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 +
- s->dac_sub_index];
- if (++s->dac_sub_index == 3) {
- s->dac_sub_index = 0;
- s->dac_read_index++;
- }
- return CIRRUS_HOOK_HANDLED;
-}
-
-static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
-{
- if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
- return CIRRUS_HOOK_NOT_HANDLED;
- s->dac_cache[s->dac_sub_index] = reg_value;
- if (++s->dac_sub_index == 3) {
- memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3],
- s->dac_cache, 3);
- /* XXX update cursor */
- s->dac_sub_index = 0;
- s->dac_write_index++;
- }
- return CIRRUS_HOOK_HANDLED;
-}
-
-/***************************************
- *
- * I/O access between 0x3ce-0x3cf
- *
- ***************************************/
-
-static int
-cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
-{
- switch (reg_index) {
- case 0x00: // Standard VGA, BGCOLOR 0x000000ff
- *reg_value = s->cirrus_shadow_gr0;
- return CIRRUS_HOOK_HANDLED;
- case 0x01: // Standard VGA, FGCOLOR 0x000000ff
- *reg_value = s->cirrus_shadow_gr1;
- return CIRRUS_HOOK_HANDLED;
- case 0x02: // Standard VGA
- case 0x03: // Standard VGA
- case 0x04: // Standard VGA
- case 0x06: // Standard VGA
- case 0x07: // Standard VGA
- case 0x08: // Standard VGA
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x05: // Standard VGA, Cirrus extended mode
- default:
- break;
- }
-
- if (reg_index < 0x3a) {
- *reg_value = s->gr[reg_index];
- } else {
-#ifdef DEBUG_CIRRUS
- printf("cirrus: inport gr_index %02x\n", reg_index);
-#endif
- *reg_value = 0xff;
- }
-
- return CIRRUS_HOOK_HANDLED;
-}
-
-static int
-cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
-{
-#if defined(DEBUG_BITBLT) && 0
- printf("gr%02x: %02x\n", reg_index, reg_value);
-#endif
- switch (reg_index) {
- case 0x00: // Standard VGA, BGCOLOR 0x000000ff
- s->cirrus_shadow_gr0 = reg_value;
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x01: // Standard VGA, FGCOLOR 0x000000ff
- s->cirrus_shadow_gr1 = reg_value;
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x02: // Standard VGA
- case 0x03: // Standard VGA
- case 0x04: // Standard VGA
- case 0x06: // Standard VGA
- case 0x07: // Standard VGA
- case 0x08: // Standard VGA
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x05: // Standard VGA, Cirrus extended mode
- s->gr[reg_index] = reg_value & 0x7f;
- cirrus_update_memory_access(s);
- break;
- case 0x09: // bank offset #0
- case 0x0A: // bank offset #1
- s->gr[reg_index] = reg_value;
- cirrus_update_bank_ptr(s, 0);
- cirrus_update_bank_ptr(s, 1);
- break;
- case 0x0B:
- s->gr[reg_index] = reg_value;
- cirrus_update_bank_ptr(s, 0);
- cirrus_update_bank_ptr(s, 1);
- cirrus_update_memory_access(s);
- break;
- case 0x10: // BGCOLOR 0x0000ff00
- case 0x11: // FGCOLOR 0x0000ff00
- case 0x12: // BGCOLOR 0x00ff0000
- case 0x13: // FGCOLOR 0x00ff0000
- case 0x14: // BGCOLOR 0xff000000
- case 0x15: // FGCOLOR 0xff000000
- case 0x20: // BLT WIDTH 0x0000ff
- case 0x22: // BLT HEIGHT 0x0000ff
- case 0x24: // BLT DEST PITCH 0x0000ff
- case 0x26: // BLT SRC PITCH 0x0000ff
- case 0x28: // BLT DEST ADDR 0x0000ff
- case 0x29: // BLT DEST ADDR 0x00ff00
- case 0x2c: // BLT SRC ADDR 0x0000ff
- case 0x2d: // BLT SRC ADDR 0x00ff00
- case 0x2f: // BLT WRITEMASK
- case 0x30: // BLT MODE
- case 0x32: // RASTER OP
- case 0x33: // BLT MODEEXT
- case 0x34: // BLT TRANSPARENT COLOR 0x00ff
- case 0x35: // BLT TRANSPARENT COLOR 0xff00
- case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
- case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
- s->gr[reg_index] = reg_value;
- break;
- case 0x21: // BLT WIDTH 0x001f00
- case 0x23: // BLT HEIGHT 0x001f00
- case 0x25: // BLT DEST PITCH 0x001f00
- case 0x27: // BLT SRC PITCH 0x001f00
- s->gr[reg_index] = reg_value & 0x1f;
- break;
- case 0x2a: // BLT DEST ADDR 0x3f0000
- s->gr[reg_index] = reg_value & 0x3f;
- /* if auto start mode, starts bit blt now */
- if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) {
- cirrus_bitblt_start(s);
- }
- break;
- case 0x2e: // BLT SRC ADDR 0x3f0000
- s->gr[reg_index] = reg_value & 0x3f;
- break;
- case 0x31: // BLT STATUS/START
- cirrus_write_bitblt(s, reg_value);
- break;
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
- reg_value);
-#endif
- break;
- }
-
- return CIRRUS_HOOK_HANDLED;
-}
-
-/***************************************
- *
- * I/O access between 0x3d4-0x3d5
- *
- ***************************************/
-
-static int
-cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
-{
- switch (reg_index) {
- case 0x00: // Standard VGA
- case 0x01: // Standard VGA
- case 0x02: // Standard VGA
- case 0x03: // Standard VGA
- case 0x04: // Standard VGA
- case 0x05: // Standard VGA
- case 0x06: // Standard VGA
- case 0x07: // Standard VGA
- case 0x08: // Standard VGA
- case 0x09: // Standard VGA
- case 0x0a: // Standard VGA
- case 0x0b: // Standard VGA
- case 0x0c: // Standard VGA
- case 0x0d: // Standard VGA
- case 0x0e: // Standard VGA
- case 0x0f: // Standard VGA
- case 0x10: // Standard VGA
- case 0x11: // Standard VGA
- case 0x12: // Standard VGA
- case 0x13: // Standard VGA
- case 0x14: // Standard VGA
- case 0x15: // Standard VGA
- case 0x16: // Standard VGA
- case 0x17: // Standard VGA
- case 0x18: // Standard VGA
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x19: // Interlace End
- case 0x1a: // Miscellaneous Control
- case 0x1b: // Extended Display Control
- case 0x1c: // Sync Adjust and Genlock
- case 0x1d: // Overlay Extended Control
- case 0x22: // Graphics Data Latches Readback (R)
- case 0x24: // Attribute Controller Toggle Readback (R)
- case 0x25: // Part Status
- case 0x27: // Part ID (R)
- *reg_value = s->cr[reg_index];
- break;
- case 0x26: // Attribute Controller Index Readback (R)
- *reg_value = s->ar_index & 0x3f;
- break;
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: inport cr_index %02x\n", reg_index);
- *reg_value = 0xff;
-#endif
- break;
- }
-
- return CIRRUS_HOOK_HANDLED;
-}
-
-static int
-cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
-{
- switch (reg_index) {
- case 0x00: // Standard VGA
- case 0x01: // Standard VGA
- case 0x02: // Standard VGA
- case 0x03: // Standard VGA
- case 0x04: // Standard VGA
- case 0x05: // Standard VGA
- case 0x06: // Standard VGA
- case 0x07: // Standard VGA
- case 0x08: // Standard VGA
- case 0x09: // Standard VGA
- case 0x0a: // Standard VGA
- case 0x0b: // Standard VGA
- case 0x0c: // Standard VGA
- case 0x0d: // Standard VGA
- case 0x0e: // Standard VGA
- case 0x0f: // Standard VGA
- case 0x10: // Standard VGA
- case 0x11: // Standard VGA
- case 0x12: // Standard VGA
- case 0x13: // Standard VGA
- case 0x14: // Standard VGA
- case 0x15: // Standard VGA
- case 0x16: // Standard VGA
- case 0x17: // Standard VGA
- case 0x18: // Standard VGA
- return CIRRUS_HOOK_NOT_HANDLED;
- case 0x19: // Interlace End
- case 0x1a: // Miscellaneous Control
- case 0x1b: // Extended Display Control
- case 0x1c: // Sync Adjust and Genlock
- case 0x1d: // Overlay Extended Control
- s->cr[reg_index] = reg_value;
-#ifdef DEBUG_CIRRUS
- printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
- reg_index, reg_value);
-#endif
- break;
- case 0x22: // Graphics Data Latches Readback (R)
- case 0x24: // Attribute Controller Toggle Readback (R)
- case 0x26: // Attribute Controller Index Readback (R)
- case 0x27: // Part ID (R)
- break;
- case 0x25: // Part Status
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
- reg_value);
-#endif
- break;
- }
-
- return CIRRUS_HOOK_HANDLED;
-}
-
-/***************************************
- *
- * memory-mapped I/O (bitblt)
- *
- ***************************************/
-
-static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
-{
- int value = 0xff;
-
- switch (address) {
- case (CIRRUS_MMIO_BLTBGCOLOR + 0):
- cirrus_hook_read_gr(s, 0x00, &value);
- break;
- case (CIRRUS_MMIO_BLTBGCOLOR + 1):
- cirrus_hook_read_gr(s, 0x10, &value);
- break;
- case (CIRRUS_MMIO_BLTBGCOLOR + 2):
- cirrus_hook_read_gr(s, 0x12, &value);
- break;
- case (CIRRUS_MMIO_BLTBGCOLOR + 3):
- cirrus_hook_read_gr(s, 0x14, &value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 0):
- cirrus_hook_read_gr(s, 0x01, &value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 1):
- cirrus_hook_read_gr(s, 0x11, &value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 2):
- cirrus_hook_read_gr(s, 0x13, &value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 3):
- cirrus_hook_read_gr(s, 0x15, &value);
- break;
- case (CIRRUS_MMIO_BLTWIDTH + 0):
- cirrus_hook_read_gr(s, 0x20, &value);
- break;
- case (CIRRUS_MMIO_BLTWIDTH + 1):
- cirrus_hook_read_gr(s, 0x21, &value);
- break;
- case (CIRRUS_MMIO_BLTHEIGHT + 0):
- cirrus_hook_read_gr(s, 0x22, &value);
- break;
- case (CIRRUS_MMIO_BLTHEIGHT + 1):
- cirrus_hook_read_gr(s, 0x23, &value);
- break;
- case (CIRRUS_MMIO_BLTDESTPITCH + 0):
- cirrus_hook_read_gr(s, 0x24, &value);
- break;
- case (CIRRUS_MMIO_BLTDESTPITCH + 1):
- cirrus_hook_read_gr(s, 0x25, &value);
- break;
- case (CIRRUS_MMIO_BLTSRCPITCH + 0):
- cirrus_hook_read_gr(s, 0x26, &value);
- break;
- case (CIRRUS_MMIO_BLTSRCPITCH + 1):
- cirrus_hook_read_gr(s, 0x27, &value);
- break;
- case (CIRRUS_MMIO_BLTDESTADDR + 0):
- cirrus_hook_read_gr(s, 0x28, &value);
- break;
- case (CIRRUS_MMIO_BLTDESTADDR + 1):
- cirrus_hook_read_gr(s, 0x29, &value);
- break;
- case (CIRRUS_MMIO_BLTDESTADDR + 2):
- cirrus_hook_read_gr(s, 0x2a, &value);
- break;
- case (CIRRUS_MMIO_BLTSRCADDR + 0):
- cirrus_hook_read_gr(s, 0x2c, &value);
- break;
- case (CIRRUS_MMIO_BLTSRCADDR + 1):
- cirrus_hook_read_gr(s, 0x2d, &value);
- break;
- case (CIRRUS_MMIO_BLTSRCADDR + 2):
- cirrus_hook_read_gr(s, 0x2e, &value);
- break;
- case CIRRUS_MMIO_BLTWRITEMASK:
- cirrus_hook_read_gr(s, 0x2f, &value);
- break;
- case CIRRUS_MMIO_BLTMODE:
- cirrus_hook_read_gr(s, 0x30, &value);
- break;
- case CIRRUS_MMIO_BLTROP:
- cirrus_hook_read_gr(s, 0x32, &value);
- break;
- case CIRRUS_MMIO_BLTMODEEXT:
- cirrus_hook_read_gr(s, 0x33, &value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
- cirrus_hook_read_gr(s, 0x34, &value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
- cirrus_hook_read_gr(s, 0x35, &value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
- cirrus_hook_read_gr(s, 0x38, &value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
- cirrus_hook_read_gr(s, 0x39, &value);
- break;
- case CIRRUS_MMIO_BLTSTATUS:
- cirrus_hook_read_gr(s, 0x31, &value);
- break;
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mmio read - address 0x%04x\n", address);
-#endif
- break;
- }
-
- return (uint8_t) value;
-}
-
-static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
- uint8_t value)
-{
- switch (address) {
- case (CIRRUS_MMIO_BLTBGCOLOR + 0):
- cirrus_hook_write_gr(s, 0x00, value);
- break;
- case (CIRRUS_MMIO_BLTBGCOLOR + 1):
- cirrus_hook_write_gr(s, 0x10, value);
- break;
- case (CIRRUS_MMIO_BLTBGCOLOR + 2):
- cirrus_hook_write_gr(s, 0x12, value);
- break;
- case (CIRRUS_MMIO_BLTBGCOLOR + 3):
- cirrus_hook_write_gr(s, 0x14, value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 0):
- cirrus_hook_write_gr(s, 0x01, value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 1):
- cirrus_hook_write_gr(s, 0x11, value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 2):
- cirrus_hook_write_gr(s, 0x13, value);
- break;
- case (CIRRUS_MMIO_BLTFGCOLOR + 3):
- cirrus_hook_write_gr(s, 0x15, value);
- break;
- case (CIRRUS_MMIO_BLTWIDTH + 0):
- cirrus_hook_write_gr(s, 0x20, value);
- break;
- case (CIRRUS_MMIO_BLTWIDTH + 1):
- cirrus_hook_write_gr(s, 0x21, value);
- break;
- case (CIRRUS_MMIO_BLTHEIGHT + 0):
- cirrus_hook_write_gr(s, 0x22, value);
- break;
- case (CIRRUS_MMIO_BLTHEIGHT + 1):
- cirrus_hook_write_gr(s, 0x23, value);
- break;
- case (CIRRUS_MMIO_BLTDESTPITCH + 0):
- cirrus_hook_write_gr(s, 0x24, value);
- break;
- case (CIRRUS_MMIO_BLTDESTPITCH + 1):
- cirrus_hook_write_gr(s, 0x25, value);
- break;
- case (CIRRUS_MMIO_BLTSRCPITCH + 0):
- cirrus_hook_write_gr(s, 0x26, value);
- break;
- case (CIRRUS_MMIO_BLTSRCPITCH + 1):
- cirrus_hook_write_gr(s, 0x27, value);
- break;
- case (CIRRUS_MMIO_BLTDESTADDR + 0):
- cirrus_hook_write_gr(s, 0x28, value);
- break;
- case (CIRRUS_MMIO_BLTDESTADDR + 1):
- cirrus_hook_write_gr(s, 0x29, value);
- break;
- case (CIRRUS_MMIO_BLTDESTADDR + 2):
- cirrus_hook_write_gr(s, 0x2a, value);
- break;
- case (CIRRUS_MMIO_BLTDESTADDR + 3):
- /* ignored */
- break;
- case (CIRRUS_MMIO_BLTSRCADDR + 0):
- cirrus_hook_write_gr(s, 0x2c, value);
- break;
- case (CIRRUS_MMIO_BLTSRCADDR + 1):
- cirrus_hook_write_gr(s, 0x2d, value);
- break;
- case (CIRRUS_MMIO_BLTSRCADDR + 2):
- cirrus_hook_write_gr(s, 0x2e, value);
- break;
- case CIRRUS_MMIO_BLTWRITEMASK:
- cirrus_hook_write_gr(s, 0x2f, value);
- break;
- case CIRRUS_MMIO_BLTMODE:
- cirrus_hook_write_gr(s, 0x30, value);
- break;
- case CIRRUS_MMIO_BLTROP:
- cirrus_hook_write_gr(s, 0x32, value);
- break;
- case CIRRUS_MMIO_BLTMODEEXT:
- cirrus_hook_write_gr(s, 0x33, value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
- cirrus_hook_write_gr(s, 0x34, value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
- cirrus_hook_write_gr(s, 0x35, value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
- cirrus_hook_write_gr(s, 0x38, value);
- break;
- case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
- cirrus_hook_write_gr(s, 0x39, value);
- break;
- case CIRRUS_MMIO_BLTSTATUS:
- cirrus_hook_write_gr(s, 0x31, value);
- break;
- default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
- address, value);
-#endif
- break;
- }
-}
-
-/***************************************
- *
- * write mode 4/5
- *
- * assume TARGET_PAGE_SIZE >= 16
- *
- ***************************************/
-
-static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
- unsigned mode,
- unsigned offset,
- uint32_t mem_value)
-{
- int x;
- unsigned val = mem_value;
- uint8_t *dst;
-
- dst = s->vram_ptr + offset;
- for (x = 0; x < 8; x++) {
- if (val & 0x80) {
- *dst = s->cirrus_shadow_gr1;
- } else if (mode == 5) {
- *dst = s->cirrus_shadow_gr0;
- }
- val <<= 1;
- dst++;
- }
- cpu_physical_memory_set_dirty(s->vram_offset + offset);
- cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
-}
-
-static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
- unsigned mode,
- unsigned offset,
- uint32_t mem_value)
-{
- int x;
- unsigned val = mem_value;
- uint8_t *dst;
-
- dst = s->vram_ptr + offset;
- for (x = 0; x < 8; x++) {
- if (val & 0x80) {
- *dst = s->cirrus_shadow_gr1;
- *(dst + 1) = s->gr[0x11];
- } else if (mode == 5) {
- *dst = s->cirrus_shadow_gr0;
- *(dst + 1) = s->gr[0x10];
- }
- val <<= 1;
- dst += 2;
- }
- cpu_physical_memory_set_dirty(s->vram_offset + offset);
- cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
-}
-
-/***************************************
- *
- * memory access between 0xa0000-0xbffff
- *
- ***************************************/
-
-static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- CirrusVGAState *s = opaque;
- unsigned bank_index;
- unsigned bank_offset;
- uint32_t val;
-
- if ((s->sr[0x07] & 0x01) == 0) {
- return vga_mem_readb(s, addr);
- }
-
- addr &= 0x1ffff;
-
- if (addr < 0x10000) {
- /* XXX handle bitblt */
- /* video memory */
- bank_index = addr >> 15;
- bank_offset = addr & 0x7fff;
- if (bank_offset < s->cirrus_bank_limit[bank_index]) {
- bank_offset += s->cirrus_bank_base[bank_index];
- if ((s->gr[0x0B] & 0x14) == 0x14) {
- bank_offset <<= 4;
- } else if (s->gr[0x0B] & 0x02) {
- bank_offset <<= 3;
- }
- bank_offset &= s->cirrus_addr_mask;
- val = *(s->vram_ptr + bank_offset);
- } else
- val = 0xff;
- } else if (addr >= 0x18000 && addr < 0x18100) {
- /* memory-mapped I/O */
- val = 0xff;
- if ((s->sr[0x17] & 0x44) == 0x04) {
- val = cirrus_mmio_blt_read(s, addr & 0xff);
- }
- } else {
- val = 0xff;
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mem_readb %06x\n", addr);
-#endif
- }
- return val;
-}
-
-static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_vga_mem_readb(opaque, addr) << 8;
- v |= cirrus_vga_mem_readb(opaque, addr + 1);
-#else
- v = cirrus_vga_mem_readb(opaque, addr);
- v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
-#endif
- return v;
-}
-
-static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_vga_mem_readb(opaque, addr) << 24;
- v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
- v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
- v |= cirrus_vga_mem_readb(opaque, addr + 3);
-#else
- v = cirrus_vga_mem_readb(opaque, addr);
- v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
- v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
- v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
-#endif
- return v;
-}
-
-static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
- uint32_t mem_value)
-{
- CirrusVGAState *s = opaque;
- unsigned bank_index;
- unsigned bank_offset;
- unsigned mode;
-
- if ((s->sr[0x07] & 0x01) == 0) {
- vga_mem_writeb(s, addr, mem_value);
- return;
- }
-
- addr &= 0x1ffff;
-
- if (addr < 0x10000) {
- if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
- /* bitblt */
- *s->cirrus_srcptr++ = (uint8_t) mem_value;
- if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
- cirrus_bitblt_cputovideo_next(s);
- }
- } else {
- /* video memory */
- bank_index = addr >> 15;
- bank_offset = addr & 0x7fff;
- if (bank_offset < s->cirrus_bank_limit[bank_index]) {
- bank_offset += s->cirrus_bank_base[bank_index];
- if ((s->gr[0x0B] & 0x14) == 0x14) {
- bank_offset <<= 4;
- } else if (s->gr[0x0B] & 0x02) {
- bank_offset <<= 3;
- }
- bank_offset &= s->cirrus_addr_mask;
- mode = s->gr[0x05] & 0x7;
- if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
- *(s->vram_ptr + bank_offset) = mem_value;
- cpu_physical_memory_set_dirty(s->vram_offset +
- bank_offset);
- } else {
- if ((s->gr[0x0B] & 0x14) != 0x14) {
- cirrus_mem_writeb_mode4and5_8bpp(s, mode,
- bank_offset,
- mem_value);
- } else {
- cirrus_mem_writeb_mode4and5_16bpp(s, mode,
- bank_offset,
- mem_value);
- }
- }
- }
- }
- } else if (addr >= 0x18000 && addr < 0x18100) {
- /* memory-mapped I/O */
- if ((s->sr[0x17] & 0x44) == 0x04) {
- cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
- }
- } else {
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
-#endif
- }
-}
-
-static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
-#else
- cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
-}
-
-static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
-#else
- cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
-}
-
-static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
- cirrus_vga_mem_readb,
- cirrus_vga_mem_readw,
- cirrus_vga_mem_readl,
-};
-
-static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
- cirrus_vga_mem_writeb,
- cirrus_vga_mem_writew,
- cirrus_vga_mem_writel,
-};
-
-/***************************************
- *
- * hardware cursor
- *
- ***************************************/
-
-static inline void invalidate_cursor1(CirrusVGAState *s)
-{
- if (s->last_hw_cursor_size) {
- vga_invalidate_scanlines((VGAState *)s,
- s->last_hw_cursor_y + s->last_hw_cursor_y_start,
- s->last_hw_cursor_y + s->last_hw_cursor_y_end);
- }
-}
-
-static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
-{
- const uint8_t *src;
- uint32_t content;
- int y, y_min, y_max;
-
- src = s->vram_ptr + s->real_vram_size - 16 * 1024;
- if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
- src += (s->sr[0x13] & 0x3c) * 256;
- y_min = 64;
- y_max = -1;
- for(y = 0; y < 64; y++) {
- content = ((uint32_t *)src)[0] |
- ((uint32_t *)src)[1] |
- ((uint32_t *)src)[2] |
- ((uint32_t *)src)[3];
- if (content) {
- if (y < y_min)
- y_min = y;
- if (y > y_max)
- y_max = y;
- }
- src += 16;
- }
- } else {
- src += (s->sr[0x13] & 0x3f) * 256;
- y_min = 32;
- y_max = -1;
- for(y = 0; y < 32; y++) {
- content = ((uint32_t *)src)[0] |
- ((uint32_t *)(src + 128))[0];
- if (content) {
- if (y < y_min)
- y_min = y;
- if (y > y_max)
- y_max = y;
- }
- src += 4;
- }
- }
- if (y_min > y_max) {
- s->last_hw_cursor_y_start = 0;
- s->last_hw_cursor_y_end = 0;
- } else {
- s->last_hw_cursor_y_start = y_min;
- s->last_hw_cursor_y_end = y_max + 1;
- }
-}
-
-/* NOTE: we do not currently handle the cursor bitmap change, so we
- update the cursor only if it moves. */
-static void cirrus_cursor_invalidate(VGAState *s1)
-{
- CirrusVGAState *s = (CirrusVGAState *)s1;
- int size;
-
- if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) {
- size = 0;
- } else {
- if (s->sr[0x12] & CIRRUS_CURSOR_LARGE)
- size = 64;
- else
- size = 32;
- }
- /* invalidate last cursor and new cursor if any change */
- if (s->last_hw_cursor_size != size ||
- s->last_hw_cursor_x != s->hw_cursor_x ||
- s->last_hw_cursor_y != s->hw_cursor_y) {
-
- invalidate_cursor1(s);
-
- s->last_hw_cursor_size = size;
- s->last_hw_cursor_x = s->hw_cursor_x;
- s->last_hw_cursor_y = s->hw_cursor_y;
- /* compute the real cursor min and max y */
- cirrus_cursor_compute_yrange(s);
- invalidate_cursor1(s);
- }
-}
-
-static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y)
-{
- CirrusVGAState *s = (CirrusVGAState *)s1;
- int w, h, bpp, x1, x2, poffset;
- unsigned int color0, color1;
- const uint8_t *palette, *src;
- uint32_t content;
-
- if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW))
- return;
- /* fast test to see if the cursor intersects with the scan line */
- if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
- h = 64;
- } else {
- h = 32;
- }
- if (scr_y < s->hw_cursor_y ||
- scr_y >= (s->hw_cursor_y + h))
- return;
-
- src = s->vram_ptr + s->real_vram_size - 16 * 1024;
- if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
- src += (s->sr[0x13] & 0x3c) * 256;
- src += (scr_y - s->hw_cursor_y) * 16;
- poffset = 8;
- content = ((uint32_t *)src)[0] |
- ((uint32_t *)src)[1] |
- ((uint32_t *)src)[2] |
- ((uint32_t *)src)[3];
- } else {
- src += (s->sr[0x13] & 0x3f) * 256;
- src += (scr_y - s->hw_cursor_y) * 4;
- poffset = 128;
- content = ((uint32_t *)src)[0] |
- ((uint32_t *)(src + 128))[0];
- }
- /* if nothing to draw, no need to continue */
- if (!content)
- return;
- w = h;
-
- x1 = s->hw_cursor_x;
- if (x1 >= s->last_scr_width)
- return;
- x2 = s->hw_cursor_x + w;
- if (x2 > s->last_scr_width)
- x2 = s->last_scr_width;
- w = x2 - x1;
- palette = s->cirrus_hidden_palette;
- color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]),
- c6_to_8(palette[0x0 * 3 + 1]),
- c6_to_8(palette[0x0 * 3 + 2]));
- color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]),
- c6_to_8(palette[0xf * 3 + 1]),
- c6_to_8(palette[0xf * 3 + 2]));
- bpp = ((s->ds->depth + 7) >> 3);
- d1 += x1 * bpp;
- switch(s->ds->depth) {
- default:
- break;
- case 8:
- vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff);
- break;
- case 15:
- vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff);
- break;
- case 16:
- vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff);
- break;
- case 32:
- vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff);
- break;
- }
-}
-
-/***************************************
- *
- * LFB memory access
- *
- ***************************************/
-
-static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
- uint32_t ret;
-
- addr &= s->cirrus_addr_mask;
-
- if (((s->sr[0x17] & 0x44) == 0x44) &&
- ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
- /* memory-mapped I/O */
- ret = cirrus_mmio_blt_read(s, addr & 0xff);
- } else if (0) {
- /* XXX handle bitblt */
- ret = 0xff;
- } else {
- /* video memory */
- if ((s->gr[0x0B] & 0x14) == 0x14) {
- addr <<= 4;
- } else if (s->gr[0x0B] & 0x02) {
- addr <<= 3;
- }
- addr &= s->cirrus_addr_mask;
- ret = *(s->vram_ptr + addr);
- }
-
- return ret;
-}
-
-static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_linear_readb(opaque, addr) << 8;
- v |= cirrus_linear_readb(opaque, addr + 1);
-#else
- v = cirrus_linear_readb(opaque, addr);
- v |= cirrus_linear_readb(opaque, addr + 1) << 8;
-#endif
- return v;
-}
-
-static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_linear_readb(opaque, addr) << 24;
- v |= cirrus_linear_readb(opaque, addr + 1) << 16;
- v |= cirrus_linear_readb(opaque, addr + 2) << 8;
- v |= cirrus_linear_readb(opaque, addr + 3);
-#else
- v = cirrus_linear_readb(opaque, addr);
- v |= cirrus_linear_readb(opaque, addr + 1) << 8;
- v |= cirrus_linear_readb(opaque, addr + 2) << 16;
- v |= cirrus_linear_readb(opaque, addr + 3) << 24;
-#endif
- return v;
-}
-
-static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
- unsigned mode;
-
- addr &= s->cirrus_addr_mask;
-
- if (((s->sr[0x17] & 0x44) == 0x44) &&
- ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
- /* memory-mapped I/O */
- cirrus_mmio_blt_write(s, addr & 0xff, val);
- } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
- /* bitblt */
- *s->cirrus_srcptr++ = (uint8_t) val;
- if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
- cirrus_bitblt_cputovideo_next(s);
- }
- } else {
- /* video memory */
- if ((s->gr[0x0B] & 0x14) == 0x14) {
- addr <<= 4;
- } else if (s->gr[0x0B] & 0x02) {
- addr <<= 3;
- }
- addr &= s->cirrus_addr_mask;
-
- mode = s->gr[0x05] & 0x7;
- if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
- *(s->vram_ptr + addr) = (uint8_t) val;
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
- } else {
- if ((s->gr[0x0B] & 0x14) != 0x14) {
- cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
- } else {
- cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
- }
- }
- }
-}
-
-static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
- cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
-#else
- cirrus_linear_writeb(opaque, addr, val & 0xff);
- cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
-}
-
-static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
- cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
-#else
- cirrus_linear_writeb(opaque, addr, val & 0xff);
- cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
-}
-
-
-static CPUReadMemoryFunc *cirrus_linear_read[3] = {
- cirrus_linear_readb,
- cirrus_linear_readw,
- cirrus_linear_readl,
-};
-
-static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
- cirrus_linear_writeb,
- cirrus_linear_writew,
- cirrus_linear_writel,
-};
-
-static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
-
- addr &= s->cirrus_addr_mask;
- *(s->vram_ptr + addr) = val;
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
-}
-
-static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
-
- addr &= s->cirrus_addr_mask;
- cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val);
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
-}
-
-static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
-
- addr &= s->cirrus_addr_mask;
- cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val);
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
-}
-
-/***************************************
- *
- * system to screen memory access
- *
- ***************************************/
-
-
-static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret;
-
- /* XXX handle bitblt */
- ret = 0xff;
- return ret;
-}
-
-static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
- v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
-#else
- v = cirrus_linear_bitblt_readb(opaque, addr);
- v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
-#endif
- return v;
-}
-
-static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
- v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
- v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
- v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
-#else
- v = cirrus_linear_bitblt_readb(opaque, addr);
- v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
- v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
- v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
-#endif
- return v;
-}
-
-static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
-
- if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
- /* bitblt */
- *s->cirrus_srcptr++ = (uint8_t) val;
- if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
- cirrus_bitblt_cputovideo_next(s);
- }
- }
-}
-
-static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
-#else
- cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
-}
-
-static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
-#else
- cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
-}
-
-
-static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = {
- cirrus_linear_bitblt_readb,
- cirrus_linear_bitblt_readw,
- cirrus_linear_bitblt_readl,
-};
-
-static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = {
- cirrus_linear_bitblt_writeb,
- cirrus_linear_bitblt_writew,
- cirrus_linear_bitblt_writel,
-};
-
-/* Compute the memory access functions */
-static void cirrus_update_memory_access(CirrusVGAState *s)
-{
- unsigned mode;
-
- if ((s->sr[0x17] & 0x44) == 0x44) {
- goto generic_io;
- } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
- goto generic_io;
- } else {
- if ((s->gr[0x0B] & 0x14) == 0x14) {
- goto generic_io;
- } else if (s->gr[0x0B] & 0x02) {
- goto generic_io;
- }
-
- mode = s->gr[0x05] & 0x7;
- if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
- s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
- s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
- s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
- } else {
- generic_io:
- s->cirrus_linear_write[0] = cirrus_linear_writeb;
- s->cirrus_linear_write[1] = cirrus_linear_writew;
- s->cirrus_linear_write[2] = cirrus_linear_writel;
- }
- }
-}
-
-
-/* I/O ports */
-
-static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
-{
- CirrusVGAState *s = opaque;
- int val, index;
-
- /* check port range access depending on color/monochrome mode */
- if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
- || (addr >= 0x3d0 && addr <= 0x3df
- && !(s->msr & MSR_COLOR_EMULATION))) {
- val = 0xff;
- } else {
- switch (addr) {
- case 0x3c0:
- if (s->ar_flip_flop == 0) {
- val = s->ar_index;
- } else {
- val = 0;
- }
- break;
- case 0x3c1:
- index = s->ar_index & 0x1f;
- if (index < 21)
- val = s->ar[index];
- else
- val = 0;
- break;
- case 0x3c2:
- val = s->st00;
- break;
- case 0x3c4:
- val = s->sr_index;
- break;
- case 0x3c5:
- if (cirrus_hook_read_sr(s, s->sr_index, &val))
- break;
- val = s->sr[s->sr_index];
-#ifdef DEBUG_VGA_REG
- printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
-#endif
- break;
- case 0x3c6:
- cirrus_read_hidden_dac(s, &val);
- break;
- case 0x3c7:
- val = s->dac_state;
- break;
- case 0x3c8:
- val = s->dac_write_index;
- s->cirrus_hidden_dac_lockindex = 0;
- break;
- case 0x3c9:
- if (cirrus_hook_read_palette(s, &val))
- break;
- val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
- if (++s->dac_sub_index == 3) {
- s->dac_sub_index = 0;
- s->dac_read_index++;
- }
- break;
- case 0x3ca:
- val = s->fcr;
- break;
- case 0x3cc:
- val = s->msr;
- break;
- case 0x3ce:
- val = s->gr_index;
- break;
- case 0x3cf:
- if (cirrus_hook_read_gr(s, s->gr_index, &val))
- break;
- val = s->gr[s->gr_index];
-#ifdef DEBUG_VGA_REG
- printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
-#endif
- break;
- case 0x3b4:
- case 0x3d4:
- val = s->cr_index;
- break;
- case 0x3b5:
- case 0x3d5:
- if (cirrus_hook_read_cr(s, s->cr_index, &val))
- break;
- val = s->cr[s->cr_index];
-#ifdef DEBUG_VGA_REG
- printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
-#endif
- break;
- case 0x3ba:
- case 0x3da:
- /* just toggle to fool polling */
- s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
- val = s->st01;
- s->ar_flip_flop = 0;
- break;
- default:
- val = 0x00;
- break;
- }
- }
-#if defined(DEBUG_VGA)
- printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
-#endif
- return val;
-}
-
-static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- CirrusVGAState *s = opaque;
- int index;
-
- /* check port range access depending on color/monochrome mode */
- if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
- || (addr >= 0x3d0 && addr <= 0x3df
- && !(s->msr & MSR_COLOR_EMULATION)))
- return;
-
-#ifdef DEBUG_VGA
- printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
-#endif
-
- switch (addr) {
- case 0x3c0:
- if (s->ar_flip_flop == 0) {
- val &= 0x3f;
- s->ar_index = val;
- } else {
- index = s->ar_index & 0x1f;
- switch (index) {
- case 0x00 ... 0x0f:
- s->ar[index] = val & 0x3f;
- break;
- case 0x10:
- s->ar[index] = val & ~0x10;
- break;
- case 0x11:
- s->ar[index] = val;
- break;
- case 0x12:
- s->ar[index] = val & ~0xc0;
- break;
- case 0x13:
- s->ar[index] = val & ~0xf0;
- break;
- case 0x14:
- s->ar[index] = val & ~0xf0;
- break;
- default:
- break;
- }
- }
- s->ar_flip_flop ^= 1;
- break;
- case 0x3c2:
- s->msr = val & ~0x10;
- break;
- case 0x3c4:
- s->sr_index = val;
- break;
- case 0x3c5:
- if (cirrus_hook_write_sr(s, s->sr_index, val))
- break;
-#ifdef DEBUG_VGA_REG
- printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
-#endif
- s->sr[s->sr_index] = val & sr_mask[s->sr_index];
- break;
- case 0x3c6:
- cirrus_write_hidden_dac(s, val);
- break;
- case 0x3c7:
- s->dac_read_index = val;
- s->dac_sub_index = 0;
- s->dac_state = 3;
- break;
- case 0x3c8:
- s->dac_write_index = val;
- s->dac_sub_index = 0;
- s->dac_state = 0;
- break;
- case 0x3c9:
- if (cirrus_hook_write_palette(s, val))
- break;
- s->dac_cache[s->dac_sub_index] = val;
- if (++s->dac_sub_index == 3) {
- memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
- s->dac_sub_index = 0;
- s->dac_write_index++;
- }
- break;
- case 0x3ce:
- s->gr_index = val;
- break;
- case 0x3cf:
- if (cirrus_hook_write_gr(s, s->gr_index, val))
- break;
-#ifdef DEBUG_VGA_REG
- printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
-#endif
- s->gr[s->gr_index] = val & gr_mask[s->gr_index];
- break;
- case 0x3b4:
- case 0x3d4:
- s->cr_index = val;
- break;
- case 0x3b5:
- case 0x3d5:
- if (cirrus_hook_write_cr(s, s->cr_index, val))
- break;
-#ifdef DEBUG_VGA_REG
- printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
-#endif
- /* handle CR0-7 protection */
- if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
- /* can always write bit 4 of CR7 */
- if (s->cr_index == 7)
- s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
- return;
- }
- switch (s->cr_index) {
- case 0x01: /* horizontal display end */
- case 0x07:
- case 0x09:
- case 0x0c:
- case 0x0d:
- case 0x12: /* veritcal display end */
- s->cr[s->cr_index] = val;
- break;
-
- default:
- s->cr[s->cr_index] = val;
- break;
- }
- break;
- case 0x3ba:
- case 0x3da:
- s->fcr = val & 0x10;
- break;
- }
-}
-
-/***************************************
- *
- * memory-mapped I/O access
- *
- ***************************************/
-
-static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
-
- addr &= CIRRUS_PNPMMIO_SIZE - 1;
-
- if (addr >= 0x100) {
- return cirrus_mmio_blt_read(s, addr - 0x100);
- } else {
- return vga_ioport_read(s, addr + 0x3c0);
- }
-}
-
-static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_mmio_readb(opaque, addr) << 8;
- v |= cirrus_mmio_readb(opaque, addr + 1);
-#else
- v = cirrus_mmio_readb(opaque, addr);
- v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
-#endif
- return v;
-}
-
-static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = cirrus_mmio_readb(opaque, addr) << 24;
- v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
- v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
- v |= cirrus_mmio_readb(opaque, addr + 3);
-#else
- v = cirrus_mmio_readb(opaque, addr);
- v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
- v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
- v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
-#endif
- return v;
-}
-
-static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- CirrusVGAState *s = (CirrusVGAState *) opaque;
-
- addr &= CIRRUS_PNPMMIO_SIZE - 1;
-
- if (addr >= 0x100) {
- cirrus_mmio_blt_write(s, addr - 0x100, val);
- } else {
- vga_ioport_write(s, addr + 0x3c0, val);
- }
-}
-
-static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
- cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
-#else
- cirrus_mmio_writeb(opaque, addr, val & 0xff);
- cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
-}
-
-static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
- cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
-#else
- cirrus_mmio_writeb(opaque, addr, val & 0xff);
- cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
-}
-
-
-static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
- cirrus_mmio_readb,
- cirrus_mmio_readw,
- cirrus_mmio_readl,
-};
-
-static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
- cirrus_mmio_writeb,
- cirrus_mmio_writew,
- cirrus_mmio_writel,
-};
-
-/* load/save state */
-
-static void cirrus_vga_save(QEMUFile *f, void *opaque)
-{
- CirrusVGAState *s = opaque;
-
- qemu_put_be32s(f, &s->latch);
- qemu_put_8s(f, &s->sr_index);
- qemu_put_buffer(f, s->sr, 256);
- qemu_put_8s(f, &s->gr_index);
- qemu_put_8s(f, &s->cirrus_shadow_gr0);
- qemu_put_8s(f, &s->cirrus_shadow_gr1);
- qemu_put_buffer(f, s->gr + 2, 254);
- qemu_put_8s(f, &s->ar_index);
- qemu_put_buffer(f, s->ar, 21);
- qemu_put_be32s(f, &s->ar_flip_flop);
- qemu_put_8s(f, &s->cr_index);
- qemu_put_buffer(f, s->cr, 256);
- qemu_put_8s(f, &s->msr);
- qemu_put_8s(f, &s->fcr);
- qemu_put_8s(f, &s->st00);
- qemu_put_8s(f, &s->st01);
-
- qemu_put_8s(f, &s->dac_state);
- qemu_put_8s(f, &s->dac_sub_index);
- qemu_put_8s(f, &s->dac_read_index);
- qemu_put_8s(f, &s->dac_write_index);
- qemu_put_buffer(f, s->dac_cache, 3);
- qemu_put_buffer(f, s->palette, 768);
-
- qemu_put_be32s(f, &s->bank_offset);
-
- qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex);
- qemu_put_8s(f, &s->cirrus_hidden_dac_data);
-
- qemu_put_be32s(f, &s->hw_cursor_x);
- qemu_put_be32s(f, &s->hw_cursor_y);
- /* XXX: we do not save the bitblt state - we assume we do not save
- the state when the blitter is active */
-}
-
-static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
-{
- CirrusVGAState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->latch);
- qemu_get_8s(f, &s->sr_index);
- qemu_get_buffer(f, s->sr, 256);
- qemu_get_8s(f, &s->gr_index);
- qemu_get_8s(f, &s->cirrus_shadow_gr0);
- qemu_get_8s(f, &s->cirrus_shadow_gr1);
- s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
- s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
- qemu_get_buffer(f, s->gr + 2, 254);
- qemu_get_8s(f, &s->ar_index);
- qemu_get_buffer(f, s->ar, 21);
- qemu_get_be32s(f, &s->ar_flip_flop);
- qemu_get_8s(f, &s->cr_index);
- qemu_get_buffer(f, s->cr, 256);
- qemu_get_8s(f, &s->msr);
- qemu_get_8s(f, &s->fcr);
- qemu_get_8s(f, &s->st00);
- qemu_get_8s(f, &s->st01);
-
- qemu_get_8s(f, &s->dac_state);
- qemu_get_8s(f, &s->dac_sub_index);
- qemu_get_8s(f, &s->dac_read_index);
- qemu_get_8s(f, &s->dac_write_index);
- qemu_get_buffer(f, s->dac_cache, 3);
- qemu_get_buffer(f, s->palette, 768);
-
- qemu_get_be32s(f, &s->bank_offset);
-
- qemu_get_8s(f, &s->cirrus_hidden_dac_lockindex);
- qemu_get_8s(f, &s->cirrus_hidden_dac_data);
-
- qemu_get_be32s(f, &s->hw_cursor_x);
- qemu_get_be32s(f, &s->hw_cursor_y);
-
- /* force refresh */
- s->graphic_mode = -1;
- cirrus_update_bank_ptr(s, 0);
- cirrus_update_bank_ptr(s, 1);
- return 0;
-}
-
-/***************************************
- *
- * initialize
- *
- ***************************************/
-
-static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
-{
- int vga_io_memory, i;
- static int inited;
-
- if (!inited) {
- inited = 1;
- for(i = 0;i < 256; i++)
- rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
- rop_to_index[CIRRUS_ROP_0] = 0;
- rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
- rop_to_index[CIRRUS_ROP_NOP] = 2;
- rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
- rop_to_index[CIRRUS_ROP_NOTDST] = 4;
- rop_to_index[CIRRUS_ROP_SRC] = 5;
- rop_to_index[CIRRUS_ROP_1] = 6;
- rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
- rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
- rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
- rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
- rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
- rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
- rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
- rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
- rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
- }
-
- register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
-
- register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
- register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
- register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
- register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
-
- register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
-
- register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
- register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
- register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
- register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
-
- vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read,
- cirrus_vga_mem_write, s);
- cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
- vga_io_memory);
-
- s->sr[0x06] = 0x0f;
- if (device_id == CIRRUS_ID_CLGD5446) {
- /* 4MB 64 bit memory config, always PCI */
- s->sr[0x1F] = 0x2d; // MemClock
- s->gr[0x18] = 0x0f; // fastest memory configuration
-#if 1
- s->sr[0x0f] = 0x98;
- s->sr[0x17] = 0x20;
- s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
- s->real_vram_size = 4096 * 1024;
-#else
- s->sr[0x0f] = 0x18;
- s->sr[0x17] = 0x20;
- s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
- s->real_vram_size = 2048 * 1024;
-#endif
- } else {
- s->sr[0x1F] = 0x22; // MemClock
- s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
- if (is_pci)
- s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
- else
- s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
- s->real_vram_size = 2048 * 1024;
- s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
- }
- s->cr[0x27] = device_id;
-
- /* Win2K seems to assume that the pattern buffer is at 0xff
- initially ! */
- memset(s->vram_ptr, 0xff, s->real_vram_size);
-
- s->cirrus_hidden_dac_lockindex = 5;
- s->cirrus_hidden_dac_data = 0;
-
- /* I/O handler for LFB */
- s->cirrus_linear_io_addr =
- cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
- s);
- s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr);
-
- /* I/O handler for LFB */
- s->cirrus_linear_bitblt_io_addr =
- cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,
- s);
-
- /* I/O handler for memory-mapped I/O */
- s->cirrus_mmio_io_addr =
- cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
-
- /* XXX: s->vram_size must be a power of two */
- s->cirrus_addr_mask = s->real_vram_size - 1;
- s->linear_mmio_mask = s->real_vram_size - 256;
-
- s->get_bpp = cirrus_get_bpp;
- s->get_offsets = cirrus_get_offsets;
- s->get_resolution = cirrus_get_resolution;
- s->cursor_invalidate = cirrus_cursor_invalidate;
- s->cursor_draw_line = cirrus_cursor_draw_line;
-
- register_savevm("cirrus_vga", 0, 1, cirrus_vga_save, cirrus_vga_load, s);
-}
-
-/***************************************
- *
- * ISA bus support
- *
- ***************************************/
-
-void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size)
-{
- CirrusVGAState *s;
-
- s = qemu_mallocz(sizeof(CirrusVGAState));
-
- vga_common_init((VGAState *)s,
- ds, vga_ram_base, vga_ram_offset, vga_ram_size);
- cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
- /* XXX ISA-LFB support */
-}
-
-/***************************************
- *
- * PCI bus support
- *
- ***************************************/
-
-static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
-
- /* XXX: add byte swapping apertures */
- cpu_register_physical_memory(addr, s->vram_size,
- s->cirrus_linear_io_addr);
- cpu_register_physical_memory(addr + 0x1000000, 0x400000,
- s->cirrus_linear_bitblt_io_addr);
-}
-
-static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
-
- cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
- s->cirrus_mmio_io_addr);
-}
-
-void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size)
-{
- PCICirrusVGAState *d;
- uint8_t *pci_conf;
- CirrusVGAState *s;
- int device_id;
-
- device_id = CIRRUS_ID_CLGD5446;
-
- /* setup PCI configuration registers */
- d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
- sizeof(PCICirrusVGAState),
- -1, NULL, NULL);
- pci_conf = d->dev.config;
- pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
- pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
- pci_conf[0x02] = (uint8_t) (device_id & 0xff);
- pci_conf[0x03] = (uint8_t) (device_id >> 8);
- pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
- pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
- pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
- pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
-
- /* setup VGA */
- s = &d->cirrus_vga;
- vga_common_init((VGAState *)s,
- ds, vga_ram_base, vga_ram_offset, vga_ram_size);
- cirrus_init_common(s, device_id, 1);
-
- /* setup memory space */
- /* memory #0 LFB */
- /* memory #1 memory-mapped I/O */
- /* XXX: s->vram_size must be a power of two */
- pci_register_io_region((PCIDevice *)d, 0, 0x2000000,
- PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
- if (device_id == CIRRUS_ID_CLGD5446) {
- pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
- PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
- }
- /* XXX: ROM BIOS */
-}
diff --git a/hw/cirrus_vga_rop.h b/hw/cirrus_vga_rop.h
deleted file mode 100644
index c54f125..0000000
--- a/hw/cirrus_vga_rop.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * QEMU Cirrus CLGD 54xx VGA Emulator.
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-static void
-glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
- int bltwidth,int bltheight)
-{
- int x,y;
- dstpitch -= bltwidth;
- srcpitch -= bltwidth;
- for (y = 0; y < bltheight; y++) {
- for (x = 0; x < bltwidth; x++) {
- ROP_OP(*dst, *src);
- dst++;
- src++;
- }
- dst += dstpitch;
- src += srcpitch;
- }
-}
-
-static void
-glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
- int dstpitch,int srcpitch,
- int bltwidth,int bltheight)
-{
- int x,y;
- dstpitch += bltwidth;
- srcpitch += bltwidth;
- for (y = 0; y < bltheight; y++) {
- for (x = 0; x < bltwidth; x++) {
- ROP_OP(*dst, *src);
- dst--;
- src--;
- }
- dst += dstpitch;
- src += srcpitch;
- }
-}
-
-#define DEPTH 8
-#include "cirrus_vga_rop2.h"
-
-#define DEPTH 16
-#include "cirrus_vga_rop2.h"
-
-#define DEPTH 24
-#include "cirrus_vga_rop2.h"
-
-#define DEPTH 32
-#include "cirrus_vga_rop2.h"
-
-#undef ROP_NAME
-#undef ROP_OP
diff --git a/hw/cirrus_vga_rop2.h b/hw/cirrus_vga_rop2.h
deleted file mode 100644
index da11d0f..0000000
--- a/hw/cirrus_vga_rop2.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * QEMU Cirrus CLGD 54xx VGA Emulator.
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if DEPTH == 8
-#define PUTPIXEL() ROP_OP(d[0], col)
-#elif DEPTH == 16
-#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col);
-#elif DEPTH == 24
-#define PUTPIXEL() ROP_OP(d[0], col); \
- ROP_OP(d[1], (col >> 8)); \
- ROP_OP(d[2], (col >> 16))
-#elif DEPTH == 32
-#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col)
-#else
-#error unsupported DEPTH
-#endif
-
-static void
-glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
-{
- uint8_t *d;
- int x, y, pattern_y, pattern_pitch, pattern_x;
- unsigned int col;
- const uint8_t *src1;
-#if DEPTH == 24
- int skipleft = s->gr[0x2f] & 0x1f;
-#else
- int skipleft = (s->gr[0x2f] & 0x07) * (DEPTH / 8);
-#endif
-
-#if DEPTH == 8
- pattern_pitch = 8;
-#elif DEPTH == 16
- pattern_pitch = 16;
-#else
- pattern_pitch = 32;
-#endif
- pattern_y = s->cirrus_blt_srcaddr & 7;
- for(y = 0; y < bltheight; y++) {
- pattern_x = skipleft;
- d = dst + skipleft;
- src1 = src + pattern_y * pattern_pitch;
- for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
-#if DEPTH == 8
- col = src1[pattern_x];
- pattern_x = (pattern_x + 1) & 7;
-#elif DEPTH == 16
- col = ((uint16_t *)(src1 + pattern_x))[0];
- pattern_x = (pattern_x + 2) & 15;
-#elif DEPTH == 24
- {
- const uint8_t *src2 = src1 + pattern_x * 3;
- col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
- pattern_x = (pattern_x + 1) & 7;
- }
-#else
- col = ((uint32_t *)(src1 + pattern_x))[0];
- pattern_x = (pattern_x + 4) & 31;
-#endif
- PUTPIXEL();
- d += (DEPTH / 8);
- }
- pattern_y = (pattern_y + 1) & 7;
- dst += dstpitch;
- }
-}
-
-/* NOTE: srcpitch is ignored */
-static void
-glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
-{
- uint8_t *d;
- int x, y;
- unsigned bits, bits_xor;
- unsigned int col;
- unsigned bitmask;
- unsigned index;
-#if DEPTH == 24
- int dstskipleft = s->gr[0x2f] & 0x1f;
- int srcskipleft = dstskipleft / 3;
-#else
- int srcskipleft = s->gr[0x2f] & 0x07;
- int dstskipleft = srcskipleft * (DEPTH / 8);
-#endif
-
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
- bits_xor = 0xff;
- col = s->cirrus_blt_bgcol;
- } else {
- bits_xor = 0x00;
- col = s->cirrus_blt_fgcol;
- }
-
- for(y = 0; y < bltheight; y++) {
- bitmask = 0x80 >> srcskipleft;
- bits = *src++ ^ bits_xor;
- d = dst + dstskipleft;
- for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
- if ((bitmask & 0xff) == 0) {
- bitmask = 0x80;
- bits = *src++ ^ bits_xor;
- }
- index = (bits & bitmask);
- if (index) {
- PUTPIXEL();
- }
- d += (DEPTH / 8);
- bitmask >>= 1;
- }
- dst += dstpitch;
- }
-}
-
-static void
-glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
-{
- uint32_t colors[2];
- uint8_t *d;
- int x, y;
- unsigned bits;
- unsigned int col;
- unsigned bitmask;
- int srcskipleft = s->gr[0x2f] & 0x07;
- int dstskipleft = srcskipleft * (DEPTH / 8);
-
- colors[0] = s->cirrus_blt_bgcol;
- colors[1] = s->cirrus_blt_fgcol;
- for(y = 0; y < bltheight; y++) {
- bitmask = 0x80 >> srcskipleft;
- bits = *src++;
- d = dst + dstskipleft;
- for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
- if ((bitmask & 0xff) == 0) {
- bitmask = 0x80;
- bits = *src++;
- }
- col = colors[!!(bits & bitmask)];
- PUTPIXEL();
- d += (DEPTH / 8);
- bitmask >>= 1;
- }
- dst += dstpitch;
- }
-}
-
-static void
-glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
-{
- uint8_t *d;
- int x, y, bitpos, pattern_y;
- unsigned int bits, bits_xor;
- unsigned int col;
-#if DEPTH == 24
- int dstskipleft = s->gr[0x2f] & 0x1f;
- int srcskipleft = dstskipleft / 3;
-#else
- int srcskipleft = s->gr[0x2f] & 0x07;
- int dstskipleft = srcskipleft * (DEPTH / 8);
-#endif
-
- if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
- bits_xor = 0xff;
- col = s->cirrus_blt_bgcol;
- } else {
- bits_xor = 0x00;
- col = s->cirrus_blt_fgcol;
- }
- pattern_y = s->cirrus_blt_srcaddr & 7;
-
- for(y = 0; y < bltheight; y++) {
- bits = src[pattern_y] ^ bits_xor;
- bitpos = 7 - srcskipleft;
- d = dst + dstskipleft;
- for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
- if ((bits >> bitpos) & 1) {
- PUTPIXEL();
- }
- d += (DEPTH / 8);
- bitpos = (bitpos - 1) & 7;
- }
- pattern_y = (pattern_y + 1) & 7;
- dst += dstpitch;
- }
-}
-
-static void
-glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
- int dstpitch, int srcpitch,
- int bltwidth, int bltheight)
-{
- uint32_t colors[2];
- uint8_t *d;
- int x, y, bitpos, pattern_y;
- unsigned int bits;
- unsigned int col;
- int srcskipleft = s->gr[0x2f] & 0x07;
- int dstskipleft = srcskipleft * (DEPTH / 8);
-
- colors[0] = s->cirrus_blt_bgcol;
- colors[1] = s->cirrus_blt_fgcol;
- pattern_y = s->cirrus_blt_srcaddr & 7;
-
- for(y = 0; y < bltheight; y++) {
- bits = src[pattern_y];
- bitpos = 7 - srcskipleft;
- d = dst + dstskipleft;
- for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
- col = colors[(bits >> bitpos) & 1];
- PUTPIXEL();
- d += (DEPTH / 8);
- bitpos = (bitpos - 1) & 7;
- }
- pattern_y = (pattern_y + 1) & 7;
- dst += dstpitch;
- }
-}
-
-static void
-glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
- (CirrusVGAState *s,
- uint8_t *dst, int dst_pitch,
- int width, int height)
-{
- uint8_t *d, *d1;
- uint32_t col;
- int x, y;
-
- col = s->cirrus_blt_fgcol;
-
- d1 = dst;
- for(y = 0; y < height; y++) {
- d = d1;
- for(x = 0; x < width; x += (DEPTH / 8)) {
- PUTPIXEL();
- d += (DEPTH / 8);
- }
- d1 += dst_pitch;
- }
-}
-
-#undef DEPTH
-#undef PUTPIXEL
diff --git a/hw/cuda.c b/hw/cuda.c
deleted file mode 100644
index f3c2b56..0000000
--- a/hw/cuda.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
- * QEMU CUDA support
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* XXX: implement all timer modes */
-
-//#define DEBUG_CUDA
-//#define DEBUG_CUDA_PACKET
-
-/* Bits in B data register: all active low */
-#define TREQ 0x08 /* Transfer request (input) */
-#define TACK 0x10 /* Transfer acknowledge (output) */
-#define TIP 0x20 /* Transfer in progress (output) */
-
-/* Bits in ACR */
-#define SR_CTRL 0x1c /* Shift register control bits */
-#define SR_EXT 0x0c /* Shift on external clock */
-#define SR_OUT 0x10 /* Shift out if 1 */
-
-/* Bits in IFR and IER */
-#define IER_SET 0x80 /* set bits in IER */
-#define IER_CLR 0 /* clear bits in IER */
-#define SR_INT 0x04 /* Shift register full/empty */
-#define T1_INT 0x40 /* Timer 1 interrupt */
-#define T2_INT 0x20 /* Timer 2 interrupt */
-
-/* Bits in ACR */
-#define T1MODE 0xc0 /* Timer 1 mode */
-#define T1MODE_CONT 0x40 /* continuous interrupts */
-
-/* commands (1st byte) */
-#define ADB_PACKET 0
-#define CUDA_PACKET 1
-#define ERROR_PACKET 2
-#define TIMER_PACKET 3
-#define POWER_PACKET 4
-#define MACIIC_PACKET 5
-#define PMU_PACKET 6
-
-
-/* CUDA commands (2nd byte) */
-#define CUDA_WARM_START 0x0
-#define CUDA_AUTOPOLL 0x1
-#define CUDA_GET_6805_ADDR 0x2
-#define CUDA_GET_TIME 0x3
-#define CUDA_GET_PRAM 0x7
-#define CUDA_SET_6805_ADDR 0x8
-#define CUDA_SET_TIME 0x9
-#define CUDA_POWERDOWN 0xa
-#define CUDA_POWERUP_TIME 0xb
-#define CUDA_SET_PRAM 0xc
-#define CUDA_MS_RESET 0xd
-#define CUDA_SEND_DFAC 0xe
-#define CUDA_BATTERY_SWAP_SENSE 0x10
-#define CUDA_RESET_SYSTEM 0x11
-#define CUDA_SET_IPL 0x12
-#define CUDA_FILE_SERVER_FLAG 0x13
-#define CUDA_SET_AUTO_RATE 0x14
-#define CUDA_GET_AUTO_RATE 0x16
-#define CUDA_SET_DEVICE_LIST 0x19
-#define CUDA_GET_DEVICE_LIST 0x1a
-#define CUDA_SET_ONE_SECOND_MODE 0x1b
-#define CUDA_SET_POWER_MESSAGES 0x21
-#define CUDA_GET_SET_IIC 0x22
-#define CUDA_WAKEUP 0x23
-#define CUDA_TIMER_TICKLE 0x24
-#define CUDA_COMBINED_FORMAT_IIC 0x25
-
-#define CUDA_TIMER_FREQ (4700000 / 6)
-#define CUDA_ADB_POLL_FREQ 50
-
-/* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
-#define RTC_OFFSET 2082844800
-
-typedef struct CUDATimer {
- int index;
- uint16_t latch;
- uint16_t counter_value; /* counter value at load time */
- int64_t load_time;
- int64_t next_irq_time;
- QEMUTimer *timer;
-} CUDATimer;
-
-typedef struct CUDAState {
- /* cuda registers */
- uint8_t b; /* B-side data */
- uint8_t a; /* A-side data */
- uint8_t dirb; /* B-side direction (1=output) */
- uint8_t dira; /* A-side direction (1=output) */
- uint8_t sr; /* Shift register */
- uint8_t acr; /* Auxiliary control register */
- uint8_t pcr; /* Peripheral control register */
- uint8_t ifr; /* Interrupt flag register */
- uint8_t ier; /* Interrupt enable register */
- uint8_t anh; /* A-side data, no handshake */
-
- CUDATimer timers[2];
-
- uint8_t last_b; /* last value of B register */
- uint8_t last_acr; /* last value of B register */
-
- int data_in_size;
- int data_in_index;
- int data_out_index;
-
- SetIRQFunc *set_irq;
- int irq;
- void *irq_opaque;
- uint8_t autopoll;
- uint8_t data_in[128];
- uint8_t data_out[16];
- QEMUTimer *adb_poll_timer;
-} CUDAState;
-
-static CUDAState cuda_state;
-ADBBusState adb_bus;
-
-static void cuda_update(CUDAState *s);
-static void cuda_receive_packet_from_host(CUDAState *s,
- const uint8_t *data, int len);
-static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
- int64_t current_time);
-
-static void cuda_update_irq(CUDAState *s)
-{
- if (s->ifr & s->ier & (SR_INT | T1_INT)) {
- s->set_irq(s->irq_opaque, s->irq, 1);
- } else {
- s->set_irq(s->irq_opaque, s->irq, 0);
- }
-}
-
-static unsigned int get_counter(CUDATimer *s)
-{
- int64_t d;
- unsigned int counter;
-
- d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
- CUDA_TIMER_FREQ, ticks_per_sec);
- if (s->index == 0) {
- /* the timer goes down from latch to -1 (period of latch + 2) */
- if (d <= (s->counter_value + 1)) {
- counter = (s->counter_value - d) & 0xffff;
- } else {
- counter = (d - (s->counter_value + 1)) % (s->latch + 2);
- counter = (s->latch - counter) & 0xffff;
- }
- } else {
- counter = (s->counter_value - d) & 0xffff;
- }
- return counter;
-}
-
-static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
-{
-#ifdef DEBUG_CUDA
- printf("cuda: T%d.counter=%d\n",
- 1 + (ti->timer == NULL), val);
-#endif
- ti->load_time = qemu_get_clock(vm_clock);
- ti->counter_value = val;
- cuda_timer_update(s, ti, ti->load_time);
-}
-
-static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
-{
- int64_t d, next_time;
- unsigned int counter;
-
- /* current counter value */
- d = muldiv64(current_time - s->load_time,
- CUDA_TIMER_FREQ, ticks_per_sec);
- /* the timer goes down from latch to -1 (period of latch + 2) */
- if (d <= (s->counter_value + 1)) {
- counter = (s->counter_value - d) & 0xffff;
- } else {
- counter = (d - (s->counter_value + 1)) % (s->latch + 2);
- counter = (s->latch - counter) & 0xffff;
- }
-
- /* Note: we consider the irq is raised on 0 */
- if (counter == 0xffff) {
- next_time = d + s->latch + 1;
- } else if (counter == 0) {
- next_time = d + s->latch + 2;
- } else {
- next_time = d + counter;
- }
-#if 0
-#ifdef DEBUG_CUDA
- printf("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
- s->latch, d, next_time - d);
-#endif
-#endif
- next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
- s->load_time;
- if (next_time <= current_time)
- next_time = current_time + 1;
- return next_time;
-}
-
-static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
- int64_t current_time)
-{
- if (!ti->timer)
- return;
- if ((s->acr & T1MODE) != T1MODE_CONT) {
- qemu_del_timer(ti->timer);
- } else {
- ti->next_irq_time = get_next_irq_time(ti, current_time);
- qemu_mod_timer(ti->timer, ti->next_irq_time);
- }
-}
-
-static void cuda_timer1(void *opaque)
-{
- CUDAState *s = opaque;
- CUDATimer *ti = &s->timers[0];
-
- cuda_timer_update(s, ti, ti->next_irq_time);
- s->ifr |= T1_INT;
- cuda_update_irq(s);
-}
-
-static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
-{
- CUDAState *s = opaque;
- uint32_t val;
-
- addr = (addr >> 9) & 0xf;
- switch(addr) {
- case 0:
- val = s->b;
- break;
- case 1:
- val = s->a;
- break;
- case 2:
- val = s->dirb;
- break;
- case 3:
- val = s->dira;
- break;
- case 4:
- val = get_counter(&s->timers[0]) & 0xff;
- s->ifr &= ~T1_INT;
- cuda_update_irq(s);
- break;
- case 5:
- val = get_counter(&s->timers[0]) >> 8;
- cuda_update_irq(s);
- break;
- case 6:
- val = s->timers[0].latch & 0xff;
- break;
- case 7:
- /* XXX: check this */
- val = (s->timers[0].latch >> 8) & 0xff;
- break;
- case 8:
- val = get_counter(&s->timers[1]) & 0xff;
- s->ifr &= ~T2_INT;
- break;
- case 9:
- val = get_counter(&s->timers[1]) >> 8;
- break;
- case 10:
- val = s->sr;
- s->ifr &= ~SR_INT;
- cuda_update_irq(s);
- break;
- case 11:
- val = s->acr;
- break;
- case 12:
- val = s->pcr;
- break;
- case 13:
- val = s->ifr;
- if (s->ifr & s->ier)
- val |= 0x80;
- break;
- case 14:
- val = s->ier | 0x80;
- break;
- default:
- case 15:
- val = s->anh;
- break;
- }
-#ifdef DEBUG_CUDA
- if (addr != 13 || val != 0)
- printf("cuda: read: reg=0x%x val=%02x\n", addr, val);
-#endif
- return val;
-}
-
-static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- CUDAState *s = opaque;
-
- addr = (addr >> 9) & 0xf;
-#ifdef DEBUG_CUDA
- printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
-#endif
-
- switch(addr) {
- case 0:
- s->b = val;
- cuda_update(s);
- break;
- case 1:
- s->a = val;
- break;
- case 2:
- s->dirb = val;
- break;
- case 3:
- s->dira = val;
- break;
- case 4:
- s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
- break;
- case 5:
- s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
- s->ifr &= ~T1_INT;
- set_counter(s, &s->timers[0], s->timers[0].latch);
- break;
- case 6:
- s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
- break;
- case 7:
- s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
- s->ifr &= ~T1_INT;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
- break;
- case 8:
- s->timers[1].latch = val;
- set_counter(s, &s->timers[1], val);
- break;
- case 9:
- set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
- break;
- case 10:
- s->sr = val;
- break;
- case 11:
- s->acr = val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
- cuda_update(s);
- break;
- case 12:
- s->pcr = val;
- break;
- case 13:
- /* reset bits */
- s->ifr &= ~val;
- cuda_update_irq(s);
- break;
- case 14:
- if (val & IER_SET) {
- /* set bits */
- s->ier |= val & 0x7f;
- } else {
- /* reset bits */
- s->ier &= ~val;
- }
- cuda_update_irq(s);
- break;
- default:
- case 15:
- s->anh = val;
- break;
- }
-}
-
-/* NOTE: TIP and TREQ are negated */
-static void cuda_update(CUDAState *s)
-{
- int packet_received, len;
-
- packet_received = 0;
- if (!(s->b & TIP)) {
- /* transfer requested from host */
-
- if (s->acr & SR_OUT) {
- /* data output */
- if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
- if (s->data_out_index < sizeof(s->data_out)) {
-#ifdef DEBUG_CUDA
- printf("cuda: send: %02x\n", s->sr);
-#endif
- s->data_out[s->data_out_index++] = s->sr;
- s->ifr |= SR_INT;
- cuda_update_irq(s);
- }
- }
- } else {
- if (s->data_in_index < s->data_in_size) {
- /* data input */
- if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
- s->sr = s->data_in[s->data_in_index++];
-#ifdef DEBUG_CUDA
- printf("cuda: recv: %02x\n", s->sr);
-#endif
- /* indicate end of transfer */
- if (s->data_in_index >= s->data_in_size) {
- s->b = (s->b | TREQ);
- }
- s->ifr |= SR_INT;
- cuda_update_irq(s);
- }
- }
- }
- } else {
- /* no transfer requested: handle sync case */
- if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
- /* update TREQ state each time TACK change state */
- if (s->b & TACK)
- s->b = (s->b | TREQ);
- else
- s->b = (s->b & ~TREQ);
- s->ifr |= SR_INT;
- cuda_update_irq(s);
- } else {
- if (!(s->last_b & TIP)) {
- /* handle end of host to cuda transfert */
- packet_received = (s->data_out_index > 0);
- /* always an IRQ at the end of transfert */
- s->ifr |= SR_INT;
- cuda_update_irq(s);
- }
- /* signal if there is data to read */
- if (s->data_in_index < s->data_in_size) {
- s->b = (s->b & ~TREQ);
- }
- }
- }
-
- s->last_acr = s->acr;
- s->last_b = s->b;
-
- /* NOTE: cuda_receive_packet_from_host() can call cuda_update()
- recursively */
- if (packet_received) {
- len = s->data_out_index;
- s->data_out_index = 0;
- cuda_receive_packet_from_host(s, s->data_out, len);
- }
-}
-
-static void cuda_send_packet_to_host(CUDAState *s,
- const uint8_t *data, int len)
-{
-#ifdef DEBUG_CUDA_PACKET
- {
- int i;
- printf("cuda_send_packet_to_host:\n");
- for(i = 0; i < len; i++)
- printf(" %02x", data[i]);
- printf("\n");
- }
-#endif
- memcpy(s->data_in, data, len);
- s->data_in_size = len;
- s->data_in_index = 0;
- cuda_update(s);
- s->ifr |= SR_INT;
- cuda_update_irq(s);
-}
-
-static void cuda_adb_poll(void *opaque)
-{
- CUDAState *s = opaque;
- uint8_t obuf[ADB_MAX_OUT_LEN + 2];
- int olen;
-
- olen = adb_poll(&adb_bus, obuf + 2);
- if (olen > 0) {
- obuf[0] = ADB_PACKET;
- obuf[1] = 0x40; /* polled data */
- cuda_send_packet_to_host(s, obuf, olen + 2);
- }
- qemu_mod_timer(s->adb_poll_timer,
- qemu_get_clock(vm_clock) +
- (ticks_per_sec / CUDA_ADB_POLL_FREQ));
-}
-
-static void cuda_receive_packet(CUDAState *s,
- const uint8_t *data, int len)
-{
- uint8_t obuf[16];
- int ti, autopoll;
-
- switch(data[0]) {
- case CUDA_AUTOPOLL:
- autopoll = (data[1] != 0);
- if (autopoll != s->autopoll) {
- s->autopoll = autopoll;
- if (autopoll) {
- qemu_mod_timer(s->adb_poll_timer,
- qemu_get_clock(vm_clock) +
- (ticks_per_sec / CUDA_ADB_POLL_FREQ));
- } else {
- qemu_del_timer(s->adb_poll_timer);
- }
- }
- obuf[0] = CUDA_PACKET;
- obuf[1] = data[1];
- cuda_send_packet_to_host(s, obuf, 2);
- break;
- case CUDA_GET_TIME:
- case CUDA_SET_TIME:
- /* XXX: add time support ? */
- ti = time(NULL) + RTC_OFFSET;
- obuf[0] = CUDA_PACKET;
- obuf[1] = 0;
- obuf[2] = 0;
- obuf[3] = ti >> 24;
- obuf[4] = ti >> 16;
- obuf[5] = ti >> 8;
- obuf[6] = ti;
- cuda_send_packet_to_host(s, obuf, 7);
- break;
- case CUDA_FILE_SERVER_FLAG:
- case CUDA_SET_DEVICE_LIST:
- case CUDA_SET_AUTO_RATE:
- case CUDA_SET_POWER_MESSAGES:
- obuf[0] = CUDA_PACKET;
- obuf[1] = 0;
- cuda_send_packet_to_host(s, obuf, 2);
- break;
- case CUDA_POWERDOWN:
- obuf[0] = CUDA_PACKET;
- obuf[1] = 0;
- cuda_send_packet_to_host(s, obuf, 2);
- qemu_system_shutdown_request();
- break;
- default:
- break;
- }
-}
-
-static void cuda_receive_packet_from_host(CUDAState *s,
- const uint8_t *data, int len)
-{
-#ifdef DEBUG_CUDA_PACKET
- {
- int i;
- printf("cuda_receive_packet_from_host:\n");
- for(i = 0; i < len; i++)
- printf(" %02x", data[i]);
- printf("\n");
- }
-#endif
- switch(data[0]) {
- case ADB_PACKET:
- {
- uint8_t obuf[ADB_MAX_OUT_LEN + 2];
- int olen;
- olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
- if (olen > 0) {
- obuf[0] = ADB_PACKET;
- obuf[1] = 0x00;
- } else {
- /* error */
- obuf[0] = ADB_PACKET;
- obuf[1] = -olen;
- olen = 0;
- }
- cuda_send_packet_to_host(s, obuf, olen + 2);
- }
- break;
- case CUDA_PACKET:
- cuda_receive_packet(s, data + 1, len - 1);
- break;
- }
-}
-
-static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static CPUWriteMemoryFunc *cuda_write[] = {
- &cuda_writeb,
- &cuda_writew,
- &cuda_writel,
-};
-
-static CPUReadMemoryFunc *cuda_read[] = {
- &cuda_readb,
- &cuda_readw,
- &cuda_readl,
-};
-
-int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq)
-{
- CUDAState *s = &cuda_state;
- int cuda_mem_index;
-
- s->set_irq = set_irq;
- s->irq_opaque = irq_opaque;
- s->irq = irq;
-
- s->timers[0].index = 0;
- s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
- s->timers[0].latch = 0xffff;
- set_counter(s, &s->timers[0], 0xffff);
-
- s->timers[1].index = 1;
- s->timers[1].latch = 0;
- // s->ier = T1_INT | SR_INT;
- s->ier = 0;
- set_counter(s, &s->timers[1], 0xffff);
-
- s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
- cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
- return cuda_mem_index;
-}
diff --git a/hw/es1370.c b/hw/es1370.c
deleted file mode 100644
index 0d2d861..0000000
--- a/hw/es1370.c
+++ /dev/null
@@ -1,1062 +0,0 @@
-/*
- * QEMU ES1370 emulation
- *
- * Copyright (c) 2005 Vassili Karpov (malc)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/* #define DEBUG_ES1370 */
-/* #define VERBOSE_ES1370 */
-#define SILENT_ES1370
-
-#include "vl.h"
-
-/* Missing stuff:
- SCTRL_P[12](END|ST)INC
- SCTRL_P1SCTRLD
- SCTRL_P2DACSEN
- CTRL_DAC_SYNC
- MIDI
- non looped mode
- surely more
-*/
-
-/*
- Following macros and samplerate array were copied verbatim from
- Linux kernel 2.4.30: drivers/sound/es1370.c
-
- Copyright (C) 1998-2001, 2003 Thomas Sailer (t.sailer@alumni.ethz.ch)
-*/
-
-/* Start blatant GPL violation */
-
-#define ES1370_REG_CONTROL 0x00
-#define ES1370_REG_STATUS 0x04
-#define ES1370_REG_UART_DATA 0x08
-#define ES1370_REG_UART_STATUS 0x09
-#define ES1370_REG_UART_CONTROL 0x09
-#define ES1370_REG_UART_TEST 0x0a
-#define ES1370_REG_MEMPAGE 0x0c
-#define ES1370_REG_CODEC 0x10
-#define ES1370_REG_SERIAL_CONTROL 0x20
-#define ES1370_REG_DAC1_SCOUNT 0x24
-#define ES1370_REG_DAC2_SCOUNT 0x28
-#define ES1370_REG_ADC_SCOUNT 0x2c
-
-#define ES1370_REG_DAC1_FRAMEADR 0xc30
-#define ES1370_REG_DAC1_FRAMECNT 0xc34
-#define ES1370_REG_DAC2_FRAMEADR 0xc38
-#define ES1370_REG_DAC2_FRAMECNT 0xc3c
-#define ES1370_REG_ADC_FRAMEADR 0xd30
-#define ES1370_REG_ADC_FRAMECNT 0xd34
-#define ES1370_REG_PHANTOM_FRAMEADR 0xd38
-#define ES1370_REG_PHANTOM_FRAMECNT 0xd3c
-
-static const unsigned dac1_samplerate[] = { 5512, 11025, 22050, 44100 };
-
-#define DAC2_SRTODIV(x) (((1411200+(x)/2)/(x))-2)
-#define DAC2_DIVTOSR(x) (1411200/((x)+2))
-
-#define CTRL_ADC_STOP 0x80000000 /* 1 = ADC stopped */
-#define CTRL_XCTL1 0x40000000 /* electret mic bias */
-#define CTRL_OPEN 0x20000000 /* no function, can be read and written */
-#define CTRL_PCLKDIV 0x1fff0000 /* ADC/DAC2 clock divider */
-#define CTRL_SH_PCLKDIV 16
-#define CTRL_MSFMTSEL 0x00008000 /* MPEG serial data fmt: 0 = Sony, 1 = I2S */
-#define CTRL_M_SBB 0x00004000 /* DAC2 clock: 0 = PCLKDIV, 1 = MPEG */
-#define CTRL_WTSRSEL 0x00003000 /* DAC1 clock freq: 0=5512, 1=11025, 2=22050, 3=44100 */
-#define CTRL_SH_WTSRSEL 12
-#define CTRL_DAC_SYNC 0x00000800 /* 1 = DAC2 runs off DAC1 clock */
-#define CTRL_CCB_INTRM 0x00000400 /* 1 = CCB "voice" ints enabled */
-#define CTRL_M_CB 0x00000200 /* recording source: 0 = ADC, 1 = MPEG */
-#define CTRL_XCTL0 0x00000100 /* 0 = Line in, 1 = Line out */
-#define CTRL_BREQ 0x00000080 /* 1 = test mode (internal mem test) */
-#define CTRL_DAC1_EN 0x00000040 /* enable DAC1 */
-#define CTRL_DAC2_EN 0x00000020 /* enable DAC2 */
-#define CTRL_ADC_EN 0x00000010 /* enable ADC */
-#define CTRL_UART_EN 0x00000008 /* enable MIDI uart */
-#define CTRL_JYSTK_EN 0x00000004 /* enable Joystick port (presumably at address 0x200) */
-#define CTRL_CDC_EN 0x00000002 /* enable serial (CODEC) interface */
-#define CTRL_SERR_DIS 0x00000001 /* 1 = disable PCI SERR signal */
-
-#define STAT_INTR 0x80000000 /* wired or of all interrupt bits */
-#define STAT_CSTAT 0x00000400 /* 1 = codec busy or codec write in progress */
-#define STAT_CBUSY 0x00000200 /* 1 = codec busy */
-#define STAT_CWRIP 0x00000100 /* 1 = codec write in progress */
-#define STAT_VC 0x00000060 /* CCB int source, 0=DAC1, 1=DAC2, 2=ADC, 3=undef */
-#define STAT_SH_VC 5
-#define STAT_MCCB 0x00000010 /* CCB int pending */
-#define STAT_UART 0x00000008 /* UART int pending */
-#define STAT_DAC1 0x00000004 /* DAC1 int pending */
-#define STAT_DAC2 0x00000002 /* DAC2 int pending */
-#define STAT_ADC 0x00000001 /* ADC int pending */
-
-#define USTAT_RXINT 0x80 /* UART rx int pending */
-#define USTAT_TXINT 0x04 /* UART tx int pending */
-#define USTAT_TXRDY 0x02 /* UART tx ready */
-#define USTAT_RXRDY 0x01 /* UART rx ready */
-
-#define UCTRL_RXINTEN 0x80 /* 1 = enable RX ints */
-#define UCTRL_TXINTEN 0x60 /* TX int enable field mask */
-#define UCTRL_ENA_TXINT 0x20 /* enable TX int */
-#define UCTRL_CNTRL 0x03 /* control field */
-#define UCTRL_CNTRL_SWR 0x03 /* software reset command */
-
-#define SCTRL_P2ENDINC 0x00380000 /* */
-#define SCTRL_SH_P2ENDINC 19
-#define SCTRL_P2STINC 0x00070000 /* */
-#define SCTRL_SH_P2STINC 16
-#define SCTRL_R1LOOPSEL 0x00008000 /* 0 = loop mode */
-#define SCTRL_P2LOOPSEL 0x00004000 /* 0 = loop mode */
-#define SCTRL_P1LOOPSEL 0x00002000 /* 0 = loop mode */
-#define SCTRL_P2PAUSE 0x00001000 /* 1 = pause mode */
-#define SCTRL_P1PAUSE 0x00000800 /* 1 = pause mode */
-#define SCTRL_R1INTEN 0x00000400 /* enable interrupt */
-#define SCTRL_P2INTEN 0x00000200 /* enable interrupt */
-#define SCTRL_P1INTEN 0x00000100 /* enable interrupt */
-#define SCTRL_P1SCTRLD 0x00000080 /* reload sample count register for DAC1 */
-#define SCTRL_P2DACSEN 0x00000040 /* 1 = DAC2 play back last sample when disabled */
-#define SCTRL_R1SEB 0x00000020 /* 1 = 16bit */
-#define SCTRL_R1SMB 0x00000010 /* 1 = stereo */
-#define SCTRL_R1FMT 0x00000030 /* format mask */
-#define SCTRL_SH_R1FMT 4
-#define SCTRL_P2SEB 0x00000008 /* 1 = 16bit */
-#define SCTRL_P2SMB 0x00000004 /* 1 = stereo */
-#define SCTRL_P2FMT 0x0000000c /* format mask */
-#define SCTRL_SH_P2FMT 2
-#define SCTRL_P1SEB 0x00000002 /* 1 = 16bit */
-#define SCTRL_P1SMB 0x00000001 /* 1 = stereo */
-#define SCTRL_P1FMT 0x00000003 /* format mask */
-#define SCTRL_SH_P1FMT 0
-
-/* End blatant GPL violation */
-
-#define NB_CHANNELS 3
-#define DAC1_CHANNEL 0
-#define DAC2_CHANNEL 1
-#define ADC_CHANNEL 2
-
-#define IO_READ_PROTO(n) \
-static uint32_t n (void *opaque, uint32_t addr)
-#define IO_WRITE_PROTO(n) \
-static void n (void *opaque, uint32_t addr, uint32_t val)
-
-static void es1370_dac1_callback (void *opaque, int free);
-static void es1370_dac2_callback (void *opaque, int free);
-static void es1370_adc_callback (void *opaque, int avail);
-
-#ifdef DEBUG_ES1370
-
-#define ldebug(...) AUD_log ("es1370", __VA_ARGS__)
-
-static void print_ctl (uint32_t val)
-{
- char buf[1024];
-
- buf[0] = '\0';
-#define a(n) if (val & CTRL_##n) strcat (buf, " "#n)
- a (ADC_STOP);
- a (XCTL1);
- a (OPEN);
- a (MSFMTSEL);
- a (M_SBB);
- a (DAC_SYNC);
- a (CCB_INTRM);
- a (M_CB);
- a (XCTL0);
- a (BREQ);
- a (DAC1_EN);
- a (DAC2_EN);
- a (ADC_EN);
- a (UART_EN);
- a (JYSTK_EN);
- a (CDC_EN);
- a (SERR_DIS);
-#undef a
- AUD_log ("es1370", "ctl - PCLKDIV %d(DAC2 freq %d), freq %d,%s\n",
- (val & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV,
- DAC2_DIVTOSR ((val & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV),
- dac1_samplerate[(val & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL],
- buf);
-}
-
-static void print_sctl (uint32_t val)
-{
- static const char *fmt_names[] = {"8M", "8S", "16M", "16S"};
- char buf[1024];
-
- buf[0] = '\0';
-
-#define a(n) if (val & SCTRL_##n) strcat (buf, " "#n)
-#define b(n) if (!(val & SCTRL_##n)) strcat (buf, " "#n)
- b (R1LOOPSEL);
- b (P2LOOPSEL);
- b (P1LOOPSEL);
- a (P2PAUSE);
- a (P1PAUSE);
- a (R1INTEN);
- a (P2INTEN);
- a (P1INTEN);
- a (P1SCTRLD);
- a (P2DACSEN);
- if (buf[0]) {
- strcat (buf, "\n ");
- }
- else {
- buf[0] = ' ';
- buf[1] = '\0';
- }
-#undef b
-#undef a
- AUD_log ("es1370",
- "%s"
- "p2_end_inc %d, p2_st_inc %d, r1_fmt %s, p2_fmt %s, p1_fmt %s\n",
- buf,
- (val & SCTRL_P2ENDINC) >> SCTRL_SH_P2ENDINC,
- (val & SCTRL_P2STINC) >> SCTRL_SH_P2STINC,
- fmt_names [(val >> SCTRL_SH_R1FMT) & 3],
- fmt_names [(val >> SCTRL_SH_P2FMT) & 3],
- fmt_names [(val >> SCTRL_SH_P1FMT) & 3]
- );
-}
-#else
-#define ldebug(...)
-#define print_ctl(...)
-#define print_sctl(...)
-#endif
-
-#ifdef VERBOSE_ES1370
-#define dolog(...) AUD_log ("es1370", __VA_ARGS__)
-#else
-#define dolog(...)
-#endif
-
-#ifndef SILENT_ES1370
-#define lwarn(...) AUD_log ("es1370: warning", __VA_ARGS__)
-#else
-#define lwarn(...)
-#endif
-
-struct chan {
- uint32_t shift;
- uint32_t leftover;
- uint32_t scount;
- uint32_t frame_addr;
- uint32_t frame_cnt;
-};
-
-typedef struct ES1370State {
- PCIDevice *pci_dev;
-
- QEMUSoundCard card;
- struct chan chan[NB_CHANNELS];
- SWVoiceOut *dac_voice[2];
- SWVoiceIn *adc_voice;
-
- uint32_t ctl;
- uint32_t status;
- uint32_t mempage;
- uint32_t codec;
- uint32_t sctl;
-} ES1370State;
-
-typedef struct PCIES1370State {
- PCIDevice dev;
- ES1370State es1370;
-} PCIES1370State;
-
-struct chan_bits {
- uint32_t ctl_en;
- uint32_t stat_int;
- uint32_t sctl_pause;
- uint32_t sctl_inten;
- uint32_t sctl_fmt;
- uint32_t sctl_sh_fmt;
- uint32_t sctl_loopsel;
- void (*calc_freq) (ES1370State *s, uint32_t ctl,
- uint32_t *old_freq, uint32_t *new_freq);
-};
-
-static void es1370_dac1_calc_freq (ES1370State *s, uint32_t ctl,
- uint32_t *old_freq, uint32_t *new_freq);
-static void es1370_dac2_and_adc_calc_freq (ES1370State *s, uint32_t ctl,
- uint32_t *old_freq,
- uint32_t *new_freq);
-
-static const struct chan_bits es1370_chan_bits[] = {
- {CTRL_DAC1_EN, STAT_DAC1, SCTRL_P1PAUSE, SCTRL_P1INTEN,
- SCTRL_P1FMT, SCTRL_SH_P1FMT, SCTRL_P1LOOPSEL,
- es1370_dac1_calc_freq},
-
- {CTRL_DAC2_EN, STAT_DAC2, SCTRL_P2PAUSE, SCTRL_P2INTEN,
- SCTRL_P2FMT, SCTRL_SH_P2FMT, SCTRL_P2LOOPSEL,
- es1370_dac2_and_adc_calc_freq},
-
- {CTRL_ADC_EN, STAT_ADC, 0, SCTRL_R1INTEN,
- SCTRL_R1FMT, SCTRL_SH_R1FMT, SCTRL_R1LOOPSEL,
- es1370_dac2_and_adc_calc_freq}
-};
-
-static void es1370_update_status (ES1370State *s, uint32_t new_status)
-{
- uint32_t level = new_status & (STAT_DAC1 | STAT_DAC2 | STAT_ADC);
-
- if (level) {
- s->status = new_status | STAT_INTR;
- }
- else {
- s->status = new_status & ~STAT_INTR;
- }
- pci_set_irq (s->pci_dev, 0, !!level);
-}
-
-static void es1370_reset (ES1370State *s)
-{
- size_t i;
-
- s->ctl = 1;
- s->status = 0x60;
- s->mempage = 0;
- s->codec = 0;
- s->sctl = 0;
-
- for (i = 0; i < NB_CHANNELS; ++i) {
- struct chan *d = &s->chan[i];
- d->scount = 0;
- d->leftover = 0;
- if (i == ADC_CHANNEL) {
- AUD_close_in (&s->card, s->adc_voice);
- s->adc_voice = NULL;
- }
- else {
- AUD_close_out (&s->card, s->dac_voice[i]);
- s->dac_voice[i] = NULL;
- }
- }
- pci_set_irq (s->pci_dev, 0, 0);
-}
-
-static void es1370_maybe_lower_irq (ES1370State *s, uint32_t sctl)
-{
- uint32_t new_status = s->status;
-
- if (!(sctl & SCTRL_P1INTEN) && (s->sctl & SCTRL_P1INTEN)) {
- new_status &= ~STAT_DAC1;
- }
-
- if (!(sctl & SCTRL_P2INTEN) && (s->sctl & SCTRL_P2INTEN)) {
- new_status &= ~STAT_DAC2;
- }
-
- if (!(sctl & SCTRL_R1INTEN) && (s->sctl & SCTRL_R1INTEN)) {
- new_status &= ~STAT_ADC;
- }
-
- if (new_status != s->status) {
- es1370_update_status (s, new_status);
- }
-}
-
-static void es1370_dac1_calc_freq (ES1370State *s, uint32_t ctl,
- uint32_t *old_freq, uint32_t *new_freq)
-
-{
- *old_freq = dac1_samplerate[(s->ctl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL];
- *new_freq = dac1_samplerate[(ctl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL];
-}
-
-static void es1370_dac2_and_adc_calc_freq (ES1370State *s, uint32_t ctl,
- uint32_t *old_freq,
- uint32_t *new_freq)
-
-{
- uint32_t old_pclkdiv, new_pclkdiv;
-
- new_pclkdiv = (ctl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV;
- old_pclkdiv = (s->ctl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV;
- *new_freq = DAC2_DIVTOSR (new_pclkdiv);
- *old_freq = DAC2_DIVTOSR (old_pclkdiv);
-}
-
-static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
-{
- size_t i;
- uint32_t old_freq, new_freq, old_fmt, new_fmt;
-
- for (i = 0; i < NB_CHANNELS; ++i) {
- struct chan *d = &s->chan[i];
- const struct chan_bits *b = &es1370_chan_bits[i];
-
- new_fmt = (sctl & b->sctl_fmt) >> b->sctl_sh_fmt;
- old_fmt = (s->sctl & b->sctl_fmt) >> b->sctl_sh_fmt;
-
- b->calc_freq (s, ctl, &old_freq, &new_freq);
-
- if ((old_fmt != new_fmt) || (old_freq != new_freq)) {
- d->shift = (new_fmt & 1) + (new_fmt >> 1);
- ldebug ("channel %d, freq = %d, nchannels %d, fmt %d, shift %d\n",
- i,
- new_freq,
- 1 << (new_fmt & 1),
- (new_fmt & 2) ? AUD_FMT_S16 : AUD_FMT_U8,
- d->shift);
- if (new_freq) {
- audsettings_t as;
-
- as.freq = new_freq;
- as.nchannels = 1 << (new_fmt & 1);
- as.fmt = (new_fmt & 2) ? AUD_FMT_S16 : AUD_FMT_U8;
- as.endianness = 0;
-
- if (i == ADC_CHANNEL) {
- s->adc_voice =
- AUD_open_in (
- &s->card,
- s->adc_voice,
- "es1370.adc",
- s,
- es1370_adc_callback,
- &as
- );
- }
- else {
- s->dac_voice[i] =
- AUD_open_out (
- &s->card,
- s->dac_voice[i],
- i ? "es1370.dac2" : "es1370.dac1",
- s,
- i ? es1370_dac2_callback : es1370_dac1_callback,
- &as
- );
- }
- }
- }
-
- if (((ctl ^ s->ctl) & b->ctl_en)
- || ((sctl ^ s->sctl) & b->sctl_pause)) {
- int on = (ctl & b->ctl_en) && !(sctl & b->sctl_pause);
-
- if (i == ADC_CHANNEL) {
- AUD_set_active_in (s->adc_voice, on);
- }
- else {
- AUD_set_active_out (s->dac_voice[i], on);
- }
- }
- }
-
- s->ctl = ctl;
- s->sctl = sctl;
-}
-
-static inline uint32_t es1370_fixup (ES1370State *s, uint32_t addr)
-{
- addr &= 0xff;
- if (addr >= 0x30 && addr <= 0x3f)
- addr |= s->mempage << 8;
- return addr;
-}
-
-IO_WRITE_PROTO (es1370_writeb)
-{
- ES1370State *s = opaque;
- uint32_t shift, mask;
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case ES1370_REG_CONTROL:
- case ES1370_REG_CONTROL + 1:
- case ES1370_REG_CONTROL + 2:
- case ES1370_REG_CONTROL + 3:
- shift = (addr - ES1370_REG_CONTROL) << 3;
- mask = 0xff << shift;
- val = (s->ctl & ~mask) | ((val & 0xff) << shift);
- es1370_update_voices (s, val, s->sctl);
- print_ctl (val);
- break;
- case ES1370_REG_MEMPAGE:
- s->mempage = val;
- break;
- case ES1370_REG_SERIAL_CONTROL:
- case ES1370_REG_SERIAL_CONTROL + 1:
- case ES1370_REG_SERIAL_CONTROL + 2:
- case ES1370_REG_SERIAL_CONTROL + 3:
- shift = (addr - ES1370_REG_SERIAL_CONTROL) << 3;
- mask = 0xff << shift;
- val = (s->sctl & ~mask) | ((val & 0xff) << shift);
- es1370_maybe_lower_irq (s, val);
- es1370_update_voices (s, s->ctl, val);
- print_sctl (val);
- break;
- default:
- lwarn ("writeb %#x <- %#x\n", addr, val);
- break;
- }
-}
-
-IO_WRITE_PROTO (es1370_writew)
-{
- ES1370State *s = opaque;
- addr = es1370_fixup (s, addr);
- uint32_t shift, mask;
- struct chan *d = &s->chan[0];
-
- switch (addr) {
- case ES1370_REG_CODEC:
- dolog ("ignored codec write address %#x, data %#x\n",
- (val >> 8) & 0xff, val & 0xff);
- s->codec = val;
- break;
-
- case ES1370_REG_CONTROL:
- case ES1370_REG_CONTROL + 2:
- shift = (addr != ES1370_REG_CONTROL) << 4;
- mask = 0xffff << shift;
- val = (s->ctl & ~mask) | ((val & 0xffff) << shift);
- es1370_update_voices (s, val, s->sctl);
- print_ctl (val);
- break;
-
- case ES1370_REG_ADC_SCOUNT:
- d++;
- case ES1370_REG_DAC2_SCOUNT:
- d++;
- case ES1370_REG_DAC1_SCOUNT:
- d->scount = (d->scount & ~0xffff) | (val & 0xffff);
- break;
-
- default:
- lwarn ("writew %#x <- %#x\n", addr, val);
- break;
- }
-}
-
-IO_WRITE_PROTO (es1370_writel)
-{
- ES1370State *s = opaque;
- struct chan *d = &s->chan[0];
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case ES1370_REG_CONTROL:
- es1370_update_voices (s, val, s->sctl);
- print_ctl (val);
- break;
-
- case ES1370_REG_MEMPAGE:
- s->mempage = val & 0xf;
- break;
-
- case ES1370_REG_SERIAL_CONTROL:
- es1370_maybe_lower_irq (s, val);
- es1370_update_voices (s, s->ctl, val);
- print_sctl (val);
- break;
-
- case ES1370_REG_ADC_SCOUNT:
- d++;
- case ES1370_REG_DAC2_SCOUNT:
- d++;
- case ES1370_REG_DAC1_SCOUNT:
- d->scount = (val & 0xffff) | (d->scount & ~0xffff);
- ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n",
- d - &s->chan[0], val >> 16, (val & 0xffff));
- break;
-
- case ES1370_REG_ADC_FRAMEADR:
- d++;
- case ES1370_REG_DAC2_FRAMEADR:
- d++;
- case ES1370_REG_DAC1_FRAMEADR:
- d->frame_addr = val;
- ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val);
- break;
-
- case ES1370_REG_PHANTOM_FRAMECNT:
- lwarn ("writing to phantom frame count %#x\n", val);
- break;
- case ES1370_REG_PHANTOM_FRAMEADR:
- lwarn ("writing to phantom frame address %#x\n", val);
- break;
-
- case ES1370_REG_ADC_FRAMECNT:
- d++;
- case ES1370_REG_DAC2_FRAMECNT:
- d++;
- case ES1370_REG_DAC1_FRAMECNT:
- d->frame_cnt = val;
- d->leftover = 0;
- ldebug ("chan %d frame count %d, buffer size %d\n",
- d - &s->chan[0], val >> 16, val & 0xffff);
- break;
-
- default:
- lwarn ("writel %#x <- %#x\n", addr, val);
- break;
- }
-}
-
-IO_READ_PROTO (es1370_readb)
-{
- ES1370State *s = opaque;
- uint32_t val;
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case 0x1b: /* Legacy */
- lwarn ("Attempt to read from legacy register\n");
- val = 5;
- break;
- case ES1370_REG_MEMPAGE:
- val = s->mempage;
- break;
- case ES1370_REG_CONTROL + 0:
- case ES1370_REG_CONTROL + 1:
- case ES1370_REG_CONTROL + 2:
- case ES1370_REG_CONTROL + 3:
- val = s->ctl >> ((addr - ES1370_REG_CONTROL) << 3);
- break;
- case ES1370_REG_STATUS + 0:
- case ES1370_REG_STATUS + 1:
- case ES1370_REG_STATUS + 2:
- case ES1370_REG_STATUS + 3:
- val = s->status >> ((addr - ES1370_REG_STATUS) << 3);
- break;
- default:
- val = ~0;
- lwarn ("readb %#x -> %#x\n", addr, val);
- break;
- }
- return val;
-}
-
-IO_READ_PROTO (es1370_readw)
-{
- ES1370State *s = opaque;
- struct chan *d = &s->chan[0];
- uint32_t val;
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case ES1370_REG_ADC_SCOUNT + 2:
- d++;
- case ES1370_REG_DAC2_SCOUNT + 2:
- d++;
- case ES1370_REG_DAC1_SCOUNT + 2:
- val = d->scount >> 16;
- break;
-
- case ES1370_REG_ADC_FRAMECNT:
- d++;
- case ES1370_REG_DAC2_FRAMECNT:
- d++;
- case ES1370_REG_DAC1_FRAMECNT:
- val = d->frame_cnt & 0xffff;
- break;
-
- case ES1370_REG_ADC_FRAMECNT + 2:
- d++;
- case ES1370_REG_DAC2_FRAMECNT + 2:
- d++;
- case ES1370_REG_DAC1_FRAMECNT + 2:
- val = d->frame_cnt >> 16;
- break;
-
- default:
- val = ~0;
- lwarn ("readw %#x -> %#x\n", addr, val);
- break;
- }
-
- return val;
-}
-
-IO_READ_PROTO (es1370_readl)
-{
- ES1370State *s = opaque;
- uint32_t val;
- struct chan *d = &s->chan[0];
-
- addr = es1370_fixup (s, addr);
-
- switch (addr) {
- case ES1370_REG_CONTROL:
- val = s->ctl;
- break;
- case ES1370_REG_STATUS:
- val = s->status;
- break;
- case ES1370_REG_MEMPAGE:
- val = s->mempage;
- break;
- case ES1370_REG_CODEC:
- val = s->codec;
- break;
- case ES1370_REG_SERIAL_CONTROL:
- val = s->sctl;
- break;
-
- case ES1370_REG_ADC_SCOUNT:
- d++;
- case ES1370_REG_DAC2_SCOUNT:
- d++;
- case ES1370_REG_DAC1_SCOUNT:
- val = d->scount;
-#ifdef DEBUG_ES1370
- {
- uint32_t curr_count = d->scount >> 16;
- uint32_t count = d->scount & 0xffff;
-
- curr_count <<= d->shift;
- count <<= d->shift;
- dolog ("read scount curr %d, total %d\n", curr_count, count);
- }
-#endif
- break;
-
- case ES1370_REG_ADC_FRAMECNT:
- d++;
- case ES1370_REG_DAC2_FRAMECNT:
- d++;
- case ES1370_REG_DAC1_FRAMECNT:
- val = d->frame_cnt;
-#ifdef DEBUG_ES1370
- {
- uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2;
- uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2;
- if (curr > size)
- dolog ("read framecnt curr %d, size %d %d\n", curr, size,
- curr > size);
- }
-#endif
- break;
-
- case ES1370_REG_ADC_FRAMEADR:
- d++;
- case ES1370_REG_DAC2_FRAMEADR:
- d++;
- case ES1370_REG_DAC1_FRAMEADR:
- val = d->frame_addr;
- break;
-
- case ES1370_REG_PHANTOM_FRAMECNT:
- val = ~0U;
- lwarn ("reading from phantom frame count\n");
- break;
- case ES1370_REG_PHANTOM_FRAMEADR:
- val = ~0U;
- lwarn ("reading from phantom frame address\n");
- break;
-
- default:
- val = ~0U;
- lwarn ("readl %#x -> %#x\n", addr, val);
- break;
- }
- return val;
-}
-
-
-static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
- int max, int *irq)
-{
- uint8_t tmpbuf[4096];
- uint32_t addr = d->frame_addr;
- int sc = d->scount & 0xffff;
- int csc = d->scount >> 16;
- int csc_bytes = (csc + 1) << d->shift;
- int cnt = d->frame_cnt >> 16;
- int size = d->frame_cnt & 0xffff;
- int left = ((size - cnt + 1) << 2) + d->leftover;
- int transfered = 0;
- int temp = audio_MIN (max, audio_MIN (left, csc_bytes));
- int index = d - &s->chan[0];
-
- addr += (cnt << 2) + d->leftover;
-
- if (index == ADC_CHANNEL) {
- while (temp) {
- int acquired, to_copy;
-
- to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf));
- acquired = AUD_read (s->adc_voice, tmpbuf, to_copy);
- if (!acquired)
- break;
-
- cpu_physical_memory_write (addr, tmpbuf, acquired);
-
- temp -= acquired;
- addr += acquired;
- transfered += acquired;
- }
- }
- else {
- SWVoiceOut *voice = s->dac_voice[index];
-
- while (temp) {
- int copied, to_copy;
-
- to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf));
- cpu_physical_memory_read (addr, tmpbuf, to_copy);
- copied = AUD_write (voice, tmpbuf, to_copy);
- if (!copied)
- break;
- temp -= copied;
- addr += copied;
- transfered += copied;
- }
- }
-
- if (csc_bytes == transfered) {
- *irq = 1;
- d->scount = sc | (sc << 16);
- ldebug ("sc = %d, rate = %f\n",
- (sc + 1) << d->shift,
- (sc + 1) / (double) 44100);
- }
- else {
- *irq = 0;
- d->scount = sc | (((csc_bytes - transfered - 1) >> d->shift) << 16);
- }
-
- cnt += (transfered + d->leftover) >> 2;
-
- if (s->sctl & loop_sel) {
- /* Bah, how stupid is that having a 0 represent true value?
- i just spent few hours on this shit */
- AUD_log ("es1370: warning", "non looping mode\n");
- }
- else {
- d->frame_cnt = size;
-
- if ((uint32_t) cnt <= d->frame_cnt)
- d->frame_cnt |= cnt << 16;
- }
-
- d->leftover = (transfered + d->leftover) & 3;
-}
-
-static void es1370_run_channel (ES1370State *s, size_t chan, int free_or_avail)
-{
- uint32_t new_status = s->status;
- int max_bytes, irq;
- struct chan *d = &s->chan[chan];
- const struct chan_bits *b = &es1370_chan_bits[chan];
-
- if (!(s->ctl & b->ctl_en) || (s->sctl & b->sctl_pause)) {
- return;
- }
-
- max_bytes = free_or_avail;
- max_bytes &= ~((1 << d->shift) - 1);
- if (!max_bytes) {
- return;
- }
-
- es1370_transfer_audio (s, d, b->sctl_loopsel, max_bytes, &irq);
-
- if (irq) {
- if (s->sctl & b->sctl_inten) {
- new_status |= b->stat_int;
- }
- }
-
- if (new_status != s->status) {
- es1370_update_status (s, new_status);
- }
-}
-
-static void es1370_dac1_callback (void *opaque, int free)
-{
- ES1370State *s = opaque;
-
- es1370_run_channel (s, DAC1_CHANNEL, free);
-}
-
-static void es1370_dac2_callback (void *opaque, int free)
-{
- ES1370State *s = opaque;
-
- es1370_run_channel (s, DAC2_CHANNEL, free);
-}
-
-static void es1370_adc_callback (void *opaque, int avail)
-{
- ES1370State *s = opaque;
-
- es1370_run_channel (s, ADC_CHANNEL, avail);
-}
-
-static void es1370_map (PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCIES1370State *d = (PCIES1370State *) pci_dev;
- ES1370State *s = &d->es1370;
-
- (void) region_num;
- (void) size;
- (void) type;
-
- register_ioport_write (addr, 0x40 * 4, 1, es1370_writeb, s);
- register_ioport_write (addr, 0x40 * 2, 2, es1370_writew, s);
- register_ioport_write (addr, 0x40, 4, es1370_writel, s);
-
- register_ioport_read (addr, 0x40 * 4, 1, es1370_readb, s);
- register_ioport_read (addr, 0x40 * 2, 2, es1370_readw, s);
- register_ioport_read (addr, 0x40, 4, es1370_readl, s);
-}
-
-static void es1370_save (QEMUFile *f, void *opaque)
-{
- ES1370State *s = opaque;
- size_t i;
-
- for (i = 0; i < NB_CHANNELS; ++i) {
- struct chan *d = &s->chan[i];
- qemu_put_be32s (f, &d->shift);
- qemu_put_be32s (f, &d->leftover);
- qemu_put_be32s (f, &d->scount);
- qemu_put_be32s (f, &d->frame_addr);
- qemu_put_be32s (f, &d->frame_cnt);
- }
- qemu_put_be32s (f, &s->ctl);
- qemu_put_be32s (f, &s->status);
- qemu_put_be32s (f, &s->mempage);
- qemu_put_be32s (f, &s->codec);
- qemu_put_be32s (f, &s->sctl);
-}
-
-static int es1370_load (QEMUFile *f, void *opaque, int version_id)
-{
- uint32_t ctl, sctl;
- ES1370State *s = opaque;
- size_t i;
-
- if (version_id != 1)
- return -EINVAL;
-
- for (i = 0; i < NB_CHANNELS; ++i) {
- struct chan *d = &s->chan[i];
- qemu_get_be32s (f, &d->shift);
- qemu_get_be32s (f, &d->leftover);
- qemu_get_be32s (f, &d->scount);
- qemu_get_be32s (f, &d->frame_addr);
- qemu_get_be32s (f, &d->frame_cnt);
- if (i == ADC_CHANNEL) {
- if (s->adc_voice) {
- AUD_close_in (&s->card, s->adc_voice);
- s->adc_voice = NULL;
- }
- }
- else {
- if (s->dac_voice[i]) {
- AUD_close_out (&s->card, s->dac_voice[i]);
- s->dac_voice[i] = NULL;
- }
- }
- }
-
- qemu_get_be32s (f, &ctl);
- qemu_get_be32s (f, &s->status);
- qemu_get_be32s (f, &s->mempage);
- qemu_get_be32s (f, &s->codec);
- qemu_get_be32s (f, &sctl);
-
- s->ctl = 0;
- s->sctl = 0;
- es1370_update_voices (s, ctl, sctl);
- return 0;
-}
-
-static void es1370_on_reset (void *opaque)
-{
- ES1370State *s = opaque;
- es1370_reset (s);
-}
-
-int es1370_init (PCIBus *bus, AudioState *audio)
-{
- PCIES1370State *d;
- ES1370State *s;
- uint8_t *c;
-
- if (!bus) {
- dolog ("No PCI bus\n");
- return -1;
- }
-
- if (!audio) {
- dolog ("No audio state\n");
- return -1;
- }
-
- d = (PCIES1370State *) pci_register_device (bus, "ES1370",
- sizeof (PCIES1370State),
- -1, NULL, NULL);
-
- if (!d) {
- AUD_log (NULL, "Failed to register PCI device for ES1370\n");
- return -1;
- }
-
- c = d->dev.config;
- c[0x00] = 0x74;
- c[0x01] = 0x12;
- c[0x02] = 0x00;
- c[0x03] = 0x50;
- c[0x07] = 2 << 1;
- c[0x0a] = 0x01;
- c[0x0b] = 0x04;
-
-#if 1
- c[0x2c] = 0x42;
- c[0x2d] = 0x49;
- c[0x2e] = 0x4c;
- c[0x2f] = 0x4c;
-#else
- c[0x2c] = 0x74;
- c[0x2d] = 0x12;
- c[0x2e] = 0x71;
- c[0x2f] = 0x13;
- c[0x34] = 0xdc;
- c[0x3c] = 10;
- c[0xdc] = 0x00;
-#endif
-
- c[0x3d] = 1;
- c[0x3e] = 0x0c;
- c[0x3f] = 0x80;
-
- s = &d->es1370;
- s->pci_dev = &d->dev;
-
- pci_register_io_region (&d->dev, 0, 256, PCI_ADDRESS_SPACE_IO, es1370_map);
- register_savevm ("es1370", 0, 1, es1370_save, es1370_load, s);
- qemu_register_reset (es1370_on_reset, s);
-
- AUD_register_card (audio, "es1370", &s->card);
- es1370_reset (s);
- return 0;
-}
diff --git a/hw/esp.c b/hw/esp.c
deleted file mode 100644
index cdd062f..0000000
--- a/hw/esp.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * QEMU ESP emulation
- *
- * Copyright (c) 2005-2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug ESP card */
-//#define DEBUG_ESP
-
-#ifdef DEBUG_ESP
-#define DPRINTF(fmt, args...) \
-do { printf("ESP: " fmt , ##args); } while (0)
-#define pic_set_irq(irq, level) \
-do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
-#else
-#define DPRINTF(fmt, args...)
-#endif
-
-#define ESPDMA_REGS 4
-#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
-#define ESP_MAXREG 0x3f
-#define TI_BUFSZ 32
-#define DMA_VER 0xa0000000
-#define DMA_INTR 1
-#define DMA_INTREN 0x10
-#define DMA_WRITE_MEM 0x100
-#define DMA_LOADED 0x04000000
-typedef struct ESPState ESPState;
-
-struct ESPState {
- BlockDriverState **bd;
- uint8_t rregs[ESP_MAXREG];
- uint8_t wregs[ESP_MAXREG];
- int irq;
- uint32_t espdmaregs[ESPDMA_REGS];
- uint32_t ti_size;
- uint32_t ti_rptr, ti_wptr;
- uint8_t ti_buf[TI_BUFSZ];
- int sense;
- int dma;
- SCSIDevice *scsi_dev[MAX_DISKS];
- SCSIDevice *current_dev;
- uint8_t cmdbuf[TI_BUFSZ];
- int cmdlen;
- int do_cmd;
-};
-
-#define STAT_DO 0x00
-#define STAT_DI 0x01
-#define STAT_CD 0x02
-#define STAT_ST 0x03
-#define STAT_MI 0x06
-#define STAT_MO 0x07
-
-#define STAT_TC 0x10
-#define STAT_IN 0x80
-
-#define INTR_FC 0x08
-#define INTR_BS 0x10
-#define INTR_DC 0x20
-#define INTR_RST 0x80
-
-#define SEQ_0 0x0
-#define SEQ_CD 0x4
-
-static int get_cmd(ESPState *s, uint8_t *buf)
-{
- uint32_t dmaptr, dmalen;
- int target;
-
- dmalen = s->wregs[0] | (s->wregs[1] << 8);
- target = s->wregs[4] & 7;
- DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
- if (s->dma) {
- dmaptr = iommu_translate(s->espdmaregs[1]);
- DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
- s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
- cpu_physical_memory_read(dmaptr, buf, dmalen);
- } else {
- buf[0] = 0;
- memcpy(&buf[1], s->ti_buf, dmalen);
- dmalen++;
- }
-
- s->ti_size = 0;
- s->ti_rptr = 0;
- s->ti_wptr = 0;
-
- if (target >= 4 || !s->scsi_dev[target]) {
- // No such drive
- s->rregs[4] = STAT_IN;
- s->rregs[5] = INTR_DC;
- s->rregs[6] = SEQ_0;
- s->espdmaregs[0] |= DMA_INTR;
- pic_set_irq(s->irq, 1);
- return 0;
- }
- s->current_dev = s->scsi_dev[target];
- return dmalen;
-}
-
-static void do_cmd(ESPState *s, uint8_t *buf)
-{
- int32_t datalen;
- int lun;
-
- DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
- lun = buf[0] & 7;
- datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
- if (datalen == 0) {
- s->ti_size = 0;
- } else {
- s->rregs[4] = STAT_IN | STAT_TC;
- if (datalen > 0) {
- s->rregs[4] |= STAT_DI;
- s->ti_size = datalen;
- } else {
- s->rregs[4] |= STAT_DO;
- s->ti_size = -datalen;
- }
- }
- s->rregs[5] = INTR_BS | INTR_FC;
- s->rregs[6] = SEQ_CD;
- s->espdmaregs[0] |= DMA_INTR;
- pic_set_irq(s->irq, 1);
-}
-
-static void handle_satn(ESPState *s)
-{
- uint8_t buf[32];
- int len;
-
- len = get_cmd(s, buf);
- if (len)
- do_cmd(s, buf);
-}
-
-static void handle_satn_stop(ESPState *s)
-{
- s->cmdlen = get_cmd(s, s->cmdbuf);
- if (s->cmdlen) {
- DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
- s->do_cmd = 1;
- s->espdmaregs[1] += s->cmdlen;
- s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
- s->rregs[5] = INTR_BS | INTR_FC;
- s->rregs[6] = SEQ_CD;
- s->espdmaregs[0] |= DMA_INTR;
- pic_set_irq(s->irq, 1);
- }
-}
-
-static void write_response(ESPState *s)
-{
- uint32_t dmaptr;
-
- DPRINTF("Transfer status (sense=%d)\n", s->sense);
- s->ti_buf[0] = s->sense;
- s->ti_buf[1] = 0;
- if (s->dma) {
- dmaptr = iommu_translate(s->espdmaregs[1]);
- DPRINTF("DMA Direction: %c\n",
- s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
- cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
- s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
- s->rregs[5] = INTR_BS | INTR_FC;
- s->rregs[6] = SEQ_CD;
- } else {
- s->ti_size = 2;
- s->ti_rptr = 0;
- s->ti_wptr = 0;
- s->rregs[7] = 2;
- }
- s->espdmaregs[0] |= DMA_INTR;
- pic_set_irq(s->irq, 1);
-
-}
-
-static void esp_command_complete(void *opaque, uint32_t tag, int sense)
-{
- ESPState *s = (ESPState *)opaque;
-
- DPRINTF("SCSI Command complete\n");
- if (s->ti_size != 0)
- DPRINTF("SCSI command completed unexpectedly\n");
- s->ti_size = 0;
- if (sense)
- DPRINTF("Command failed\n");
- s->sense = sense;
- s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
-}
-
-static void handle_ti(ESPState *s)
-{
- uint32_t dmaptr, dmalen, minlen, len, from, to;
- unsigned int i;
- int to_device;
- uint8_t buf[TARGET_PAGE_SIZE];
-
- dmalen = s->wregs[0] | (s->wregs[1] << 8);
- if (dmalen==0) {
- dmalen=0x10000;
- }
-
- if (s->do_cmd)
- minlen = (dmalen < 32) ? dmalen : 32;
- else
- minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
- DPRINTF("Transfer Information len %d\n", minlen);
- if (s->dma) {
- dmaptr = iommu_translate(s->espdmaregs[1]);
- /* Check if the transfer writes to to reads from the device. */
- to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
- DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
- to_device ? 'r': 'w', dmaptr, s->ti_size);
- from = s->espdmaregs[1];
- to = from + minlen;
- for (i = 0; i < minlen; i += len, from += len) {
- dmaptr = iommu_translate(s->espdmaregs[1] + i);
- if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
- len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
- } else {
- len = to - from;
- }
- DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
- s->ti_size -= len;
- if (s->do_cmd) {
- DPRINTF("command len %d + %d\n", s->cmdlen, len);
- cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
- s->ti_size = 0;
- s->cmdlen = 0;
- s->do_cmd = 0;
- do_cmd(s, s->cmdbuf);
- return;
- } else {
- if (to_device) {
- cpu_physical_memory_read(dmaptr, buf, len);
- scsi_write_data(s->current_dev, buf, len);
- } else {
- scsi_read_data(s->current_dev, buf, len);
- cpu_physical_memory_write(dmaptr, buf, len);
- }
- }
- }
- if (s->ti_size) {
- s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
- }
- s->rregs[5] = INTR_BS;
- s->rregs[6] = 0;
- s->rregs[7] = 0;
- s->espdmaregs[0] |= DMA_INTR;
- } else if (s->do_cmd) {
- DPRINTF("command len %d\n", s->cmdlen);
- s->ti_size = 0;
- s->cmdlen = 0;
- s->do_cmd = 0;
- do_cmd(s, s->cmdbuf);
- return;
- }
- pic_set_irq(s->irq, 1);
-}
-
-static void esp_reset(void *opaque)
-{
- ESPState *s = opaque;
- memset(s->rregs, 0, ESP_MAXREG);
- memset(s->wregs, 0, ESP_MAXREG);
- s->rregs[0x0e] = 0x4; // Indicate fas100a
- memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
- s->ti_size = 0;
- s->ti_rptr = 0;
- s->ti_wptr = 0;
- s->dma = 0;
- s->do_cmd = 0;
-}
-
-static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- ESPState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & ESP_MAXREG) >> 2;
- DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
- switch (saddr) {
- case 2:
- // FIFO
- if (s->ti_size > 0) {
- s->ti_size--;
- if ((s->rregs[4] & 6) == 0) {
- /* Data in/out. */
- scsi_read_data(s->current_dev, &s->rregs[2], 0);
- } else {
- s->rregs[2] = s->ti_buf[s->ti_rptr++];
- }
- pic_set_irq(s->irq, 1);
- }
- if (s->ti_size == 0) {
- s->ti_rptr = 0;
- s->ti_wptr = 0;
- }
- break;
- case 5:
- // interrupt
- // Clear status bits except TC
- s->rregs[4] &= STAT_TC;
- pic_set_irq(s->irq, 0);
- s->espdmaregs[0] &= ~DMA_INTR;
- break;
- default:
- break;
- }
- return s->rregs[saddr];
-}
-
-static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- ESPState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & ESP_MAXREG) >> 2;
- DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
- switch (saddr) {
- case 0:
- case 1:
- s->rregs[saddr] = val;
- break;
- case 2:
- // FIFO
- if (s->do_cmd) {
- s->cmdbuf[s->cmdlen++] = val & 0xff;
- } else if ((s->rregs[4] & 6) == 0) {
- uint8_t buf;
- buf = val & 0xff;
- s->ti_size--;
- scsi_write_data(s->current_dev, &buf, 0);
- } else {
- s->ti_size++;
- s->ti_buf[s->ti_wptr++] = val & 0xff;
- }
- break;
- case 3:
- s->rregs[saddr] = val;
- // Command
- if (val & 0x80) {
- s->dma = 1;
- } else {
- s->dma = 0;
- }
- switch(val & 0x7f) {
- case 0:
- DPRINTF("NOP (%2.2x)\n", val);
- break;
- case 1:
- DPRINTF("Flush FIFO (%2.2x)\n", val);
- //s->ti_size = 0;
- s->rregs[5] = INTR_FC;
- s->rregs[6] = 0;
- break;
- case 2:
- DPRINTF("Chip reset (%2.2x)\n", val);
- esp_reset(s);
- break;
- case 3:
- DPRINTF("Bus reset (%2.2x)\n", val);
- s->rregs[5] = INTR_RST;
- if (!(s->wregs[8] & 0x40)) {
- s->espdmaregs[0] |= DMA_INTR;
- pic_set_irq(s->irq, 1);
- }
- break;
- case 0x10:
- handle_ti(s);
- break;
- case 0x11:
- DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
- write_response(s);
- break;
- case 0x12:
- DPRINTF("Message Accepted (%2.2x)\n", val);
- write_response(s);
- s->rregs[5] = INTR_DC;
- s->rregs[6] = 0;
- break;
- case 0x1a:
- DPRINTF("Set ATN (%2.2x)\n", val);
- break;
- case 0x42:
- DPRINTF("Set ATN (%2.2x)\n", val);
- handle_satn(s);
- break;
- case 0x43:
- DPRINTF("Set ATN & stop (%2.2x)\n", val);
- handle_satn_stop(s);
- break;
- default:
- DPRINTF("Unhandled ESP command (%2.2x)\n", val);
- break;
- }
- break;
- case 4 ... 7:
- break;
- case 8:
- s->rregs[saddr] = val;
- break;
- case 9 ... 10:
- break;
- case 11:
- s->rregs[saddr] = val & 0x15;
- break;
- case 12 ... 15:
- s->rregs[saddr] = val;
- break;
- default:
- break;
- }
- s->wregs[saddr] = val;
-}
-
-static CPUReadMemoryFunc *esp_mem_read[3] = {
- esp_mem_readb,
- esp_mem_readb,
- esp_mem_readb,
-};
-
-static CPUWriteMemoryFunc *esp_mem_write[3] = {
- esp_mem_writeb,
- esp_mem_writeb,
- esp_mem_writeb,
-};
-
-static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- ESPState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & ESPDMA_MAXADDR) >> 2;
- DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
-
- return s->espdmaregs[saddr];
-}
-
-static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- ESPState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & ESPDMA_MAXADDR) >> 2;
- DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
- switch (saddr) {
- case 0:
- if (!(val & DMA_INTREN))
- pic_set_irq(s->irq, 0);
- if (val & 0x80) {
- esp_reset(s);
- } else if (val & 0x40) {
- val &= ~0x40;
- } else if (val == 0)
- val = 0x40;
- val &= 0x0fffffff;
- val |= DMA_VER;
- break;
- case 1:
- s->espdmaregs[0] |= DMA_LOADED;
- break;
- default:
- break;
- }
- s->espdmaregs[saddr] = val;
-}
-
-static CPUReadMemoryFunc *espdma_mem_read[3] = {
- espdma_mem_readl,
- espdma_mem_readl,
- espdma_mem_readl,
-};
-
-static CPUWriteMemoryFunc *espdma_mem_write[3] = {
- espdma_mem_writel,
- espdma_mem_writel,
- espdma_mem_writel,
-};
-
-static void esp_save(QEMUFile *f, void *opaque)
-{
- ESPState *s = opaque;
- unsigned int i;
-
- qemu_put_buffer(f, s->rregs, ESP_MAXREG);
- qemu_put_buffer(f, s->wregs, ESP_MAXREG);
- qemu_put_be32s(f, &s->irq);
- for (i = 0; i < ESPDMA_REGS; i++)
- qemu_put_be32s(f, &s->espdmaregs[i]);
- qemu_put_be32s(f, &s->ti_size);
- qemu_put_be32s(f, &s->ti_rptr);
- qemu_put_be32s(f, &s->ti_wptr);
- qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
- qemu_put_be32s(f, &s->dma);
-}
-
-static int esp_load(QEMUFile *f, void *opaque, int version_id)
-{
- ESPState *s = opaque;
- unsigned int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_buffer(f, s->rregs, ESP_MAXREG);
- qemu_get_buffer(f, s->wregs, ESP_MAXREG);
- qemu_get_be32s(f, &s->irq);
- for (i = 0; i < ESPDMA_REGS; i++)
- qemu_get_be32s(f, &s->espdmaregs[i]);
- qemu_get_be32s(f, &s->ti_size);
- qemu_get_be32s(f, &s->ti_rptr);
- qemu_get_be32s(f, &s->ti_wptr);
- qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
- qemu_get_be32s(f, &s->dma);
-
- return 0;
-}
-
-void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
-{
- ESPState *s;
- int esp_io_memory, espdma_io_memory;
- int i;
-
- s = qemu_mallocz(sizeof(ESPState));
- if (!s)
- return;
-
- s->bd = bd;
- s->irq = irq;
-
- esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
- cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
-
- espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
- cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
-
- esp_reset(s);
-
- register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
- qemu_register_reset(esp_reset, s);
- for (i = 0; i < MAX_DISKS; i++) {
- if (bs_table[i]) {
- s->scsi_dev[i] =
- scsi_disk_init(bs_table[i], esp_command_complete, s);
- }
- }
-}
-
diff --git a/hw/fdc.c b/hw/fdc.c
deleted file mode 100644
index 3890ace..0000000
--- a/hw/fdc.c
+++ /dev/null
@@ -1,1757 +0,0 @@
-/*
- * QEMU Floppy disk emulator (Intel 82078)
- *
- * Copyright (c) 2003 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-/*
- * The controller is used in Sun4m systems in a slightly different
- * way. There are changes in DOR register and DMA is not available.
- */
-#include "vl.h"
-
-/********************************************************/
-/* debug Floppy devices */
-//#define DEBUG_FLOPPY
-
-#ifdef DEBUG_FLOPPY
-#define FLOPPY_DPRINTF(fmt, args...) \
-do { printf("FLOPPY: " fmt , ##args); } while (0)
-#else
-#define FLOPPY_DPRINTF(fmt, args...)
-#endif
-
-#define FLOPPY_ERROR(fmt, args...) \
-do { printf("FLOPPY ERROR: %s: " fmt, __func__ , ##args); } while (0)
-
-/********************************************************/
-/* Floppy drive emulation */
-
-/* Will always be a fixed parameter for us */
-#define FD_SECTOR_LEN 512
-#define FD_SECTOR_SC 2 /* Sector size code */
-
-/* Floppy disk drive emulation */
-typedef enum fdisk_type_t {
- FDRIVE_DISK_288 = 0x01, /* 2.88 MB disk */
- FDRIVE_DISK_144 = 0x02, /* 1.44 MB disk */
- FDRIVE_DISK_720 = 0x03, /* 720 kB disk */
- FDRIVE_DISK_USER = 0x04, /* User defined geometry */
- FDRIVE_DISK_NONE = 0x05, /* No disk */
-} fdisk_type_t;
-
-typedef enum fdrive_type_t {
- FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */
- FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */
- FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */
- FDRIVE_DRV_NONE = 0x03, /* No drive connected */
-} fdrive_type_t;
-
-typedef enum fdrive_flags_t {
- FDRIVE_MOTOR_ON = 0x01, /* motor on/off */
- FDRIVE_REVALIDATE = 0x02, /* Revalidated */
-} fdrive_flags_t;
-
-typedef enum fdisk_flags_t {
- FDISK_DBL_SIDES = 0x01,
-} fdisk_flags_t;
-
-typedef struct fdrive_t {
- BlockDriverState *bs;
- /* Drive status */
- fdrive_type_t drive;
- fdrive_flags_t drflags;
- uint8_t perpendicular; /* 2.88 MB access mode */
- /* Position */
- uint8_t head;
- uint8_t track;
- uint8_t sect;
- /* Last operation status */
- uint8_t dir; /* Direction */
- uint8_t rw; /* Read/write */
- /* Media */
- fdisk_flags_t flags;
- uint8_t last_sect; /* Nb sector per track */
- uint8_t max_track; /* Nb of tracks */
- uint16_t bps; /* Bytes per sector */
- uint8_t ro; /* Is read-only */
-} fdrive_t;
-
-static void fd_init (fdrive_t *drv, BlockDriverState *bs)
-{
- /* Drive */
- drv->bs = bs;
- drv->drive = FDRIVE_DRV_NONE;
- drv->drflags = 0;
- drv->perpendicular = 0;
- /* Disk */
- drv->last_sect = 0;
- drv->max_track = 0;
-}
-
-static int _fd_sector (uint8_t head, uint8_t track,
- uint8_t sect, uint8_t last_sect)
-{
- return (((track * 2) + head) * last_sect) + sect - 1;
-}
-
-/* Returns current position, in sectors, for given drive */
-static int fd_sector (fdrive_t *drv)
-{
- return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect);
-}
-
-static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
- int enable_seek)
-{
- uint32_t sector;
- int ret;
-
- if (track > drv->max_track ||
- (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
- FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
- head, track, sect, 1,
- (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
- drv->max_track, drv->last_sect);
- return 2;
- }
- if (sect > drv->last_sect) {
- FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
- head, track, sect, 1,
- (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
- drv->max_track, drv->last_sect);
- return 3;
- }
- sector = _fd_sector(head, track, sect, drv->last_sect);
- ret = 0;
- if (sector != fd_sector(drv)) {
-#if 0
- if (!enable_seek) {
- FLOPPY_ERROR("no implicit seek %d %02x %02x (max=%d %02x %02x)\n",
- head, track, sect, 1, drv->max_track, drv->last_sect);
- return 4;
- }
-#endif
- drv->head = head;
- if (drv->track != track)
- ret = 1;
- drv->track = track;
- drv->sect = sect;
- }
-
- return ret;
-}
-
-/* Set drive back to track 0 */
-static void fd_recalibrate (fdrive_t *drv)
-{
- FLOPPY_DPRINTF("recalibrate\n");
- drv->head = 0;
- drv->track = 0;
- drv->sect = 1;
- drv->dir = 1;
- drv->rw = 0;
-}
-
-/* Recognize floppy formats */
-typedef struct fd_format_t {
- fdrive_type_t drive;
- fdisk_type_t disk;
- uint8_t last_sect;
- uint8_t max_track;
- uint8_t max_head;
- const unsigned char *str;
-} fd_format_t;
-
-static fd_format_t fd_formats[] = {
- /* First entry is default format */
- /* 1.44 MB 3"1/2 floppy disks */
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1, "1.6 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", },
- /* 2.88 MB 3"1/2 floppy disks */
- { FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", },
- { FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", },
- { FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1, "3.2 MB 3\"1/2", },
- { FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", },
- { FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", },
- /* 720 kB 3"1/2 floppy disks */
- { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 1, "720 kB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1, "800 kB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1, "820 kB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1, "830 kB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", },
- { FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", },
- /* 1.2 MB 5"1/4 floppy disks */
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1, "1.2 kB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1, "1.6 MB 5\"1/4", },
- /* 720 kB 5"1/4 floppy disks */
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 80, 1, "720 kB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1, "880 kB 5\"1/4", },
- /* 360 kB 5"1/4 floppy disks */
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 1, "360 kB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 0, "180 kB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1, "410 kB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1, "420 kB 5\"1/4", },
- /* 320 kB 5"1/4 floppy disks */
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 1, "320 kB 5\"1/4", },
- { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 0, "160 kB 5\"1/4", },
- /* 360 kB must match 5"1/4 better than 3"1/2... */
- { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 0, "360 kB 3\"1/2", },
- /* end */
- { FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, },
-};
-
-/* Revalidate a disk drive after a disk change */
-static void fd_revalidate (fdrive_t *drv)
-{
- fd_format_t *parse;
- int64_t nb_sectors, size;
- int i, first_match, match;
- int nb_heads, max_track, last_sect, ro;
-
- FLOPPY_DPRINTF("revalidate\n");
- drv->drflags &= ~FDRIVE_REVALIDATE;
- if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
- ro = bdrv_is_read_only(drv->bs);
- bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
- if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
- FLOPPY_DPRINTF("User defined disk (%d %d %d)",
- nb_heads - 1, max_track, last_sect);
- } else {
- bdrv_get_geometry(drv->bs, &nb_sectors);
- match = -1;
- first_match = -1;
- for (i = 0;; i++) {
- parse = &fd_formats[i];
- if (parse->drive == FDRIVE_DRV_NONE)
- break;
- if (drv->drive == parse->drive ||
- drv->drive == FDRIVE_DRV_NONE) {
- size = (parse->max_head + 1) * parse->max_track *
- parse->last_sect;
- if (nb_sectors == size) {
- match = i;
- break;
- }
- if (first_match == -1)
- first_match = i;
- }
- }
- if (match == -1) {
- if (first_match == -1)
- match = 1;
- else
- match = first_match;
- parse = &fd_formats[match];
- }
- nb_heads = parse->max_head + 1;
- max_track = parse->max_track;
- last_sect = parse->last_sect;
- drv->drive = parse->drive;
- FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
- nb_heads, max_track, last_sect, ro ? "ro" : "rw");
- }
- if (nb_heads == 1) {
- drv->flags &= ~FDISK_DBL_SIDES;
- } else {
- drv->flags |= FDISK_DBL_SIDES;
- }
- drv->max_track = max_track;
- drv->last_sect = last_sect;
- drv->ro = ro;
- } else {
- FLOPPY_DPRINTF("No disk in drive\n");
- drv->last_sect = 0;
- drv->max_track = 0;
- drv->flags &= ~FDISK_DBL_SIDES;
- }
- drv->drflags |= FDRIVE_REVALIDATE;
-}
-
-/* Motor control */
-static void fd_start (fdrive_t *drv)
-{
- drv->drflags |= FDRIVE_MOTOR_ON;
-}
-
-static void fd_stop (fdrive_t *drv)
-{
- drv->drflags &= ~FDRIVE_MOTOR_ON;
-}
-
-/* Re-initialise a drives (motor off, repositioned) */
-static void fd_reset (fdrive_t *drv)
-{
- fd_stop(drv);
- fd_recalibrate(drv);
-}
-
-/********************************************************/
-/* Intel 82078 floppy disk controller emulation */
-
-static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq);
-static void fdctrl_reset_fifo (fdctrl_t *fdctrl);
-static int fdctrl_transfer_handler (void *opaque, int nchan,
- int dma_pos, int dma_len);
-static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status);
-static void fdctrl_result_timer(void *opaque);
-
-static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl);
-static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl);
-static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value);
-static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl);
-static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value);
-static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl);
-static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value);
-static uint32_t fdctrl_read_data (fdctrl_t *fdctrl);
-static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value);
-static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
-
-enum {
- FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
- FD_CTRL_RESET = 0x02,
- FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */
- FD_CTRL_BUSY = 0x08, /* dma transfer in progress */
- FD_CTRL_INTR = 0x10,
-};
-
-enum {
- FD_DIR_WRITE = 0,
- FD_DIR_READ = 1,
- FD_DIR_SCANE = 2,
- FD_DIR_SCANL = 3,
- FD_DIR_SCANH = 4,
-};
-
-enum {
- FD_STATE_CMD = 0x00,
- FD_STATE_STATUS = 0x01,
- FD_STATE_DATA = 0x02,
- FD_STATE_STATE = 0x03,
- FD_STATE_MULTI = 0x10,
- FD_STATE_SEEK = 0x20,
- FD_STATE_FORMAT = 0x40,
-};
-
-#define FD_STATE(state) ((state) & FD_STATE_STATE)
-#define FD_SET_STATE(state, new_state) \
-do { (state) = ((state) & ~FD_STATE_STATE) | (new_state); } while (0)
-#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
-#define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
-#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
-
-struct fdctrl_t {
- fdctrl_t *fdctrl;
- /* Controller's identification */
- uint8_t version;
- /* HW */
- int irq_lvl;
- int dma_chann;
- uint32_t io_base;
- /* Controller state */
- QEMUTimer *result_timer;
- uint8_t state;
- uint8_t dma_en;
- uint8_t cur_drv;
- uint8_t bootsel;
- /* Command FIFO */
- uint8_t fifo[FD_SECTOR_LEN];
- uint32_t data_pos;
- uint32_t data_len;
- uint8_t data_state;
- uint8_t data_dir;
- uint8_t int_status;
- uint8_t eot; /* last wanted sector */
- /* States kept only to be returned back */
- /* Timers state */
- uint8_t timer0;
- uint8_t timer1;
- /* precompensation */
- uint8_t precomp_trk;
- uint8_t config;
- uint8_t lock;
- /* Power down config (also with status regB access mode */
- uint8_t pwrd;
- /* Floppy drives */
- fdrive_t drives[2];
-};
-
-static uint32_t fdctrl_read (void *opaque, uint32_t reg)
-{
- fdctrl_t *fdctrl = opaque;
- uint32_t retval;
-
- switch (reg & 0x07) {
-#ifdef TARGET_SPARC
- case 0x00:
- // Identify to Linux as S82078B
- retval = fdctrl_read_statusB(fdctrl);
- break;
-#endif
- case 0x01:
- retval = fdctrl_read_statusB(fdctrl);
- break;
- case 0x02:
- retval = fdctrl_read_dor(fdctrl);
- break;
- case 0x03:
- retval = fdctrl_read_tape(fdctrl);
- break;
- case 0x04:
- retval = fdctrl_read_main_status(fdctrl);
- break;
- case 0x05:
- retval = fdctrl_read_data(fdctrl);
- break;
- case 0x07:
- retval = fdctrl_read_dir(fdctrl);
- break;
- default:
- retval = (uint32_t)(-1);
- break;
- }
- FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
-
- return retval;
-}
-
-static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
-{
- fdctrl_t *fdctrl = opaque;
-
- FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
-
- switch (reg & 0x07) {
- case 0x02:
- fdctrl_write_dor(fdctrl, value);
- break;
- case 0x03:
- fdctrl_write_tape(fdctrl, value);
- break;
- case 0x04:
- fdctrl_write_rate(fdctrl, value);
- break;
- case 0x05:
- fdctrl_write_data(fdctrl, value);
- break;
- default:
- break;
- }
-}
-
-static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg)
-{
- return fdctrl_read(opaque, reg);
-}
-
-static void fdctrl_write_mem (void *opaque,
- target_phys_addr_t reg, uint32_t value)
-{
- fdctrl_write(opaque, reg, value);
-}
-
-static CPUReadMemoryFunc *fdctrl_mem_read[3] = {
- fdctrl_read_mem,
- fdctrl_read_mem,
- fdctrl_read_mem,
-};
-
-static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
- fdctrl_write_mem,
- fdctrl_write_mem,
- fdctrl_write_mem,
-};
-
-static void fd_change_cb (void *opaque)
-{
- fdrive_t *drv = opaque;
-
- FLOPPY_DPRINTF("disk change\n");
- fd_revalidate(drv);
-#if 0
- fd_recalibrate(drv);
- fdctrl_reset_fifo(drv->fdctrl);
- fdctrl_raise_irq(drv->fdctrl, 0x20);
-#endif
-}
-
-fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
- uint32_t io_base,
- BlockDriverState **fds)
-{
- fdctrl_t *fdctrl;
- int io_mem;
- int i;
-
- FLOPPY_DPRINTF("init controller\n");
- fdctrl = qemu_mallocz(sizeof(fdctrl_t));
- if (!fdctrl)
- return NULL;
- fdctrl->result_timer = qemu_new_timer(vm_clock,
- fdctrl_result_timer, fdctrl);
-
- fdctrl->version = 0x90; /* Intel 82078 controller */
- fdctrl->irq_lvl = irq_lvl;
- fdctrl->dma_chann = dma_chann;
- fdctrl->io_base = io_base;
- fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
- if (fdctrl->dma_chann != -1) {
- fdctrl->dma_en = 1;
- DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
- } else {
- fdctrl->dma_en = 0;
- }
- for (i = 0; i < 2; i++) {
- fd_init(&fdctrl->drives[i], fds[i]);
- if (fds[i]) {
- bdrv_set_change_cb(fds[i],
- &fd_change_cb, &fdctrl->drives[i]);
- }
- }
- fdctrl_reset(fdctrl, 0);
- fdctrl->state = FD_CTRL_ACTIVE;
- if (mem_mapped) {
- io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl);
- cpu_register_physical_memory(io_base, 0x08, io_mem);
- } else {
- register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);
- register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);
- register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);
- register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);
- }
- for (i = 0; i < 2; i++) {
- fd_revalidate(&fdctrl->drives[i]);
- }
-
- return fdctrl;
-}
-
-/* XXX: may change if moved to bdrv */
-int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
-{
- return fdctrl->drives[drive_num].drive;
-}
-
-/* Change IRQ state */
-static void fdctrl_reset_irq (fdctrl_t *fdctrl)
-{
- FLOPPY_DPRINTF("Reset interrupt\n");
- pic_set_irq(fdctrl->irq_lvl, 0);
- fdctrl->state &= ~FD_CTRL_INTR;
-}
-
-static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
-{
-#ifdef TARGET_SPARC
- // Sparc mutation
- if (!fdctrl->dma_en) {
- fdctrl->state &= ~FD_CTRL_BUSY;
- fdctrl->int_status = status;
- return;
- }
-#endif
- if (~(fdctrl->state & FD_CTRL_INTR)) {
- pic_set_irq(fdctrl->irq_lvl, 1);
- fdctrl->state |= FD_CTRL_INTR;
- }
- FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);
- fdctrl->int_status = status;
-}
-
-/* Reset controller */
-static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
-{
- int i;
-
- FLOPPY_DPRINTF("reset controller\n");
- fdctrl_reset_irq(fdctrl);
- /* Initialise controller */
- fdctrl->cur_drv = 0;
- /* FIFO state */
- fdctrl->data_pos = 0;
- fdctrl->data_len = 0;
- fdctrl->data_state = FD_STATE_CMD;
- fdctrl->data_dir = FD_DIR_WRITE;
- for (i = 0; i < MAX_FD; i++)
- fd_reset(&fdctrl->drives[i]);
- fdctrl_reset_fifo(fdctrl);
- if (do_irq)
- fdctrl_raise_irq(fdctrl, 0xc0);
-}
-
-static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
-{
- return &fdctrl->drives[fdctrl->bootsel];
-}
-
-static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
-{
- return &fdctrl->drives[1 - fdctrl->bootsel];
-}
-
-static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
-{
- return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);
-}
-
-/* Status B register : 0x01 (read-only) */
-static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
-{
- FLOPPY_DPRINTF("status register: 0x00\n");
- return 0;
-}
-
-/* Digital output register : 0x02 */
-static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
-{
- uint32_t retval = 0;
-
- /* Drive motors state indicators */
- if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
- retval |= 1 << 5;
- if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
- retval |= 1 << 4;
- /* DMA enable */
- retval |= fdctrl->dma_en << 3;
- /* Reset indicator */
- retval |= (fdctrl->state & FD_CTRL_RESET) == 0 ? 0x04 : 0;
- /* Selected drive */
- retval |= fdctrl->cur_drv;
- FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
-
- return retval;
-}
-
-static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
-{
- /* Reset mode */
- if (fdctrl->state & FD_CTRL_RESET) {
- if (!(value & 0x04)) {
- FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
- return;
- }
- }
- FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
- /* Drive motors state indicators */
- if (value & 0x20)
- fd_start(drv1(fdctrl));
- else
- fd_stop(drv1(fdctrl));
- if (value & 0x10)
- fd_start(drv0(fdctrl));
- else
- fd_stop(drv0(fdctrl));
- /* DMA enable */
-#if 0
- if (fdctrl->dma_chann != -1)
- fdctrl->dma_en = 1 - ((value >> 3) & 1);
-#endif
- /* Reset */
- if (!(value & 0x04)) {
- if (!(fdctrl->state & FD_CTRL_RESET)) {
- FLOPPY_DPRINTF("controller enter RESET state\n");
- fdctrl->state |= FD_CTRL_RESET;
- }
- } else {
- if (fdctrl->state & FD_CTRL_RESET) {
- FLOPPY_DPRINTF("controller out of RESET state\n");
- fdctrl_reset(fdctrl, 1);
- fdctrl->state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP);
- }
- }
- /* Selected drive */
- fdctrl->cur_drv = value & 1;
-}
-
-/* Tape drive register : 0x03 */
-static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
-{
- uint32_t retval = 0;
-
- /* Disk boot selection indicator */
- retval |= fdctrl->bootsel << 2;
- /* Tape indicators: never allowed */
- FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);
-
- return retval;
-}
-
-static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
-{
- /* Reset mode */
- if (fdctrl->state & FD_CTRL_RESET) {
- FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
- return;
- }
- FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
- /* Disk boot selection indicator */
- fdctrl->bootsel = (value >> 2) & 1;
- /* Tape indicators: never allow */
-}
-
-/* Main status register : 0x04 (read) */
-static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
-{
- uint32_t retval = 0;
-
- fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET);
- if (!(fdctrl->state & FD_CTRL_BUSY)) {
- /* Data transfer allowed */
- retval |= 0x80;
- /* Data transfer direction indicator */
- if (fdctrl->data_dir == FD_DIR_READ)
- retval |= 0x40;
- }
- /* Should handle 0x20 for SPECIFY command */
- /* Command busy indicator */
- if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA ||
- FD_STATE(fdctrl->data_state) == FD_STATE_STATUS)
- retval |= 0x10;
- FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
-
- return retval;
-}
-
-/* Data select rate register : 0x04 (write) */
-static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
-{
- /* Reset mode */
- if (fdctrl->state & FD_CTRL_RESET) {
- FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
- return;
- }
- FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
- /* Reset: autoclear */
- if (value & 0x80) {
- fdctrl->state |= FD_CTRL_RESET;
- fdctrl_reset(fdctrl, 1);
- fdctrl->state &= ~FD_CTRL_RESET;
- }
- if (value & 0x40) {
- fdctrl->state |= FD_CTRL_SLEEP;
- fdctrl_reset(fdctrl, 1);
- }
-// fdctrl.precomp = (value >> 2) & 0x07;
-}
-
-/* Digital input register : 0x07 (read-only) */
-static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
-{
- uint32_t retval = 0;
-
- if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE ||
- drv1(fdctrl)->drflags & FDRIVE_REVALIDATE)
- retval |= 0x80;
- if (retval != 0)
- FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
- drv0(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
- drv1(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
-
- return retval;
-}
-
-/* FIFO state control */
-static void fdctrl_reset_fifo (fdctrl_t *fdctrl)
-{
- fdctrl->data_dir = FD_DIR_WRITE;
- fdctrl->data_pos = 0;
- FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD);
-}
-
-/* Set FIFO status for the host to read */
-static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq)
-{
- fdctrl->data_dir = FD_DIR_READ;
- fdctrl->data_len = fifo_len;
- fdctrl->data_pos = 0;
- FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS);
- if (do_irq)
- fdctrl_raise_irq(fdctrl, 0x00);
-}
-
-/* Set an error: unimplemented/unknown command */
-static void fdctrl_unimplemented (fdctrl_t *fdctrl)
-{
-#if 0
- fdrive_t *cur_drv;
-
- cur_drv = get_cur_drv(fdctrl);
- fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv;
- fdctrl->fifo[1] = 0x00;
- fdctrl->fifo[2] = 0x00;
- fdctrl_set_fifo(fdctrl, 3, 1);
-#else
- // fdctrl_reset_fifo(fdctrl);
- fdctrl->fifo[0] = 0x80;
- fdctrl_set_fifo(fdctrl, 1, 0);
-#endif
-}
-
-/* Callback for transfer end (stop or abort) */
-static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
- uint8_t status1, uint8_t status2)
-{
- fdrive_t *cur_drv;
-
- cur_drv = get_cur_drv(fdctrl);
- FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
- status0, status1, status2,
- status0 | (cur_drv->head << 2) | fdctrl->cur_drv);
- fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv;
- fdctrl->fifo[1] = status1;
- fdctrl->fifo[2] = status2;
- fdctrl->fifo[3] = cur_drv->track;
- fdctrl->fifo[4] = cur_drv->head;
- fdctrl->fifo[5] = cur_drv->sect;
- fdctrl->fifo[6] = FD_SECTOR_SC;
- fdctrl->data_dir = FD_DIR_READ;
- if (fdctrl->state & FD_CTRL_BUSY) {
- DMA_release_DREQ(fdctrl->dma_chann);
- fdctrl->state &= ~FD_CTRL_BUSY;
- }
- fdctrl_set_fifo(fdctrl, 7, 1);
-}
-
-/* Prepare a data transfer (either DMA or FIFO) */
-static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
-{
- fdrive_t *cur_drv;
- uint8_t kh, kt, ks;
- int did_seek;
-
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- kt = fdctrl->fifo[2];
- kh = fdctrl->fifo[3];
- ks = fdctrl->fifo[4];
- FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
- fdctrl->cur_drv, kh, kt, ks,
- _fd_sector(kh, kt, ks, cur_drv->last_sect));
- did_seek = 0;
- switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
- case 2:
- /* sect too big */
- fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
- fdctrl->fifo[3] = kt;
- fdctrl->fifo[4] = kh;
- fdctrl->fifo[5] = ks;
- return;
- case 3:
- /* track too big */
- fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
- fdctrl->fifo[3] = kt;
- fdctrl->fifo[4] = kh;
- fdctrl->fifo[5] = ks;
- return;
- case 4:
- /* No seek enabled */
- fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
- fdctrl->fifo[3] = kt;
- fdctrl->fifo[4] = kh;
- fdctrl->fifo[5] = ks;
- return;
- case 1:
- did_seek = 1;
- break;
- default:
- break;
- }
- /* Set the FIFO state */
- fdctrl->data_dir = direction;
- fdctrl->data_pos = 0;
- FD_SET_STATE(fdctrl->data_state, FD_STATE_DATA); /* FIFO ready for data */
- if (fdctrl->fifo[0] & 0x80)
- fdctrl->data_state |= FD_STATE_MULTI;
- else
- fdctrl->data_state &= ~FD_STATE_MULTI;
- if (did_seek)
- fdctrl->data_state |= FD_STATE_SEEK;
- else
- fdctrl->data_state &= ~FD_STATE_SEEK;
- if (fdctrl->fifo[5] == 00) {
- fdctrl->data_len = fdctrl->fifo[8];
- } else {
- int tmp;
- fdctrl->data_len = 128 << fdctrl->fifo[5];
- tmp = (cur_drv->last_sect - ks + 1);
- if (fdctrl->fifo[0] & 0x80)
- tmp += cur_drv->last_sect;
- fdctrl->data_len *= tmp;
- }
- fdctrl->eot = fdctrl->fifo[6];
- if (fdctrl->dma_en) {
- int dma_mode;
- /* DMA transfer are enabled. Check if DMA channel is well programmed */
- dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
- dma_mode = (dma_mode >> 2) & 3;
- FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
- dma_mode, direction,
- (128 << fdctrl->fifo[5]) *
- (cur_drv->last_sect - ks + 1), fdctrl->data_len);
- if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
- direction == FD_DIR_SCANH) && dma_mode == 0) ||
- (direction == FD_DIR_WRITE && dma_mode == 2) ||
- (direction == FD_DIR_READ && dma_mode == 1)) {
- /* No access is allowed until DMA transfer has completed */
- fdctrl->state |= FD_CTRL_BUSY;
- /* Now, we just have to wait for the DMA controller to
- * recall us...
- */
- DMA_hold_DREQ(fdctrl->dma_chann);
- DMA_schedule(fdctrl->dma_chann);
- return;
- } else {
- FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
- }
- }
- FLOPPY_DPRINTF("start non-DMA transfer\n");
- /* IO based transfer: calculate len */
- fdctrl_raise_irq(fdctrl, 0x00);
-
- return;
-}
-
-/* Prepare a transfer of deleted data */
-static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction)
-{
- /* We don't handle deleted data,
- * so we don't return *ANYTHING*
- */
- fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
-}
-
-/* handlers for DMA transfers */
-static int fdctrl_transfer_handler (void *opaque, int nchan,
- int dma_pos, int dma_len)
-{
- fdctrl_t *fdctrl;
- fdrive_t *cur_drv;
- int len, start_pos, rel_pos;
- uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
-
- fdctrl = opaque;
- if (!(fdctrl->state & FD_CTRL_BUSY)) {
- FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
- return 0;
- }
- cur_drv = get_cur_drv(fdctrl);
- if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
- fdctrl->data_dir == FD_DIR_SCANH)
- status2 = 0x04;
- if (dma_len > fdctrl->data_len)
- dma_len = fdctrl->data_len;
- if (cur_drv->bs == NULL) {
- if (fdctrl->data_dir == FD_DIR_WRITE)
- fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
- else
- fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
- len = 0;
- goto transfer_error;
- }
- rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
- for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
- len = dma_len - fdctrl->data_pos;
- if (len + rel_pos > FD_SECTOR_LEN)
- len = FD_SECTOR_LEN - rel_pos;
- FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x "
- "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
- fdctrl->data_len, fdctrl->cur_drv, cur_drv->head,
- cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
- fd_sector(cur_drv) * 512);
- if (fdctrl->data_dir != FD_DIR_WRITE ||
- len < FD_SECTOR_LEN || rel_pos != 0) {
- /* READ & SCAN commands and realign to a sector for WRITE */
- if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, 1) < 0) {
- FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
- fd_sector(cur_drv));
- /* Sure, image size is too small... */
- memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
- }
- }
- switch (fdctrl->data_dir) {
- case FD_DIR_READ:
- /* READ commands */
- DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
- fdctrl->data_pos, len);
-/* cpu_physical_memory_write(addr + fdctrl->data_pos, */
-/* fdctrl->fifo + rel_pos, len); */
- break;
- case FD_DIR_WRITE:
- /* WRITE commands */
- DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
- fdctrl->data_pos, len);
-/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
-/* fdctrl->fifo + rel_pos, len); */
- if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, 1) < 0) {
- FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
- fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
- goto transfer_error;
- }
- break;
- default:
- /* SCAN commands */
- {
- uint8_t tmpbuf[FD_SECTOR_LEN];
- int ret;
- DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
-/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
-/* tmpbuf, len); */
- ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
- if (ret == 0) {
- status2 = 0x08;
- goto end_transfer;
- }
- if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
- (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
- status2 = 0x00;
- goto end_transfer;
- }
- }
- break;
- }
- fdctrl->data_pos += len;
- rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
- if (rel_pos == 0) {
- /* Seek to next sector */
- FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
- cur_drv->head, cur_drv->track, cur_drv->sect,
- fd_sector(cur_drv),
- fdctrl->data_pos - len);
- /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
- error in fact */
- if (cur_drv->sect >= cur_drv->last_sect ||
- cur_drv->sect == fdctrl->eot) {
- cur_drv->sect = 1;
- if (FD_MULTI_TRACK(fdctrl->data_state)) {
- if (cur_drv->head == 0 &&
- (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
- cur_drv->head = 1;
- } else {
- cur_drv->head = 0;
- cur_drv->track++;
- if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
- break;
- }
- } else {
- cur_drv->track++;
- break;
- }
- FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
- cur_drv->head, cur_drv->track,
- cur_drv->sect, fd_sector(cur_drv));
- } else {
- cur_drv->sect++;
- }
- }
- }
-end_transfer:
- len = fdctrl->data_pos - start_pos;
- FLOPPY_DPRINTF("end transfer %d %d %d\n",
- fdctrl->data_pos, len, fdctrl->data_len);
- if (fdctrl->data_dir == FD_DIR_SCANE ||
- fdctrl->data_dir == FD_DIR_SCANL ||
- fdctrl->data_dir == FD_DIR_SCANH)
- status2 = 0x08;
- if (FD_DID_SEEK(fdctrl->data_state))
- status0 |= 0x20;
- fdctrl->data_len -= len;
- // if (fdctrl->data_len == 0)
- fdctrl_stop_transfer(fdctrl, status0, status1, status2);
-transfer_error:
-
- return len;
-}
-
-/* Data register : 0x05 */
-static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
-{
- fdrive_t *cur_drv;
- uint32_t retval = 0;
- int pos, len;
-
- cur_drv = get_cur_drv(fdctrl);
- fdctrl->state &= ~FD_CTRL_SLEEP;
- if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) {
- FLOPPY_ERROR("can't read data in CMD state\n");
- return 0;
- }
- pos = fdctrl->data_pos;
- if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
- pos %= FD_SECTOR_LEN;
- if (pos == 0) {
- len = fdctrl->data_len - fdctrl->data_pos;
- if (len > FD_SECTOR_LEN)
- len = FD_SECTOR_LEN;
- bdrv_read(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, len);
- }
- }
- retval = fdctrl->fifo[pos];
- if (++fdctrl->data_pos == fdctrl->data_len) {
- fdctrl->data_pos = 0;
- /* Switch from transfer mode to status mode
- * then from status mode to command mode
- */
- if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
- fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
- } else {
- fdctrl_reset_fifo(fdctrl);
- fdctrl_reset_irq(fdctrl);
- }
- }
- FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
-
- return retval;
-}
-
-static void fdctrl_format_sector (fdctrl_t *fdctrl)
-{
- fdrive_t *cur_drv;
- uint8_t kh, kt, ks;
- int did_seek;
-
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- kt = fdctrl->fifo[6];
- kh = fdctrl->fifo[7];
- ks = fdctrl->fifo[8];
- FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
- fdctrl->cur_drv, kh, kt, ks,
- _fd_sector(kh, kt, ks, cur_drv->last_sect));
- did_seek = 0;
- switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
- case 2:
- /* sect too big */
- fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
- fdctrl->fifo[3] = kt;
- fdctrl->fifo[4] = kh;
- fdctrl->fifo[5] = ks;
- return;
- case 3:
- /* track too big */
- fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
- fdctrl->fifo[3] = kt;
- fdctrl->fifo[4] = kh;
- fdctrl->fifo[5] = ks;
- return;
- case 4:
- /* No seek enabled */
- fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
- fdctrl->fifo[3] = kt;
- fdctrl->fifo[4] = kh;
- fdctrl->fifo[5] = ks;
- return;
- case 1:
- did_seek = 1;
- fdctrl->data_state |= FD_STATE_SEEK;
- break;
- default:
- break;
- }
- memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
- if (cur_drv->bs == NULL ||
- bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
- FLOPPY_ERROR("formating sector %d\n", fd_sector(cur_drv));
- fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
- } else {
- if (cur_drv->sect == cur_drv->last_sect) {
- fdctrl->data_state &= ~FD_STATE_FORMAT;
- /* Last sector done */
- if (FD_DID_SEEK(fdctrl->data_state))
- fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
- else
- fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
- } else {
- /* More to do */
- fdctrl->data_pos = 0;
- fdctrl->data_len = 4;
- }
- }
-}
-
-static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
-{
- fdrive_t *cur_drv;
-
- cur_drv = get_cur_drv(fdctrl);
- /* Reset mode */
- if (fdctrl->state & FD_CTRL_RESET) {
- FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
- return;
- }
- fdctrl->state &= ~FD_CTRL_SLEEP;
- if (FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) {
- FLOPPY_ERROR("can't write data in status mode\n");
- return;
- }
- /* Is it write command time ? */
- if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
- /* FIFO data write */
- fdctrl->fifo[fdctrl->data_pos++] = value;
- if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) ||
- fdctrl->data_pos == fdctrl->data_len) {
- bdrv_write(cur_drv->bs, fd_sector(cur_drv),
- fdctrl->fifo, FD_SECTOR_LEN);
- }
- /* Switch from transfer mode to status mode
- * then from status mode to command mode
- */
- if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA)
- fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
- return;
- }
- if (fdctrl->data_pos == 0) {
- /* Command */
- switch (value & 0x5F) {
- case 0x46:
- /* READ variants */
- FLOPPY_DPRINTF("READ command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- case 0x4C:
- /* READ_DELETED variants */
- FLOPPY_DPRINTF("READ_DELETED command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- case 0x50:
- /* SCAN_EQUAL variants */
- FLOPPY_DPRINTF("SCAN_EQUAL command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- case 0x56:
- /* VERIFY variants */
- FLOPPY_DPRINTF("VERIFY command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- case 0x59:
- /* SCAN_LOW_OR_EQUAL variants */
- FLOPPY_DPRINTF("SCAN_LOW_OR_EQUAL command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- case 0x5D:
- /* SCAN_HIGH_OR_EQUAL variants */
- FLOPPY_DPRINTF("SCAN_HIGH_OR_EQUAL command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- default:
- break;
- }
- switch (value & 0x7F) {
- case 0x45:
- /* WRITE variants */
- FLOPPY_DPRINTF("WRITE command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- case 0x49:
- /* WRITE_DELETED variants */
- FLOPPY_DPRINTF("WRITE_DELETED command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- default:
- break;
- }
- switch (value) {
- case 0x03:
- /* SPECIFY */
- FLOPPY_DPRINTF("SPECIFY command\n");
- /* 1 parameter cmd */
- fdctrl->data_len = 3;
- goto enqueue;
- case 0x04:
- /* SENSE_DRIVE_STATUS */
- FLOPPY_DPRINTF("SENSE_DRIVE_STATUS command\n");
- /* 1 parameter cmd */
- fdctrl->data_len = 2;
- goto enqueue;
- case 0x07:
- /* RECALIBRATE */
- FLOPPY_DPRINTF("RECALIBRATE command\n");
- /* 1 parameter cmd */
- fdctrl->data_len = 2;
- goto enqueue;
- case 0x08:
- /* SENSE_INTERRUPT_STATUS */
- FLOPPY_DPRINTF("SENSE_INTERRUPT_STATUS command (%02x)\n",
- fdctrl->int_status);
- /* No parameters cmd: returns status if no interrupt */
-#if 0
- fdctrl->fifo[0] =
- fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv;
-#else
- /* XXX: int_status handling is broken for read/write
- commands, so we do this hack. It should be suppressed
- ASAP */
- fdctrl->fifo[0] =
- 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv;
-#endif
- fdctrl->fifo[1] = cur_drv->track;
- fdctrl_set_fifo(fdctrl, 2, 0);
- fdctrl_reset_irq(fdctrl);
- fdctrl->int_status = 0xC0;
- return;
- case 0x0E:
- /* DUMPREG */
- FLOPPY_DPRINTF("DUMPREG command\n");
- /* Drives position */
- fdctrl->fifo[0] = drv0(fdctrl)->track;
- fdctrl->fifo[1] = drv1(fdctrl)->track;
- fdctrl->fifo[2] = 0;
- fdctrl->fifo[3] = 0;
- /* timers */
- fdctrl->fifo[4] = fdctrl->timer0;
- fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en;
- fdctrl->fifo[6] = cur_drv->last_sect;
- fdctrl->fifo[7] = (fdctrl->lock << 7) |
- (cur_drv->perpendicular << 2);
- fdctrl->fifo[8] = fdctrl->config;
- fdctrl->fifo[9] = fdctrl->precomp_trk;
- fdctrl_set_fifo(fdctrl, 10, 0);
- return;
- case 0x0F:
- /* SEEK */
- FLOPPY_DPRINTF("SEEK command\n");
- /* 2 parameters cmd */
- fdctrl->data_len = 3;
- goto enqueue;
- case 0x10:
- /* VERSION */
- FLOPPY_DPRINTF("VERSION command\n");
- /* No parameters cmd */
- /* Controller's version */
- fdctrl->fifo[0] = fdctrl->version;
- fdctrl_set_fifo(fdctrl, 1, 1);
- return;
- case 0x12:
- /* PERPENDICULAR_MODE */
- FLOPPY_DPRINTF("PERPENDICULAR_MODE command\n");
- /* 1 parameter cmd */
- fdctrl->data_len = 2;
- goto enqueue;
- case 0x13:
- /* CONFIGURE */
- FLOPPY_DPRINTF("CONFIGURE command\n");
- /* 3 parameters cmd */
- fdctrl->data_len = 4;
- goto enqueue;
- case 0x14:
- /* UNLOCK */
- FLOPPY_DPRINTF("UNLOCK command\n");
- /* No parameters cmd */
- fdctrl->lock = 0;
- fdctrl->fifo[0] = 0;
- fdctrl_set_fifo(fdctrl, 1, 0);
- return;
- case 0x17:
- /* POWERDOWN_MODE */
- FLOPPY_DPRINTF("POWERDOWN_MODE command\n");
- /* 2 parameters cmd */
- fdctrl->data_len = 3;
- goto enqueue;
- case 0x18:
- /* PART_ID */
- FLOPPY_DPRINTF("PART_ID command\n");
- /* No parameters cmd */
- fdctrl->fifo[0] = 0x41; /* Stepping 1 */
- fdctrl_set_fifo(fdctrl, 1, 0);
- return;
- case 0x2C:
- /* SAVE */
- FLOPPY_DPRINTF("SAVE command\n");
- /* No parameters cmd */
- fdctrl->fifo[0] = 0;
- fdctrl->fifo[1] = 0;
- /* Drives position */
- fdctrl->fifo[2] = drv0(fdctrl)->track;
- fdctrl->fifo[3] = drv1(fdctrl)->track;
- fdctrl->fifo[4] = 0;
- fdctrl->fifo[5] = 0;
- /* timers */
- fdctrl->fifo[6] = fdctrl->timer0;
- fdctrl->fifo[7] = fdctrl->timer1;
- fdctrl->fifo[8] = cur_drv->last_sect;
- fdctrl->fifo[9] = (fdctrl->lock << 7) |
- (cur_drv->perpendicular << 2);
- fdctrl->fifo[10] = fdctrl->config;
- fdctrl->fifo[11] = fdctrl->precomp_trk;
- fdctrl->fifo[12] = fdctrl->pwrd;
- fdctrl->fifo[13] = 0;
- fdctrl->fifo[14] = 0;
- fdctrl_set_fifo(fdctrl, 15, 1);
- return;
- case 0x33:
- /* OPTION */
- FLOPPY_DPRINTF("OPTION command\n");
- /* 1 parameter cmd */
- fdctrl->data_len = 2;
- goto enqueue;
- case 0x42:
- /* READ_TRACK */
- FLOPPY_DPRINTF("READ_TRACK command\n");
- /* 8 parameters cmd */
- fdctrl->data_len = 9;
- goto enqueue;
- case 0x4A:
- /* READ_ID */
- FLOPPY_DPRINTF("READ_ID command\n");
- /* 1 parameter cmd */
- fdctrl->data_len = 2;
- goto enqueue;
- case 0x4C:
- /* RESTORE */
- FLOPPY_DPRINTF("RESTORE command\n");
- /* 17 parameters cmd */
- fdctrl->data_len = 18;
- goto enqueue;
- case 0x4D:
- /* FORMAT_TRACK */
- FLOPPY_DPRINTF("FORMAT_TRACK command\n");
- /* 5 parameters cmd */
- fdctrl->data_len = 6;
- goto enqueue;
- case 0x8E:
- /* DRIVE_SPECIFICATION_COMMAND */
- FLOPPY_DPRINTF("DRIVE_SPECIFICATION_COMMAND command\n");
- /* 5 parameters cmd */
- fdctrl->data_len = 6;
- goto enqueue;
- case 0x8F:
- /* RELATIVE_SEEK_OUT */
- FLOPPY_DPRINTF("RELATIVE_SEEK_OUT command\n");
- /* 2 parameters cmd */
- fdctrl->data_len = 3;
- goto enqueue;
- case 0x94:
- /* LOCK */
- FLOPPY_DPRINTF("LOCK command\n");
- /* No parameters cmd */
- fdctrl->lock = 1;
- fdctrl->fifo[0] = 0x10;
- fdctrl_set_fifo(fdctrl, 1, 1);
- return;
- case 0xCD:
- /* FORMAT_AND_WRITE */
- FLOPPY_DPRINTF("FORMAT_AND_WRITE command\n");
- /* 10 parameters cmd */
- fdctrl->data_len = 11;
- goto enqueue;
- case 0xCF:
- /* RELATIVE_SEEK_IN */
- FLOPPY_DPRINTF("RELATIVE_SEEK_IN command\n");
- /* 2 parameters cmd */
- fdctrl->data_len = 3;
- goto enqueue;
- default:
- /* Unknown command */
- FLOPPY_ERROR("unknown command: 0x%02x\n", value);
- fdctrl_unimplemented(fdctrl);
- return;
- }
- }
-enqueue:
- FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
- fdctrl->fifo[fdctrl->data_pos] = value;
- if (++fdctrl->data_pos == fdctrl->data_len) {
- /* We now have all parameters
- * and will be able to treat the command
- */
- if (fdctrl->data_state & FD_STATE_FORMAT) {
- fdctrl_format_sector(fdctrl);
- return;
- }
- switch (fdctrl->fifo[0] & 0x1F) {
- case 0x06:
- {
- /* READ variants */
- FLOPPY_DPRINTF("treat READ command\n");
- fdctrl_start_transfer(fdctrl, FD_DIR_READ);
- return;
- }
- case 0x0C:
- /* READ_DELETED variants */
-// FLOPPY_DPRINTF("treat READ_DELETED command\n");
- FLOPPY_ERROR("treat READ_DELETED command\n");
- fdctrl_start_transfer_del(fdctrl, FD_DIR_READ);
- return;
- case 0x16:
- /* VERIFY variants */
-// FLOPPY_DPRINTF("treat VERIFY command\n");
- FLOPPY_ERROR("treat VERIFY command\n");
- fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
- return;
- case 0x10:
- /* SCAN_EQUAL variants */
-// FLOPPY_DPRINTF("treat SCAN_EQUAL command\n");
- FLOPPY_ERROR("treat SCAN_EQUAL command\n");
- fdctrl_start_transfer(fdctrl, FD_DIR_SCANE);
- return;
- case 0x19:
- /* SCAN_LOW_OR_EQUAL variants */
-// FLOPPY_DPRINTF("treat SCAN_LOW_OR_EQUAL command\n");
- FLOPPY_ERROR("treat SCAN_LOW_OR_EQUAL command\n");
- fdctrl_start_transfer(fdctrl, FD_DIR_SCANL);
- return;
- case 0x1D:
- /* SCAN_HIGH_OR_EQUAL variants */
-// FLOPPY_DPRINTF("treat SCAN_HIGH_OR_EQUAL command\n");
- FLOPPY_ERROR("treat SCAN_HIGH_OR_EQUAL command\n");
- fdctrl_start_transfer(fdctrl, FD_DIR_SCANH);
- return;
- default:
- break;
- }
- switch (fdctrl->fifo[0] & 0x3F) {
- case 0x05:
- /* WRITE variants */
- FLOPPY_DPRINTF("treat WRITE command (%02x)\n", fdctrl->fifo[0]);
- fdctrl_start_transfer(fdctrl, FD_DIR_WRITE);
- return;
- case 0x09:
- /* WRITE_DELETED variants */
-// FLOPPY_DPRINTF("treat WRITE_DELETED command\n");
- FLOPPY_ERROR("treat WRITE_DELETED command\n");
- fdctrl_start_transfer_del(fdctrl, FD_DIR_WRITE);
- return;
- default:
- break;
- }
- switch (fdctrl->fifo[0]) {
- case 0x03:
- /* SPECIFY */
- FLOPPY_DPRINTF("treat SPECIFY command\n");
- fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
- fdctrl->timer1 = fdctrl->fifo[2] >> 1;
- fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ;
- /* No result back */
- fdctrl_reset_fifo(fdctrl);
- break;
- case 0x04:
- /* SENSE_DRIVE_STATUS */
- FLOPPY_DPRINTF("treat SENSE_DRIVE_STATUS command\n");
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
- /* 1 Byte status back */
- fdctrl->fifo[0] = (cur_drv->ro << 6) |
- (cur_drv->track == 0 ? 0x10 : 0x00) |
- (cur_drv->head << 2) |
- fdctrl->cur_drv |
- 0x28;
- fdctrl_set_fifo(fdctrl, 1, 0);
- break;
- case 0x07:
- /* RECALIBRATE */
- FLOPPY_DPRINTF("treat RECALIBRATE command\n");
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fd_recalibrate(cur_drv);
- fdctrl_reset_fifo(fdctrl);
- /* Raise Interrupt */
- fdctrl_raise_irq(fdctrl, 0x20);
- break;
- case 0x0F:
- /* SEEK */
- FLOPPY_DPRINTF("treat SEEK command\n");
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fd_start(cur_drv);
- if (fdctrl->fifo[2] <= cur_drv->track)
- cur_drv->dir = 1;
- else
- cur_drv->dir = 0;
- fdctrl_reset_fifo(fdctrl);
- if (fdctrl->fifo[2] > cur_drv->max_track) {
- fdctrl_raise_irq(fdctrl, 0x60);
- } else {
- cur_drv->track = fdctrl->fifo[2];
- /* Raise Interrupt */
- fdctrl_raise_irq(fdctrl, 0x20);
- }
- break;
- case 0x12:
- /* PERPENDICULAR_MODE */
- FLOPPY_DPRINTF("treat PERPENDICULAR_MODE command\n");
- if (fdctrl->fifo[1] & 0x80)
- cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
- /* No result back */
- fdctrl_reset_fifo(fdctrl);
- break;
- case 0x13:
- /* CONFIGURE */
- FLOPPY_DPRINTF("treat CONFIGURE command\n");
- fdctrl->config = fdctrl->fifo[2];
- fdctrl->precomp_trk = fdctrl->fifo[3];
- /* No result back */
- fdctrl_reset_fifo(fdctrl);
- break;
- case 0x17:
- /* POWERDOWN_MODE */
- FLOPPY_DPRINTF("treat POWERDOWN_MODE command\n");
- fdctrl->pwrd = fdctrl->fifo[1];
- fdctrl->fifo[0] = fdctrl->fifo[1];
- fdctrl_set_fifo(fdctrl, 1, 1);
- break;
- case 0x33:
- /* OPTION */
- FLOPPY_DPRINTF("treat OPTION command\n");
- /* No result back */
- fdctrl_reset_fifo(fdctrl);
- break;
- case 0x42:
- /* READ_TRACK */
-// FLOPPY_DPRINTF("treat READ_TRACK command\n");
- FLOPPY_ERROR("treat READ_TRACK command\n");
- fdctrl_start_transfer(fdctrl, FD_DIR_READ);
- break;
- case 0x4A:
- /* READ_ID */
- FLOPPY_DPRINTF("treat READ_ID command\n");
- /* XXX: should set main status register to busy */
- cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
- qemu_mod_timer(fdctrl->result_timer,
- qemu_get_clock(vm_clock) + (ticks_per_sec / 50));
- break;
- case 0x4C:
- /* RESTORE */
- FLOPPY_DPRINTF("treat RESTORE command\n");
- /* Drives position */
- drv0(fdctrl)->track = fdctrl->fifo[3];
- drv1(fdctrl)->track = fdctrl->fifo[4];
- /* timers */
- fdctrl->timer0 = fdctrl->fifo[7];
- fdctrl->timer1 = fdctrl->fifo[8];
- cur_drv->last_sect = fdctrl->fifo[9];
- fdctrl->lock = fdctrl->fifo[10] >> 7;
- cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
- fdctrl->config = fdctrl->fifo[11];
- fdctrl->precomp_trk = fdctrl->fifo[12];
- fdctrl->pwrd = fdctrl->fifo[13];
- fdctrl_reset_fifo(fdctrl);
- break;
- case 0x4D:
- /* FORMAT_TRACK */
- FLOPPY_DPRINTF("treat FORMAT_TRACK command\n");
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fdctrl->data_state |= FD_STATE_FORMAT;
- if (fdctrl->fifo[0] & 0x80)
- fdctrl->data_state |= FD_STATE_MULTI;
- else
- fdctrl->data_state &= ~FD_STATE_MULTI;
- fdctrl->data_state &= ~FD_STATE_SEEK;
- cur_drv->bps =
- fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
-#if 0
- cur_drv->last_sect =
- cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
- fdctrl->fifo[3] / 2;
-#else
- cur_drv->last_sect = fdctrl->fifo[3];
-#endif
- /* Bochs BIOS is buggy and don't send format informations
- * for each sector. So, pretend all's done right now...
- */
- fdctrl->data_state &= ~FD_STATE_FORMAT;
- fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
- break;
- case 0x8E:
- /* DRIVE_SPECIFICATION_COMMAND */
- FLOPPY_DPRINTF("treat DRIVE_SPECIFICATION_COMMAND command\n");
- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
- /* Command parameters done */
- if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
- fdctrl->fifo[0] = fdctrl->fifo[1];
- fdctrl->fifo[2] = 0;
- fdctrl->fifo[3] = 0;
- fdctrl_set_fifo(fdctrl, 4, 1);
- } else {
- fdctrl_reset_fifo(fdctrl);
- }
- } else if (fdctrl->data_len > 7) {
- /* ERROR */
- fdctrl->fifo[0] = 0x80 |
- (cur_drv->head << 2) | fdctrl->cur_drv;
- fdctrl_set_fifo(fdctrl, 1, 1);
- }
- break;
- case 0x8F:
- /* RELATIVE_SEEK_OUT */
- FLOPPY_DPRINTF("treat RELATIVE_SEEK_OUT command\n");
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fd_start(cur_drv);
- cur_drv->dir = 0;
- if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
- cur_drv->track = cur_drv->max_track - 1;
- } else {
- cur_drv->track += fdctrl->fifo[2];
- }
- fdctrl_reset_fifo(fdctrl);
- fdctrl_raise_irq(fdctrl, 0x20);
- break;
- case 0xCD:
- /* FORMAT_AND_WRITE */
-// FLOPPY_DPRINTF("treat FORMAT_AND_WRITE command\n");
- FLOPPY_ERROR("treat FORMAT_AND_WRITE command\n");
- fdctrl_unimplemented(fdctrl);
- break;
- case 0xCF:
- /* RELATIVE_SEEK_IN */
- FLOPPY_DPRINTF("treat RELATIVE_SEEK_IN command\n");
- fdctrl->cur_drv = fdctrl->fifo[1] & 1;
- cur_drv = get_cur_drv(fdctrl);
- fd_start(cur_drv);
- cur_drv->dir = 1;
- if (fdctrl->fifo[2] > cur_drv->track) {
- cur_drv->track = 0;
- } else {
- cur_drv->track -= fdctrl->fifo[2];
- }
- fdctrl_reset_fifo(fdctrl);
- /* Raise Interrupt */
- fdctrl_raise_irq(fdctrl, 0x20);
- break;
- }
- }
-}
-
-static void fdctrl_result_timer(void *opaque)
-{
- fdctrl_t *fdctrl = opaque;
- fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
-}
diff --git a/hw/fmopl.c b/hw/fmopl.c
deleted file mode 100644
index 2b0e82b..0000000
--- a/hw/fmopl.c
+++ /dev/null
@@ -1,1390 +0,0 @@
-/*
-**
-** File: fmopl.c -- software implementation of FM sound generator
-**
-** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
-**
-** Version 0.37a
-**
-*/
-
-/*
- preliminary :
- Problem :
- note:
-*/
-
-/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define INLINE __inline
-#define HAS_YM3812 1
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <math.h>
-//#include "driver.h" /* use M.A.M.E. */
-#include "fmopl.h"
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-/* -------------------- for debug --------------------- */
-/* #define OPL_OUTPUT_LOG */
-#ifdef OPL_OUTPUT_LOG
-static FILE *opl_dbg_fp = NULL;
-static FM_OPL *opl_dbg_opl[16];
-static int opl_dbg_maxchip,opl_dbg_chip;
-#endif
-
-/* -------------------- preliminary define section --------------------- */
-/* attack/decay rate time rate */
-#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
-#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
-
-#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
-
-#define FREQ_BITS 24 /* frequency turn */
-
-/* counter bits = 20 , octerve 7 */
-#define FREQ_RATE (1<<(FREQ_BITS-20))
-#define TL_BITS (FREQ_BITS+2)
-
-/* final output shift , limit minimum and maximum */
-#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
-#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
-#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
-
-/* -------------------- quality selection --------------------- */
-
-/* sinwave entries */
-/* used static memory = SIN_ENT * 4 (byte) */
-#define SIN_ENT 2048
-
-/* output level entries (envelope,sinwave) */
-/* envelope counter lower bits */
-#define ENV_BITS 16
-/* envelope output entries */
-#define EG_ENT 4096
-/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
-/* used static memory = EG_ENT*4 (byte) */
-
-#define EG_OFF ((2*EG_ENT)<<ENV_BITS) /* OFF */
-#define EG_DED EG_OFF
-#define EG_DST (EG_ENT<<ENV_BITS) /* DECAY START */
-#define EG_AED EG_DST
-#define EG_AST 0 /* ATTACK START */
-
-#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
-
-/* LFO table entries */
-#define VIB_ENT 512
-#define VIB_SHIFT (32-9)
-#define AMS_ENT 512
-#define AMS_SHIFT (32-9)
-
-#define VIB_RATE 256
-
-/* -------------------- local defines , macros --------------------- */
-
-/* register number to channel number , slot offset */
-#define SLOT1 0
-#define SLOT2 1
-
-/* envelope phase */
-#define ENV_MOD_RR 0x00
-#define ENV_MOD_DR 0x01
-#define ENV_MOD_AR 0x02
-
-/* -------------------- tables --------------------- */
-static const int slot_array[32]=
-{
- 0, 2, 4, 1, 3, 5,-1,-1,
- 6, 8,10, 7, 9,11,-1,-1,
- 12,14,16,13,15,17,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1
-};
-
-/* key scale level */
-/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
-#define DV (EG_STEP/2)
-static const UINT32 KSL_TABLE[8*16]=
-{
- /* OCT 0 */
- 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
- 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
- 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
- 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
- /* OCT 1 */
- 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
- 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
- 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
- 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
- /* OCT 2 */
- 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
- 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
- 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
- 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
- /* OCT 3 */
- 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
- 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
- 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
- 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
- /* OCT 4 */
- 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
- 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
- 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
- 10.875/DV,11.250/DV,11.625/DV,12.000/DV,
- /* OCT 5 */
- 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
- 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
- 12.000/DV,12.750/DV,13.125/DV,13.500/DV,
- 13.875/DV,14.250/DV,14.625/DV,15.000/DV,
- /* OCT 6 */
- 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
- 12.000/DV,13.125/DV,13.875/DV,14.625/DV,
- 15.000/DV,15.750/DV,16.125/DV,16.500/DV,
- 16.875/DV,17.250/DV,17.625/DV,18.000/DV,
- /* OCT 7 */
- 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
- 15.000/DV,16.125/DV,16.875/DV,17.625/DV,
- 18.000/DV,18.750/DV,19.125/DV,19.500/DV,
- 19.875/DV,20.250/DV,20.625/DV,21.000/DV
-};
-#undef DV
-
-/* sustain lebel table (3db per step) */
-/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
-#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
-static const INT32 SL_TABLE[16]={
- SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
- SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
-};
-#undef SC
-
-#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
-/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
-/* TL_TABLE[ 0 to TL_MAX ] : plus section */
-/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
-static INT32 *TL_TABLE;
-
-/* pointers to TL_TABLE with sinwave output offset */
-static INT32 **SIN_TABLE;
-
-/* LFO table */
-static INT32 *AMS_TABLE;
-static INT32 *VIB_TABLE;
-
-/* envelope output curve table */
-/* attack + decay + OFF */
-static INT32 ENV_CURVE[2*EG_ENT+1];
-
-/* multiple table */
-#define ML 2
-static const UINT32 MUL_TABLE[16]= {
-/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
- 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
- 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
-};
-#undef ML
-
-/* dummy attack / decay rate ( when rate == 0 ) */
-static INT32 RATE_0[16]=
-{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-/* -------------------- static state --------------------- */
-
-/* lock level of common table */
-static int num_lock = 0;
-
-/* work table */
-static void *cur_chip = NULL; /* current chip point */
-/* currenct chip state */
-/* static OPLSAMPLE *bufL,*bufR; */
-static OPL_CH *S_CH;
-static OPL_CH *E_CH;
-OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
-
-static INT32 outd[1];
-static INT32 ams;
-static INT32 vib;
-INT32 *ams_table;
-INT32 *vib_table;
-static INT32 amsIncr;
-static INT32 vibIncr;
-static INT32 feedback2; /* connect for SLOT 2 */
-
-/* log output level */
-#define LOG_ERR 3 /* ERROR */
-#define LOG_WAR 2 /* WARNING */
-#define LOG_INF 1 /* INFORMATION */
-
-//#define LOG_LEVEL LOG_INF
-#define LOG_LEVEL LOG_ERR
-
-//#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x
-#define LOG(n,x)
-
-/* --------------------- subroutines --------------------- */
-
-INLINE int Limit( int val, int max, int min ) {
- if ( val > max )
- val = max;
- else if ( val < min )
- val = min;
-
- return val;
-}
-
-/* status set and IRQ handling */
-INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
-{
- /* set status flag */
- OPL->status |= flag;
- if(!(OPL->status & 0x80))
- {
- if(OPL->status & OPL->statusmask)
- { /* IRQ on */
- OPL->status |= 0x80;
- /* callback user interrupt handler (IRQ is OFF to ON) */
- if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
- }
- }
-}
-
-/* status reset and IRQ handling */
-INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
-{
- /* reset status flag */
- OPL->status &=~flag;
- if((OPL->status & 0x80))
- {
- if (!(OPL->status & OPL->statusmask) )
- {
- OPL->status &= 0x7f;
- /* callback user interrupt handler (IRQ is ON to OFF) */
- if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
- }
- }
-}
-
-/* IRQ mask set */
-INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
-{
- OPL->statusmask = flag;
- /* IRQ handling check */
- OPL_STATUS_SET(OPL,0);
- OPL_STATUS_RESET(OPL,0);
-}
-
-/* ----- key on ----- */
-INLINE void OPL_KEYON(OPL_SLOT *SLOT)
-{
- /* sin wave restart */
- SLOT->Cnt = 0;
- /* set attack */
- SLOT->evm = ENV_MOD_AR;
- SLOT->evs = SLOT->evsa;
- SLOT->evc = EG_AST;
- SLOT->eve = EG_AED;
-}
-/* ----- key off ----- */
-INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
-{
- if( SLOT->evm > ENV_MOD_RR)
- {
- /* set envelope counter from envleope output */
- SLOT->evm = ENV_MOD_RR;
- if( !(SLOT->evc&EG_DST) )
- //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
- SLOT->evc = EG_DST;
- SLOT->eve = EG_DED;
- SLOT->evs = SLOT->evsr;
- }
-}
-
-/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
-/* return : envelope output */
-INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
-{
- /* calcrate envelope generator */
- if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
- {
- switch( SLOT->evm ){
- case ENV_MOD_AR: /* ATTACK -> DECAY1 */
- /* next DR */
- SLOT->evm = ENV_MOD_DR;
- SLOT->evc = EG_DST;
- SLOT->eve = SLOT->SL;
- SLOT->evs = SLOT->evsd;
- break;
- case ENV_MOD_DR: /* DECAY -> SL or RR */
- SLOT->evc = SLOT->SL;
- SLOT->eve = EG_DED;
- if(SLOT->eg_typ)
- {
- SLOT->evs = 0;
- }
- else
- {
- SLOT->evm = ENV_MOD_RR;
- SLOT->evs = SLOT->evsr;
- }
- break;
- case ENV_MOD_RR: /* RR -> OFF */
- SLOT->evc = EG_OFF;
- SLOT->eve = EG_OFF+1;
- SLOT->evs = 0;
- break;
- }
- }
- /* calcrate envelope */
- return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
-}
-
-/* set algorythm connection */
-static void set_algorythm( OPL_CH *CH)
-{
- INT32 *carrier = &outd[0];
- CH->connect1 = CH->CON ? carrier : &feedback2;
- CH->connect2 = carrier;
-}
-
-/* ---------- frequency counter for operater update ---------- */
-INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
-{
- int ksr;
-
- /* frequency step counter */
- SLOT->Incr = CH->fc * SLOT->mul;
- ksr = CH->kcode >> SLOT->KSR;
-
- if( SLOT->ksr != ksr )
- {
- SLOT->ksr = ksr;
- /* attack , decay rate recalcration */
- SLOT->evsa = SLOT->AR[ksr];
- SLOT->evsd = SLOT->DR[ksr];
- SLOT->evsr = SLOT->RR[ksr];
- }
- SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
-}
-
-/* set multi,am,vib,EG-TYP,KSR,mul */
-INLINE void set_mul(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->mul = MUL_TABLE[v&0x0f];
- SLOT->KSR = (v&0x10) ? 0 : 2;
- SLOT->eg_typ = (v&0x20)>>5;
- SLOT->vib = (v&0x40);
- SLOT->ams = (v&0x80);
- CALC_FCSLOT(CH,SLOT);
-}
-
-/* set ksl & tl */
-INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
- int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */
-
- SLOT->ksl = ksl ? 3-ksl : 31;
- SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
-
- if( !(OPL->mode&0x80) )
- { /* not CSM latch total level */
- SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
- }
-}
-
-/* set attack rate & decay rate */
-INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
- int ar = v>>4;
- int dr = v&0x0f;
-
- SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
- SLOT->evsa = SLOT->AR[SLOT->ksr];
- if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
-
- SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
- SLOT->evsd = SLOT->DR[SLOT->ksr];
- if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
-}
-
-/* set sustain level & release rate */
-INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
- int sl = v>>4;
- int rr = v & 0x0f;
-
- SLOT->SL = SL_TABLE[sl];
- if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
- SLOT->RR = &OPL->DR_TABLE[rr<<2];
- SLOT->evsr = SLOT->RR[SLOT->ksr];
- if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
-}
-
-/* operator output calcrator */
-#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
-/* ---------- calcrate one of channel ---------- */
-INLINE void OPL_CALC_CH( OPL_CH *CH )
-{
- UINT32 env_out;
- OPL_SLOT *SLOT;
-
- feedback2 = 0;
- /* SLOT 1 */
- SLOT = &CH->SLOT[SLOT1];
- env_out=OPL_CALC_SLOT(SLOT);
- if( env_out < EG_ENT-1 )
- {
- /* PG */
- if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
- else SLOT->Cnt += SLOT->Incr;
- /* connectoion */
- if(CH->FB)
- {
- int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
- CH->op1_out[1] = CH->op1_out[0];
- *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
- }
- else
- {
- *CH->connect1 += OP_OUT(SLOT,env_out,0);
- }
- }else
- {
- CH->op1_out[1] = CH->op1_out[0];
- CH->op1_out[0] = 0;
- }
- /* SLOT 2 */
- SLOT = &CH->SLOT[SLOT2];
- env_out=OPL_CALC_SLOT(SLOT);
- if( env_out < EG_ENT-1 )
- {
- /* PG */
- if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
- else SLOT->Cnt += SLOT->Incr;
- /* connectoion */
- outd[0] += OP_OUT(SLOT,env_out, feedback2);
- }
-}
-
-/* ---------- calcrate rythm block ---------- */
-#define WHITE_NOISE_db 6.0
-INLINE void OPL_CALC_RH( OPL_CH *CH )
-{
- UINT32 env_tam,env_sd,env_top,env_hh;
- int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
- INT32 tone8;
-
- OPL_SLOT *SLOT;
- int env_out;
-
- /* BD : same as FM serial mode and output level is large */
- feedback2 = 0;
- /* SLOT 1 */
- SLOT = &CH[6].SLOT[SLOT1];
- env_out=OPL_CALC_SLOT(SLOT);
- if( env_out < EG_ENT-1 )
- {
- /* PG */
- if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
- else SLOT->Cnt += SLOT->Incr;
- /* connectoion */
- if(CH[6].FB)
- {
- int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;
- CH[6].op1_out[1] = CH[6].op1_out[0];
- feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
- }
- else
- {
- feedback2 = OP_OUT(SLOT,env_out,0);
- }
- }else
- {
- feedback2 = 0;
- CH[6].op1_out[1] = CH[6].op1_out[0];
- CH[6].op1_out[0] = 0;
- }
- /* SLOT 2 */
- SLOT = &CH[6].SLOT[SLOT2];
- env_out=OPL_CALC_SLOT(SLOT);
- if( env_out < EG_ENT-1 )
- {
- /* PG */
- if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
- else SLOT->Cnt += SLOT->Incr;
- /* connectoion */
- outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;
- }
-
- // SD (17) = mul14[fnum7] + white noise
- // TAM (15) = mul15[fnum8]
- // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
- // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
- env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;
- env_tam=OPL_CALC_SLOT(SLOT8_1);
- env_top=OPL_CALC_SLOT(SLOT8_2);
- env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;
-
- /* PG */
- if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);
- else SLOT7_1->Cnt += 2*SLOT7_1->Incr;
- if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);
- else SLOT7_2->Cnt += (CH[7].fc*8);
- if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);
- else SLOT8_1->Cnt += SLOT8_1->Incr;
- if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);
- else SLOT8_2->Cnt += (CH[8].fc*48);
-
- tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
-
- /* SD */
- if( env_sd < EG_ENT-1 )
- outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;
- /* TAM */
- if( env_tam < EG_ENT-1 )
- outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;
- /* TOP-CY */
- if( env_top < EG_ENT-1 )
- outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;
- /* HH */
- if( env_hh < EG_ENT-1 )
- outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;
-}
-
-/* ----------- initialize time tabls ----------- */
-static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
-{
- int i;
- double rate;
-
- /* make attack rate & decay rate tables */
- for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
- for (i = 4;i <= 60;i++){
- rate = OPL->freqbase; /* frequency rate */
- if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
- rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */
- rate *= (double)(EG_ENT<<ENV_BITS);
- OPL->AR_TABLE[i] = rate / ARRATE;
- OPL->DR_TABLE[i] = rate / DRRATE;
- }
- for (i = 60;i < 76;i++)
- {
- OPL->AR_TABLE[i] = EG_AED-1;
- OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
- }
-#if 0
- for (i = 0;i < 64 ;i++){ /* make for overflow area */
- LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i,
- ((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),
- ((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));
- }
-#endif
-}
-
-/* ---------- generic table initialize ---------- */
-static int OPLOpenTable( void )
-{
- int s,t;
- double rate;
- int i,j;
- double pom;
-
- /* allocate dynamic tables */
- if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
- return 0;
- if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
- {
- free(TL_TABLE);
- return 0;
- }
- if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
- {
- free(TL_TABLE);
- free(SIN_TABLE);
- return 0;
- }
- if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
- {
- free(TL_TABLE);
- free(SIN_TABLE);
- free(AMS_TABLE);
- return 0;
- }
- /* make total level table */
- for (t = 0;t < EG_ENT-1 ;t++){
- rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */
- TL_TABLE[ t] = (int)rate;
- TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
-/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/
- }
- /* fill volume off area */
- for ( t = EG_ENT-1; t < TL_MAX ;t++){
- TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
- }
-
- /* make sinwave table (total level offet) */
- /* degree 0 = degree 180 = off */
- SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1];
- for (s = 1;s <= SIN_ENT/4;s++){
- pom = sin(2*PI*s/SIN_ENT); /* sin */
- pom = 20*log10(1/pom); /* decibel */
- j = pom / EG_STEP; /* TL_TABLE steps */
-
- /* degree 0 - 90 , degree 180 - 90 : plus section */
- SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
- /* degree 180 - 270 , degree 360 - 270 : minus section */
- SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j];
-/* LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/
- }
- for (s = 0;s < SIN_ENT;s++)
- {
- SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
- SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
- SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
- }
-
- /* envelope counter -> envelope output table */
- for (i=0; i<EG_ENT; i++)
- {
- /* ATTACK curve */
- pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
- /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
- ENV_CURVE[i] = (int)pom;
- /* DECAY ,RELEASE curve */
- ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
- }
- /* off */
- ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
- /* make LFO ams table */
- for (i=0; i<AMS_ENT; i++)
- {
- pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */
- AMS_TABLE[i] = (1.0/EG_STEP)*pom; /* 1dB */
- AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */
- }
- /* make LFO vibrate table */
- for (i=0; i<VIB_ENT; i++)
- {
- /* 100cent = 1seminote = 6% ?? */
- pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */
- VIB_TABLE[i] = VIB_RATE + (pom*0.07); /* +- 7cent */
- VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */
- /* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */
- }
- return 1;
-}
-
-
-static void OPLCloseTable( void )
-{
- free(TL_TABLE);
- free(SIN_TABLE);
- free(AMS_TABLE);
- free(VIB_TABLE);
-}
-
-/* CSM Key Controll */
-INLINE void CSMKeyControll(OPL_CH *CH)
-{
- OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
- OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
- /* all key off */
- OPL_KEYOFF(slot1);
- OPL_KEYOFF(slot2);
- /* total level latch */
- slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
- slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
- /* key on */
- CH->op1_out[0] = CH->op1_out[1] = 0;
- OPL_KEYON(slot1);
- OPL_KEYON(slot2);
-}
-
-/* ---------- opl initialize ---------- */
-static void OPL_initalize(FM_OPL *OPL)
-{
- int fn;
-
- /* frequency base */
- OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
- /* Timer base time */
- OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
- /* make time tables */
- init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
- /* make fnumber -> increment counter table */
- for( fn=0 ; fn < 1024 ; fn++ )
- {
- OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
- }
- /* LFO freq.table */
- OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;
- OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;
-}
-
-/* ---------- write a OPL registers ---------- */
-static void OPLWriteReg(FM_OPL *OPL, int r, int v)
-{
- OPL_CH *CH;
- int slot;
- int block_fnum;
-
- switch(r&0xe0)
- {
- case 0x00: /* 00-1f:controll */
- switch(r&0x1f)
- {
- case 0x01:
- /* wave selector enable */
- if(OPL->type&OPL_TYPE_WAVESEL)
- {
- OPL->wavesel = v&0x20;
- if(!OPL->wavesel)
- {
- /* preset compatible mode */
- int c;
- for(c=0;c<OPL->max_ch;c++)
- {
- OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
- OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
- }
- }
- }
- return;
- case 0x02: /* Timer 1 */
- OPL->T[0] = (256-v)*4;
- break;
- case 0x03: /* Timer 2 */
- OPL->T[1] = (256-v)*16;
- return;
- case 0x04: /* IRQ clear / mask and Timer enable */
- if(v&0x80)
- { /* IRQ flag clear */
- OPL_STATUS_RESET(OPL,0x7f);
- }
- else
- { /* set IRQ mask ,timer enable*/
- UINT8 st1 = v&1;
- UINT8 st2 = (v>>1)&1;
- /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
- OPL_STATUS_RESET(OPL,v&0x78);
- OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
- /* timer 2 */
- if(OPL->st[1] != st2)
- {
- double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;
- OPL->st[1] = st2;
- if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);
- }
- /* timer 1 */
- if(OPL->st[0] != st1)
- {
- double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;
- OPL->st[0] = st1;
- if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);
- }
- }
- return;
-#if BUILD_Y8950
- case 0x06: /* Key Board OUT */
- if(OPL->type&OPL_TYPE_KEYBOARD)
- {
- if(OPL->keyboardhandler_w)
- OPL->keyboardhandler_w(OPL->keyboard_param,v);
- else
- LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
- }
- return;
- case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
- return;
- case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
- OPL->mode = v;
- v&=0x1f; /* for DELTA-T unit */
- case 0x09: /* START ADD */
- case 0x0a:
- case 0x0b: /* STOP ADD */
- case 0x0c:
- case 0x0d: /* PRESCALE */
- case 0x0e:
- case 0x0f: /* ADPCM data */
- case 0x10: /* DELTA-N */
- case 0x11: /* DELTA-N */
- case 0x12: /* EG-CTRL */
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
- return;
-#if 0
- case 0x15: /* DAC data */
- case 0x16:
- case 0x17: /* SHIFT */
- return;
- case 0x18: /* I/O CTRL (Direction) */
- if(OPL->type&OPL_TYPE_IO)
- OPL->portDirection = v&0x0f;
- return;
- case 0x19: /* I/O DATA */
- if(OPL->type&OPL_TYPE_IO)
- {
- OPL->portLatch = v;
- if(OPL->porthandler_w)
- OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
- }
- return;
- case 0x1a: /* PCM data */
- return;
-#endif
-#endif
- }
- break;
- case 0x20: /* am,vib,ksr,eg type,mul */
- slot = slot_array[r&0x1f];
- if(slot == -1) return;
- set_mul(OPL,slot,v);
- return;
- case 0x40:
- slot = slot_array[r&0x1f];
- if(slot == -1) return;
- set_ksl_tl(OPL,slot,v);
- return;
- case 0x60:
- slot = slot_array[r&0x1f];
- if(slot == -1) return;
- set_ar_dr(OPL,slot,v);
- return;
- case 0x80:
- slot = slot_array[r&0x1f];
- if(slot == -1) return;
- set_sl_rr(OPL,slot,v);
- return;
- case 0xa0:
- switch(r)
- {
- case 0xbd:
- /* amsep,vibdep,r,bd,sd,tom,tc,hh */
- {
- UINT8 rkey = OPL->rythm^v;
- OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
- OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
- OPL->rythm = v&0x3f;
- if(OPL->rythm&0x20)
- {
-#if 0
- usrintf_showmessage("OPL Rythm mode select");
-#endif
- /* BD key on/off */
- if(rkey&0x10)
- {
- if(v&0x10)
- {
- OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
- OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
- OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
- }
- else
- {
- OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
- OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
- }
- }
- /* SD key on/off */
- if(rkey&0x08)
- {
- if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
- else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
- }/* TAM key on/off */
- if(rkey&0x04)
- {
- if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
- else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
- }
- /* TOP-CY key on/off */
- if(rkey&0x02)
- {
- if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
- else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
- }
- /* HH key on/off */
- if(rkey&0x01)
- {
- if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
- else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
- }
- }
- }
- return;
- }
- /* keyon,block,fnum */
- if( (r&0x0f) > 8) return;
- CH = &OPL->P_CH[r&0x0f];
- if(!(r&0x10))
- { /* a0-a8 */
- block_fnum = (CH->block_fnum&0x1f00) | v;
- }
- else
- { /* b0-b8 */
- int keyon = (v>>5)&1;
- block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
- if(CH->keyon != keyon)
- {
- if( (CH->keyon=keyon) )
- {
- CH->op1_out[0] = CH->op1_out[1] = 0;
- OPL_KEYON(&CH->SLOT[SLOT1]);
- OPL_KEYON(&CH->SLOT[SLOT2]);
- }
- else
- {
- OPL_KEYOFF(&CH->SLOT[SLOT1]);
- OPL_KEYOFF(&CH->SLOT[SLOT2]);
- }
- }
- }
- /* update */
- if(CH->block_fnum != block_fnum)
- {
- int blockRv = 7-(block_fnum>>10);
- int fnum = block_fnum&0x3ff;
- CH->block_fnum = block_fnum;
-
- CH->ksl_base = KSL_TABLE[block_fnum>>6];
- CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
- CH->kcode = CH->block_fnum>>9;
- if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
- CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
- CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
- }
- return;
- case 0xc0:
- /* FB,C */
- if( (r&0x0f) > 8) return;
- CH = &OPL->P_CH[r&0x0f];
- {
- int feedback = (v>>1)&7;
- CH->FB = feedback ? (8+1) - feedback : 0;
- CH->CON = v&1;
- set_algorythm(CH);
- }
- return;
- case 0xe0: /* wave type */
- slot = slot_array[r&0x1f];
- if(slot == -1) return;
- CH = &OPL->P_CH[slot/2];
- if(OPL->wavesel)
- {
- /* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */
- CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
- }
- return;
- }
-}
-
-/* lock/unlock for common table */
-static int OPL_LockTable(void)
-{
- num_lock++;
- if(num_lock>1) return 0;
- /* first time */
- cur_chip = NULL;
- /* allocate total level table (128kb space) */
- if( !OPLOpenTable() )
- {
- num_lock--;
- return -1;
- }
- return 0;
-}
-
-static void OPL_UnLockTable(void)
-{
- if(num_lock) num_lock--;
- if(num_lock) return;
- /* last time */
- cur_chip = NULL;
- OPLCloseTable();
-}
-
-#if (BUILD_YM3812 || BUILD_YM3526)
-/*******************************************************************************/
-/* YM3812 local section */
-/*******************************************************************************/
-
-/* ---------- update one of chip ----------- */
-void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
-{
- int i;
- int data;
- OPLSAMPLE *buf = buffer;
- UINT32 amsCnt = OPL->amsCnt;
- UINT32 vibCnt = OPL->vibCnt;
- UINT8 rythm = OPL->rythm&0x20;
- OPL_CH *CH,*R_CH;
-
- if( (void *)OPL != cur_chip ){
- cur_chip = (void *)OPL;
- /* channel pointers */
- S_CH = OPL->P_CH;
- E_CH = &S_CH[9];
- /* rythm slot */
- SLOT7_1 = &S_CH[7].SLOT[SLOT1];
- SLOT7_2 = &S_CH[7].SLOT[SLOT2];
- SLOT8_1 = &S_CH[8].SLOT[SLOT1];
- SLOT8_2 = &S_CH[8].SLOT[SLOT2];
- /* LFO state */
- amsIncr = OPL->amsIncr;
- vibIncr = OPL->vibIncr;
- ams_table = OPL->ams_table;
- vib_table = OPL->vib_table;
- }
- R_CH = rythm ? &S_CH[6] : E_CH;
- for( i=0; i < length ; i++ )
- {
- /* channel A channel B channel C */
- /* LFO */
- ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
- vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
- outd[0] = 0;
- /* FM part */
- for(CH=S_CH ; CH < R_CH ; CH++)
- OPL_CALC_CH(CH);
- /* Rythn part */
- if(rythm)
- OPL_CALC_RH(S_CH);
- /* limit check */
- data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
- /* store to sound buffer */
- buf[i] = data >> OPL_OUTSB;
- }
-
- OPL->amsCnt = amsCnt;
- OPL->vibCnt = vibCnt;
-#ifdef OPL_OUTPUT_LOG
- if(opl_dbg_fp)
- {
- for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
- if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
- fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256);
- }
-#endif
-}
-#endif /* (BUILD_YM3812 || BUILD_YM3526) */
-
-#if BUILD_Y8950
-
-void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
-{
- int i;
- int data;
- OPLSAMPLE *buf = buffer;
- UINT32 amsCnt = OPL->amsCnt;
- UINT32 vibCnt = OPL->vibCnt;
- UINT8 rythm = OPL->rythm&0x20;
- OPL_CH *CH,*R_CH;
- YM_DELTAT *DELTAT = OPL->deltat;
-
- /* setup DELTA-T unit */
- YM_DELTAT_DECODE_PRESET(DELTAT);
-
- if( (void *)OPL != cur_chip ){
- cur_chip = (void *)OPL;
- /* channel pointers */
- S_CH = OPL->P_CH;
- E_CH = &S_CH[9];
- /* rythm slot */
- SLOT7_1 = &S_CH[7].SLOT[SLOT1];
- SLOT7_2 = &S_CH[7].SLOT[SLOT2];
- SLOT8_1 = &S_CH[8].SLOT[SLOT1];
- SLOT8_2 = &S_CH[8].SLOT[SLOT2];
- /* LFO state */
- amsIncr = OPL->amsIncr;
- vibIncr = OPL->vibIncr;
- ams_table = OPL->ams_table;
- vib_table = OPL->vib_table;
- }
- R_CH = rythm ? &S_CH[6] : E_CH;
- for( i=0; i < length ; i++ )
- {
- /* channel A channel B channel C */
- /* LFO */
- ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
- vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
- outd[0] = 0;
- /* deltaT ADPCM */
- if( DELTAT->portstate )
- YM_DELTAT_ADPCM_CALC(DELTAT);
- /* FM part */
- for(CH=S_CH ; CH < R_CH ; CH++)
- OPL_CALC_CH(CH);
- /* Rythn part */
- if(rythm)
- OPL_CALC_RH(S_CH);
- /* limit check */
- data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
- /* store to sound buffer */
- buf[i] = data >> OPL_OUTSB;
- }
- OPL->amsCnt = amsCnt;
- OPL->vibCnt = vibCnt;
- /* deltaT START flag */
- if( !DELTAT->portstate )
- OPL->status &= 0xfe;
-}
-#endif
-
-/* ---------- reset one of chip ---------- */
-void OPLResetChip(FM_OPL *OPL)
-{
- int c,s;
- int i;
-
- /* reset chip */
- OPL->mode = 0; /* normal mode */
- OPL_STATUS_RESET(OPL,0x7f);
- /* reset with register write */
- OPLWriteReg(OPL,0x01,0); /* wabesel disable */
- OPLWriteReg(OPL,0x02,0); /* Timer1 */
- OPLWriteReg(OPL,0x03,0); /* Timer2 */
- OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
- for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
- /* reset OPerator paramater */
- for( c = 0 ; c < OPL->max_ch ; c++ )
- {
- OPL_CH *CH = &OPL->P_CH[c];
- /* OPL->P_CH[c].PAN = OPN_CENTER; */
- for(s = 0 ; s < 2 ; s++ )
- {
- /* wave table */
- CH->SLOT[s].wavetable = &SIN_TABLE[0];
- /* CH->SLOT[s].evm = ENV_MOD_RR; */
- CH->SLOT[s].evc = EG_OFF;
- CH->SLOT[s].eve = EG_OFF+1;
- CH->SLOT[s].evs = 0;
- }
- }
-#if BUILD_Y8950
- if(OPL->type&OPL_TYPE_ADPCM)
- {
- YM_DELTAT *DELTAT = OPL->deltat;
-
- DELTAT->freqbase = OPL->freqbase;
- DELTAT->output_pointer = outd;
- DELTAT->portshift = 5;
- DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
- YM_DELTAT_ADPCM_Reset(DELTAT,0);
- }
-#endif
-}
-
-/* ---------- Create one of vietual YM3812 ---------- */
-/* 'rate' is sampling rate and 'bufsiz' is the size of the */
-FM_OPL *OPLCreate(int type, int clock, int rate)
-{
- char *ptr;
- FM_OPL *OPL;
- int state_size;
- int max_ch = 9; /* normaly 9 channels */
-
- if( OPL_LockTable() ==-1) return NULL;
- /* allocate OPL state space */
- state_size = sizeof(FM_OPL);
- state_size += sizeof(OPL_CH)*max_ch;
-#if BUILD_Y8950
- if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
-#endif
- /* allocate memory block */
- ptr = malloc(state_size);
- if(ptr==NULL) return NULL;
- /* clear */
- memset(ptr,0,state_size);
- OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
- OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
-#if BUILD_Y8950
- if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
-#endif
- /* set channel state pointer */
- OPL->type = type;
- OPL->clock = clock;
- OPL->rate = rate;
- OPL->max_ch = max_ch;
- /* init grobal tables */
- OPL_initalize(OPL);
- /* reset chip */
- OPLResetChip(OPL);
-#ifdef OPL_OUTPUT_LOG
- if(!opl_dbg_fp)
- {
- opl_dbg_fp = fopen("opllog.opl","wb");
- opl_dbg_maxchip = 0;
- }
- if(opl_dbg_fp)
- {
- opl_dbg_opl[opl_dbg_maxchip] = OPL;
- fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip,
- type,
- clock&0xff,
- (clock/0x100)&0xff,
- (clock/0x10000)&0xff,
- (clock/0x1000000)&0xff);
- opl_dbg_maxchip++;
- }
-#endif
- return OPL;
-}
-
-/* ---------- Destroy one of vietual YM3812 ---------- */
-void OPLDestroy(FM_OPL *OPL)
-{
-#ifdef OPL_OUTPUT_LOG
- if(opl_dbg_fp)
- {
- fclose(opl_dbg_fp);
- opl_dbg_fp = NULL;
- }
-#endif
- OPL_UnLockTable();
- free(OPL);
-}
-
-/* ---------- Option handlers ---------- */
-
-void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
-{
- OPL->TimerHandler = TimerHandler;
- OPL->TimerParam = channelOffset;
-}
-void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
-{
- OPL->IRQHandler = IRQHandler;
- OPL->IRQParam = param;
-}
-void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
-{
- OPL->UpdateHandler = UpdateHandler;
- OPL->UpdateParam = param;
-}
-#if BUILD_Y8950
-void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
-{
- OPL->porthandler_w = PortHandler_w;
- OPL->porthandler_r = PortHandler_r;
- OPL->port_param = param;
-}
-
-void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
-{
- OPL->keyboardhandler_w = KeyboardHandler_w;
- OPL->keyboardhandler_r = KeyboardHandler_r;
- OPL->keyboard_param = param;
-}
-#endif
-/* ---------- YM3812 I/O interface ---------- */
-int OPLWrite(FM_OPL *OPL,int a,int v)
-{
- if( !(a&1) )
- { /* address port */
- OPL->address = v & 0xff;
- }
- else
- { /* data port */
- if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
-#ifdef OPL_OUTPUT_LOG
- if(opl_dbg_fp)
- {
- for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
- if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
- fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v);
- }
-#endif
- OPLWriteReg(OPL,OPL->address,v);
- }
- return OPL->status>>7;
-}
-
-unsigned char OPLRead(FM_OPL *OPL,int a)
-{
- if( !(a&1) )
- { /* status port */
- return OPL->status & (OPL->statusmask|0x80);
- }
- /* data port */
- switch(OPL->address)
- {
- case 0x05: /* KeyBoard IN */
- if(OPL->type&OPL_TYPE_KEYBOARD)
- {
- if(OPL->keyboardhandler_r)
- return OPL->keyboardhandler_r(OPL->keyboard_param);
- else
- LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));
- }
- return 0;
-#if 0
- case 0x0f: /* ADPCM-DATA */
- return 0;
-#endif
- case 0x19: /* I/O DATA */
- if(OPL->type&OPL_TYPE_IO)
- {
- if(OPL->porthandler_r)
- return OPL->porthandler_r(OPL->port_param);
- else
- LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));
- }
- return 0;
- case 0x1a: /* PCM-DATA */
- return 0;
- }
- return 0;
-}
-
-int OPLTimerOver(FM_OPL *OPL,int c)
-{
- if( c )
- { /* Timer B */
- OPL_STATUS_SET(OPL,0x20);
- }
- else
- { /* Timer A */
- OPL_STATUS_SET(OPL,0x40);
- /* CSM mode key,TL controll */
- if( OPL->mode & 0x80 )
- { /* CSM mode total level latch and auto key on */
- int ch;
- if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
- for(ch=0;ch<9;ch++)
- CSMKeyControll( &OPL->P_CH[ch] );
- }
- }
- /* reload timer */
- if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
- return OPL->status>>7;
-}
diff --git a/hw/fmopl.h b/hw/fmopl.h
deleted file mode 100644
index a01ff90..0000000
--- a/hw/fmopl.h
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef __FMOPL_H_
-#define __FMOPL_H_
-
-/* --- select emulation chips --- */
-#define BUILD_YM3812 (HAS_YM3812)
-//#define BUILD_YM3526 (HAS_YM3526)
-//#define BUILD_Y8950 (HAS_Y8950)
-
-/* --- system optimize --- */
-/* select bit size of output : 8 or 16 */
-#define OPL_OUTPUT_BIT 16
-
-/* compiler dependence */
-#ifndef OSD_CPU_H
-#define OSD_CPU_H
-typedef unsigned char UINT8; /* unsigned 8bit */
-typedef unsigned short UINT16; /* unsigned 16bit */
-typedef unsigned int UINT32; /* unsigned 32bit */
-typedef signed char INT8; /* signed 8bit */
-typedef signed short INT16; /* signed 16bit */
-typedef signed int INT32; /* signed 32bit */
-#endif
-
-#if (OPL_OUTPUT_BIT==16)
-typedef INT16 OPLSAMPLE;
-#endif
-#if (OPL_OUTPUT_BIT==8)
-typedef unsigned char OPLSAMPLE;
-#endif
-
-
-#if BUILD_Y8950
-#include "ymdeltat.h"
-#endif
-
-typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
-typedef void (*OPL_IRQHANDLER)(int param,int irq);
-typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
-typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
-typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
-
-/* !!!!! here is private section , do not access there member direct !!!!! */
-
-#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
-#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
-#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
-#define OPL_TYPE_IO 0x08 /* I/O port */
-
-/* Saving is necessary for member of the 'R' mark for suspend/resume */
-/* ---------- OPL one of slot ---------- */
-typedef struct fm_opl_slot {
- INT32 TL; /* total level :TL << 8 */
- INT32 TLL; /* adjusted now TL */
- UINT8 KSR; /* key scale rate :(shift down bit) */
- INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */
- INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */
- INT32 SL; /* sustin level :SL_TALBE[SL] */
- INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */
- UINT8 ksl; /* keyscale level :(shift down bits) */
- UINT8 ksr; /* key scale rate :kcode>>KSR */
- UINT32 mul; /* multiple :ML_TABLE[ML] */
- UINT32 Cnt; /* frequency count : */
- UINT32 Incr; /* frequency step : */
- /* envelope generator state */
- UINT8 eg_typ; /* envelope type flag */
- UINT8 evm; /* envelope phase */
- INT32 evc; /* envelope counter */
- INT32 eve; /* envelope counter end point */
- INT32 evs; /* envelope counter step */
- INT32 evsa; /* envelope step for AR :AR[ksr] */
- INT32 evsd; /* envelope step for DR :DR[ksr] */
- INT32 evsr; /* envelope step for RR :RR[ksr] */
- /* LFO */
- UINT8 ams; /* ams flag */
- UINT8 vib; /* vibrate flag */
- /* wave selector */
- INT32 **wavetable;
-}OPL_SLOT;
-
-/* ---------- OPL one of channel ---------- */
-typedef struct fm_opl_channel {
- OPL_SLOT SLOT[2];
- UINT8 CON; /* connection type */
- UINT8 FB; /* feed back :(shift down bit) */
- INT32 *connect1; /* slot1 output pointer */
- INT32 *connect2; /* slot2 output pointer */
- INT32 op1_out[2]; /* slot1 output for selfeedback */
- /* phase generator state */
- UINT32 block_fnum; /* block+fnum : */
- UINT8 kcode; /* key code : KeyScaleCode */
- UINT32 fc; /* Freq. Increment base */
- UINT32 ksl_base; /* KeyScaleLevel Base step */
- UINT8 keyon; /* key on/off flag */
-} OPL_CH;
-
-/* OPL state */
-typedef struct fm_opl_f {
- UINT8 type; /* chip type */
- int clock; /* master clock (Hz) */
- int rate; /* sampling rate (Hz) */
- double freqbase; /* frequency base */
- double TimerBase; /* Timer base time (==sampling time) */
- UINT8 address; /* address register */
- UINT8 status; /* status flag */
- UINT8 statusmask; /* status mask */
- UINT32 mode; /* Reg.08 : CSM , notesel,etc. */
- /* Timer */
- int T[2]; /* timer counter */
- UINT8 st[2]; /* timer enable */
- /* FM channel slots */
- OPL_CH *P_CH; /* pointer of CH */
- int max_ch; /* maximum channel */
- /* Rythm sention */
- UINT8 rythm; /* Rythm mode , key flag */
-#if BUILD_Y8950
- /* Delta-T ADPCM unit (Y8950) */
- YM_DELTAT *deltat; /* DELTA-T ADPCM */
-#endif
- /* Keyboard / I/O interface unit (Y8950) */
- UINT8 portDirection;
- UINT8 portLatch;
- OPL_PORTHANDLER_R porthandler_r;
- OPL_PORTHANDLER_W porthandler_w;
- int port_param;
- OPL_PORTHANDLER_R keyboardhandler_r;
- OPL_PORTHANDLER_W keyboardhandler_w;
- int keyboard_param;
- /* time tables */
- INT32 AR_TABLE[75]; /* atttack rate tables */
- INT32 DR_TABLE[75]; /* decay rate tables */
- UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */
- /* LFO */
- INT32 *ams_table;
- INT32 *vib_table;
- INT32 amsCnt;
- INT32 amsIncr;
- INT32 vibCnt;
- INT32 vibIncr;
- /* wave selector enable flag */
- UINT8 wavesel;
- /* external event callback handler */
- OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
- int TimerParam; /* TIMER parameter */
- OPL_IRQHANDLER IRQHandler; /* IRQ handler */
- int IRQParam; /* IRQ parameter */
- OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
- int UpdateParam; /* stream update parameter */
-} FM_OPL;
-
-/* ---------- Generic interface section ---------- */
-#define OPL_TYPE_YM3526 (0)
-#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
-#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
-
-FM_OPL *OPLCreate(int type, int clock, int rate);
-void OPLDestroy(FM_OPL *OPL);
-void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
-void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
-void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
-/* Y8950 port handlers */
-void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
-void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
-
-void OPLResetChip(FM_OPL *OPL);
-int OPLWrite(FM_OPL *OPL,int a,int v);
-unsigned char OPLRead(FM_OPL *OPL,int a);
-int OPLTimerOver(FM_OPL *OPL,int c);
-
-/* YM3626/YM3812 local section */
-void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
-
-void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
-
-#endif
diff --git a/hw/goldfish_audio.c b/hw/goldfish_audio.c
new file mode 100644
index 0000000..69b2ef4
--- /dev/null
+++ b/hw/goldfish_audio.c
@@ -0,0 +1,521 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "goldfish_device.h"
+#include "audio/audio.h"
+#include "android_debug.h"
+
+#define DEBUG 1
+
+#if DEBUG
+# define D(...) VERBOSE_PRINT(audio,__VA_ARGS__)
+#else
+# define D(...) ((void)0)
+#endif
+
+extern void dprint(const char* fmt, ...);
+
+/* define USE_QEMU_AUDIO_IN to 1 to use QEMU's audio subsystem to
+ * implement the audio input. if 0, this will try to read a .wav file
+ * directly...
+ */
+#define USE_QEMU_AUDIO_IN 1
+
+enum {
+ /* audio status register */
+ AUDIO_INT_STATUS = 0x00,
+ /* set this to enable IRQ */
+ AUDIO_INT_ENABLE = 0x04,
+ /* set these to specify buffer addresses */
+ AUDIO_SET_WRITE_BUFFER_1 = 0x08,
+ AUDIO_SET_WRITE_BUFFER_2 = 0x0C,
+ /* set number of bytes in buffer to write */
+ AUDIO_WRITE_BUFFER_1 = 0x10,
+ AUDIO_WRITE_BUFFER_2 = 0x14,
+
+ /* true if audio input is supported */
+ AUDIO_READ_SUPPORTED = 0x18,
+ /* buffer to use for audio input */
+ AUDIO_SET_READ_BUFFER = 0x1C,
+
+ /* driver writes number of bytes to read */
+ AUDIO_START_READ = 0x20,
+
+ /* number of bytes available in read buffer */
+ AUDIO_READ_BUFFER_AVAILABLE = 0x24,
+
+ /* AUDIO_INT_STATUS bits */
+
+ /* this bit set when it is safe to write more bytes to the buffer */
+ AUDIO_INT_WRITE_BUFFER_1_EMPTY = 1U << 0,
+ AUDIO_INT_WRITE_BUFFER_2_EMPTY = 1U << 1,
+ AUDIO_INT_READ_BUFFER_FULL = 1U << 2,
+};
+
+
+struct goldfish_audio_state {
+ struct goldfish_device dev;
+ // pointers to our two write buffers
+ uint32_t buffer_1, buffer_2;
+ uint32_t read_buffer;
+ // buffer flags
+ uint32_t int_status;
+ // irq enable mask for int_status
+ uint32_t int_enable;
+
+#if USE_QEMU_AUDIO_IN
+ uint32_t read_pos;
+ uint32_t read_size;
+#else
+ // path to file or device to use for input
+ const char* input_source;
+ // true if input is a wav file
+ int input_is_wav;
+ // true if we need to convert stereo -> mono
+ int input_is_stereo;
+ // file descriptor to use for input
+ int input_fd;
+#endif
+
+ // number of bytes available in the read buffer
+ int read_buffer_available;
+
+ // set to 1 or 2 to indicate which buffer we are writing from, or zero if both buffers are empty
+ int current_buffer;
+
+ // current data to write
+ uint8* data_1;
+ uint32_t data_1_length;
+ uint8* data_2;
+ uint32_t data_2_length;
+
+
+ // for QEMU sound output
+ QEMUSoundCard card;
+ SWVoiceOut *voice;
+#if USE_QEMU_AUDIO_IN
+ SWVoiceIn* voicein;
+#endif
+};
+
+/* update this whenever you change the goldfish_audio_state structure */
+#define AUDIO_STATE_SAVE_VERSION 1
+
+#define QFIELD_STRUCT struct goldfish_audio_state
+QFIELD_BEGIN(audio_state_fields)
+ QFIELD_INT32(buffer_1),
+ QFIELD_INT32(buffer_2),
+ QFIELD_INT32(read_buffer),
+ QFIELD_INT32(int_status),
+ QFIELD_INT32(int_enable),
+#if USE_QEMU_AUDIO_IN
+ QFIELD_INT32(read_pos),
+ QFIELD_INT32(read_size),
+#endif
+ QFIELD_INT32(read_buffer_available),
+ QFIELD_INT32(current_buffer),
+ QFIELD_INT32(data_1_length),
+ QFIELD_INT32(data_2_length),
+QFIELD_END
+
+static void audio_state_save( QEMUFile* f, void* opaque )
+{
+ struct goldfish_audio_state* s = opaque;
+
+ qemu_put_struct(f, audio_state_fields, s);
+
+ /* we can't write data_1 and data_2 directly */
+ qemu_put_be32( f, s->data_1 - phys_ram_base );
+ qemu_put_be32( f, s->data_2 - phys_ram_base );
+}
+
+static int audio_state_load( QEMUFile* f, void* opaque, int version_id )
+{
+ struct goldfish_audio_state* s = opaque;
+ int ret;
+
+ if (version_id != AUDIO_STATE_SAVE_VERSION)
+ return -1;
+
+ ret = qemu_get_struct(f, audio_state_fields, s);
+ if (!ret) {
+ s->data_1 = qemu_get_be32(f) + phys_ram_base;
+ s->data_2 = qemu_get_be32(f) + phys_ram_base;
+ }
+ return -1;
+}
+
+static void enable_audio(struct goldfish_audio_state *s, int enable)
+{
+ // enable or disable the output voice
+ AUD_set_active_out(s->voice, (enable & (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY)) != 0);
+ AUD_set_active_in (s->voicein, (enable & AUDIO_INT_READ_BUFFER_FULL) != 0);
+ // reset buffer information
+ s->data_1_length = 0;
+ s->data_2_length = 0;
+ s->current_buffer = 0;
+ s->read_pos = 0;
+}
+
+#if USE_QEMU_AUDIO_IN
+static void start_read(struct goldfish_audio_state *s, uint32_t count)
+{
+ //printf( "... goldfish audio start_read, count=%d\n", count );
+ s->read_size = count;
+ s->read_buffer_available = 0;
+ s->read_pos = 0;
+}
+#else
+static void start_read(struct goldfish_audio_state *s, uint32_t count)
+{
+ uint8 wav_header[44];
+ int result;
+
+ if (!s->input_source) return;
+
+ if (s->input_fd < 0) {
+ s->input_fd = open(s->input_source, O_BINARY | O_RDONLY);
+
+ if (s->input_fd < 0) {
+ fprintf(stderr, "goldfish_audio could not open %s for audio input\n", s->input_source);
+ s->input_source = NULL; // set to to avoid endless retries
+ return;
+ }
+
+ // skip WAV header if we have a WAV file
+ if (s->input_is_wav) {
+ if (read(s->input_fd, wav_header, sizeof(wav_header)) != sizeof(wav_header)) {
+ fprintf(stderr, "goldfish_audio could not read WAV file header %s\n", s->input_source);
+ s->input_fd = -1;
+ s->input_source = NULL; // set to to avoid endless retries
+ return;
+ }
+
+ // is the WAV file stereo?
+ s->input_is_stereo = (wav_header[22] == 2);
+ } else {
+ // assume input from an audio device is stereo
+ s->input_is_stereo = 1;
+ }
+ }
+
+ uint8* buffer = (uint8*)phys_ram_base + s->read_buffer;
+ if (s->input_is_stereo) {
+ // need to read twice as much data
+ count *= 2;
+ }
+
+try_again:
+ result = read(s->input_fd, buffer, count);
+ if (result == 0 && s->input_is_wav) {
+ // end of file, so seek back to the beginning
+ lseek(s->input_fd, sizeof(wav_header), SEEK_SET);
+ goto try_again;
+ }
+
+ if (result > 0 && s->input_is_stereo) {
+ // we need to convert stereo to mono
+ uint8* src = (uint8*)buffer;
+ uint8* dest = src;
+ int count = result/2;
+ while (count-- > 0) {
+ int sample1 = src[0] | (src[1] << 8);
+ int sample2 = src[2] | (src[3] << 8);
+ int sample = (sample1 + sample2) >> 1;
+ dst[0] = (uint8_t) sample;
+ dst[1] = (uint8_t)(sample >> 8);
+ src += 4;
+ dst += 2;
+ }
+
+ // we reduced the number of bytes by 2
+ result /= 2;
+ }
+
+ s->read_buffer_available = (result > 0 ? result : 0);
+ s->int_status |= AUDIO_INT_READ_BUFFER_FULL;
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+}
+#endif
+
+static uint32_t goldfish_audio_read(void *opaque, target_phys_addr_t offset)
+{
+ uint32_t ret;
+ struct goldfish_audio_state *s = opaque;
+ offset -= s->dev.base;
+ switch(offset) {
+ case AUDIO_INT_STATUS:
+ // return current buffer status flags
+ ret = s->int_status & s->int_enable;
+ if(ret) {
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ }
+ return ret;
+
+ case AUDIO_READ_SUPPORTED:
+#if USE_QEMU_AUDIO_IN
+ D("%s: AUDIO_READ_SUPPORTED returns %d", __FUNCTION__,
+ (s->voicein != NULL));
+ return (s->voicein != NULL);
+#else
+ return (s->input_source ? 1 : 0);
+#endif
+
+ case AUDIO_READ_BUFFER_AVAILABLE:
+ D("%s: AUDIO_READ_BUFFER_AVAILABLE returns %d", __FUNCTION__,
+ s->read_buffer_available);
+ return s->read_buffer_available;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_audio_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_audio_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+{
+ struct goldfish_audio_state *s = opaque;
+ offset -= s->dev.base;
+
+ switch(offset) {
+ case AUDIO_INT_ENABLE:
+ /* enable buffer empty interrupts */
+ D("%s: AUDIO_INT_ENABLE %d", __FUNCTION__, val );
+ enable_audio(s, val);
+ s->int_enable = val;
+ s->int_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY);
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ break;
+ case AUDIO_SET_WRITE_BUFFER_1:
+ /* save pointer to buffer 1 */
+ s->buffer_1 = val;
+ break;
+ case AUDIO_SET_WRITE_BUFFER_2:
+ /* save pointer to buffer 2 */
+ s->buffer_2 = val;
+ break;
+ case AUDIO_WRITE_BUFFER_1:
+ /* record that data in buffer 1 is ready to write */
+ if (s->current_buffer == 0) s->current_buffer = 1;
+ s->data_1 = phys_ram_base + s->buffer_1;
+ s->data_1_length = val;
+ s->int_status &= ~AUDIO_INT_WRITE_BUFFER_1_EMPTY;
+ break;
+ case AUDIO_WRITE_BUFFER_2:
+ /* record that data in buffer 2 is ready to write */
+ if (s->current_buffer == 0) s->current_buffer = 2;
+ s->data_2 = phys_ram_base + s->buffer_2;
+ s->data_2_length = val;
+ s->int_status &= ~AUDIO_INT_WRITE_BUFFER_2_EMPTY;
+ break;
+
+ case AUDIO_SET_READ_BUFFER:
+ /* save pointer to the read buffer */
+ s->read_buffer = val;
+ D( "%s: AUDIO_SET_READ_BUFFER %p", __FUNCTION__, (void*)val );
+ break;
+
+ case AUDIO_START_READ:
+ D( "%s: AUDIO_START_READ %d", __FUNCTION__, val );
+ start_read(s, val);
+ s->int_status &= ~AUDIO_INT_READ_BUFFER_FULL;
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_audio_write: Bad offset %x\n", offset);
+ }
+}
+
+static void goldfish_audio_callback(void *opaque, int free)
+{
+ struct goldfish_audio_state *s = opaque;
+ int new_status = 0;
+
+ /* loop until free is zero or both buffers are empty */
+ while (free && s->current_buffer) {
+
+ /* write data in buffer 1 */
+ while (free && s->current_buffer == 1) {
+ int write = s->data_1_length;
+ if (write > free) write = free;
+
+ int written = AUD_write(s->voice, s->data_1, write);
+ if (written) {
+ D("%s: sent %d bytes to audio output", __FUNCTION__, write);
+ s->data_1 += written;
+ s->data_1_length -= written;
+ free -= written;
+
+ if (s->data_1_length == 0) {
+ new_status |= AUDIO_INT_WRITE_BUFFER_1_EMPTY;
+ s->current_buffer = (s->data_2_length ? 2 : 0);
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* write data in buffer 2 */
+ while (free && s->current_buffer == 2) {
+ int write = s->data_2_length;
+ if (write > free) write = free;
+
+ int written = AUD_write(s->voice, s->data_2, write);
+ if (written) {
+ D("%s: sent %d bytes to audio output", __FUNCTION__, write);
+ s->data_2 += written;
+ s->data_2_length -= written;
+ free -= written;
+
+ if (s->data_2_length == 0) {
+ new_status |= AUDIO_INT_WRITE_BUFFER_2_EMPTY;
+ s->current_buffer = (s->data_1_length ? 1 : 0);
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (new_status && new_status != s->int_status) {
+ s->int_status |= new_status;
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ }
+}
+
+#if USE_QEMU_AUDIO_IN
+static void
+goldfish_audio_in_callback(void *opaque, int avail)
+{
+ struct goldfish_audio_state *s = opaque;
+ int new_status = 0;
+
+ if (s->read_pos >= s->read_size)
+ return;
+
+ if (0 && s->read_size > 0)
+ D("%s: in %d (pos=%d size=%d)", __FUNCTION__,
+ avail, s->read_pos, s->read_size );
+
+ while (avail > 0) {
+ int pos = s->read_pos;
+ int missing = s->read_size - pos;
+ uint8* buffer = (uint8*)phys_ram_base + s->read_buffer + pos;
+ int read;
+ int avail2 = (avail > missing) ? missing : avail;
+
+ read = AUD_read(s->voicein, buffer, avail2);
+ if (read == 0)
+ break;
+
+ if (avail2 > 0)
+ D("%s: AUD_read(%d) returned %d", __FUNCTION__, avail2, read);
+
+ s->read_buffer_available += read;
+
+ avail -= read;
+ pos += read;
+ if (pos == s->read_size) {
+ new_status |= AUDIO_INT_READ_BUFFER_FULL;
+ D("%s: AUDIO_INT_READ_BUFFER_FULL available=%d", __FUNCTION__, s->read_buffer_available);
+ }
+ s->read_pos = pos;
+ }
+
+ if (new_status && new_status != s->int_status) {
+ s->int_status |= new_status;
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ }
+}
+#endif /* USE_QEMU_AUDIO_IN */
+
+static CPUReadMemoryFunc *goldfish_audio_readfn[] = {
+ goldfish_audio_read,
+ goldfish_audio_read,
+ goldfish_audio_read
+};
+
+static CPUWriteMemoryFunc *goldfish_audio_writefn[] = {
+ goldfish_audio_write,
+ goldfish_audio_write,
+ goldfish_audio_write
+};
+
+void goldfish_audio_init(uint32_t base, int id, const char* input_source)
+{
+ struct goldfish_audio_state *s;
+ audsettings_t as;
+
+ s = (struct goldfish_audio_state *)qemu_mallocz(sizeof(*s));
+ s->dev.name = "goldfish_audio";
+ s->dev.id = id;
+ s->dev.base = base;
+ s->dev.size = 0x1000;
+ s->dev.irq_count = 1;
+
+#ifndef USE_QEMU_AUDIO_IN
+ s->input_fd = -1;
+ if (input_source) {
+ s->input_source = input_source;
+ char* extension = strrchr(input_source, '.');
+ if (extension && strcasecmp(extension, ".wav") == 0) {
+ s->input_is_wav = 1;
+ }
+ }
+#endif
+
+ AUD_register_card( &glob_audio_state, "goldfish_audio", &s->card);
+
+ as.freq = 44100;
+ as.nchannels = 2;
+ as.fmt = AUD_FMT_S16;
+ as.endianness = AUDIO_HOST_ENDIANNESS;
+
+ s->voice = AUD_open_out (
+ &s->card,
+ s->voice,
+ "goldfish_audio",
+ s,
+ goldfish_audio_callback,
+ &as
+ );
+ if (!s->voice) {
+ dprint("warning: opening audio output failed\n");
+ return;
+ }
+
+#if USE_QEMU_AUDIO_IN
+ as.freq = 8000;
+ as.nchannels = 1;
+ as.fmt = AUD_FMT_S16;
+ as.endianness = AUDIO_HOST_ENDIANNESS;
+
+ s->voicein = AUD_open_in (
+ &s->card,
+ NULL,
+ "goldfish_audio_in",
+ s,
+ goldfish_audio_in_callback,
+ &as
+ );
+ if (!s->voicein) {
+ dprint("warning: opening audio input failed\n");
+ }
+#endif
+
+ goldfish_device_add(&s->dev, goldfish_audio_readfn, goldfish_audio_writefn, s);
+
+ register_savevm( "audio_state", 0, AUDIO_STATE_SAVE_VERSION,
+ audio_state_save, audio_state_load, s );
+}
+
diff --git a/hw/goldfish_battery.c b/hw/goldfish_battery.c
new file mode 100644
index 0000000..f8452db
--- /dev/null
+++ b/hw/goldfish_battery.c
@@ -0,0 +1,261 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "goldfish_device.h"
+#include "power_supply.h"
+
+
+enum {
+ /* status register */
+ BATTERY_INT_STATUS = 0x00,
+ /* set this to enable IRQ */
+ BATTERY_INT_ENABLE = 0x04,
+
+ BATTERY_AC_ONLINE = 0x08,
+ BATTERY_STATUS = 0x0C,
+ BATTERY_HEALTH = 0x10,
+ BATTERY_PRESENT = 0x14,
+ BATTERY_CAPACITY = 0x18,
+
+ BATTERY_STATUS_CHANGED = 1U << 0,
+ AC_STATUS_CHANGED = 1U << 1,
+ BATTERY_INT_MASK = BATTERY_STATUS_CHANGED | AC_STATUS_CHANGED,
+};
+
+
+struct goldfish_battery_state {
+ struct goldfish_device dev;
+ // IRQs
+ uint32_t int_status;
+ // irq enable mask for int_status
+ uint32_t int_enable;
+
+ int ac_online;
+ int status;
+ int health;
+ int present;
+ int capacity;
+};
+
+/* update this each time you update the battery_state struct */
+#define BATTERY_STATE_SAVE_VERSION 1
+
+#define QFIELD_STRUCT struct goldfish_battery_state
+QFIELD_BEGIN(goldfish_battery_fields)
+ QFIELD_INT32(int_status),
+ QFIELD_INT32(int_enable),
+ QFIELD_INT32(ac_online),
+ QFIELD_INT32(status),
+ QFIELD_INT32(health),
+ QFIELD_INT32(present),
+ QFIELD_INT32(capacity),
+QFIELD_END
+
+static void goldfish_battery_save(QEMUFile* f, void* opaque)
+{
+ struct goldfish_battery_state* s = opaque;
+
+ qemu_put_struct(f, goldfish_battery_fields, s);
+}
+
+static int goldfish_battery_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct goldfish_battery_state* s = opaque;
+
+ if (version_id != BATTERY_STATE_SAVE_VERSION)
+ return -1;
+
+ return qemu_get_struct(f, goldfish_battery_fields, s);
+}
+
+static struct goldfish_battery_state *battery_state;
+
+static uint32_t goldfish_battery_read(void *opaque, target_phys_addr_t offset)
+{
+ uint32_t ret;
+ struct goldfish_battery_state *s = opaque;
+ offset -= s->dev.base;
+ switch(offset) {
+ case BATTERY_INT_STATUS:
+ // return current buffer status flags
+ ret = s->int_status & s->int_enable;
+ if (ret) {
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ s->int_status = 0;
+ }
+ return ret;
+
+ case BATTERY_INT_ENABLE:
+ return s->int_enable;
+ case BATTERY_AC_ONLINE:
+ return s->ac_online;
+ case BATTERY_STATUS:
+ return s->status;
+ case BATTERY_HEALTH:
+ return s->health;
+ case BATTERY_PRESENT:
+ return s->present;
+ case BATTERY_CAPACITY:
+ return s->capacity;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_battery_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_battery_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+{
+ struct goldfish_battery_state *s = opaque;
+ offset -= s->dev.base;
+
+ switch(offset) {
+ case BATTERY_INT_ENABLE:
+ /* enable interrupts */
+ s->int_enable = val;
+// s->int_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY);
+// goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_audio_write: Bad offset %x\n", offset);
+ }
+}
+
+static CPUReadMemoryFunc *goldfish_battery_readfn[] = {
+ goldfish_battery_read,
+ goldfish_battery_read,
+ goldfish_battery_read
+};
+
+
+static CPUWriteMemoryFunc *goldfish_battery_writefn[] = {
+ goldfish_battery_write,
+ goldfish_battery_write,
+ goldfish_battery_write
+};
+
+void goldfish_battery_init()
+{
+ struct goldfish_battery_state *s;
+
+ s = (struct goldfish_battery_state *)qemu_mallocz(sizeof(*s));
+ s->dev.name = "goldfish-battery";
+ s->dev.base = 0; // will be allocated dynamically
+ s->dev.size = 0x1000;
+ s->dev.irq_count = 1;
+
+ // default values for the battery
+ s->ac_online = 1;
+ s->status = POWER_SUPPLY_STATUS_CHARGING;
+ s->health = POWER_SUPPLY_HEALTH_GOOD;
+ s->present = 1; // battery is present
+ s->capacity = 50; // 50% charged
+
+ battery_state = s;
+
+ goldfish_device_add(&s->dev, goldfish_battery_readfn, goldfish_battery_writefn, s);
+
+ register_savevm( "battery_state", 0, BATTERY_STATE_SAVE_VERSION,
+ goldfish_battery_save, goldfish_battery_load, s);
+}
+
+void goldfish_battery_set_prop(int ac, int property, int value)
+{
+ int new_status = (ac ? AC_STATUS_CHANGED : BATTERY_STATUS_CHANGED);
+
+ if (ac) {
+ switch (property) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ battery_state->ac_online = value;
+ break;
+ }
+ } else {
+ switch (property) {
+ case POWER_SUPPLY_PROP_STATUS:
+ battery_state->status = value;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ battery_state->health = value;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ battery_state->present = value;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ battery_state->capacity = value;
+ break;
+ }
+ }
+
+ if (new_status != battery_state->int_status) {
+ battery_state->int_status |= new_status;
+ goldfish_device_set_irq(&battery_state->dev, 0, (battery_state->int_status & battery_state->int_enable));
+ }
+}
+
+void goldfish_battery_display(void (* callback)(void *data, const char* string), void *data)
+{
+ char buffer[100];
+ char* value;
+
+ sprintf(buffer, "AC: %s\r\n", (battery_state->ac_online ? "online" : "offline"));
+ callback(data, buffer);
+
+ switch (battery_state->status) {
+ case POWER_SUPPLY_STATUS_CHARGING:
+ value = "Charging";
+ break;
+ case POWER_SUPPLY_STATUS_DISCHARGING:
+ value = "Discharging";
+ break;
+ case POWER_SUPPLY_STATUS_NOT_CHARGING:
+ value = "Not charging";
+ break;
+ case POWER_SUPPLY_STATUS_FULL:
+ value = "Full";
+ break;
+ default:
+ value = "Unknown";
+ break;
+ }
+ sprintf(buffer, "status: %s\r\n", value);
+ callback(data, buffer);
+
+ switch (battery_state->health) {
+ case POWER_SUPPLY_HEALTH_GOOD:
+ value = "Good";
+ break;
+ case POWER_SUPPLY_HEALTH_OVERHEAT:
+ value = "Overhead";
+ break;
+ case POWER_SUPPLY_HEALTH_DEAD:
+ value = "Dead";
+ break;
+ case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
+ value = "Overvoltage";
+ break;
+ case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
+ value = "Unspecified failure";
+ break;
+ default:
+ value = "Unknown";
+ break;
+ }
+ sprintf(buffer, "health: %s\r\n", value);
+ callback(data, buffer);
+
+ sprintf(buffer, "present: %s\r\n", (battery_state->present ? "true" : "false"));
+ callback(data, buffer);
+
+ sprintf(buffer, "capacity: %d\r\n", battery_state->capacity);
+ callback(data, buffer);
+}
diff --git a/hw/goldfish_device.c b/hw/goldfish_device.c
new file mode 100644
index 0000000..a7d80a6
--- /dev/null
+++ b/hw/goldfish_device.c
@@ -0,0 +1,200 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "arm_pic.h"
+#include "goldfish_device.h"
+
+#define PDEV_BUS_OP_DONE (0x00)
+#define PDEV_BUS_OP_REMOVE_DEV (0x04)
+#define PDEV_BUS_OP_ADD_DEV (0x08)
+
+#define PDEV_BUS_OP_INIT (0x00)
+
+#define PDEV_BUS_OP (0x00)
+#define PDEV_BUS_GET_NAME (0x04)
+#define PDEV_BUS_NAME_LEN (0x08)
+#define PDEV_BUS_ID (0x0c)
+#define PDEV_BUS_IO_BASE (0x10)
+#define PDEV_BUS_IO_SIZE (0x14)
+#define PDEV_BUS_IRQ (0x18)
+#define PDEV_BUS_IRQ_COUNT (0x1c)
+
+struct bus_state {
+ struct goldfish_device dev;
+ struct goldfish_device *current;
+};
+
+qemu_irq *goldfish_pic;
+static struct goldfish_device *first_device;
+static struct goldfish_device *last_device;
+uint32_t goldfish_free_base;
+uint32_t goldfish_free_irq;
+
+void goldfish_device_set_irq(struct goldfish_device *dev, int irq, int level)
+{
+ if(irq >= dev->irq_count)
+ cpu_abort (cpu_single_env, "goldfish_device_set_irq: Bad irq %d >= %d\n", irq, dev->irq_count);
+ else
+ qemu_set_irq(goldfish_pic[dev->irq + irq], level);
+}
+
+int goldfish_add_device_no_io(struct goldfish_device *dev)
+{
+ if(dev->base == 0) {
+ dev->base = goldfish_free_base;
+ goldfish_free_base += dev->size;
+ }
+ if(dev->irq == 0 && dev->irq_count > 0) {
+ dev->irq = goldfish_free_irq;
+ goldfish_free_irq += dev->irq_count;
+ }
+ //printf("goldfish_add_device: %s, base %x %x, irq %d %d\n",
+ // dev->name, dev->base, dev->size, dev->irq, dev->irq_count);
+ dev->next = NULL;
+ if(last_device) {
+ last_device->next = dev;
+ }
+ else {
+ first_device = dev;
+ }
+ last_device = dev;
+ return 0;
+}
+
+int goldfish_device_add(struct goldfish_device *dev,
+ CPUReadMemoryFunc **mem_read,
+ CPUWriteMemoryFunc **mem_write,
+ void *opaque)
+{
+ int iomemtype;
+ goldfish_add_device_no_io(dev);
+ iomemtype = cpu_register_io_memory(0, mem_read,
+ mem_write, opaque);
+ cpu_register_physical_memory(dev->base, dev->size, iomemtype);
+ return 0;
+}
+
+static uint32_t goldfish_bus_read(void *opaque, target_phys_addr_t offset)
+{
+ struct bus_state *s = (struct bus_state *)opaque;
+ offset -= s->dev.base;
+
+ switch (offset) {
+ case PDEV_BUS_OP:
+ if(s->current) {
+ s->current->reported_state = 1;
+ s->current = s->current->next;
+ }
+ else {
+ s->current = first_device;
+ }
+ while(s->current && s->current->reported_state == 1)
+ s->current = s->current->next;
+ if(s->current)
+ return PDEV_BUS_OP_ADD_DEV;
+ else {
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ return PDEV_BUS_OP_DONE;
+ }
+
+ case PDEV_BUS_NAME_LEN:
+ return s->current ? strlen(s->current->name) : 0;
+ case PDEV_BUS_ID:
+ return s->current ? s->current->id : 0;
+ case PDEV_BUS_IO_BASE:
+ return s->current ? s->current->base : 0;
+ case PDEV_BUS_IO_SIZE:
+ return s->current ? s->current->size : 0;
+ case PDEV_BUS_IRQ:
+ return s->current ? s->current->irq : 0;
+ case PDEV_BUS_IRQ_COUNT:
+ return s->current ? s->current->irq_count : 0;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_bus_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_bus_op_init(struct bus_state *s)
+{
+ struct goldfish_device *dev = first_device;
+ while(dev) {
+ dev->reported_state = 0;
+ dev = dev->next;
+ }
+ s->current = NULL;
+ goldfish_device_set_irq(&s->dev, 0, first_device != NULL);
+}
+
+static void goldfish_bus_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ struct bus_state *s = (struct bus_state *)opaque;
+ offset -= s->dev.base;
+
+ switch(offset) {
+ case PDEV_BUS_OP:
+ switch(value) {
+ case PDEV_BUS_OP_INIT:
+ goldfish_bus_op_init(s);
+ break;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_bus_write: Bad PDEV_BUS_OP value %x\n", value);
+ };
+ break;
+ case PDEV_BUS_GET_NAME:
+ if(s->current)
+ pmemcpy(value, s->current->name, strlen(s->current->name));
+ break;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_bus_write: Bad offset %x\n", offset);
+ }
+}
+
+static CPUReadMemoryFunc *goldfish_bus_readfn[] = {
+ goldfish_bus_read,
+ goldfish_bus_read,
+ goldfish_bus_read
+};
+
+static CPUWriteMemoryFunc *goldfish_bus_writefn[] = {
+ goldfish_bus_write,
+ goldfish_bus_write,
+ goldfish_bus_write
+};
+
+
+static struct bus_state bus_state = {
+ .dev = {
+ .name = "goldfish_device_bus",
+ .id = -1,
+ .base = 0x10001000,
+ .size = 0x1000,
+ .irq = 1,
+ .irq_count = 1,
+ }
+};
+
+void goldfish_device_init(qemu_irq *pic, uint32_t base, uint32_t size, uint32_t irq, uint32_t irq_count)
+{
+ goldfish_pic = pic;
+ goldfish_free_base = base;
+ goldfish_free_irq = irq;
+}
+
+int goldfish_device_bus_init(uint32_t base, uint32_t irq)
+{
+ bus_state.dev.base = base;
+ bus_state.dev.irq = irq;
+
+ return goldfish_device_add(&bus_state.dev, goldfish_bus_readfn, goldfish_bus_writefn, &bus_state);
+}
+
diff --git a/hw/goldfish_device.h b/hw/goldfish_device.h
new file mode 100644
index 0000000..abe102e
--- /dev/null
+++ b/hw/goldfish_device.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#ifndef GOLDFISH_DEVICE_H
+#define GOLDFISH_DEVICE_H
+
+struct goldfish_device {
+ struct goldfish_device *next;
+ struct goldfish_device *prev;
+ uint32_t reported_state;
+ void *cookie;
+ const char *name;
+ uint32_t id;
+ uint32_t base; // filled in by goldfish_device_add if 0
+ uint32_t size;
+ uint32_t irq; // filled in by goldfish_device_add if 0
+ uint32_t irq_count;
+};
+
+
+void goldfish_device_set_irq(struct goldfish_device *dev, int irq, int level);
+int goldfish_device_add(struct goldfish_device *dev,
+ CPUReadMemoryFunc **mem_read,
+ CPUWriteMemoryFunc **mem_write,
+ void *opaque);
+
+int goldfish_add_device_no_io(struct goldfish_device *dev);
+
+void goldfish_device_init(qemu_irq *pic, uint32_t base, uint32_t size, uint32_t irq, uint32_t irq_count);
+int goldfish_device_bus_init(uint32_t base, uint32_t irq);
+
+// device init functions:
+qemu_irq *goldfish_interrupt_init(uint32_t base, qemu_irq parent_irq, qemu_irq parent_fiq);
+void goldfish_timer_and_rtc_init(uint32_t timerbase, int timerirq);
+int goldfish_tty_add(CharDriverState *cs, int id, uint32_t base, int irq);
+void goldfish_fb_init(DisplayState *ds, int id);
+void goldfish_audio_init(uint32_t base, int id, const char* input_source);
+void goldfish_battery_init();
+void goldfish_battery_set_prop(int ac, int property, int value);
+void goldfish_battery_display(void (* callback)(void *data, const char* string), void *data);
+void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs);
+void *goldfish_switch_add(char *name, uint32_t (*writefn)(void *opaque, uint32_t state), void *writeopaque, int id);
+void goldfish_switch_set_state(void *opaque, uint32_t state);
+
+// these do not add a device
+void trace_dev_init(uint32_t base);
+void events_dev_init(uint32_t base, qemu_irq irq);
+void nand_dev_init(uint32_t base);
+
+#endif
diff --git a/hw/goldfish_events_device.c b/hw/goldfish_events_device.c
new file mode 100644
index 0000000..66ac2fc
--- /dev/null
+++ b/hw/goldfish_events_device.c
@@ -0,0 +1,423 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "android_events.h"
+#include "irq.h"
+
+#if 0
+// From kernel...
+#define EV_SYN 0x00
+#define EV_KEY 0x01
+#define EV_REL 0x02
+#define EV_ABS 0x03
+#define EV_MSC 0x04
+#define EV_SW 0x05
+#define EV_LED 0x11
+#define EV_SND 0x12
+#define EV_REP 0x14
+#define EV_FF 0x15
+#define EV_PWR 0x16
+#define EV_FF_STATUS 0x17
+#define EV_MAX 0x1f
+
+#define BTN_MISC 0x100
+#define BTN_0 0x100
+#define BTN_1 0x101
+#define BTN_2 0x102
+#define BTN_3 0x103
+#define BTN_4 0x104
+#define BTN_5 0x105
+#define BTN_6 0x106
+#define BTN_7 0x107
+#define BTN_8 0x108
+#define BTN_9 0x109
+
+#define BTN_MOUSE 0x110
+#define BTN_LEFT 0x110
+#define BTN_RIGHT 0x111
+#define BTN_MIDDLE 0x112
+#define BTN_SIDE 0x113
+#define BTN_EXTRA 0x114
+#define BTN_FORWARD 0x115
+#define BTN_BACK 0x116
+#define BTN_TASK 0x117
+
+#define BTN_JOYSTICK 0x120
+#define BTN_TRIGGER 0x120
+#define BTN_THUMB 0x121
+#define BTN_THUMB2 0x122
+#define BTN_TOP 0x123
+#define BTN_TOP2 0x124
+#define BTN_PINKIE 0x125
+#define BTN_BASE 0x126
+#define BTN_BASE2 0x127
+#define BTN_BASE3 0x128
+#define BTN_BASE4 0x129
+#define BTN_BASE5 0x12a
+#define BTN_BASE6 0x12b
+#define BTN_DEAD 0x12f
+
+#define BTN_GAMEPAD 0x130
+#define BTN_A 0x130
+#define BTN_B 0x131
+#define BTN_C 0x132
+#define BTN_X 0x133
+#define BTN_Y 0x134
+#define BTN_Z 0x135
+#define BTN_TL 0x136
+#define BTN_TR 0x137
+#define BTN_TL2 0x138
+#define BTN_TR2 0x139
+#define BTN_SELECT 0x13a
+#define BTN_START 0x13b
+#define BTN_MODE 0x13c
+#define BTN_THUMBL 0x13d
+#define BTN_THUMBR 0x13e
+
+#define BTN_DIGI 0x140
+#define BTN_TOOL_PEN 0x140
+#define BTN_TOOL_RUBBER 0x141
+#define BTN_TOOL_BRUSH 0x142
+#define BTN_TOOL_PENCIL 0x143
+#define BTN_TOOL_AIRBRUSH 0x144
+#define BTN_TOOL_FINGER 0x145
+#define BTN_TOOL_MOUSE 0x146
+#define BTN_TOOL_LENS 0x147
+#define BTN_TOUCH 0x14a
+#define BTN_STYLUS 0x14b
+#define BTN_STYLUS2 0x14c
+#define BTN_TOOL_DOUBLETAP 0x14d
+#define BTN_TOOL_TRIPLETAP 0x14e
+
+#define BTN_WHEEL 0x150
+#define BTN_GEAR_DOWN 0x150
+#define BTN_GEAR_UP 0x151
+
+#define REL_X 0x00
+#define REL_Y 0x01
+
+#define ABS_X 0x00
+#define ABS_Y 0x01
+#define ABS_Z 0x02
+#define ABS_RX 0x03
+#define ABS_RY 0x04
+#define ABS_RZ 0x05
+#define ABS_THROTTLE 0x06
+#define ABS_RUDDER 0x07
+#define ABS_WHEEL 0x08
+#define ABS_GAS 0x09
+#define ABS_BRAKE 0x0a
+#define ABS_HAT0X 0x10
+#define ABS_HAT0Y 0x11
+#define ABS_HAT1X 0x12
+#define ABS_HAT1Y 0x13
+#define ABS_HAT2X 0x14
+#define ABS_HAT2Y 0x15
+#define ABS_HAT3X 0x16
+#define ABS_HAT3Y 0x17
+#define ABS_PRESSURE 0x18
+#define ABS_DISTANCE 0x19
+#define ABS_TILT_X 0x1a
+#define ABS_TILT_Y 0x1b
+#define ABS_TOOL_WIDTH 0x1c
+#define ABS_VOLUME 0x20
+#define ABS_MISC 0x28
+#define ABS_MAX 0x3f
+#endif
+
+#define MAX_EVENTS 256*4
+
+enum {
+ REG_READ = 0x00,
+ REG_SET_PAGE = 0x00,
+ REG_LEN = 0x04,
+ REG_DATA = 0x08,
+
+ PAGE_NAME = 0x00000,
+ PAGE_EVBITS = 0x10000,
+ PAGE_ABSDATA = 0x20000 | EV_ABS,
+};
+
+typedef struct
+{
+ uint32_t base;
+ qemu_irq irq;
+ int pending;
+ int page;
+
+ unsigned events[MAX_EVENTS];
+ unsigned first;
+ unsigned last;
+
+ const char *name;
+ struct {
+ size_t len;
+ uint8_t *bits;
+ } ev_bits[EV_MAX + 1];
+ int32_t *abs_info;
+ size_t abs_info_count;
+} events_state;
+
+/* modify this each time you change the events_device structure. you
+ * will also need to upadte events_state_load and events_state_save
+ */
+#define EVENTS_STATE_SAVE_VERSION 1
+
+#undef QFIELD_STRUCT
+#define QFIELD_STRUCT events_state
+
+QFIELD_BEGIN(events_state_fields)
+ QFIELD_INT32(pending),
+ QFIELD_INT32(page),
+ QFIELD_BUFFER(events),
+ QFIELD_INT32(first),
+ QFIELD_INT32(last),
+QFIELD_END
+
+static void events_state_save(QEMUFile* f, void* opaque)
+{
+ events_state* s = opaque;
+
+ qemu_put_struct(f, events_state_fields, s);
+}
+
+static int events_state_load(QEMUFile* f, void* opaque, int version_id)
+{
+ events_state* s = opaque;
+
+ if (version_id != EVENTS_STATE_SAVE_VERSION)
+ return -1;
+
+ return qemu_get_struct(f, events_state_fields, s);
+}
+
+extern const char* android_skin_keycharmap;
+
+static void enqueue_event(events_state *s, unsigned int type, unsigned int code, int value)
+{
+ int enqueued = s->last - s->first;
+
+ if (enqueued < 0)
+ enqueued += MAX_EVENTS;
+
+ if (enqueued + 3 >= MAX_EVENTS-1) {
+ fprintf(stderr, "##KBD: Full queue, lose event\n");
+ return;
+ }
+
+ if(s->first == s->last){
+ qemu_irq_raise(s->irq);
+ }
+
+ //fprintf(stderr, "##KBD: type=%d code=%d value=%d\n", type, code, value);
+
+ s->events[s->last] = type;
+ s->last = (s->last + 1) & (MAX_EVENTS-1);
+ s->events[s->last] = code;
+ s->last = (s->last + 1) & (MAX_EVENTS-1);
+ s->events[s->last] = value;
+ s->last = (s->last + 1) & (MAX_EVENTS-1);
+}
+
+static unsigned dequeue_event(events_state *s)
+{
+ unsigned n;
+
+ if(s->first == s->last) {
+ return 0;
+ }
+
+ n = s->events[s->first];
+
+ s->first = (s->first + 1) & (MAX_EVENTS - 1);
+
+ if(s->first == s->last) {
+ qemu_irq_lower(s->irq);
+ }
+
+ return n;
+}
+
+static int get_page_len(events_state *s)
+{
+ int page = s->page;
+ if (page == PAGE_NAME)
+ return strlen(s->name);
+ if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX)
+ return s->ev_bits[page - PAGE_EVBITS].len;
+ if (page == PAGE_ABSDATA)
+ return s->abs_info_count * sizeof(s->abs_info[0]);
+ return 0;
+}
+
+static int get_page_data(events_state *s, int offset)
+{
+ int page_len = get_page_len(s);
+ int page = s->page;
+ if (offset > page_len)
+ return 0;
+ if (page == PAGE_NAME)
+ return s->name[offset];
+ if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX)
+ return s->ev_bits[page - PAGE_EVBITS].bits[offset];
+ if (page == PAGE_ABSDATA)
+ return s->abs_info[offset / sizeof(s->abs_info[0])];
+ return 0;
+}
+
+static uint32_t events_read(void *x, target_phys_addr_t off)
+{
+ events_state *s = (events_state *) x;
+ int offset = off - s->base;
+ if (offset == REG_READ)
+ return dequeue_event(s);
+ else if (offset == REG_LEN)
+ return get_page_len(s);
+ else if (offset >= REG_DATA)
+ return get_page_data(s, offset - REG_DATA);
+ return 0; // this shouldn't happen, if the driver does the right thing
+}
+
+static void events_write(void *x, target_phys_addr_t off, uint32_t val)
+{
+ events_state *s = (events_state *) x;
+ int offset = off - s->base;
+ if (offset == REG_SET_PAGE)
+ s->page = val;
+}
+
+static CPUReadMemoryFunc *events_readfn[] = {
+ events_read,
+ events_read,
+ events_read
+};
+
+static CPUWriteMemoryFunc *events_writefn[] = {
+ events_write,
+ events_write,
+ events_write
+};
+
+static void events_put_keycode(void *x, int keycode)
+{
+ events_state *s = (events_state *) x;
+
+ enqueue_event(s, EV_KEY, keycode&0x1ff, (keycode&0x200) ? 1 : 0);
+}
+
+static void events_put_mouse(void *opaque, int dx, int dy, int dz, int buttons_state)
+{
+ events_state *s = (events_state *) opaque;
+ if (dz == 0) {
+ enqueue_event(s, EV_ABS, ABS_X, dx);
+ enqueue_event(s, EV_ABS, ABS_Y, dy);
+ enqueue_event(s, EV_ABS, ABS_Z, dz);
+ enqueue_event(s, EV_KEY, BTN_TOUCH, buttons_state&1);
+ } else {
+ enqueue_event(s, EV_REL, REL_X, dx);
+ enqueue_event(s, EV_REL, REL_Y, dy);
+ }
+ enqueue_event(s, EV_SYN, 0, 0);
+}
+
+static void events_put_generic(void* opaque, int type, int code, int value)
+{
+ events_state *s = (events_state *) opaque;
+
+ enqueue_event(s, type, code, value);
+}
+
+static int events_set_bits(events_state *s, int type, int bitl, int bith)
+{
+ uint8_t *bits;
+ uint8_t maskl, maskh;
+ int il, ih;
+ il = bitl / 8;
+ ih = bith / 8;
+ if (ih >= s->ev_bits[type].len) {
+ bits = qemu_mallocz(ih + 1);
+ if (bits == NULL)
+ return -ENOMEM;
+ memcpy(bits, s->ev_bits[type].bits, s->ev_bits[type].len);
+ qemu_free(s->ev_bits[type].bits);
+ s->ev_bits[type].bits = bits;
+ s->ev_bits[type].len = ih + 1;
+ }
+ else
+ bits = s->ev_bits[type].bits;
+ maskl = 0xffU << (bitl & 7);
+ maskh = 0xffU >> (7 - (bith & 7));
+ if (il >= ih)
+ maskh &= maskl;
+ else {
+ bits[il] |= maskl;
+ while (++il < ih)
+ bits[il] = 0xff;
+ }
+ bits[ih] |= maskh;
+ return 0;
+}
+
+#if 0
+static int events_set_abs_info(events_state *s, int axis, int32_t min, int32_t max, int32_t fuzz, int32_t flat)
+{
+ int32_t *info;
+ if (axis * 4 >= s->abs_info_count) {
+ info = qemu_mallocz((axis + 1) * 4 * sizeof(int32_t));
+ if (info == NULL)
+ return -ENOMEM;
+ memcpy(info, s->abs_info, s->abs_info_count);
+ qemu_free(s->abs_info);
+ s->abs_info = info;
+ s->abs_info_count = (axis + 1) * 4;
+ }
+ else
+ info = s->abs_info;
+ info += axis * 4;
+ *info++ = min;
+ *info++ = max;
+ *info++ = fuzz;
+ *info++ = flat;
+}
+#endif
+
+void events_dev_init(uint32_t base, qemu_irq irq)
+{
+ events_state *s;
+ int iomemtype;
+
+ s = (events_state *) qemu_mallocz(sizeof(events_state));
+ s->name = android_skin_keycharmap;
+ events_set_bits(s, EV_SYN, EV_SYN, EV_ABS);
+ events_set_bits(s, EV_SYN, EV_SW, EV_SW);
+ events_set_bits(s, EV_KEY, 1, 0x1ff);
+ events_set_bits(s, EV_REL, REL_X, REL_Y);
+ events_set_bits(s, EV_ABS, ABS_X, ABS_Z);
+ events_set_bits(s, EV_SW, 0, 0);
+ iomemtype = cpu_register_io_memory(0, events_readfn, events_writefn, s);
+
+ cpu_register_physical_memory(base, 0xfff, iomemtype);
+
+ qemu_add_kbd_event_handler(events_put_keycode, s);
+ qemu_add_mouse_event_handler(events_put_mouse, s, 1);
+ qemu_add_generic_event_handler(events_put_generic, s);
+
+ s->base = base;
+ s->irq = irq;
+
+ s->first = 0;
+ s->last = 0;
+
+ register_savevm( "events_state", 0, EVENTS_STATE_SAVE_VERSION,
+ events_state_save, events_state_load, s );
+}
+
diff --git a/hw/goldfish_fb.c b/hw/goldfish_fb.c
new file mode 100644
index 0000000..0924735
--- /dev/null
+++ b/hw/goldfish_fb.c
@@ -0,0 +1,405 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "android.h"
+#include "goldfish_device.h"
+#include "framebuffer.h"
+
+enum {
+ FB_GET_WIDTH = 0x00,
+ FB_GET_HEIGHT = 0x04,
+ FB_INT_STATUS = 0x08,
+ FB_INT_ENABLE = 0x0c,
+ FB_SET_BASE = 0x10,
+ FB_SET_ROTATION = 0x14,
+ FB_SET_BLANK = 0x18,
+ FB_GET_PHYS_WIDTH = 0x1c,
+ FB_GET_PHYS_HEIGHT = 0x20,
+
+ FB_INT_VSYNC = 1U << 0,
+ FB_INT_BASE_UPDATE_DONE = 1U << 1
+};
+
+struct goldfish_fb_state {
+ struct goldfish_device dev;
+ QFrameBuffer* qfbuff;
+ uint32_t fb_base;
+ uint32_t base_valid : 1;
+ uint32_t need_update : 1;
+ uint32_t need_int : 1;
+ uint32_t set_rotation : 2;
+ uint32_t blank : 1;
+ uint32_t int_status;
+ uint32_t int_enable;
+ int rotation; /* 0, 1, 2 or 3 */
+};
+
+#define GOLDFISH_FB_SAVE_VERSION 1
+
+static void goldfish_fb_save(QEMUFile* f, void* opaque)
+{
+ struct goldfish_fb_state* s = opaque;
+
+ QFrameBuffer* q = s->qfbuff;
+
+ qemu_put_be32(f, q->width);
+ qemu_put_be32(f, q->height);
+ qemu_put_be32(f, q->pitch);
+ qemu_put_byte(f, q->rotation);
+
+ qemu_put_be32(f, s->fb_base);
+ qemu_put_byte(f, s->base_valid);
+ qemu_put_byte(f, s->need_update);
+ qemu_put_byte(f, s->need_int);
+ qemu_put_byte(f, s->set_rotation);
+ qemu_put_byte(f, s->blank);
+ qemu_put_be32(f, s->int_status);
+ qemu_put_be32(f, s->int_enable);
+ qemu_put_be32(f, s->rotation);
+}
+
+static int goldfish_fb_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct goldfish_fb_state* s = opaque;
+
+ QFrameBuffer* q = s->qfbuff;
+ int ret = -1;
+ int ds_w, ds_h, ds_pitch, ds_rot;
+
+ if (version_id != GOLDFISH_FB_SAVE_VERSION)
+ goto Exit;
+
+ ds_w = qemu_get_be32(f);
+ ds_h = qemu_get_be32(f);
+ ds_pitch = qemu_get_be32(f);
+ ds_rot = qemu_get_byte(f);
+
+ if (q->width != ds_w ||
+ q->height != ds_h ||
+ q->pitch != ds_pitch ||
+ q->rotation != ds_rot )
+ {
+ /* XXX: We should be able to force a resize/rotation from here ? */
+ fprintf(stderr, "%s: framebuffer dimensions mismatch\n", __FUNCTION__);
+ goto Exit;
+ }
+
+ s->fb_base = qemu_get_be32(f);
+ s->base_valid = qemu_get_byte(f);
+ s->need_update = qemu_get_byte(f);
+ s->need_int = qemu_get_byte(f);
+ s->set_rotation = qemu_get_byte(f);
+ s->blank = qemu_get_byte(f);
+ s->int_status = qemu_get_be32(f);
+ s->int_enable = qemu_get_be32(f);
+ s->rotation = qemu_get_be32(f);
+
+ /* force a refresh */
+ s->need_update = 1;
+
+ ret = 0;
+Exit:
+ return ret;
+}
+
+
+#define STATS 0
+
+#if STATS
+static int stats_counter;
+static long stats_total;
+static int stats_full_updates;
+static long stats_total_full_updates;
+#endif
+
+static void goldfish_fb_update_display(void *opaque)
+{
+ struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque;
+ uint32_t addr;
+ uint32_t base;
+
+ uint8_t* dst_line;
+ uint8_t* src_line;
+ int y_first, y_last = 0;
+ int full_update = 0;
+ int width, height, pitch;
+
+ base = s->fb_base;
+ if(base == 0)
+ return;
+
+ if((s->int_enable & FB_INT_VSYNC) && !(s->int_status & FB_INT_VSYNC)) {
+ s->int_status |= FB_INT_VSYNC;
+ goldfish_device_set_irq(&s->dev, 0, 1);
+ }
+
+ y_first = -1;
+ addr = base;
+ if(s->need_update) {
+ full_update = 1;
+ if(s->need_int) {
+ s->int_status |= FB_INT_BASE_UPDATE_DONE;
+ if(s->int_enable & FB_INT_BASE_UPDATE_DONE)
+ goldfish_device_set_irq(&s->dev, 0, 1);
+ }
+ s->need_int = 0;
+ s->need_update = 0;
+ }
+
+ src_line = phys_ram_base + base;
+ dst_line = s->qfbuff->pixels;
+ pitch = s->qfbuff->pitch;
+ width = s->qfbuff->width;
+ height = s->qfbuff->height;
+
+#if STATS
+ if (full_update)
+ stats_full_updates += 1;
+ if (++stats_counter == 120) {
+ stats_total += stats_counter;
+ stats_total_full_updates += stats_full_updates;
+
+ printf( "full update stats: peak %.2f %% total %.2f %%\n",
+ stats_full_updates*100.0/stats_counter,
+ stats_total_full_updates*100.0/stats_total );
+
+ stats_counter = 0;
+ stats_full_updates = 0;
+ }
+#endif /* STATS */
+
+ if (s->blank)
+ {
+ memset( dst_line, 0, height*pitch );
+ y_first = 0;
+ y_last = height-1;
+ }
+ else if (full_update)
+ {
+ int yy;
+
+ for (yy = 0; yy < height; yy++, dst_line += pitch, src_line += width*2)
+ {
+ uint16_t* src = (uint16_t*) src_line;
+ uint16_t* dst = (uint16_t*) dst_line;
+ int nn;
+
+ for (nn = 0; nn < width; nn++) {
+ unsigned spix = src[nn];
+ unsigned dpix = dst[nn];
+#if WORDS_BIGENDIAN
+ spix = ((spix << 8) | (spix >> 8)) & 0xffff;
+#else
+ if (spix != dpix)
+ break;
+#endif
+ }
+
+ if (nn == width)
+ continue;
+
+#if WORDS_BIGENDIAN
+ for ( ; nn < width; nn++ ) {
+ unsigned spix = src[nn];
+ dst[nn] = (uint16_t)((spix << 8) | (spix >> 8));
+ }
+#else
+ memcpy( dst+nn, src+nn, (width-nn)*2 );
+#endif
+
+ y_first = (y_first < 0) ? yy : y_first;
+ y_last = yy;
+ }
+ }
+ else /* not a full update, should not happen very often with Android */
+ {
+ int yy;
+
+ for (yy = 0; yy < height; yy++, dst_line += pitch, src_line += width*2)
+ {
+ uint16_t* src = (uint16_t*) src_line;
+ uint16_t* dst = (uint16_t*) dst_line;
+ int len = width*2;
+#if WORDS_BIGENDIAN
+ int nn;
+#endif
+ int dirty = 0;
+
+ while (len > 0) {
+ int len2 = TARGET_PAGE_SIZE - (addr & (TARGET_PAGE_SIZE-1));
+
+ if (len2 > len)
+ len2 = len;
+
+ dirty |= cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG);
+ addr += len2;
+ len -= len2;
+ }
+
+ if (!dirty)
+ continue;
+
+#if WORDS_BIGENDIAN
+ for (nn = 0; nn < width; nn++ ) {
+ unsigned spix = src[nn];
+ dst[nn] = (uint16_t)((spix << 8) | (spix >> 8));
+ }
+#else
+ memcpy( dst, src, width*2 );
+#endif
+
+ y_first = (y_first < 0) ? yy : y_first;
+ y_last = yy;
+ }
+ }
+
+ if (y_first < 0)
+ return;
+
+ y_last += 1;
+ //printf("goldfish_fb_update_display %d %d, base %x\n", first, last, base);
+
+ cpu_physical_memory_reset_dirty(base + y_first * width * 2,
+ base + y_last * width * 2,
+ VGA_DIRTY_FLAG);
+
+ qframebuffer_update( s->qfbuff, 0, y_first, width, y_last-y_first );
+}
+
+static void goldfish_fb_invalidate_display(void * opaque)
+{
+ // is this called?
+ struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque;
+ s->need_update = 1;
+}
+
+static void goldfish_fb_detach_display(void* opaque)
+{
+ struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque;
+ s->qfbuff = NULL;
+}
+
+static uint32_t goldfish_fb_read(void *opaque, target_phys_addr_t offset)
+{
+ uint32_t ret;
+ struct goldfish_fb_state *s = opaque;
+ offset -= s->dev.base;
+ switch(offset) {
+ case FB_GET_WIDTH:
+ ret = s->qfbuff->width;
+ //printf("FB_GET_WIDTH => %d\n", ret);
+ return ret;
+
+ case FB_GET_HEIGHT:
+ ret = s->qfbuff->height;
+ //printf( "FB_GET_HEIGHT = %d\n", ret);
+ return ret;
+
+ case FB_INT_STATUS:
+ ret = s->int_status & s->int_enable;
+ if(ret) {
+ s->int_status &= ~ret;
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ }
+ return ret;
+
+ case FB_GET_PHYS_WIDTH:
+ ret = s->qfbuff->phys_width_mm;
+ //printf( "FB_GET_PHYS_WIDTH => %d\n", ret );
+ return ret;
+
+ case FB_GET_PHYS_HEIGHT:
+ ret = s->qfbuff->phys_height_mm;
+ //printf( "FB_GET_PHYS_HEIGHT => %d\n", ret );
+ return ret;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_fb_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_fb_write(void *opaque, target_phys_addr_t offset,
+ uint32_t val)
+{
+ struct goldfish_fb_state *s = opaque;
+ offset -= s->dev.base;
+ switch(offset) {
+ case FB_INT_ENABLE:
+ s->int_enable = val;
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ break;
+ case FB_SET_BASE: {
+ int need_resize = !s->base_valid;
+ s->fb_base = val;
+ s->int_status &= ~FB_INT_BASE_UPDATE_DONE;
+ s->need_update = 1;
+ s->need_int = 1;
+ s->base_valid = 1;
+ if(s->set_rotation != s->rotation) {
+ //printf("FB_SET_BASE: rotation : %d => %d\n", s->rotation, s->set_rotation);
+ s->rotation = s->set_rotation;
+ need_resize = 1;
+ }
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ if (need_resize) {
+ //printf("FB_SET_BASE: need resize (rotation=%d)\n", s->rotation );
+ qframebuffer_rotate( s->qfbuff, s->rotation );
+ }
+ } break;
+ case FB_SET_ROTATION:
+ //printf( "FB_SET_ROTATION %d\n", val);
+ s->set_rotation = val;
+ break;
+ case FB_SET_BLANK:
+ s->blank = val;
+ s->need_update = 1;
+ break;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_fb_write: Bad offset %x\n", offset);
+ }
+}
+
+static CPUReadMemoryFunc *goldfish_fb_readfn[] = {
+ goldfish_fb_read,
+ goldfish_fb_read,
+ goldfish_fb_read
+};
+
+static CPUWriteMemoryFunc *goldfish_fb_writefn[] = {
+ goldfish_fb_write,
+ goldfish_fb_write,
+ goldfish_fb_write
+};
+
+void goldfish_fb_init(DisplayState *ds, int id)
+{
+ struct goldfish_fb_state *s;
+
+ s = (struct goldfish_fb_state *)qemu_mallocz(sizeof(*s));
+ s->dev.name = "goldfish_fb";
+ s->dev.id = id;
+ s->dev.size = 0x1000;
+ s->dev.irq_count = 1;
+
+ s->qfbuff = qframebuffer_fifo_get();
+ qframebuffer_add_producer( s->qfbuff, s,
+ goldfish_fb_update_display,
+ goldfish_fb_invalidate_display,
+ goldfish_fb_detach_display );
+
+ goldfish_device_add(&s->dev, goldfish_fb_readfn, goldfish_fb_writefn, s);
+
+ register_savevm( "goldfish_fb", 0, GOLDFISH_FB_SAVE_VERSION,
+ goldfish_fb_save, goldfish_fb_load, s);
+}
+
diff --git a/hw/goldfish_interrupt.c b/hw/goldfish_interrupt.c
new file mode 100644
index 0000000..c89130d
--- /dev/null
+++ b/hw/goldfish_interrupt.c
@@ -0,0 +1,190 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "arm_pic.h"
+#include "goldfish_device.h"
+#include "irq.h"
+
+enum {
+ INTERRUPT_STATUS = 0x00, // number of pending interrupts
+ INTERRUPT_NUMBER = 0x04,
+ INTERRUPT_DISABLE_ALL = 0x08,
+ INTERRUPT_DISABLE = 0x0c,
+ INTERRUPT_ENABLE = 0x10
+};
+
+struct goldfish_int_state {
+ struct goldfish_device dev;
+ uint32_t level;
+ uint32_t pending_count;
+ uint32_t irq_enabled;
+ uint32_t fiq_enabled;
+ qemu_irq parent_irq;
+ qemu_irq parent_fiq;
+};
+
+#define GOLDFISH_INT_SAVE_VERSION 1
+
+#define QFIELD_STRUCT struct goldfish_int_state
+QFIELD_BEGIN(goldfish_int_fields)
+ QFIELD_INT32(level),
+ QFIELD_INT32(pending_count),
+ QFIELD_INT32(irq_enabled),
+ QFIELD_INT32(fiq_enabled),
+QFIELD_END
+
+static void goldfish_int_save(QEMUFile* f, void* opaque)
+{
+ struct goldfish_int_state* s = opaque;
+
+ qemu_put_struct(f, goldfish_int_fields, s);
+}
+
+static int goldfish_int_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct goldfish_int_state* s = opaque;
+
+ if (version_id != GOLDFISH_INT_SAVE_VERSION)
+ return -1;
+
+ return qemu_get_struct(f, goldfish_int_fields, s);
+}
+
+static void goldfish_int_update(struct goldfish_int_state *s)
+{
+ uint32_t flags;
+
+ flags = (s->level & s->irq_enabled);
+ qemu_set_irq(s->parent_irq, flags != 0);
+
+ flags = (s->level & s->fiq_enabled);
+ qemu_set_irq(s->parent_fiq, flags != 0);
+}
+
+static void goldfish_int_set_irq(void *opaque, int irq, int level)
+{
+ struct goldfish_int_state *s = (struct goldfish_int_state *)opaque;
+ uint32_t mask = (1U << irq);
+
+ if(level) {
+ if(!(s->level & mask)) {
+ if(s->irq_enabled & mask)
+ s->pending_count++;
+ s->level |= mask;
+ }
+ }
+ else {
+ if(s->level & mask) {
+ if(s->irq_enabled & mask)
+ s->pending_count--;
+ s->level &= ~mask;
+ }
+ }
+ goldfish_int_update(s);
+}
+
+static uint32_t goldfish_int_read(void *opaque, target_phys_addr_t offset)
+{
+ struct goldfish_int_state *s = (struct goldfish_int_state *)opaque;
+ offset -= s->dev.base;
+
+ switch (offset) {
+ case INTERRUPT_STATUS: /* IRQ_STATUS */
+ return s->pending_count;
+ case INTERRUPT_NUMBER: {
+ int i;
+ uint32_t pending = s->level & s->irq_enabled;
+ for(i = 0; i < 32; i++) {
+ if(pending & (1U << i))
+ return i;
+ }
+ return 0;
+ }
+ default:
+ cpu_abort (cpu_single_env, "goldfish_int_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_int_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ struct goldfish_int_state *s = (struct goldfish_int_state *)opaque;
+ uint32_t mask = (1U << value);
+ offset -= s->dev.base;
+
+ switch (offset) {
+ case INTERRUPT_DISABLE_ALL:
+ s->pending_count = 0;
+ s->level = 0;
+ break;
+
+ case INTERRUPT_DISABLE:
+ if(s->irq_enabled & mask) {
+ if(s->level & mask)
+ s->pending_count--;
+ s->irq_enabled &= ~mask;
+ }
+ break;
+ case INTERRUPT_ENABLE:
+ if(!(s->irq_enabled & mask)) {
+ s->irq_enabled |= mask;
+ if(s->level & mask)
+ s->pending_count++;
+ }
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_int_write: Bad offset %x\n", offset);
+ return;
+ }
+ goldfish_int_update(s);
+}
+
+static CPUReadMemoryFunc *goldfish_int_readfn[] = {
+ goldfish_int_read,
+ goldfish_int_read,
+ goldfish_int_read
+};
+
+static CPUWriteMemoryFunc *goldfish_int_writefn[] = {
+ goldfish_int_write,
+ goldfish_int_write,
+ goldfish_int_write
+};
+
+qemu_irq* goldfish_interrupt_init(uint32_t base, qemu_irq parent_irq, qemu_irq parent_fiq)
+{
+ int ret;
+ struct goldfish_int_state *s;
+ qemu_irq* qi;
+
+ s = qemu_mallocz(sizeof(*s));
+ qi = qemu_allocate_irqs(goldfish_int_set_irq, s, 32);
+ s->dev.name = "goldfish_interrupt_controller";
+ s->dev.id = -1;
+ s->dev.base = base;
+ s->dev.size = 0x1000;
+ s->parent_irq = parent_irq;
+ s->parent_fiq = parent_fiq;
+
+ ret = goldfish_device_add(&s->dev, goldfish_int_readfn, goldfish_int_writefn, s);
+ if(ret) {
+ qemu_free(s);
+ return NULL;
+ }
+
+ register_savevm( "goldfish_int", 0, GOLDFISH_INT_SAVE_VERSION,
+ goldfish_int_save, goldfish_int_load, s);
+
+ return qi;
+}
+
diff --git a/hw/goldfish_memlog.c b/hw/goldfish_memlog.c
new file mode 100644
index 0000000..e2a89a6
--- /dev/null
+++ b/hw/goldfish_memlog.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "vl.h"
+#include "goldfish_device.h"
+#include "audio/audio.h"
+
+extern void dprint(const char* fmt, ...);
+
+int fd = -1;
+
+static uint32_t memlog_read(void *opaque, target_phys_addr_t offset)
+{
+ struct goldfish_device *dev = opaque;
+ offset -= dev->base;
+
+ return 0;
+}
+
+unsigned info[8];
+
+static void memlog_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+{
+ char buf[128];
+ struct goldfish_device *dev = opaque;
+ offset -= dev->base;
+
+ info[offset / 4] = val;
+
+ if (offset == 0) {
+ /* write PID and VADDR to logfile */
+ sprintf(buf,"%08x %08x\n", info[0], info[1]);
+ write(fd, buf, strlen(buf));
+ }
+}
+
+
+static CPUReadMemoryFunc *memlog_readfn[] = {
+ memlog_read,
+ memlog_read,
+ memlog_read
+};
+
+static CPUWriteMemoryFunc *memlog_writefn[] = {
+ memlog_write,
+ memlog_write,
+ memlog_write
+};
+
+struct goldfish_device memlog_dev;
+
+void goldfish_memlog_init(uint32_t base)
+{
+ struct goldfish_device *dev = &memlog_dev;
+
+ dev->name = "goldfish_memlog";
+ dev->id = 0;
+ dev->base = base;
+ dev->size = 0x1000;
+ dev->irq_count = 0;
+
+ fd = open("mem.log", /* O_CREAT | */ O_TRUNC | O_WRONLY, 0644);
+
+ goldfish_device_add(dev, memlog_readfn, memlog_writefn, dev);
+}
+
diff --git a/hw/goldfish_mmc.c b/hw/goldfish_mmc.c
new file mode 100644
index 0000000..a00340c
--- /dev/null
+++ b/hw/goldfish_mmc.c
@@ -0,0 +1,465 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "goldfish_device.h"
+#include "mmc.h"
+#include "sd.h"
+
+enum {
+ /* status register */
+ MMC_INT_STATUS = 0x00,
+ /* set this to enable IRQ */
+ MMC_INT_ENABLE = 0x04,
+ /* set this to specify buffer address */
+ MMC_SET_BUFFER = 0x08,
+
+ /* MMC command number */
+ MMC_CMD = 0x0C,
+
+ /* MMC argument */
+ MMC_ARG = 0x10,
+
+ /* MMC response (or R2 bits 0 - 31) */
+ MMC_RESP_0 = 0x14,
+
+ /* MMC R2 response bits 32 - 63 */
+ MMC_RESP_1 = 0x18,
+
+ /* MMC R2 response bits 64 - 95 */
+ MMC_RESP_2 = 0x1C,
+
+ /* MMC R2 response bits 96 - 127 */
+ MMC_RESP_3 = 0x20,
+
+ MMC_BLOCK_LENGTH = 0x24,
+ MMC_BLOCK_COUNT = 0x28,
+
+ /* MMC state flags */
+ MMC_STATE = 0x2C,
+
+ /* MMC_INT_STATUS bits */
+
+ MMC_STAT_END_OF_CMD = 1U << 0,
+ MMC_STAT_END_OF_DATA = 1U << 1,
+ MMC_STAT_STATE_CHANGE = 1U << 2,
+
+ /* MMC_STATE bits */
+ MMC_STATE_INSERTED = 1U << 0,
+ MMC_STATE_READ_ONLY = 1U << 1,
+};
+
+
+struct goldfish_mmc_state {
+ struct goldfish_device dev;
+ BlockDriverState *bs;
+ // pointer to our buffer
+ uint8_t* buffer;
+ // offsets for read and write operations
+ uint32_t read_offset, write_offset;
+ // buffer status flags
+ uint32_t int_status;
+ // irq enable mask for int_status
+ uint32_t int_enable;
+
+ // MMC command argument
+ uint32_t arg;
+ uint32_t resp[4];
+
+ uint32_t block_length;
+ uint32_t block_count;
+ int is_SDHC;
+};
+
+#define GOLDFISH_MMC_SAVE_VERSION 1
+#define QFIELD_STRUCT struct goldfish_mmc_state
+QFIELD_BEGIN(goldfish_mmc_fields)
+ QFIELD_INT32(read_offset),
+ QFIELD_INT32(write_offset),
+ QFIELD_INT32(int_status),
+ QFIELD_INT32(int_enable),
+ QFIELD_INT32(arg),
+ QFIELD_INT32(resp[0]),
+ QFIELD_INT32(resp[1]),
+ QFIELD_INT32(resp[2]),
+ QFIELD_INT32(resp[3]),
+ QFIELD_INT32(block_length),
+ QFIELD_INT32(block_count),
+ QFIELD_INT32(is_SDHC),
+QFIELD_END
+
+static void goldfish_mmc_save(QEMUFile* f, void* opaque)
+{
+ struct goldfish_mmc_state* s = opaque;
+
+ qemu_put_be32(f, s->buffer - phys_ram_base);
+ qemu_put_struct(f, goldfish_mmc_fields, s);
+}
+
+static int goldfish_mmc_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct goldfish_mmc_state* s = opaque;
+
+ if (version_id != GOLDFISH_MMC_SAVE_VERSION)
+ return -1;
+
+ s->buffer = qemu_get_be32(f) + phys_ram_base;
+ return qemu_get_struct(f, goldfish_mmc_fields, s);
+}
+
+struct mmc_opcode {
+ const char* name;
+ int cmd;
+} mmc_opcodes[] = {
+ { "MMC_GO_IDLE_STATE", 0 },
+ { "MMC_SEND_OP_COND", 1 },
+ { "MMC_ALL_SEND_CID", 2 },
+ { "MMC_SET_RELATIVE_ADDR", 3 },
+ { "MMC_SET_DSR", 4 },
+ { "MMC_SWITCH", 6 },
+ { "MMC_SELECT_CARD", 7 },
+ { "MMC_SEND_EXT_CSD", 8 },
+ { "MMC_SEND_CSD", 9 },
+ { "MMC_SEND_CID", 10 },
+ { "MMC_READ_DAT_UNTIL_STOP", 11 },
+ { "MMC_STOP_TRANSMISSION", 12 },
+ { "MMC_SEND_STATUS", 13 },
+ { "MMC_GO_INACTIVE_STATE", 15 },
+ { "MMC_SET_BLOCKLEN", 16 },
+ { "MMC_READ_SINGLE_BLOCK", 17 },
+ { "MMC_READ_MULTIPLE_BLOCK", 18 },
+ { "MMC_WRITE_DAT_UNTIL_STOP", 20 },
+ { "MMC_SET_BLOCK_COUNT", 23 },
+ { "MMC_WRITE_BLOCK", 24 },
+ { "MMC_WRITE_MULTIPLE_BLOCK", 25 },
+ { "MMC_PROGRAM_CID", 26 },
+ { "MMC_PROGRAM_CSD", 27 },
+ { "MMC_SET_WRITE_PROT", 28 },
+ { "MMC_CLR_WRITE_PROT", 29 },
+ { "MMC_SEND_WRITE_PROT", 30 },
+ { "MMC_ERASE_GROUP_START", 35 },
+ { "MMC_ERASE_GROUP_END", 36 },
+ { "MMC_ERASE", 38 },
+ { "MMC_FAST_IO", 39 },
+ { "MMC_GO_IRQ_STATE", 40 },
+ { "MMC_LOCK_UNLOCK", 42 },
+ { "MMC_APP_CMD", 55 },
+ { "MMC_GEN_CMD", 56 },
+ { "SD_APP_OP_COND", 41 },
+ { "SD_APP_SEND_SCR", 51 },
+ { "UNKNOWN" -1 }
+};
+
+static const char* get_command_name(int command)
+{
+ struct mmc_opcode* opcode = mmc_opcodes;
+
+ while (opcode->cmd != command && opcode->cmd != -1) opcode++;
+ return opcode->name;
+}
+
+static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd, uint32_t arg)
+{
+ int result;
+ int new_status = MMC_STAT_END_OF_CMD;
+ int opcode = cmd & 63;
+
+// fprintf(stderr, "goldfish_mmc_do_command opcode: %s (0x%04X), arg: %d\n", get_command_name(opcode), cmd, arg);
+
+ s->resp[0] = 0;
+ s->resp[1] = 0;
+ s->resp[2] = 0;
+ s->resp[3] = 0;
+
+#define SET_R1_CURRENT_STATE(s) ((s << 9) & 0x00001E00) /* sx, b (4 bits) */
+
+ switch (opcode) {
+ case MMC_SEND_CSD: {
+ int64_t sector_count = 0;
+ uint64_t capacity;
+ uint8_t exponent;
+ uint32_t m;
+
+ bdrv_get_geometry(s->bs, &sector_count);
+ capacity = sector_count * 512;
+ if (capacity > 2147483648U) {
+ // if storages is > 2 gig, then emulate SDHC card
+ s->is_SDHC = 1;
+
+ // CSD bits borrowed from a real SDHC card, with capacity bits zeroed out
+ s->resp[3] = 0x400E0032;
+ s->resp[2] = 0x5B590000;
+ s->resp[1] = 0x00007F80;
+ s->resp[0] = 0x0A4040DF;
+
+ // stuff in the real capacity
+ // m = UNSTUFF_BITS(resp, 48, 22);
+ m = (uint32_t)(capacity / (512*1024)) - 1;
+ // m must fit into 22 bits
+ if (m & 0xFFC00000) {
+ fprintf(stderr, "SD card too big (%lld bytes). Maximum SDHC card size is 128 gigabytes.\n", capacity);
+ abort();
+ }
+
+ // low 16 bits go in high end of resp[1]
+ s->resp[1] |= ((m & 0x0000FFFF) << 16);
+ // high 6 bits go in low end of resp[2]
+ s->resp[2] |= (m >> 16);
+ } else {
+ // emulate standard SD card
+ s->is_SDHC = 0;
+
+ // CSD bits borrowed from a real SD card, with capacity bits zeroed out
+ s->resp[3] = 0x00260032;
+ s->resp[2] = 0x5F5A8000;
+ s->resp[1] = 0x3EF84FFF;
+ s->resp[0] = 0x928040CB;
+
+ // stuff in the real capacity
+ // e = UNSTUFF_BITS(resp, 47, 3);
+ // m = UNSTUFF_BITS(resp, 62, 12);
+ // csd->capacity = (1 + m) << (e + 2);
+ // need to reverse the formula and calculate e and m
+ exponent = 0;
+ capacity = sector_count * 512;
+ if (capacity > 2147483648U) {
+ fprintf(stderr, "SD card too big (%lld bytes). Maximum SD card size is 2 gigabytes.\n", capacity);
+ abort();
+ }
+ capacity >>= 10; // convert to Kbytes
+ while (capacity > 4096) {
+ // (capacity - 1) must fit into 12 bits
+ exponent++;
+ capacity >>= 1;
+ }
+ capacity -= 1;
+ exponent -= 2;
+ if (exponent > 7)
+ cpu_abort(cpu_single_env, "exponent %d too big\n", exponent);
+
+ s->resp[2] |= (((uint32_t)capacity >> 2) & 0x3FF); // high 10 bits to bottom of resp[2]
+ s->resp[1] |= (((uint32_t)capacity & 3) << 30); // low 2 bits to top of resp[1]
+ s->resp[1] |= (exponent << (47 - 32));
+ }
+ break;
+ }
+
+ case MMC_SEND_EXT_CSD:
+ s->resp[0] = arg;
+ break;
+
+ case MMC_APP_CMD:
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336
+ break;
+
+ case SD_APP_OP_COND:
+ s->resp[0] = 0x80FF8000;
+ break;
+
+ case SD_APP_SEND_SCR:
+ {
+ uint32_t* scr = (uint32_t*)s->buffer;
+ scr[0] = 0x00002502;
+ scr[1] = 0x00000000;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336
+ new_status |= MMC_STAT_END_OF_DATA;
+ break;
+ }
+ case MMC_SET_RELATIVE_ADDR:
+ s->resp[0] = -518519520;
+ break;
+
+ case MMC_ALL_SEND_CID:
+ s->resp[3] = 55788627;
+ s->resp[2] = 1429221959;
+ s->resp[1] = -2147479692;
+ s->resp[0] = -436179883;
+ break;
+
+ case MMC_SELECT_CARD:
+ s->resp[0] = SET_R1_CURRENT_STATE(3) | R1_READY_FOR_DATA; // 1792
+ break;
+
+ case MMC_SWITCH:
+ if (arg == 0x00FFFFF1 || arg == 0x80FFFFF1) {
+ uint8_t* switchbuf = s->buffer;
+ memset(switchbuf, 0, 64);
+ switchbuf[13] = 2;
+ new_status |= MMC_STAT_END_OF_DATA;
+ }
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336
+ break;
+
+ case MMC_SET_BLOCKLEN:
+ s->block_length = arg;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+
+ case MMC_READ_SINGLE_BLOCK:
+ s->block_count = 1;
+ // fall through
+ case MMC_READ_MULTIPLE_BLOCK: {
+ if (s->is_SDHC) {
+ // arg is block offset
+ } else {
+ // arg is byte offset
+ if (arg & 511) fprintf(stderr, "offset %d is not multiple of 512 when reading\n", arg);
+ arg /= s->block_length;
+ }
+ result = bdrv_read(s->bs, arg, s->buffer, s->block_count);
+ new_status |= MMC_STAT_END_OF_DATA;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+ }
+
+ case MMC_WRITE_BLOCK:
+ s->block_count = 1;
+ // fall through
+ case MMC_WRITE_MULTIPLE_BLOCK: {
+ if (s->is_SDHC) {
+ // arg is block offset
+ } else {
+ // arg is byte offset
+ if (arg & 511) fprintf(stderr, "offset %d is not multiple of 512 when writing\n", arg);
+ arg /= s->block_length;
+ }
+ // arg is byte offset
+ result = bdrv_write(s->bs, arg, s->buffer, s->block_count);
+// bdrv_flush(s->bs);
+ new_status |= MMC_STAT_END_OF_DATA;
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+ }
+
+ case MMC_STOP_TRANSMISSION:
+ s->resp[0] = SET_R1_CURRENT_STATE(5) | R1_READY_FOR_DATA; // 2816
+ break;
+
+ case MMC_SEND_STATUS:
+ s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304
+ break;
+ }
+
+ s->int_status |= new_status;
+
+ if ((s->int_status & s->int_enable)) {
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ }
+}
+
+static uint32_t goldfish_mmc_read(void *opaque, target_phys_addr_t offset)
+{
+ uint32_t ret;
+ struct goldfish_mmc_state *s = opaque;
+
+ offset -= s->dev.base;
+ switch(offset) {
+ case MMC_INT_STATUS:
+ // return current buffer status flags
+ return s->int_status & s->int_enable;
+ case MMC_RESP_0:
+ return s->resp[0];
+ case MMC_RESP_1:
+ return s->resp[1];
+ case MMC_RESP_2:
+ return s->resp[2];
+ case MMC_RESP_3:
+ return s->resp[3];
+ case MMC_STATE: {
+ ret = MMC_STATE_INSERTED;
+ if (bdrv_is_read_only(s->bs)) {
+ ret |= MMC_STATE_READ_ONLY;
+ }
+ return ret;
+ }
+ default:
+ cpu_abort(cpu_single_env, "goldfish_mmc_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_mmc_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+{
+ struct goldfish_mmc_state *s = opaque;
+ int status, old_status;
+
+ offset -= s->dev.base;
+
+ switch(offset) {
+
+ case MMC_INT_STATUS:
+ status = s->int_status;
+ old_status = status;
+ status &= ~val;
+ s->int_status = status;
+ if(status != old_status) {
+ goldfish_device_set_irq(&s->dev, 0, status);
+ }
+ break;
+
+ case MMC_INT_ENABLE:
+ /* enable buffer interrupts */
+ s->int_enable = val;
+ s->int_status = 0;
+ goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ break;
+ case MMC_SET_BUFFER:
+ /* save pointer to buffer 1 */
+ s->buffer = phys_ram_base + val;
+ break;
+ case MMC_CMD:
+ goldfish_mmc_do_command(s, val, s->arg);
+ break;
+ case MMC_ARG:
+ s->arg = val;
+ break;
+ case MMC_BLOCK_LENGTH:
+ s->block_length = val + 1;
+ break;
+ case MMC_BLOCK_COUNT:
+ s->block_count = val + 1;
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_mmc_write: Bad offset %x\n", offset);
+ }
+}
+
+static CPUReadMemoryFunc *goldfish_mmc_readfn[] = {
+ goldfish_mmc_read,
+ goldfish_mmc_read,
+ goldfish_mmc_read
+};
+
+static CPUWriteMemoryFunc *goldfish_mmc_writefn[] = {
+ goldfish_mmc_write,
+ goldfish_mmc_write,
+ goldfish_mmc_write
+};
+
+void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs)
+{
+ struct goldfish_mmc_state *s;
+
+ s = (struct goldfish_mmc_state *)qemu_mallocz(sizeof(*s));
+ s->dev.name = "goldfish_mmc";
+ s->dev.id = id;
+ s->dev.base = base;
+ s->dev.size = 0x1000;
+ s->dev.irq_count = 1;
+ s->bs = bs;
+
+ goldfish_device_add(&s->dev, goldfish_mmc_readfn, goldfish_mmc_writefn, s);
+
+ register_savevm( "goldfish_mmc", 0, GOLDFISH_MMC_SAVE_VERSION,
+ goldfish_mmc_save, goldfish_mmc_load, s);
+}
+
diff --git a/hw/goldfish_nand.c b/hw/goldfish_nand.c
new file mode 100644
index 0000000..e3042bf
--- /dev/null
+++ b/hw/goldfish_nand.c
@@ -0,0 +1,639 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "goldfish_nand_reg.h"
+#include "goldfish_nand.h"
+#include "android_utils.h"
+#include "android_debug.h"
+#include "android.h"
+
+#define DEBUG 1
+#if DEBUG
+# define D(...) VERBOSE_PRINT(nand,__VA_ARGS__)
+# define D_ACTIVE VERBOSE_CHECK(nand)
+# define T(...) VERBOSE_PRINT(nand_limits,__VA_ARGS__)
+# define T_ACTIVE VERBOSE_CHECK(nand_limits)
+#else
+# define D(...) ((void)0)
+# define D_ACTIVE 0
+# define T(...) ((void)0)
+# define T_ACTIVE 0
+#endif
+
+/* lseek uses 64-bit offsets on Darwin. */
+/* prefer lseek64 on Linux */
+#ifdef __APPLE__
+# define llseek lseek
+#elif defined(__linux__)
+# define llseek lseek64
+#endif
+
+#define XLOG xlog
+
+static void
+xlog( const char* format, ... )
+{
+ va_list args;
+ va_start(args, format);
+ fprintf(stderr, "NAND: ");
+ vfprintf(stderr, format, args);
+ va_end(args);
+}
+
+typedef struct {
+ char* devname;
+ size_t devname_len;
+ char* data;
+ int fd;
+ uint32_t flags;
+ uint32_t page_size;
+ uint32_t extra_size;
+ uint32_t erase_size;
+ uint64_t size;
+} nand_dev;
+
+nand_threshold android_nand_write_threshold;
+nand_threshold android_nand_read_threshold;
+
+#ifdef CONFIG_NAND_THRESHOLD
+
+/* update a threshold, return 1 if limit is hit, 0 otherwise */
+static void
+nand_threshold_update( nand_threshold* t, uint32_t len )
+{
+ if (t->counter < t->limit) {
+ uint64_t avail = t->limit - t->counter;
+ if (avail > len)
+ avail = len;
+
+ if (t->counter == 0) {
+ T("%s: starting threshold counting to %lld",
+ __FUNCTION__, t->limit);
+ }
+ t->counter += avail;
+ if (t->counter >= t->limit) {
+ /* threshold reach, send a signal to an external process */
+ T( "%s: sending signal %d to pid %d !",
+ __FUNCTION__, t->signal, t->pid );
+
+ kill( t->pid, t->signal );
+ }
+ }
+ return;
+}
+
+#define NAND_UPDATE_READ_THRESHOLD(len) \
+ nand_threshold_update( &android_nand_read_threshold, (uint32_t)(len) )
+
+#define NAND_UPDATE_WRITE_THRESHOLD(len) \
+ nand_threshold_update( &android_nand_write_threshold, (uint32_t)(len) )
+
+#else /* !NAND_THRESHOLD */
+
+#define NAND_UPDATE_READ_THRESHOLD(len) \
+ do {} while (0)
+
+#define NAND_UPDATE_WRITE_THRESHOLD(len) \
+ do {} while (0)
+
+#endif /* !NAND_THRESHOLD */
+
+static nand_dev *nand_devs = NULL;
+static uint32_t nand_dev_count = 0;
+
+typedef struct {
+ uint32_t base;
+
+ // register state
+ uint32_t dev;
+ uint32_t addr_low;
+ uint32_t addr_high;
+ uint32_t transfer_size;
+ uint32_t data;
+ uint32_t result;
+} nand_dev_state;
+
+/* update this everytime you change the nand_dev_state structure */
+#define NAND_DEV_STATE_SAVE_VERSION 1
+
+#define QFIELD_STRUCT nand_dev_state
+QFIELD_BEGIN(nand_dev_state_fields)
+ QFIELD_INT32(dev),
+ QFIELD_INT32(addr_low),
+ QFIELD_INT32(addr_high),
+ QFIELD_INT32(transfer_size),
+ QFIELD_INT32(data),
+ QFIELD_INT32(result),
+QFIELD_END
+
+static void nand_dev_state_save(QEMUFile* f, void* opaque)
+{
+ nand_dev_state* s = opaque;
+
+ qemu_put_struct(f, nand_dev_state_fields, s);
+}
+
+static int nand_dev_state_load(QEMUFile* f, void* opaque, int version_id)
+{
+ nand_dev_state* s = opaque;
+
+ if (version_id != NAND_DEV_STATE_SAVE_VERSION)
+ return -1;
+
+ return qemu_get_struct(f, nand_dev_state_fields, s);
+}
+
+
+extern void vmemcpy(target_ulong ptr, char *buf, int size); /* copy memory from the simulated virtual space to a buffer in QEMU */
+extern void pmemcpy(target_ulong ptr, char *buf, int size); /* copy memory from the QEMU buffer to simulated virtual space */
+
+static int do_read(int fd, void* buf, size_t size)
+{
+ int ret;
+ do {
+ ret = read(fd, buf, size);
+ } while (ret < 0 && errno == EINTR);
+
+ return ret;
+}
+
+static int do_write(int fd, const void* buf, size_t size)
+{
+ int ret;
+ do {
+ ret = write(fd, buf, size);
+ } while (ret < 0 && errno == EINTR);
+
+ return ret;
+}
+
+static uint32_t nand_dev_read_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len)
+{
+ uint32_t len = total_len;
+ size_t read_len = dev->erase_size;
+ int eof = 0;
+
+ NAND_UPDATE_READ_THRESHOLD(total_len);
+
+ lseek(dev->fd, addr, SEEK_SET);
+ while(len > 0) {
+ if(read_len < dev->erase_size) {
+ memset(dev->data, 0xff, dev->erase_size);
+ read_len = dev->erase_size;
+ eof = 1;
+ }
+ if(len < read_len)
+ read_len = len;
+ if(!eof) {
+ read_len = do_read(dev->fd, dev->data, read_len);
+ }
+ pmemcpy(data, dev->data, read_len);
+ data += read_len;
+ len -= read_len;
+ }
+ return total_len;
+}
+
+static uint32_t nand_dev_write_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len)
+{
+ uint32_t len = total_len;
+ size_t write_len = dev->erase_size;
+ int ret;
+
+ NAND_UPDATE_WRITE_THRESHOLD(total_len);
+
+ lseek(dev->fd, addr, SEEK_SET);
+ while(len > 0) {
+ if(len < write_len)
+ write_len = len;
+ vmemcpy(data, dev->data, write_len);
+ ret = do_write(dev->fd, dev->data, write_len);
+ if(ret < write_len) {
+ XLOG("nand_dev_write_file, write failed: %s\n", strerror(errno));
+ break;
+ }
+ data += write_len;
+ len -= write_len;
+ }
+ return total_len - len;
+}
+
+static uint32_t nand_dev_erase_file(nand_dev *dev, uint64_t addr, uint32_t total_len)
+{
+ uint32_t len = total_len;
+ size_t write_len = dev->erase_size;
+ int ret;
+
+ lseek(dev->fd, addr, SEEK_SET);
+ memset(dev->data, 0xff, dev->erase_size);
+ while(len > 0) {
+ if(len < write_len)
+ write_len = len;
+ ret = do_write(dev->fd, dev->data, write_len);
+ if(ret < write_len) {
+ XLOG( "nand_dev_write_file, write failed: %s\n", strerror(errno));
+ break;
+ }
+ len -= write_len;
+ }
+ return total_len - len;
+}
+
+/* this is a huge hack required to make the PowerPC emulator binary usable
+ * on Mac OS X. If you define this function as 'static', the emulated kernel
+ * will panic when attempting to mount the /data partition.
+ *
+ * worse, if you do *not* define the function as static on Linux-x86, the
+ * emulated kernel will also panic !?
+ *
+ * I still wonder if this is a compiler bug, or due to some nasty thing the
+ * emulator does with CPU registers during execution of the translated code.
+ */
+#if !(defined __APPLE__ && defined __powerpc__)
+static
+#endif
+uint32_t nand_dev_do_cmd(nand_dev_state *s, uint32_t cmd)
+{
+ uint32_t size;
+ uint64_t addr;
+ nand_dev *dev;
+
+ addr = s->addr_low | ((uint64_t)s->addr_high << 32);
+ size = s->transfer_size;
+ if(s->dev >= nand_dev_count)
+ return 0;
+ dev = nand_devs + s->dev;
+
+ switch(cmd) {
+ case NAND_CMD_GET_DEV_NAME:
+ if(size > dev->devname_len)
+ size = dev->devname_len;
+ pmemcpy(s->data, dev->devname, size);
+ return size;
+ case NAND_CMD_READ:
+ if(addr >= dev->size)
+ return 0;
+ if(size + addr > dev->size)
+ size = dev->size - addr;
+ if(dev->fd >= 0)
+ return nand_dev_read_file(dev, s->data, addr, size);
+ pmemcpy(s->data, &dev->data[addr], size);
+ return size;
+ case NAND_CMD_WRITE:
+ if(dev->flags & NAND_DEV_FLAG_READ_ONLY)
+ return 0;
+ if(addr >= dev->size)
+ return 0;
+ if(size + addr > dev->size)
+ size = dev->size - addr;
+ if(dev->fd >= 0)
+ return nand_dev_write_file(dev, s->data, addr, size);
+ vmemcpy(s->data, &dev->data[addr], size);
+ return size;
+ case NAND_CMD_ERASE:
+ if(dev->flags & NAND_DEV_FLAG_READ_ONLY)
+ return 0;
+ if(addr >= dev->size)
+ return 0;
+ if(size + addr > dev->size)
+ size = dev->size - addr;
+ if(dev->fd >= 0)
+ return nand_dev_erase_file(dev, addr, size);
+ memset(&dev->data[addr], 0xff, size);
+ return size;
+ case NAND_CMD_BLOCK_BAD_GET: // no bad block support
+ return 0;
+ case NAND_CMD_BLOCK_BAD_SET:
+ if(dev->flags & NAND_DEV_FLAG_READ_ONLY)
+ return 0;
+ return 0;
+ default:
+ cpu_abort(cpu_single_env, "nand_dev_do_cmd: Bad command %x\n", cmd);
+ return 0;
+ }
+}
+
+/* I/O write */
+static void nand_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ nand_dev_state *s = (nand_dev_state *)opaque;
+
+ offset -= s->base;
+ switch (offset) {
+ case NAND_DEV:
+ s->dev = value;
+ if(s->dev >= nand_dev_count) {
+ cpu_abort(cpu_single_env, "nand_dev_write: Bad dev %x\n", value);
+ }
+ break;
+ case NAND_ADDR_HIGH:
+ s->addr_high = value;
+ break;
+ case NAND_ADDR_LOW:
+ s->addr_low = value;
+ break;
+ case NAND_TRANSFER_SIZE:
+ s->transfer_size = value;
+ break;
+ case NAND_DATA:
+ s->data = value;
+ break;
+ case NAND_COMMAND:
+ s->result = nand_dev_do_cmd(s, value);
+ break;
+ default:
+ cpu_abort(cpu_single_env, "nand_dev_write: Bad offset %x\n", offset);
+ break;
+ }
+}
+
+/* I/O read */
+static uint32_t nand_dev_read(void *opaque, target_phys_addr_t offset)
+{
+ nand_dev_state *s = (nand_dev_state *)opaque;
+ nand_dev *dev;
+
+ offset -= s->base;
+ switch (offset) {
+ case NAND_VERSION:
+ return NAND_VERSION_CURRENT;
+ case NAND_NUM_DEV:
+ return nand_dev_count;
+ case NAND_RESULT:
+ return s->result;
+ }
+
+ if(s->dev >= nand_dev_count)
+ return 0;
+
+ dev = nand_devs + s->dev;
+
+ switch (offset) {
+ case NAND_DEV_FLAGS:
+ return dev->flags;
+
+ case NAND_DEV_NAME_LEN:
+ return dev->devname_len;
+
+ case NAND_DEV_PAGE_SIZE:
+ return dev->page_size;
+
+ case NAND_DEV_EXTRA_SIZE:
+ return dev->extra_size;
+
+ case NAND_DEV_ERASE_SIZE:
+ return dev->erase_size;
+
+ case NAND_DEV_SIZE_LOW:
+ return (uint32_t)dev->size;
+
+ case NAND_DEV_SIZE_HIGH:
+ return (uint32_t)(dev->size >> 32);
+
+ default:
+ cpu_abort(cpu_single_env, "nand_dev_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static CPUReadMemoryFunc *nand_dev_readfn[] = {
+ nand_dev_read,
+ nand_dev_read,
+ nand_dev_read
+};
+
+static CPUWriteMemoryFunc *nand_dev_writefn[] = {
+ nand_dev_write,
+ nand_dev_write,
+ nand_dev_write
+};
+
+/* initialize the QFB device */
+void nand_dev_init(uint32_t base)
+{
+ int iomemtype;
+ static int instance_id = 0;
+ nand_dev_state *s;
+
+ s = (nand_dev_state *)qemu_mallocz(sizeof(nand_dev_state));
+ iomemtype = cpu_register_io_memory(0, nand_dev_readfn, nand_dev_writefn, s);
+ cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+ s->base = base;
+
+ register_savevm( "nand_dev", instance_id++, NAND_DEV_STATE_SAVE_VERSION,
+ nand_dev_state_save, nand_dev_state_load, s);
+}
+
+static int arg_match(const char *a, const char *b, size_t b_len)
+{
+ while(*a && b_len--) {
+ if(*a++ != *b++)
+ return 0;
+ }
+ return b_len == 0;
+}
+
+void nand_add_dev(const char *arg)
+{
+ uint64_t dev_size = 0;
+ const char *next_arg;
+ const char *value;
+ size_t arg_len, value_len;
+ nand_dev *new_devs, *dev;
+ char *devname = NULL;
+ size_t devname_len = 0;
+ char *initfilename = NULL;
+ char *rwfilename = NULL;
+ int initfd = -1;
+ int rwfd = -1;
+ int read_only = 0;
+ int pad;
+ ssize_t read_size;
+ uint32_t page_size = 2048;
+ uint32_t extra_size = 64;
+ uint32_t erase_pages = 64;
+
+ while(arg) {
+ next_arg = strchr(arg, ',');
+ value = strchr(arg, '=');
+ if(next_arg != NULL) {
+ arg_len = next_arg - arg;
+ next_arg++;
+ if(value >= next_arg)
+ value = NULL;
+ }
+ else
+ arg_len = strlen(arg);
+ if(value != NULL) {
+ size_t new_arg_len = value - arg;
+ value_len = arg_len - new_arg_len - 1;
+ arg_len = new_arg_len;
+ value++;
+ }
+ else
+ value_len = 0;
+
+ if(devname == NULL) {
+ if(value != NULL)
+ goto bad_arg_and_value;
+ devname_len = arg_len;
+ devname = malloc(arg_len);
+ if(devname == NULL)
+ goto out_of_memory;
+ memcpy(devname, arg, arg_len);
+ }
+ else if(value == NULL) {
+ if(arg_match("readonly", arg, arg_len)) {
+ read_only = 1;
+ }
+ else {
+ XLOG("bad arg: %.*s\n", arg_len, arg);
+ exit(1);
+ }
+ }
+ else {
+ if(arg_match("size", arg, arg_len)) {
+ char *ep;
+ dev_size = strtoull(value, &ep, 0);
+ if(ep != value + value_len)
+ goto bad_arg_and_value;
+ }
+ else if(arg_match("pagesize", arg, arg_len)) {
+ char *ep;
+ page_size = strtoul(value, &ep, 0);
+ if(ep != value + value_len)
+ goto bad_arg_and_value;
+ }
+ else if(arg_match("extrasize", arg, arg_len)) {
+ char *ep;
+ extra_size = strtoul(value, &ep, 0);
+ if(ep != value + value_len)
+ goto bad_arg_and_value;
+ }
+ else if(arg_match("erasepages", arg, arg_len)) {
+ char *ep;
+ erase_pages = strtoul(value, &ep, 0);
+ if(ep != value + value_len)
+ goto bad_arg_and_value;
+ }
+ else if(arg_match("initfile", arg, arg_len)) {
+ initfilename = malloc(value_len + 1);
+ if(initfilename == NULL)
+ goto out_of_memory;
+ memcpy(initfilename, value, value_len);
+ initfilename[value_len] = '\0';
+ }
+ else if(arg_match("file", arg, arg_len)) {
+ rwfilename = malloc(value_len + 1);
+ if(rwfilename == NULL)
+ goto out_of_memory;
+ memcpy(rwfilename, value, value_len);
+ rwfilename[value_len] = '\0';
+ }
+ else {
+ goto bad_arg_and_value;
+ }
+ }
+
+ arg = next_arg;
+ }
+
+ if (rwfilename == NULL) {
+ /* we create a temporary file to store everything */
+ TempFile* tmp = tempfile_create();
+
+ if (tmp == NULL) {
+ XLOG("could not create temp file for %.*s NAND disk image: %s",
+ devname_len, devname, strerror(errno));
+ exit(1);
+ }
+ rwfilename = (char*) tempfile_path(tmp);
+ if (VERBOSE_CHECK(init))
+ dprint( "mapping '%.*s' NAND image to %s", devname_len, devname, rwfilename);
+ }
+
+ if(rwfilename) {
+ rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR));
+ if(rwfd < 0 && read_only) {
+ XLOG("could not open file %s, %s\n", rwfilename, strerror(errno));
+ exit(1);
+ }
+ /* this could be a writable temporary file. use atexit_close_fd to ensure
+ * that it is properly cleaned up at exit on Win32
+ */
+ if (!read_only)
+ atexit_close_fd(rwfd);
+ }
+
+ if(initfilename) {
+ initfd = open(initfilename, O_BINARY | O_RDONLY);
+ if(initfd < 0) {
+ XLOG("could not open file %s, %s\n", initfilename, strerror(errno));
+ exit(1);
+ }
+ if(dev_size == 0) {
+ dev_size = lseek(initfd, 0, SEEK_END);
+ lseek(initfd, 0, SEEK_SET);
+ }
+ }
+
+ new_devs = realloc(nand_devs, sizeof(nand_devs[0]) * (nand_dev_count + 1));
+ if(new_devs == NULL)
+ goto out_of_memory;
+ nand_devs = new_devs;
+ dev = &new_devs[nand_dev_count];
+
+ dev->page_size = page_size;
+ dev->extra_size = extra_size;
+ dev->erase_size = erase_pages * (page_size + extra_size);
+ pad = dev_size % dev->erase_size;
+ if (pad != 0) {
+ dev_size += (dev->erase_size - pad);
+ XLOG("rounding devsize up to a full eraseunit, now %llx\n", dev_size);
+ }
+ dev->devname = devname;
+ dev->devname_len = devname_len;
+ dev->size = dev_size;
+ dev->data = malloc(dev->erase_size);
+ if(dev->data == NULL)
+ goto out_of_memory;
+ dev->flags = read_only ? NAND_DEV_FLAG_READ_ONLY : 0;
+
+ if (initfd >= 0) {
+ do {
+ read_size = do_read(initfd, dev->data, dev->erase_size);
+ if(read_size < 0) {
+ XLOG("could not read file %s, %s\n", initfilename, strerror(errno));
+ exit(1);
+ }
+ if(do_write(rwfd, dev->data, read_size) != read_size) {
+ XLOG("could not write file %s, %s\n", initfilename, strerror(errno));
+ exit(1);
+ }
+ } while(read_size == dev->erase_size);
+ close(initfd);
+ }
+ dev->fd = rwfd;
+
+ nand_dev_count++;
+
+ return;
+
+out_of_memory:
+ XLOG("out of memory\n");
+ exit(1);
+
+bad_arg_and_value:
+ XLOG("bad arg: %.*s=%.*s\n", arg_len, arg, value_len, value);
+ exit(1);
+}
+
diff --git a/hw/goldfish_nand.h b/hw/goldfish_nand.h
new file mode 100644
index 0000000..dcc59d8
--- /dev/null
+++ b/hw/goldfish_nand.h
@@ -0,0 +1,28 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#ifndef NAND_DEVICE_H
+#define NAND_DEVICE_H
+
+void nand_dev_init(uint32_t base);
+void nand_add_dev(const char *arg);
+
+typedef struct {
+ uint64_t limit;
+ uint64_t counter;
+ int pid;
+ int signal;
+} nand_threshold;
+
+extern nand_threshold android_nand_read_threshold;
+extern nand_threshold android_nand_write_threshold;
+
+#endif
diff --git a/hw/goldfish_nand_reg.h b/hw/goldfish_nand_reg.h
new file mode 100644
index 0000000..ea91461
--- /dev/null
+++ b/hw/goldfish_nand_reg.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#ifndef NAND_DEVICE_REG_H
+#define NAND_DEVICE_REG_H
+
+enum nand_cmd {
+ NAND_CMD_GET_DEV_NAME, // Write device name for NAND_DEV to NAND_DATA (vaddr)
+ NAND_CMD_READ,
+ NAND_CMD_WRITE,
+ NAND_CMD_ERASE,
+ NAND_CMD_BLOCK_BAD_GET, // NAND_RESULT is 1 if block is bad, 0 if it is not
+ NAND_CMD_BLOCK_BAD_SET
+};
+
+enum nand_dev_flags {
+ NAND_DEV_FLAG_READ_ONLY = 0x00000001
+};
+
+#define NAND_VERSION_CURRENT (1)
+
+enum nand_reg {
+ // Global
+ NAND_VERSION = 0x000,
+ NAND_NUM_DEV = 0x004,
+ NAND_DEV = 0x008,
+
+ // Dev info
+ NAND_DEV_FLAGS = 0x010,
+ NAND_DEV_NAME_LEN = 0x014,
+ NAND_DEV_PAGE_SIZE = 0x018,
+ NAND_DEV_EXTRA_SIZE = 0x01c,
+ NAND_DEV_ERASE_SIZE = 0x020,
+ NAND_DEV_SIZE_LOW = 0x028,
+ NAND_DEV_SIZE_HIGH = 0x02c,
+
+ // Command
+ NAND_RESULT = 0x040,
+ NAND_COMMAND = 0x044,
+ NAND_DATA = 0x048,
+ NAND_TRANSFER_SIZE = 0x04c,
+ NAND_ADDR_LOW = 0x050,
+ NAND_ADDR_HIGH = 0x054,
+};
+
+#endif
diff --git a/hw/goldfish_switch.c b/hw/goldfish_switch.c
new file mode 100644
index 0000000..04fcad7
--- /dev/null
+++ b/hw/goldfish_switch.c
@@ -0,0 +1,172 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "goldfish_device.h"
+
+enum {
+ SW_NAME_LEN = 0x00,
+ SW_NAME_PTR = 0x04,
+ SW_FLAGS = 0x08,
+ SW_STATE = 0x0c,
+ SW_INT_STATUS = 0x10,
+ SW_INT_ENABLE = 0x14,
+
+ SW_FLAGS_OUTPUT = 1U << 0
+};
+
+
+struct switch_state {
+ struct goldfish_device dev;
+ char *name;
+ uint32_t state;
+ uint32_t state_changed : 1;
+ uint32_t int_enable : 1;
+ uint32_t (*writefn)(void *opaque, uint32_t state);
+ void *writeopaque;
+};
+
+#define GOLDFISH_SWITCH_SAVE_VERSION 1
+
+static void goldfish_switch_save(QEMUFile* f, void* opaque)
+{
+ struct switch_state* s = opaque;
+
+ qemu_put_be32(f, s->state);
+ qemu_put_byte(f, s->state_changed);
+ qemu_put_byte(f, s->int_enable);
+}
+
+static int goldfish_switch_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct switch_state* s = opaque;
+
+ if (version_id != GOLDFISH_SWITCH_SAVE_VERSION)
+ return -1;
+
+ s->state = qemu_get_be32(f);
+ s->state_changed = qemu_get_byte(f);
+ s->int_enable = qemu_get_byte(f);
+
+ return 0;
+}
+
+static uint32_t goldfish_switch_read(void *opaque, target_phys_addr_t offset)
+{
+ struct switch_state *s = (struct switch_state *)opaque;
+ offset -= s->dev.base;
+
+ //printf("goldfish_switch_read %x %x\n", offset, size);
+
+ switch (offset) {
+ case SW_NAME_LEN:
+ return strlen(s->name);
+ case SW_FLAGS:
+ return s->writefn ? SW_FLAGS_OUTPUT : 0;
+ case SW_STATE:
+ return s->state;
+ case SW_INT_STATUS:
+ if(s->state_changed && s->int_enable) {
+ s->state_changed = 0;
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ return 1;
+ }
+ return 0;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_switch_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_switch_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ struct switch_state *s = (struct switch_state *)opaque;
+ offset -= s->dev.base;
+
+ //printf("goldfish_switch_read %x %x %x\n", offset, value, size);
+
+ switch(offset) {
+ case SW_NAME_PTR:
+ pmemcpy(value, s->name, strlen(s->name));
+ break;
+
+ case SW_STATE:
+ if(s->writefn) {
+ uint32_t new_state;
+ new_state = s->writefn(s->writeopaque, value);
+ if(new_state != s->state) {
+ goldfish_switch_set_state(s, new_state);
+ }
+ }
+ else
+ cpu_abort (cpu_single_env, "goldfish_switch_write: write to SW_STATE on input\n");
+ break;
+
+ case SW_INT_ENABLE:
+ value &= 1;
+ if(s->state_changed && s->int_enable != value)
+ goldfish_device_set_irq(&s->dev, 0, value);
+ s->int_enable = value;
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_switch_write: Bad offset %x\n", offset);
+ }
+}
+
+static CPUReadMemoryFunc *goldfish_switch_readfn[] = {
+ goldfish_switch_read,
+ goldfish_switch_read,
+ goldfish_switch_read
+};
+
+static CPUWriteMemoryFunc *goldfish_switch_writefn[] = {
+ goldfish_switch_write,
+ goldfish_switch_write,
+ goldfish_switch_write
+};
+
+void goldfish_switch_set_state(void *opaque, uint32_t state)
+{
+ struct switch_state *s = opaque;
+ s->state_changed = 1;
+ s->state = state;
+ if(s->int_enable)
+ goldfish_device_set_irq(&s->dev, 0, 1);
+}
+
+void *goldfish_switch_add(char *name, uint32_t (*writefn)(void *opaque, uint32_t state), void *writeopaque, int id)
+{
+ int ret;
+ struct switch_state *s;
+
+ s = qemu_mallocz(sizeof(*s));
+ s->dev.name = "goldfish-switch";
+ s->dev.id = id;
+ s->dev.size = 0x1000;
+ s->dev.irq_count = 1;
+ s->name = name;
+ s->writefn = writefn;
+ s->writeopaque = writeopaque;
+
+
+ ret = goldfish_device_add(&s->dev, goldfish_switch_readfn, goldfish_switch_writefn, s);
+ if(ret) {
+ qemu_free(s);
+ return NULL;
+ }
+
+ register_savevm( "goldfish_switch", 0, GOLDFISH_SWITCH_SAVE_VERSION,
+ goldfish_switch_save, goldfish_switch_load, s);
+
+ return s;
+}
+
diff --git a/hw/goldfish_timer.c b/hw/goldfish_timer.c
new file mode 100644
index 0000000..bb345a5
--- /dev/null
+++ b/hw/goldfish_timer.c
@@ -0,0 +1,255 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "arm_pic.h"
+#include "goldfish_device.h"
+
+enum {
+ TIMER_TIME_LOW = 0x00, // get low bits of current time and update TIMER_TIME_HIGH
+ TIMER_TIME_HIGH = 0x04, // get high bits of time at last TIMER_TIME_LOW read
+ TIMER_ALARM_LOW = 0x08, // set low bits of alarm and activate it
+ TIMER_ALARM_HIGH = 0x0c, // set high bits of next alarm
+ TIMER_CLEAR_INTERRUPT = 0x10,
+ TIMER_CLEAR_ALARM = 0x14
+};
+
+struct timer_state {
+ struct goldfish_device dev;
+ uint32_t alarm_low;
+ int32_t alarm_high;
+ int64_t now;
+ int armed;
+ QEMUTimer *timer;
+};
+
+#define GOLDFISH_TIMER_SAVE_VERSION 1
+
+static void goldfish_timer_save(QEMUFile* f, void* opaque)
+{
+ struct timer_state* s = opaque;
+
+ qemu_put_be64(f, s->now); /* in case the kernel is in the middle of a timer read */
+ qemu_put_byte(f, s->armed);
+ if (s->armed) {
+ int64_t now = qemu_get_clock(vm_clock);
+ int64_t alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000);
+ qemu_put_be64(f, alarm-now);
+ }
+}
+
+static int goldfish_timer_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct timer_state* s = opaque;
+
+ if (version_id != GOLDFISH_TIMER_SAVE_VERSION)
+ return -1;
+
+ s->now = qemu_get_be64(f);
+ s->armed = qemu_get_byte(f);
+ if (s->armed) {
+ int64_t now = qemu_get_clock(vm_clock);
+ int64_t diff = qemu_get_be64(f);
+ int64_t alarm = now + diff;
+
+ if (alarm <= now) {
+ goldfish_device_set_irq(&s->dev, 0, 1);
+ s->armed = 0;
+ } else {
+ qemu_mod_timer(s->timer, alarm);
+ }
+ }
+ return 0;
+}
+
+static uint32_t goldfish_timer_read(void *opaque, target_phys_addr_t offset)
+{
+ struct timer_state *s = (struct timer_state *)opaque;
+ offset -= s->dev.base;
+ switch(offset) {
+ case TIMER_TIME_LOW:
+ s->now = muldiv64(qemu_get_clock(vm_clock), 1000000000, ticks_per_sec);
+ return s->now;
+ case TIMER_TIME_HIGH:
+ return s->now >> 32;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_timer_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ struct timer_state *s = (struct timer_state *)opaque;
+ int64_t alarm, now;
+ offset -= s->dev.base;
+ switch(offset) {
+ case TIMER_ALARM_LOW:
+ s->alarm_low = value;
+ alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000);
+ now = qemu_get_clock(vm_clock);
+ if (alarm <= now) {
+ goldfish_device_set_irq(&s->dev, 0, 1);
+ } else {
+ qemu_mod_timer(s->timer, alarm);
+ s->armed = 1;
+ }
+ break;
+ case TIMER_ALARM_HIGH:
+ s->alarm_high = value;
+ //printf("alarm_high %d\n", s->alarm_high);
+ break;
+ case TIMER_CLEAR_ALARM:
+ qemu_del_timer(s->timer);
+ s->armed = 0;
+ /* fall through */
+ case TIMER_CLEAR_INTERRUPT:
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ break;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_timer_write: Bad offset %x\n", offset);
+ }
+}
+
+static void goldfish_timer_tick(void *opaque)
+{
+ struct timer_state *s = (struct timer_state *)opaque;
+
+ s->armed = 0;
+ goldfish_device_set_irq(&s->dev, 0, 1);
+}
+
+struct rtc_state {
+ struct goldfish_device dev;
+ uint32_t alarm_low;
+ int32_t alarm_high;
+ int64_t now;
+};
+
+/* we save the RTC for the case where the kernel is in the middle of a rtc_read
+ * (i.e. it has read the low 32-bit of s->now, but not the high 32-bits yet */
+#define GOLDFISH_RTC_SAVE_VERSION 1
+
+static void goldfish_rtc_save(QEMUFile* f, void* opaque)
+{
+ struct rtc_state* s = opaque;
+
+ qemu_put_be64(f, s->now);
+}
+
+static int goldfish_rtc_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct rtc_state* s = opaque;
+
+ if (version_id != GOLDFISH_RTC_SAVE_VERSION)
+ return -1;
+
+ /* this is an old value that is not correct. but that's ok anyway */
+ s->now = qemu_get_be64(f);
+ return 0;
+}
+
+static uint32_t goldfish_rtc_read(void *opaque, target_phys_addr_t offset)
+{
+ struct rtc_state *s = (struct rtc_state *)opaque;
+ offset -= s->dev.base;
+ switch(offset) {
+ case 0x0:
+ s->now = (int64_t)time(NULL) * 1000000000;
+ return s->now;
+ case 0x4:
+ return s->now >> 32;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_rtc_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ struct rtc_state *s = (struct rtc_state *)opaque;
+ int64_t alarm;
+ offset -= s->dev.base;
+ switch(offset) {
+ case 0x8:
+ s->alarm_low = value;
+ alarm = s->alarm_low | (int64_t)s->alarm_high << 32;
+ //printf("next alarm at %lld, tps %lld\n", alarm, ticks_per_sec);
+ //qemu_mod_timer(s->timer, alarm);
+ break;
+ case 0xc:
+ s->alarm_high = value;
+ //printf("alarm_high %d\n", s->alarm_high);
+ break;
+ case 0x10:
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ break;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_rtc_write: Bad offset %x\n", offset);
+ }
+}
+
+static struct timer_state timer_state = {
+ .dev = {
+ .name = "goldfish_timer",
+ .id = -1,
+ .size = 0x1000,
+ .irq_count = 1,
+ }
+};
+
+static struct timer_state rtc_state = {
+ .dev = {
+ .name = "goldfish_rtc",
+ .id = -1,
+ .size = 0x1000,
+ .irq_count = 1,
+ }
+};
+
+static CPUReadMemoryFunc *goldfish_timer_readfn[] = {
+ goldfish_timer_read,
+ goldfish_timer_read,
+ goldfish_timer_read
+};
+
+static CPUWriteMemoryFunc *goldfish_timer_writefn[] = {
+ goldfish_timer_write,
+ goldfish_timer_write,
+ goldfish_timer_write
+};
+
+static CPUReadMemoryFunc *goldfish_rtc_readfn[] = {
+ goldfish_rtc_read,
+ goldfish_rtc_read,
+ goldfish_rtc_read
+};
+
+static CPUWriteMemoryFunc *goldfish_rtc_writefn[] = {
+ goldfish_rtc_write,
+ goldfish_rtc_write,
+ goldfish_rtc_write
+};
+
+void goldfish_timer_and_rtc_init(uint32_t timerbase, int timerirq)
+{
+ timer_state.dev.base = timerbase;
+ timer_state.dev.irq = timerirq;
+ timer_state.timer = qemu_new_timer(vm_clock, goldfish_timer_tick, &timer_state);
+ goldfish_device_add(&timer_state.dev, goldfish_timer_readfn, goldfish_timer_writefn, &timer_state);
+ register_savevm( "goldfish_timer", 0, GOLDFISH_TIMER_SAVE_VERSION,
+ goldfish_timer_save, goldfish_timer_load, &timer_state);
+
+ goldfish_device_add(&rtc_state.dev, goldfish_rtc_readfn, goldfish_rtc_writefn, &rtc_state);
+ register_savevm( "goldfish_rtc", 0, GOLDFISH_RTC_SAVE_VERSION,
+ goldfish_rtc_save, goldfish_rtc_load, &rtc_state);
+}
+
diff --git a/hw/goldfish_trace.c b/hw/goldfish_trace.c
new file mode 100644
index 0000000..47822b3
--- /dev/null
+++ b/hw/goldfish_trace.c
@@ -0,0 +1,252 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+/*
+ * Virtual hardware for bridging the FUSE kernel module
+ * in the emulated OS and outside file system
+ */
+#include "vl.h"
+
+#include "goldfish_trace.h"
+
+//#define DEBUG 1
+
+extern void cpu_loop_exit(void);
+
+extern int tracing;
+
+/* for execve */
+static char path[CLIENT_PAGE_SIZE];
+static char arg[CLIENT_PAGE_SIZE];
+static unsigned long vstart; // VM start
+static unsigned long vend; // VM end
+static unsigned long eoff; // offset in EXE file
+static unsigned cmdlen; // cmdline length
+static unsigned pid; // PID (really thread id)
+static unsigned tgid; // thread group id (really process id)
+static unsigned long dsaddr; // dynamic symbol address
+static unsigned long unmap_start; // start address to unmap
+
+/* for context switch */
+//static unsigned long cs_pid; // context switch PID
+
+/* I/O write */
+static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ trace_dev_state *s = (trace_dev_state *)opaque;
+
+ offset -= s->base;
+ switch (offset >> 2) {
+ case TRACE_DEV_REG_SWITCH: // context switch, switch to pid
+ trace_switch(value);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, context switch %u\n", value);
+#endif
+ break;
+ case TRACE_DEV_REG_TGID: // save the tgid for the following fork/clone
+ tgid = value;
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, tgid %u\n", value);
+#endif
+ break;
+ case TRACE_DEV_REG_FORK: // fork, fork new pid
+ trace_fork(tgid, value);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, fork %u\n", value);
+#endif
+ break;
+ case TRACE_DEV_REG_CLONE: // fork, clone new pid (i.e. thread)
+ trace_clone(tgid, value);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, clone %u\n", value);
+#endif
+ break;
+ case TRACE_DEV_REG_EXECVE_VMSTART: // execve, vstart
+ vstart = value;
+ break;
+ case TRACE_DEV_REG_EXECVE_VMEND: // execve, vend
+ vend = value;
+ break;
+ case TRACE_DEV_REG_EXECVE_OFFSET: // execve, offset in EXE
+ eoff = value;
+ break;
+ case TRACE_DEV_REG_EXECVE_EXEPATH: // init exec, path of EXE
+ vstrcpy(value, path, CLIENT_PAGE_SIZE);
+ trace_init_exec(vstart, vend, eoff, path);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, path);
+#endif
+ path[0] = 0;
+ break;
+ case TRACE_DEV_REG_CMDLINE_LEN: // execve, process cmdline length
+ cmdlen = value;
+ break;
+ case TRACE_DEV_REG_CMDLINE: // execve, process cmdline
+ vmemcpy(value, arg, cmdlen);
+ trace_execve(arg, cmdlen);
+#ifdef DEBUG
+ {
+ int i;
+ for (i = 0; i < cmdlen; i ++)
+ if (i != cmdlen - 1 && arg[i] == 0)
+ arg[i] = ' ';
+ printf("QEMU.trace: kernel, execve %s[%d]\n", arg, cmdlen);
+ }
+#endif
+ arg[0] = 0;
+ break;
+ case TRACE_DEV_REG_EXIT: // exit, exit current process with exit code
+ trace_exit(value);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, exit %x\n", value);
+#endif
+ break;
+ case TRACE_DEV_REG_NAME: // record thread name
+ vstrcpy(value, path, CLIENT_PAGE_SIZE);
+
+ // Remove the trailing newline if it exists
+ int len = strlen(path);
+ if (path[len - 1] == '\n') {
+ path[len - 1] = 0;
+ }
+ trace_name(path);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, name %s\n", path);
+#endif
+ break;
+ case TRACE_DEV_REG_MMAP_EXEPATH: // mmap, path of EXE, the others are same as execve
+ vstrcpy(value, path, CLIENT_PAGE_SIZE);
+ trace_mmap(vstart, vend, eoff, path);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, path);
+#endif
+ path[0] = 0;
+ break;
+ case TRACE_DEV_REG_INIT_PID: // init, name the pid that starts before device registered
+ pid = value;
+ break;
+ case TRACE_DEV_REG_INIT_NAME: // init, the comm of the init pid
+ vstrcpy(value, path, CLIENT_PAGE_SIZE);
+ trace_init_name(tgid, pid, path);
+#ifdef DEBUG
+ printf("QEMU.trace: kernel, init name %u [%s]\n", pid, path);
+#endif
+ path[0] = 0;
+ break;
+
+ case TRACE_DEV_REG_DYN_SYM_ADDR: // dynamic symbol address
+ dsaddr = value;
+ break;
+ case TRACE_DEV_REG_DYN_SYM: // add dynamic symbol
+ vstrcpy(value, arg, CLIENT_PAGE_SIZE);
+ trace_dynamic_symbol_add(dsaddr, arg);
+#ifdef DEBUG
+ printf("QEMU.trace: dynamic symbol %lx:%s\n", dsaddr, arg);
+#endif
+ arg[0] = 0;
+ break;
+ case TRACE_DEV_REG_REMOVE_ADDR: // remove dynamic symbol addr
+ trace_dynamic_symbol_remove(value);
+#ifdef DEBUG
+ printf("QEMU.trace: dynamic symbol remove %lx\n", dsaddr);
+#endif
+ arg[0] = 0;
+ break;
+
+ case TRACE_DEV_REG_PRINT_STR: // print string
+ vstrcpy(value, arg, CLIENT_PAGE_SIZE);
+ printf("%s", arg);
+ arg[0] = 0;
+ break;
+ case TRACE_DEV_REG_PRINT_NUM_DEC: // print number in decimal
+ printf("%d", value);
+ break;
+ case TRACE_DEV_REG_PRINT_NUM_HEX: // print number in hexical
+ printf("%x", value);
+ break;
+
+ case TRACE_DEV_REG_STOP_EMU: // stop the VM execution
+ // To ensure that the number of instructions executed in this
+ // block is correct, we pretend that there was an exception.
+ trace_exception(0);
+
+ cpu_single_env->exception_index = EXCP_HLT;
+ cpu_single_env->halted = 1;
+ qemu_system_shutdown_request();
+ cpu_loop_exit();
+ break;
+
+ case TRACE_DEV_REG_ENABLE: // tracing enable: 0 = stop, 1 = start
+ if (value == 1)
+ start_tracing();
+ else if (value == 0) {
+ stop_tracing();
+
+ // To ensure that the number of instructions executed in this
+ // block is correct, we pretend that there was an exception.
+ trace_exception(0);
+ }
+ break;
+
+ case TRACE_DEV_REG_UNMAP_START:
+ unmap_start = value;
+ break;
+ case TRACE_DEV_REG_UNMAP_END:
+ trace_munmap(unmap_start, value);
+ break;
+
+ default:
+ cpu_abort(cpu_single_env, "trace_dev_write: Bad offset %x\n", offset);
+ break;
+ }
+}
+
+/* I/O read */
+static uint32_t trace_dev_read(void *opaque, target_phys_addr_t offset)
+{
+ trace_dev_state *s = (trace_dev_state *)opaque;
+
+ offset -= s->base;
+ switch (offset >> 2) {
+ case TRACE_DEV_REG_ENABLE: // tracing enable
+ return tracing;
+ default:
+ cpu_abort(cpu_single_env, "trace_dev_read: Bad offset %x\n", offset);
+ return 0;
+ }
+ return 0;
+}
+
+static CPUReadMemoryFunc *trace_dev_readfn[] = {
+ trace_dev_read,
+ trace_dev_read,
+ trace_dev_read
+};
+
+static CPUWriteMemoryFunc *trace_dev_writefn[] = {
+ trace_dev_write,
+ trace_dev_write,
+ trace_dev_write
+};
+
+/* initialize the trace device */
+void trace_dev_init(uint32_t base)
+{
+ int iomemtype;
+ trace_dev_state *s;
+
+ s = (trace_dev_state *)qemu_mallocz(sizeof(trace_dev_state));
+ iomemtype = cpu_register_io_memory(0, trace_dev_readfn, trace_dev_writefn, s);
+ cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+ s->base = base;
+
+ path[0] = arg[0] = '\0';
+}
diff --git a/hw/goldfish_trace.h b/hw/goldfish_trace.h
new file mode 100644
index 0000000..ea627e8
--- /dev/null
+++ b/hw/goldfish_trace.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#ifndef _TRACE_DEV_H_
+#define _TRACE_DEV_H_
+
+#define CLIENT_PAGE_SIZE 4096
+
+/* trace device registers */
+#define TRACE_DEV_REG_SWITCH 0
+#define TRACE_DEV_REG_FORK 1
+#define TRACE_DEV_REG_EXECVE_PID 2
+#define TRACE_DEV_REG_EXECVE_VMSTART 3
+#define TRACE_DEV_REG_EXECVE_VMEND 4
+#define TRACE_DEV_REG_EXECVE_OFFSET 5
+#define TRACE_DEV_REG_EXECVE_EXEPATH 6
+#define TRACE_DEV_REG_EXIT 7
+#define TRACE_DEV_REG_CMDLINE 8
+#define TRACE_DEV_REG_CMDLINE_LEN 9
+#define TRACE_DEV_REG_MMAP_EXEPATH 10
+#define TRACE_DEV_REG_INIT_PID 11
+#define TRACE_DEV_REG_INIT_NAME 12
+#define TRACE_DEV_REG_CLONE 13
+#define TRACE_DEV_REG_UNMAP_START 14
+#define TRACE_DEV_REG_UNMAP_END 15
+#define TRACE_DEV_REG_NAME 16
+#define TRACE_DEV_REG_TGID 17
+#define TRACE_DEV_REG_DYN_SYM 50
+#define TRACE_DEV_REG_DYN_SYM_ADDR 51
+#define TRACE_DEV_REG_REMOVE_ADDR 52
+#define TRACE_DEV_REG_PRINT_STR 60
+#define TRACE_DEV_REG_PRINT_NUM_DEC 61
+#define TRACE_DEV_REG_PRINT_NUM_HEX 62
+#define TRACE_DEV_REG_STOP_EMU 90
+#define TRACE_DEV_REG_ENABLE 100
+
+/* the virtual trace device state */
+typedef struct {
+ uint32_t base;
+} trace_dev_state;
+
+/*
+ * interfaces for copy from virtual space
+ * from target-arm/op_helper.c
+ */
+extern unsigned long v2p(target_ulong ptr, int is_user);
+extern void vmemcpy(target_ulong ptr, char *buf, int size);
+extern void vstrcpy(target_ulong ptr, char *buf, int max);
+
+/*
+ * interfaces to trace module to signal kernel events
+ */
+extern void trace_switch(int pid);
+extern void trace_fork(int tgid, int pid);
+extern void trace_clone(int tgid, int pid);
+extern void trace_execve(const char *arg, int len);
+extern void trace_exit(int exitcode);
+extern void trace_mmap(unsigned long vstart, unsigned long vend,
+ unsigned long offset, const char *path);
+extern void trace_munmap(unsigned long vstart, unsigned long vend);
+extern void trace_dynamic_symbol_add(unsigned long vaddr, const char *name);
+extern void trace_dynamic_symbol_remove(unsigned long vaddr);
+extern void trace_init_name(int tgid, int pid, const char *name);
+extern void trace_init_exec(unsigned long start, unsigned long end,
+ unsigned long offset, const char *exe);
+extern void start_tracing(void);
+extern void stop_tracing(void);
+extern void trace_exception(uint32 target_pc);
+
+#endif
diff --git a/hw/goldfish_tty.c b/hw/goldfish_tty.c
new file mode 100644
index 0000000..d61712a
--- /dev/null
+++ b/hw/goldfish_tty.c
@@ -0,0 +1,225 @@
+/* Copyright (C) 2007-2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "vl.h"
+#include "goldfish_device.h"
+
+enum {
+ TTY_PUT_CHAR = 0x00,
+ TTY_BYTES_READY = 0x04,
+ TTY_CMD = 0x08,
+
+ TTY_DATA_PTR = 0x10,
+ TTY_DATA_LEN = 0x14,
+
+ TTY_CMD_INT_DISABLE = 0,
+ TTY_CMD_INT_ENABLE = 1,
+ TTY_CMD_WRITE_BUFFER = 2,
+ TTY_CMD_READ_BUFFER = 3,
+};
+
+struct tty_state {
+ struct goldfish_device dev;
+ CharDriverState *cs;
+ uint32_t ptr;
+ uint32_t ptr_len;
+ uint32_t ready;
+ uint8_t data[128];
+ uint32_t data_count;
+};
+
+#define GOLDFISH_TTY_SAVE_VERSION 1
+
+static void goldfish_tty_save(QEMUFile* f, void* opaque)
+{
+ struct tty_state* s = opaque;
+
+ qemu_put_be32( f, s->ptr );
+ qemu_put_be32( f, s->ptr_len );
+ qemu_put_byte( f, s->ready );
+ qemu_put_byte( f, s->data_count );
+ qemu_put_buffer( f, s->data, s->data_count );
+}
+
+static int goldfish_tty_load(QEMUFile* f, void* opaque, int version_id)
+{
+ struct tty_state* s = opaque;
+
+ if (version_id != GOLDFISH_TTY_SAVE_VERSION)
+ return -1;
+
+ s->ptr = qemu_get_be32(f);
+ s->ptr_len = qemu_get_be32(f);
+ s->ready = qemu_get_byte(f);
+ s->data_count = qemu_get_byte(f);
+ qemu_get_buffer(f, s->data, s->data_count);
+
+ return 0;
+}
+
+static uint32_t goldfish_tty_read(void *opaque, target_phys_addr_t offset)
+{
+ struct tty_state *s = (struct tty_state *)opaque;
+ offset -= s->dev.base;
+
+ //printf("goldfish_tty_read %x %x\n", offset, size);
+
+ switch (offset) {
+ case TTY_BYTES_READY:
+ return s->data_count;
+ default:
+ cpu_abort (cpu_single_env, "goldfish_tty_read: Bad offset %x\n", offset);
+ return 0;
+ }
+}
+
+static void goldfish_tty_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+ struct tty_state *s = (struct tty_state *)opaque;
+ offset -= s->dev.base;
+
+ //printf("goldfish_tty_read %x %x %x\n", offset, value, size);
+
+ switch(offset) {
+ case TTY_PUT_CHAR: {
+ uint8_t ch = value;
+ if(s->cs)
+ qemu_chr_write(s->cs, &ch, 1);
+ } break;
+
+ case TTY_CMD:
+ switch(value) {
+ case TTY_CMD_INT_DISABLE:
+ if(s->ready) {
+ if(s->data_count > 0)
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ s->ready = 0;
+ }
+ break;
+
+ case TTY_CMD_INT_ENABLE:
+ if(!s->ready) {
+ if(s->data_count > 0)
+ goldfish_device_set_irq(&s->dev, 0, 1);
+ s->ready = 1;
+ }
+ break;
+
+ case TTY_CMD_WRITE_BUFFER:
+ if(s->cs) {
+ int len;
+ target_ulong buf;
+
+ buf = s->ptr;
+ len = s->ptr_len;
+
+ while(len) {
+ int page_remain = TARGET_PAGE_SIZE - (buf & ~TARGET_PAGE_MASK);
+ int to_write = len;
+ uint8_t *phys = (uint8_t *)v2p(buf, 0);
+ if(to_write > page_remain)
+ to_write = page_remain;
+ qemu_chr_write(s->cs, phys, to_write);
+ buf += to_write;
+ len -= to_write;
+ }
+ //printf("goldfish_tty_write: got %d bytes from %x\n", s->ptr_len, s->ptr);
+ }
+ break;
+
+ case TTY_CMD_READ_BUFFER:
+ if(s->ptr_len > s->data_count)
+ cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count);
+ pmemcpy(s->ptr, s->data, s->ptr_len);
+ //printf("goldfish_tty_write: read %d bytes to %x\n", s->ptr_len, s->ptr);
+ if(s->data_count > s->ptr_len)
+ memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len);
+ s->data_count -= s->ptr_len;
+ if(s->data_count == 0 && s->ready)
+ goldfish_device_set_irq(&s->dev, 0, 0);
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_tty_write: Bad command %x\n", value);
+ };
+ break;
+
+ case TTY_DATA_PTR:
+ s->ptr = value;
+ break;
+
+ case TTY_DATA_LEN:
+ s->ptr_len = value;
+ break;
+
+ default:
+ cpu_abort (cpu_single_env, "goldfish_tty_write: Bad offset %x\n", offset);
+ }
+}
+
+static int tty_can_recieve(void *opaque)
+{
+ struct tty_state *s = opaque;
+
+ return (sizeof(s->data) - s->data_count);
+}
+
+static void tty_recieve(void *opaque, const uint8_t *buf, int size)
+{
+ struct tty_state *s = opaque;
+
+ memcpy(s->data + s->data_count, buf, size);
+ s->data_count += size;
+ if(s->data_count > 0 && s->ready)
+ goldfish_device_set_irq(&s->dev, 0, 1);
+}
+
+static CPUReadMemoryFunc *goldfish_tty_readfn[] = {
+ goldfish_tty_read,
+ goldfish_tty_read,
+ goldfish_tty_read
+};
+
+static CPUWriteMemoryFunc *goldfish_tty_writefn[] = {
+ goldfish_tty_write,
+ goldfish_tty_write,
+ goldfish_tty_write
+};
+
+int goldfish_tty_add(CharDriverState *cs, int id, uint32_t base, int irq)
+{
+ int ret;
+ struct tty_state *s;
+ static int instance_id = 0;
+
+ s = qemu_mallocz(sizeof(*s));
+ s->dev.name = "goldfish_tty";
+ s->dev.id = id;
+ s->dev.base = base;
+ s->dev.size = 0x1000;
+ s->dev.irq = irq;
+ s->dev.irq_count = 1;
+ s->cs = cs;
+
+ if(cs) {
+ qemu_chr_add_read_handler(cs, tty_can_recieve, tty_recieve, s);
+ }
+
+ ret = goldfish_device_add(&s->dev, goldfish_tty_readfn, goldfish_tty_writefn, s);
+ if(ret) {
+ qemu_free(s);
+ } else {
+ register_savevm( "goldfish_tty", instance_id++, GOLDFISH_TTY_SAVE_VERSION,
+ goldfish_tty_save, goldfish_tty_load, s);
+ }
+ return ret;
+}
+
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
deleted file mode 100644
index e3cbceb..0000000
--- a/hw/grackle_pci.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * QEMU Grackle (heathrow PPC) PCI host
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "vl.h"
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
-typedef PCIHostState GrackleState;
-
-static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- GrackleState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- s->config_reg = val;
-}
-
-static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr)
-{
- GrackleState *s = opaque;
- uint32_t val;
-
- val = s->config_reg;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- return val;
-}
-
-static CPUWriteMemoryFunc *pci_grackle_config_write[] = {
- &pci_grackle_config_writel,
- &pci_grackle_config_writel,
- &pci_grackle_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_grackle_config_read[] = {
- &pci_grackle_config_readl,
- &pci_grackle_config_readl,
- &pci_grackle_config_readl,
-};
-
-static CPUWriteMemoryFunc *pci_grackle_write[] = {
- &pci_host_data_writeb,
- &pci_host_data_writew,
- &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc *pci_grackle_read[] = {
- &pci_host_data_readb,
- &pci_host_data_readw,
- &pci_host_data_readl,
-};
-
-/* XXX: we do not simulate the hardware - we rely on the BIOS to
- set correctly for irq line field */
-static void pci_grackle_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
-{
- heathrow_pic_set_irq(pic, d->config[PCI_INTERRUPT_LINE], level);
-}
-
-PCIBus *pci_grackle_init(uint32_t base, void *pic)
-{
- GrackleState *s;
- PCIDevice *d;
- int pci_mem_config, pci_mem_data;
-
- s = qemu_mallocz(sizeof(GrackleState));
- s->bus = pci_register_bus(pci_grackle_set_irq, pic, 0);
-
- pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read,
- pci_grackle_config_write, s);
- pci_mem_data = cpu_register_io_memory(0, pci_grackle_read,
- pci_grackle_write, s);
- cpu_register_physical_memory(base, 0x1000, pci_mem_config);
- cpu_register_physical_memory(base + 0x00200000, 0x1000, pci_mem_data);
- d = pci_register_device(s->bus, "Grackle host bridge", sizeof(PCIDevice),
- 0, NULL, NULL);
- d->config[0x00] = 0x57; // vendor_id
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x02; // device_id
- d->config[0x03] = 0x00;
- d->config[0x08] = 0x00; // revision
- d->config[0x09] = 0x01;
- d->config[0x0a] = 0x00; // class_sub = host
- d->config[0x0b] = 0x06; // class_base = PCI_bridge
- d->config[0x0e] = 0x00; // header_type
-
- d->config[0x18] = 0x00; // primary_bus
- d->config[0x19] = 0x01; // secondary_bus
- d->config[0x1a] = 0x00; // subordinate_bus
- d->config[0x1c] = 0x00;
- d->config[0x1d] = 0x00;
-
- d->config[0x20] = 0x00; // memory_base
- d->config[0x21] = 0x00;
- d->config[0x22] = 0x01; // memory_limit
- d->config[0x23] = 0x00;
-
- d->config[0x24] = 0x00; // prefetchable_memory_base
- d->config[0x25] = 0x00;
- d->config[0x26] = 0x00; // prefetchable_memory_limit
- d->config[0x27] = 0x00;
-
-#if 0
- /* PCI2PCI bridge same values as PearPC - check this */
- d->config[0x00] = 0x11; // vendor_id
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x26; // device_id
- d->config[0x03] = 0x00;
- d->config[0x08] = 0x02; // revision
- d->config[0x0a] = 0x04; // class_sub = pci2pci
- d->config[0x0b] = 0x06; // class_base = PCI_bridge
- d->config[0x0e] = 0x01; // header_type
-
- d->config[0x18] = 0x0; // primary_bus
- d->config[0x19] = 0x1; // secondary_bus
- d->config[0x1a] = 0x1; // subordinate_bus
- d->config[0x1c] = 0x10; // io_base
- d->config[0x1d] = 0x20; // io_limit
-
- d->config[0x20] = 0x80; // memory_base
- d->config[0x21] = 0x80;
- d->config[0x22] = 0x90; // memory_limit
- d->config[0x23] = 0x80;
-
- d->config[0x24] = 0x00; // prefetchable_memory_base
- d->config[0x25] = 0x84;
- d->config[0x26] = 0x00; // prefetchable_memory_limit
- d->config[0x27] = 0x85;
-#endif
- return s->bus;
-}
-
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
deleted file mode 100644
index 4980cef..0000000
--- a/hw/heathrow_pic.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Heathrow PIC support (standard PowerMac PIC)
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define DEBUG
-
-typedef struct HeathrowPIC {
- uint32_t events;
- uint32_t mask;
- uint32_t levels;
- uint32_t level_triggered;
-} HeathrowPIC;
-
-struct HeathrowPICS {
- HeathrowPIC pics[2];
-};
-
-static inline int check_irq(HeathrowPIC *pic)
-{
- return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask;
-}
-
-/* update the CPU irq state */
-static void heathrow_pic_update(HeathrowPICS *s)
-{
- if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) {
- cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
- }
-}
-
-static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- HeathrowPICS *s = opaque;
- HeathrowPIC *pic;
- unsigned int n;
-
- value = bswap32(value);
-#ifdef DEBUG
- printf("pic_writel: %08x: %08x\n",
- addr, value);
-#endif
- n = ((addr & 0xfff) - 0x10) >> 4;
- if (n >= 2)
- return;
- pic = &s->pics[n];
- switch(addr & 0xf) {
- case 0x04:
- pic->mask = value;
- heathrow_pic_update(s);
- break;
- case 0x08:
- /* do not reset level triggered IRQs */
- value &= ~pic->level_triggered;
- pic->events &= ~value;
- heathrow_pic_update(s);
- break;
- default:
- break;
- }
-}
-
-static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
-{
- HeathrowPICS *s = opaque;
- HeathrowPIC *pic;
- unsigned int n;
- uint32_t value;
-
- n = ((addr & 0xfff) - 0x10) >> 4;
- if (n >= 2) {
- value = 0;
- } else {
- pic = &s->pics[n];
- switch(addr & 0xf) {
- case 0x0:
- value = pic->events;
- break;
- case 0x4:
- value = pic->mask;
- break;
- case 0xc:
- value = pic->levels;
- break;
- default:
- value = 0;
- break;
- }
- }
-#ifdef DEBUG
- printf("pic_readl: %08x: %08x\n",
- addr, value);
-#endif
- value = bswap32(value);
- return value;
-}
-
-static CPUWriteMemoryFunc *pic_write[] = {
- &pic_writel,
- &pic_writel,
- &pic_writel,
-};
-
-static CPUReadMemoryFunc *pic_read[] = {
- &pic_readl,
- &pic_readl,
- &pic_readl,
-};
-
-
-void heathrow_pic_set_irq(void *opaque, int num, int level)
-{
- HeathrowPICS *s = opaque;
- HeathrowPIC *pic;
- unsigned int irq_bit;
-
-#if defined(DEBUG)
- {
- static int last_level[64];
- if (last_level[num] != level) {
- printf("set_irq: num=0x%02x level=%d\n", num, level);
- last_level[num] = level;
- }
- }
-#endif
- pic = &s->pics[1 - (num >> 5)];
- irq_bit = 1 << (num & 0x1f);
- if (level) {
- pic->events |= irq_bit & ~pic->level_triggered;
- pic->levels |= irq_bit;
- } else {
- pic->levels &= ~irq_bit;
- }
- heathrow_pic_update(s);
-}
-
-HeathrowPICS *heathrow_pic_init(int *pmem_index)
-{
- HeathrowPICS *s;
-
- s = qemu_mallocz(sizeof(HeathrowPICS));
- s->pics[0].level_triggered = 0;
- s->pics[1].level_triggered = 0x1ff00000;
- *pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s);
- return s;
-}
diff --git a/hw/i8254.c b/hw/i8254.c
deleted file mode 100644
index a409763..0000000
--- a/hw/i8254.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * QEMU 8253/8254 interval timer emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define DEBUG_PIT
-
-#define RW_STATE_LSB 1
-#define RW_STATE_MSB 2
-#define RW_STATE_WORD0 3
-#define RW_STATE_WORD1 4
-
-typedef struct PITChannelState {
- int count; /* can be 65536 */
- uint16_t latched_count;
- uint8_t count_latched;
- uint8_t status_latched;
- uint8_t status;
- uint8_t read_state;
- uint8_t write_state;
- uint8_t write_latch;
- uint8_t rw_mode;
- uint8_t mode;
- uint8_t bcd; /* not supported */
- uint8_t gate; /* timer start */
- int64_t count_load_time;
- /* irq handling */
- int64_t next_transition_time;
- QEMUTimer *irq_timer;
- int irq;
-} PITChannelState;
-
-struct PITState {
- PITChannelState channels[3];
-};
-
-static PITState pit_state;
-
-static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
-
-static int pit_get_count(PITChannelState *s)
-{
- uint64_t d;
- int counter;
-
- d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
- switch(s->mode) {
- case 0:
- case 1:
- case 4:
- case 5:
- counter = (s->count - d) & 0xffff;
- break;
- case 3:
- /* XXX: may be incorrect for odd counts */
- counter = s->count - ((2 * d) % s->count);
- break;
- default:
- counter = s->count - (d % s->count);
- break;
- }
- return counter;
-}
-
-/* get pit output bit */
-static int pit_get_out1(PITChannelState *s, int64_t current_time)
-{
- uint64_t d;
- int out;
-
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
- switch(s->mode) {
- default:
- case 0:
- out = (d >= s->count);
- break;
- case 1:
- out = (d < s->count);
- break;
- case 2:
- if ((d % s->count) == 0 && d != 0)
- out = 1;
- else
- out = 0;
- break;
- case 3:
- out = (d % s->count) < ((s->count + 1) >> 1);
- break;
- case 4:
- case 5:
- out = (d == s->count);
- break;
- }
- return out;
-}
-
-int pit_get_out(PITState *pit, int channel, int64_t current_time)
-{
- PITChannelState *s = &pit->channels[channel];
- return pit_get_out1(s, current_time);
-}
-
-/* return -1 if no transition will occur. */
-static int64_t pit_get_next_transition_time(PITChannelState *s,
- int64_t current_time)
-{
- uint64_t d, next_time, base;
- int period2;
-
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
- switch(s->mode) {
- default:
- case 0:
- case 1:
- if (d < s->count)
- next_time = s->count;
- else
- return -1;
- break;
- case 2:
- base = (d / s->count) * s->count;
- if ((d - base) == 0 && d != 0)
- next_time = base + s->count;
- else
- next_time = base + s->count + 1;
- break;
- case 3:
- base = (d / s->count) * s->count;
- period2 = ((s->count + 1) >> 1);
- if ((d - base) < period2)
- next_time = base + period2;
- else
- next_time = base + s->count;
- break;
- case 4:
- case 5:
- if (d < s->count)
- next_time = s->count;
- else if (d == s->count)
- next_time = s->count + 1;
- else
- return -1;
- break;
- }
- /* convert to timer units */
- next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
- /* fix potential rounding problems */
- /* XXX: better solution: use a clock at PIT_FREQ Hz */
- if (next_time <= current_time)
- next_time = current_time + 1;
- return next_time;
-}
-
-/* val must be 0 or 1 */
-void pit_set_gate(PITState *pit, int channel, int val)
-{
- PITChannelState *s = &pit->channels[channel];
-
- switch(s->mode) {
- default:
- case 0:
- case 4:
- /* XXX: just disable/enable counting */
- break;
- case 1:
- case 5:
- if (s->gate < val) {
- /* restart counting on rising edge */
- s->count_load_time = qemu_get_clock(vm_clock);
- pit_irq_timer_update(s, s->count_load_time);
- }
- break;
- case 2:
- case 3:
- if (s->gate < val) {
- /* restart counting on rising edge */
- s->count_load_time = qemu_get_clock(vm_clock);
- pit_irq_timer_update(s, s->count_load_time);
- }
- /* XXX: disable/enable counting */
- break;
- }
- s->gate = val;
-}
-
-int pit_get_gate(PITState *pit, int channel)
-{
- PITChannelState *s = &pit->channels[channel];
- return s->gate;
-}
-
-int pit_get_initial_count(PITState *pit, int channel)
-{
- PITChannelState *s = &pit->channels[channel];
- return s->count;
-}
-
-int pit_get_mode(PITState *pit, int channel)
-{
- PITChannelState *s = &pit->channels[channel];
- return s->mode;
-}
-
-static inline void pit_load_count(PITChannelState *s, int val)
-{
- if (val == 0)
- val = 0x10000;
- s->count_load_time = qemu_get_clock(vm_clock);
- s->count = val;
- pit_irq_timer_update(s, s->count_load_time);
-}
-
-/* if already latched, do not latch again */
-static void pit_latch_count(PITChannelState *s)
-{
- if (!s->count_latched) {
- s->latched_count = pit_get_count(s);
- s->count_latched = s->rw_mode;
- }
-}
-
-static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PITState *pit = opaque;
- int channel, access;
- PITChannelState *s;
-
- addr &= 3;
- if (addr == 3) {
- channel = val >> 6;
- if (channel == 3) {
- /* read back command */
- for(channel = 0; channel < 3; channel++) {
- s = &pit->channels[channel];
- if (val & (2 << channel)) {
- if (!(val & 0x20)) {
- pit_latch_count(s);
- }
- if (!(val & 0x10) && !s->status_latched) {
- /* status latch */
- /* XXX: add BCD and null count */
- s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
- (s->rw_mode << 4) |
- (s->mode << 1) |
- s->bcd;
- s->status_latched = 1;
- }
- }
- }
- } else {
- s = &pit->channels[channel];
- access = (val >> 4) & 3;
- if (access == 0) {
- pit_latch_count(s);
- } else {
- s->rw_mode = access;
- s->read_state = access;
- s->write_state = access;
-
- s->mode = (val >> 1) & 7;
- s->bcd = val & 1;
- /* XXX: update irq timer ? */
- }
- }
- } else {
- s = &pit->channels[addr];
- switch(s->write_state) {
- default:
- case RW_STATE_LSB:
- pit_load_count(s, val);
- break;
- case RW_STATE_MSB:
- pit_load_count(s, val << 8);
- break;
- case RW_STATE_WORD0:
- s->write_latch = val;
- s->write_state = RW_STATE_WORD1;
- break;
- case RW_STATE_WORD1:
- pit_load_count(s, s->write_latch | (val << 8));
- s->write_state = RW_STATE_WORD0;
- break;
- }
- }
-}
-
-static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
-{
- PITState *pit = opaque;
- int ret, count;
- PITChannelState *s;
-
- addr &= 3;
- s = &pit->channels[addr];
- if (s->status_latched) {
- s->status_latched = 0;
- ret = s->status;
- } else if (s->count_latched) {
- switch(s->count_latched) {
- default:
- case RW_STATE_LSB:
- ret = s->latched_count & 0xff;
- s->count_latched = 0;
- break;
- case RW_STATE_MSB:
- ret = s->latched_count >> 8;
- s->count_latched = 0;
- break;
- case RW_STATE_WORD0:
- ret = s->latched_count & 0xff;
- s->count_latched = RW_STATE_MSB;
- break;
- }
- } else {
- switch(s->read_state) {
- default:
- case RW_STATE_LSB:
- count = pit_get_count(s);
- ret = count & 0xff;
- break;
- case RW_STATE_MSB:
- count = pit_get_count(s);
- ret = (count >> 8) & 0xff;
- break;
- case RW_STATE_WORD0:
- count = pit_get_count(s);
- ret = count & 0xff;
- s->read_state = RW_STATE_WORD1;
- break;
- case RW_STATE_WORD1:
- count = pit_get_count(s);
- ret = (count >> 8) & 0xff;
- s->read_state = RW_STATE_WORD0;
- break;
- }
- }
- return ret;
-}
-
-static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
-{
- int64_t expire_time;
- int irq_level;
-
- if (!s->irq_timer)
- return;
- expire_time = pit_get_next_transition_time(s, current_time);
- irq_level = pit_get_out1(s, current_time);
- pic_set_irq(s->irq, irq_level);
-#ifdef DEBUG_PIT
- printf("irq_level=%d next_delay=%f\n",
- irq_level,
- (double)(expire_time - current_time) / ticks_per_sec);
-#endif
- s->next_transition_time = expire_time;
- if (expire_time != -1)
- qemu_mod_timer(s->irq_timer, expire_time);
- else
- qemu_del_timer(s->irq_timer);
-}
-
-static void pit_irq_timer(void *opaque)
-{
- PITChannelState *s = opaque;
-
- pit_irq_timer_update(s, s->next_transition_time);
-}
-
-static void pit_save(QEMUFile *f, void *opaque)
-{
- PITState *pit = opaque;
- PITChannelState *s;
- int i;
-
- for(i = 0; i < 3; i++) {
- s = &pit->channels[i];
- qemu_put_be32s(f, &s->count);
- qemu_put_be16s(f, &s->latched_count);
- qemu_put_8s(f, &s->count_latched);
- qemu_put_8s(f, &s->status_latched);
- qemu_put_8s(f, &s->status);
- qemu_put_8s(f, &s->read_state);
- qemu_put_8s(f, &s->write_state);
- qemu_put_8s(f, &s->write_latch);
- qemu_put_8s(f, &s->rw_mode);
- qemu_put_8s(f, &s->mode);
- qemu_put_8s(f, &s->bcd);
- qemu_put_8s(f, &s->gate);
- qemu_put_be64s(f, &s->count_load_time);
- if (s->irq_timer) {
- qemu_put_be64s(f, &s->next_transition_time);
- qemu_put_timer(f, s->irq_timer);
- }
- }
-}
-
-static int pit_load(QEMUFile *f, void *opaque, int version_id)
-{
- PITState *pit = opaque;
- PITChannelState *s;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- for(i = 0; i < 3; i++) {
- s = &pit->channels[i];
- qemu_get_be32s(f, &s->count);
- qemu_get_be16s(f, &s->latched_count);
- qemu_get_8s(f, &s->count_latched);
- qemu_get_8s(f, &s->status_latched);
- qemu_get_8s(f, &s->status);
- qemu_get_8s(f, &s->read_state);
- qemu_get_8s(f, &s->write_state);
- qemu_get_8s(f, &s->write_latch);
- qemu_get_8s(f, &s->rw_mode);
- qemu_get_8s(f, &s->mode);
- qemu_get_8s(f, &s->bcd);
- qemu_get_8s(f, &s->gate);
- qemu_get_be64s(f, &s->count_load_time);
- if (s->irq_timer) {
- qemu_get_be64s(f, &s->next_transition_time);
- qemu_get_timer(f, s->irq_timer);
- }
- }
- return 0;
-}
-
-static void pit_reset(void *opaque)
-{
- PITState *pit = opaque;
- PITChannelState *s;
- int i;
-
- for(i = 0;i < 3; i++) {
- s = &pit->channels[i];
- s->mode = 3;
- s->gate = (i != 2);
- pit_load_count(s, 0);
- }
-}
-
-PITState *pit_init(int base, int irq)
-{
- PITState *pit = &pit_state;
- PITChannelState *s;
-
- s = &pit->channels[0];
- /* the timer 0 is connected to an IRQ */
- s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
- s->irq = irq;
-
- register_savevm("i8254", base, 1, pit_save, pit_load, pit);
-
- qemu_register_reset(pit_reset, pit);
- register_ioport_write(base, 4, 1, pit_ioport_write, pit);
- register_ioport_read(base, 3, 1, pit_ioport_read, pit);
-
- pit_reset(pit);
-
- return pit;
-}
diff --git a/hw/i8259.c b/hw/i8259.c
deleted file mode 100644
index c747f10..0000000
--- a/hw/i8259.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * QEMU 8259 interrupt controller emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug PIC */
-//#define DEBUG_PIC
-
-//#define DEBUG_IRQ_LATENCY
-//#define DEBUG_IRQ_COUNT
-
-typedef struct PicState {
- uint8_t last_irr; /* edge detection */
- uint8_t irr; /* interrupt request register */
- uint8_t imr; /* interrupt mask register */
- uint8_t isr; /* interrupt service register */
- uint8_t priority_add; /* highest irq priority */
- uint8_t irq_base;
- uint8_t read_reg_select;
- uint8_t poll;
- uint8_t special_mask;
- uint8_t init_state;
- uint8_t auto_eoi;
- uint8_t rotate_on_auto_eoi;
- uint8_t special_fully_nested_mode;
- uint8_t init4; /* true if 4 byte init */
- uint8_t elcr; /* PIIX edge/trigger selection*/
- uint8_t elcr_mask;
- PicState2 *pics_state;
-} PicState;
-
-struct PicState2 {
- /* 0 is master pic, 1 is slave pic */
- /* XXX: better separation between the two pics */
- PicState pics[2];
- IRQRequestFunc *irq_request;
- void *irq_request_opaque;
- /* IOAPIC callback support */
- SetIRQFunc *alt_irq_func;
- void *alt_irq_opaque;
-};
-
-#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
-static int irq_level[16];
-#endif
-#ifdef DEBUG_IRQ_COUNT
-static uint64_t irq_count[16];
-#endif
-
-/* set irq level. If an edge is detected, then the IRR is set to 1 */
-static inline void pic_set_irq1(PicState *s, int irq, int level)
-{
- int mask;
- mask = 1 << irq;
- if (s->elcr & mask) {
- /* level triggered */
- if (level) {
- s->irr |= mask;
- s->last_irr |= mask;
- } else {
- s->irr &= ~mask;
- s->last_irr &= ~mask;
- }
- } else {
- /* edge triggered */
- if (level) {
- if ((s->last_irr & mask) == 0)
- s->irr |= mask;
- s->last_irr |= mask;
- } else {
- s->last_irr &= ~mask;
- }
- }
-}
-
-/* return the highest priority found in mask (highest = smallest
- number). Return 8 if no irq */
-static inline int get_priority(PicState *s, int mask)
-{
- int priority;
- if (mask == 0)
- return 8;
- priority = 0;
- while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
- priority++;
- return priority;
-}
-
-/* return the pic wanted interrupt. return -1 if none */
-static int pic_get_irq(PicState *s)
-{
- int mask, cur_priority, priority;
-
- mask = s->irr & ~s->imr;
- priority = get_priority(s, mask);
- if (priority == 8)
- return -1;
- /* compute current priority. If special fully nested mode on the
- master, the IRQ coming from the slave is not taken into account
- for the priority computation. */
- mask = s->isr;
- if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
- mask &= ~(1 << 2);
- cur_priority = get_priority(s, mask);
- if (priority < cur_priority) {
- /* higher priority found: an irq should be generated */
- return (priority + s->priority_add) & 7;
- } else {
- return -1;
- }
-}
-
-/* raise irq to CPU if necessary. must be called every time the active
- irq may change */
-/* XXX: should not export it, but it is needed for an APIC kludge */
-void pic_update_irq(PicState2 *s)
-{
- int irq2, irq;
-
- /* first look at slave pic */
- irq2 = pic_get_irq(&s->pics[1]);
- if (irq2 >= 0) {
- /* if irq request by slave pic, signal master PIC */
- pic_set_irq1(&s->pics[0], 2, 1);
- pic_set_irq1(&s->pics[0], 2, 0);
- }
- /* look at requested irq */
- irq = pic_get_irq(&s->pics[0]);
- if (irq >= 0) {
-#if defined(DEBUG_PIC)
- {
- int i;
- for(i = 0; i < 2; i++) {
- printf("pic%d: imr=%x irr=%x padd=%d\n",
- i, s->pics[i].imr, s->pics[i].irr,
- s->pics[i].priority_add);
-
- }
- }
- printf("pic: cpu_interrupt\n");
-#endif
- s->irq_request(s->irq_request_opaque, 1);
- }
-}
-
-#ifdef DEBUG_IRQ_LATENCY
-int64_t irq_time[16];
-#endif
-
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
- PicState2 *s = opaque;
-
-#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
- if (level != irq_level[irq]) {
-#if defined(DEBUG_PIC)
- printf("pic_set_irq: irq=%d level=%d\n", irq, level);
-#endif
- irq_level[irq] = level;
-#ifdef DEBUG_IRQ_COUNT
- if (level == 1)
- irq_count[irq]++;
-#endif
- }
-#endif
-#ifdef DEBUG_IRQ_LATENCY
- if (level) {
- irq_time[irq] = qemu_get_clock(vm_clock);
- }
-#endif
- pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
- /* used for IOAPIC irqs */
- if (s->alt_irq_func)
- s->alt_irq_func(s->alt_irq_opaque, irq, level);
- pic_update_irq(s);
-}
-
-/* obsolete function */
-void pic_set_irq(int irq, int level)
-{
- pic_set_irq_new(isa_pic, irq, level);
-}
-
-/* acknowledge interrupt 'irq' */
-static inline void pic_intack(PicState *s, int irq)
-{
- if (s->auto_eoi) {
- if (s->rotate_on_auto_eoi)
- s->priority_add = (irq + 1) & 7;
- } else {
- s->isr |= (1 << irq);
- }
- /* We don't clear a level sensitive interrupt here */
- if (!(s->elcr & (1 << irq)))
- s->irr &= ~(1 << irq);
-}
-
-int pic_read_irq(PicState2 *s)
-{
- int irq, irq2, intno;
-
- irq = pic_get_irq(&s->pics[0]);
- if (irq >= 0) {
- pic_intack(&s->pics[0], irq);
- if (irq == 2) {
- irq2 = pic_get_irq(&s->pics[1]);
- if (irq2 >= 0) {
- pic_intack(&s->pics[1], irq2);
- } else {
- /* spurious IRQ on slave controller */
- irq2 = 7;
- }
- intno = s->pics[1].irq_base + irq2;
- irq = irq2 + 8;
- } else {
- intno = s->pics[0].irq_base + irq;
- }
- } else {
- /* spurious IRQ on host controller */
- irq = 7;
- intno = s->pics[0].irq_base + irq;
- }
- pic_update_irq(s);
-
-#ifdef DEBUG_IRQ_LATENCY
- printf("IRQ%d latency=%0.3fus\n",
- irq,
- (double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / ticks_per_sec);
-#endif
-#if defined(DEBUG_PIC)
- printf("pic_interrupt: irq=%d\n", irq);
-#endif
- return intno;
-}
-
-static void pic_reset(void *opaque)
-{
- PicState *s = opaque;
-
- s->last_irr = 0;
- s->irr = 0;
- s->imr = 0;
- s->isr = 0;
- s->priority_add = 0;
- s->irq_base = 0;
- s->read_reg_select = 0;
- s->poll = 0;
- s->special_mask = 0;
- s->init_state = 0;
- s->auto_eoi = 0;
- s->rotate_on_auto_eoi = 0;
- s->special_fully_nested_mode = 0;
- s->init4 = 0;
- /* Note: ELCR is not reset */
-}
-
-static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PicState *s = opaque;
- int priority, cmd, irq;
-
-#ifdef DEBUG_PIC
- printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
-#endif
- addr &= 1;
- if (addr == 0) {
- if (val & 0x10) {
- /* init */
- pic_reset(s);
- /* deassert a pending interrupt */
- s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
- s->init_state = 1;
- s->init4 = val & 1;
- if (val & 0x02)
- hw_error("single mode not supported");
- if (val & 0x08)
- hw_error("level sensitive irq not supported");
- } else if (val & 0x08) {
- if (val & 0x04)
- s->poll = 1;
- if (val & 0x02)
- s->read_reg_select = val & 1;
- if (val & 0x40)
- s->special_mask = (val >> 5) & 1;
- } else {
- cmd = val >> 5;
- switch(cmd) {
- case 0:
- case 4:
- s->rotate_on_auto_eoi = cmd >> 2;
- break;
- case 1: /* end of interrupt */
- case 5:
- priority = get_priority(s, s->isr);
- if (priority != 8) {
- irq = (priority + s->priority_add) & 7;
- s->isr &= ~(1 << irq);
- if (cmd == 5)
- s->priority_add = (irq + 1) & 7;
- pic_update_irq(s->pics_state);
- }
- break;
- case 3:
- irq = val & 7;
- s->isr &= ~(1 << irq);
- pic_update_irq(s->pics_state);
- break;
- case 6:
- s->priority_add = (val + 1) & 7;
- pic_update_irq(s->pics_state);
- break;
- case 7:
- irq = val & 7;
- s->isr &= ~(1 << irq);
- s->priority_add = (irq + 1) & 7;
- pic_update_irq(s->pics_state);
- break;
- default:
- /* no operation */
- break;
- }
- }
- } else {
- switch(s->init_state) {
- case 0:
- /* normal mode */
- s->imr = val;
- pic_update_irq(s->pics_state);
- break;
- case 1:
- s->irq_base = val & 0xf8;
- s->init_state = 2;
- break;
- case 2:
- if (s->init4) {
- s->init_state = 3;
- } else {
- s->init_state = 0;
- }
- break;
- case 3:
- s->special_fully_nested_mode = (val >> 4) & 1;
- s->auto_eoi = (val >> 1) & 1;
- s->init_state = 0;
- break;
- }
- }
-}
-
-static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
-{
- int ret;
-
- ret = pic_get_irq(s);
- if (ret >= 0) {
- if (addr1 >> 7) {
- s->pics_state->pics[0].isr &= ~(1 << 2);
- s->pics_state->pics[0].irr &= ~(1 << 2);
- }
- s->irr &= ~(1 << ret);
- s->isr &= ~(1 << ret);
- if (addr1 >> 7 || ret != 2)
- pic_update_irq(s->pics_state);
- } else {
- ret = 0x07;
- pic_update_irq(s->pics_state);
- }
-
- return ret;
-}
-
-static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
-{
- PicState *s = opaque;
- unsigned int addr;
- int ret;
-
- addr = addr1;
- addr &= 1;
- if (s->poll) {
- ret = pic_poll_read(s, addr1);
- s->poll = 0;
- } else {
- if (addr == 0) {
- if (s->read_reg_select)
- ret = s->isr;
- else
- ret = s->irr;
- } else {
- ret = s->imr;
- }
- }
-#ifdef DEBUG_PIC
- printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
-#endif
- return ret;
-}
-
-/* memory mapped interrupt status */
-/* XXX: may be the same than pic_read_irq() */
-uint32_t pic_intack_read(PicState2 *s)
-{
- int ret;
-
- ret = pic_poll_read(&s->pics[0], 0x00);
- if (ret == 2)
- ret = pic_poll_read(&s->pics[1], 0x80) + 8;
- /* Prepare for ISR read */
- s->pics[0].read_reg_select = 1;
-
- return ret;
-}
-
-static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PicState *s = opaque;
- s->elcr = val & s->elcr_mask;
-}
-
-static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
-{
- PicState *s = opaque;
- return s->elcr;
-}
-
-static void pic_save(QEMUFile *f, void *opaque)
-{
- PicState *s = opaque;
-
- qemu_put_8s(f, &s->last_irr);
- qemu_put_8s(f, &s->irr);
- qemu_put_8s(f, &s->imr);
- qemu_put_8s(f, &s->isr);
- qemu_put_8s(f, &s->priority_add);
- qemu_put_8s(f, &s->irq_base);
- qemu_put_8s(f, &s->read_reg_select);
- qemu_put_8s(f, &s->poll);
- qemu_put_8s(f, &s->special_mask);
- qemu_put_8s(f, &s->init_state);
- qemu_put_8s(f, &s->auto_eoi);
- qemu_put_8s(f, &s->rotate_on_auto_eoi);
- qemu_put_8s(f, &s->special_fully_nested_mode);
- qemu_put_8s(f, &s->init4);
- qemu_put_8s(f, &s->elcr);
-}
-
-static int pic_load(QEMUFile *f, void *opaque, int version_id)
-{
- PicState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_8s(f, &s->last_irr);
- qemu_get_8s(f, &s->irr);
- qemu_get_8s(f, &s->imr);
- qemu_get_8s(f, &s->isr);
- qemu_get_8s(f, &s->priority_add);
- qemu_get_8s(f, &s->irq_base);
- qemu_get_8s(f, &s->read_reg_select);
- qemu_get_8s(f, &s->poll);
- qemu_get_8s(f, &s->special_mask);
- qemu_get_8s(f, &s->init_state);
- qemu_get_8s(f, &s->auto_eoi);
- qemu_get_8s(f, &s->rotate_on_auto_eoi);
- qemu_get_8s(f, &s->special_fully_nested_mode);
- qemu_get_8s(f, &s->init4);
- qemu_get_8s(f, &s->elcr);
- return 0;
-}
-
-/* XXX: add generic master/slave system */
-static void pic_init1(int io_addr, int elcr_addr, PicState *s)
-{
- register_ioport_write(io_addr, 2, 1, pic_ioport_write, s);
- register_ioport_read(io_addr, 2, 1, pic_ioport_read, s);
- if (elcr_addr >= 0) {
- register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
- register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
- }
- register_savevm("i8259", io_addr, 1, pic_save, pic_load, s);
- qemu_register_reset(pic_reset, s);
-}
-
-void pic_info(void)
-{
- int i;
- PicState *s;
-
- if (!isa_pic)
- return;
-
- for(i=0;i<2;i++) {
- s = &isa_pic->pics[i];
- term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
- i, s->irr, s->imr, s->isr, s->priority_add,
- s->irq_base, s->read_reg_select, s->elcr,
- s->special_fully_nested_mode);
- }
-}
-
-void irq_info(void)
-{
-#ifndef DEBUG_IRQ_COUNT
- term_printf("irq statistic code not compiled.\n");
-#else
- int i;
- int64_t count;
-
- term_printf("IRQ statistics:\n");
- for (i = 0; i < 16; i++) {
- count = irq_count[i];
- if (count > 0)
- term_printf("%2d: %" PRId64 "\n", i, count);
- }
-#endif
-}
-
-PicState2 *pic_init(IRQRequestFunc *irq_request, void *irq_request_opaque)
-{
- PicState2 *s;
- s = qemu_mallocz(sizeof(PicState2));
- if (!s)
- return NULL;
- pic_init1(0x20, 0x4d0, &s->pics[0]);
- pic_init1(0xa0, 0x4d1, &s->pics[1]);
- s->pics[0].elcr_mask = 0xf8;
- s->pics[1].elcr_mask = 0xde;
- s->irq_request = irq_request;
- s->irq_request_opaque = irq_request_opaque;
- s->pics[0].pics_state = s;
- s->pics[1].pics_state = s;
- return s;
-}
-
-void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
- void *alt_irq_opaque)
-{
- s->alt_irq_func = alt_irq_func;
- s->alt_irq_opaque = alt_irq_opaque;
-}
diff --git a/hw/ide.c b/hw/ide.c
deleted file mode 100644
index debbc0f..0000000
--- a/hw/ide.c
+++ /dev/null
@@ -1,2535 +0,0 @@
-/*
- * QEMU IDE disk and CD-ROM Emulator
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug IDE devices */
-//#define DEBUG_IDE
-//#define DEBUG_IDE_ATAPI
-
-/* Bits of HD_STATUS */
-#define ERR_STAT 0x01
-#define INDEX_STAT 0x02
-#define ECC_STAT 0x04 /* Corrected error */
-#define DRQ_STAT 0x08
-#define SEEK_STAT 0x10
-#define SRV_STAT 0x10
-#define WRERR_STAT 0x20
-#define READY_STAT 0x40
-#define BUSY_STAT 0x80
-
-/* Bits for HD_ERROR */
-#define MARK_ERR 0x01 /* Bad address mark */
-#define TRK0_ERR 0x02 /* couldn't find track 0 */
-#define ABRT_ERR 0x04 /* Command aborted */
-#define MCR_ERR 0x08 /* media change request */
-#define ID_ERR 0x10 /* ID field not found */
-#define MC_ERR 0x20 /* media changed */
-#define ECC_ERR 0x40 /* Uncorrectable ECC error */
-#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
-#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
-
-/* Bits of HD_NSECTOR */
-#define CD 0x01
-#define IO 0x02
-#define REL 0x04
-#define TAG_MASK 0xf8
-
-#define IDE_CMD_RESET 0x04
-#define IDE_CMD_DISABLE_IRQ 0x02
-
-/* ATA/ATAPI Commands pre T13 Spec */
-#define WIN_NOP 0x00
-/*
- * 0x01->0x02 Reserved
- */
-#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
-/*
- * 0x04->0x07 Reserved
- */
-#define WIN_SRST 0x08 /* ATAPI soft reset command */
-#define WIN_DEVICE_RESET 0x08
-/*
- * 0x09->0x0F Reserved
- */
-#define WIN_RECAL 0x10
-#define WIN_RESTORE WIN_RECAL
-/*
- * 0x10->0x1F Reserved
- */
-#define WIN_READ 0x20 /* 28-Bit */
-#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */
-#define WIN_READ_LONG 0x22 /* 28-Bit */
-#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */
-#define WIN_READ_EXT 0x24 /* 48-Bit */
-#define WIN_READDMA_EXT 0x25 /* 48-Bit */
-#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */
-#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
-/*
- * 0x28
- */
-#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
-/*
- * 0x2A->0x2F Reserved
- */
-#define WIN_WRITE 0x30 /* 28-Bit */
-#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */
-#define WIN_WRITE_LONG 0x32 /* 28-Bit */
-#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */
-#define WIN_WRITE_EXT 0x34 /* 48-Bit */
-#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
-#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
-#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
-#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
-#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
-/*
- * 0x3A->0x3B Reserved
- */
-#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */
-/*
- * 0x3D->0x3F Reserved
- */
-#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
-#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */
-#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
-/*
- * 0x43->0x4F Reserved
- */
-#define WIN_FORMAT 0x50
-/*
- * 0x51->0x5F Reserved
- */
-#define WIN_INIT 0x60
-/*
- * 0x61->0x5F Reserved
- */
-#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */
-#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
-#define WIN_DIAGNOSE 0x90
-#define WIN_SPECIFY 0x91 /* set drive geometry translation */
-#define WIN_DOWNLOAD_MICROCODE 0x92
-#define WIN_STANDBYNOW2 0x94
-#define WIN_STANDBY2 0x96
-#define WIN_SETIDLE2 0x97
-#define WIN_CHECKPOWERMODE2 0x98
-#define WIN_SLEEPNOW2 0x99
-/*
- * 0x9A VENDOR
- */
-#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
-#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
-#define WIN_QUEUED_SERVICE 0xA2
-#define WIN_SMART 0xB0 /* self-monitoring and reporting */
-#define CFA_ERASE_SECTORS 0xC0
-#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
-#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
-#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
-#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */
-#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
-#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */
-#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
-#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */
-#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
-#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
-#define WIN_GETMEDIASTATUS 0xDA
-#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */
-#define WIN_POSTBOOT 0xDC
-#define WIN_PREBOOT 0xDD
-#define WIN_DOORLOCK 0xDE /* lock door on removable drives */
-#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */
-#define WIN_STANDBYNOW1 0xE0
-#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
-#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
-#define WIN_SETIDLE1 0xE3
-#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
-#define WIN_CHECKPOWERMODE1 0xE5
-#define WIN_SLEEPNOW1 0xE6
-#define WIN_FLUSH_CACHE 0xE7
-#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
-#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */
- /* SET_FEATURES 0x22 or 0xDD */
-#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
-#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
-#define WIN_MEDIAEJECT 0xED
-#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
-#define WIN_SETFEATURES 0xEF /* set special drive features */
-#define EXABYTE_ENABLE_NEST 0xF0
-#define WIN_SECURITY_SET_PASS 0xF1
-#define WIN_SECURITY_UNLOCK 0xF2
-#define WIN_SECURITY_ERASE_PREPARE 0xF3
-#define WIN_SECURITY_ERASE_UNIT 0xF4
-#define WIN_SECURITY_FREEZE_LOCK 0xF5
-#define WIN_SECURITY_DISABLE 0xF6
-#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
-#define WIN_SET_MAX 0xF9
-#define DISABLE_SEAGATE 0xFB
-
-/* set to 1 set disable mult support */
-#define MAX_MULT_SECTORS 16
-
-/* ATAPI defines */
-
-#define ATAPI_PACKET_SIZE 12
-
-/* The generic packet command opcodes for CD/DVD Logical Units,
- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-#define GPCMD_BLANK 0xa1
-#define GPCMD_CLOSE_TRACK 0x5b
-#define GPCMD_FLUSH_CACHE 0x35
-#define GPCMD_FORMAT_UNIT 0x04
-#define GPCMD_GET_CONFIGURATION 0x46
-#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
-#define GPCMD_GET_PERFORMANCE 0xac
-#define GPCMD_INQUIRY 0x12
-#define GPCMD_LOAD_UNLOAD 0xa6
-#define GPCMD_MECHANISM_STATUS 0xbd
-#define GPCMD_MODE_SELECT_10 0x55
-#define GPCMD_MODE_SENSE_10 0x5a
-#define GPCMD_PAUSE_RESUME 0x4b
-#define GPCMD_PLAY_AUDIO_10 0x45
-#define GPCMD_PLAY_AUDIO_MSF 0x47
-#define GPCMD_PLAY_AUDIO_TI 0x48
-#define GPCMD_PLAY_CD 0xbc
-#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define GPCMD_READ_10 0x28
-#define GPCMD_READ_12 0xa8
-#define GPCMD_READ_CDVD_CAPACITY 0x25
-#define GPCMD_READ_CD 0xbe
-#define GPCMD_READ_CD_MSF 0xb9
-#define GPCMD_READ_DISC_INFO 0x51
-#define GPCMD_READ_DVD_STRUCTURE 0xad
-#define GPCMD_READ_FORMAT_CAPACITIES 0x23
-#define GPCMD_READ_HEADER 0x44
-#define GPCMD_READ_TRACK_RZONE_INFO 0x52
-#define GPCMD_READ_SUBCHANNEL 0x42
-#define GPCMD_READ_TOC_PMA_ATIP 0x43
-#define GPCMD_REPAIR_RZONE_TRACK 0x58
-#define GPCMD_REPORT_KEY 0xa4
-#define GPCMD_REQUEST_SENSE 0x03
-#define GPCMD_RESERVE_RZONE_TRACK 0x53
-#define GPCMD_SCAN 0xba
-#define GPCMD_SEEK 0x2b
-#define GPCMD_SEND_DVD_STRUCTURE 0xad
-#define GPCMD_SEND_EVENT 0xa2
-#define GPCMD_SEND_KEY 0xa3
-#define GPCMD_SEND_OPC 0x54
-#define GPCMD_SET_READ_AHEAD 0xa7
-#define GPCMD_SET_STREAMING 0xb6
-#define GPCMD_START_STOP_UNIT 0x1b
-#define GPCMD_STOP_PLAY_SCAN 0x4e
-#define GPCMD_TEST_UNIT_READY 0x00
-#define GPCMD_VERIFY_10 0x2f
-#define GPCMD_WRITE_10 0x2a
-#define GPCMD_WRITE_AND_VERIFY_10 0x2e
-/* This is listed as optional in ATAPI 2.6, but is (curiously)
- * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
- * Table 377 as an MMC command for SCSi devices though... Most ATAPI
- * drives support it. */
-#define GPCMD_SET_SPEED 0xbb
-/* This seems to be a SCSI specific CD-ROM opcode
- * to play data at track/index */
-#define GPCMD_PLAYAUDIO_TI 0x48
-/*
- * From MS Media Status Notification Support Specification. For
- * older drives only.
- */
-#define GPCMD_GET_MEDIA_STATUS 0xda
-
-/* Mode page codes for mode sense/set */
-#define GPMODE_R_W_ERROR_PAGE 0x01
-#define GPMODE_WRITE_PARMS_PAGE 0x05
-#define GPMODE_AUDIO_CTL_PAGE 0x0e
-#define GPMODE_POWER_PAGE 0x1a
-#define GPMODE_FAULT_FAIL_PAGE 0x1c
-#define GPMODE_TO_PROTECT_PAGE 0x1d
-#define GPMODE_CAPABILITIES_PAGE 0x2a
-#define GPMODE_ALL_PAGES 0x3f
-/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
- * of MODE_SENSE_POWER_PAGE */
-#define GPMODE_CDROM_PAGE 0x0d
-
-#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
-#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
-#define ATAPI_INT_REASON_REL 0x04
-#define ATAPI_INT_REASON_TAG 0xf8
-
-/* same constants as bochs */
-#define ASC_ILLEGAL_OPCODE 0x20
-#define ASC_LOGICAL_BLOCK_OOR 0x21
-#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
-#define ASC_MEDIUM_NOT_PRESENT 0x3a
-#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
-
-#define SENSE_NONE 0
-#define SENSE_NOT_READY 2
-#define SENSE_ILLEGAL_REQUEST 5
-#define SENSE_UNIT_ATTENTION 6
-
-struct IDEState;
-
-typedef void EndTransferFunc(struct IDEState *);
-
-/* NOTE: IDEState represents in fact one drive */
-typedef struct IDEState {
- /* ide config */
- int is_cdrom;
- int cylinders, heads, sectors;
- int64_t nb_sectors;
- int mult_sectors;
- int identify_set;
- uint16_t identify_data[256];
- SetIRQFunc *set_irq;
- void *irq_opaque;
- int irq;
- PCIDevice *pci_dev;
- struct BMDMAState *bmdma;
- int drive_serial;
- /* ide regs */
- uint8_t feature;
- uint8_t error;
- uint32_t nsector;
- uint8_t sector;
- uint8_t lcyl;
- uint8_t hcyl;
- /* other part of tf for lba48 support */
- uint8_t hob_feature;
- uint8_t hob_nsector;
- uint8_t hob_sector;
- uint8_t hob_lcyl;
- uint8_t hob_hcyl;
-
- uint8_t select;
- uint8_t status;
-
- /* 0x3f6 command, only meaningful for drive 0 */
- uint8_t cmd;
- /* set for lba48 access */
- uint8_t lba48;
- /* depends on bit 4 in select, only meaningful for drive 0 */
- struct IDEState *cur_drive;
- BlockDriverState *bs;
- /* ATAPI specific */
- uint8_t sense_key;
- uint8_t asc;
- int packet_transfer_size;
- int elementary_transfer_size;
- int io_buffer_index;
- int lba;
- int cd_sector_size;
- int atapi_dma; /* true if dma is requested for the packet cmd */
- /* ATA DMA state */
- int io_buffer_size;
- /* PIO transfer handling */
- int req_nb_sectors; /* number of sectors per interrupt */
- EndTransferFunc *end_transfer_func;
- uint8_t *data_ptr;
- uint8_t *data_end;
- uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
- QEMUTimer *sector_write_timer; /* only used for win2k instal hack */
- uint32_t irq_count; /* counts IRQs when using win2k install hack */
-} IDEState;
-
-#define BM_STATUS_DMAING 0x01
-#define BM_STATUS_ERROR 0x02
-#define BM_STATUS_INT 0x04
-
-#define BM_CMD_START 0x01
-#define BM_CMD_READ 0x08
-
-#define IDE_TYPE_PIIX3 0
-#define IDE_TYPE_CMD646 1
-
-/* CMD646 specific */
-#define MRDMODE 0x71
-#define MRDMODE_INTR_CH0 0x04
-#define MRDMODE_INTR_CH1 0x08
-#define MRDMODE_BLK_CH0 0x10
-#define MRDMODE_BLK_CH1 0x20
-#define UDIDETCR0 0x73
-#define UDIDETCR1 0x7B
-
-typedef int IDEDMAFunc(IDEState *s,
- target_phys_addr_t phys_addr,
- int transfer_size1);
-
-typedef struct BMDMAState {
- uint8_t cmd;
- uint8_t status;
- uint32_t addr;
-
- struct PCIIDEState *pci_dev;
- /* current transfer state */
- IDEState *ide_if;
- IDEDMAFunc *dma_cb;
-} BMDMAState;
-
-typedef struct PCIIDEState {
- PCIDevice dev;
- IDEState ide_if[4];
- BMDMAState bmdma[2];
- int type; /* see IDE_TYPE_xxx */
-} PCIIDEState;
-
-static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
-
-static void padstr(char *str, const char *src, int len)
-{
- int i, v;
- for(i = 0; i < len; i++) {
- if (*src)
- v = *src++;
- else
- v = ' ';
- *(char *)((long)str ^ 1) = v;
- str++;
- }
-}
-
-static void padstr8(uint8_t *buf, int buf_size, const char *src)
-{
- int i;
- for(i = 0; i < buf_size; i++) {
- if (*src)
- buf[i] = *src++;
- else
- buf[i] = ' ';
- }
-}
-
-static void put_le16(uint16_t *p, unsigned int v)
-{
- *p = cpu_to_le16(v);
-}
-
-static void ide_identify(IDEState *s)
-{
- uint16_t *p;
- unsigned int oldsize;
- char buf[20];
-
- if (s->identify_set) {
- memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
- return;
- }
-
- memset(s->io_buffer, 0, 512);
- p = (uint16_t *)s->io_buffer;
- put_le16(p + 0, 0x0040);
- put_le16(p + 1, s->cylinders);
- put_le16(p + 3, s->heads);
- put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
- put_le16(p + 5, 512); /* XXX: retired, remove ? */
- put_le16(p + 6, s->sectors);
- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
- padstr((uint8_t *)(p + 10), buf, 20); /* serial number */
- put_le16(p + 20, 3); /* XXX: retired, remove ? */
- put_le16(p + 21, 512); /* cache size in sectors */
- put_le16(p + 22, 4); /* ecc bytes */
- padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
- padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */
-#if MAX_MULT_SECTORS > 1
- put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
-#endif
- put_le16(p + 48, 1); /* dword I/O */
- put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */
- put_le16(p + 51, 0x200); /* PIO transfer cycle */
- put_le16(p + 52, 0x200); /* DMA transfer cycle */
- put_le16(p + 53, 1 | (1 << 1) | (1 << 2)); /* words 54-58,64-70,88 are valid */
- put_le16(p + 54, s->cylinders);
- put_le16(p + 55, s->heads);
- put_le16(p + 56, s->sectors);
- oldsize = s->cylinders * s->heads * s->sectors;
- put_le16(p + 57, oldsize);
- put_le16(p + 58, oldsize >> 16);
- if (s->mult_sectors)
- put_le16(p + 59, 0x100 | s->mult_sectors);
- put_le16(p + 60, s->nb_sectors);
- put_le16(p + 61, s->nb_sectors >> 16);
- put_le16(p + 63, 0x07); /* mdma0-2 supported */
- put_le16(p + 65, 120);
- put_le16(p + 66, 120);
- put_le16(p + 67, 120);
- put_le16(p + 68, 120);
- put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */
- put_le16(p + 81, 0x16); /* conforms to ata5 */
- put_le16(p + 82, (1 << 14));
- /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
- put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
- put_le16(p + 84, (1 << 14));
- put_le16(p + 85, (1 << 14));
- /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
- put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
- put_le16(p + 87, (1 << 14));
- put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
- put_le16(p + 93, 1 | (1 << 14) | 0x2000);
- put_le16(p + 100, s->nb_sectors);
- put_le16(p + 101, s->nb_sectors >> 16);
- put_le16(p + 102, s->nb_sectors >> 32);
- put_le16(p + 103, s->nb_sectors >> 48);
-
- memcpy(s->identify_data, p, sizeof(s->identify_data));
- s->identify_set = 1;
-}
-
-static void ide_atapi_identify(IDEState *s)
-{
- uint16_t *p;
- char buf[20];
-
- if (s->identify_set) {
- memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
- return;
- }
-
- memset(s->io_buffer, 0, 512);
- p = (uint16_t *)s->io_buffer;
- /* Removable CDROM, 50us response, 12 byte packets */
- put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
- snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
- padstr((uint8_t *)(p + 10), buf, 20); /* serial number */
- put_le16(p + 20, 3); /* buffer type */
- put_le16(p + 21, 512); /* cache size in sectors */
- put_le16(p + 22, 4); /* ecc bytes */
- padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
- padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */
- put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
- put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
- put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
- put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
- put_le16(p + 64, 1); /* PIO modes */
- put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
- put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
- put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
- put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */
-
- put_le16(p + 71, 30); /* in ns */
- put_le16(p + 72, 30); /* in ns */
-
- put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
-
- memcpy(s->identify_data, p, sizeof(s->identify_data));
- s->identify_set = 1;
-}
-
-static void ide_set_signature(IDEState *s)
-{
- s->select &= 0xf0; /* clear head */
- /* put signature */
- s->nsector = 1;
- s->sector = 1;
- if (s->is_cdrom) {
- s->lcyl = 0x14;
- s->hcyl = 0xeb;
- } else if (s->bs) {
- s->lcyl = 0;
- s->hcyl = 0;
- } else {
- s->lcyl = 0xff;
- s->hcyl = 0xff;
- }
-}
-
-static inline void ide_abort_command(IDEState *s)
-{
- s->status = READY_STAT | ERR_STAT;
- s->error = ABRT_ERR;
-}
-
-static inline void ide_set_irq(IDEState *s)
-{
- BMDMAState *bm = s->bmdma;
- if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
- if (bm) {
- bm->status |= BM_STATUS_INT;
- }
- s->set_irq(s->irq_opaque, s->irq, 1);
- }
-}
-
-/* prepare data transfer and tell what to do after */
-static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
- EndTransferFunc *end_transfer_func)
-{
- s->end_transfer_func = end_transfer_func;
- s->data_ptr = buf;
- s->data_end = buf + size;
- s->status |= DRQ_STAT;
-}
-
-static void ide_transfer_stop(IDEState *s)
-{
- s->end_transfer_func = ide_transfer_stop;
- s->data_ptr = s->io_buffer;
- s->data_end = s->io_buffer;
- s->status &= ~DRQ_STAT;
-}
-
-static int64_t ide_get_sector(IDEState *s)
-{
- int64_t sector_num;
- if (s->select & 0x40) {
- /* lba */
- if (!s->lba48) {
- sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
- (s->lcyl << 8) | s->sector;
- } else {
- sector_num = ((int64_t)s->hob_hcyl << 40) |
- ((int64_t) s->hob_lcyl << 32) |
- ((int64_t) s->hob_sector << 24) |
- ((int64_t) s->hcyl << 16) |
- ((int64_t) s->lcyl << 8) | s->sector;
- }
- } else {
- sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
- (s->select & 0x0f) * s->sectors + (s->sector - 1);
- }
- return sector_num;
-}
-
-static void ide_set_sector(IDEState *s, int64_t sector_num)
-{
- unsigned int cyl, r;
- if (s->select & 0x40) {
- if (!s->lba48) {
- s->select = (s->select & 0xf0) | (sector_num >> 24);
- s->hcyl = (sector_num >> 16);
- s->lcyl = (sector_num >> 8);
- s->sector = (sector_num);
- } else {
- s->sector = sector_num;
- s->lcyl = sector_num >> 8;
- s->hcyl = sector_num >> 16;
- s->hob_sector = sector_num >> 24;
- s->hob_lcyl = sector_num >> 32;
- s->hob_hcyl = sector_num >> 40;
- }
- } else {
- cyl = sector_num / (s->heads * s->sectors);
- r = sector_num % (s->heads * s->sectors);
- s->hcyl = cyl >> 8;
- s->lcyl = cyl;
- s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
- s->sector = (r % s->sectors) + 1;
- }
-}
-
-static void ide_sector_read(IDEState *s)
-{
- int64_t sector_num;
- int ret, n;
-
- s->status = READY_STAT | SEEK_STAT;
- s->error = 0; /* not needed by IDE spec, but needed by Windows */
- sector_num = ide_get_sector(s);
- n = s->nsector;
- if (n == 0) {
- /* no more sector to read from disk */
- ide_transfer_stop(s);
- } else {
-#if defined(DEBUG_IDE)
- printf("read sector=%Ld\n", sector_num);
-#endif
- if (n > s->req_nb_sectors)
- n = s->req_nb_sectors;
- ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
- ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
- ide_set_irq(s);
- ide_set_sector(s, sector_num + n);
- s->nsector -= n;
- }
-}
-
-static int ide_read_dma_cb(IDEState *s,
- target_phys_addr_t phys_addr,
- int transfer_size1)
-{
- int len, transfer_size, n;
- int64_t sector_num;
-
- transfer_size = transfer_size1;
- while (transfer_size > 0) {
- len = s->io_buffer_size - s->io_buffer_index;
- if (len <= 0) {
- /* transfert next data */
- n = s->nsector;
- if (n == 0)
- break;
- if (n > MAX_MULT_SECTORS)
- n = MAX_MULT_SECTORS;
- sector_num = ide_get_sector(s);
- bdrv_read(s->bs, sector_num, s->io_buffer, n);
- s->io_buffer_index = 0;
- s->io_buffer_size = n * 512;
- len = s->io_buffer_size;
- sector_num += n;
- ide_set_sector(s, sector_num);
- s->nsector -= n;
- }
- if (len > transfer_size)
- len = transfer_size;
- cpu_physical_memory_write(phys_addr,
- s->io_buffer + s->io_buffer_index, len);
- s->io_buffer_index += len;
- transfer_size -= len;
- phys_addr += len;
- }
- if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) {
- s->status = READY_STAT | SEEK_STAT;
- ide_set_irq(s);
-#ifdef DEBUG_IDE_ATAPI
- printf("dma status=0x%x\n", s->status);
-#endif
- return 0;
- }
- return transfer_size1 - transfer_size;
-}
-
-static void ide_sector_read_dma(IDEState *s)
-{
- s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
- s->io_buffer_index = 0;
- s->io_buffer_size = 0;
- ide_dma_start(s, ide_read_dma_cb);
-}
-
-static void ide_sector_write_timer_cb(void *opaque)
-{
- IDEState *s = opaque;
- ide_set_irq(s);
-}
-
-static void ide_sector_write(IDEState *s)
-{
- int64_t sector_num;
- int ret, n, n1;
-
- s->status = READY_STAT | SEEK_STAT;
- sector_num = ide_get_sector(s);
-#if defined(DEBUG_IDE)
- printf("write sector=%Ld\n", sector_num);
-#endif
- n = s->nsector;
- if (n > s->req_nb_sectors)
- n = s->req_nb_sectors;
- ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
- s->nsector -= n;
- if (s->nsector == 0) {
- /* no more sector to write */
- ide_transfer_stop(s);
- } else {
- n1 = s->nsector;
- if (n1 > s->req_nb_sectors)
- n1 = s->req_nb_sectors;
- ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
- }
- ide_set_sector(s, sector_num + n);
-
-#ifdef TARGET_I386
- if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
- /* It seems there is a bug in the Windows 2000 installer HDD
- IDE driver which fills the disk with empty logs when the
- IDE write IRQ comes too early. This hack tries to correct
- that at the expense of slower write performances. Use this
- option _only_ to install Windows 2000. You must disable it
- for normal use. */
- qemu_mod_timer(s->sector_write_timer,
- qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));
- } else
-#endif
- {
- ide_set_irq(s);
- }
-}
-
-static int ide_write_dma_cb(IDEState *s,
- target_phys_addr_t phys_addr,
- int transfer_size1)
-{
- int len, transfer_size, n;
- int64_t sector_num;
-
- transfer_size = transfer_size1;
- for(;;) {
- len = s->io_buffer_size - s->io_buffer_index;
- if (len == 0) {
- n = s->io_buffer_size >> 9;
- sector_num = ide_get_sector(s);
- bdrv_write(s->bs, sector_num, s->io_buffer,
- s->io_buffer_size >> 9);
- sector_num += n;
- ide_set_sector(s, sector_num);
- s->nsector -= n;
- n = s->nsector;
- if (n == 0) {
- /* end of transfer */
- s->status = READY_STAT | SEEK_STAT;
-#ifdef TARGET_I386
- if (win2k_install_hack && ((++s->irq_count % 16) == 0)) {
- /* It seems there is a bug in the Windows 2000 installer
- HDD IDE driver which fills the disk with empty logs
- when the IDE write IRQ comes too early. This hack tries
- to correct that at the expense of slower write
- performances. Use this option _only_ to install Windows
- 2000. You must disable it for normal use. */
- qemu_mod_timer(s->sector_write_timer,
- qemu_get_clock(vm_clock) + (ticks_per_sec / 1000));
- } else
-#endif
- ide_set_irq(s);
- return 0;
- }
- if (n > MAX_MULT_SECTORS)
- n = MAX_MULT_SECTORS;
- s->io_buffer_index = 0;
- s->io_buffer_size = n * 512;
- len = s->io_buffer_size;
- }
- if (transfer_size <= 0)
- break;
- if (len > transfer_size)
- len = transfer_size;
- cpu_physical_memory_read(phys_addr,
- s->io_buffer + s->io_buffer_index, len);
- s->io_buffer_index += len;
- transfer_size -= len;
- phys_addr += len;
- }
- return transfer_size1 - transfer_size;
-}
-
-static void ide_sector_write_dma(IDEState *s)
-{
- int n;
- s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
- n = s->nsector;
- if (n > MAX_MULT_SECTORS)
- n = MAX_MULT_SECTORS;
- s->io_buffer_index = 0;
- s->io_buffer_size = n * 512;
- ide_dma_start(s, ide_write_dma_cb);
-}
-
-static void ide_atapi_cmd_ok(IDEState *s)
-{
- s->error = 0;
- s->status = READY_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- ide_set_irq(s);
-}
-
-static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
-{
-#ifdef DEBUG_IDE_ATAPI
- printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
-#endif
- s->error = sense_key << 4;
- s->status = READY_STAT | ERR_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- s->sense_key = sense_key;
- s->asc = asc;
- ide_set_irq(s);
-}
-
-static inline void cpu_to_ube16(uint8_t *buf, int val)
-{
- buf[0] = val >> 8;
- buf[1] = val;
-}
-
-static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
-{
- buf[0] = val >> 24;
- buf[1] = val >> 16;
- buf[2] = val >> 8;
- buf[3] = val;
-}
-
-static inline int ube16_to_cpu(const uint8_t *buf)
-{
- return (buf[0] << 8) | buf[1];
-}
-
-static inline int ube32_to_cpu(const uint8_t *buf)
-{
- return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-}
-
-static void lba_to_msf(uint8_t *buf, int lba)
-{
- lba += 150;
- buf[0] = (lba / 75) / 60;
- buf[1] = (lba / 75) % 60;
- buf[2] = lba % 75;
-}
-
-static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
- int sector_size)
-{
- switch(sector_size) {
- case 2048:
- bdrv_read(bs, (int64_t)lba << 2, buf, 4);
- break;
- case 2352:
- /* sync bytes */
- buf[0] = 0x00;
- memset(buf + 1, 0xff, 10);
- buf[11] = 0x00;
- buf += 12;
- /* MSF */
- lba_to_msf(buf, lba);
- buf[3] = 0x01; /* mode 1 data */
- buf += 4;
- /* data */
- bdrv_read(bs, (int64_t)lba << 2, buf, 4);
- buf += 2048;
- /* ECC */
- memset(buf, 0, 288);
- break;
- default:
- break;
- }
-}
-
-/* The whole ATAPI transfer logic is handled in this function */
-static void ide_atapi_cmd_reply_end(IDEState *s)
-{
- int byte_count_limit, size;
-#ifdef DEBUG_IDE_ATAPI
- printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
- s->packet_transfer_size,
- s->elementary_transfer_size,
- s->io_buffer_index);
-#endif
- if (s->packet_transfer_size <= 0) {
- /* end of transfer */
- ide_transfer_stop(s);
- s->status = READY_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- ide_set_irq(s);
-#ifdef DEBUG_IDE_ATAPI
- printf("status=0x%x\n", s->status);
-#endif
- } else {
- /* see if a new sector must be read */
- if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
- cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
- s->lba++;
- s->io_buffer_index = 0;
- }
- if (s->elementary_transfer_size > 0) {
- /* there are some data left to transmit in this elementary
- transfer */
- size = s->cd_sector_size - s->io_buffer_index;
- if (size > s->elementary_transfer_size)
- size = s->elementary_transfer_size;
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
- size, ide_atapi_cmd_reply_end);
- s->packet_transfer_size -= size;
- s->elementary_transfer_size -= size;
- s->io_buffer_index += size;
- } else {
- /* a new transfer is needed */
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
- byte_count_limit = s->lcyl | (s->hcyl << 8);
-#ifdef DEBUG_IDE_ATAPI
- printf("byte_count_limit=%d\n", byte_count_limit);
-#endif
- if (byte_count_limit == 0xffff)
- byte_count_limit--;
- size = s->packet_transfer_size;
- if (size > byte_count_limit) {
- /* byte count limit must be even if this case */
- if (byte_count_limit & 1)
- byte_count_limit--;
- size = byte_count_limit;
- }
- s->lcyl = size;
- s->hcyl = size >> 8;
- s->elementary_transfer_size = size;
- /* we cannot transmit more than one sector at a time */
- if (s->lba != -1) {
- if (size > (s->cd_sector_size - s->io_buffer_index))
- size = (s->cd_sector_size - s->io_buffer_index);
- }
- ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
- size, ide_atapi_cmd_reply_end);
- s->packet_transfer_size -= size;
- s->elementary_transfer_size -= size;
- s->io_buffer_index += size;
- ide_set_irq(s);
-#ifdef DEBUG_IDE_ATAPI
- printf("status=0x%x\n", s->status);
-#endif
- }
- }
-}
-
-/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
-static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
-{
- if (size > max_size)
- size = max_size;
- s->lba = -1; /* no sector read */
- s->packet_transfer_size = size;
- s->elementary_transfer_size = 0;
- s->io_buffer_index = 0;
-
- s->status = READY_STAT;
- ide_atapi_cmd_reply_end(s);
-}
-
-/* start a CD-CDROM read command */
-static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
- int sector_size)
-{
- s->lba = lba;
- s->packet_transfer_size = nb_sectors * sector_size;
- s->elementary_transfer_size = 0;
- s->io_buffer_index = sector_size;
- s->cd_sector_size = sector_size;
-
- s->status = READY_STAT;
- ide_atapi_cmd_reply_end(s);
-}
-
-/* ATAPI DMA support */
-static int ide_atapi_cmd_read_dma_cb(IDEState *s,
- target_phys_addr_t phys_addr,
- int transfer_size1)
-{
- int len, transfer_size;
-
- transfer_size = transfer_size1;
- while (transfer_size > 0) {
-#ifdef DEBUG_IDE_ATAPI
- printf("transfer_size: %d phys_addr=%08x\n", transfer_size, phys_addr);
-#endif
- if (s->packet_transfer_size <= 0)
- break;
- len = s->cd_sector_size - s->io_buffer_index;
- if (len <= 0) {
- /* transfert next data */
- cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
- s->lba++;
- s->io_buffer_index = 0;
- len = s->cd_sector_size;
- }
- if (len > transfer_size)
- len = transfer_size;
- cpu_physical_memory_write(phys_addr,
- s->io_buffer + s->io_buffer_index, len);
- s->packet_transfer_size -= len;
- s->io_buffer_index += len;
- transfer_size -= len;
- phys_addr += len;
- }
- if (s->packet_transfer_size <= 0) {
- s->status = READY_STAT;
- s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
- ide_set_irq(s);
-#ifdef DEBUG_IDE_ATAPI
- printf("dma status=0x%x\n", s->status);
-#endif
- return 0;
- }
- return transfer_size1 - transfer_size;
-}
-
-/* start a CD-CDROM read command with DMA */
-/* XXX: test if DMA is available */
-static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
- int sector_size)
-{
- s->lba = lba;
- s->packet_transfer_size = nb_sectors * sector_size;
- s->io_buffer_index = sector_size;
- s->cd_sector_size = sector_size;
-
- s->status = READY_STAT | DRQ_STAT;
- ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
-}
-
-static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
- int sector_size)
-{
-#ifdef DEBUG_IDE_ATAPI
- printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors);
-#endif
- if (s->atapi_dma) {
- ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
- } else {
- ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);
- }
-}
-
-static void ide_atapi_cmd(IDEState *s)
-{
- const uint8_t *packet;
- uint8_t *buf;
- int max_len;
-
- packet = s->io_buffer;
- buf = s->io_buffer;
-#ifdef DEBUG_IDE_ATAPI
- {
- int i;
- printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
- for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
- printf(" %02x", packet[i]);
- }
- printf("\n");
- }
-#endif
- switch(s->io_buffer[0]) {
- case GPCMD_TEST_UNIT_READY:
- if (bdrv_is_inserted(s->bs)) {
- ide_atapi_cmd_ok(s);
- } else {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- }
- break;
- case GPCMD_MODE_SENSE_10:
- {
- int action, code;
- max_len = ube16_to_cpu(packet + 7);
- action = packet[2] >> 6;
- code = packet[2] & 0x3f;
- switch(action) {
- case 0: /* current values */
- switch(code) {
- case 0x01: /* error recovery */
- cpu_to_ube16(&buf[0], 16 + 6);
- buf[2] = 0x70;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 0;
- buf[6] = 0;
- buf[7] = 0;
-
- buf[8] = 0x01;
- buf[9] = 0x06;
- buf[10] = 0x00;
- buf[11] = 0x05;
- buf[12] = 0x00;
- buf[13] = 0x00;
- buf[14] = 0x00;
- buf[15] = 0x00;
- ide_atapi_cmd_reply(s, 16, max_len);
- break;
- case 0x2a:
- cpu_to_ube16(&buf[0], 28 + 6);
- buf[2] = 0x70;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 0;
- buf[6] = 0;
- buf[7] = 0;
-
- buf[8] = 0x2a;
- buf[9] = 0x12;
- buf[10] = 0x00;
- buf[11] = 0x00;
-
- buf[12] = 0x70;
- buf[13] = 3 << 5;
- buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
- if (bdrv_is_locked(s->bs))
- buf[6] |= 1 << 1;
- buf[15] = 0x00;
- cpu_to_ube16(&buf[16], 706);
- buf[18] = 0;
- buf[19] = 2;
- cpu_to_ube16(&buf[20], 512);
- cpu_to_ube16(&buf[22], 706);
- buf[24] = 0;
- buf[25] = 0;
- buf[26] = 0;
- buf[27] = 0;
- ide_atapi_cmd_reply(s, 28, max_len);
- break;
- default:
- goto error_cmd;
- }
- break;
- case 1: /* changeable values */
- goto error_cmd;
- case 2: /* default values */
- goto error_cmd;
- default:
- case 3: /* saved values */
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
- break;
- }
- }
- break;
- case GPCMD_REQUEST_SENSE:
- max_len = packet[4];
- memset(buf, 0, 18);
- buf[0] = 0x70 | (1 << 7);
- buf[2] = s->sense_key;
- buf[7] = 10;
- buf[12] = s->asc;
- ide_atapi_cmd_reply(s, 18, max_len);
- break;
- case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
- if (bdrv_is_inserted(s->bs)) {
- bdrv_set_locked(s->bs, packet[4] & 1);
- ide_atapi_cmd_ok(s);
- } else {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- }
- break;
- case GPCMD_READ_10:
- case GPCMD_READ_12:
- {
- int nb_sectors, lba;
-
- if (!bdrv_is_inserted(s->bs)) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- if (packet[0] == GPCMD_READ_10)
- nb_sectors = ube16_to_cpu(packet + 7);
- else
- nb_sectors = ube32_to_cpu(packet + 6);
- lba = ube32_to_cpu(packet + 2);
- if (nb_sectors == 0) {
- ide_atapi_cmd_ok(s);
- break;
- }
- if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_LOGICAL_BLOCK_OOR);
- break;
- }
- ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
- }
- break;
- case GPCMD_READ_CD:
- {
- int nb_sectors, lba, transfer_request;
-
- if (!bdrv_is_inserted(s->bs)) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
- lba = ube32_to_cpu(packet + 2);
- if (nb_sectors == 0) {
- ide_atapi_cmd_ok(s);
- break;
- }
- if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_LOGICAL_BLOCK_OOR);
- break;
- }
- transfer_request = packet[9];
- switch(transfer_request & 0xf8) {
- case 0x00:
- /* nothing */
- ide_atapi_cmd_ok(s);
- break;
- case 0x10:
- /* normal read */
- ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
- break;
- case 0xf8:
- /* read all data */
- ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
- break;
- default:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- break;
- }
- }
- break;
- case GPCMD_SEEK:
- {
- int lba;
- if (!bdrv_is_inserted(s->bs)) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- lba = ube32_to_cpu(packet + 2);
- if (((int64_t)lba << 2) > s->nb_sectors) {
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_LOGICAL_BLOCK_OOR);
- break;
- }
- ide_atapi_cmd_ok(s);
- }
- break;
- case GPCMD_START_STOP_UNIT:
- {
- int start, eject;
- start = packet[4] & 1;
- eject = (packet[4] >> 1) & 1;
-
- if (eject && !start) {
- /* eject the disk */
- bdrv_close(s->bs);
- }
- ide_atapi_cmd_ok(s);
- }
- break;
- case GPCMD_MECHANISM_STATUS:
- {
- max_len = ube16_to_cpu(packet + 8);
- cpu_to_ube16(buf, 0);
- /* no current LBA */
- buf[2] = 0;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 1;
- cpu_to_ube16(buf + 6, 0);
- ide_atapi_cmd_reply(s, 8, max_len);
- }
- break;
- case GPCMD_READ_TOC_PMA_ATIP:
- {
- int format, msf, start_track, len;
-
- if (!bdrv_is_inserted(s->bs)) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- max_len = ube16_to_cpu(packet + 7);
- format = packet[9] >> 6;
- msf = (packet[1] >> 1) & 1;
- start_track = packet[6];
- switch(format) {
- case 0:
- len = cdrom_read_toc(s->nb_sectors >> 2, buf, msf, start_track);
- if (len < 0)
- goto error_cmd;
- ide_atapi_cmd_reply(s, len, max_len);
- break;
- case 1:
- /* multi session : only a single session defined */
- memset(buf, 0, 12);
- buf[1] = 0x0a;
- buf[2] = 0x01;
- buf[3] = 0x01;
- ide_atapi_cmd_reply(s, 12, max_len);
- break;
- case 2:
- len = cdrom_read_toc_raw(s->nb_sectors >> 2, buf, msf, start_track);
- if (len < 0)
- goto error_cmd;
- ide_atapi_cmd_reply(s, len, max_len);
- break;
- default:
- error_cmd:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- break;
- }
- }
- break;
- case GPCMD_READ_CDVD_CAPACITY:
- if (!bdrv_is_inserted(s->bs)) {
- ide_atapi_cmd_error(s, SENSE_NOT_READY,
- ASC_MEDIUM_NOT_PRESENT);
- break;
- }
- /* NOTE: it is really the number of sectors minus 1 */
- cpu_to_ube32(buf, (s->nb_sectors >> 2) - 1);
- cpu_to_ube32(buf + 4, 2048);
- ide_atapi_cmd_reply(s, 8, 8);
- break;
- case GPCMD_INQUIRY:
- max_len = packet[4];
- buf[0] = 0x05; /* CD-ROM */
- buf[1] = 0x80; /* removable */
- buf[2] = 0x00; /* ISO */
- buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
- buf[4] = 31; /* additionnal length */
- buf[5] = 0; /* reserved */
- buf[6] = 0; /* reserved */
- buf[7] = 0; /* reserved */
- padstr8(buf + 8, 8, "QEMU");
- padstr8(buf + 16, 16, "QEMU CD-ROM");
- padstr8(buf + 32, 4, QEMU_VERSION);
- ide_atapi_cmd_reply(s, 36, max_len);
- break;
- default:
- ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
- ASC_ILLEGAL_OPCODE);
- break;
- }
-}
-
-/* called when the inserted state of the media has changed */
-static void cdrom_change_cb(void *opaque)
-{
- IDEState *s = opaque;
- int64_t nb_sectors;
-
- /* XXX: send interrupt too */
- bdrv_get_geometry(s->bs, &nb_sectors);
- s->nb_sectors = nb_sectors;
-}
-
-static void ide_cmd_lba48_transform(IDEState *s, int lba48)
-{
- s->lba48 = lba48;
-
- /* handle the 'magic' 0 nsector count conversion here. to avoid
- * fiddling with the rest of the read logic, we just store the
- * full sector count in ->nsector and ignore ->hob_nsector from now
- */
- if (!s->lba48) {
- if (!s->nsector)
- s->nsector = 256;
- } else {
- if (!s->nsector && !s->hob_nsector)
- s->nsector = 65536;
- else {
- int lo = s->nsector;
- int hi = s->hob_nsector;
-
- s->nsector = (hi << 8) | lo;
- }
- }
-}
-
-static void ide_clear_hob(IDEState *ide_if)
-{
- /* any write clears HOB high bit of device control register */
- ide_if[0].select &= ~(1 << 7);
- ide_if[1].select &= ~(1 << 7);
-}
-
-static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- IDEState *ide_if = opaque;
- IDEState *s;
- int unit, n;
- int lba48 = 0;
-
-#ifdef DEBUG_IDE
- printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
-#endif
-
- addr &= 7;
- switch(addr) {
- case 0:
- break;
- case 1:
- ide_clear_hob(ide_if);
- /* NOTE: data is written to the two drives */
- ide_if[0].hob_feature = ide_if[0].feature;
- ide_if[1].hob_feature = ide_if[1].feature;
- ide_if[0].feature = val;
- ide_if[1].feature = val;
- break;
- case 2:
- ide_clear_hob(ide_if);
- ide_if[0].hob_nsector = ide_if[0].nsector;
- ide_if[1].hob_nsector = ide_if[1].nsector;
- ide_if[0].nsector = val;
- ide_if[1].nsector = val;
- break;
- case 3:
- ide_clear_hob(ide_if);
- ide_if[0].hob_sector = ide_if[0].sector;
- ide_if[1].hob_sector = ide_if[1].sector;
- ide_if[0].sector = val;
- ide_if[1].sector = val;
- break;
- case 4:
- ide_clear_hob(ide_if);
- ide_if[0].hob_lcyl = ide_if[0].lcyl;
- ide_if[1].hob_lcyl = ide_if[1].lcyl;
- ide_if[0].lcyl = val;
- ide_if[1].lcyl = val;
- break;
- case 5:
- ide_clear_hob(ide_if);
- ide_if[0].hob_hcyl = ide_if[0].hcyl;
- ide_if[1].hob_hcyl = ide_if[1].hcyl;
- ide_if[0].hcyl = val;
- ide_if[1].hcyl = val;
- break;
- case 6:
- /* FIXME: HOB readback uses bit 7 */
- ide_if[0].select = (val & ~0x10) | 0xa0;
- ide_if[1].select = (val | 0x10) | 0xa0;
- /* select drive */
- unit = (val >> 4) & 1;
- s = ide_if + unit;
- ide_if->cur_drive = s;
- break;
- default:
- case 7:
- /* command */
-#if defined(DEBUG_IDE)
- printf("ide: CMD=%02x\n", val);
-#endif
- s = ide_if->cur_drive;
- /* ignore commands to non existant slave */
- if (s != ide_if && !s->bs)
- break;
-
- switch(val) {
- case WIN_IDENTIFY:
- if (s->bs && !s->is_cdrom) {
- ide_identify(s);
- s->status = READY_STAT | SEEK_STAT;
- ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
- } else {
- if (s->is_cdrom) {
- ide_set_signature(s);
- }
- ide_abort_command(s);
- }
- ide_set_irq(s);
- break;
- case WIN_SPECIFY:
- case WIN_RECAL:
- s->error = 0;
- s->status = READY_STAT | SEEK_STAT;
- ide_set_irq(s);
- break;
- case WIN_SETMULT:
- if (s->nsector > MAX_MULT_SECTORS ||
- s->nsector == 0 ||
- (s->nsector & (s->nsector - 1)) != 0) {
- ide_abort_command(s);
- } else {
- s->mult_sectors = s->nsector;
- s->status = READY_STAT;
- }
- ide_set_irq(s);
- break;
- case WIN_VERIFY_EXT:
- lba48 = 1;
- case WIN_VERIFY:
- case WIN_VERIFY_ONCE:
- /* do sector number check ? */
- ide_cmd_lba48_transform(s, lba48);
- s->status = READY_STAT;
- ide_set_irq(s);
- break;
- case WIN_READ_EXT:
- lba48 = 1;
- case WIN_READ:
- case WIN_READ_ONCE:
- if (!s->bs)
- goto abort_cmd;
- ide_cmd_lba48_transform(s, lba48);
- s->req_nb_sectors = 1;
- ide_sector_read(s);
- break;
- case WIN_WRITE_EXT:
- lba48 = 1;
- case WIN_WRITE:
- case WIN_WRITE_ONCE:
- ide_cmd_lba48_transform(s, lba48);
- s->error = 0;
- s->status = SEEK_STAT | READY_STAT;
- s->req_nb_sectors = 1;
- ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
- break;
- case WIN_MULTREAD_EXT:
- lba48 = 1;
- case WIN_MULTREAD:
- if (!s->mult_sectors)
- goto abort_cmd;
- ide_cmd_lba48_transform(s, lba48);
- s->req_nb_sectors = s->mult_sectors;
- ide_sector_read(s);
- break;
- case WIN_MULTWRITE_EXT:
- lba48 = 1;
- case WIN_MULTWRITE:
- if (!s->mult_sectors)
- goto abort_cmd;
- ide_cmd_lba48_transform(s, lba48);
- s->error = 0;
- s->status = SEEK_STAT | READY_STAT;
- s->req_nb_sectors = s->mult_sectors;
- n = s->nsector;
- if (n > s->req_nb_sectors)
- n = s->req_nb_sectors;
- ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
- break;
- case WIN_READDMA_EXT:
- lba48 = 1;
- case WIN_READDMA:
- case WIN_READDMA_ONCE:
- if (!s->bs)
- goto abort_cmd;
- ide_cmd_lba48_transform(s, lba48);
- ide_sector_read_dma(s);
- break;
- case WIN_WRITEDMA_EXT:
- lba48 = 1;
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_ONCE:
- if (!s->bs)
- goto abort_cmd;
- ide_cmd_lba48_transform(s, lba48);
- ide_sector_write_dma(s);
- break;
- case WIN_READ_NATIVE_MAX_EXT:
- lba48 = 1;
- case WIN_READ_NATIVE_MAX:
- ide_cmd_lba48_transform(s, lba48);
- ide_set_sector(s, s->nb_sectors - 1);
- s->status = READY_STAT;
- ide_set_irq(s);
- break;
- case WIN_CHECKPOWERMODE1:
- s->nsector = 0xff; /* device active or idle */
- s->status = READY_STAT;
- ide_set_irq(s);
- break;
- case WIN_SETFEATURES:
- if (!s->bs)
- goto abort_cmd;
- /* XXX: valid for CDROM ? */
- switch(s->feature) {
- case 0x02: /* write cache enable */
- case 0x82: /* write cache disable */
- case 0xaa: /* read look-ahead enable */
- case 0x55: /* read look-ahead disable */
- s->status = READY_STAT | SEEK_STAT;
- ide_set_irq(s);
- break;
- case 0x03: { /* set transfer mode */
- uint8_t val = s->nsector & 0x07;
-
- switch (s->nsector >> 3) {
- case 0x00: /* pio default */
- case 0x01: /* pio mode */
- put_le16(s->identify_data + 63,0x07);
- put_le16(s->identify_data + 88,0x3f);
- break;
- case 0x04: /* mdma mode */
- put_le16(s->identify_data + 63,0x07 | (1 << (val + 8)));
- put_le16(s->identify_data + 88,0x3f);
- break;
- case 0x08: /* udma mode */
- put_le16(s->identify_data + 63,0x07);
- put_le16(s->identify_data + 88,0x3f | (1 << (val + 8)));
- break;
- default:
- goto abort_cmd;
- }
- s->status = READY_STAT | SEEK_STAT;
- ide_set_irq(s);
- break;
- }
- default:
- goto abort_cmd;
- }
- break;
- case WIN_FLUSH_CACHE:
- case WIN_FLUSH_CACHE_EXT:
- if (s->bs)
- bdrv_flush(s->bs);
- s->status = READY_STAT;
- ide_set_irq(s);
- break;
- case WIN_STANDBYNOW1:
- case WIN_IDLEIMMEDIATE:
- s->status = READY_STAT;
- ide_set_irq(s);
- break;
- /* ATAPI commands */
- case WIN_PIDENTIFY:
- if (s->is_cdrom) {
- ide_atapi_identify(s);
- s->status = READY_STAT | SEEK_STAT;
- ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
- } else {
- ide_abort_command(s);
- }
- ide_set_irq(s);
- break;
- case WIN_DIAGNOSE:
- ide_set_signature(s);
- s->status = 0x00; /* NOTE: READY is _not_ set */
- s->error = 0x01;
- break;
- case WIN_SRST:
- if (!s->is_cdrom)
- goto abort_cmd;
- ide_set_signature(s);
- s->status = 0x00; /* NOTE: READY is _not_ set */
- s->error = 0x01;
- break;
- case WIN_PACKETCMD:
- if (!s->is_cdrom)
- goto abort_cmd;
- /* overlapping commands not supported */
- if (s->feature & 0x02)
- goto abort_cmd;
- s->atapi_dma = s->feature & 1;
- s->nsector = 1;
- ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
- ide_atapi_cmd);
- break;
- default:
- abort_cmd:
- ide_abort_command(s);
- ide_set_irq(s);
- break;
- }
- }
-}
-
-static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
-{
- IDEState *ide_if = opaque;
- IDEState *s = ide_if->cur_drive;
- uint32_t addr;
- int ret, hob;
-
- addr = addr1 & 7;
- /* FIXME: HOB readback uses bit 7, but it's always set right now */
- //hob = s->select & (1 << 7);
- hob = 0;
- switch(addr) {
- case 0:
- ret = 0xff;
- break;
- case 1:
- if (!ide_if[0].bs && !ide_if[1].bs)
- ret = 0;
- else if (!hob)
- ret = s->error;
- else
- ret = s->hob_feature;
- break;
- case 2:
- if (!ide_if[0].bs && !ide_if[1].bs)
- ret = 0;
- else if (!hob)
- ret = s->nsector & 0xff;
- else
- ret = s->hob_nsector;
- break;
- case 3:
- if (!ide_if[0].bs && !ide_if[1].bs)
- ret = 0;
- else if (!hob)
- ret = s->sector;
- else
- ret = s->hob_sector;
- break;
- case 4:
- if (!ide_if[0].bs && !ide_if[1].bs)
- ret = 0;
- else if (!hob)
- ret = s->lcyl;
- else
- ret = s->hob_lcyl;
- break;
- case 5:
- if (!ide_if[0].bs && !ide_if[1].bs)
- ret = 0;
- else if (!hob)
- ret = s->hcyl;
- else
- ret = s->hob_hcyl;
- break;
- case 6:
- if (!ide_if[0].bs && !ide_if[1].bs)
- ret = 0;
- else
- ret = s->select;
- break;
- default:
- case 7:
- if ((!ide_if[0].bs && !ide_if[1].bs) ||
- (s != ide_if && !s->bs))
- ret = 0;
- else
- ret = s->status;
- s->set_irq(s->irq_opaque, s->irq, 0);
- break;
- }
-#ifdef DEBUG_IDE
- printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
-#endif
- return ret;
-}
-
-static uint32_t ide_status_read(void *opaque, uint32_t addr)
-{
- IDEState *ide_if = opaque;
- IDEState *s = ide_if->cur_drive;
- int ret;
-
- if ((!ide_if[0].bs && !ide_if[1].bs) ||
- (s != ide_if && !s->bs))
- ret = 0;
- else
- ret = s->status;
-#ifdef DEBUG_IDE
- printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
-#endif
- return ret;
-}
-
-static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
-{
- IDEState *ide_if = opaque;
- IDEState *s;
- int i;
-
-#ifdef DEBUG_IDE
- printf("ide: write control addr=0x%x val=%02x\n", addr, val);
-#endif
- /* common for both drives */
- if (!(ide_if[0].cmd & IDE_CMD_RESET) &&
- (val & IDE_CMD_RESET)) {
- /* reset low to high */
- for(i = 0;i < 2; i++) {
- s = &ide_if[i];
- s->status = BUSY_STAT | SEEK_STAT;
- s->error = 0x01;
- }
- } else if ((ide_if[0].cmd & IDE_CMD_RESET) &&
- !(val & IDE_CMD_RESET)) {
- /* high to low */
- for(i = 0;i < 2; i++) {
- s = &ide_if[i];
- if (s->is_cdrom)
- s->status = 0x00; /* NOTE: READY is _not_ set */
- else
- s->status = READY_STAT | SEEK_STAT;
- ide_set_signature(s);
- }
- }
-
- ide_if[0].cmd = val;
- ide_if[1].cmd = val;
-}
-
-static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- IDEState *s = ((IDEState *)opaque)->cur_drive;
- uint8_t *p;
-
- p = s->data_ptr;
- *(uint16_t *)p = le16_to_cpu(val);
- p += 2;
- s->data_ptr = p;
- if (p >= s->data_end)
- s->end_transfer_func(s);
-}
-
-static uint32_t ide_data_readw(void *opaque, uint32_t addr)
-{
- IDEState *s = ((IDEState *)opaque)->cur_drive;
- uint8_t *p;
- int ret;
- p = s->data_ptr;
- ret = cpu_to_le16(*(uint16_t *)p);
- p += 2;
- s->data_ptr = p;
- if (p >= s->data_end)
- s->end_transfer_func(s);
- return ret;
-}
-
-static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- IDEState *s = ((IDEState *)opaque)->cur_drive;
- uint8_t *p;
-
- p = s->data_ptr;
- *(uint32_t *)p = le32_to_cpu(val);
- p += 4;
- s->data_ptr = p;
- if (p >= s->data_end)
- s->end_transfer_func(s);
-}
-
-static uint32_t ide_data_readl(void *opaque, uint32_t addr)
-{
- IDEState *s = ((IDEState *)opaque)->cur_drive;
- uint8_t *p;
- int ret;
-
- p = s->data_ptr;
- ret = cpu_to_le32(*(uint32_t *)p);
- p += 4;
- s->data_ptr = p;
- if (p >= s->data_end)
- s->end_transfer_func(s);
- return ret;
-}
-
-static void ide_dummy_transfer_stop(IDEState *s)
-{
- s->data_ptr = s->io_buffer;
- s->data_end = s->io_buffer;
- s->io_buffer[0] = 0xff;
- s->io_buffer[1] = 0xff;
- s->io_buffer[2] = 0xff;
- s->io_buffer[3] = 0xff;
-}
-
-static void ide_reset(IDEState *s)
-{
- s->mult_sectors = MAX_MULT_SECTORS;
- s->cur_drive = s;
- s->select = 0xa0;
- s->status = READY_STAT;
- ide_set_signature(s);
- /* init the transfer handler so that 0xffff is returned on data
- accesses */
- s->end_transfer_func = ide_dummy_transfer_stop;
- ide_dummy_transfer_stop(s);
-}
-
-struct partition {
- uint8_t boot_ind; /* 0x80 - active */
- uint8_t head; /* starting head */
- uint8_t sector; /* starting sector */
- uint8_t cyl; /* starting cylinder */
- uint8_t sys_ind; /* What partition type */
- uint8_t end_head; /* end head */
- uint8_t end_sector; /* end sector */
- uint8_t end_cyl; /* end cylinder */
- uint32_t start_sect; /* starting sector counting from 0 */
- uint32_t nr_sects; /* nr of sectors in partition */
-} __attribute__((packed));
-
-/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
-static int guess_disk_lchs(IDEState *s,
- int *pcylinders, int *pheads, int *psectors)
-{
- uint8_t buf[512];
- int ret, i, heads, sectors, cylinders;
- struct partition *p;
- uint32_t nr_sects;
-
- ret = bdrv_read(s->bs, 0, buf, 1);
- if (ret < 0)
- return -1;
- /* test msdos magic */
- if (buf[510] != 0x55 || buf[511] != 0xaa)
- return -1;
- for(i = 0; i < 4; i++) {
- p = ((struct partition *)(buf + 0x1be)) + i;
- nr_sects = le32_to_cpu(p->nr_sects);
- if (nr_sects && p->end_head) {
- /* We make the assumption that the partition terminates on
- a cylinder boundary */
- heads = p->end_head + 1;
- sectors = p->end_sector & 63;
- if (sectors == 0)
- continue;
- cylinders = s->nb_sectors / (heads * sectors);
- if (cylinders < 1 || cylinders > 16383)
- continue;
- *pheads = heads;
- *psectors = sectors;
- *pcylinders = cylinders;
-#if 0
- printf("guessed geometry: LCHS=%d %d %d\n",
- cylinders, heads, sectors);
-#endif
- return 0;
- }
- }
- return -1;
-}
-
-static void ide_init2(IDEState *ide_state,
- BlockDriverState *hd0, BlockDriverState *hd1,
- SetIRQFunc *set_irq, void *irq_opaque, int irq)
-{
- IDEState *s;
- static int drive_serial = 1;
- int i, cylinders, heads, secs, translation;
- int64_t nb_sectors;
-
- for(i = 0; i < 2; i++) {
- s = ide_state + i;
- if (i == 0)
- s->bs = hd0;
- else
- s->bs = hd1;
- if (s->bs) {
- bdrv_get_geometry(s->bs, &nb_sectors);
- s->nb_sectors = nb_sectors;
- /* if a geometry hint is available, use it */
- bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
- if (cylinders != 0) {
- s->cylinders = cylinders;
- s->heads = heads;
- s->sectors = secs;
- } else {
- if (guess_disk_lchs(s, &cylinders, &heads, &secs) == 0) {
- if (heads > 16) {
- /* if heads > 16, it means that a BIOS LBA
- translation was active, so the default
- hardware geometry is OK */
- goto default_geometry;
- } else {
- s->cylinders = cylinders;
- s->heads = heads;
- s->sectors = secs;
- /* disable any translation to be in sync with
- the logical geometry */
- translation = bdrv_get_translation_hint(s->bs);
- if (translation == BIOS_ATA_TRANSLATION_AUTO) {
- bdrv_set_translation_hint(s->bs,
- BIOS_ATA_TRANSLATION_NONE);
- }
- }
- } else {
- default_geometry:
- /* if no geometry, use a standard physical disk geometry */
- cylinders = nb_sectors / (16 * 63);
- if (cylinders > 16383)
- cylinders = 16383;
- else if (cylinders < 2)
- cylinders = 2;
- s->cylinders = cylinders;
- s->heads = 16;
- s->sectors = 63;
- }
- bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors);
- }
- if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
- s->is_cdrom = 1;
- bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
- }
- }
- s->drive_serial = drive_serial++;
- s->set_irq = set_irq;
- s->irq_opaque = irq_opaque;
- s->irq = irq;
- s->sector_write_timer = qemu_new_timer(vm_clock,
- ide_sector_write_timer_cb, s);
- ide_reset(s);
- }
-}
-
-static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2)
-{
- register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state);
- register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state);
- if (iobase2) {
- register_ioport_read(iobase2, 1, 1, ide_status_read, ide_state);
- register_ioport_write(iobase2, 1, 1, ide_cmd_write, ide_state);
- }
-
- /* data ports */
- register_ioport_write(iobase, 2, 2, ide_data_writew, ide_state);
- register_ioport_read(iobase, 2, 2, ide_data_readw, ide_state);
- register_ioport_write(iobase, 4, 4, ide_data_writel, ide_state);
- register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state);
-}
-
-/***********************************************************/
-/* ISA IDE definitions */
-
-void isa_ide_init(int iobase, int iobase2, int irq,
- BlockDriverState *hd0, BlockDriverState *hd1)
-{
- IDEState *ide_state;
-
- ide_state = qemu_mallocz(sizeof(IDEState) * 2);
- if (!ide_state)
- return;
-
- ide_init2(ide_state, hd0, hd1, pic_set_irq_new, isa_pic, irq);
- ide_init_ioport(ide_state, iobase, iobase2);
-}
-
-/***********************************************************/
-/* PCI IDE definitions */
-
-static void cmd646_update_irq(PCIIDEState *d);
-
-static void ide_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCIIDEState *d = (PCIIDEState *)pci_dev;
- IDEState *ide_state;
-
- if (region_num <= 3) {
- ide_state = &d->ide_if[(region_num >> 1) * 2];
- if (region_num & 1) {
- register_ioport_read(addr + 2, 1, 1, ide_status_read, ide_state);
- register_ioport_write(addr + 2, 1, 1, ide_cmd_write, ide_state);
- } else {
- register_ioport_write(addr, 8, 1, ide_ioport_write, ide_state);
- register_ioport_read(addr, 8, 1, ide_ioport_read, ide_state);
-
- /* data ports */
- register_ioport_write(addr, 2, 2, ide_data_writew, ide_state);
- register_ioport_read(addr, 2, 2, ide_data_readw, ide_state);
- register_ioport_write(addr, 4, 4, ide_data_writel, ide_state);
- register_ioport_read(addr, 4, 4, ide_data_readl, ide_state);
- }
- }
-}
-
-/* XXX: full callback usage to prepare non blocking I/Os support -
- error handling */
-static void ide_dma_loop(BMDMAState *bm)
-{
- struct {
- uint32_t addr;
- uint32_t size;
- } prd;
- target_phys_addr_t cur_addr;
- int len, i, len1;
-
- cur_addr = bm->addr;
- /* at most one page to avoid hanging if erroneous parameters */
- for(i = 0; i < 512; i++) {
- cpu_physical_memory_read(cur_addr, (uint8_t *)&prd, 8);
- prd.addr = le32_to_cpu(prd.addr);
- prd.size = le32_to_cpu(prd.size);
-#ifdef DEBUG_IDE
- printf("ide: dma: prd: %08x: addr=0x%08x size=0x%08x\n",
- (int)cur_addr, prd.addr, prd.size);
-#endif
- len = prd.size & 0xfffe;
- if (len == 0)
- len = 0x10000;
- while (len > 0) {
- len1 = bm->dma_cb(bm->ide_if, prd.addr, len);
- if (len1 == 0)
- goto the_end;
- prd.addr += len1;
- len -= len1;
- }
- /* end of transfer */
- if (prd.size & 0x80000000)
- break;
- cur_addr += 8;
- }
- /* end of transfer */
- the_end:
- bm->status &= ~BM_STATUS_DMAING;
- bm->status |= BM_STATUS_INT;
- bm->dma_cb = NULL;
- bm->ide_if = NULL;
-}
-
-static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb)
-{
- BMDMAState *bm = s->bmdma;
- if(!bm)
- return;
- bm->ide_if = s;
- bm->dma_cb = dma_cb;
- if (bm->status & BM_STATUS_DMAING) {
- ide_dma_loop(bm);
- }
-}
-
-static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- BMDMAState *bm = opaque;
-#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
-#endif
- if (!(val & BM_CMD_START)) {
- /* XXX: do it better */
- bm->status &= ~BM_STATUS_DMAING;
- bm->cmd = val & 0x09;
- } else {
- bm->status |= BM_STATUS_DMAING;
- bm->cmd = val & 0x09;
- /* start dma transfer if possible */
- if (bm->dma_cb)
- ide_dma_loop(bm);
- }
-}
-
-static uint32_t bmdma_readb(void *opaque, uint32_t addr)
-{
- BMDMAState *bm = opaque;
- PCIIDEState *pci_dev;
- uint32_t val;
-
- switch(addr & 3) {
- case 0:
- val = bm->cmd;
- break;
- case 1:
- pci_dev = bm->pci_dev;
- if (pci_dev->type == IDE_TYPE_CMD646) {
- val = pci_dev->dev.config[MRDMODE];
- } else {
- val = 0xff;
- }
- break;
- case 2:
- val = bm->status;
- break;
- case 3:
- pci_dev = bm->pci_dev;
- if (pci_dev->type == IDE_TYPE_CMD646) {
- if (bm == &pci_dev->bmdma[0])
- val = pci_dev->dev.config[UDIDETCR0];
- else
- val = pci_dev->dev.config[UDIDETCR1];
- } else {
- val = 0xff;
- }
- break;
- default:
- val = 0xff;
- break;
- }
-#ifdef DEBUG_IDE
- printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val);
-#endif
- return val;
-}
-
-static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- BMDMAState *bm = opaque;
- PCIIDEState *pci_dev;
-#ifdef DEBUG_IDE
- printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
-#endif
- switch(addr & 3) {
- case 1:
- pci_dev = bm->pci_dev;
- if (pci_dev->type == IDE_TYPE_CMD646) {
- pci_dev->dev.config[MRDMODE] =
- (pci_dev->dev.config[MRDMODE] & ~0x30) | (val & 0x30);
- cmd646_update_irq(pci_dev);
- }
- break;
- case 2:
- bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
- break;
- case 3:
- pci_dev = bm->pci_dev;
- if (pci_dev->type == IDE_TYPE_CMD646) {
- if (bm == &pci_dev->bmdma[0])
- pci_dev->dev.config[UDIDETCR0] = val;
- else
- pci_dev->dev.config[UDIDETCR1] = val;
- }
- break;
- }
-}
-
-static uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
-{
- BMDMAState *bm = opaque;
- uint32_t val;
- val = bm->addr;
-#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
-#endif
- return val;
-}
-
-static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- BMDMAState *bm = opaque;
-#ifdef DEBUG_IDE
- printf("%s: 0x%08x\n", __func__, val);
-#endif
- bm->addr = val & ~3;
-}
-
-static void bmdma_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCIIDEState *d = (PCIIDEState *)pci_dev;
- int i;
-
- for(i = 0;i < 2; i++) {
- BMDMAState *bm = &d->bmdma[i];
- d->ide_if[2 * i].bmdma = bm;
- d->ide_if[2 * i + 1].bmdma = bm;
- bm->pci_dev = (PCIIDEState *)pci_dev;
-
- register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
-
- register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm);
- register_ioport_read(addr, 4, 1, bmdma_readb, bm);
-
- register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
- register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
- addr += 8;
- }
-}
-
-/* XXX: call it also when the MRDMODE is changed from the PCI config
- registers */
-static void cmd646_update_irq(PCIIDEState *d)
-{
- int pci_level;
- pci_level = ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH0) &&
- !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH0)) ||
- ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH1) &&
- !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH1));
- pci_set_irq((PCIDevice *)d, 0, pci_level);
-}
-
-/* the PCI irq level is the logical OR of the two channels */
-static void cmd646_set_irq(void *opaque, int channel, int level)
-{
- PCIIDEState *d = opaque;
- int irq_mask;
-
- irq_mask = MRDMODE_INTR_CH0 << channel;
- if (level)
- d->dev.config[MRDMODE] |= irq_mask;
- else
- d->dev.config[MRDMODE] &= ~irq_mask;
- cmd646_update_irq(d);
-}
-
-/* CMD646 PCI IDE controller */
-void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
- int secondary_ide_enabled)
-{
- PCIIDEState *d;
- uint8_t *pci_conf;
- int i;
-
- d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE",
- sizeof(PCIIDEState),
- -1,
- NULL, NULL);
- d->type = IDE_TYPE_CMD646;
- pci_conf = d->dev.config;
- pci_conf[0x00] = 0x95; // CMD646
- pci_conf[0x01] = 0x10;
- pci_conf[0x02] = 0x46;
- pci_conf[0x03] = 0x06;
-
- pci_conf[0x08] = 0x07; // IDE controller revision
- pci_conf[0x09] = 0x8f;
-
- pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
- pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
- pci_conf[0x0e] = 0x00; // header_type
-
- if (secondary_ide_enabled) {
- /* XXX: if not enabled, really disable the seconday IDE controller */
- pci_conf[0x51] = 0x80; /* enable IDE1 */
- }
-
- pci_register_io_region((PCIDevice *)d, 0, 0x8,
- PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 1, 0x4,
- PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 2, 0x8,
- PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 3, 0x4,
- PCI_ADDRESS_SPACE_IO, ide_map);
- pci_register_io_region((PCIDevice *)d, 4, 0x10,
- PCI_ADDRESS_SPACE_IO, bmdma_map);
-
- pci_conf[0x3d] = 0x01; // interrupt on pin 1
-
- for(i = 0; i < 4; i++)
- d->ide_if[i].pci_dev = (PCIDevice *)d;
- ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
- cmd646_set_irq, d, 0);
- ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
- cmd646_set_irq, d, 1);
-}
-
-/* hd_table must contain 4 block drivers */
-/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
-void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
-{
- PCIIDEState *d;
- uint8_t *pci_conf;
-
- /* register a function 1 of PIIX3 */
- d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
- sizeof(PCIIDEState),
- devfn,
- NULL, NULL);
- d->type = IDE_TYPE_PIIX3;
-
- pci_conf = d->dev.config;
- pci_conf[0x00] = 0x86; // Intel
- pci_conf[0x01] = 0x80;
- pci_conf[0x02] = 0x10;
- pci_conf[0x03] = 0x70;
- pci_conf[0x09] = 0x80; // legacy ATA mode
- pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
- pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
- pci_conf[0x0e] = 0x00; // header_type
-
- pci_register_io_region((PCIDevice *)d, 4, 0x10,
- PCI_ADDRESS_SPACE_IO, bmdma_map);
-
- ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
- pic_set_irq_new, isa_pic, 14);
- ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
- pic_set_irq_new, isa_pic, 15);
- ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
- ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
-}
-
-/***********************************************************/
-/* MacIO based PowerPC IDE */
-
-/* PowerMac IDE memory IO */
-static void pmac_ide_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t val)
-{
- addr = (addr & 0xFFF) >> 4;
- switch (addr) {
- case 1 ... 7:
- ide_ioport_write(opaque, addr, val);
- break;
- case 8:
- case 22:
- ide_cmd_write(opaque, 0, val);
- break;
- default:
- break;
- }
-}
-
-static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr)
-{
- uint8_t retval;
-
- addr = (addr & 0xFFF) >> 4;
- switch (addr) {
- case 1 ... 7:
- retval = ide_ioport_read(opaque, addr);
- break;
- case 8:
- case 22:
- retval = ide_status_read(opaque, 0);
- break;
- default:
- retval = 0xFF;
- break;
- }
- return retval;
-}
-
-static void pmac_ide_writew (void *opaque,
- target_phys_addr_t addr, uint32_t val)
-{
- addr = (addr & 0xFFF) >> 4;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap16(val);
-#endif
- if (addr == 0) {
- ide_data_writew(opaque, 0, val);
- }
-}
-
-static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr)
-{
- uint16_t retval;
-
- addr = (addr & 0xFFF) >> 4;
- if (addr == 0) {
- retval = ide_data_readw(opaque, 0);
- } else {
- retval = 0xFFFF;
- }
-#ifdef TARGET_WORDS_BIGENDIAN
- retval = bswap16(retval);
-#endif
- return retval;
-}
-
-static void pmac_ide_writel (void *opaque,
- target_phys_addr_t addr, uint32_t val)
-{
- addr = (addr & 0xFFF) >> 4;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- if (addr == 0) {
- ide_data_writel(opaque, 0, val);
- }
-}
-
-static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
-{
- uint32_t retval;
-
- addr = (addr & 0xFFF) >> 4;
- if (addr == 0) {
- retval = ide_data_readl(opaque, 0);
- } else {
- retval = 0xFFFFFFFF;
- }
-#ifdef TARGET_WORDS_BIGENDIAN
- retval = bswap32(retval);
-#endif
- return retval;
-}
-
-static CPUWriteMemoryFunc *pmac_ide_write[] = {
- pmac_ide_writeb,
- pmac_ide_writew,
- pmac_ide_writel,
-};
-
-static CPUReadMemoryFunc *pmac_ide_read[] = {
- pmac_ide_readb,
- pmac_ide_readw,
- pmac_ide_readl,
-};
-
-/* hd_table must contain 4 block drivers */
-/* PowerMac uses memory mapped registers, not I/O. Return the memory
- I/O index to access the ide. */
-int pmac_ide_init (BlockDriverState **hd_table,
- SetIRQFunc *set_irq, void *irq_opaque, int irq)
-{
- IDEState *ide_if;
- int pmac_ide_memory;
-
- ide_if = qemu_mallocz(sizeof(IDEState) * 2);
- ide_init2(&ide_if[0], hd_table[0], hd_table[1],
- set_irq, irq_opaque, irq);
-
- pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
- pmac_ide_write, &ide_if[0]);
- return pmac_ide_memory;
-}
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
deleted file mode 100644
index f438af7..0000000
--- a/hw/integratorcp.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * ARM Integrator CP System emulation.
- *
- * Copyright (c) 2005-2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GPL
- */
-
-#include "vl.h"
-#include "arm_pic.h"
-
-void DMA_run (void)
-{
-}
-
-typedef struct {
- uint32_t flash_offset;
- uint32_t cm_osc;
- uint32_t cm_ctrl;
- uint32_t cm_lock;
- uint32_t cm_auxosc;
- uint32_t cm_sdram;
- uint32_t cm_init;
- uint32_t cm_flags;
- uint32_t cm_nvflags;
- uint32_t int_level;
- uint32_t irq_enabled;
- uint32_t fiq_enabled;
-} integratorcm_state;
-
-static uint8_t integrator_spd[128] = {
- 128, 8, 4, 11, 9, 1, 64, 0, 2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
- 0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
-};
-
-static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
-{
- integratorcm_state *s = (integratorcm_state *)opaque;
- offset -= 0x10000000;
- if (offset >= 0x100 && offset < 0x200) {
- /* CM_SPD */
- if (offset >= 0x180)
- return 0;
- return integrator_spd[offset >> 2];
- }
- switch (offset >> 2) {
- case 0: /* CM_ID */
- return 0x411a3001;
- case 1: /* CM_PROC */
- return 0;
- case 2: /* CM_OSC */
- return s->cm_osc;
- case 3: /* CM_CTRL */
- return s->cm_ctrl;
- case 4: /* CM_STAT */
- return 0x00100000;
- case 5: /* CM_LOCK */
- if (s->cm_lock == 0xa05f) {
- return 0x1a05f;
- } else {
- return s->cm_lock;
- }
- case 6: /* CM_LMBUSCNT */
- /* ??? High frequency timer. */
- cpu_abort(cpu_single_env, "integratorcm_read: CM_LMBUSCNT");
- case 7: /* CM_AUXOSC */
- return s->cm_auxosc;
- case 8: /* CM_SDRAM */
- return s->cm_sdram;
- case 9: /* CM_INIT */
- return s->cm_init;
- case 10: /* CM_REFCT */
- /* ??? High frequency timer. */
- cpu_abort(cpu_single_env, "integratorcm_read: CM_REFCT");
- case 12: /* CM_FLAGS */
- return s->cm_flags;
- case 14: /* CM_NVFLAGS */
- return s->cm_nvflags;
- case 16: /* CM_IRQ_STAT */
- return s->int_level & s->irq_enabled;
- case 17: /* CM_IRQ_RSTAT */
- return s->int_level;
- case 18: /* CM_IRQ_ENSET */
- return s->irq_enabled;
- case 20: /* CM_SOFT_INTSET */
- return s->int_level & 1;
- case 24: /* CM_FIQ_STAT */
- return s->int_level & s->fiq_enabled;
- case 25: /* CM_FIQ_RSTAT */
- return s->int_level;
- case 26: /* CM_FIQ_ENSET */
- return s->fiq_enabled;
- case 32: /* CM_VOLTAGE_CTL0 */
- case 33: /* CM_VOLTAGE_CTL1 */
- case 34: /* CM_VOLTAGE_CTL2 */
- case 35: /* CM_VOLTAGE_CTL3 */
- /* ??? Voltage control unimplemented. */
- return 0;
- default:
- cpu_abort (cpu_single_env,
- "integratorcm_read: Unimplemented offset 0x%x\n", offset);
- return 0;
- }
-}
-
-static void integratorcm_do_remap(integratorcm_state *s, int flash)
-{
- if (flash) {
- cpu_register_physical_memory(0, 0x100000, IO_MEM_RAM);
- } else {
- cpu_register_physical_memory(0, 0x100000, s->flash_offset | IO_MEM_RAM);
- }
- //??? tlb_flush (cpu_single_env, 1);
-}
-
-static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
-{
- if (value & 8) {
- cpu_abort(cpu_single_env, "Board reset\n");
- }
- if ((s->cm_init ^ value) & 4) {
- integratorcm_do_remap(s, (value & 4) == 0);
- }
- if ((s->cm_init ^ value) & 1) {
- printf("Green LED %s\n", (value & 1) ? "on" : "off");
- }
- s->cm_init = (s->cm_init & ~ 5) | (value ^ 5);
-}
-
-static void integratorcm_update(integratorcm_state *s)
-{
- /* ??? The CPU irq/fiq is raised when either the core module or base PIC
- are active. */
- if (s->int_level & (s->irq_enabled | s->fiq_enabled))
- cpu_abort(cpu_single_env, "Core module interrupt\n");
-}
-
-static void integratorcm_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- integratorcm_state *s = (integratorcm_state *)opaque;
- offset -= 0x10000000;
- switch (offset >> 2) {
- case 2: /* CM_OSC */
- if (s->cm_lock == 0xa05f)
- s->cm_osc = value;
- break;
- case 3: /* CM_CTRL */
- integratorcm_set_ctrl(s, value);
- break;
- case 5: /* CM_LOCK */
- s->cm_lock = value & 0xffff;
- break;
- case 7: /* CM_AUXOSC */
- if (s->cm_lock == 0xa05f)
- s->cm_auxosc = value;
- break;
- case 8: /* CM_SDRAM */
- s->cm_sdram = value;
- break;
- case 9: /* CM_INIT */
- /* ??? This can change the memory bus frequency. */
- s->cm_init = value;
- break;
- case 12: /* CM_FLAGSS */
- s->cm_flags |= value;
- break;
- case 13: /* CM_FLAGSC */
- s->cm_flags &= ~value;
- break;
- case 14: /* CM_NVFLAGSS */
- s->cm_nvflags |= value;
- break;
- case 15: /* CM_NVFLAGSS */
- s->cm_nvflags &= ~value;
- break;
- case 18: /* CM_IRQ_ENSET */
- s->irq_enabled |= value;
- integratorcm_update(s);
- break;
- case 19: /* CM_IRQ_ENCLR */
- s->irq_enabled &= ~value;
- integratorcm_update(s);
- break;
- case 20: /* CM_SOFT_INTSET */
- s->int_level |= (value & 1);
- integratorcm_update(s);
- break;
- case 21: /* CM_SOFT_INTCLR */
- s->int_level &= ~(value & 1);
- integratorcm_update(s);
- break;
- case 26: /* CM_FIQ_ENSET */
- s->fiq_enabled |= value;
- integratorcm_update(s);
- break;
- case 27: /* CM_FIQ_ENCLR */
- s->fiq_enabled &= ~value;
- integratorcm_update(s);
- break;
- case 32: /* CM_VOLTAGE_CTL0 */
- case 33: /* CM_VOLTAGE_CTL1 */
- case 34: /* CM_VOLTAGE_CTL2 */
- case 35: /* CM_VOLTAGE_CTL3 */
- /* ??? Voltage control unimplemented. */
- break;
- default:
- cpu_abort (cpu_single_env,
- "integratorcm_write: Unimplemented offset 0x%x\n", offset);
- break;
- }
-}
-
-/* Integrator/CM control registers. */
-
-static CPUReadMemoryFunc *integratorcm_readfn[] = {
- integratorcm_read,
- integratorcm_read,
- integratorcm_read
-};
-
-static CPUWriteMemoryFunc *integratorcm_writefn[] = {
- integratorcm_write,
- integratorcm_write,
- integratorcm_write
-};
-
-static void integratorcm_init(int memsz, uint32_t flash_offset)
-{
- int iomemtype;
- integratorcm_state *s;
-
- s = (integratorcm_state *)qemu_mallocz(sizeof(integratorcm_state));
- s->cm_osc = 0x01000048;
- /* ??? What should the high bits of this value be? */
- s->cm_auxosc = 0x0007feff;
- s->cm_sdram = 0x00011122;
- if (memsz >= 256) {
- integrator_spd[31] = 64;
- s->cm_sdram |= 0x10;
- } else if (memsz >= 128) {
- integrator_spd[31] = 32;
- s->cm_sdram |= 0x0c;
- } else if (memsz >= 64) {
- integrator_spd[31] = 16;
- s->cm_sdram |= 0x08;
- } else if (memsz >= 32) {
- integrator_spd[31] = 4;
- s->cm_sdram |= 0x04;
- } else {
- integrator_spd[31] = 2;
- }
- memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
- s->cm_init = 0x00000112;
- s->flash_offset = flash_offset;
-
- iomemtype = cpu_register_io_memory(0, integratorcm_readfn,
- integratorcm_writefn, s);
- cpu_register_physical_memory(0x10000000, 0x007fffff, iomemtype);
- integratorcm_do_remap(s, 1);
- /* ??? Save/restore. */
-}
-
-/* Integrator/CP hardware emulation. */
-/* Primary interrupt controller. */
-
-typedef struct icp_pic_state
-{
- arm_pic_handler handler;
- uint32_t base;
- uint32_t level;
- uint32_t irq_enabled;
- uint32_t fiq_enabled;
- void *parent;
- int parent_irq;
- int parent_fiq;
-} icp_pic_state;
-
-static void icp_pic_update(icp_pic_state *s)
-{
- uint32_t flags;
-
- if (s->parent_irq != -1) {
- flags = (s->level & s->irq_enabled);
- pic_set_irq_new(s->parent, s->parent_irq, flags != 0);
- }
- if (s->parent_fiq != -1) {
- flags = (s->level & s->fiq_enabled);
- pic_set_irq_new(s->parent, s->parent_fiq, flags != 0);
- }
-}
-
-static void icp_pic_set_irq(void *opaque, int irq, int level)
-{
- icp_pic_state *s = (icp_pic_state *)opaque;
- if (level)
- s->level |= 1 << irq;
- else
- s->level &= ~(1 << irq);
- icp_pic_update(s);
-}
-
-static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
-{
- icp_pic_state *s = (icp_pic_state *)opaque;
-
- offset -= s->base;
- switch (offset >> 2) {
- case 0: /* IRQ_STATUS */
- return s->level & s->irq_enabled;
- case 1: /* IRQ_RAWSTAT */
- return s->level;
- case 2: /* IRQ_ENABLESET */
- return s->irq_enabled;
- case 4: /* INT_SOFTSET */
- return s->level & 1;
- case 8: /* FRQ_STATUS */
- return s->level & s->fiq_enabled;
- case 9: /* FRQ_RAWSTAT */
- return s->level;
- case 10: /* FRQ_ENABLESET */
- return s->fiq_enabled;
- case 3: /* IRQ_ENABLECLR */
- case 5: /* INT_SOFTCLR */
- case 11: /* FRQ_ENABLECLR */
- default:
- printf ("icp_pic_read: Bad register offset 0x%x\n", offset);
- return 0;
- }
-}
-
-static void icp_pic_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- icp_pic_state *s = (icp_pic_state *)opaque;
- offset -= s->base;
-
- switch (offset >> 2) {
- case 2: /* IRQ_ENABLESET */
- s->irq_enabled |= value;
- break;
- case 3: /* IRQ_ENABLECLR */
- s->irq_enabled &= ~value;
- break;
- case 4: /* INT_SOFTSET */
- if (value & 1)
- pic_set_irq_new(s, 0, 1);
- break;
- case 5: /* INT_SOFTCLR */
- if (value & 1)
- pic_set_irq_new(s, 0, 0);
- break;
- case 10: /* FRQ_ENABLESET */
- s->fiq_enabled |= value;
- break;
- case 11: /* FRQ_ENABLECLR */
- s->fiq_enabled &= ~value;
- break;
- case 0: /* IRQ_STATUS */
- case 1: /* IRQ_RAWSTAT */
- case 8: /* FRQ_STATUS */
- case 9: /* FRQ_RAWSTAT */
- default:
- printf ("icp_pic_write: Bad register offset 0x%x\n", offset);
- return;
- }
- icp_pic_update(s);
-}
-
-static CPUReadMemoryFunc *icp_pic_readfn[] = {
- icp_pic_read,
- icp_pic_read,
- icp_pic_read
-};
-
-static CPUWriteMemoryFunc *icp_pic_writefn[] = {
- icp_pic_write,
- icp_pic_write,
- icp_pic_write
-};
-
-static icp_pic_state *icp_pic_init(uint32_t base, void *parent,
- int parent_irq, int parent_fiq)
-{
- icp_pic_state *s;
- int iomemtype;
-
- s = (icp_pic_state *)qemu_mallocz(sizeof(icp_pic_state));
- if (!s)
- return NULL;
- s->handler = icp_pic_set_irq;
- s->base = base;
- s->parent = parent;
- s->parent_irq = parent_irq;
- s->parent_fiq = parent_fiq;
- iomemtype = cpu_register_io_memory(0, icp_pic_readfn,
- icp_pic_writefn, s);
- cpu_register_physical_memory(base, 0x007fffff, iomemtype);
- /* ??? Save/restore. */
- return s;
-}
-
-/* CP control registers. */
-typedef struct {
- uint32_t base;
-} icp_control_state;
-
-static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
-{
- icp_control_state *s = (icp_control_state *)opaque;
- offset -= s->base;
- switch (offset >> 2) {
- case 0: /* CP_IDFIELD */
- return 0x41034003;
- case 1: /* CP_FLASHPROG */
- return 0;
- case 2: /* CP_INTREG */
- return 0;
- case 3: /* CP_DECODE */
- return 0x11;
- default:
- cpu_abort (cpu_single_env, "icp_control_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void icp_control_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- icp_control_state *s = (icp_control_state *)opaque;
- offset -= s->base;
- switch (offset >> 2) {
- case 1: /* CP_FLASHPROG */
- case 2: /* CP_INTREG */
- case 3: /* CP_DECODE */
- /* Nothing interesting implemented yet. */
- break;
- default:
- cpu_abort (cpu_single_env, "icp_control_write: Bad offset %x\n", offset);
- }
-}
-static CPUReadMemoryFunc *icp_control_readfn[] = {
- icp_control_read,
- icp_control_read,
- icp_control_read
-};
-
-static CPUWriteMemoryFunc *icp_control_writefn[] = {
- icp_control_write,
- icp_control_write,
- icp_control_write
-};
-
-static void icp_control_init(uint32_t base)
-{
- int iomemtype;
- icp_control_state *s;
-
- s = (icp_control_state *)qemu_mallocz(sizeof(icp_control_state));
- iomemtype = cpu_register_io_memory(0, icp_control_readfn,
- icp_control_writefn, s);
- cpu_register_physical_memory(base, 0x007fffff, iomemtype);
- s->base = base;
- /* ??? Save/restore. */
-}
-
-
-/* Board init. */
-
-static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename, uint32_t cpuid)
-{
- CPUState *env;
- uint32_t bios_offset;
- icp_pic_state *pic;
- void *cpu_pic;
-
- env = cpu_init();
- cpu_arm_set_model(env, cpuid);
- bios_offset = ram_size + vga_ram_size;
- /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */
- /* ??? RAM shoud repeat to fill physical memory space. */
- /* SDRAM at address zero*/
- cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
- /* And again at address 0x80000000 */
- cpu_register_physical_memory(0x80000000, ram_size, IO_MEM_RAM);
-
- integratorcm_init(ram_size >> 20, bios_offset);
- cpu_pic = arm_pic_init_cpu(env);
- pic = icp_pic_init(0x14000000, cpu_pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
- icp_pic_init(0xca000000, pic, 26, -1);
- icp_pit_init(0x13000000, pic, 5);
- pl011_init(0x16000000, pic, 1, serial_hds[0]);
- pl011_init(0x17000000, pic, 2, serial_hds[1]);
- icp_control_init(0xcb000000);
- pl050_init(0x18000000, pic, 3, 0);
- pl050_init(0x19000000, pic, 4, 1);
- if (nd_table[0].vlan) {
- if (nd_table[0].model == NULL
- || strcmp(nd_table[0].model, "smc91c111") == 0) {
- smc91c111_init(&nd_table[0], 0xc8000000, pic, 27);
- } else {
- fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
- exit (1);
- }
- }
- pl110_init(ds, 0xc0000000, pic, 22, 0);
-
- arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
- initrd_filename, 0x113);
-}
-
-static void integratorcp926_init(int ram_size, int vga_ram_size,
- int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
- snapshot, kernel_filename, kernel_cmdline,
- initrd_filename, ARM_CPUID_ARM926);
-}
-
-static void integratorcp1026_init(int ram_size, int vga_ram_size,
- int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
- snapshot, kernel_filename, kernel_cmdline,
- initrd_filename, ARM_CPUID_ARM1026);
-}
-
-QEMUMachine integratorcp926_machine = {
- "integratorcp926",
- "ARM Integrator/CP (ARM926EJ-S)",
- integratorcp926_init,
-};
-
-QEMUMachine integratorcp1026_machine = {
- "integratorcp1026",
- "ARM Integrator/CP (ARM1026EJ-S)",
- integratorcp1026_init,
-};
diff --git a/hw/iommu.c b/hw/iommu.c
deleted file mode 100644
index e7d96c8..0000000
--- a/hw/iommu.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * QEMU SPARC iommu emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug iommu */
-//#define DEBUG_IOMMU
-
-#ifdef DEBUG_IOMMU
-#define DPRINTF(fmt, args...) \
-do { printf("IOMMU: " fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...)
-#endif
-
-#define IOMMU_NREGS (3*4096/4)
-#define IOMMU_CTRL (0x0000 >> 2)
-#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
-#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
-#define IOMMU_VERSION 0x04000000
-#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
-#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
-#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
-#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
-#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
-#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
-#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
-#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
-#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
-#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
-#define IOMMU_CTRL_MASK 0x0000001d
-
-#define IOMMU_BASE (0x0004 >> 2)
-#define IOMMU_BASE_MASK 0x07fffc00
-
-#define IOMMU_TLBFLUSH (0x0014 >> 2)
-#define IOMMU_TLBFLUSH_MASK 0xffffffff
-
-#define IOMMU_PGFLUSH (0x0018 >> 2)
-#define IOMMU_PGFLUSH_MASK 0xffffffff
-
-#define IOMMU_SBCFG0 (0x1010 >> 2) /* SBUS configration per-slot */
-#define IOMMU_SBCFG1 (0x1014 >> 2) /* SBUS configration per-slot */
-#define IOMMU_SBCFG2 (0x1018 >> 2) /* SBUS configration per-slot */
-#define IOMMU_SBCFG3 (0x101c >> 2) /* SBUS configration per-slot */
-#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
-#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
-#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
-#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
- produced by this device as pure
- physical. */
-#define IOMMU_SBCFG_MASK 0x00010003
-
-#define IOMMU_ARBEN (0x2000 >> 2) /* SBUS arbitration enable */
-#define IOMMU_ARBEN_MASK 0x001f0000
-#define IOMMU_MID 0x00000008
-
-/* The format of an iopte in the page tables */
-#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
-#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
-#define IOPTE_WRITE 0x00000004 /* Writeable */
-#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
-#define IOPTE_WAZ 0x00000001 /* Write as zeros */
-
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1 << PAGE_SHIFT)
-#define PAGE_MASK (PAGE_SIZE - 1)
-
-typedef struct IOMMUState {
- uint32_t addr;
- uint32_t regs[IOMMU_NREGS];
- uint32_t iostart;
-} IOMMUState;
-
-static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
-{
- IOMMUState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr - s->addr) >> 2;
- switch (saddr) {
- default:
- DPRINTF("read reg[%d] = %x\n", saddr, s->regs[saddr]);
- return s->regs[saddr];
- break;
- }
- return 0;
-}
-
-static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- IOMMUState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr - s->addr) >> 2;
- DPRINTF("write reg[%d] = %x\n", saddr, val);
- switch (saddr) {
- case IOMMU_CTRL:
- switch (val & IOMMU_CTRL_RNGE) {
- case IOMMU_RNGE_16MB:
- s->iostart = 0xff000000;
- break;
- case IOMMU_RNGE_32MB:
- s->iostart = 0xfe000000;
- break;
- case IOMMU_RNGE_64MB:
- s->iostart = 0xfc000000;
- break;
- case IOMMU_RNGE_128MB:
- s->iostart = 0xf8000000;
- break;
- case IOMMU_RNGE_256MB:
- s->iostart = 0xf0000000;
- break;
- case IOMMU_RNGE_512MB:
- s->iostart = 0xe0000000;
- break;
- case IOMMU_RNGE_1GB:
- s->iostart = 0xc0000000;
- break;
- default:
- case IOMMU_RNGE_2GB:
- s->iostart = 0x80000000;
- break;
- }
- DPRINTF("iostart = %x\n", s->iostart);
- s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | IOMMU_VERSION);
- break;
- case IOMMU_BASE:
- s->regs[saddr] = val & IOMMU_BASE_MASK;
- break;
- case IOMMU_TLBFLUSH:
- DPRINTF("tlb flush %x\n", val);
- s->regs[saddr] = val & IOMMU_TLBFLUSH_MASK;
- break;
- case IOMMU_PGFLUSH:
- DPRINTF("page flush %x\n", val);
- s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;
- break;
- case IOMMU_SBCFG0:
- case IOMMU_SBCFG1:
- case IOMMU_SBCFG2:
- case IOMMU_SBCFG3:
- s->regs[saddr] = val & IOMMU_SBCFG_MASK;
- break;
- case IOMMU_ARBEN:
- // XXX implement SBus probing: fault when reading unmapped
- // addresses, fault cause and address stored to MMU/IOMMU
- s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID;
- break;
- default:
- s->regs[saddr] = val;
- break;
- }
-}
-
-static CPUReadMemoryFunc *iommu_mem_read[3] = {
- iommu_mem_readw,
- iommu_mem_readw,
- iommu_mem_readw,
-};
-
-static CPUWriteMemoryFunc *iommu_mem_write[3] = {
- iommu_mem_writew,
- iommu_mem_writew,
- iommu_mem_writew,
-};
-
-uint32_t iommu_translate_local(void *opaque, uint32_t addr)
-{
- IOMMUState *s = opaque;
- uint32_t iopte, pa, tmppte;
-
- iopte = s->regs[1] << 4;
- addr &= ~s->iostart;
- iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
- pa = ldl_phys(iopte);
- tmppte = pa;
- pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
- DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte);
- return pa;
-}
-
-static void iommu_save(QEMUFile *f, void *opaque)
-{
- IOMMUState *s = opaque;
- int i;
-
- qemu_put_be32s(f, &s->addr);
- for (i = 0; i < IOMMU_NREGS; i++)
- qemu_put_be32s(f, &s->regs[i]);
- qemu_put_be32s(f, &s->iostart);
-}
-
-static int iommu_load(QEMUFile *f, void *opaque, int version_id)
-{
- IOMMUState *s = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->addr);
- for (i = 0; i < IOMMU_NREGS; i++)
- qemu_put_be32s(f, &s->regs[i]);
- qemu_get_be32s(f, &s->iostart);
-
- return 0;
-}
-
-static void iommu_reset(void *opaque)
-{
- IOMMUState *s = opaque;
-
- memset(s->regs, 0, IOMMU_NREGS * 4);
- s->iostart = 0;
- s->regs[0] = IOMMU_VERSION;
-}
-
-void *iommu_init(uint32_t addr)
-{
- IOMMUState *s;
- int iommu_io_memory;
-
- s = qemu_mallocz(sizeof(IOMMUState));
- if (!s)
- return NULL;
-
- s->addr = addr;
-
- iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
- cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory);
-
- register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
- qemu_register_reset(iommu_reset, s);
- return s;
-}
-
diff --git a/hw/irq.c b/hw/irq.c
new file mode 100644
index 0000000..3621b8e
--- /dev/null
+++ b/hw/irq.c
@@ -0,0 +1,71 @@
+/*
+ * QEMU IRQ/GPIO common code.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "irq.h"
+
+struct IRQState {
+ qemu_irq_handler handler;
+ void *opaque;
+ int n;
+};
+
+void qemu_set_irq(qemu_irq irq, int level)
+{
+ if (!irq)
+ return;
+
+ irq->handler(irq->opaque, irq->n, level);
+}
+
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+{
+ qemu_irq *s;
+ struct IRQState *p;
+ int i;
+
+ s = (qemu_irq *)qemu_mallocz(sizeof(qemu_irq) * n);
+ p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n);
+ for (i = 0; i < n; i++) {
+ p->handler = handler;
+ p->opaque = opaque;
+ p->n = i;
+ s[i] = p;
+ p++;
+ }
+ return s;
+}
+
+static void qemu_notirq(void *opaque, int line, int level)
+{
+ struct IRQState *irq = opaque;
+
+ irq->handler(irq->opaque, irq->n, !level);
+}
+
+qemu_irq qemu_irq_invert(qemu_irq irq)
+{
+ /* The default state for IRQs is low, so raise the output now. */
+ qemu_irq_raise(irq);
+ return qemu_allocate_irqs(qemu_notirq, irq, 1)[0];
+}
diff --git a/hw/irq.h b/hw/irq.h
new file mode 100644
index 0000000..814511a
--- /dev/null
+++ b/hw/irq.h
@@ -0,0 +1,32 @@
+#ifndef QEMU_IRQ_H
+#define QEMU_IRQ_H
+
+/* Generic IRQ/GPIO pin infrastructure. */
+
+typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
+
+void qemu_set_irq(qemu_irq irq, int level);
+
+static inline void qemu_irq_raise(qemu_irq irq)
+{
+ qemu_set_irq(irq, 1);
+}
+
+static inline void qemu_irq_lower(qemu_irq irq)
+{
+ qemu_set_irq(irq, 0);
+}
+
+static inline void qemu_irq_pulse(qemu_irq irq)
+{
+ qemu_set_irq(irq, 1);
+ qemu_set_irq(irq, 0);
+}
+
+/* Returns an array of N IRQs. */
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+
+/* Returns a new IRQ with opposite polarity. */
+qemu_irq qemu_irq_invert(qemu_irq irq);
+
+#endif
diff --git a/hw/lance.c b/hw/lance.c
deleted file mode 100644
index d167937..0000000
--- a/hw/lance.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * QEMU Lance emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug LANCE card */
-//#define DEBUG_LANCE
-
-#ifdef DEBUG_LANCE
-#define DPRINTF(fmt, args...) \
-do { printf("LANCE: " fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...)
-#endif
-
-#ifndef LANCE_LOG_TX_BUFFERS
-#define LANCE_LOG_TX_BUFFERS 4
-#define LANCE_LOG_RX_BUFFERS 4
-#endif
-
-#define LE_CSR0 0
-#define LE_CSR1 1
-#define LE_CSR2 2
-#define LE_CSR3 3
-#define LE_NREGS (LE_CSR3 + 1)
-#define LE_MAXREG LE_CSR3
-
-#define LE_RDP 0
-#define LE_RAP 1
-
-#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */
-
-#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */
-#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */
-#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */
-#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */
-#define LE_C0_MERR 0x0800 /* ME: Memory error */
-#define LE_C0_RINT 0x0400 /* Received interrupt */
-#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */
-#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */
-#define LE_C0_INTR 0x0080 /* Interrupt or error */
-#define LE_C0_INEA 0x0040 /* Interrupt enable */
-#define LE_C0_RXON 0x0020 /* Receiver on */
-#define LE_C0_TXON 0x0010 /* Transmitter on */
-#define LE_C0_TDMD 0x0008 /* Transmitter demand */
-#define LE_C0_STOP 0x0004 /* Stop the card */
-#define LE_C0_STRT 0x0002 /* Start the card */
-#define LE_C0_INIT 0x0001 /* Init the card */
-
-#define LE_C3_BSWP 0x4 /* SWAP */
-#define LE_C3_ACON 0x2 /* ALE Control */
-#define LE_C3_BCON 0x1 /* Byte control */
-
-/* Receive message descriptor 1 */
-#define LE_R1_OWN 0x80 /* Who owns the entry */
-#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */
-#define LE_R1_FRA 0x20 /* FRA: Frame error */
-#define LE_R1_OFL 0x10 /* OFL: Frame overflow */
-#define LE_R1_CRC 0x08 /* CRC error */
-#define LE_R1_BUF 0x04 /* BUF: Buffer error */
-#define LE_R1_SOP 0x02 /* Start of packet */
-#define LE_R1_EOP 0x01 /* End of packet */
-#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */
-
-#define LE_T1_OWN 0x80 /* Lance owns the packet */
-#define LE_T1_ERR 0x40 /* Error summary */
-#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */
-#define LE_T1_EONE 0x08 /* Error: one retry needed */
-#define LE_T1_EDEF 0x04 /* Error: deferred */
-#define LE_T1_SOP 0x02 /* Start of packet */
-#define LE_T1_EOP 0x01 /* End of packet */
-#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */
-
-#define LE_T3_BUF 0x8000 /* Buffer error */
-#define LE_T3_UFL 0x4000 /* Error underflow */
-#define LE_T3_LCOL 0x1000 /* Error late collision */
-#define LE_T3_CLOS 0x0800 /* Error carrier loss */
-#define LE_T3_RTY 0x0400 /* Error retry */
-#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */
-
-#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
-#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
-#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
-
-#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
-#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
-#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
-
-#define PKT_BUF_SZ 1544
-#define RX_BUFF_SIZE PKT_BUF_SZ
-#define TX_BUFF_SIZE PKT_BUF_SZ
-
-struct lance_rx_desc {
- unsigned short rmd0; /* low address of packet */
- unsigned char rmd1_bits; /* descriptor bits */
- unsigned char rmd1_hadr; /* high address of packet */
- short length; /* This length is 2s complement (negative)!
- * Buffer length
- */
- unsigned short mblength; /* This is the actual number of bytes received */
-};
-
-struct lance_tx_desc {
- unsigned short tmd0; /* low address of packet */
- unsigned char tmd1_bits; /* descriptor bits */
- unsigned char tmd1_hadr; /* high address of packet */
- short length; /* Length is 2s complement (negative)! */
- unsigned short misc;
-};
-
-/* The LANCE initialization block, described in databook. */
-/* On the Sparc, this block should be on a DMA region */
-struct lance_init_block {
- unsigned short mode; /* Pre-set mode (reg. 15) */
- unsigned char phys_addr[6]; /* Physical ethernet address */
- unsigned filter[2]; /* Multicast filter. */
-
- /* Receive and transmit ring base, along with extra bits. */
- unsigned short rx_ptr; /* receive descriptor addr */
- unsigned short rx_len; /* receive len and high addr */
- unsigned short tx_ptr; /* transmit descriptor addr */
- unsigned short tx_len; /* transmit len and high addr */
-
- /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
- struct lance_rx_desc brx_ring[RX_RING_SIZE];
- struct lance_tx_desc btx_ring[TX_RING_SIZE];
-
- char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
- char pad[2]; /* align rx_buf for copy_and_sum(). */
- char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
-};
-
-#define LEDMA_REGS 4
-#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
-
-typedef struct LANCEState {
- VLANClientState *vc;
- uint8_t macaddr[6]; /* init mac address */
- uint32_t leptr;
- uint16_t addr;
- uint16_t regs[LE_NREGS];
- uint8_t phys[6]; /* mac address */
- int irq;
- unsigned int rxptr, txptr;
- uint32_t ledmaregs[LEDMA_REGS];
-} LANCEState;
-
-static void lance_send(void *opaque);
-
-static void lance_reset(void *opaque)
-{
- LANCEState *s = opaque;
- memcpy(s->phys, s->macaddr, 6);
- s->rxptr = 0;
- s->txptr = 0;
- memset(s->regs, 0, LE_NREGS * 2);
- s->regs[LE_CSR0] = LE_C0_STOP;
- memset(s->ledmaregs, 0, LEDMA_REGS * 4);
-}
-
-static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
-{
- LANCEState *s = opaque;
- uint32_t saddr;
-
- saddr = addr & LE_MAXREG;
- switch (saddr >> 1) {
- case LE_RDP:
- DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]);
- return s->regs[s->addr];
- case LE_RAP:
- DPRINTF("read areg = %4.4x\n", s->addr);
- return s->addr;
- default:
- DPRINTF("read unknown(%d)\n", saddr>>1);
- break;
- }
- return 0;
-}
-
-static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LANCEState *s = opaque;
- uint32_t saddr;
- uint16_t reg;
-
- saddr = addr & LE_MAXREG;
- switch (saddr >> 1) {
- case LE_RDP:
- DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val);
- switch(s->addr) {
- case LE_CSR0:
- if (val & LE_C0_STOP) {
- s->regs[LE_CSR0] = LE_C0_STOP;
- break;
- }
-
- reg = s->regs[LE_CSR0];
-
- // 1 = clear for some bits
- reg &= ~(val & 0x7f00);
-
- // generated bits
- reg &= ~(LE_C0_ERR | LE_C0_INTR);
- if (reg & 0x7100)
- reg |= LE_C0_ERR;
- if (reg & 0x7f00)
- reg |= LE_C0_INTR;
-
- // direct bit
- reg &= ~LE_C0_INEA;
- reg |= val & LE_C0_INEA;
-
- // exclusive bits
- if (val & LE_C0_INIT) {
- reg |= LE_C0_IDON | LE_C0_INIT;
- reg &= ~LE_C0_STOP;
- }
- else if (val & LE_C0_STRT) {
- reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
- reg &= ~LE_C0_STOP;
- }
-
- s->regs[LE_CSR0] = reg;
- break;
- case LE_CSR1:
- s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
- s->regs[s->addr] = val;
- break;
- case LE_CSR2:
- s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
- s->regs[s->addr] = val;
- break;
- case LE_CSR3:
- s->regs[s->addr] = val;
- break;
- }
- break;
- case LE_RAP:
- DPRINTF("write areg = %4.4x\n", val);
- if (val < LE_NREGS)
- s->addr = val;
- break;
- default:
- DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val);
- break;
- }
- lance_send(s);
-}
-
-static CPUReadMemoryFunc *lance_mem_read[3] = {
- lance_mem_readw,
- lance_mem_readw,
- lance_mem_readw,
-};
-
-static CPUWriteMemoryFunc *lance_mem_write[3] = {
- lance_mem_writew,
- lance_mem_writew,
- lance_mem_writew,
-};
-
-
-#define MIN_BUF_SIZE 60
-
-static int lance_can_receive(void *opaque)
-{
- return 1;
-}
-
-static void lance_receive(void *opaque, const uint8_t *buf, int size)
-{
- LANCEState *s = opaque;
- uint32_t dmaptr = s->leptr + s->ledmaregs[3];
- struct lance_init_block *ib;
- unsigned int i, old_rxptr;
- uint16_t temp16;
- uint8_t temp8;
-
- DPRINTF("receive size %d\n", size);
- if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
- return;
-
- ib = (void *) iommu_translate(dmaptr);
-
- old_rxptr = s->rxptr;
- for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
- cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
- if (temp8 == (LE_R1_OWN)) {
- s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
- temp16 = size + 4;
- bswap16s(&temp16);
- cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2);
- cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
- temp8 = LE_R1_POK;
- cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
- s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
- if (s->regs[LE_CSR0] & LE_C0_INEA)
- pic_set_irq(s->irq, 1);
- DPRINTF("got packet, len %d\n", size);
- return;
- }
- }
-}
-
-static void lance_send(void *opaque)
-{
- LANCEState *s = opaque;
- uint32_t dmaptr = s->leptr + s->ledmaregs[3];
- struct lance_init_block *ib;
- unsigned int i, old_txptr;
- uint16_t temp16;
- uint8_t temp8;
- char pkt_buf[PKT_BUF_SZ];
-
- DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]);
- if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
- return;
-
- ib = (void *) iommu_translate(dmaptr);
-
- DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring);
- old_txptr = s->txptr;
- for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
- cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
- if (temp8 == (LE_T1_POK|LE_T1_OWN)) {
- cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2);
- bswap16s(&temp16);
- temp16 = (~temp16) + 1;
- cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16);
- DPRINTF("sending packet, len %d\n", temp16);
- qemu_send_packet(s->vc, pkt_buf, temp16);
- temp8 = LE_T1_POK;
- cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
- s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
- s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
- }
- }
- if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
- pic_set_irq(s->irq, 1);
-}
-
-static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- LANCEState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & LEDMA_MAXADDR) >> 2;
- return s->ledmaregs[saddr];
-}
-
-static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LANCEState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & LEDMA_MAXADDR) >> 2;
- s->ledmaregs[saddr] = val;
-}
-
-static CPUReadMemoryFunc *ledma_mem_read[3] = {
- ledma_mem_readl,
- ledma_mem_readl,
- ledma_mem_readl,
-};
-
-static CPUWriteMemoryFunc *ledma_mem_write[3] = {
- ledma_mem_writel,
- ledma_mem_writel,
- ledma_mem_writel,
-};
-
-static void lance_save(QEMUFile *f, void *opaque)
-{
- LANCEState *s = opaque;
- int i;
-
- qemu_put_be32s(f, &s->leptr);
- qemu_put_be16s(f, &s->addr);
- for (i = 0; i < LE_NREGS; i ++)
- qemu_put_be16s(f, &s->regs[i]);
- qemu_put_buffer(f, s->phys, 6);
- qemu_put_be32s(f, &s->irq);
- for (i = 0; i < LEDMA_REGS; i ++)
- qemu_put_be32s(f, &s->ledmaregs[i]);
-}
-
-static int lance_load(QEMUFile *f, void *opaque, int version_id)
-{
- LANCEState *s = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->leptr);
- qemu_get_be16s(f, &s->addr);
- for (i = 0; i < LE_NREGS; i ++)
- qemu_get_be16s(f, &s->regs[i]);
- qemu_get_buffer(f, s->phys, 6);
- qemu_get_be32s(f, &s->irq);
- for (i = 0; i < LEDMA_REGS; i ++)
- qemu_get_be32s(f, &s->ledmaregs[i]);
- return 0;
-}
-
-void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
-{
- LANCEState *s;
- int lance_io_memory, ledma_io_memory;
-
- s = qemu_mallocz(sizeof(LANCEState));
- if (!s)
- return;
-
- s->irq = irq;
-
- lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
- cpu_register_physical_memory(leaddr, 4, lance_io_memory);
-
- ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
- cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
-
- memcpy(s->macaddr, nd->macaddr, 6);
-
- lance_reset(s);
-
- s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, s);
-
- snprintf(s->vc->info_str, sizeof(s->vc->info_str),
- "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
- s->macaddr[0],
- s->macaddr[1],
- s->macaddr[2],
- s->macaddr[3],
- s->macaddr[4],
- s->macaddr[5]);
-
- register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
- qemu_register_reset(lance_reset, s);
-}
-
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
deleted file mode 100644
index 24dff0e..0000000
--- a/hw/lsi53c895a.c
+++ /dev/null
@@ -1,1571 +0,0 @@
-/*
- * QEMU LSI53C895A SCSI Host Bus Adapter emulation
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the LGPL.
- */
-
-/* ??? Need to check if the {read,write}[wl] routines work properly on
- big-endian targets. */
-
-#include "vl.h"
-
-//#define DEBUG_LSI
-//#define DEBUG_LSI_REG
-
-#ifdef DEBUG_LSI
-#define DPRINTF(fmt, args...) \
-do { printf("lsi_scsi: " fmt , ##args); } while (0)
-#define BADF(fmt, args...) \
-do { fprintf(stderr, "lsi_scsi: " fmt , ##args); exit(1);} while (0)
-#else
-#define DPRINTF(fmt, args...) do {} while(0)
-#define BADF(fmt, args...) \
-do { fprintf(stderr, "lsi_scsi: " fmt , ##args); } while (0)
-#endif
-
-#define LSI_SCNTL0_TRG 0x01
-#define LSI_SCNTL0_AAP 0x02
-#define LSI_SCNTL0_EPC 0x08
-#define LSI_SCNTL0_WATN 0x10
-#define LSI_SCNTL0_START 0x20
-
-#define LSI_SCNTL1_SST 0x01
-#define LSI_SCNTL1_IARB 0x02
-#define LSI_SCNTL1_AESP 0x04
-#define LSI_SCNTL1_RST 0x08
-#define LSI_SCNTL1_CON 0x10
-#define LSI_SCNTL1_DHP 0x20
-#define LSI_SCNTL1_ADB 0x40
-#define LSI_SCNTL1_EXC 0x80
-
-#define LSI_SCNTL2_WSR 0x01
-#define LSI_SCNTL2_VUE0 0x02
-#define LSI_SCNTL2_VUE1 0x04
-#define LSI_SCNTL2_WSS 0x08
-#define LSI_SCNTL2_SLPHBEN 0x10
-#define LSI_SCNTL2_SLPMD 0x20
-#define LSI_SCNTL2_CHM 0x40
-#define LSI_SCNTL2_SDU 0x80
-
-#define LSI_ISTAT0_DIP 0x01
-#define LSI_ISTAT0_SIP 0x02
-#define LSI_ISTAT0_INTF 0x04
-#define LSI_ISTAT0_CON 0x08
-#define LSI_ISTAT0_SEM 0x10
-#define LSI_ISTAT0_SIGP 0x20
-#define LSI_ISTAT0_SRST 0x40
-#define LSI_ISTAT0_ABRT 0x80
-
-#define LSI_ISTAT1_SI 0x01
-#define LSI_ISTAT1_SRUN 0x02
-#define LSI_ISTAT1_FLSH 0x04
-
-#define LSI_SSTAT0_SDP0 0x01
-#define LSI_SSTAT0_RST 0x02
-#define LSI_SSTAT0_WOA 0x04
-#define LSI_SSTAT0_LOA 0x08
-#define LSI_SSTAT0_AIP 0x10
-#define LSI_SSTAT0_OLF 0x20
-#define LSI_SSTAT0_ORF 0x40
-#define LSI_SSTAT0_ILF 0x80
-
-#define LSI_SIST0_PAR 0x01
-#define LSI_SIST0_RST 0x02
-#define LSI_SIST0_UDC 0x04
-#define LSI_SIST0_SGE 0x08
-#define LSI_SIST0_RSL 0x10
-#define LSI_SIST0_SEL 0x20
-#define LSI_SIST0_CMP 0x40
-#define LSI_SIST0_MA 0x80
-
-#define LSI_SIST1_HTH 0x01
-#define LSI_SIST1_GEN 0x02
-#define LSI_SIST1_STO 0x04
-#define LSI_SIST1_SBMC 0x10
-
-#define LSI_SOCL_IO 0x01
-#define LSI_SOCL_CD 0x02
-#define LSI_SOCL_MSG 0x04
-#define LSI_SOCL_ATN 0x08
-#define LSI_SOCL_SEL 0x10
-#define LSI_SOCL_BSY 0x20
-#define LSI_SOCL_ACK 0x40
-#define LSI_SOCL_REQ 0x80
-
-#define LSI_DSTAT_IID 0x01
-#define LSI_DSTAT_SIR 0x04
-#define LSI_DSTAT_SSI 0x08
-#define LSI_DSTAT_ABRT 0x10
-#define LSI_DSTAT_BF 0x20
-#define LSI_DSTAT_MDPE 0x40
-#define LSI_DSTAT_DFE 0x80
-
-#define LSI_DCNTL_COM 0x01
-#define LSI_DCNTL_IRQD 0x02
-#define LSI_DCNTL_STD 0x04
-#define LSI_DCNTL_IRQM 0x08
-#define LSI_DCNTL_SSM 0x10
-#define LSI_DCNTL_PFEN 0x20
-#define LSI_DCNTL_PFF 0x40
-#define LSI_DCNTL_CLSE 0x80
-
-#define LSI_DMODE_MAN 0x01
-#define LSI_DMODE_BOF 0x02
-#define LSI_DMODE_ERMP 0x04
-#define LSI_DMODE_ERL 0x08
-#define LSI_DMODE_DIOM 0x10
-#define LSI_DMODE_SIOM 0x20
-
-#define LSI_CTEST2_DACK 0x01
-#define LSI_CTEST2_DREQ 0x02
-#define LSI_CTEST2_TEOP 0x04
-#define LSI_CTEST2_PCICIE 0x08
-#define LSI_CTEST2_CM 0x10
-#define LSI_CTEST2_CIO 0x20
-#define LSI_CTEST2_SIGP 0x40
-#define LSI_CTEST2_DDIR 0x80
-
-#define LSI_CTEST5_BL2 0x04
-#define LSI_CTEST5_DDIR 0x08
-#define LSI_CTEST5_MASR 0x10
-#define LSI_CTEST5_DFSN 0x20
-#define LSI_CTEST5_BBCK 0x40
-#define LSI_CTEST5_ADCK 0x80
-
-#define LSI_CCNTL0_DILS 0x01
-#define LSI_CCNTL0_DISFC 0x10
-#define LSI_CCNTL0_ENNDJ 0x20
-#define LSI_CCNTL0_PMJCTL 0x40
-#define LSI_CCNTL0_ENPMJ 0x80
-
-#define PHASE_DO 0
-#define PHASE_DI 1
-#define PHASE_CMD 2
-#define PHASE_ST 3
-#define PHASE_MO 6
-#define PHASE_MI 7
-#define PHASE_MASK 7
-
-/* The HBA is ID 7, so for simplicitly limit to 7 devices. */
-#define LSI_MAX_DEVS 7
-
-typedef struct {
- PCIDevice pci_dev;
- int mmio_io_addr;
- int ram_io_addr;
- uint32_t script_ram_base;
- uint32_t data_len;
-
- int carry; /* ??? Should this be an a visible register somewhere? */
- int sense;
- uint8_t msg;
- /* Nonzero if a Wait Reselect instruction has been issued. */
- int waiting;
- SCSIDevice *scsi_dev[LSI_MAX_DEVS];
- SCSIDevice *current_dev;
- int current_lun;
-
- uint32_t dsa;
- uint32_t temp;
- uint32_t dnad;
- uint32_t dbc;
- uint8_t istat0;
- uint8_t istat1;
- uint8_t dcmd;
- uint8_t dstat;
- uint8_t dien;
- uint8_t sist0;
- uint8_t sist1;
- uint8_t sien0;
- uint8_t sien1;
- uint8_t mbox0;
- uint8_t mbox1;
- uint8_t dfifo;
- uint8_t ctest3;
- uint8_t ctest4;
- uint8_t ctest5;
- uint8_t ccntl0;
- uint8_t ccntl1;
- uint32_t dsp;
- uint32_t dsps;
- uint8_t dmode;
- uint8_t dcntl;
- uint8_t scntl0;
- uint8_t scntl1;
- uint8_t scntl2;
- uint8_t scntl3;
- uint8_t sstat0;
- uint8_t sstat1;
- uint8_t scid;
- uint8_t sxfer;
- uint8_t socl;
- uint8_t sdid;
- uint8_t sfbr;
- uint8_t stest1;
- uint8_t stest2;
- uint8_t stest3;
- uint8_t stime0;
- uint8_t respid0;
- uint8_t respid1;
- uint32_t mmrs;
- uint32_t mmws;
- uint32_t sfs;
- uint32_t drs;
- uint32_t sbms;
- uint32_t dmbs;
- uint32_t dnad64;
- uint32_t pmjad1;
- uint32_t pmjad2;
- uint32_t rbc;
- uint32_t ua;
- uint32_t ia;
- uint32_t sbc;
- uint32_t csbc;
- uint32_t scratch[13]; /* SCRATCHA-SCRATCHR */
-
- /* Script ram is stored as 32-bit words in host byteorder. */
- uint32_t script_ram[2048];
-} LSIState;
-
-static void lsi_soft_reset(LSIState *s)
-{
- DPRINTF("Reset\n");
- s->carry = 0;
-
- s->waiting = 0;
- s->dsa = 0;
- s->dnad = 0;
- s->dbc = 0;
- s->temp = 0;
- memset(s->scratch, 0, sizeof(s->scratch));
- s->istat0 = 0;
- s->istat1 = 0;
- s->dcmd = 0;
- s->dstat = 0;
- s->dien = 0;
- s->sist0 = 0;
- s->sist1 = 0;
- s->sien0 = 0;
- s->sien1 = 0;
- s->mbox0 = 0;
- s->mbox1 = 0;
- s->dfifo = 0;
- s->ctest3 = 0;
- s->ctest4 = 0;
- s->ctest5 = 0;
- s->ccntl0 = 0;
- s->ccntl1 = 0;
- s->dsp = 0;
- s->dsps = 0;
- s->dmode = 0;
- s->dcntl = 0;
- s->scntl0 = 0xc0;
- s->scntl1 = 0;
- s->scntl2 = 0;
- s->scntl3 = 0;
- s->sstat0 = 0;
- s->sstat1 = 0;
- s->scid = 7;
- s->sxfer = 0;
- s->socl = 0;
- s->stest1 = 0;
- s->stest2 = 0;
- s->stest3 = 0;
- s->stime0 = 0;
- s->respid0 = 0x80;
- s->respid1 = 0;
- s->mmrs = 0;
- s->mmws = 0;
- s->sfs = 0;
- s->drs = 0;
- s->sbms = 0;
- s->dmbs = 0;
- s->dnad64 = 0;
- s->pmjad1 = 0;
- s->pmjad2 = 0;
- s->rbc = 0;
- s->ua = 0;
- s->ia = 0;
- s->sbc = 0;
- s->csbc = 0;
-}
-
-static uint8_t lsi_reg_readb(LSIState *s, int offset);
-static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
-
-static inline uint32_t read_dword(LSIState *s, uint32_t addr)
-{
- uint32_t buf;
-
- /* Optimize reading from SCRIPTS RAM. */
- if ((addr & 0xffffe000) == s->script_ram_base) {
- return s->script_ram[(addr & 0x1fff) >> 2];
- }
- cpu_physical_memory_read(addr, (uint8_t *)&buf, 4);
- return cpu_to_le32(buf);
-}
-
-static void lsi_stop_script(LSIState *s)
-{
- s->istat1 &= ~LSI_ISTAT1_SRUN;
-}
-
-static void lsi_update_irq(LSIState *s)
-{
- int level;
- static int last_level;
-
- /* It's unclear whether the DIP/SIP bits should be cleared when the
- Interrupt Status Registers are cleared or when istat0 is read.
- We currently do the formwer, which seems to work. */
- level = 0;
- if (s->dstat) {
- if (s->dstat & s->dien)
- level = 1;
- s->istat0 |= LSI_ISTAT0_DIP;
- } else {
- s->istat0 &= ~LSI_ISTAT0_DIP;
- }
-
- if (s->sist0 || s->sist1) {
- if ((s->sist0 & s->sien0) || (s->sist1 & s->sien1))
- level = 1;
- s->istat0 |= LSI_ISTAT0_SIP;
- } else {
- s->istat0 &= ~LSI_ISTAT0_SIP;
- }
- if (s->istat0 & LSI_ISTAT0_INTF)
- level = 1;
-
- if (level != last_level) {
- DPRINTF("Update IRQ level %d dstat %02x sist %02x%02x\n",
- level, s->dstat, s->sist1, s->sist0);
- last_level = level;
- }
- pci_set_irq(&s->pci_dev, 0, level);
-}
-
-/* Stop SCRIPTS execution and raise a SCSI interrupt. */
-static void lsi_script_scsi_interrupt(LSIState *s, int stat0, int stat1)
-{
- uint32_t mask0;
- uint32_t mask1;
-
- DPRINTF("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n",
- stat1, stat0, s->sist1, s->sist0);
- s->sist0 |= stat0;
- s->sist1 |= stat1;
- /* Stop processor on fatal or unmasked interrupt. As a special hack
- we don't stop processing when raising STO. Instead continue
- execution and stop at the next insn that accesses the SCSI bus. */
- mask0 = s->sien0 | ~(LSI_SIST0_CMP | LSI_SIST0_SEL | LSI_SIST0_RSL);
- mask1 = s->sien1 | ~(LSI_SIST1_GEN | LSI_SIST1_HTH);
- mask1 &= ~LSI_SIST1_STO;
- if (s->sist0 & mask0 || s->sist1 & mask1) {
- lsi_stop_script(s);
- }
- lsi_update_irq(s);
-}
-
-/* Stop SCRIPTS execution and raise a DMA interrupt. */
-static void lsi_script_dma_interrupt(LSIState *s, int stat)
-{
- DPRINTF("DMA Interrupt 0x%x prev 0x%x\n", stat, s->dstat);
- s->dstat |= stat;
- lsi_update_irq(s);
- lsi_stop_script(s);
-}
-
-static inline void lsi_set_phase(LSIState *s, int phase)
-{
- s->sstat1 = (s->sstat1 & ~PHASE_MASK) | phase;
-}
-
-static void lsi_bad_phase(LSIState *s, int out, int new_phase)
-{
- /* Trigger a phase mismatch. */
- if (s->ccntl0 & LSI_CCNTL0_ENPMJ) {
- if ((s->ccntl0 & LSI_CCNTL0_PMJCTL) || out) {
- s->dsp = s->pmjad1;
- } else {
- s->dsp = s->pmjad2;
- }
- DPRINTF("Data phase mismatch jump to %08x\n", s->dsp);
- } else {
- DPRINTF("Phase mismatch interrupt\n");
- lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
- lsi_stop_script(s);
- }
- lsi_set_phase(s, new_phase);
-}
-
-static void lsi_do_dma(LSIState *s, int out)
-{
- uint8_t buf[TARGET_PAGE_SIZE];
- uint32_t addr;
- uint32_t count;
- int n;
-
- count = s->dbc;
- addr = s->dnad;
- DPRINTF("DMA %s addr=0x%08x len=%d avail=%d\n", out ? "out" : "in",
- addr, count, s->data_len);
- /* ??? Too long transfers are truncated. Don't know if this is the
- correct behavior. */
- if (count > s->data_len) {
- /* If the DMA length is greater then the device data length then
- a phase mismatch will occur. */
- count = s->data_len;
- s->dbc = count;
- lsi_bad_phase(s, out, PHASE_ST);
- }
-
- s->csbc += count;
-
- /* ??? Set SFBR to first data byte. */
- while (count) {
- n = (count > TARGET_PAGE_SIZE) ? TARGET_PAGE_SIZE : count;
- if (out) {
- cpu_physical_memory_read(addr, buf, n);
- scsi_write_data(s->current_dev, buf, n);
- } else {
- scsi_read_data(s->current_dev, buf, n);
- cpu_physical_memory_write(addr, buf, n);
- }
- addr += n;
- count -= n;
- }
-}
-
-
-static void lsi_do_command(LSIState *s)
-{
- uint8_t buf[16];
- int n;
-
- DPRINTF("Send command len=%d\n", s->dbc);
- if (s->dbc > 16)
- s->dbc = 16;
- cpu_physical_memory_read(s->dnad, buf, s->dbc);
- s->sfbr = buf[0];
- n = scsi_send_command(s->current_dev, 0, buf, s->current_lun);
- if (n > 0) {
- s->data_len = n;
- lsi_set_phase(s, PHASE_DI);
- } else if (n < 0) {
- s->data_len = -n;
- lsi_set_phase(s, PHASE_DO);
- }
-}
-
-static void lsi_command_complete(void *opaque, uint32_t tag, int sense)
-{
- LSIState *s = (LSIState *)opaque;
-
- DPRINTF("Command complete sense=%d\n", sense);
- s->sense = sense;
- lsi_set_phase(s, PHASE_ST);
-}
-
-static void lsi_do_status(LSIState *s)
-{
- DPRINTF("Get status len=%d sense=%d\n", s->dbc, s->sense);
- if (s->dbc != 1)
- BADF("Bad Status move\n");
- s->dbc = 1;
- s->msg = s->sense;
- cpu_physical_memory_write(s->dnad, &s->msg, 1);
- s->sfbr = s->msg;
- lsi_set_phase(s, PHASE_MI);
- s->msg = 0; /* COMMAND COMPLETE */
-}
-
-static void lsi_disconnect(LSIState *s)
-{
- s->scntl1 &= ~LSI_SCNTL1_CON;
- s->sstat1 &= ~PHASE_MASK;
-}
-
-static void lsi_do_msgin(LSIState *s)
-{
- DPRINTF("Message in len=%d\n", s->dbc);
- s->dbc = 1;
- s->sfbr = s->msg;
- cpu_physical_memory_write(s->dnad, &s->msg, 1);
- if (s->msg == 0) {
- lsi_disconnect(s);
- } else {
- /* ??? Check if ATN (not yet implemented) is asserted and maybe
- switch to PHASE_MO. */
- lsi_set_phase(s, PHASE_CMD);
- }
-}
-
-static void lsi_do_msgout(LSIState *s)
-{
- uint8_t msg;
-
- DPRINTF("MSG out len=%d\n", s->dbc);
- if (s->dbc != 1) {
- /* Multibyte messages not implemented. */
- s->msg = 7; /* MESSAGE REJECT */
- //s->dbc = 1;
- //lsi_bad_phase(s, 1, PHASE_MI);
- lsi_set_phase(s, PHASE_MI);
- return;
- }
- cpu_physical_memory_read(s->dnad, &msg, 1);
- s->sfbr = msg;
- s->dnad++;
-
- switch (msg) {
- case 0x00:
- DPRINTF("Got Disconnect\n");
- lsi_disconnect(s);
- return;
- case 0x08:
- DPRINTF("Got No Operation\n");
- lsi_set_phase(s, PHASE_CMD);
- return;
- }
- if ((msg & 0x80) == 0) {
- DPRINTF("Unimplemented message 0x%d\n", msg);
- s->msg = 7; /* MESSAGE REJECT */
- lsi_bad_phase(s, 1, PHASE_MI);
- return;
- }
- s->current_lun = msg & 7;
- DPRINTF("Select LUN %d\n", s->current_lun);
- lsi_set_phase(s, PHASE_CMD);
-}
-
-/* Sign extend a 24-bit value. */
-static inline int32_t sxt24(int32_t n)
-{
- return (n << 8) >> 8;
-}
-
-static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count)
-{
- int n;
- uint8_t buf[TARGET_PAGE_SIZE];
-
- DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count);
- while (count) {
- n = (count > TARGET_PAGE_SIZE) ? TARGET_PAGE_SIZE : count;
- cpu_physical_memory_read(src, buf, n);
- cpu_physical_memory_write(dest, buf, n);
- src += n;
- dest += n;
- count -= n;
- }
-}
-
-static void lsi_execute_script(LSIState *s)
-{
- uint32_t insn;
- uint32_t addr;
- int opcode;
-
- s->istat1 |= LSI_ISTAT1_SRUN;
-again:
- insn = read_dword(s, s->dsp);
- addr = read_dword(s, s->dsp + 4);
- DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr);
- s->dsps = addr;
- s->dcmd = insn >> 24;
- s->dsp += 8;
- switch (insn >> 30) {
- case 0: /* Block move. */
- if (s->sist1 & LSI_SIST1_STO) {
- DPRINTF("Delayed select timeout\n");
- lsi_stop_script(s);
- break;
- }
- s->dbc = insn & 0xffffff;
- s->rbc = s->dbc;
- if (insn & (1 << 29)) {
- /* Indirect addressing. */
- addr = read_dword(s, addr);
- } else if (insn & (1 << 28)) {
- uint32_t buf[2];
- int32_t offset;
- /* Table indirect addressing. */
- offset = sxt24(addr);
- cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8);
- s->dbc = cpu_to_le32(buf[0]);
- addr = cpu_to_le32(buf[1]);
- }
- if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
- DPRINTF("Wrong phase got %d expected %d\n",
- s->sstat1 & PHASE_MASK, (insn >> 24) & 7);
- lsi_script_scsi_interrupt(s, LSI_SIST0_MA, 0);
- break;
- }
- s->dnad = addr;
- switch (s->sstat1 & 0x7) {
- case PHASE_DO:
- lsi_do_dma(s, 1);
- break;
- case PHASE_DI:
- lsi_do_dma(s, 0);
- break;
- case PHASE_CMD:
- lsi_do_command(s);
- break;
- case PHASE_ST:
- lsi_do_status(s);
- break;
- case PHASE_MO:
- lsi_do_msgout(s);
- break;
- case PHASE_MI:
- lsi_do_msgin(s);
- break;
- default:
- BADF("Unimplemented phase %d\n", s->sstat1 & PHASE_MASK);
- exit(1);
- }
- s->dfifo = s->dbc & 0xff;
- s->ctest5 = (s->ctest5 & 0xfc) | ((s->dbc >> 8) & 3);
- s->sbc = s->dbc;
- s->rbc -= s->dbc;
- s->ua = addr + s->dbc;
- /* ??? Set ESA. */
- s->ia = s->dsp - 8;
- break;
-
- case 1: /* IO or Read/Write instruction. */
- opcode = (insn >> 27) & 7;
- if (opcode < 5) {
- uint32_t id;
-
- if (insn & (1 << 25)) {
- id = read_dword(s, s->dsa + sxt24(insn));
- } else {
- id = addr;
- }
- id = (id >> 16) & 0xf;
- if (insn & (1 << 26)) {
- addr = s->dsp + sxt24(addr);
- }
- s->dnad = addr;
- switch (opcode) {
- case 0: /* Select */
- s->sstat0 |= LSI_SSTAT0_WOA;
- s->scntl1 &= ~LSI_SCNTL1_IARB;
- s->sdid = id;
- if (id >= LSI_MAX_DEVS || !s->scsi_dev[id]) {
- DPRINTF("Selected absent target %d\n", id);
- lsi_script_scsi_interrupt(s, 0, LSI_SIST1_STO);
- lsi_disconnect(s);
- break;
- }
- DPRINTF("Selected target %d%s\n",
- id, insn & (1 << 3) ? " ATN" : "");
- /* ??? Linux drivers compain when this is set. Maybe
- it only applies in low-level mode (unimplemented).
- lsi_script_scsi_interrupt(s, LSI_SIST0_CMP, 0); */
- s->current_dev = s->scsi_dev[id];
- s->scntl1 |= LSI_SCNTL1_CON;
- if (insn & (1 << 3)) {
- s->socl |= LSI_SOCL_ATN;
- }
- lsi_set_phase(s, PHASE_MO);
- break;
- case 1: /* Disconnect */
- DPRINTF("Wait Disconect\n");
- s->scntl1 &= ~LSI_SCNTL1_CON;
- break;
- case 2: /* Wait Reselect */
- DPRINTF("Wait Reselect\n");
- s->waiting = 1;
- break;
- case 3: /* Set */
- DPRINTF("Set%s%s%s%s\n",
- insn & (1 << 3) ? " ATN" : "",
- insn & (1 << 6) ? " ACK" : "",
- insn & (1 << 9) ? " TM" : "",
- insn & (1 << 10) ? " CC" : "");
- if (insn & (1 << 3)) {
- s->socl |= LSI_SOCL_ATN;
- lsi_set_phase(s, PHASE_MO);
- }
- if (insn & (1 << 9)) {
- BADF("Target mode not implemented\n");
- exit(1);
- }
- if (insn & (1 << 10))
- s->carry = 1;
- break;
- case 4: /* Clear */
- DPRINTF("Clear%s%s%s%s\n",
- insn & (1 << 3) ? " ATN" : "",
- insn & (1 << 6) ? " ACK" : "",
- insn & (1 << 9) ? " TM" : "",
- insn & (1 << 10) ? " CC" : "");
- if (insn & (1 << 3)) {
- s->socl &= ~LSI_SOCL_ATN;
- }
- if (insn & (1 << 10))
- s->carry = 0;
- break;
- }
- } else {
- uint8_t op0;
- uint8_t op1;
- uint8_t data8;
- int reg;
- int operator;
-#ifdef DEBUG_LSI
- static const char *opcode_names[3] =
- {"Write", "Read", "Read-Modify-Write"};
- static const char *operator_names[8] =
- {"MOV", "SHL", "OR", "XOR", "AND", "SHR", "ADD", "ADC"};
-#endif
-
- reg = ((insn >> 16) & 0x7f) | (insn & 0x80);
- data8 = (insn >> 8) & 0xff;
- opcode = (insn >> 27) & 7;
- operator = (insn >> 24) & 7;
- DPRINTF("%s reg 0x%x %s data8 %d%s\n",
- opcode_names[opcode - 5], reg,
- operator_names[operator], data8,
- (insn & (1 << 23)) ? " SFBR" : "");
- op0 = op1 = 0;
- switch (opcode) {
- case 5: /* From SFBR */
- op0 = s->sfbr;
- op1 = data8;
- break;
- case 6: /* To SFBR */
- if (operator)
- op0 = lsi_reg_readb(s, reg);
- op1 = data8;
- break;
- case 7: /* Read-modify-write */
- if (operator)
- op0 = lsi_reg_readb(s, reg);
- if (insn & (1 << 23)) {
- op1 = s->sfbr;
- } else {
- op1 = data8;
- }
- break;
- }
-
- switch (operator) {
- case 0: /* move */
- op0 = op1;
- break;
- case 1: /* Shift left */
- op1 = op0 >> 7;
- op0 = (op0 << 1) | s->carry;
- s->carry = op1;
- break;
- case 2: /* OR */
- op0 |= op1;
- break;
- case 3: /* XOR */
- op0 |= op1;
- break;
- case 4: /* AND */
- op0 &= op1;
- break;
- case 5: /* SHR */
- op1 = op0 & 1;
- op0 = (op0 >> 1) | (s->carry << 7);
- break;
- case 6: /* ADD */
- op0 += op1;
- s->carry = op0 < op1;
- break;
- case 7: /* ADC */
- op0 += op1 + s->carry;
- if (s->carry)
- s->carry = op0 <= op1;
- else
- s->carry = op0 < op1;
- break;
- }
-
- switch (opcode) {
- case 5: /* From SFBR */
- case 7: /* Read-modify-write */
- lsi_reg_writeb(s, reg, op0);
- break;
- case 6: /* To SFBR */
- s->sfbr = op0;
- break;
- }
- }
- break;
-
- case 2: /* Transfer Control. */
- {
- int cond;
- int jmp;
-
- if ((insn & 0x002e0000) == 0) {
- DPRINTF("NOP\n");
- break;
- }
- if (s->sist1 & LSI_SIST1_STO) {
- DPRINTF("Delayed select timeout\n");
- lsi_stop_script(s);
- break;
- }
- cond = jmp = (insn & (1 << 19)) != 0;
- if (cond == jmp && (insn & (1 << 21))) {
- DPRINTF("Compare carry %d\n", s->carry == jmp);
- cond = s->carry != 0;
- }
- if (cond == jmp && (insn & (1 << 17))) {
- DPRINTF("Compare phase %d %c= %d\n",
- (s->sstat1 & PHASE_MASK),
- jmp ? '=' : '!',
- ((insn >> 24) & 7));
- cond = (s->sstat1 & PHASE_MASK) == ((insn >> 24) & 7);
- }
- if (cond == jmp && (insn & (1 << 18))) {
- uint8_t mask;
-
- mask = (~insn >> 8) & 0xff;
- DPRINTF("Compare data 0x%x & 0x%x %c= 0x%x\n",
- s->sfbr, mask, jmp ? '=' : '!', insn & mask);
- cond = (s->sfbr & mask) == (insn & mask);
- }
- if (cond == jmp) {
- if (insn & (1 << 23)) {
- /* Relative address. */
- addr = s->dsp + sxt24(addr);
- }
- switch ((insn >> 27) & 7) {
- case 0: /* Jump */
- DPRINTF("Jump to 0x%08x\n", addr);
- s->dsp = addr;
- break;
- case 1: /* Call */
- DPRINTF("Call 0x%08x\n", addr);
- s->temp = s->dsp;
- s->dsp = addr;
- break;
- case 2: /* Return */
- DPRINTF("Return to 0x%08x\n", s->temp);
- s->dsp = s->temp;
- break;
- case 3: /* Interrupt */
- DPRINTF("Interrupt 0x%08x\n", s->dsps);
- if ((insn & (1 << 20)) != 0) {
- s->istat0 |= LSI_ISTAT0_INTF;
- lsi_update_irq(s);
- } else {
- lsi_script_dma_interrupt(s, LSI_DSTAT_SIR);
- }
- break;
- default:
- DPRINTF("Illegal transfer control\n");
- lsi_script_dma_interrupt(s, LSI_DSTAT_IID);
- break;
- }
- } else {
- DPRINTF("Control condition failed\n");
- }
- }
- break;
-
- case 3:
- if ((insn & (1 << 29)) == 0) {
- /* Memory move. */
- uint32_t dest;
- /* ??? The docs imply the destination address is loaded into
- the TEMP register. However the Linux drivers rely on
- the value being presrved. */
- dest = read_dword(s, s->dsp);
- s->dsp += 4;
- lsi_memcpy(s, dest, addr, insn & 0xffffff);
- } else {
- uint8_t data[7];
- int reg;
- int n;
- int i;
-
- if (insn & (1 << 28)) {
- addr = s->dsa + sxt24(addr);
- }
- n = (insn & 7);
- reg = (insn >> 16) & 0xff;
- if (insn & (1 << 24)) {
- DPRINTF("Load reg 0x%x size %d addr 0x%08x\n", reg, n, addr);
- cpu_physical_memory_read(addr, data, n);
- for (i = 0; i < n; i++) {
- lsi_reg_writeb(s, reg + i, data[i]);
- }
- } else {
- DPRINTF("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr);
- for (i = 0; i < n; i++) {
- data[i] = lsi_reg_readb(s, reg + i);
- }
- cpu_physical_memory_write(addr, data, n);
- }
- }
- }
- /* ??? Need to avoid infinite loops. */
- if (s->istat1 & LSI_ISTAT1_SRUN && !s->waiting) {
- if (s->dcntl & LSI_DCNTL_SSM) {
- lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
- } else {
- goto again;
- }
- }
- DPRINTF("SCRIPTS execution stopped\n");
-}
-
-static uint8_t lsi_reg_readb(LSIState *s, int offset)
-{
- uint8_t tmp;
-#define CASE_GET_REG32(name, addr) \
- case addr: return s->name & 0xff; \
- case addr + 1: return (s->name >> 8) & 0xff; \
- case addr + 2: return (s->name >> 16) & 0xff; \
- case addr + 3: return (s->name >> 24) & 0xff;
-
-#ifdef DEBUG_LSI_REG
- DPRINTF("Read reg %x\n", offset);
-#endif
- switch (offset) {
- case 0x00: /* SCNTL0 */
- return s->scntl0;
- case 0x01: /* SCNTL1 */
- return s->scntl1;
- case 0x02: /* SCNTL2 */
- return s->scntl2;
- case 0x03: /* SCNTL3 */
- return s->scntl3;
- case 0x04: /* SCID */
- return s->scid;
- case 0x05: /* SXFER */
- return s->sxfer;
- case 0x06: /* SDID */
- return s->sdid;
- case 0x07: /* GPREG0 */
- return 0x7f;
- case 0xb: /* SBCL */
- /* ??? This is not correct. However it's (hopefully) only
- used for diagnostics, so should be ok. */
- return 0;
- case 0xc: /* DSTAT */
- tmp = s->dstat | 0x80;
- if ((s->istat0 & LSI_ISTAT0_INTF) == 0)
- s->dstat = 0;
- lsi_update_irq(s);
- return tmp;
- case 0x0d: /* SSTAT0 */
- return s->sstat0;
- case 0x0e: /* SSTAT1 */
- return s->sstat1;
- case 0x0f: /* SSTAT2 */
- return s->scntl1 & LSI_SCNTL1_CON ? 0 : 2;
- CASE_GET_REG32(dsa, 0x10)
- case 0x14: /* ISTAT0 */
- return s->istat0;
- case 0x16: /* MBOX0 */
- return s->mbox0;
- case 0x17: /* MBOX1 */
- return s->mbox1;
- case 0x18: /* CTEST0 */
- return 0xff;
- case 0x19: /* CTEST1 */
- return 0;
- case 0x1a: /* CTEST2 */
- tmp = LSI_CTEST2_DACK | LSI_CTEST2_CM;
- if (s->istat0 & LSI_ISTAT0_SIGP) {
- s->istat0 &= ~LSI_ISTAT0_SIGP;
- tmp |= LSI_CTEST2_SIGP;
- }
- return tmp;
- case 0x1b: /* CTEST3 */
- return s->ctest3;
- CASE_GET_REG32(temp, 0x1c)
- case 0x20: /* DFIFO */
- return 0;
- case 0x21: /* CTEST4 */
- return s->ctest4;
- case 0x22: /* CTEST5 */
- return s->ctest5;
- case 0x24: /* DBC[0:7] */
- return s->dbc & 0xff;
- case 0x25: /* DBC[8:15] */
- return (s->dbc >> 8) & 0xff;
- case 0x26: /* DBC[16->23] */
- return (s->dbc >> 16) & 0xff;
- case 0x27: /* DCMD */
- return s->dcmd;
- CASE_GET_REG32(dsp, 0x2c)
- CASE_GET_REG32(dsps, 0x30)
- CASE_GET_REG32(scratch[0], 0x34)
- case 0x38: /* DMODE */
- return s->dmode;
- case 0x39: /* DIEN */
- return s->dien;
- case 0x3b: /* DCNTL */
- return s->dcntl;
- case 0x40: /* SIEN0 */
- return s->sien0;
- case 0x41: /* SIEN1 */
- return s->sien1;
- case 0x42: /* SIST0 */
- tmp = s->sist0;
- s->sist0 = 0;
- lsi_update_irq(s);
- return tmp;
- case 0x43: /* SIST1 */
- tmp = s->sist1;
- s->sist1 = 0;
- lsi_update_irq(s);
- return tmp;
- case 0x47: /* GPCNTL0 */
- return 0x0f;
- case 0x48: /* STIME0 */
- return s->stime0;
- case 0x4a: /* RESPID0 */
- return s->respid0;
- case 0x4b: /* RESPID1 */
- return s->respid1;
- case 0x4d: /* STEST1 */
- return s->stest1;
- case 0x4e: /* STEST2 */
- return s->stest2;
- case 0x4f: /* STEST3 */
- return s->stest3;
- case 0x52: /* STEST4 */
- return 0xe0;
- case 0x56: /* CCNTL0 */
- return s->ccntl0;
- case 0x57: /* CCNTL1 */
- return s->ccntl1;
- case 0x58: case 0x59: /* SBDL */
- return 0;
- CASE_GET_REG32(mmrs, 0xa0)
- CASE_GET_REG32(mmws, 0xa4)
- CASE_GET_REG32(sfs, 0xa8)
- CASE_GET_REG32(drs, 0xac)
- CASE_GET_REG32(sbms, 0xb0)
- CASE_GET_REG32(dmbs, 0xb4)
- CASE_GET_REG32(dnad64, 0xb8)
- CASE_GET_REG32(pmjad1, 0xc0)
- CASE_GET_REG32(pmjad2, 0xc4)
- CASE_GET_REG32(rbc, 0xc8)
- CASE_GET_REG32(ua, 0xcc)
- CASE_GET_REG32(ia, 0xd4)
- CASE_GET_REG32(sbc, 0xd8)
- CASE_GET_REG32(csbc, 0xdc)
- }
- if (offset >= 0x5c && offset < 0xa0) {
- int n;
- int shift;
- n = (offset - 0x58) >> 2;
- shift = (offset & 3) * 8;
- return (s->scratch[n] >> shift) & 0xff;
- }
- BADF("readb 0x%x\n", offset);
- exit(1);
-#undef CASE_GET_REG32
-}
-
-static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
-{
-#define CASE_SET_REG32(name, addr) \
- case addr : s->name &= 0xffffff00; s->name |= val; break; \
- case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8; break; \
- case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
- case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
-
-#ifdef DEBUG_LSI_REG
- DPRINTF("Write reg %x = %02x\n", offset, val);
-#endif
- switch (offset) {
- case 0x00: /* SCNTL0 */
- s->scntl0 = val;
- if (val & LSI_SCNTL0_START) {
- BADF("Start sequence not implemented\n");
- }
- break;
- case 0x01: /* SCNTL1 */
- s->scntl1 = val & ~LSI_SCNTL1_SST;
- if (val & LSI_SCNTL1_IARB) {
- BADF("Immediate Arbritration not implemented\n");
- }
- if (val & LSI_SCNTL1_RST) {
- s->sstat0 |= LSI_SSTAT0_RST;
- lsi_script_scsi_interrupt(s, LSI_SIST0_RST, 0);
- } else {
- s->sstat0 &= ~LSI_SSTAT0_RST;
- }
- break;
- case 0x02: /* SCNTL2 */
- val &= ~(LSI_SCNTL2_WSR | LSI_SCNTL2_WSS);
- s->scntl3 = val;
- break;
- case 0x03: /* SCNTL3 */
- s->scntl3 = val;
- break;
- case 0x04: /* SCID */
- s->scid = val;
- break;
- case 0x05: /* SXFER */
- s->sxfer = val;
- break;
- case 0x07: /* GPREG0 */
- break;
- case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- /* Linux writes to these readonly registers on startup. */
- return;
- CASE_SET_REG32(dsa, 0x10)
- case 0x14: /* ISTAT0 */
- s->istat0 = (s->istat0 & 0x0f) | (val & 0xf0);
- if (val & LSI_ISTAT0_ABRT) {
- lsi_script_dma_interrupt(s, LSI_DSTAT_ABRT);
- }
- if (val & LSI_ISTAT0_INTF) {
- s->istat0 &= ~LSI_ISTAT0_INTF;
- lsi_update_irq(s);
- }
- if (s->waiting && val & LSI_ISTAT0_SIGP) {
- DPRINTF("Woken by SIGP\n");
- s->waiting = 0;
- s->dsp = s->dnad;
- lsi_execute_script(s);
- }
- if (val & LSI_ISTAT0_SRST) {
- lsi_soft_reset(s);
- }
- case 0x16: /* MBOX0 */
- s->mbox0 = val;
- case 0x17: /* MBOX1 */
- s->mbox1 = val;
- case 0x1b: /* CTEST3 */
- s->ctest3 = val & 0x0f;
- break;
- CASE_SET_REG32(temp, 0x1c)
- case 0x21: /* CTEST4 */
- if (val & 7) {
- BADF("Unimplemented CTEST4-FBL 0x%x\n", val);
- }
- s->ctest4 = val;
- break;
- case 0x22: /* CTEST5 */
- if (val & (LSI_CTEST5_ADCK | LSI_CTEST5_BBCK)) {
- BADF("CTEST5 DMA increment not implemented\n");
- }
- s->ctest5 = val;
- break;
- case 0x2c: /* DSPS[0:7] */
- s->dsp &= 0xffffff00;
- s->dsp |= val;
- break;
- case 0x2d: /* DSPS[8:15] */
- s->dsp &= 0xffff00ff;
- s->dsp |= val << 8;
- break;
- case 0x2e: /* DSPS[16:23] */
- s->dsp &= 0xff00ffff;
- s->dsp |= val << 16;
- break;
- case 0x2f: /* DSPS[14:31] */
- s->dsp &= 0x00ffffff;
- s->dsp |= val << 24;
- if ((s->dmode & LSI_DMODE_MAN) == 0
- && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
- lsi_execute_script(s);
- break;
- CASE_SET_REG32(dsps, 0x30)
- CASE_SET_REG32(scratch[0], 0x34)
- case 0x38: /* DMODE */
- if (val & (LSI_DMODE_SIOM | LSI_DMODE_DIOM)) {
- BADF("IO mappings not implemented\n");
- }
- s->dmode = val;
- break;
- case 0x39: /* DIEN */
- s->dien = val;
- lsi_update_irq(s);
- break;
- case 0x3b: /* DCNTL */
- s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
- if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
- lsi_execute_script(s);
- break;
- case 0x40: /* SIEN0 */
- s->sien0 = val;
- lsi_update_irq(s);
- break;
- case 0x41: /* SIEN1 */
- s->sien1 = val;
- lsi_update_irq(s);
- break;
- case 0x47: /* GPCNTL0 */
- break;
- case 0x48: /* STIME0 */
- s->stime0 = val;
- break;
- case 0x49: /* STIME1 */
- if (val & 0xf) {
- DPRINTF("General purpose timer not implemented\n");
- /* ??? Raising the interrupt immediately seems to be sufficient
- to keep the FreeBSD driver happy. */
- lsi_script_scsi_interrupt(s, 0, LSI_SIST1_GEN);
- }
- break;
- case 0x4a: /* RESPID0 */
- s->respid0 = val;
- break;
- case 0x4b: /* RESPID1 */
- s->respid1 = val;
- break;
- case 0x4d: /* STEST1 */
- s->stest1 = val;
- break;
- case 0x4e: /* STEST2 */
- if (val & 1) {
- BADF("Low level mode not implemented\n");
- }
- s->stest2 = val;
- break;
- case 0x4f: /* STEST3 */
- if (val & 0x41) {
- BADF("SCSI FIFO test mode not implemented\n");
- }
- s->stest3 = val;
- break;
- case 0x56: /* CCNTL0 */
- s->ccntl0 = val;
- break;
- case 0x57: /* CCNTL1 */
- s->ccntl1 = val;
- break;
- CASE_SET_REG32(mmrs, 0xa0)
- CASE_SET_REG32(mmws, 0xa4)
- CASE_SET_REG32(sfs, 0xa8)
- CASE_SET_REG32(drs, 0xac)
- CASE_SET_REG32(sbms, 0xb0)
- CASE_SET_REG32(dmbs, 0xb4)
- CASE_SET_REG32(dnad64, 0xb8)
- CASE_SET_REG32(pmjad1, 0xc0)
- CASE_SET_REG32(pmjad2, 0xc4)
- CASE_SET_REG32(rbc, 0xc8)
- CASE_SET_REG32(ua, 0xcc)
- CASE_SET_REG32(ia, 0xd4)
- CASE_SET_REG32(sbc, 0xd8)
- CASE_SET_REG32(csbc, 0xdc)
- default:
- if (offset >= 0x5c && offset < 0xa0) {
- int n;
- int shift;
- n = (offset - 0x58) >> 2;
- shift = (offset & 3) * 8;
- s->scratch[n] &= ~(0xff << shift);
- s->scratch[n] |= (val & 0xff) << shift;
- } else {
- BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
- }
- }
-#undef CASE_SET_REG32
-}
-
-static void lsi_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
-
- lsi_reg_writeb(s, addr & 0xff, val);
-}
-
-static void lsi_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
-
- addr &= 0xff;
- lsi_reg_writeb(s, addr, val & 0xff);
- lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
-}
-
-static void lsi_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
-
- addr &= 0xff;
- lsi_reg_writeb(s, addr, val & 0xff);
- lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
- lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
- lsi_reg_writeb(s, addr + 3, (val >> 24) & 0xff);
-}
-
-static uint32_t lsi_mmio_readb(void *opaque, target_phys_addr_t addr)
-{
- LSIState *s = (LSIState *)opaque;
-
- return lsi_reg_readb(s, addr & 0xff);
-}
-
-static uint32_t lsi_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t val;
-
- addr &= 0xff;
- val = lsi_reg_readb(s, addr);
- val |= lsi_reg_readb(s, addr + 1) << 8;
- return val;
-}
-
-static uint32_t lsi_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t val;
- addr &= 0xff;
- val = lsi_reg_readb(s, addr);
- val |= lsi_reg_readb(s, addr + 1) << 8;
- val |= lsi_reg_readb(s, addr + 2) << 16;
- val |= lsi_reg_readb(s, addr + 3) << 24;
- return val;
-}
-
-static CPUReadMemoryFunc *lsi_mmio_readfn[3] = {
- lsi_mmio_readb,
- lsi_mmio_readw,
- lsi_mmio_readl,
-};
-
-static CPUWriteMemoryFunc *lsi_mmio_writefn[3] = {
- lsi_mmio_writeb,
- lsi_mmio_writew,
- lsi_mmio_writel,
-};
-
-static void lsi_ram_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t newval;
- int shift;
-
- addr &= 0x1fff;
- newval = s->script_ram[addr >> 2];
- shift = (addr & 3) * 8;
- newval &= ~(0xff << shift);
- newval |= val << shift;
- s->script_ram[addr >> 2] = newval;
-}
-
-static void lsi_ram_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t newval;
-
- addr &= 0x1fff;
- newval = s->script_ram[addr >> 2];
- if (addr & 2) {
- newval = (newval & 0xffff) | (val << 16);
- } else {
- newval = (newval & 0xffff0000) | val;
- }
- s->script_ram[addr >> 2] = newval;
-}
-
-
-static void lsi_ram_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
-
- addr &= 0x1fff;
- s->script_ram[addr >> 2] = val;
-}
-
-static uint32_t lsi_ram_readb(void *opaque, target_phys_addr_t addr)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t val;
-
- addr &= 0x1fff;
- val = s->script_ram[addr >> 2];
- val >>= (addr & 3) * 8;
- return val & 0xff;
-}
-
-static uint32_t lsi_ram_readw(void *opaque, target_phys_addr_t addr)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t val;
-
- addr &= 0x1fff;
- val = s->script_ram[addr >> 2];
- if (addr & 2)
- val >>= 16;
- return le16_to_cpu(val);
-}
-
-static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
-{
- LSIState *s = (LSIState *)opaque;
-
- addr &= 0x1fff;
- return le32_to_cpu(s->script_ram[addr >> 2]);
-}
-
-static CPUReadMemoryFunc *lsi_ram_readfn[3] = {
- lsi_ram_readb,
- lsi_ram_readw,
- lsi_ram_readl,
-};
-
-static CPUWriteMemoryFunc *lsi_ram_writefn[3] = {
- lsi_ram_writeb,
- lsi_ram_writew,
- lsi_ram_writel,
-};
-
-static uint32_t lsi_io_readb(void *opaque, uint32_t addr)
-{
- LSIState *s = (LSIState *)opaque;
- return lsi_reg_readb(s, addr & 0xff);
-}
-
-static uint32_t lsi_io_readw(void *opaque, uint32_t addr)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t val;
- addr &= 0xff;
- val = lsi_reg_readb(s, addr);
- val |= lsi_reg_readb(s, addr + 1) << 8;
- return val;
-}
-
-static uint32_t lsi_io_readl(void *opaque, uint32_t addr)
-{
- LSIState *s = (LSIState *)opaque;
- uint32_t val;
- addr &= 0xff;
- val = lsi_reg_readb(s, addr);
- val |= lsi_reg_readb(s, addr + 1) << 8;
- val |= lsi_reg_readb(s, addr + 2) << 16;
- val |= lsi_reg_readb(s, addr + 3) << 24;
- return val;
-}
-
-static void lsi_io_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
- lsi_reg_writeb(s, addr & 0xff, val);
-}
-
-static void lsi_io_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
- addr &= 0xff;
- lsi_reg_writeb(s, addr, val & 0xff);
- lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
-}
-
-static void lsi_io_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- LSIState *s = (LSIState *)opaque;
- addr &= 0xff;
- lsi_reg_writeb(s, addr, val & 0xff);
- lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
- lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
- lsi_reg_writeb(s, addr + 2, (val >> 24) & 0xff);
-}
-
-static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- LSIState *s = (LSIState *)pci_dev;
-
- DPRINTF("Mapping IO at %08x\n", addr);
-
- register_ioport_write(addr, 256, 1, lsi_io_writeb, s);
- register_ioport_read(addr, 256, 1, lsi_io_readb, s);
- register_ioport_write(addr, 256, 2, lsi_io_writew, s);
- register_ioport_read(addr, 256, 2, lsi_io_readw, s);
- register_ioport_write(addr, 256, 4, lsi_io_writel, s);
- register_ioport_read(addr, 256, 4, lsi_io_readl, s);
-}
-
-static void lsi_ram_mapfunc(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- LSIState *s = (LSIState *)pci_dev;
-
- DPRINTF("Mapping ram at %08x\n", addr);
- s->script_ram_base = addr;
- cpu_register_physical_memory(addr + 0, 0x2000, s->ram_io_addr);
-}
-
-static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- LSIState *s = (LSIState *)pci_dev;
-
- DPRINTF("Mapping registers at %08x\n", addr);
- cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
-}
-
-void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id)
-{
- LSIState *s = (LSIState *)opaque;
-
- if (id < 0) {
- for (id = 0; id < LSI_MAX_DEVS; id++) {
- if (s->scsi_dev[id] == NULL)
- break;
- }
- }
- if (id >= LSI_MAX_DEVS) {
- BADF("Bad Device ID %d\n", id);
- return;
- }
- if (s->scsi_dev[id]) {
- DPRINTF("Destroying device %d\n", id);
- scsi_disk_destroy(s->scsi_dev[id]);
- }
- DPRINTF("Attaching block device %d\n", id);
- s->scsi_dev[id] = scsi_disk_init(bd, lsi_command_complete, s);
-}
-
-void *lsi_scsi_init(PCIBus *bus, int devfn)
-{
- LSIState *s;
-
- s = (LSIState *)pci_register_device(bus, "LSI53C895A SCSI HBA",
- sizeof(*s), devfn, NULL, NULL);
- if (s == NULL) {
- fprintf(stderr, "lsi-scsi: Failed to register PCI device\n");
- return NULL;
- }
-
- s->pci_dev.config[0x00] = 0x00;
- s->pci_dev.config[0x01] = 0x10;
- s->pci_dev.config[0x02] = 0x12;
- s->pci_dev.config[0x03] = 0x00;
- s->pci_dev.config[0x0b] = 0x01;
- s->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
-
- s->mmio_io_addr = cpu_register_io_memory(0, lsi_mmio_readfn,
- lsi_mmio_writefn, s);
- s->ram_io_addr = cpu_register_io_memory(0, lsi_ram_readfn,
- lsi_ram_writefn, s);
-
- pci_register_io_region((struct PCIDevice *)s, 0, 256,
- PCI_ADDRESS_SPACE_IO, lsi_io_mapfunc);
- pci_register_io_region((struct PCIDevice *)s, 1, 0x400,
- PCI_ADDRESS_SPACE_MEM, lsi_mmio_mapfunc);
- pci_register_io_region((struct PCIDevice *)s, 2, 0x2000,
- PCI_ADDRESS_SPACE_MEM, lsi_ram_mapfunc);
-
- lsi_soft_reset(s);
-
- return s;
-}
-
diff --git a/hw/m48t59.c b/hw/m48t59.c
deleted file mode 100644
index daa1c52..0000000
--- a/hw/m48t59.c
+++ /dev/null
@@ -1,614 +0,0 @@
-/*
- * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
- *
- * Copyright (c) 2003-2005 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-#include "m48t59.h"
-
-//#define DEBUG_NVRAM
-
-#if defined(DEBUG_NVRAM)
-#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
-#else
-#define NVRAM_PRINTF(fmt, args...) do { } while (0)
-#endif
-
-/*
- * The M48T08 and M48T59 chips are very similar. The newer '59 has
- * alarm and a watchdog timer and related control registers. In the
- * PPC platform there is also a nvram lock function.
- */
-struct m48t59_t {
- /* Model parameters */
- int type; // 8 = m48t08, 59 = m48t59
- /* Hardware parameters */
- int IRQ;
- int mem_index;
- uint32_t mem_base;
- uint32_t io_base;
- uint16_t size;
- /* RTC management */
- time_t time_offset;
- time_t stop_time;
- /* Alarm & watchdog */
- time_t alarm;
- struct QEMUTimer *alrm_timer;
- struct QEMUTimer *wd_timer;
- /* NVRAM storage */
- uint8_t lock;
- uint16_t addr;
- uint8_t *buffer;
-};
-
-/* Fake timer functions */
-/* Generic helpers for BCD */
-static inline uint8_t toBCD (uint8_t value)
-{
- return (((value / 10) % 10) << 4) | (value % 10);
-}
-
-static inline uint8_t fromBCD (uint8_t BCD)
-{
- return ((BCD >> 4) * 10) + (BCD & 0x0F);
-}
-
-/* RTC management helpers */
-static void get_time (m48t59_t *NVRAM, struct tm *tm)
-{
- time_t t;
-
- t = time(NULL) + NVRAM->time_offset;
-#ifdef _WIN32
- memcpy(tm,localtime(&t),sizeof(*tm));
-#else
- localtime_r (&t, tm) ;
-#endif
-}
-
-static void set_time (m48t59_t *NVRAM, struct tm *tm)
-{
- time_t now, new_time;
-
- new_time = mktime(tm);
- now = time(NULL);
- NVRAM->time_offset = new_time - now;
-}
-
-/* Alarm management */
-static void alarm_cb (void *opaque)
-{
- struct tm tm, tm_now;
- uint64_t next_time;
- m48t59_t *NVRAM = opaque;
-
- pic_set_irq(NVRAM->IRQ, 1);
- if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once a month */
- get_time(NVRAM, &tm_now);
- memcpy(&tm, &tm_now, sizeof(struct tm));
- tm.tm_mon++;
- if (tm.tm_mon == 13) {
- tm.tm_mon = 1;
- tm.tm_year++;
- }
- next_time = mktime(&tm);
- } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once a day */
- next_time = 24 * 60 * 60 + mktime(&tm_now);
- } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once an hour */
- next_time = 60 * 60 + mktime(&tm_now);
- } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once a minute */
- next_time = 60 + mktime(&tm_now);
- } else {
- /* Repeat once a second */
- next_time = 1 + mktime(&tm_now);
- }
- qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
- pic_set_irq(NVRAM->IRQ, 0);
-}
-
-
-static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
-{
-#ifdef _WIN32
- memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
-#else
- localtime_r (&NVRAM->alarm, tm);
-#endif
-}
-
-static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
-{
- NVRAM->alarm = mktime(tm);
- if (NVRAM->alrm_timer != NULL) {
- qemu_del_timer(NVRAM->alrm_timer);
- NVRAM->alrm_timer = NULL;
- }
- if (NVRAM->alarm - time(NULL) > 0)
- qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
-}
-
-/* Watchdog management */
-static void watchdog_cb (void *opaque)
-{
- m48t59_t *NVRAM = opaque;
-
- NVRAM->buffer[0x1FF0] |= 0x80;
- if (NVRAM->buffer[0x1FF7] & 0x80) {
- NVRAM->buffer[0x1FF7] = 0x00;
- NVRAM->buffer[0x1FFC] &= ~0x40;
- /* May it be a hw CPU Reset instead ? */
- qemu_system_reset_request();
- } else {
- pic_set_irq(NVRAM->IRQ, 1);
- pic_set_irq(NVRAM->IRQ, 0);
- }
-}
-
-static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
-{
- uint64_t interval; /* in 1/16 seconds */
-
- if (NVRAM->wd_timer != NULL) {
- qemu_del_timer(NVRAM->wd_timer);
- NVRAM->wd_timer = NULL;
- }
- NVRAM->buffer[0x1FF0] &= ~0x80;
- if (value != 0) {
- interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
- qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
- ((interval * 1000) >> 4));
- }
-}
-
-/* Direct access to NVRAM */
-void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val)
-{
- struct tm tm;
- int tmp;
-
- if (addr > 0x1FF8 && addr < 0x2000)
- NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
- if (NVRAM->type == 8 &&
- (addr >= 0x1ff0 && addr <= 0x1ff7))
- goto do_write;
- switch (addr) {
- case 0x1FF0:
- /* flags register : read-only */
- break;
- case 0x1FF1:
- /* unused */
- break;
- case 0x1FF2:
- /* alarm seconds */
- tmp = fromBCD(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- get_alarm(NVRAM, &tm);
- tm.tm_sec = tmp;
- NVRAM->buffer[0x1FF2] = val;
- set_alarm(NVRAM, &tm);
- }
- break;
- case 0x1FF3:
- /* alarm minutes */
- tmp = fromBCD(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- get_alarm(NVRAM, &tm);
- tm.tm_min = tmp;
- NVRAM->buffer[0x1FF3] = val;
- set_alarm(NVRAM, &tm);
- }
- break;
- case 0x1FF4:
- /* alarm hours */
- tmp = fromBCD(val & 0x3F);
- if (tmp >= 0 && tmp <= 23) {
- get_alarm(NVRAM, &tm);
- tm.tm_hour = tmp;
- NVRAM->buffer[0x1FF4] = val;
- set_alarm(NVRAM, &tm);
- }
- break;
- case 0x1FF5:
- /* alarm date */
- tmp = fromBCD(val & 0x1F);
- if (tmp != 0) {
- get_alarm(NVRAM, &tm);
- tm.tm_mday = tmp;
- NVRAM->buffer[0x1FF5] = val;
- set_alarm(NVRAM, &tm);
- }
- break;
- case 0x1FF6:
- /* interrupts */
- NVRAM->buffer[0x1FF6] = val;
- break;
- case 0x1FF7:
- /* watchdog */
- NVRAM->buffer[0x1FF7] = val;
- set_up_watchdog(NVRAM, val);
- break;
- case 0x1FF8:
- /* control */
- NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
- break;
- case 0x1FF9:
- /* seconds (BCD) */
- tmp = fromBCD(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- get_time(NVRAM, &tm);
- tm.tm_sec = tmp;
- set_time(NVRAM, &tm);
- }
- if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
- if (val & 0x80) {
- NVRAM->stop_time = time(NULL);
- } else {
- NVRAM->time_offset += NVRAM->stop_time - time(NULL);
- NVRAM->stop_time = 0;
- }
- }
- NVRAM->buffer[0x1FF9] = val & 0x80;
- break;
- case 0x1FFA:
- /* minutes (BCD) */
- tmp = fromBCD(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- get_time(NVRAM, &tm);
- tm.tm_min = tmp;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFB:
- /* hours (BCD) */
- tmp = fromBCD(val & 0x3F);
- if (tmp >= 0 && tmp <= 23) {
- get_time(NVRAM, &tm);
- tm.tm_hour = tmp;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFC:
- /* day of the week / century */
- tmp = fromBCD(val & 0x07);
- get_time(NVRAM, &tm);
- tm.tm_wday = tmp;
- set_time(NVRAM, &tm);
- NVRAM->buffer[0x1FFC] = val & 0x40;
- break;
- case 0x1FFD:
- /* date */
- tmp = fromBCD(val & 0x1F);
- if (tmp != 0) {
- get_time(NVRAM, &tm);
- tm.tm_mday = tmp;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFE:
- /* month */
- tmp = fromBCD(val & 0x1F);
- if (tmp >= 1 && tmp <= 12) {
- get_time(NVRAM, &tm);
- tm.tm_mon = tmp - 1;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFF:
- /* year */
- tmp = fromBCD(val);
- if (tmp >= 0 && tmp <= 99) {
- get_time(NVRAM, &tm);
- if (NVRAM->type == 8)
- tm.tm_year = fromBCD(val) + 68; // Base year is 1968
- else
- tm.tm_year = fromBCD(val);
- set_time(NVRAM, &tm);
- }
- break;
- default:
- /* Check lock registers state */
- if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
- break;
- if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
- break;
- do_write:
- if (addr < NVRAM->size) {
- NVRAM->buffer[addr] = val & 0xFF;
- }
- break;
- }
-}
-
-uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr)
-{
- struct tm tm;
- uint32_t retval = 0xFF;
-
- if (NVRAM->type == 8 &&
- (addr >= 0x1ff0 && addr <= 0x1ff7))
- goto do_read;
- switch (addr) {
- case 0x1FF0:
- /* flags register */
- goto do_read;
- case 0x1FF1:
- /* unused */
- retval = 0;
- break;
- case 0x1FF2:
- /* alarm seconds */
- goto do_read;
- case 0x1FF3:
- /* alarm minutes */
- goto do_read;
- case 0x1FF4:
- /* alarm hours */
- goto do_read;
- case 0x1FF5:
- /* alarm date */
- goto do_read;
- case 0x1FF6:
- /* interrupts */
- goto do_read;
- case 0x1FF7:
- /* A read resets the watchdog */
- set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
- goto do_read;
- case 0x1FF8:
- /* control */
- goto do_read;
- case 0x1FF9:
- /* seconds (BCD) */
- get_time(NVRAM, &tm);
- retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
- break;
- case 0x1FFA:
- /* minutes (BCD) */
- get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_min);
- break;
- case 0x1FFB:
- /* hours (BCD) */
- get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_hour);
- break;
- case 0x1FFC:
- /* day of the week / century */
- get_time(NVRAM, &tm);
- retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
- break;
- case 0x1FFD:
- /* date */
- get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_mday);
- break;
- case 0x1FFE:
- /* month */
- get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_mon + 1);
- break;
- case 0x1FFF:
- /* year */
- get_time(NVRAM, &tm);
- if (NVRAM->type == 8)
- retval = toBCD(tm.tm_year - 68); // Base year is 1968
- else
- retval = toBCD(tm.tm_year);
- break;
- default:
- /* Check lock registers state */
- if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
- break;
- if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
- break;
- do_read:
- if (addr < NVRAM->size) {
- retval = NVRAM->buffer[addr];
- }
- break;
- }
- if (addr > 0x1FF9 && addr < 0x2000)
- NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
-
- return retval;
-}
-
-void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
-{
- NVRAM->addr = addr;
-}
-
-void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
-{
- NVRAM->lock ^= 1 << lock;
-}
-
-/* IO access to NVRAM */
-static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
-{
- m48t59_t *NVRAM = opaque;
-
- addr -= NVRAM->io_base;
- NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
- switch (addr) {
- case 0:
- NVRAM->addr &= ~0x00FF;
- NVRAM->addr |= val;
- break;
- case 1:
- NVRAM->addr &= ~0xFF00;
- NVRAM->addr |= val << 8;
- break;
- case 3:
- m48t59_write(NVRAM, val, NVRAM->addr);
- NVRAM->addr = 0x0000;
- break;
- default:
- break;
- }
-}
-
-static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
-{
- m48t59_t *NVRAM = opaque;
- uint32_t retval;
-
- addr -= NVRAM->io_base;
- switch (addr) {
- case 3:
- retval = m48t59_read(NVRAM, NVRAM->addr);
- break;
- default:
- retval = -1;
- break;
- }
- NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
-
- return retval;
-}
-
-static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- m48t59_t *NVRAM = opaque;
-
- addr -= NVRAM->mem_base;
- m48t59_write(NVRAM, addr, value & 0xff);
-}
-
-static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- m48t59_t *NVRAM = opaque;
-
- addr -= NVRAM->mem_base;
- m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
- m48t59_write(NVRAM, addr + 1, value & 0xff);
-}
-
-static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- m48t59_t *NVRAM = opaque;
-
- addr -= NVRAM->mem_base;
- m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
- m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
- m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
- m48t59_write(NVRAM, addr + 3, value & 0xff);
-}
-
-static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
-{
- m48t59_t *NVRAM = opaque;
- uint32_t retval;
-
- addr -= NVRAM->mem_base;
- retval = m48t59_read(NVRAM, addr);
- return retval;
-}
-
-static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
-{
- m48t59_t *NVRAM = opaque;
- uint32_t retval;
-
- addr -= NVRAM->mem_base;
- retval = m48t59_read(NVRAM, addr) << 8;
- retval |= m48t59_read(NVRAM, addr + 1);
- return retval;
-}
-
-static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
-{
- m48t59_t *NVRAM = opaque;
- uint32_t retval;
-
- addr -= NVRAM->mem_base;
- retval = m48t59_read(NVRAM, addr) << 24;
- retval |= m48t59_read(NVRAM, addr + 1) << 16;
- retval |= m48t59_read(NVRAM, addr + 2) << 8;
- retval |= m48t59_read(NVRAM, addr + 3);
- return retval;
-}
-
-static CPUWriteMemoryFunc *nvram_write[] = {
- &nvram_writeb,
- &nvram_writew,
- &nvram_writel,
-};
-
-static CPUReadMemoryFunc *nvram_read[] = {
- &nvram_readb,
- &nvram_readw,
- &nvram_readl,
-};
-
-/* Initialisation routine */
-m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
- uint32_t io_base, uint16_t size,
- int type)
-{
- m48t59_t *s;
-
- s = qemu_mallocz(sizeof(m48t59_t));
- if (!s)
- return NULL;
- s->buffer = qemu_mallocz(size);
- if (!s->buffer) {
- qemu_free(s);
- return NULL;
- }
- s->IRQ = IRQ;
- s->size = size;
- s->mem_base = mem_base;
- s->io_base = io_base;
- s->addr = 0;
- s->type = type;
- if (io_base != 0) {
- register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
- register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
- }
- if (mem_base != 0) {
- s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
- cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
- }
- if (type == 59) {
- s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
- s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
- }
- s->lock = 0;
-
- return s;
-}
diff --git a/hw/m48t59.h b/hw/m48t59.h
deleted file mode 100644
index af22dc1..0000000
--- a/hw/m48t59.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if !defined (__M48T59_H__)
-#define __M48T59_H__
-
-typedef struct m48t59_t m48t59_t;
-
-void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val);
-uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr);
-void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
-m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
- uint32_t io_base, uint16_t size,
- int type);
-
-#endif /* !defined (__M48T59_H__) */
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
deleted file mode 100644
index 9d4cbed..0000000
--- a/hw/mc146818rtc.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * QEMU MC146818 RTC emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define DEBUG_CMOS
-
-#define RTC_SECONDS 0
-#define RTC_SECONDS_ALARM 1
-#define RTC_MINUTES 2
-#define RTC_MINUTES_ALARM 3
-#define RTC_HOURS 4
-#define RTC_HOURS_ALARM 5
-#define RTC_ALARM_DONT_CARE 0xC0
-
-#define RTC_DAY_OF_WEEK 6
-#define RTC_DAY_OF_MONTH 7
-#define RTC_MONTH 8
-#define RTC_YEAR 9
-
-#define RTC_REG_A 10
-#define RTC_REG_B 11
-#define RTC_REG_C 12
-#define RTC_REG_D 13
-
-#define REG_A_UIP 0x80
-
-#define REG_B_SET 0x80
-#define REG_B_PIE 0x40
-#define REG_B_AIE 0x20
-#define REG_B_UIE 0x10
-
-struct RTCState {
- uint8_t cmos_data[128];
- uint8_t cmos_index;
- struct tm current_tm;
- int irq;
- /* periodic timer */
- QEMUTimer *periodic_timer;
- int64_t next_periodic_time;
- /* second update */
- int64_t next_second_time;
- QEMUTimer *second_timer;
- QEMUTimer *second_timer2;
-};
-
-static void rtc_set_time(RTCState *s);
-static void rtc_copy_date(RTCState *s);
-
-static void rtc_timer_update(RTCState *s, int64_t current_time)
-{
- int period_code, period;
- int64_t cur_clock, next_irq_clock;
-
- period_code = s->cmos_data[RTC_REG_A] & 0x0f;
- if (period_code != 0 &&
- (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
- if (period_code <= 2)
- period_code += 7;
- /* period in 32 Khz cycles */
- period = 1 << (period_code - 1);
- /* compute 32 khz clock */
- cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
- next_irq_clock = (cur_clock & ~(period - 1)) + period;
- s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
- qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
- } else {
- qemu_del_timer(s->periodic_timer);
- }
-}
-
-static void rtc_periodic_timer(void *opaque)
-{
- RTCState *s = opaque;
-
- rtc_timer_update(s, s->next_periodic_time);
- s->cmos_data[RTC_REG_C] |= 0xc0;
- pic_set_irq(s->irq, 1);
-}
-
-static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
-{
- RTCState *s = opaque;
-
- if ((addr & 1) == 0) {
- s->cmos_index = data & 0x7f;
- } else {
-#ifdef DEBUG_CMOS
- printf("cmos: write index=0x%02x val=0x%02x\n",
- s->cmos_index, data);
-#endif
- switch(s->cmos_index) {
- case RTC_SECONDS_ALARM:
- case RTC_MINUTES_ALARM:
- case RTC_HOURS_ALARM:
- /* XXX: not supported */
- s->cmos_data[s->cmos_index] = data;
- break;
- case RTC_SECONDS:
- case RTC_MINUTES:
- case RTC_HOURS:
- case RTC_DAY_OF_WEEK:
- case RTC_DAY_OF_MONTH:
- case RTC_MONTH:
- case RTC_YEAR:
- s->cmos_data[s->cmos_index] = data;
- /* if in set mode, do not update the time */
- if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
- rtc_set_time(s);
- }
- break;
- case RTC_REG_A:
- /* UIP bit is read only */
- s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
- (s->cmos_data[RTC_REG_A] & REG_A_UIP);
- rtc_timer_update(s, qemu_get_clock(vm_clock));
- break;
- case RTC_REG_B:
- if (data & REG_B_SET) {
- /* set mode: reset UIP mode */
- s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
- data &= ~REG_B_UIE;
- } else {
- /* if disabling set mode, update the time */
- if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
- rtc_set_time(s);
- }
- }
- s->cmos_data[RTC_REG_B] = data;
- rtc_timer_update(s, qemu_get_clock(vm_clock));
- break;
- case RTC_REG_C:
- case RTC_REG_D:
- /* cannot write to them */
- break;
- default:
- s->cmos_data[s->cmos_index] = data;
- break;
- }
- }
-}
-
-static inline int to_bcd(RTCState *s, int a)
-{
- if (s->cmos_data[RTC_REG_B] & 0x04) {
- return a;
- } else {
- return ((a / 10) << 4) | (a % 10);
- }
-}
-
-static inline int from_bcd(RTCState *s, int a)
-{
- if (s->cmos_data[RTC_REG_B] & 0x04) {
- return a;
- } else {
- return ((a >> 4) * 10) + (a & 0x0f);
- }
-}
-
-static void rtc_set_time(RTCState *s)
-{
- struct tm *tm = &s->current_tm;
-
- tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
- tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
- tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
- if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
- (s->cmos_data[RTC_HOURS] & 0x80)) {
- tm->tm_hour += 12;
- }
- tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
- tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
- tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
- tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
-}
-
-static void rtc_copy_date(RTCState *s)
-{
- const struct tm *tm = &s->current_tm;
-
- s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
- s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
- if (s->cmos_data[RTC_REG_B] & 0x02) {
- /* 24 hour format */
- s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
- } else {
- /* 12 hour format */
- s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
- if (tm->tm_hour >= 12)
- s->cmos_data[RTC_HOURS] |= 0x80;
- }
- s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
- s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
- s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
- s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
-}
-
-/* month is between 0 and 11. */
-static int get_days_in_month(int month, int year)
-{
- static const int days_tab[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- int d;
- if ((unsigned )month >= 12)
- return 31;
- d = days_tab[month];
- if (month == 1) {
- if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
- d++;
- }
- return d;
-}
-
-/* update 'tm' to the next second */
-static void rtc_next_second(struct tm *tm)
-{
- int days_in_month;
-
- tm->tm_sec++;
- if ((unsigned)tm->tm_sec >= 60) {
- tm->tm_sec = 0;
- tm->tm_min++;
- if ((unsigned)tm->tm_min >= 60) {
- tm->tm_min = 0;
- tm->tm_hour++;
- if ((unsigned)tm->tm_hour >= 24) {
- tm->tm_hour = 0;
- /* next day */
- tm->tm_wday++;
- if ((unsigned)tm->tm_wday >= 7)
- tm->tm_wday = 0;
- days_in_month = get_days_in_month(tm->tm_mon,
- tm->tm_year + 1900);
- tm->tm_mday++;
- if (tm->tm_mday < 1) {
- tm->tm_mday = 1;
- } else if (tm->tm_mday > days_in_month) {
- tm->tm_mday = 1;
- tm->tm_mon++;
- if (tm->tm_mon >= 12) {
- tm->tm_mon = 0;
- tm->tm_year++;
- }
- }
- }
- }
- }
-}
-
-
-static void rtc_update_second(void *opaque)
-{
- RTCState *s = opaque;
- int64_t delay;
-
- /* if the oscillator is not in normal operation, we do not update */
- if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
- s->next_second_time += ticks_per_sec;
- qemu_mod_timer(s->second_timer, s->next_second_time);
- } else {
- rtc_next_second(&s->current_tm);
-
- if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
- /* update in progress bit */
- s->cmos_data[RTC_REG_A] |= REG_A_UIP;
- }
- /* should be 244 us = 8 / 32768 seconds, but currently the
- timers do not have the necessary resolution. */
- delay = (ticks_per_sec * 1) / 100;
- if (delay < 1)
- delay = 1;
- qemu_mod_timer(s->second_timer2,
- s->next_second_time + delay);
- }
-}
-
-static void rtc_update_second2(void *opaque)
-{
- RTCState *s = opaque;
-
- if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
- rtc_copy_date(s);
- }
-
- /* check alarm */
- if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
- if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
- s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
- ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
- s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
- ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
- s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
-
- s->cmos_data[RTC_REG_C] |= 0xa0;
- pic_set_irq(s->irq, 1);
- }
- }
-
- /* update ended interrupt */
- if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
- s->cmos_data[RTC_REG_C] |= 0x90;
- pic_set_irq(s->irq, 1);
- }
-
- /* clear update in progress bit */
- s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
-
- s->next_second_time += ticks_per_sec;
- qemu_mod_timer(s->second_timer, s->next_second_time);
-}
-
-static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
-{
- RTCState *s = opaque;
- int ret;
- if ((addr & 1) == 0) {
- return 0xff;
- } else {
- switch(s->cmos_index) {
- case RTC_SECONDS:
- case RTC_MINUTES:
- case RTC_HOURS:
- case RTC_DAY_OF_WEEK:
- case RTC_DAY_OF_MONTH:
- case RTC_MONTH:
- case RTC_YEAR:
- ret = s->cmos_data[s->cmos_index];
- break;
- case RTC_REG_A:
- ret = s->cmos_data[s->cmos_index];
- break;
- case RTC_REG_C:
- ret = s->cmos_data[s->cmos_index];
- pic_set_irq(s->irq, 0);
- s->cmos_data[RTC_REG_C] = 0x00;
- break;
- default:
- ret = s->cmos_data[s->cmos_index];
- break;
- }
-#ifdef DEBUG_CMOS
- printf("cmos: read index=0x%02x val=0x%02x\n",
- s->cmos_index, ret);
-#endif
- return ret;
- }
-}
-
-void rtc_set_memory(RTCState *s, int addr, int val)
-{
- if (addr >= 0 && addr <= 127)
- s->cmos_data[addr] = val;
-}
-
-void rtc_set_date(RTCState *s, const struct tm *tm)
-{
- s->current_tm = *tm;
- rtc_copy_date(s);
-}
-
-static void rtc_save(QEMUFile *f, void *opaque)
-{
- RTCState *s = opaque;
-
- qemu_put_buffer(f, s->cmos_data, 128);
- qemu_put_8s(f, &s->cmos_index);
-
- qemu_put_be32s(f, &s->current_tm.tm_sec);
- qemu_put_be32s(f, &s->current_tm.tm_min);
- qemu_put_be32s(f, &s->current_tm.tm_hour);
- qemu_put_be32s(f, &s->current_tm.tm_wday);
- qemu_put_be32s(f, &s->current_tm.tm_mday);
- qemu_put_be32s(f, &s->current_tm.tm_mon);
- qemu_put_be32s(f, &s->current_tm.tm_year);
-
- qemu_put_timer(f, s->periodic_timer);
- qemu_put_be64s(f, &s->next_periodic_time);
-
- qemu_put_be64s(f, &s->next_second_time);
- qemu_put_timer(f, s->second_timer);
- qemu_put_timer(f, s->second_timer2);
-}
-
-static int rtc_load(QEMUFile *f, void *opaque, int version_id)
-{
- RTCState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_buffer(f, s->cmos_data, 128);
- qemu_get_8s(f, &s->cmos_index);
-
- qemu_get_be32s(f, &s->current_tm.tm_sec);
- qemu_get_be32s(f, &s->current_tm.tm_min);
- qemu_get_be32s(f, &s->current_tm.tm_hour);
- qemu_get_be32s(f, &s->current_tm.tm_wday);
- qemu_get_be32s(f, &s->current_tm.tm_mday);
- qemu_get_be32s(f, &s->current_tm.tm_mon);
- qemu_get_be32s(f, &s->current_tm.tm_year);
-
- qemu_get_timer(f, s->periodic_timer);
- qemu_get_be64s(f, &s->next_periodic_time);
-
- qemu_get_be64s(f, &s->next_second_time);
- qemu_get_timer(f, s->second_timer);
- qemu_get_timer(f, s->second_timer2);
- return 0;
-}
-
-RTCState *rtc_init(int base, int irq)
-{
- RTCState *s;
-
- s = qemu_mallocz(sizeof(RTCState));
- if (!s)
- return NULL;
-
- s->irq = irq;
- s->cmos_data[RTC_REG_A] = 0x26;
- s->cmos_data[RTC_REG_B] = 0x02;
- s->cmos_data[RTC_REG_C] = 0x00;
- s->cmos_data[RTC_REG_D] = 0x80;
-
- s->periodic_timer = qemu_new_timer(vm_clock,
- rtc_periodic_timer, s);
- s->second_timer = qemu_new_timer(vm_clock,
- rtc_update_second, s);
- s->second_timer2 = qemu_new_timer(vm_clock,
- rtc_update_second2, s);
-
- s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
- qemu_mod_timer(s->second_timer2, s->next_second_time);
-
- register_ioport_write(base, 2, 1, cmos_ioport_write, s);
- register_ioport_read(base, 2, 1, cmos_ioport_read, s);
-
- register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
- return s;
-}
-
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
deleted file mode 100644
index 22d742a..0000000
--- a/hw/mips_r4k.c
+++ /dev/null
@@ -1,291 +0,0 @@
-#include "vl.h"
-
-#define BIOS_FILENAME "mips_bios.bin"
-//#define BIOS_FILENAME "system.bin"
-#define KERNEL_LOAD_ADDR 0x80010000
-#define INITRD_LOAD_ADDR 0x80800000
-
-#define VIRT_TO_PHYS_ADDEND (-0x80000000LL)
-
-extern FILE *logfile;
-
-static PITState *pit;
-
-static void pic_irq_request(void *opaque, int level)
-{
- CPUState *env = first_cpu;
- if (level) {
- env->CP0_Cause |= 0x00000400;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- } else {
- env->CP0_Cause &= ~0x00000400;
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
- }
-}
-
-void cpu_mips_irqctrl_init (void)
-{
-}
-
-/* XXX: do not use a global */
-uint32_t cpu_mips_get_random (CPUState *env)
-{
- static uint32_t seed = 0;
- uint32_t idx;
- seed = seed * 314159 + 1;
- idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
- return idx;
-}
-
-/* MIPS R4K timer */
-uint32_t cpu_mips_get_count (CPUState *env)
-{
- return env->CP0_Count +
- (uint32_t)muldiv64(qemu_get_clock(vm_clock),
- 100 * 1000 * 1000, ticks_per_sec);
-}
-
-static void cpu_mips_update_count (CPUState *env, uint32_t count,
- uint32_t compare)
-{
- uint64_t now, next;
- uint32_t tmp;
-
- tmp = count;
- if (count == compare)
- tmp++;
- now = qemu_get_clock(vm_clock);
- next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
- if (next == now)
- next++;
-#if 0
- if (logfile) {
- fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n",
- __func__, now, count, compare, next - now);
- }
-#endif
- /* Store new count and compare registers */
- env->CP0_Compare = compare;
- env->CP0_Count =
- count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
- /* Adjust timer */
- qemu_mod_timer(env->timer, next);
-}
-
-void cpu_mips_store_count (CPUState *env, uint32_t value)
-{
- cpu_mips_update_count(env, value, env->CP0_Compare);
-}
-
-void cpu_mips_store_compare (CPUState *env, uint32_t value)
-{
- cpu_mips_update_count(env, cpu_mips_get_count(env), value);
- env->CP0_Cause &= ~0x00008000;
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-}
-
-static void mips_timer_cb (void *opaque)
-{
- CPUState *env;
-
- env = opaque;
-#if 0
- if (logfile) {
- fprintf(logfile, "%s\n", __func__);
- }
-#endif
- cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
- env->CP0_Cause |= 0x00008000;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
-}
-
-void cpu_mips_clock_init (CPUState *env)
-{
- env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
- env->CP0_Compare = 0;
- cpu_mips_update_count(env, 1, 0);
-}
-
-
-static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#if 0
- if (logfile)
- fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
-#endif
- cpu_outb(NULL, addr & 0xffff, value);
-}
-
-static uint32_t io_readb (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret = cpu_inb(NULL, addr & 0xffff);
-#if 0
- if (logfile)
- fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
-#endif
- return ret;
-}
-
-static void io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#if 0
- if (logfile)
- fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
-#endif
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap16(value);
-#endif
- cpu_outw(NULL, addr & 0xffff, value);
-}
-
-static uint32_t io_readw (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret = cpu_inw(NULL, addr & 0xffff);
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = bswap16(ret);
-#endif
-#if 0
- if (logfile)
- fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
-#endif
- return ret;
-}
-
-static void io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#if 0
- if (logfile)
- fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
-#endif
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap32(value);
-#endif
- cpu_outl(NULL, addr & 0xffff, value);
-}
-
-static uint32_t io_readl (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret = cpu_inl(NULL, addr & 0xffff);
-
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = bswap32(ret);
-#endif
-#if 0
- if (logfile)
- fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
-#endif
- return ret;
-}
-
-CPUWriteMemoryFunc *io_write[] = {
- &io_writeb,
- &io_writew,
- &io_writel,
-};
-
-CPUReadMemoryFunc *io_read[] = {
- &io_readb,
- &io_readw,
- &io_readl,
-};
-
-void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- char buf[1024];
- int64_t entry = 0;
- unsigned long bios_offset;
- int io_memory;
- int ret;
- CPUState *env;
- long kernel_size;
-
- env = cpu_init();
- register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
-
- /* allocate RAM */
- cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
-
- /* Try to load a BIOS image. If this fails, we continue regardless,
- but initialize the hardware ourselves. When a kernel gets
- preloaded we also initialize the hardware, since the BIOS wasn't
- run. */
- bios_offset = ram_size + vga_ram_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
- ret = load_image(buf, phys_ram_base + bios_offset);
- if (ret == BIOS_SIZE) {
- cpu_register_physical_memory((uint32_t)(0x1fc00000),
- BIOS_SIZE, bios_offset | IO_MEM_ROM);
- } else {
- /* not fatal */
- fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
- buf);
- }
-
- kernel_size = 0;
- if (kernel_filename) {
- kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
- if (kernel_size >= 0)
- env->PC = entry;
- else {
- kernel_size = load_image(kernel_filename,
- phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
- if (kernel_size < 0) {
- fprintf(stderr, "qemu: could not load kernel '%s'\n",
- kernel_filename);
- exit(1);
- }
- env->PC = KERNEL_LOAD_ADDR;
- }
-
- /* load initrd */
- if (initrd_filename) {
- if (load_image(initrd_filename,
- phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND)
- == (target_ulong) -1) {
- fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- initrd_filename);
- exit(1);
- }
- }
-
- /* Store command line. */
- strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
- /* FIXME: little endian support */
- *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
- *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
- }
-
- /* Init internal devices */
- cpu_mips_clock_init(env);
- cpu_mips_irqctrl_init();
-
- /* Register 64 KB of ISA IO space at 0x14000000 */
- io_memory = cpu_register_io_memory(0, io_read, io_write, NULL);
- cpu_register_physical_memory(0x14000000, 0x00010000, io_memory);
- isa_mem_base = 0x10000000;
-
- isa_pic = pic_init(pic_irq_request, env);
- pit = pit_init(0x40, 0);
- serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
- vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size,
- vga_ram_size, 0, 0);
-
- if (nd_table[0].vlan) {
- if (nd_table[0].model == NULL
- || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
- isa_ne2000_init(0x300, 9, &nd_table[0]);
- } else {
- fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
- exit (1);
- }
- }
-}
-
-QEMUMachine mips_machine = {
- "mips",
- "mips r4k platform",
- mips_r4k_init,
-};
diff --git a/hw/mmc.h b/hw/mmc.h
new file mode 100644
index 0000000..3ae3ea9
--- /dev/null
+++ b/hw/mmc.h
@@ -0,0 +1,214 @@
+/*
+ * Header for MultiMediaCard (MMC)
+ *
+ * Copyright 2002 Hewlett-Packard Company
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Based strongly on code by:
+ *
+ * Author: Yong-iL Joh <tolkien@mizi.com>
+ * Date : $Date: 2002/06/18 12:37:30 $
+ *
+ * Author: Andrew Christian
+ * 15 May 2002
+ */
+
+#ifndef MMC_MMC_H
+#define MMC_MMC_H
+
+/* Standard MMC commands (4.1) type argument response */
+ /* class 1 */
+#define MMC_GO_IDLE_STATE 0 /* bc */
+#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
+#define MMC_ALL_SEND_CID 2 /* bcr R2 */
+#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
+#define MMC_SET_DSR 4 /* bc [31:16] RCA */
+#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
+#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
+#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
+#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
+#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
+#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
+#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
+#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
+#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
+
+ /* class 2 */
+#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
+#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
+#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
+
+ /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
+
+ /* class 4 */
+#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
+#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
+#define MMC_PROGRAM_CID 26 /* adtc R1 */
+#define MMC_PROGRAM_CSD 27 /* adtc R1 */
+
+ /* class 6 */
+#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
+#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
+#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
+
+ /* class 5 */
+#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
+#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
+#define MMC_ERASE 38 /* ac R1b */
+
+ /* class 9 */
+#define MMC_FAST_IO 39 /* ac <Complex> R4 */
+#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
+
+ /* class 7 */
+#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
+
+ /* class 8 */
+#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
+#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
+
+/*
+ * MMC_SWITCH argument format:
+ *
+ * [31:26] Always 0
+ * [25:24] Access Mode
+ * [23:16] Location of target Byte in EXT_CSD
+ * [15:08] Value Byte
+ * [07:03] Always 0
+ * [02:00] Command Set
+ */
+
+/*
+ MMC status in R1
+ Type
+ e : error bit
+ s : status bit
+ r : detected and set for the actual command response
+ x : detected and set during command execution. the host must poll
+ the card by sending status command in order to read these bits.
+ Clear condition
+ a : according to the card state
+ b : always related to the previous command. Reception of
+ a valid command will clear it (with a delay of one command)
+ c : clear by read
+ */
+
+#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
+#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
+#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
+#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
+#define R1_ERASE_PARAM (1 << 27) /* ex, c */
+#define R1_WP_VIOLATION (1 << 26) /* erx, c */
+#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
+#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
+#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
+#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
+#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
+#define R1_CC_ERROR (1 << 20) /* erx, c */
+#define R1_ERROR (1 << 19) /* erx, c */
+#define R1_UNDERRUN (1 << 18) /* ex, c */
+#define R1_OVERRUN (1 << 17) /* ex, c */
+#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
+#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
+#define R1_ERASE_RESET (1 << 13) /* sr, c */
+#define R1_STATUS(x) (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
+#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
+#define R1_APP_CMD (1 << 5) /* sr, c */
+
+
+/*
+ * OCR bits are mostly in host.h
+ */
+#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
+
+/*
+ * Card Command Classes (CCC)
+ */
+#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
+ /* (CMD0,1,2,3,4,7,9,10,12,13,15) */
+#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
+ /* (CMD11) */
+#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
+ /* (CMD16,17,18) */
+#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
+ /* (CMD20) */
+#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
+ /* (CMD16,24,25,26,27) */
+#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
+ /* (CMD32,33,34,35,36,37,38,39) */
+#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
+ /* (CMD28,29,30) */
+#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
+ /* (CMD16,CMD42) */
+#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
+ /* (CMD55,56,57,ACMD*) */
+#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
+ /* (CMD5,39,40,52,53) */
+#define CCC_SWITCH (1<<10) /* (10) High speed switch */
+ /* (CMD6,34,35,36,37,50) */
+ /* (11) Reserved */
+ /* (CMD?) */
+
+/*
+ * CSD field definitions
+ */
+
+#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
+#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
+#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
+
+#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
+#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
+#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
+#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
+
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+#define EXT_CSD_HS_TIMING 185 /* R/W */
+#define EXT_CSD_CARD_TYPE 196 /* RO */
+#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+#define EXT_CSD_CMD_SET_NORMAL (1<<0)
+#define EXT_CSD_CMD_SET_SECURE (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
+
+#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
+
+#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+
+/*
+ * MMC_SWITCH access modes
+ */
+
+#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
+
+#endif /* MMC_MMC_PROTOCOL_H */
+
diff --git a/hw/ne2000.c b/hw/ne2000.c
deleted file mode 100644
index e23c6df..0000000
--- a/hw/ne2000.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
- * QEMU NE2000 emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug NE2000 card */
-//#define DEBUG_NE2000
-
-#define MAX_ETH_FRAME_SIZE 1514
-
-#define E8390_CMD 0x00 /* The command register (for all pages) */
-/* Page 0 register offsets. */
-#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
-#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
-#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
-#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
-#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
-#define EN0_TSR 0x04 /* Transmit status reg RD */
-#define EN0_TPSR 0x04 /* Transmit starting page WR */
-#define EN0_NCR 0x05 /* Number of collision reg RD */
-#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
-#define EN0_FIFO 0x06 /* FIFO RD */
-#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
-#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
-#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
-#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
-#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
-#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
-#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
-#define EN0_RTL8029ID0 0x0a /* Realtek ID byte #1 RD */
-#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
-#define EN0_RTL8029ID1 0x0b /* Realtek ID byte #2 RD */
-#define EN0_RSR 0x0c /* rx status reg RD */
-#define EN0_RXCR 0x0c /* RX configuration reg WR */
-#define EN0_TXCR 0x0d /* TX configuration reg WR */
-#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
-#define EN0_DCFG 0x0e /* Data configuration reg WR */
-#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
-#define EN0_IMR 0x0f /* Interrupt mask reg WR */
-#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
-
-#define EN1_PHYS 0x11
-#define EN1_CURPAG 0x17
-#define EN1_MULT 0x18
-
-#define EN2_STARTPG 0x21 /* Starting page of ring bfr RD */
-#define EN2_STOPPG 0x22 /* Ending page +1 of ring bfr RD */
-
-#define EN3_CONFIG0 0x33
-#define EN3_CONFIG1 0x34
-#define EN3_CONFIG2 0x35
-#define EN3_CONFIG3 0x36
-
-/* Register accessed at EN_CMD, the 8390 base addr. */
-#define E8390_STOP 0x01 /* Stop and reset the chip */
-#define E8390_START 0x02 /* Start the chip, clear reset */
-#define E8390_TRANS 0x04 /* Transmit a frame */
-#define E8390_RREAD 0x08 /* Remote read */
-#define E8390_RWRITE 0x10 /* Remote write */
-#define E8390_NODMA 0x20 /* Remote DMA */
-#define E8390_PAGE0 0x00 /* Select page chip registers */
-#define E8390_PAGE1 0x40 /* using the two high-order bits */
-#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
-
-/* Bits in EN0_ISR - Interrupt status register */
-#define ENISR_RX 0x01 /* Receiver, no error */
-#define ENISR_TX 0x02 /* Transmitter, no error */
-#define ENISR_RX_ERR 0x04 /* Receiver, with error */
-#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
-#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
-#define ENISR_COUNTERS 0x20 /* Counters need emptying */
-#define ENISR_RDC 0x40 /* remote dma complete */
-#define ENISR_RESET 0x80 /* Reset completed */
-#define ENISR_ALL 0x3f /* Interrupts we will enable */
-
-/* Bits in received packet status byte and EN0_RSR*/
-#define ENRSR_RXOK 0x01 /* Received a good packet */
-#define ENRSR_CRC 0x02 /* CRC error */
-#define ENRSR_FAE 0x04 /* frame alignment error */
-#define ENRSR_FO 0x08 /* FIFO overrun */
-#define ENRSR_MPA 0x10 /* missed pkt */
-#define ENRSR_PHY 0x20 /* physical/multicast address */
-#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
-#define ENRSR_DEF 0x80 /* deferring */
-
-/* Transmitted packet status, EN0_TSR. */
-#define ENTSR_PTX 0x01 /* Packet transmitted without error */
-#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
-#define ENTSR_COL 0x04 /* The transmit collided at least once. */
-#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
-#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
-#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
-#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
-#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
-
-#define NE2000_PMEM_SIZE (32*1024)
-#define NE2000_PMEM_START (16*1024)
-#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START)
-#define NE2000_MEM_SIZE NE2000_PMEM_END
-
-typedef struct NE2000State {
- uint8_t cmd;
- uint32_t start;
- uint32_t stop;
- uint8_t boundary;
- uint8_t tsr;
- uint8_t tpsr;
- uint16_t tcnt;
- uint16_t rcnt;
- uint32_t rsar;
- uint8_t rsr;
- uint8_t rxcr;
- uint8_t isr;
- uint8_t dcfg;
- uint8_t imr;
- uint8_t phys[6]; /* mac address */
- uint8_t curpag;
- uint8_t mult[8]; /* multicast mask array */
- int irq;
- PCIDevice *pci_dev;
- VLANClientState *vc;
- uint8_t macaddr[6];
- uint8_t mem[NE2000_MEM_SIZE];
-} NE2000State;
-
-static void ne2000_reset(NE2000State *s)
-{
- int i;
-
- s->isr = ENISR_RESET;
- memcpy(s->mem, s->macaddr, 6);
- s->mem[14] = 0x57;
- s->mem[15] = 0x57;
-
- /* duplicate prom data */
- for(i = 15;i >= 0; i--) {
- s->mem[2 * i] = s->mem[i];
- s->mem[2 * i + 1] = s->mem[i];
- }
-}
-
-static void ne2000_update_irq(NE2000State *s)
-{
- int isr;
- isr = (s->isr & s->imr) & 0x7f;
-#if defined(DEBUG_NE2000)
- printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
- s->irq, isr ? 1 : 0, s->isr, s->imr);
-#endif
- if (s->irq == 16) {
- /* PCI irq */
- pci_set_irq(s->pci_dev, 0, (isr != 0));
- } else {
- /* ISA irq */
- pic_set_irq(s->irq, (isr != 0));
- }
-}
-
-#define POLYNOMIAL 0x04c11db6
-
-/* From FreeBSD */
-/* XXX: optimize */
-static int compute_mcast_idx(const uint8_t *ep)
-{
- uint32_t crc;
- int carry, i, j;
- uint8_t b;
-
- crc = 0xffffffff;
- for (i = 0; i < 6; i++) {
- b = *ep++;
- for (j = 0; j < 8; j++) {
- carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
- crc <<= 1;
- b >>= 1;
- if (carry)
- crc = ((crc ^ POLYNOMIAL) | carry);
- }
- }
- return (crc >> 26);
-}
-
-static int ne2000_buffer_full(NE2000State *s)
-{
- int avail, index, boundary;
-
- index = s->curpag << 8;
- boundary = s->boundary << 8;
- if (index <= boundary)
- avail = boundary - index;
- else
- avail = (s->stop - s->start) - (index - boundary);
- if (avail < (MAX_ETH_FRAME_SIZE + 4))
- return 1;
- return 0;
-}
-
-static int ne2000_can_receive(void *opaque)
-{
- NE2000State *s = opaque;
-
- if (s->cmd & E8390_STOP)
- return 1;
- return !ne2000_buffer_full(s);
-}
-
-#define MIN_BUF_SIZE 60
-
-static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
-{
- NE2000State *s = opaque;
- uint8_t *p;
- int total_len, next, avail, len, index, mcast_idx;
- uint8_t buf1[60];
- static const uint8_t broadcast_macaddr[6] =
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-#if defined(DEBUG_NE2000)
- printf("NE2000: received len=%d\n", size);
-#endif
-
- if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
- return;
-
- /* XXX: check this */
- if (s->rxcr & 0x10) {
- /* promiscuous: receive all */
- } else {
- if (!memcmp(buf, broadcast_macaddr, 6)) {
- /* broadcast address */
- if (!(s->rxcr & 0x04))
- return;
- } else if (buf[0] & 0x01) {
- /* multicast */
- if (!(s->rxcr & 0x08))
- return;
- mcast_idx = compute_mcast_idx(buf);
- if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
- return;
- } else if (s->mem[0] == buf[0] &&
- s->mem[2] == buf[1] &&
- s->mem[4] == buf[2] &&
- s->mem[6] == buf[3] &&
- s->mem[8] == buf[4] &&
- s->mem[10] == buf[5]) {
- /* match */
- } else {
- return;
- }
- }
-
-
- /* 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;
- /* address for next packet (4 bytes for CRC) */
- next = index + ((total_len + 4 + 255) & ~0xff);
- if (next >= s->stop)
- next -= (s->stop - s->start);
- /* prepare packet header */
- p = s->mem + index;
- s->rsr = ENRSR_RXOK; /* receive status */
- /* XXX: check this */
- if (buf[0] & 0x01)
- s->rsr |= ENRSR_PHY;
- p[0] = s->rsr;
- p[1] = next >> 8;
- p[2] = total_len;
- p[3] = total_len >> 8;
- index += 4;
-
- /* write packet data */
- while (size > 0) {
- avail = s->stop - index;
- len = size;
- if (len > avail)
- len = avail;
- memcpy(s->mem + index, buf, len);
- buf += len;
- index += len;
- if (index == s->stop)
- index = s->start;
- size -= len;
- }
- s->curpag = next >> 8;
-
- /* now we can signal we have receive something */
- s->isr |= ENISR_RX;
- ne2000_update_irq(s);
-}
-
-static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- NE2000State *s = opaque;
- int offset, page, index;
-
- addr &= 0xf;
-#ifdef DEBUG_NE2000
- printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
-#endif
- if (addr == E8390_CMD) {
- /* control register */
- s->cmd = val;
- if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
- s->isr &= ~ENISR_RESET;
- /* test specific case: zero length transfert */
- if ((val & (E8390_RREAD | E8390_RWRITE)) &&
- s->rcnt == 0) {
- s->isr |= ENISR_RDC;
- ne2000_update_irq(s);
- }
- if (val & E8390_TRANS) {
- index = (s->tpsr << 8);
- /* XXX: next 2 lines are a hack to make netware 3.11 work */
- if (index >= NE2000_PMEM_END)
- index -= NE2000_PMEM_SIZE;
- /* fail safe: check range on the transmitted length */
- if (index + s->tcnt <= NE2000_PMEM_END) {
- qemu_send_packet(s->vc, s->mem + index, s->tcnt);
- }
- /* signal end of transfert */
- s->tsr = ENTSR_PTX;
- s->isr |= ENISR_TX;
- s->cmd &= ~E8390_TRANS;
- ne2000_update_irq(s);
- }
- }
- } else {
- page = s->cmd >> 6;
- offset = addr | (page << 4);
- switch(offset) {
- case EN0_STARTPG:
- s->start = val << 8;
- break;
- case EN0_STOPPG:
- s->stop = val << 8;
- break;
- case EN0_BOUNDARY:
- s->boundary = val;
- break;
- case EN0_IMR:
- s->imr = val;
- ne2000_update_irq(s);
- break;
- case EN0_TPSR:
- s->tpsr = val;
- break;
- case EN0_TCNTLO:
- s->tcnt = (s->tcnt & 0xff00) | val;
- break;
- case EN0_TCNTHI:
- s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
- break;
- case EN0_RSARLO:
- s->rsar = (s->rsar & 0xff00) | val;
- break;
- case EN0_RSARHI:
- s->rsar = (s->rsar & 0x00ff) | (val << 8);
- break;
- case EN0_RCNTLO:
- s->rcnt = (s->rcnt & 0xff00) | val;
- break;
- case EN0_RCNTHI:
- s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
- break;
- case EN0_RXCR:
- s->rxcr = val;
- break;
- case EN0_DCFG:
- s->dcfg = val;
- break;
- case EN0_ISR:
- s->isr &= ~(val & 0x7f);
- ne2000_update_irq(s);
- break;
- case EN1_PHYS ... EN1_PHYS + 5:
- s->phys[offset - EN1_PHYS] = val;
- break;
- case EN1_CURPAG:
- s->curpag = val;
- break;
- case EN1_MULT ... EN1_MULT + 7:
- s->mult[offset - EN1_MULT] = val;
- break;
- }
- }
-}
-
-static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
-{
- NE2000State *s = opaque;
- int offset, page, ret;
-
- addr &= 0xf;
- if (addr == E8390_CMD) {
- ret = s->cmd;
- } else {
- page = s->cmd >> 6;
- offset = addr | (page << 4);
- switch(offset) {
- case EN0_TSR:
- ret = s->tsr;
- break;
- case EN0_BOUNDARY:
- ret = s->boundary;
- break;
- case EN0_ISR:
- ret = s->isr;
- break;
- case EN0_RSARLO:
- ret = s->rsar & 0x00ff;
- break;
- case EN0_RSARHI:
- ret = s->rsar >> 8;
- break;
- case EN1_PHYS ... EN1_PHYS + 5:
- ret = s->phys[offset - EN1_PHYS];
- break;
- case EN1_CURPAG:
- ret = s->curpag;
- break;
- case EN1_MULT ... EN1_MULT + 7:
- ret = s->mult[offset - EN1_MULT];
- break;
- case EN0_RSR:
- ret = s->rsr;
- break;
- case EN2_STARTPG:
- ret = s->start >> 8;
- break;
- case EN2_STOPPG:
- ret = s->stop >> 8;
- break;
- case EN0_RTL8029ID0:
- ret = 0x50;
- break;
- case EN0_RTL8029ID1:
- ret = 0x43;
- break;
- case EN3_CONFIG0:
- ret = 0; /* 10baseT media */
- break;
- case EN3_CONFIG2:
- ret = 0x40; /* 10baseT active */
- break;
- case EN3_CONFIG3:
- ret = 0x40; /* Full duplex */
- break;
- default:
- ret = 0x00;
- break;
- }
- }
-#ifdef DEBUG_NE2000
- printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
-#endif
- return ret;
-}
-
-static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
- uint32_t val)
-{
- if (addr < 32 ||
- (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
- s->mem[addr] = val;
- }
-}
-
-static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
- uint32_t val)
-{
- addr &= ~1; /* XXX: check exact behaviour if not even */
- if (addr < 32 ||
- (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
- *(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
- }
-}
-
-static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
- uint32_t val)
-{
- addr &= ~1; /* XXX: check exact behaviour if not even */
- if (addr < 32 ||
- (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
- cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
- }
-}
-
-static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
-{
- if (addr < 32 ||
- (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
- return s->mem[addr];
- } else {
- return 0xff;
- }
-}
-
-static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
-{
- addr &= ~1; /* XXX: check exact behaviour if not even */
- if (addr < 32 ||
- (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
- return le16_to_cpu(*(uint16_t *)(s->mem + addr));
- } else {
- return 0xffff;
- }
-}
-
-static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
-{
- addr &= ~1; /* XXX: check exact behaviour if not even */
- if (addr < 32 ||
- (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
- return le32_to_cpupu((uint32_t *)(s->mem + addr));
- } else {
- return 0xffffffff;
- }
-}
-
-static inline void ne2000_dma_update(NE2000State *s, int len)
-{
- s->rsar += len;
- /* wrap */
- /* XXX: check what to do if rsar > stop */
- if (s->rsar == s->stop)
- s->rsar = s->start;
-
- if (s->rcnt <= len) {
- s->rcnt = 0;
- /* signal end of transfert */
- s->isr |= ENISR_RDC;
- ne2000_update_irq(s);
- } else {
- s->rcnt -= len;
- }
-}
-
-static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- NE2000State *s = opaque;
-
-#ifdef DEBUG_NE2000
- printf("NE2000: asic write val=0x%04x\n", val);
-#endif
- if (s->rcnt == 0)
- return;
- if (s->dcfg & 0x01) {
- /* 16 bit access */
- ne2000_mem_writew(s, s->rsar, val);
- ne2000_dma_update(s, 2);
- } else {
- /* 8 bit access */
- ne2000_mem_writeb(s, s->rsar, val);
- ne2000_dma_update(s, 1);
- }
-}
-
-static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
-{
- NE2000State *s = opaque;
- int ret;
-
- if (s->dcfg & 0x01) {
- /* 16 bit access */
- ret = ne2000_mem_readw(s, s->rsar);
- ne2000_dma_update(s, 2);
- } else {
- /* 8 bit access */
- ret = ne2000_mem_readb(s, s->rsar);
- ne2000_dma_update(s, 1);
- }
-#ifdef DEBUG_NE2000
- printf("NE2000: asic read val=0x%04x\n", ret);
-#endif
- return ret;
-}
-
-static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- NE2000State *s = opaque;
-
-#ifdef DEBUG_NE2000
- printf("NE2000: asic writel val=0x%04x\n", val);
-#endif
- if (s->rcnt == 0)
- return;
- /* 32 bit access */
- ne2000_mem_writel(s, s->rsar, val);
- ne2000_dma_update(s, 4);
-}
-
-static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
-{
- NE2000State *s = opaque;
- int ret;
-
- /* 32 bit access */
- ret = ne2000_mem_readl(s, s->rsar);
- ne2000_dma_update(s, 4);
-#ifdef DEBUG_NE2000
- printf("NE2000: asic readl val=0x%04x\n", ret);
-#endif
- return ret;
-}
-
-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(void *opaque, uint32_t addr)
-{
- NE2000State *s = opaque;
- ne2000_reset(s);
- return 0;
-}
-
-static void ne2000_save(QEMUFile* f,void* opaque)
-{
- NE2000State* s=(NE2000State*)opaque;
-
- qemu_put_8s(f, &s->rxcr);
-
- qemu_put_8s(f, &s->cmd);
- qemu_put_be32s(f, &s->start);
- qemu_put_be32s(f, &s->stop);
- qemu_put_8s(f, &s->boundary);
- qemu_put_8s(f, &s->tsr);
- qemu_put_8s(f, &s->tpsr);
- qemu_put_be16s(f, &s->tcnt);
- qemu_put_be16s(f, &s->rcnt);
- qemu_put_be32s(f, &s->rsar);
- qemu_put_8s(f, &s->rsr);
- qemu_put_8s(f, &s->isr);
- qemu_put_8s(f, &s->dcfg);
- qemu_put_8s(f, &s->imr);
- qemu_put_buffer(f, s->phys, 6);
- qemu_put_8s(f, &s->curpag);
- qemu_put_buffer(f, s->mult, 8);
- qemu_put_be32s(f, &s->irq);
- qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
-}
-
-static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
-{
- NE2000State* s=(NE2000State*)opaque;
-
- if (version_id == 2) {
- qemu_get_8s(f, &s->rxcr);
- } else if (version_id == 1) {
- s->rxcr = 0x0c;
- } else {
- return -EINVAL;
- }
-
- qemu_get_8s(f, &s->cmd);
- qemu_get_be32s(f, &s->start);
- qemu_get_be32s(f, &s->stop);
- qemu_get_8s(f, &s->boundary);
- qemu_get_8s(f, &s->tsr);
- qemu_get_8s(f, &s->tpsr);
- qemu_get_be16s(f, &s->tcnt);
- qemu_get_be16s(f, &s->rcnt);
- qemu_get_be32s(f, &s->rsar);
- qemu_get_8s(f, &s->rsr);
- qemu_get_8s(f, &s->isr);
- qemu_get_8s(f, &s->dcfg);
- qemu_get_8s(f, &s->imr);
- qemu_get_buffer(f, s->phys, 6);
- qemu_get_8s(f, &s->curpag);
- qemu_get_buffer(f, s->mult, 8);
- qemu_get_be32s(f, &s->irq);
- qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
-
- return 0;
-}
-
-void isa_ne2000_init(int base, int irq, NICInfo *nd)
-{
- NE2000State *s;
-
- 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, 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, 1, ne2000_reset_ioport_write, s);
- register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
- s->irq = irq;
- memcpy(s->macaddr, nd->macaddr, 6);
-
- ne2000_reset(s);
-
- s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
- ne2000_can_receive, s);
-
- snprintf(s->vc->info_str, sizeof(s->vc->info_str),
- "ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
- s->macaddr[0],
- s->macaddr[1],
- s->macaddr[2],
- s->macaddr[3],
- s->macaddr[4],
- s->macaddr[5]);
-
- register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
-}
-
-/***********************************************************/
-/* PCI NE2000 definitions */
-
-typedef struct PCINE2000State {
- PCIDevice dev;
- NE2000State ne2000;
-} PCINE2000State;
-
-static void ne2000_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCINE2000State *d = (PCINE2000State *)pci_dev;
- NE2000State *s = &d->ne2000;
-
- register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
- register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
-
- register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
- register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
- register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
- register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
- register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
- register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
-
- register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
- register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
-}
-
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
-{
- PCINE2000State *d;
- NE2000State *s;
- uint8_t *pci_conf;
-
- d = (PCINE2000State *)pci_register_device(bus,
- "NE2000", sizeof(PCINE2000State),
- -1,
- NULL, NULL);
- pci_conf = d->dev.config;
- pci_conf[0x00] = 0xec; // Realtek 8029
- pci_conf[0x01] = 0x10;
- pci_conf[0x02] = 0x29;
- pci_conf[0x03] = 0x80;
- pci_conf[0x0a] = 0x00; // ethernet network controller
- pci_conf[0x0b] = 0x02;
- pci_conf[0x0e] = 0x00; // header_type
- pci_conf[0x3d] = 1; // interrupt pin 0
-
- pci_register_io_region(&d->dev, 0, 0x100,
- PCI_ADDRESS_SPACE_IO, ne2000_map);
- s = &d->ne2000;
- s->irq = 16; // PCI interrupt
- s->pci_dev = (PCIDevice *)d;
- memcpy(s->macaddr, nd->macaddr, 6);
- ne2000_reset(s);
- s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
- ne2000_can_receive, s);
-
- snprintf(s->vc->info_str, sizeof(s->vc->info_str),
- "ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
- s->macaddr[0],
- s->macaddr[1],
- s->macaddr[2],
- s->macaddr[3],
- s->macaddr[4],
- s->macaddr[5]);
-
- /* XXX: instance number ? */
- register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
- register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,
- &d->dev);
-}
diff --git a/hw/openpic.c b/hw/openpic.c
deleted file mode 100644
index 3177337..0000000
--- a/hw/openpic.c
+++ /dev/null
@@ -1,1027 +0,0 @@
-/*
- * OpenPIC emulation
- *
- * Copyright (c) 2004 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-/*
- *
- * Based on OpenPic implementations:
- * - Intel GW80314 I/O compagnion chip developper's manual
- * - Motorola MPC8245 & MPC8540 user manuals.
- * - Motorola MCP750 (aka Raven) programmer manual.
- * - Motorola Harrier programmer manuel
- *
- * Serial interrupts, as implemented in Raven chipset are not supported yet.
- *
- */
-#include "vl.h"
-
-//#define DEBUG_OPENPIC
-
-#ifdef DEBUG_OPENPIC
-#define DPRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...) do { } while (0)
-#endif
-#define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
-
-#define USE_MPCxxx /* Intel model is broken, for now */
-
-#if defined (USE_INTEL_GW80314)
-/* Intel GW80314 I/O Companion chip */
-
-#define MAX_CPU 4
-#define MAX_IRQ 32
-#define MAX_DBL 4
-#define MAX_MBX 4
-#define MAX_TMR 4
-#define VECTOR_BITS 8
-#define MAX_IPI 0
-
-#define VID (0x00000000)
-
-#define OPENPIC_LITTLE_ENDIAN 1
-#define OPENPIC_BIG_ENDIAN 0
-
-#elif defined(USE_MPCxxx)
-
-#define MAX_CPU 2
-#define MAX_IRQ 64
-#define EXT_IRQ 48
-#define MAX_DBL 0
-#define MAX_MBX 0
-#define MAX_TMR 4
-#define VECTOR_BITS 8
-#define MAX_IPI 4
-#define VID 0x03 /* MPIC version ID */
-#define VENI 0x00000000 /* Vendor ID */
-
-enum {
- IRQ_IPVP = 0,
- IRQ_IDE,
-};
-
-#define OPENPIC_LITTLE_ENDIAN 1
-#define OPENPIC_BIG_ENDIAN 0
-
-#else
-#error "Please select which OpenPic implementation is to be emulated"
-#endif
-
-#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
- (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
-#define OPENPIC_SWAP
-#endif
-
-/* Interrupt definitions */
-#define IRQ_FE (EXT_IRQ) /* Internal functional IRQ */
-#define IRQ_ERR (EXT_IRQ + 1) /* Error IRQ */
-#define IRQ_TIM0 (EXT_IRQ + 2) /* First timer IRQ */
-#if MAX_IPI > 0
-#define IRQ_IPI0 (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */
-#define IRQ_DBL0 (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ */
-#else
-#define IRQ_DBL0 (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */
-#define IRQ_MBX0 (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
-#endif
-
-#define BF_WIDTH(_bits_) \
-(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
-
-static inline void set_bit (uint32_t *field, int bit)
-{
- field[bit >> 5] |= 1 << (bit & 0x1F);
-}
-
-static inline void reset_bit (uint32_t *field, int bit)
-{
- field[bit >> 5] &= ~(1 << (bit & 0x1F));
-}
-
-static inline int test_bit (uint32_t *field, int bit)
-{
- return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
-}
-
-enum {
- IRQ_EXTERNAL = 0x01,
- IRQ_INTERNAL = 0x02,
- IRQ_TIMER = 0x04,
- IRQ_SPECIAL = 0x08,
-} IRQ_src_type;
-
-typedef struct IRQ_queue_t {
- uint32_t queue[BF_WIDTH(MAX_IRQ)];
- int next;
- int priority;
-} IRQ_queue_t;
-
-typedef struct IRQ_src_t {
- uint32_t ipvp; /* IRQ vector/priority register */
- uint32_t ide; /* IRQ destination register */
- int type;
- int last_cpu;
- int pending; /* TRUE if IRQ is pending */
-} IRQ_src_t;
-
-enum IPVP_bits {
- IPVP_MASK = 31,
- IPVP_ACTIVITY = 30,
- IPVP_MODE = 29,
- IPVP_POLARITY = 23,
- IPVP_SENSE = 22,
-};
-#define IPVP_PRIORITY_MASK (0x1F << 16)
-#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
-#define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
-#define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
-
-typedef struct IRQ_dst_t {
- uint32_t pctp; /* CPU current task priority */
- uint32_t pcsr; /* CPU sensitivity register */
- IRQ_queue_t raised;
- IRQ_queue_t servicing;
- CPUState *env;
-} IRQ_dst_t;
-
-struct openpic_t {
- PCIDevice pci_dev;
- int mem_index;
- /* Global registers */
- uint32_t frep; /* Feature reporting register */
- uint32_t glbc; /* Global configuration register */
- uint32_t micr; /* MPIC interrupt configuration register */
- uint32_t veni; /* Vendor identification register */
- uint32_t spve; /* Spurious vector register */
- uint32_t tifr; /* Timer frequency reporting register */
- /* Source registers */
- IRQ_src_t src[MAX_IRQ];
- /* Local registers per output pin */
- IRQ_dst_t dst[MAX_CPU];
- int nb_cpus;
- /* Timer registers */
- struct {
- uint32_t ticc; /* Global timer current count register */
- uint32_t tibc; /* Global timer base count register */
- } timers[MAX_TMR];
-#if MAX_DBL > 0
- /* Doorbell registers */
- uint32_t dar; /* Doorbell activate register */
- struct {
- uint32_t dmr; /* Doorbell messaging register */
- } doorbells[MAX_DBL];
-#endif
-#if MAX_MBX > 0
- /* Mailbox registers */
- struct {
- uint32_t mbr; /* Mailbox register */
- } mailboxes[MAX_MAILBOXES];
-#endif
-};
-
-static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
-{
- set_bit(q->queue, n_IRQ);
-}
-
-static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
-{
- reset_bit(q->queue, n_IRQ);
-}
-
-static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
-{
- return test_bit(q->queue, n_IRQ);
-}
-
-static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
-{
- int next, i;
- int priority;
-
- next = -1;
- priority = -1;
- for (i = 0; i < MAX_IRQ; i++) {
- if (IRQ_testbit(q, i)) {
- DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
- i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
- if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
- next = i;
- priority = IPVP_PRIORITY(opp->src[i].ipvp);
- }
- }
- }
- q->next = next;
- q->priority = priority;
-}
-
-static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
-{
- if (q->next == -1) {
- /* XXX: optimize */
- IRQ_check(opp, q);
- }
-
- return q->next;
-}
-
-static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
-{
- IRQ_dst_t *dst;
- IRQ_src_t *src;
- int priority;
-
- dst = &opp->dst[n_CPU];
- src = &opp->src[n_IRQ];
- priority = IPVP_PRIORITY(src->ipvp);
- if (priority <= dst->pctp) {
- /* Too low priority */
- return;
- }
- if (IRQ_testbit(&dst->raised, n_IRQ)) {
- /* Interrupt miss */
- return;
- }
- set_bit(&src->ipvp, IPVP_ACTIVITY);
- IRQ_setbit(&dst->raised, n_IRQ);
- if (priority > dst->raised.priority) {
- IRQ_get_next(opp, &dst->raised);
- DPRINTF("Raise CPU IRQ\n");
- cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
- }
-}
-
-/* update pic state because registers for n_IRQ have changed value */
-static void openpic_update_irq(openpic_t *opp, int n_IRQ)
-{
- IRQ_src_t *src;
- int i;
-
- src = &opp->src[n_IRQ];
-
- if (!src->pending) {
- /* no irq pending */
- return;
- }
- if (test_bit(&src->ipvp, IPVP_MASK)) {
- /* Interrupt source is disabled */
- return;
- }
- if (IPVP_PRIORITY(src->ipvp) == 0) {
- /* Priority set to zero */
- return;
- }
- if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
- /* IRQ already active */
- return;
- }
- if (src->ide == 0x00000000) {
- /* No target */
- return;
- }
-
- if (!test_bit(&src->ipvp, IPVP_MODE) ||
- src->ide == (1 << src->last_cpu)) {
- /* Directed delivery mode */
- for (i = 0; i < opp->nb_cpus; i++) {
- if (test_bit(&src->ide, i))
- IRQ_local_pipe(opp, i, n_IRQ);
- }
- } else {
- /* Distributed delivery mode */
- /* XXX: incorrect code */
- for (i = src->last_cpu; i < src->last_cpu; i++) {
- if (i == MAX_IRQ)
- i = 0;
- if (test_bit(&src->ide, i)) {
- IRQ_local_pipe(opp, i, n_IRQ);
- src->last_cpu = i;
- break;
- }
- }
- }
-}
-
-void openpic_set_irq(void *opaque, int n_IRQ, int level)
-{
- openpic_t *opp = opaque;
- IRQ_src_t *src;
-
- src = &opp->src[n_IRQ];
- DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
- n_IRQ, level, src->ipvp);
- if (test_bit(&src->ipvp, IPVP_SENSE)) {
- /* level-sensitive irq */
- src->pending = level;
- if (!level)
- reset_bit(&src->ipvp, IPVP_ACTIVITY);
- } else {
- /* edge-sensitive irq */
- if (level)
- src->pending = 1;
- }
- openpic_update_irq(opp, n_IRQ);
-}
-
-static void openpic_reset (openpic_t *opp)
-{
- int i;
-
- opp->glbc = 0x80000000;
- /* Initialise controller registers */
- opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
- opp->veni = VENI;
- opp->spve = 0x000000FF;
- opp->tifr = 0x003F7A00;
- /* ? */
- opp->micr = 0x00000000;
- /* Initialise IRQ sources */
- for (i = 0; i < MAX_IRQ; i++) {
- opp->src[i].ipvp = 0xA0000000;
- opp->src[i].ide = 0x00000000;
- }
- /* Initialise IRQ destinations */
- for (i = 0; i < opp->nb_cpus; i++) {
- opp->dst[i].pctp = 0x0000000F;
- opp->dst[i].pcsr = 0x00000000;
- memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
- memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
- }
- /* Initialise timers */
- for (i = 0; i < MAX_TMR; i++) {
- opp->timers[i].ticc = 0x00000000;
- opp->timers[i].tibc = 0x80000000;
- }
- /* Initialise doorbells */
-#if MAX_DBL > 0
- opp->dar = 0x00000000;
- for (i = 0; i < MAX_DBL; i++) {
- opp->doorbells[i].dmr = 0x00000000;
- }
-#endif
- /* Initialise mailboxes */
-#if MAX_MBX > 0
- for (i = 0; i < MAX_MBX; i++) { /* ? */
- opp->mailboxes[i].mbr = 0x00000000;
- }
-#endif
- /* Go out of RESET state */
- opp->glbc = 0x00000000;
-}
-
-static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
-{
- uint32_t retval;
-
- switch (reg) {
- case IRQ_IPVP:
- retval = opp->src[n_IRQ].ipvp;
- break;
- case IRQ_IDE:
- retval = opp->src[n_IRQ].ide;
- break;
- }
-
- return retval;
-}
-
-static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
- uint32_t reg, uint32_t val)
-{
- uint32_t tmp;
-
- switch (reg) {
- case IRQ_IPVP:
- /* NOTE: not fully accurate for special IRQs, but simple and
- sufficient */
- /* ACTIVITY bit is read-only */
- opp->src[n_IRQ].ipvp =
- (opp->src[n_IRQ].ipvp & 0x40000000) |
- (val & 0x800F00FF);
- openpic_update_irq(opp, n_IRQ);
- DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
- n_IRQ, val, opp->src[n_IRQ].ipvp);
- break;
- case IRQ_IDE:
- tmp = val & 0xC0000000;
- tmp |= val & ((1 << MAX_CPU) - 1);
- opp->src[n_IRQ].ide = tmp;
- DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
- break;
- }
-}
-
-#if 0 // Code provision for Intel model
-#if MAX_DBL > 0
-static uint32_t read_doorbell_register (openpic_t *opp,
- int n_dbl, uint32_t offset)
-{
- uint32_t retval;
-
- switch (offset) {
- case DBL_IPVP_OFFSET:
- retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
- break;
- case DBL_IDE_OFFSET:
- retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
- break;
- case DBL_DMR_OFFSET:
- retval = opp->doorbells[n_dbl].dmr;
- break;
- }
-
- return retval;
-}
-
-static void write_doorbell_register (penpic_t *opp, int n_dbl,
- uint32_t offset, uint32_t value)
-{
- switch (offset) {
- case DBL_IVPR_OFFSET:
- write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
- break;
- case DBL_IDE_OFFSET:
- write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
- break;
- case DBL_DMR_OFFSET:
- opp->doorbells[n_dbl].dmr = value;
- break;
- }
-}
-#endif
-
-#if MAX_MBX > 0
-static uint32_t read_mailbox_register (openpic_t *opp,
- int n_mbx, uint32_t offset)
-{
- uint32_t retval;
-
- switch (offset) {
- case MBX_MBR_OFFSET:
- retval = opp->mailboxes[n_mbx].mbr;
- break;
- case MBX_IVPR_OFFSET:
- retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
- break;
- case MBX_DMR_OFFSET:
- retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
- break;
- }
-
- return retval;
-}
-
-static void write_mailbox_register (openpic_t *opp, int n_mbx,
- uint32_t address, uint32_t value)
-{
- switch (offset) {
- case MBX_MBR_OFFSET:
- opp->mailboxes[n_mbx].mbr = value;
- break;
- case MBX_IVPR_OFFSET:
- write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
- break;
- case MBX_DMR_OFFSET:
- write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
- break;
- }
-}
-#endif
-#endif /* 0 : Code provision for Intel model */
-
-static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
-{
- openpic_t *opp = opaque;
-
- DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
-#if defined OPENPIC_SWAP
- val = bswap32(val);
-#endif
- addr &= 0xFF;
- switch (addr) {
- case 0x00: /* FREP */
- break;
- case 0x20: /* GLBC */
- if (val & 0x80000000)
- openpic_reset(opp);
- opp->glbc = val & ~0x80000000;
- break;
- case 0x80: /* VENI */
- break;
- case 0x90: /* PINT */
- /* XXX: Should be able to reset any CPU */
- if (val & 1) {
- DPRINTF("Reset CPU IRQ\n");
- // cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET);
- }
- break;
-#if MAX_IPI > 0
- case 0xA0: /* IPI_IPVP */
- case 0xB0:
- case 0xC0:
- case 0xD0:
- {
- int idx;
- idx = (addr - 0xA0) >> 4;
- write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
- }
- break;
-#endif
- case 0xE0: /* SPVE */
- opp->spve = val & 0x000000FF;
- break;
- case 0xF0: /* TIFR */
- opp->tifr = val;
- break;
- default:
- break;
- }
-}
-
-static uint32_t openpic_gbl_read (void *opaque, uint32_t addr)
-{
- openpic_t *opp = opaque;
- uint32_t retval;
-
- DPRINTF("%s: addr %08x\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
- addr &= 0xFF;
- switch (addr) {
- case 0x00: /* FREP */
- retval = opp->frep;
- break;
- case 0x20: /* GLBC */
- retval = opp->glbc;
- break;
- case 0x80: /* VENI */
- retval = opp->veni;
- break;
- case 0x90: /* PINT */
- retval = 0x00000000;
- break;
-#if MAX_IPI > 0
- case 0xA0: /* IPI_IPVP */
- case 0xB0:
- case 0xC0:
- case 0xD0:
- {
- int idx;
- idx = (addr - 0xA0) >> 4;
- retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
- }
- break;
-#endif
- case 0xE0: /* SPVE */
- retval = opp->spve;
- break;
- case 0xF0: /* TIFR */
- retval = opp->tifr;
- break;
- default:
- break;
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval = bswap32(retval);
-#endif
-
- return retval;
-}
-
-static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
-{
- openpic_t *opp = opaque;
- int idx;
-
- DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
-#if defined OPENPIC_SWAP
- val = bswap32(val);
-#endif
- addr -= 0x1100;
- addr &= 0xFFFF;
- idx = (addr & 0xFFF0) >> 6;
- addr = addr & 0x30;
- switch (addr) {
- case 0x00: /* TICC */
- break;
- case 0x10: /* TIBC */
- if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
- (val & 0x80000000) == 0 &&
- (opp->timers[idx].tibc & 0x80000000) != 0)
- opp->timers[idx].ticc &= ~0x80000000;
- opp->timers[idx].tibc = val;
- break;
- case 0x20: /* TIVP */
- write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
- break;
- case 0x30: /* TIDE */
- write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
- break;
- }
-}
-
-static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
-{
- openpic_t *opp = opaque;
- uint32_t retval;
- int idx;
-
- DPRINTF("%s: addr %08x\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
- addr -= 0x1100;
- addr &= 0xFFFF;
- idx = (addr & 0xFFF0) >> 6;
- addr = addr & 0x30;
- switch (addr) {
- case 0x00: /* TICC */
- retval = opp->timers[idx].ticc;
- break;
- case 0x10: /* TIBC */
- retval = opp->timers[idx].tibc;
- break;
- case 0x20: /* TIPV */
- retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
- break;
- case 0x30: /* TIDE */
- retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
- break;
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval = bswap32(retval);
-#endif
-
- return retval;
-}
-
-static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
-{
- openpic_t *opp = opaque;
- int idx;
-
- DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
-#if defined OPENPIC_SWAP
- val = tswap32(val);
-#endif
- addr = addr & 0xFFF0;
- idx = addr >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- write_IRQreg(opp, idx, IRQ_IDE, val);
- } else {
- /* EXVP / IFEVP / IEEVP */
- write_IRQreg(opp, idx, IRQ_IPVP, val);
- }
-}
-
-static uint32_t openpic_src_read (void *opaque, uint32_t addr)
-{
- openpic_t *opp = opaque;
- uint32_t retval;
- int idx;
-
- DPRINTF("%s: addr %08x\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
- addr = addr & 0xFFF0;
- idx = addr >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- retval = read_IRQreg(opp, idx, IRQ_IDE);
- } else {
- /* EXVP / IFEVP / IEEVP */
- retval = read_IRQreg(opp, idx, IRQ_IPVP);
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval = tswap32(retval);
-#endif
-
- return retval;
-}
-
-static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
-{
- openpic_t *opp = opaque;
- IRQ_src_t *src;
- IRQ_dst_t *dst;
- int idx, n_IRQ;
-
- DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
-#if defined OPENPIC_SWAP
- val = bswap32(val);
-#endif
- addr &= 0x1FFF0;
- idx = addr / 0x1000;
- dst = &opp->dst[idx];
- addr &= 0xFF0;
- switch (addr) {
-#if MAX_IPI > 0
- case 0x40: /* PIPD */
- case 0x50:
- case 0x60:
- case 0x70:
- idx = (addr - 0x40) >> 4;
- write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
- openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
- openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
- break;
-#endif
- case 0x80: /* PCTP */
- dst->pctp = val & 0x0000000F;
- break;
- case 0x90: /* WHOAMI */
- /* Read-only register */
- break;
- case 0xA0: /* PIAC */
- /* Read-only register */
- break;
- case 0xB0: /* PEOI */
- DPRINTF("PEOI\n");
- n_IRQ = IRQ_get_next(opp, &dst->servicing);
- IRQ_resetbit(&dst->servicing, n_IRQ);
- dst->servicing.next = -1;
- src = &opp->src[n_IRQ];
- /* Set up next servicing IRQ */
- IRQ_get_next(opp, &dst->servicing);
- /* Check queued interrupts. */
- n_IRQ = IRQ_get_next(opp, &dst->raised);
- if (n_IRQ != -1) {
- src = &opp->src[n_IRQ];
- if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) {
- DPRINTF("Raise CPU IRQ\n");
- cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
- }
- }
- break;
- default:
- break;
- }
-}
-
-static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
-{
- openpic_t *opp = opaque;
- IRQ_src_t *src;
- IRQ_dst_t *dst;
- uint32_t retval;
- int idx, n_IRQ;
-
- DPRINTF("%s: addr %08x\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
- addr &= 0x1FFF0;
- idx = addr / 0x1000;
- dst = &opp->dst[idx];
- addr &= 0xFF0;
- switch (addr) {
- case 0x80: /* PCTP */
- retval = dst->pctp;
- break;
- case 0x90: /* WHOAMI */
- retval = idx;
- break;
- case 0xA0: /* PIAC */
- n_IRQ = IRQ_get_next(opp, &dst->raised);
- DPRINTF("PIAC: irq=%d\n", n_IRQ);
- if (n_IRQ == -1) {
- /* No more interrupt pending */
- retval = opp->spve;
- } else {
- src = &opp->src[n_IRQ];
- if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
- !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
- /* - Spurious level-sensitive IRQ
- * - Priorities has been changed
- * and the pending IRQ isn't allowed anymore
- */
- reset_bit(&src->ipvp, IPVP_ACTIVITY);
- retval = IPVP_VECTOR(opp->spve);
- } else {
- /* IRQ enter servicing state */
- IRQ_setbit(&dst->servicing, n_IRQ);
- retval = IPVP_VECTOR(src->ipvp);
- }
- IRQ_resetbit(&dst->raised, n_IRQ);
- dst->raised.next = -1;
- if (!test_bit(&src->ipvp, IPVP_SENSE)) {
- /* edge-sensitive IRQ */
- reset_bit(&src->ipvp, IPVP_ACTIVITY);
- src->pending = 0;
- }
- }
- break;
- case 0xB0: /* PEOI */
- retval = 0;
- break;
-#if MAX_IPI > 0
- case 0x40: /* IDE */
- case 0x50:
- idx = (addr - 0x40) >> 4;
- retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
- break;
-#endif
- default:
- break;
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
-#if defined OPENPIC_SWAP
- retval= bswap32(retval);
-#endif
-
- return retval;
-}
-
-static void openpic_buggy_write (void *opaque,
- target_phys_addr_t addr, uint32_t val)
-{
- printf("Invalid OPENPIC write access !\n");
-}
-
-static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
-{
- printf("Invalid OPENPIC read access !\n");
-
- return -1;
-}
-
-static void openpic_writel (void *opaque,
- target_phys_addr_t addr, uint32_t val)
-{
- openpic_t *opp = opaque;
-
- addr &= 0x3FFFF;
- DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
- if (addr < 0x1100) {
- /* Global registers */
- openpic_gbl_write(opp, addr, val);
- } else if (addr < 0x10000) {
- /* Timers registers */
- openpic_timer_write(opp, addr, val);
- } else if (addr < 0x20000) {
- /* Source registers */
- openpic_src_write(opp, addr, val);
- } else {
- /* CPU registers */
- openpic_cpu_write(opp, addr, val);
- }
-}
-
-static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
-{
- openpic_t *opp = opaque;
- uint32_t retval;
-
- addr &= 0x3FFFF;
- DPRINTF("%s: offset %08x\n", __func__, (int)addr);
- if (addr < 0x1100) {
- /* Global registers */
- retval = openpic_gbl_read(opp, addr);
- } else if (addr < 0x10000) {
- /* Timers registers */
- retval = openpic_timer_read(opp, addr);
- } else if (addr < 0x20000) {
- /* Source registers */
- retval = openpic_src_read(opp, addr);
- } else {
- /* CPU registers */
- retval = openpic_cpu_read(opp, addr);
- }
-
- return retval;
-}
-
-static CPUWriteMemoryFunc *openpic_write[] = {
- &openpic_buggy_write,
- &openpic_buggy_write,
- &openpic_writel,
-};
-
-static CPUReadMemoryFunc *openpic_read[] = {
- &openpic_buggy_read,
- &openpic_buggy_read,
- &openpic_readl,
-};
-
-static void openpic_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- openpic_t *opp;
-
- DPRINTF("Map OpenPIC\n");
- opp = (openpic_t *)pci_dev;
- /* Global registers */
- DPRINTF("Register OPENPIC gbl %08x => %08x\n",
- addr + 0x1000, addr + 0x1000 + 0x100);
- /* Timer registers */
- DPRINTF("Register OPENPIC timer %08x => %08x\n",
- addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
- /* Interrupt source registers */
- DPRINTF("Register OPENPIC src %08x => %08x\n",
- addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
- /* Per CPU registers */
- DPRINTF("Register OPENPIC dst %08x => %08x\n",
- addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
- cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
-#if 0 // Don't implement ISU for now
- opp_io_memory = cpu_register_io_memory(0, openpic_src_read,
- openpic_src_write);
- cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
- opp_io_memory);
-#endif
-}
-
-openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
- CPUPPCState **envp)
-{
- openpic_t *opp;
- uint8_t *pci_conf;
- int i, m;
-
- /* XXX: for now, only one CPU is supported */
- if (nb_cpus != 1)
- return NULL;
- if (bus) {
- opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
- -1, NULL, NULL);
- if (opp == NULL)
- return NULL;
- pci_conf = opp->pci_dev.config;
- pci_conf[0x00] = 0x14; // IBM MPIC2
- pci_conf[0x01] = 0x10;
- pci_conf[0x02] = 0xFF;
- pci_conf[0x03] = 0xFF;
- pci_conf[0x0a] = 0x80; // PIC
- pci_conf[0x0b] = 0x08;
- pci_conf[0x0e] = 0x00; // header_type
- pci_conf[0x3d] = 0x00; // no interrupt pin
-
- /* Register I/O spaces */
- pci_register_io_region((PCIDevice *)opp, 0, 0x40000,
- PCI_ADDRESS_SPACE_MEM, &openpic_map);
- } else {
- opp = qemu_mallocz(sizeof(openpic_t));
- }
-
- opp->mem_index = cpu_register_io_memory(0, openpic_read,
- openpic_write, opp);
-
- // isu_base &= 0xFFFC0000;
- opp->nb_cpus = nb_cpus;
- /* Set IRQ types */
- for (i = 0; i < EXT_IRQ; i++) {
- opp->src[i].type = IRQ_EXTERNAL;
- }
- for (; i < IRQ_TIM0; i++) {
- opp->src[i].type = IRQ_SPECIAL;
- }
-#if MAX_IPI > 0
- m = IRQ_IPI0;
-#else
- m = IRQ_DBL0;
-#endif
- for (; i < m; i++) {
- opp->src[i].type = IRQ_TIMER;
- }
- for (; i < MAX_IRQ; i++) {
- opp->src[i].type = IRQ_INTERNAL;
- }
- for (i = 0; i < nb_cpus; i++)
- opp->dst[i].env = envp[i];
- openpic_reset(opp);
- if (pmem_index)
- *pmem_index = opp->mem_index;
- return opp;
-}
diff --git a/hw/parallel.c b/hw/parallel.c
deleted file mode 100644
index cba9561..0000000
--- a/hw/parallel.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * QEMU Parallel PORT emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define DEBUG_PARALLEL
-
-/*
- * These are the definitions for the Printer Status Register
- */
-#define PARA_STS_BUSY 0x80 /* Busy complement */
-#define PARA_STS_ACK 0x40 /* Acknowledge */
-#define PARA_STS_PAPER 0x20 /* Out of paper */
-#define PARA_STS_ONLINE 0x10 /* Online */
-#define PARA_STS_ERROR 0x08 /* Error complement */
-
-/*
- * These are the definitions for the Printer Control Register
- */
-#define PARA_CTR_INTEN 0x10 /* IRQ Enable */
-#define PARA_CTR_SELECT 0x08 /* Select In complement */
-#define PARA_CTR_INIT 0x04 /* Initialize Printer complement */
-#define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */
-#define PARA_CTR_STROBE 0x01 /* Strobe complement */
-
-struct ParallelState {
- uint8_t data;
- uint8_t status; /* read only register */
- uint8_t control;
- int irq;
- int irq_pending;
- CharDriverState *chr;
- int hw_driver;
-};
-
-static void parallel_update_irq(ParallelState *s)
-{
- if (s->irq_pending)
- pic_set_irq(s->irq, 1);
- else
- pic_set_irq(s->irq, 0);
-}
-
-static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- ParallelState *s = opaque;
-
- addr &= 7;
-#ifdef DEBUG_PARALLEL
- printf("parallel: write addr=0x%02x val=0x%02x\n", addr, val);
-#endif
- switch(addr) {
- case 0:
- if (s->hw_driver) {
- s->data = val;
- qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &s->data);
- } else {
- s->data = val;
- parallel_update_irq(s);
- }
- break;
- case 2:
- if (s->hw_driver) {
- s->control = val;
- qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &s->control);
- } else {
- if ((val & PARA_CTR_INIT) == 0 ) {
- s->status = PARA_STS_BUSY;
- s->status |= PARA_STS_ACK;
- s->status |= PARA_STS_ONLINE;
- s->status |= PARA_STS_ERROR;
- }
- else if (val & PARA_CTR_SELECT) {
- if (val & PARA_CTR_STROBE) {
- s->status &= ~PARA_STS_BUSY;
- if ((s->control & PARA_CTR_STROBE) == 0)
- qemu_chr_write(s->chr, &s->data, 1);
- } else {
- if (s->control & PARA_CTR_INTEN) {
- s->irq_pending = 1;
- }
- }
- }
- parallel_update_irq(s);
- s->control = val;
- }
- break;
- }
-}
-
-static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
-{
- ParallelState *s = opaque;
- uint32_t ret = 0xff;
-
- addr &= 7;
- switch(addr) {
- case 0:
- if (s->hw_driver) {
- qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &s->data);
- }
- ret = s->data;
- break;
- case 1:
- if (s->hw_driver) {
- qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &s->status);
- ret = s->status;
- } else {
- ret = s->status;
- s->irq_pending = 0;
- if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
- /* XXX Fixme: wait 5 microseconds */
- if (s->status & PARA_STS_ACK)
- s->status &= ~PARA_STS_ACK;
- else {
- /* XXX Fixme: wait 5 microseconds */
- s->status |= PARA_STS_ACK;
- s->status |= PARA_STS_BUSY;
- }
- }
- parallel_update_irq(s);
- }
- break;
- case 2:
- if (s->hw_driver) {
- qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &s->control);
- }
- ret = s->control;
- break;
- }
-#ifdef DEBUG_PARALLEL
- printf("parallel: read addr=0x%02x val=0x%02x\n", addr, ret);
-#endif
- return ret;
-}
-
-/* If fd is zero, it means that the parallel device uses the console */
-ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
-{
- ParallelState *s;
- uint8_t dummy;
-
- s = qemu_mallocz(sizeof(ParallelState));
- if (!s)
- return NULL;
- s->chr = chr;
- s->hw_driver = 0;
- if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0)
- s->hw_driver = 1;
-
- s->irq = irq;
- s->data = 0;
- s->status = PARA_STS_BUSY;
- s->status |= PARA_STS_ACK;
- s->status |= PARA_STS_ONLINE;
- s->status |= PARA_STS_ERROR;
- s->control = PARA_CTR_SELECT;
- s->control |= PARA_CTR_INIT;
-
- register_ioport_write(base, 8, 1, parallel_ioport_write, s);
- register_ioport_read(base, 8, 1, parallel_ioport_read, s);
- return s;
-}
diff --git a/hw/pc.c b/hw/pc.c
deleted file mode 100644
index 898d068..0000000
--- a/hw/pc.c
+++ /dev/null
@@ -1,911 +0,0 @@
-/*
- * QEMU PC System Emulator
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* output Bochs bios info messages */
-//#define DEBUG_BIOS
-
-#define BIOS_FILENAME "bios.bin"
-#define VGABIOS_FILENAME "vgabios.bin"
-#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
-#define LINUX_BOOT_FILENAME "linux_boot.bin"
-
-#define KERNEL_LOAD_ADDR 0x00100000
-#define INITRD_LOAD_ADDR 0x00600000
-#define KERNEL_PARAMS_ADDR 0x00090000
-#define KERNEL_CMDLINE_ADDR 0x00099000
-
-static fdctrl_t *floppy_controller;
-static RTCState *rtc_state;
-static PITState *pit;
-static IOAPICState *ioapic;
-
-static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
-{
-}
-
-/* MSDOS compatibility mode FPU exception support */
-/* XXX: add IGNNE support */
-void cpu_set_ferr(CPUX86State *s)
-{
- pic_set_irq(13, 1);
-}
-
-static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
-{
- pic_set_irq(13, 0);
-}
-
-/* TSC handling */
-uint64_t cpu_get_tsc(CPUX86State *env)
-{
- /* Note: when using kqemu, it is more logical to return the host TSC
- because kqemu does not trap the RDTSC instruction for
- performance reasons */
-#if USE_KQEMU
- if (env->kqemu_enabled) {
- return cpu_get_real_ticks();
- } else
-#endif
- {
- return cpu_get_ticks();
- }
-}
-
-/* IRQ handling */
-int cpu_get_pic_interrupt(CPUState *env)
-{
- int intno;
-
- intno = apic_get_interrupt(env);
- if (intno >= 0) {
- /* set irq request if a PIC irq is still pending */
- /* XXX: improve that */
- pic_update_irq(isa_pic);
- return intno;
- }
- /* read the irq from the PIC */
- intno = pic_read_irq(isa_pic);
- return intno;
-}
-
-static void pic_irq_request(void *opaque, int level)
-{
- CPUState *env = opaque;
- if (level)
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- else
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-}
-
-/* PC cmos mappings */
-
-#define REG_EQUIPMENT_BYTE 0x14
-#define REG_IBM_CENTURY_BYTE 0x32
-#define REG_IBM_PS2_CENTURY_BYTE 0x37
-
-
-static inline int to_bcd(RTCState *s, int a)
-{
- return ((a / 10) << 4) | (a % 10);
-}
-
-static int cmos_get_fd_drive_type(int fd0)
-{
- int val;
-
- switch (fd0) {
- case 0:
- /* 1.44 Mb 3"5 drive */
- val = 4;
- break;
- case 1:
- /* 2.88 Mb 3"5 drive */
- val = 5;
- break;
- case 2:
- /* 1.2 Mb 5"5 drive */
- val = 2;
- break;
- default:
- val = 0;
- break;
- }
- return val;
-}
-
-static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
-{
- RTCState *s = rtc_state;
- int cylinders, heads, sectors;
- bdrv_get_geometry_hint(hd, &cylinders, &heads, &sectors);
- rtc_set_memory(s, type_ofs, 47);
- rtc_set_memory(s, info_ofs, cylinders);
- rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
- rtc_set_memory(s, info_ofs + 2, heads);
- rtc_set_memory(s, info_ofs + 3, 0xff);
- rtc_set_memory(s, info_ofs + 4, 0xff);
- rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
- rtc_set_memory(s, info_ofs + 6, cylinders);
- rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
- rtc_set_memory(s, info_ofs + 8, sectors);
-}
-
-/* hd_table must contain 4 block drivers */
-static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
-{
- RTCState *s = rtc_state;
- int val;
- int fd0, fd1, nb;
- time_t ti;
- struct tm *tm;
- int i;
-
- /* set the CMOS date */
- time(&ti);
- if (rtc_utc)
- tm = gmtime(&ti);
- else
- tm = localtime(&ti);
- rtc_set_date(s, tm);
-
- val = to_bcd(s, (tm->tm_year / 100) + 19);
- rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
- rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
-
- /* various important CMOS locations needed by PC/Bochs bios */
-
- /* memory size */
- val = 640; /* base memory in K */
- rtc_set_memory(s, 0x15, val);
- rtc_set_memory(s, 0x16, val >> 8);
-
- val = (ram_size / 1024) - 1024;
- if (val > 65535)
- val = 65535;
- rtc_set_memory(s, 0x17, val);
- rtc_set_memory(s, 0x18, val >> 8);
- rtc_set_memory(s, 0x30, val);
- rtc_set_memory(s, 0x31, val >> 8);
-
- if (ram_size > (16 * 1024 * 1024))
- val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
- else
- val = 0;
- if (val > 65535)
- val = 65535;
- rtc_set_memory(s, 0x34, val);
- rtc_set_memory(s, 0x35, val >> 8);
-
- switch(boot_device) {
- case 'a':
- case 'b':
- rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
- if (!fd_bootchk)
- rtc_set_memory(s, 0x38, 0x01); /* disable signature check */
- break;
- default:
- case 'c':
- rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
- break;
- case 'd':
- rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
- break;
- }
-
- /* floppy type */
-
- fd0 = fdctrl_get_drive_type(floppy_controller, 0);
- fd1 = fdctrl_get_drive_type(floppy_controller, 1);
-
- val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
- rtc_set_memory(s, 0x10, val);
-
- val = 0;
- nb = 0;
- if (fd0 < 3)
- nb++;
- if (fd1 < 3)
- nb++;
- switch (nb) {
- case 0:
- break;
- case 1:
- val |= 0x01; /* 1 drive, ready for boot */
- break;
- case 2:
- val |= 0x41; /* 2 drives, ready for boot */
- break;
- }
- val |= 0x02; /* FPU is there */
- val |= 0x04; /* PS/2 mouse installed */
- rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
-
- /* hard drives */
-
- rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
- if (hd_table[0])
- cmos_init_hd(0x19, 0x1b, hd_table[0]);
- if (hd_table[1])
- cmos_init_hd(0x1a, 0x24, hd_table[1]);
-
- val = 0;
- for (i = 0; i < 4; i++) {
- if (hd_table[i]) {
- int cylinders, heads, sectors, translation;
- /* NOTE: bdrv_get_geometry_hint() returns the physical
- geometry. It is always such that: 1 <= sects <= 63, 1
- <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
- geometry can be different if a translation is done. */
- translation = bdrv_get_translation_hint(hd_table[i]);
- if (translation == BIOS_ATA_TRANSLATION_AUTO) {
- bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);
- if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
- /* No translation. */
- translation = 0;
- } else {
- /* LBA translation. */
- translation = 1;
- }
- } else {
- translation--;
- }
- val |= translation << (i * 2);
- }
- }
- rtc_set_memory(s, 0x39, val);
-}
-
-void ioport_set_a20(int enable)
-{
- /* XXX: send to all CPUs ? */
- cpu_x86_set_a20(first_cpu, enable);
-}
-
-int ioport_get_a20(void)
-{
- return ((first_cpu->a20_mask >> 20) & 1);
-}
-
-static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
-{
- ioport_set_a20((val >> 1) & 1);
- /* XXX: bit 0 is fast reset */
-}
-
-static uint32_t ioport92_read(void *opaque, uint32_t addr)
-{
- return ioport_get_a20() << 1;
-}
-
-/***********************************************************/
-/* Bochs BIOS debug ports */
-
-void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
-{
- static const char shutdown_str[8] = "Shutdown";
- static int shutdown_index = 0;
-
- switch(addr) {
- /* Bochs BIOS messages */
- case 0x400:
- case 0x401:
- fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
- exit(1);
- case 0x402:
- case 0x403:
-#ifdef DEBUG_BIOS
- fprintf(stderr, "%c", val);
-#endif
- break;
- case 0x8900:
- /* same as Bochs power off */
- if (val == shutdown_str[shutdown_index]) {
- shutdown_index++;
- if (shutdown_index == 8) {
- shutdown_index = 0;
- qemu_system_shutdown_request();
- }
- } else {
- shutdown_index = 0;
- }
- break;
-
- /* LGPL'ed VGA BIOS messages */
- case 0x501:
- case 0x502:
- fprintf(stderr, "VGA BIOS panic, line %d\n", val);
- exit(1);
- case 0x500:
- case 0x503:
-#ifdef DEBUG_BIOS
- fprintf(stderr, "%c", val);
-#endif
- break;
- }
-}
-
-void bochs_bios_init(void)
-{
- 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(0x8900, 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);
-}
-
-
-int load_kernel(const char *filename, uint8_t *addr,
- uint8_t *real_addr)
-{
- int fd, size;
- int setup_sects;
-
- fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0)
- return -1;
-
- /* load 16 bit code */
- if (read(fd, real_addr, 512) != 512)
- goto fail;
- setup_sects = real_addr[0x1F1];
- if (!setup_sects)
- setup_sects = 4;
- if (read(fd, real_addr + 512, setup_sects * 512) !=
- setup_sects * 512)
- goto fail;
-
- /* load 32 bit code */
- size = read(fd, addr, 16 * 1024 * 1024);
- if (size < 0)
- goto fail;
- close(fd);
- return size;
- fail:
- close(fd);
- return -1;
-}
-
-static void main_cpu_reset(void *opaque)
-{
- CPUState *env = opaque;
- cpu_reset(env);
-}
-
-/*************************************************/
-
-static void putb(uint8_t **pp, int val)
-{
- uint8_t *q;
- q = *pp;
- *q++ = val;
- *pp = q;
-}
-
-static void putstr(uint8_t **pp, const char *str)
-{
- uint8_t *q;
- q = *pp;
- while (*str)
- *q++ = *str++;
- *pp = q;
-}
-
-static void putle16(uint8_t **pp, int val)
-{
- uint8_t *q;
- q = *pp;
- *q++ = val;
- *q++ = val >> 8;
- *pp = q;
-}
-
-static void putle32(uint8_t **pp, int val)
-{
- uint8_t *q;
- q = *pp;
- *q++ = val;
- *q++ = val >> 8;
- *q++ = val >> 16;
- *q++ = val >> 24;
- *pp = q;
-}
-
-static int mpf_checksum(const uint8_t *data, int len)
-{
- int sum, i;
- sum = 0;
- for(i = 0; i < len; i++)
- sum += data[i];
- return sum & 0xff;
-}
-
-/* Build the Multi Processor table in the BIOS. Same values as Bochs. */
-static void bios_add_mptable(uint8_t *bios_data)
-{
- uint8_t *mp_config_table, *q, *float_pointer_struct;
- int ioapic_id, offset, i, len;
-
- if (smp_cpus <= 1)
- return;
-
- mp_config_table = bios_data + 0xb000;
- q = mp_config_table;
- putstr(&q, "PCMP"); /* "PCMP signature */
- putle16(&q, 0); /* table length (patched later) */
- putb(&q, 4); /* spec rev */
- putb(&q, 0); /* checksum (patched later) */
- putstr(&q, "QEMUCPU "); /* OEM id */
- putstr(&q, "0.1 "); /* vendor id */
- putle32(&q, 0); /* OEM table ptr */
- putle16(&q, 0); /* OEM table size */
- putle16(&q, 20); /* entry count */
- putle32(&q, 0xfee00000); /* local APIC addr */
- putle16(&q, 0); /* ext table length */
- putb(&q, 0); /* ext table checksum */
- putb(&q, 0); /* reserved */
-
- for(i = 0; i < smp_cpus; i++) {
- putb(&q, 0); /* entry type = processor */
- putb(&q, i); /* APIC id */
- putb(&q, 0x11); /* local APIC version number */
- if (i == 0)
- putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
- else
- putb(&q, 1); /* cpu flags: enabled */
- putb(&q, 0); /* cpu signature */
- putb(&q, 6);
- putb(&q, 0);
- putb(&q, 0);
- putle16(&q, 0x201); /* feature flags */
- putle16(&q, 0);
-
- putle16(&q, 0); /* reserved */
- putle16(&q, 0);
- putle16(&q, 0);
- putle16(&q, 0);
- }
-
- /* isa bus */
- putb(&q, 1); /* entry type = bus */
- putb(&q, 0); /* bus ID */
- putstr(&q, "ISA ");
-
- /* ioapic */
- ioapic_id = smp_cpus;
- putb(&q, 2); /* entry type = I/O APIC */
- putb(&q, ioapic_id); /* apic ID */
- putb(&q, 0x11); /* I/O APIC version number */
- putb(&q, 1); /* enable */
- putle32(&q, 0xfec00000); /* I/O APIC addr */
-
- /* irqs */
- for(i = 0; i < 16; i++) {
- putb(&q, 3); /* entry type = I/O interrupt */
- putb(&q, 0); /* interrupt type = vectored interrupt */
- putb(&q, 0); /* flags: po=0, el=0 */
- putb(&q, 0);
- putb(&q, 0); /* source bus ID = ISA */
- putb(&q, i); /* source bus IRQ */
- putb(&q, ioapic_id); /* dest I/O APIC ID */
- putb(&q, i); /* dest I/O APIC interrupt in */
- }
- /* patch length */
- len = q - mp_config_table;
- mp_config_table[4] = len;
- mp_config_table[5] = len >> 8;
-
- mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
-
- /* align to 16 */
- offset = q - bios_data;
- offset = (offset + 15) & ~15;
- float_pointer_struct = bios_data + offset;
-
- /* floating pointer structure */
- q = float_pointer_struct;
- putstr(&q, "_MP_");
- /* pointer to MP config table */
- putle32(&q, mp_config_table - bios_data + 0x000f0000);
-
- putb(&q, 1); /* length in 16 byte units */
- putb(&q, 4); /* MP spec revision */
- putb(&q, 0); /* checksum (patched later) */
- putb(&q, 0); /* MP feature byte 1 */
-
- putb(&q, 0);
- putb(&q, 0);
- putb(&q, 0);
- putb(&q, 0);
- float_pointer_struct[10] =
- -mpf_checksum(float_pointer_struct, q - float_pointer_struct);
-}
-
-
-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 int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
-static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
-
-static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
-static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
-
-static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
-static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
-
-#ifdef HAS_AUDIO
-static void audio_init (PCIBus *pci_bus)
-{
- struct soundhw *c;
- int audio_enabled = 0;
-
- for (c = soundhw; !audio_enabled && c->name; ++c) {
- audio_enabled = c->enabled;
- }
-
- if (audio_enabled) {
- AudioState *s;
-
- s = AUD_init ();
- if (s) {
- for (c = soundhw; c->name; ++c) {
- if (c->enabled) {
- if (c->isa) {
- c->init.init_isa (s);
- }
- else {
- if (pci_bus) {
- c->init.init_pci (pci_bus, s);
- }
- }
- }
- }
- }
- }
-}
-#endif
-
-static void pc_init_ne2k_isa(NICInfo *nd)
-{
- static int nb_ne2k = 0;
-
- if (nb_ne2k == NE2000_NB_MAX)
- return;
- isa_ne2000_init(ne2000_io[nb_ne2k], ne2000_irq[nb_ne2k], nd);
- nb_ne2k++;
-}
-
-/* PC hardware initialisation */
-static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename,
- int pci_enabled)
-{
- char buf[1024];
- int ret, linux_boot, initrd_size, i;
- unsigned long bios_offset, vga_bios_offset;
- int bios_size, isa_bios_size;
- PCIBus *pci_bus;
- int piix3_devfn = -1;
- CPUState *env;
- NICInfo *nd;
-
- linux_boot = (kernel_filename != NULL);
-
- /* init CPUs */
- for(i = 0; i < smp_cpus; i++) {
- env = cpu_init();
- if (i != 0)
- env->hflags |= HF_HALTED_MASK;
- if (smp_cpus > 1) {
- /* XXX: enable it in all cases */
- env->cpuid_features |= CPUID_APIC;
- }
- register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
- qemu_register_reset(main_cpu_reset, env);
- if (pci_enabled) {
- apic_init(env);
- }
- }
-
- /* allocate RAM */
- cpu_register_physical_memory(0, ram_size, 0);
-
- /* BIOS load */
- bios_offset = ram_size + vga_ram_size;
- vga_bios_offset = bios_offset + 256 * 1024;
-
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
- bios_size = get_image_size(buf);
- if (bios_size <= 0 ||
- (bios_size % 65536) != 0 ||
- bios_size > (256 * 1024)) {
- goto bios_error;
- }
- ret = load_image(buf, phys_ram_base + bios_offset);
- if (ret != bios_size) {
- bios_error:
- fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
- exit(1);
- }
- if (bios_size == 65536) {
- bios_add_mptable(phys_ram_base + bios_offset);
- }
-
- /* VGA BIOS load */
- if (cirrus_vga_enabled) {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
- } else {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
- }
- ret = load_image(buf, phys_ram_base + vga_bios_offset);
-
- /* setup basic memory access */
- cpu_register_physical_memory(0xc0000, 0x10000,
- vga_bios_offset | IO_MEM_ROM);
-
- /* map the last 128KB of the BIOS in ISA space */
- isa_bios_size = bios_size;
- if (isa_bios_size > (128 * 1024))
- isa_bios_size = 128 * 1024;
- cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,
- IO_MEM_UNASSIGNED);
- cpu_register_physical_memory(0x100000 - isa_bios_size,
- isa_bios_size,
- (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
- /* map all the bios at the top of memory */
- cpu_register_physical_memory((uint32_t)(-bios_size),
- bios_size, bios_offset | IO_MEM_ROM);
-
- bochs_bios_init();
-
- if (linux_boot) {
- uint8_t bootsect[512];
- uint8_t old_bootsect[512];
-
- if (bs_table[0] == NULL) {
- fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n");
- exit(1);
- }
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
- ret = load_image(buf, bootsect);
- if (ret != sizeof(bootsect)) {
- fprintf(stderr, "qemu: could not load linux boot sector '%s'\n",
- buf);
- exit(1);
- }
-
- if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) {
- /* copy the MSDOS partition table */
- memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40);
- }
-
- bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
-
- /* now we can load the kernel */
- ret = load_kernel(kernel_filename,
- phys_ram_base + KERNEL_LOAD_ADDR,
- phys_ram_base + KERNEL_PARAMS_ADDR);
- if (ret < 0) {
- fprintf(stderr, "qemu: could not load kernel '%s'\n",
- kernel_filename);
- exit(1);
- }
-
- /* load initrd */
- initrd_size = 0;
- if (initrd_filename) {
- initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
- if (initrd_size < 0) {
- fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- initrd_filename);
- exit(1);
- }
- }
- if (initrd_size > 0) {
- stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
- stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
- }
- pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
- kernel_cmdline);
- stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
- stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
- KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
- /* loader type */
- stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
- }
-
- if (pci_enabled) {
- pci_bus = i440fx_init();
- piix3_devfn = piix3_init(pci_bus);
- } else {
- pci_bus = NULL;
- }
-
- /* init basic PC hardware */
- register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
-
- register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
-
- if (cirrus_vga_enabled) {
- if (pci_enabled) {
- pci_cirrus_vga_init(pci_bus,
- ds, phys_ram_base + ram_size, ram_size,
- vga_ram_size);
- } else {
- isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size,
- vga_ram_size);
- }
- } else {
- vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
- vga_ram_size, 0, 0);
- }
-
- rtc_state = rtc_init(0x70, 8);
-
- register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
- register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
-
- if (pci_enabled) {
- ioapic = ioapic_init();
- }
- isa_pic = pic_init(pic_irq_request, first_cpu);
- pit = pit_init(0x40, 0);
- pcspk_init(pit);
- if (pci_enabled) {
- pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
- }
-
- for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- if (serial_hds[i]) {
- serial_init(&pic_set_irq_new, isa_pic,
- serial_io[i], serial_irq[i], serial_hds[i]);
- }
- }
-
- for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
- if (parallel_hds[i]) {
- parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
- }
- }
-
- for(i = 0; i < nb_nics; i++) {
- nd = &nd_table[i];
- if (!nd->model) {
- if (pci_enabled) {
- nd->model = "ne2k_pci";
- } else {
- nd->model = "ne2k_isa";
- }
- }
- if (strcmp(nd->model, "ne2k_isa") == 0) {
- pc_init_ne2k_isa(nd);
- } else if (pci_enabled) {
- pci_nic_init(pci_bus, nd);
- } else {
- fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
- exit(1);
- }
- }
-
- if (pci_enabled) {
- pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1);
- } else {
- for(i = 0; i < 2; i++) {
- isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
- bs_table[2 * i], bs_table[2 * i + 1]);
- }
- }
-
- kbd_init();
- DMA_init(0);
-#ifdef HAS_AUDIO
- audio_init(pci_enabled ? pci_bus : NULL);
-#endif
-
- floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
-
- cmos_init(ram_size, boot_device, bs_table);
-
- if (pci_enabled && usb_enabled) {
- usb_uhci_init(pci_bus, piix3_devfn + 2);
- }
-
- if (pci_enabled && acpi_enabled) {
- piix4_pm_init(pci_bus, piix3_devfn + 3);
- }
-
-#if 0
- /* ??? Need to figure out some way for the user to
- specify SCSI devices. */
- if (pci_enabled) {
- void *scsi;
- BlockDriverState *bdrv;
-
- scsi = lsi_scsi_init(pci_bus, -1);
- bdrv = bdrv_new("scsidisk");
- bdrv_open(bdrv, "scsi_disk.img", 0);
- lsi_scsi_attach(scsi, bdrv, -1);
- bdrv = bdrv_new("scsicd");
- bdrv_open(bdrv, "scsi_cd.iso", 0);
- bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
- lsi_scsi_attach(scsi, bdrv, -1);
- }
-#endif
- /* must be done after all PCI devices are instanciated */
- /* XXX: should be done in the Bochs BIOS */
- if (pci_enabled) {
- pci_bios_init();
- if (acpi_enabled)
- acpi_bios_init();
- }
-}
-
-static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename)
-{
- pc_init1(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, 1);
-}
-
-static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename)
-{
- pc_init1(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, 0);
-}
-
-QEMUMachine pc_machine = {
- "pc",
- "Standard PC",
- pc_init_pci,
-};
-
-QEMUMachine isapc_machine = {
- "isapc",
- "ISA-only PC",
- pc_init_isa,
-};
diff --git a/hw/pci.c b/hw/pci.c
index f58f6fd..d8cbc2b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2,7 +2,7 @@
* QEMU PCI bus manager
*
* Copyright (c) 2004 Fabrice Bellard
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -75,16 +75,16 @@ int generic_pci_load(QEMUFile* f, void *opaque, int version_id)
}
/* -1 for devfn means auto assign */
-PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+PCIDevice *pci_register_device(PCIBus *bus, const char *name,
int instance_size, int devfn,
- PCIConfigReadFunc *config_read,
+ PCIConfigReadFunc *config_read,
PCIConfigWriteFunc *config_write)
{
PCIDevice *pci_dev;
if (pci_irq_index >= PCI_DEVICES_MAX)
return NULL;
-
+
if (devfn < 0) {
for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
if (!bus->devices[devfn])
@@ -111,8 +111,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
return pci_dev;
}
-void pci_register_io_region(PCIDevice *pci_dev, int region_num,
- uint32_t size, int type,
+void pci_register_io_region(PCIDevice *pci_dev, int region_num,
+ uint32_t size, int type,
PCIMapIORegionFunc *map_func)
{
PCIIORegion *r;
@@ -143,7 +143,7 @@ static void pci_update_mappings(PCIDevice *d)
PCIIORegion *r;
int cmd, i;
uint32_t last_addr, new_addr, config_ofs;
-
+
cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
for(i = 0; i < PCI_NUM_REGIONS; i++) {
r = &d->io_regions[i];
@@ -155,7 +155,7 @@ static void pci_update_mappings(PCIDevice *d)
if (r->size != 0) {
if (r->type & PCI_ADDRESS_SPACE_IO) {
if (cmd & PCI_COMMAND_IO) {
- new_addr = le32_to_cpu(*(uint32_t *)(d->config +
+ new_addr = le32_to_cpu(*(uint32_t *)(d->config +
config_ofs));
new_addr = new_addr & ~(r->size - 1);
last_addr = new_addr + r->size - 1;
@@ -169,7 +169,7 @@ static void pci_update_mappings(PCIDevice *d)
}
} else {
if (cmd & PCI_COMMAND_MEMORY) {
- new_addr = le32_to_cpu(*(uint32_t *)(d->config +
+ new_addr = le32_to_cpu(*(uint32_t *)(d->config +
config_ofs));
/* the ROM slot has a specific enable bit */
if (i == PCI_ROM_SLOT && !(new_addr & 1))
@@ -204,7 +204,7 @@ static void pci_update_mappings(PCIDevice *d)
}
} else {
cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
- r->size,
+ r->size,
IO_MEM_UNASSIGNED);
}
}
@@ -217,7 +217,7 @@ static void pci_update_mappings(PCIDevice *d)
}
}
-uint32_t pci_default_read_config(PCIDevice *d,
+uint32_t pci_default_read_config(PCIDevice *d,
uint32_t address, int len)
{
uint32_t val;
@@ -236,13 +236,13 @@ uint32_t pci_default_read_config(PCIDevice *d,
return val;
}
-void pci_default_write_config(PCIDevice *d,
+void pci_default_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
int can_write, i;
uint32_t end, addr;
- if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
+ if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
(address >= 0x30 && address < 0x34))) {
PCIIORegion *r;
int reg;
@@ -336,7 +336,7 @@ void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
PCIBus *s = opaque;
PCIDevice *pci_dev;
int config_addr, bus_num;
-
+
#if defined(DEBUG_PCI) && 0
printf("pci_data_write: addr=%08x val=%08x len=%d\n",
addr, val, len);
@@ -414,7 +414,7 @@ typedef struct {
const char *desc;
} pci_class_desc;
-static pci_class_desc pci_class_descriptions[] =
+static pci_class_desc pci_class_descriptions[] =
{
{ 0x0101, "IDE controller"},
{ 0x0200, "Ethernet controller"},
@@ -456,10 +456,10 @@ static void pci_info_device(PCIDevice *d)
if (r->size != 0) {
term_printf(" BAR%d: ", i);
if (r->type & PCI_ADDRESS_SPACE_IO) {
- term_printf("I/O at 0x%04x [0x%04x].\n",
+ term_printf("I/O at 0x%04x [0x%04x].\n",
r->addr, r->addr + r->size - 1);
} else {
- term_printf("32 bit memory at 0x%08x [0x%08x].\n",
+ term_printf("32 bit memory at 0x%08x [0x%08x].\n",
r->addr, r->addr + r->size - 1);
}
}
@@ -471,7 +471,7 @@ void pci_for_each_device(void (*fn)(PCIDevice *d))
PCIBus *bus = first_bus;
PCIDevice *d;
int devfn;
-
+
if (bus) {
for(devfn = 0; devfn < 256; devfn++) {
d = bus->devices[devfn];
@@ -489,6 +489,7 @@ void pci_info(void)
/* Initialize a PCI NIC. */
void pci_nic_init(PCIBus *bus, NICInfo *nd)
{
+#if 0 /* ANDROID */
if (strcmp(nd->model, "ne2k_pci") == 0) {
pci_ne2000_init(bus, nd);
} else if (strcmp(nd->model, "rtl8139") == 0) {
@@ -496,6 +497,9 @@ void pci_nic_init(PCIBus *bus, NICInfo *nd)
} else if (strcmp(nd->model, "pcnet") == 0) {
pci_pcnet_init(bus, nd);
} else {
+#else
+ {
+#endif
fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
exit (1);
}
diff --git a/hw/pckbd.c b/hw/pckbd.c
deleted file mode 100644
index 3c41e5f..0000000
--- a/hw/pckbd.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * QEMU PC keyboard emulation
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug PC keyboard */
-//#define DEBUG_KBD
-
-/* debug PC keyboard : only mouse */
-//#define DEBUG_MOUSE
-
-/* Keyboard Controller Commands */
-#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
-#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
-#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
-#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
-#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
-#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
-#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
-#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
-#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
-#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
-#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */
-#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */
-#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */
-#define KBD_CCMD_WRITE_OBUF 0xD2
-#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
- initiated by the auxiliary device */
-#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
-#define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */
-#define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */
-#define KBD_CCMD_RESET 0xFE
-
-/* Keyboard Commands */
-#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
-#define KBD_CMD_ECHO 0xEE
-#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
-#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
-#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
-#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
-#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
-#define KBD_CMD_RESET 0xFF /* Reset */
-
-/* Keyboard Replies */
-#define KBD_REPLY_POR 0xAA /* Power on reset */
-#define KBD_REPLY_ACK 0xFA /* Command ACK */
-#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
-
-/* Status Register Bits */
-#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
-#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
-#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
-#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
-#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
-#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
-#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
-#define KBD_STAT_PERR 0x80 /* Parity error */
-
-/* Controller Mode Register Bits */
-#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
-#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
-#define KBD_MODE_SYS 0x04 /* The system flag (?) */
-#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
-#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
-#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
-#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
-#define KBD_MODE_RFU 0x80
-
-/* Mouse Commands */
-#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
-#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
-#define AUX_SET_RES 0xE8 /* Set resolution */
-#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
-#define AUX_SET_STREAM 0xEA /* Set stream mode */
-#define AUX_POLL 0xEB /* Poll */
-#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
-#define AUX_SET_WRAP 0xEE /* Set wrap mode */
-#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
-#define AUX_GET_TYPE 0xF2 /* Get type */
-#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
-#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
-#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
-#define AUX_SET_DEFAULT 0xF6
-#define AUX_RESET 0xFF /* Reset aux device */
-#define AUX_ACK 0xFA /* Command byte ACK. */
-
-#define MOUSE_STATUS_REMOTE 0x40
-#define MOUSE_STATUS_ENABLED 0x20
-#define MOUSE_STATUS_SCALE21 0x10
-
-#define KBD_QUEUE_SIZE 256
-
-#define KBD_PENDING_KBD 1
-#define KBD_PENDING_AUX 2
-
-typedef struct KBDState {
- uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
- uint8_t status;
- uint8_t mode;
- /* Bitmask of devices with data available. */
- uint8_t pending;
- void *kbd;
- void *mouse;
-} KBDState;
-
-KBDState kbd_state;
-
-/* update irq and KBD_STAT_[MOUSE_]OBF */
-/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
- incorrect, but it avoids having to simulate exact delays */
-static void kbd_update_irq(KBDState *s)
-{
- int irq12_level, irq1_level;
-
- irq1_level = 0;
- irq12_level = 0;
- s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
- if (s->pending) {
- s->status |= KBD_STAT_OBF;
- /* kdb data takes priority over aux data. */
- if (s->pending == KBD_PENDING_AUX) {
- s->status |= KBD_STAT_MOUSE_OBF;
- if (s->mode & KBD_MODE_MOUSE_INT)
- irq12_level = 1;
- } else {
- if ((s->mode & KBD_MODE_KBD_INT) &&
- !(s->mode & KBD_MODE_DISABLE_KBD))
- irq1_level = 1;
- }
- }
- pic_set_irq(1, irq1_level);
- pic_set_irq(12, irq12_level);
-}
-
-static void kbd_update_kbd_irq(void *opaque, int level)
-{
- KBDState *s = (KBDState *)opaque;
-
- if (level)
- s->pending |= KBD_PENDING_KBD;
- else
- s->pending &= ~KBD_PENDING_KBD;
- kbd_update_irq(s);
-}
-
-static void kbd_update_aux_irq(void *opaque, int level)
-{
- KBDState *s = (KBDState *)opaque;
-
- if (level)
- s->pending |= KBD_PENDING_AUX;
- else
- s->pending &= ~KBD_PENDING_AUX;
- kbd_update_irq(s);
-}
-
-static uint32_t kbd_read_status(void *opaque, uint32_t addr)
-{
- KBDState *s = opaque;
- int val;
- val = s->status;
-#if defined(DEBUG_KBD)
- printf("kbd: read status=0x%02x\n", val);
-#endif
- return val;
-}
-
-static void kbd_queue(KBDState *s, int b, int aux)
-{
- if (aux)
- ps2_queue(s->mouse, b);
- else
- ps2_queue(s->kbd, b);
-}
-
-static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
-{
- KBDState *s = opaque;
-
-#ifdef DEBUG_KBD
- printf("kbd: write cmd=0x%02x\n", val);
-#endif
- switch(val) {
- case KBD_CCMD_READ_MODE:
- kbd_queue(s, s->mode, 0);
- break;
- case KBD_CCMD_WRITE_MODE:
- case KBD_CCMD_WRITE_OBUF:
- case KBD_CCMD_WRITE_AUX_OBUF:
- case KBD_CCMD_WRITE_MOUSE:
- case KBD_CCMD_WRITE_OUTPORT:
- s->write_cmd = val;
- break;
- case KBD_CCMD_MOUSE_DISABLE:
- s->mode |= KBD_MODE_DISABLE_MOUSE;
- break;
- case KBD_CCMD_MOUSE_ENABLE:
- s->mode &= ~KBD_MODE_DISABLE_MOUSE;
- break;
- case KBD_CCMD_TEST_MOUSE:
- kbd_queue(s, 0x00, 0);
- break;
- case KBD_CCMD_SELF_TEST:
- s->status |= KBD_STAT_SELFTEST;
- kbd_queue(s, 0x55, 0);
- break;
- case KBD_CCMD_KBD_TEST:
- kbd_queue(s, 0x00, 0);
- break;
- case KBD_CCMD_KBD_DISABLE:
- s->mode |= KBD_MODE_DISABLE_KBD;
- kbd_update_irq(s);
- break;
- case KBD_CCMD_KBD_ENABLE:
- s->mode &= ~KBD_MODE_DISABLE_KBD;
- kbd_update_irq(s);
- break;
- case KBD_CCMD_READ_INPORT:
- kbd_queue(s, 0x00, 0);
- break;
- case KBD_CCMD_READ_OUTPORT:
- /* XXX: check that */
-#ifdef TARGET_I386
- val = 0x01 | (ioport_get_a20() << 1);
-#else
- val = 0x01;
-#endif
- if (s->status & KBD_STAT_OBF)
- val |= 0x10;
- if (s->status & KBD_STAT_MOUSE_OBF)
- val |= 0x20;
- kbd_queue(s, val, 0);
- break;
-#ifdef TARGET_I386
- case KBD_CCMD_ENABLE_A20:
- ioport_set_a20(1);
- break;
- case KBD_CCMD_DISABLE_A20:
- ioport_set_a20(0);
- break;
-#endif
- case KBD_CCMD_RESET:
- qemu_system_reset_request();
- break;
- case 0xff:
- /* ignore that - I don't know what is its use */
- break;
- default:
- fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);
- break;
- }
-}
-
-static uint32_t kbd_read_data(void *opaque, uint32_t addr)
-{
- KBDState *s = opaque;
-
- if (s->pending == KBD_PENDING_AUX)
- return ps2_read_data(s->mouse);
-
- return ps2_read_data(s->kbd);
-}
-
-void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
-{
- KBDState *s = opaque;
-
-#ifdef DEBUG_KBD
- printf("kbd: write data=0x%02x\n", val);
-#endif
-
- switch(s->write_cmd) {
- case 0:
- ps2_write_keyboard(s->kbd, val);
- break;
- case KBD_CCMD_WRITE_MODE:
- s->mode = val;
- ps2_keyboard_set_translation(s->kbd, (s->mode & KBD_MODE_KCC) != 0);
- /* ??? */
- kbd_update_irq(s);
- break;
- case KBD_CCMD_WRITE_OBUF:
- kbd_queue(s, val, 0);
- break;
- case KBD_CCMD_WRITE_AUX_OBUF:
- kbd_queue(s, val, 1);
- break;
- case KBD_CCMD_WRITE_OUTPORT:
-#ifdef TARGET_I386
- ioport_set_a20((val >> 1) & 1);
-#endif
- if (!(val & 1)) {
- qemu_system_reset_request();
- }
- break;
- case KBD_CCMD_WRITE_MOUSE:
- ps2_write_mouse(s->mouse, val);
- break;
- default:
- break;
- }
- s->write_cmd = 0;
-}
-
-static void kbd_reset(void *opaque)
-{
- KBDState *s = opaque;
-
- s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
- s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
-}
-
-static void kbd_save(QEMUFile* f, void* opaque)
-{
- KBDState *s = (KBDState*)opaque;
-
- qemu_put_8s(f, &s->write_cmd);
- qemu_put_8s(f, &s->status);
- qemu_put_8s(f, &s->mode);
- qemu_put_8s(f, &s->pending);
-}
-
-static int kbd_load(QEMUFile* f, void* opaque, int version_id)
-{
- KBDState *s = (KBDState*)opaque;
-
- if (version_id != 3)
- return -EINVAL;
- qemu_get_8s(f, &s->write_cmd);
- qemu_get_8s(f, &s->status);
- qemu_get_8s(f, &s->mode);
- qemu_get_8s(f, &s->pending);
- return 0;
-}
-
-void kbd_init(void)
-{
- KBDState *s = &kbd_state;
-
- kbd_reset(s);
- register_savevm("pckbd", 0, 3, kbd_save, kbd_load, 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);
-
- s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
- s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
- qemu_register_reset(kbd_reset, s);
-}
diff --git a/hw/pcnet.c b/hw/pcnet.c
deleted file mode 100644
index 0845cdc..0000000
--- a/hw/pcnet.c
+++ /dev/null
@@ -1,1789 +0,0 @@
-/*
- * QEMU AMD PC-Net II (Am79C970A) emulation
- *
- * Copyright (c) 2004 Antony T Curtis
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/* This software was written to be compatible with the specification:
- * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
- * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
- */
-
-#include "vl.h"
-
-//#define PCNET_DEBUG
-//#define PCNET_DEBUG_IO
-//#define PCNET_DEBUG_BCR
-//#define PCNET_DEBUG_CSR
-//#define PCNET_DEBUG_RMD
-//#define PCNET_DEBUG_TMD
-//#define PCNET_DEBUG_MATCH
-
-
-#define PCNET_IOPORT_SIZE 0x20
-#define PCNET_PNPMMIO_SIZE 0x20
-
-
-typedef struct PCNetState_st PCNetState;
-
-struct PCNetState_st {
- PCIDevice dev;
- VLANClientState *vc;
- NICInfo *nd;
- QEMUTimer *poll_timer;
- int mmio_io_addr, rap, isr, lnkst;
- target_phys_addr_t rdra, tdra;
- uint8_t prom[16];
- uint16_t csr[128];
- uint16_t bcr[32];
- uint64_t timer;
- int xmit_pos, recv_pos;
- uint8_t buffer[4096];
- int tx_busy;
-};
-
-/* XXX: using bitfields for target memory structures is almost surely
- not portable, so it should be suppressed ASAP */
-#ifdef __GNUC__
-#define PACKED_FIELD(A) A __attribute__ ((packed))
-#else
-#error FixMe
-#endif
-
-struct qemu_ether_header {
- uint8_t ether_dhost[6];
- uint8_t ether_shost[6];
- uint16_t ether_type;
-};
-
-/* BUS CONFIGURATION REGISTERS */
-#define BCR_MSRDA 0
-#define BCR_MSWRA 1
-#define BCR_MC 2
-#define BCR_LNKST 4
-#define BCR_LED1 5
-#define BCR_LED2 6
-#define BCR_LED3 7
-#define BCR_FDC 9
-#define BCR_BSBC 18
-#define BCR_EECAS 19
-#define BCR_SWS 20
-#define BCR_PLAT 22
-
-#define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080)
-#define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100)
-#define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF)
-
-#define CSR_INIT(S) !!(((S)->csr[0])&0x0001)
-#define CSR_STRT(S) !!(((S)->csr[0])&0x0002)
-#define CSR_STOP(S) !!(((S)->csr[0])&0x0004)
-#define CSR_TDMD(S) !!(((S)->csr[0])&0x0008)
-#define CSR_TXON(S) !!(((S)->csr[0])&0x0010)
-#define CSR_RXON(S) !!(((S)->csr[0])&0x0020)
-#define CSR_INEA(S) !!(((S)->csr[0])&0x0040)
-#define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020)
-#define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040)
-#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
-#define CSR_DPOLL(S) !!(((S)->csr[4])&0x1000)
-#define CSR_SPND(S) !!(((S)->csr[5])&0x0001)
-#define CSR_LTINTEN(S) !!(((S)->csr[5])&0x4000)
-#define CSR_TOKINTD(S) !!(((S)->csr[5])&0x8000)
-#define CSR_DRX(S) !!(((S)->csr[15])&0x0001)
-#define CSR_DTX(S) !!(((S)->csr[15])&0x0002)
-#define CSR_LOOP(S) !!(((S)->csr[15])&0x0004)
-#define CSR_DRCVPA(S) !!(((S)->csr[15])&0x2000)
-#define CSR_DRCVBC(S) !!(((S)->csr[15])&0x4000)
-#define CSR_PROM(S) !!(((S)->csr[15])&0x8000)
-
-#define CSR_CRBC(S) ((S)->csr[40])
-#define CSR_CRST(S) ((S)->csr[41])
-#define CSR_CXBC(S) ((S)->csr[42])
-#define CSR_CXST(S) ((S)->csr[43])
-#define CSR_NRBC(S) ((S)->csr[44])
-#define CSR_NRST(S) ((S)->csr[45])
-#define CSR_POLL(S) ((S)->csr[46])
-#define CSR_PINT(S) ((S)->csr[47])
-#define CSR_RCVRC(S) ((S)->csr[72])
-#define CSR_XMTRC(S) ((S)->csr[74])
-#define CSR_RCVRL(S) ((S)->csr[76])
-#define CSR_XMTRL(S) ((S)->csr[78])
-#define CSR_MISSC(S) ((S)->csr[112])
-
-#define CSR_IADR(S) ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
-#define CSR_CRBA(S) ((S)->csr[18] | ((S)->csr[19] << 16))
-#define CSR_CXBA(S) ((S)->csr[20] | ((S)->csr[21] << 16))
-#define CSR_NRBA(S) ((S)->csr[22] | ((S)->csr[23] << 16))
-#define CSR_BADR(S) ((S)->csr[24] | ((S)->csr[25] << 16))
-#define CSR_NRDA(S) ((S)->csr[26] | ((S)->csr[27] << 16))
-#define CSR_CRDA(S) ((S)->csr[28] | ((S)->csr[29] << 16))
-#define CSR_BADX(S) ((S)->csr[30] | ((S)->csr[31] << 16))
-#define CSR_NXDA(S) ((S)->csr[32] | ((S)->csr[33] << 16))
-#define CSR_CXDA(S) ((S)->csr[34] | ((S)->csr[35] << 16))
-#define CSR_NNRD(S) ((S)->csr[36] | ((S)->csr[37] << 16))
-#define CSR_NNXD(S) ((S)->csr[38] | ((S)->csr[39] << 16))
-#define CSR_PXDA(S) ((S)->csr[60] | ((S)->csr[61] << 16))
-#define CSR_NXBA(S) ((S)->csr[64] | ((S)->csr[65] << 16))
-
-#define PHYSADDR(S,A) \
- (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
-
-struct pcnet_initblk16 {
- uint16_t mode;
- uint16_t padr1;
- uint16_t padr2;
- uint16_t padr3;
- uint16_t ladrf1;
- uint16_t ladrf2;
- uint16_t ladrf3;
- uint16_t ladrf4;
- unsigned PACKED_FIELD(rdra:24);
- unsigned PACKED_FIELD(res1:5);
- unsigned PACKED_FIELD(rlen:3);
- unsigned PACKED_FIELD(tdra:24);
- unsigned PACKED_FIELD(res2:5);
- unsigned PACKED_FIELD(tlen:3);
-};
-
-struct pcnet_initblk32 {
- uint16_t mode;
- unsigned PACKED_FIELD(res1:4);
- unsigned PACKED_FIELD(rlen:4);
- unsigned PACKED_FIELD(res2:4);
- unsigned PACKED_FIELD(tlen:4);
- uint16_t padr1;
- uint16_t padr2;
- uint16_t padr3;
- uint16_t _res;
- uint16_t ladrf1;
- uint16_t ladrf2;
- uint16_t ladrf3;
- uint16_t ladrf4;
- uint32_t rdra;
- uint32_t tdra;
-};
-
-struct pcnet_TMD {
- struct {
- unsigned tbadr:32;
- } tmd0;
- struct {
- unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:7), PACKED_FIELD(bpe:1);
- unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(def:1), PACKED_FIELD(one:1);
- unsigned PACKED_FIELD(ltint:1), PACKED_FIELD(nofcs:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
- } tmd1;
- struct {
- unsigned PACKED_FIELD(trc:4), PACKED_FIELD(res:12);
- unsigned PACKED_FIELD(tdr:10), PACKED_FIELD(rtry:1), PACKED_FIELD(lcar:1);
- unsigned PACKED_FIELD(lcol:1), PACKED_FIELD(exdef:1), PACKED_FIELD(uflo:1), PACKED_FIELD(buff:1);
- } tmd2;
- struct {
- unsigned res:32;
- } tmd3;
-};
-
-struct pcnet_RMD {
- struct {
- unsigned rbadr:32;
- } rmd0;
- struct {
- unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:4);
- unsigned PACKED_FIELD(bam:1), PACKED_FIELD(lafm:1), PACKED_FIELD(pam:1), PACKED_FIELD(bpe:1);
- unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(buff:1), PACKED_FIELD(crc:1);
- unsigned PACKED_FIELD(oflo:1), PACKED_FIELD(fram:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
- } rmd1;
- struct {
- unsigned PACKED_FIELD(mcnt:12), PACKED_FIELD(zeros:4);
- unsigned PACKED_FIELD(rpc:8), PACKED_FIELD(rcc:8);
- } rmd2;
- struct {
- unsigned res:32;
- } rmd3;
-};
-
-
-#define PRINT_TMD(T) printf( \
- "TMD0 : TBADR=0x%08x\n" \
- "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, " \
- "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n" \
- " BPE=%d, BCNT=%d\n" \
- "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, " \
- "LCA=%d, RTR=%d,\n" \
- " TDR=%d, TRC=%d\n", \
- (T)->tmd0.tbadr, \
- (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs, \
- (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def, \
- (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe, \
- 4096-(T)->tmd1.bcnt, \
- (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
- (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
- (T)->tmd2.tdr, (T)->tmd2.trc)
-
-#define PRINT_RMD(R) printf( \
- "RMD0 : RBADR=0x%08x\n" \
- "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, " \
- "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n " \
- "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
- "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n", \
- (R)->rmd0.rbadr, \
- (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram, \
- (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff, \
- (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe, \
- (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam, \
- (R)->rmd1.ones, 4096-(R)->rmd1.bcnt, \
- (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt, \
- (R)->rmd2.zeros)
-
-static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
-{
- if (!BCR_SWSTYLE(s)) {
- uint16_t xda[4];
- cpu_physical_memory_read(addr,
- (void *)&xda[0], sizeof(xda));
- ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
- ((xda[1]&0x00ff) << 16);
- ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
- ((xda[1] & 0xff00) << 16);
- ((uint32_t *)tmd)[2] =
- (xda[3] & 0xffff) << 16;
- ((uint32_t *)tmd)[3] = 0;
- }
- else
- if (BCR_SWSTYLE(s) != 3)
- cpu_physical_memory_read(addr, (void *)tmd, 16);
- else {
- uint32_t xda[4];
- cpu_physical_memory_read(addr,
- (void *)&xda[0], sizeof(xda));
- ((uint32_t *)tmd)[0] = xda[2];
- ((uint32_t *)tmd)[1] = xda[1];
- ((uint32_t *)tmd)[2] = xda[0];
- ((uint32_t *)tmd)[3] = xda[3];
- }
-}
-
-static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
-{
- if (!BCR_SWSTYLE(s)) {
- uint16_t xda[4];
- xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
- xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
- ((((uint32_t *)tmd)[1]>>16)&0xff00);
- xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
- xda[3] = ((uint32_t *)tmd)[2] >> 16;
- cpu_physical_memory_write(addr,
- (void *)&xda[0], sizeof(xda));
- }
- else {
- if (BCR_SWSTYLE(s) != 3)
- cpu_physical_memory_write(addr, (void *)tmd, 16);
- else {
- uint32_t xda[4];
- xda[0] = ((uint32_t *)tmd)[2];
- xda[1] = ((uint32_t *)tmd)[1];
- xda[2] = ((uint32_t *)tmd)[0];
- xda[3] = ((uint32_t *)tmd)[3];
- cpu_physical_memory_write(addr,
- (void *)&xda[0], sizeof(xda));
- }
- }
-}
-
-static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
-{
- if (!BCR_SWSTYLE(s)) {
- uint16_t rda[4];
- cpu_physical_memory_read(addr,
- (void *)&rda[0], sizeof(rda));
- ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
- ((rda[1] & 0x00ff) << 16);
- ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
- ((rda[1] & 0xff00) << 16);
- ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
- ((uint32_t *)rmd)[3] = 0;
- }
- else
- if (BCR_SWSTYLE(s) != 3)
- cpu_physical_memory_read(addr, (void *)rmd, 16);
- else {
- uint32_t rda[4];
- cpu_physical_memory_read(addr,
- (void *)&rda[0], sizeof(rda));
- ((uint32_t *)rmd)[0] = rda[2];
- ((uint32_t *)rmd)[1] = rda[1];
- ((uint32_t *)rmd)[2] = rda[0];
- ((uint32_t *)rmd)[3] = rda[3];
- }
-}
-
-static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
-{
- if (!BCR_SWSTYLE(s)) {
- uint16_t rda[4]; \
- rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
- rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
- ((((uint32_t *)rmd)[1]>>16)&0xff00);\
- rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
- rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
- cpu_physical_memory_write(addr, \
- (void *)&rda[0], sizeof(rda)); \
- }
- else {
- if (BCR_SWSTYLE(s) != 3)
- cpu_physical_memory_write(addr, (void *)rmd, 16);
- else {
- uint32_t rda[4];
- rda[0] = ((uint32_t *)rmd)[2];
- rda[1] = ((uint32_t *)rmd)[1];
- rda[2] = ((uint32_t *)rmd)[0];
- rda[3] = ((uint32_t *)rmd)[3];
- cpu_physical_memory_write(addr,
- (void *)&rda[0], sizeof(rda));
- }
- }
-}
-
-
-#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
-
-#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
-
-#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
-
-#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
-
-#if 1
-
-#define CHECK_RMD(ADDR,RES) do { \
- struct pcnet_RMD rmd; \
- RMDLOAD(&rmd,(ADDR)); \
- (RES) |= (rmd.rmd1.ones != 15) \
- || (rmd.rmd2.zeros != 0); \
-} while (0)
-
-#define CHECK_TMD(ADDR,RES) do { \
- struct pcnet_TMD tmd; \
- TMDLOAD(&tmd,(ADDR)); \
- (RES) |= (tmd.tmd1.ones != 15); \
-} while (0)
-
-#else
-
-#define CHECK_RMD(ADDR,RES) do { \
- switch (BCR_SWSTYLE(s)) { \
- case 0x00: \
- do { \
- uint16_t rda[4]; \
- cpu_physical_memory_read((ADDR), \
- (void *)&rda[0], sizeof(rda)); \
- (RES) |= (rda[2] & 0xf000)!=0xf000; \
- (RES) |= (rda[3] & 0xf000)!=0x0000; \
- } while (0); \
- break; \
- case 0x01: \
- case 0x02: \
- do { \
- uint32_t rda[4]; \
- cpu_physical_memory_read((ADDR), \
- (void *)&rda[0], sizeof(rda)); \
- (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
- (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
- } while (0); \
- break; \
- case 0x03: \
- do { \
- uint32_t rda[4]; \
- cpu_physical_memory_read((ADDR), \
- (void *)&rda[0], sizeof(rda)); \
- (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
- (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
- } while (0); \
- break; \
- } \
-} while (0)
-
-#define CHECK_TMD(ADDR,RES) do { \
- switch (BCR_SWSTYLE(s)) { \
- case 0x00: \
- do { \
- uint16_t xda[4]; \
- cpu_physical_memory_read((ADDR), \
- (void *)&xda[0], sizeof(xda)); \
- (RES) |= (xda[2] & 0xf000)!=0xf000;\
- } while (0); \
- break; \
- case 0x01: \
- case 0x02: \
- case 0x03: \
- do { \
- uint32_t xda[4]; \
- cpu_physical_memory_read((ADDR), \
- (void *)&xda[0], sizeof(xda)); \
- (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
- } while (0); \
- break; \
- } \
-} while (0)
-
-#endif
-
-#define PRINT_PKTHDR(BUF) do { \
- struct qemu_ether_header *hdr = (void *)(BUF); \
- printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
- "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
- "type=0x%04x (bcast=%d)\n", \
- hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
- hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
- hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
- hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
- be16_to_cpu(hdr->ether_type), \
- !!ETHER_IS_MULTICAST(hdr->ether_dhost)); \
-} while (0)
-
-#define MULTICAST_FILTER_LEN 8
-
-static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
-{
-#define LNC_POLYNOMIAL 0xEDB88320UL
- uint32_t crc = 0xFFFFFFFF;
- int idx, bit;
- uint8_t data;
-
- for (idx = 0; idx < 6; idx++) {
- for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
- crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
- data >>= 1;
- }
- }
- return crc;
-#undef LNC_POLYNOMIAL
-}
-
-#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
-
-/* generated using the AUTODIN II polynomial
- * x^32 + x^26 + x^23 + x^22 + x^16 +
- * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
- */
-static const uint32_t crctab[256] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
-};
-
-static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
-{
- struct qemu_ether_header *hdr = (void *)buf;
- uint8_t padr[6] = {
- s->csr[12] & 0xff, s->csr[12] >> 8,
- s->csr[13] & 0xff, s->csr[13] >> 8,
- s->csr[14] & 0xff, s->csr[14] >> 8
- };
- int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
-#ifdef PCNET_DEBUG_MATCH
- printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
- "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
- hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
- hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
- padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
- printf("padr_match result=%d\n", result);
-#endif
- return result;
-}
-
-static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
-{
- static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- struct qemu_ether_header *hdr = (void *)buf;
- int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
-#ifdef PCNET_DEBUG_MATCH
- printf("padr_bcast result=%d\n", result);
-#endif
- return result;
-}
-
-static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
-{
- struct qemu_ether_header *hdr = (void *)buf;
- if ((*(hdr->ether_dhost)&0x01) &&
- ((uint64_t *)&s->csr[8])[0] != 0LL) {
- uint8_t ladr[8] = {
- s->csr[8] & 0xff, s->csr[8] >> 8,
- s->csr[9] & 0xff, s->csr[9] >> 8,
- s->csr[10] & 0xff, s->csr[10] >> 8,
- s->csr[11] & 0xff, s->csr[11] >> 8
- };
- int index = lnc_mchash(hdr->ether_dhost) >> 26;
- return !!(ladr[index >> 3] & (1 << (index & 7)));
- }
- return 0;
-}
-
-static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx)
-{
- while (idx < 1) idx += CSR_RCVRL(s);
- return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
-}
-
-static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
-{
- int64_t next_time = current_time +
- muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
- ticks_per_sec, 33000000L);
- if (next_time <= current_time)
- next_time = current_time + 1;
- return next_time;
-}
-
-static void pcnet_poll(PCNetState *s);
-static void pcnet_poll_timer(void *opaque);
-
-static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
-static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
-static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
-static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
-
-static void pcnet_s_reset(PCNetState *s)
-{
-#ifdef PCNET_DEBUG
- printf("pcnet_s_reset\n");
-#endif
-
- s->lnkst = 0x40;
- s->rdra = 0;
- s->tdra = 0;
- s->rap = 0;
-
- s->bcr[BCR_BSBC] &= ~0x0080;
-
- s->csr[0] = 0x0004;
- s->csr[3] = 0x0000;
- s->csr[4] = 0x0115;
- s->csr[5] = 0x0000;
- s->csr[6] = 0x0000;
- s->csr[8] = 0;
- s->csr[9] = 0;
- s->csr[10] = 0;
- s->csr[11] = 0;
- s->csr[12] = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
- s->csr[13] = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
- s->csr[14] = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
- s->csr[15] &= 0x21c4;
- s->csr[72] = 1;
- s->csr[74] = 1;
- s->csr[76] = 1;
- s->csr[78] = 1;
- s->csr[80] = 0x1410;
- s->csr[88] = 0x1003;
- s->csr[89] = 0x0262;
- s->csr[94] = 0x0000;
- s->csr[100] = 0x0200;
- s->csr[103] = 0x0105;
- s->csr[103] = 0x0105;
- s->csr[112] = 0x0000;
- s->csr[114] = 0x0000;
- s->csr[122] = 0x0000;
- s->csr[124] = 0x0000;
-
- s->tx_busy = 0;
-}
-
-static void pcnet_update_irq(PCNetState *s)
-{
- int isr = 0;
- s->csr[0] &= ~0x0080;
-
-#if 1
- if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
- (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
- (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
-#else
- if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
- (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
- (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
- (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
- (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
- (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
- (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
- (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
- (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
- (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
- (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
- (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
-#endif
- {
-
- isr = CSR_INEA(s);
- s->csr[0] |= 0x0080;
- }
-
- if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
- s->csr[4] &= ~0x0080;
- s->csr[4] |= 0x0040;
- s->csr[0] |= 0x0080;
- isr = 1;
-#ifdef PCNET_DEBUG
- printf("pcnet user int\n");
-#endif
- }
-
-#if 1
- if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
-#else
- if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
- (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
-#endif
- {
- isr = 1;
- s->csr[0] |= 0x0080;
- }
-
- if (isr != s->isr) {
-#ifdef PCNET_DEBUG
- printf("pcnet: INTA=%d\n", isr);
-#endif
- }
- pci_set_irq(&s->dev, 0, isr);
- s->isr = isr;
-}
-
-static void pcnet_init(PCNetState *s)
-{
-#ifdef PCNET_DEBUG
- printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
-#endif
-
-#define PCNET_INIT() do { \
- cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)), \
- (uint8_t *)&initblk, sizeof(initblk)); \
- s->csr[15] = le16_to_cpu(initblk.mode); \
- CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \
- CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \
- s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \
- s->csr[ 8] = le16_to_cpu(initblk.ladrf1); \
- s->csr[ 9] = le16_to_cpu(initblk.ladrf2); \
- s->csr[10] = le16_to_cpu(initblk.ladrf3); \
- s->csr[11] = le16_to_cpu(initblk.ladrf4); \
- s->csr[12] = le16_to_cpu(initblk.padr1); \
- s->csr[13] = le16_to_cpu(initblk.padr2); \
- s->csr[14] = le16_to_cpu(initblk.padr3); \
- s->rdra = PHYSADDR(s,initblk.rdra); \
- s->tdra = PHYSADDR(s,initblk.tdra); \
-} while (0)
-
- if (BCR_SSIZE32(s)) {
- struct pcnet_initblk32 initblk;
- PCNET_INIT();
-#ifdef PCNET_DEBUG
- printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
- initblk.rlen, initblk.tlen);
-#endif
- } else {
- struct pcnet_initblk16 initblk;
- PCNET_INIT();
-#ifdef PCNET_DEBUG
- printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
- initblk.rlen, initblk.tlen);
-#endif
- }
-
-#undef PCNET_INIT
-
- CSR_RCVRC(s) = CSR_RCVRL(s);
- CSR_XMTRC(s) = CSR_XMTRL(s);
-
-#ifdef PCNET_DEBUG
- printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
- BCR_SSIZE32(s),
- s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
-#endif
-
- s->csr[0] |= 0x0101;
- s->csr[0] &= ~0x0004; /* clear STOP bit */
-}
-
-static void pcnet_start(PCNetState *s)
-{
-#ifdef PCNET_DEBUG
- printf("pcnet_start\n");
-#endif
-
- if (!CSR_DTX(s))
- s->csr[0] |= 0x0010; /* set TXON */
-
- if (!CSR_DRX(s))
- s->csr[0] |= 0x0020; /* set RXON */
-
- s->csr[0] &= ~0x0004; /* clear STOP bit */
- s->csr[0] |= 0x0002;
-}
-
-static void pcnet_stop(PCNetState *s)
-{
-#ifdef PCNET_DEBUG
- printf("pcnet_stop\n");
-#endif
- s->csr[0] &= ~0x7feb;
- s->csr[0] |= 0x0014;
- s->csr[4] &= ~0x02c2;
- s->csr[5] &= ~0x0011;
- pcnet_poll_timer(s);
-}
-
-static void pcnet_rdte_poll(PCNetState *s)
-{
- s->csr[28] = s->csr[29] = 0;
- if (s->rdra) {
- int bad = 0;
-#if 1
- target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
- target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
- target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
-#else
- target_phys_addr_t crda = s->rdra +
- (CSR_RCVRL(s) - CSR_RCVRC(s)) *
- (BCR_SWSTYLE(s) ? 16 : 8 );
- int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
- target_phys_addr_t nrda = s->rdra +
- (CSR_RCVRL(s) - nrdc) *
- (BCR_SWSTYLE(s) ? 16 : 8 );
- int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
- target_phys_addr_t nnrd = s->rdra +
- (CSR_RCVRL(s) - nnrc) *
- (BCR_SWSTYLE(s) ? 16 : 8 );
-#endif
-
- CHECK_RMD(PHYSADDR(s,crda), bad);
- if (!bad) {
- CHECK_RMD(PHYSADDR(s,nrda), bad);
- if (bad || (nrda == crda)) nrda = 0;
- CHECK_RMD(PHYSADDR(s,nnrd), bad);
- if (bad || (nnrd == crda)) nnrd = 0;
-
- s->csr[28] = crda & 0xffff;
- s->csr[29] = crda >> 16;
- s->csr[26] = nrda & 0xffff;
- s->csr[27] = nrda >> 16;
- s->csr[36] = nnrd & 0xffff;
- s->csr[37] = nnrd >> 16;
-#ifdef PCNET_DEBUG
- if (bad) {
- printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
- PHYSADDR(s,crda));
- }
- } else {
- printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
-#endif
- }
- }
-
- if (CSR_CRDA(s)) {
- struct pcnet_RMD rmd;
- RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
- CSR_CRBC(s) = rmd.rmd1.bcnt;
- CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
-#ifdef PCNET_DEBUG_RMD_X
- printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
- PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
- ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
- PRINT_RMD(&rmd);
-#endif
- } else {
- CSR_CRBC(s) = CSR_CRST(s) = 0;
- }
-
- if (CSR_NRDA(s)) {
- struct pcnet_RMD rmd;
- RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
- CSR_NRBC(s) = rmd.rmd1.bcnt;
- CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
- } else {
- CSR_NRBC(s) = CSR_NRST(s) = 0;
- }
-
-}
-
-static int pcnet_tdte_poll(PCNetState *s)
-{
- s->csr[34] = s->csr[35] = 0;
- if (s->tdra) {
- target_phys_addr_t cxda = s->tdra +
- (CSR_XMTRL(s) - CSR_XMTRC(s)) *
- (BCR_SWSTYLE(s) ? 16 : 8 );
- int bad = 0;
- CHECK_TMD(PHYSADDR(s, cxda),bad);
- if (!bad) {
- if (CSR_CXDA(s) != cxda) {
- s->csr[60] = s->csr[34];
- s->csr[61] = s->csr[35];
- s->csr[62] = CSR_CXBC(s);
- s->csr[63] = CSR_CXST(s);
- }
- s->csr[34] = cxda & 0xffff;
- s->csr[35] = cxda >> 16;
-#ifdef PCNET_DEBUG
- } else {
- printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
-#endif
- }
- }
-
- if (CSR_CXDA(s)) {
- struct pcnet_TMD tmd;
-
- TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
-
- CSR_CXBC(s) = tmd.tmd1.bcnt;
- CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
- } else {
- CSR_CXBC(s) = CSR_CXST(s) = 0;
- }
-
- return !!(CSR_CXST(s) & 0x8000);
-}
-
-static int pcnet_can_receive(void *opaque)
-{
- PCNetState *s = opaque;
- if (CSR_STOP(s) || CSR_SPND(s))
- return 0;
-
- if (s->recv_pos > 0)
- return 0;
-
- return sizeof(s->buffer)-16;
-}
-
-#define MIN_BUF_SIZE 60
-
-static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
-{
- PCNetState *s = opaque;
- int is_padr = 0, is_bcast = 0, is_ladr = 0;
- uint8_t buf1[60];
-
- if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
- return;
-
-#ifdef PCNET_DEBUG
- printf("pcnet_receive size=%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;
- }
-
- if (CSR_PROM(s)
- || (is_padr=padr_match(s, buf, size))
- || (is_bcast=padr_bcast(s, buf, size))
- || (is_ladr=ladr_match(s, buf, size))) {
-
- pcnet_rdte_poll(s);
-
- if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
- struct pcnet_RMD rmd;
- int rcvrc = CSR_RCVRC(s)-1,i;
- target_phys_addr_t nrda;
- for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
- if (rcvrc <= 1)
- rcvrc = CSR_RCVRL(s);
- nrda = s->rdra +
- (CSR_RCVRL(s) - rcvrc) *
- (BCR_SWSTYLE(s) ? 16 : 8 );
- RMDLOAD(&rmd, PHYSADDR(s,nrda));
- if (rmd.rmd1.own) {
-#ifdef PCNET_DEBUG_RMD
- printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
- rcvrc, CSR_RCVRC(s));
-#endif
- CSR_RCVRC(s) = rcvrc;
- pcnet_rdte_poll(s);
- break;
- }
- }
- }
-
- if (!(CSR_CRST(s) & 0x8000)) {
-#ifdef PCNET_DEBUG_RMD
- printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
-#endif
- s->csr[0] |= 0x1000; /* Set MISS flag */
- CSR_MISSC(s)++;
- } else {
- uint8_t *src = &s->buffer[8];
- target_phys_addr_t crda = CSR_CRDA(s);
- struct pcnet_RMD rmd;
- int pktcount = 0;
-
- memcpy(src, buf, size);
-
-#if 1
- /* no need to compute the CRC */
- src[size] = 0;
- src[size + 1] = 0;
- src[size + 2] = 0;
- src[size + 3] = 0;
- size += 4;
-#else
- /* XXX: avoid CRC generation */
- if (!CSR_ASTRP_RCV(s)) {
- uint32_t fcs = ~0;
- uint8_t *p = src;
-
- while (size < 46) {
- src[size++] = 0;
- }
-
- while (p != &src[size]) {
- CRC(fcs, *p++);
- }
- ((uint32_t *)&src[size])[0] = htonl(fcs);
- size += 4; /* FCS at end of packet */
- } else size += 4;
-#endif
-
-#ifdef PCNET_DEBUG_MATCH
- PRINT_PKTHDR(buf);
-#endif
-
- RMDLOAD(&rmd, PHYSADDR(s,crda));
- /*if (!CSR_LAPPEN(s))*/
- rmd.rmd1.stp = 1;
-
-#define PCNET_RECV_STORE() do { \
- int count = MIN(4096 - rmd.rmd1.bcnt,size); \
- target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \
- cpu_physical_memory_write(rbadr, src, count); \
- src += count; size -= count; \
- rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \
- RMDSTORE(&rmd, PHYSADDR(s,crda)); \
- pktcount++; \
-} while (0)
-
- PCNET_RECV_STORE();
- if ((size > 0) && CSR_NRDA(s)) {
- target_phys_addr_t nrda = CSR_NRDA(s);
- RMDLOAD(&rmd, PHYSADDR(s,nrda));
- if (rmd.rmd1.own) {
- crda = nrda;
- PCNET_RECV_STORE();
- if ((size > 0) && (nrda=CSR_NNRD(s))) {
- RMDLOAD(&rmd, PHYSADDR(s,nrda));
- if (rmd.rmd1.own) {
- crda = nrda;
- PCNET_RECV_STORE();
- }
- }
- }
- }
-
-#undef PCNET_RECV_STORE
-
- RMDLOAD(&rmd, PHYSADDR(s,crda));
- if (size == 0) {
- rmd.rmd1.enp = 1;
- rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
- rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
- rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
- } else {
- rmd.rmd1.oflo = 1;
- rmd.rmd1.buff = 1;
- rmd.rmd1.err = 1;
- }
- RMDSTORE(&rmd, PHYSADDR(s,crda));
- s->csr[0] |= 0x0400;
-
-#ifdef PCNET_DEBUG
- printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
- CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
-#endif
-#ifdef PCNET_DEBUG_RMD
- PRINT_RMD(&rmd);
-#endif
-
- while (pktcount--) {
- if (CSR_RCVRC(s) <= 1)
- CSR_RCVRC(s) = CSR_RCVRL(s);
- else
- CSR_RCVRC(s)--;
- }
-
- pcnet_rdte_poll(s);
-
- }
- }
-
- pcnet_poll(s);
- pcnet_update_irq(s);
-}
-
-static void pcnet_transmit(PCNetState *s)
-{
- target_phys_addr_t xmit_cxda = 0;
- int count = CSR_XMTRL(s)-1;
- s->xmit_pos = -1;
-
- if (!CSR_TXON(s)) {
- s->csr[0] &= ~0x0008;
- return;
- }
-
- s->tx_busy = 1;
-
- txagain:
- if (pcnet_tdte_poll(s)) {
- struct pcnet_TMD tmd;
-
- TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
-
-#ifdef PCNET_DEBUG_TMD
- printf(" TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
- PRINT_TMD(&tmd);
-#endif
- if (tmd.tmd1.stp) {
- s->xmit_pos = 0;
- if (!tmd.tmd1.enp) {
- cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
- s->buffer, 4096 - tmd.tmd1.bcnt);
- s->xmit_pos += 4096 - tmd.tmd1.bcnt;
- }
- xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
- }
- if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
- cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
- s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
- s->xmit_pos += 4096 - tmd.tmd1.bcnt;
-#ifdef PCNET_DEBUG
- printf("pcnet_transmit size=%d\n", s->xmit_pos);
-#endif
- if (CSR_LOOP(s))
- pcnet_receive(s, s->buffer, s->xmit_pos);
- else
- qemu_send_packet(s->vc, s->buffer, s->xmit_pos);
-
- s->csr[0] &= ~0x0008; /* clear TDMD */
- s->csr[4] |= 0x0004; /* set TXSTRT */
- s->xmit_pos = -1;
- }
-
- tmd.tmd1.own = 0;
- TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
- if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
- s->csr[0] |= 0x0200; /* set TINT */
-
- if (CSR_XMTRC(s)<=1)
- CSR_XMTRC(s) = CSR_XMTRL(s);
- else
- CSR_XMTRC(s)--;
- if (count--)
- goto txagain;
-
- } else
- if (s->xmit_pos >= 0) {
- struct pcnet_TMD tmd;
- TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));
- tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
- tmd.tmd1.own = 0;
- TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
- s->csr[0] |= 0x0200; /* set TINT */
- if (!CSR_DXSUFLO(s)) {
- s->csr[0] &= ~0x0010;
- } else
- if (count--)
- goto txagain;
- }
-
- s->tx_busy = 0;
-}
-
-static void pcnet_poll(PCNetState *s)
-{
- if (CSR_RXON(s)) {
- pcnet_rdte_poll(s);
- }
-
- if (CSR_TDMD(s) ||
- (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
- {
- /* prevent recursion */
- if (s->tx_busy)
- return;
-
- pcnet_transmit(s);
- }
-}
-
-static void pcnet_poll_timer(void *opaque)
-{
- PCNetState *s = opaque;
-
- qemu_del_timer(s->poll_timer);
-
- if (CSR_TDMD(s)) {
- pcnet_transmit(s);
- }
-
- pcnet_update_irq(s);
-
- if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
- uint64_t now = qemu_get_clock(vm_clock) * 33;
- if (!s->timer || !now)
- s->timer = now;
- else {
- uint64_t t = now - s->timer + CSR_POLL(s);
- if (t > 0xffffLL) {
- pcnet_poll(s);
- CSR_POLL(s) = CSR_PINT(s);
- } else
- CSR_POLL(s) = t;
- }
- qemu_mod_timer(s->poll_timer,
- pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
- }
-}
-
-
-static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
-{
- uint16_t val = new_value;
-#ifdef PCNET_DEBUG_CSR
- printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
-#endif
- switch (rap) {
- case 0:
- s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
-
- s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
-
- val = (val & 0x007f) | (s->csr[0] & 0x7f00);
-
- /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
- if ((val&7) == 7)
- val &= ~3;
-
- if (!CSR_STOP(s) && (val & 4))
- pcnet_stop(s);
-
- if (!CSR_INIT(s) && (val & 1))
- pcnet_init(s);
-
- if (!CSR_STRT(s) && (val & 2))
- pcnet_start(s);
-
- if (CSR_TDMD(s))
- pcnet_transmit(s);
-
- return;
- case 1:
- case 2:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- case 18: /* CRBAL */
- case 19: /* CRBAU */
- case 20: /* CXBAL */
- case 21: /* CXBAU */
- case 22: /* NRBAU */
- case 23: /* NRBAU */
- case 24:
- case 25:
- case 26:
- case 27:
- case 28:
- case 29:
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case 35:
- case 36:
- case 37:
- case 38:
- case 39:
- case 40: /* CRBC */
- case 41:
- case 42: /* CXBC */
- case 43:
- case 44:
- case 45:
- case 46: /* POLL */
- case 47: /* POLLINT */
- case 72:
- case 74:
- case 76: /* RCVRL */
- case 78: /* XMTRL */
- case 112:
- if (CSR_STOP(s) || CSR_SPND(s))
- break;
- return;
- case 3:
- break;
- case 4:
- s->csr[4] &= ~(val & 0x026a);
- val &= ~0x026a; val |= s->csr[4] & 0x026a;
- break;
- case 5:
- s->csr[5] &= ~(val & 0x0a90);
- val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
- break;
- case 16:
- pcnet_csr_writew(s,1,val);
- return;
- case 17:
- pcnet_csr_writew(s,2,val);
- return;
- case 58:
- pcnet_bcr_writew(s,BCR_SWS,val);
- break;
- default:
- return;
- }
- s->csr[rap] = val;
-}
-
-static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
-{
- uint32_t val;
- switch (rap) {
- case 0:
- pcnet_update_irq(s);
- val = s->csr[0];
- val |= (val & 0x7800) ? 0x8000 : 0;
- break;
- case 16:
- return pcnet_csr_readw(s,1);
- case 17:
- return pcnet_csr_readw(s,2);
- case 58:
- return pcnet_bcr_readw(s,BCR_SWS);
- case 88:
- val = s->csr[89];
- val <<= 16;
- val |= s->csr[88];
- break;
- default:
- val = s->csr[rap];
- }
-#ifdef PCNET_DEBUG_CSR
- printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
-#endif
- return val;
-}
-
-static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
-{
- rap &= 127;
-#ifdef PCNET_DEBUG_BCR
- printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
-#endif
- switch (rap) {
- case BCR_SWS:
- if (!(CSR_STOP(s) || CSR_SPND(s)))
- return;
- val &= ~0x0300;
- switch (val & 0x00ff) {
- case 0:
- val |= 0x0200;
- break;
- case 1:
- val |= 0x0100;
- break;
- case 2:
- case 3:
- val |= 0x0300;
- break;
- default:
- printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
- val = 0x0200;
- break;
- }
-#ifdef PCNET_DEBUG
- printf("BCR_SWS=0x%04x\n", val);
-#endif
- case BCR_LNKST:
- case BCR_LED1:
- case BCR_LED2:
- case BCR_LED3:
- case BCR_MC:
- case BCR_FDC:
- case BCR_BSBC:
- case BCR_EECAS:
- case BCR_PLAT:
- s->bcr[rap] = val;
- break;
- default:
- break;
- }
-}
-
-static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
-{
- uint32_t val;
- rap &= 127;
- switch (rap) {
- case BCR_LNKST:
- case BCR_LED1:
- case BCR_LED2:
- case BCR_LED3:
- val = s->bcr[rap] & ~0x8000;
- val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
- break;
- default:
- val = rap < 32 ? s->bcr[rap] : 0;
- break;
- }
-#ifdef PCNET_DEBUG_BCR
- printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
-#endif
- return val;
-}
-
-static void pcnet_h_reset(PCNetState *s)
-{
- int i;
- uint16_t checksum;
-
- /* Initialize the PROM */
-
- memcpy(s->prom, s->nd->macaddr, 6);
- s->prom[12] = s->prom[13] = 0x00;
- s->prom[14] = s->prom[15] = 0x57;
-
- for (i = 0,checksum = 0; i < 16; i++)
- checksum += s->prom[i];
- *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
-
-
- s->bcr[BCR_MSRDA] = 0x0005;
- s->bcr[BCR_MSWRA] = 0x0005;
- s->bcr[BCR_MC ] = 0x0002;
- s->bcr[BCR_LNKST] = 0x00c0;
- s->bcr[BCR_LED1 ] = 0x0084;
- s->bcr[BCR_LED2 ] = 0x0088;
- s->bcr[BCR_LED3 ] = 0x0090;
- s->bcr[BCR_FDC ] = 0x0000;
- s->bcr[BCR_BSBC ] = 0x9001;
- s->bcr[BCR_EECAS] = 0x0002;
- s->bcr[BCR_SWS ] = 0x0200;
- s->bcr[BCR_PLAT ] = 0xff06;
-
- pcnet_s_reset(s);
-}
-
-static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- PCNetState *s = opaque;
-#ifdef PCNET_DEBUG
- printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
-#endif
- /* Check APROMWE bit to enable write access */
- if (pcnet_bcr_readw(s,2) & 0x80)
- s->prom[addr & 15] = val;
-}
-
-static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
-{
- PCNetState *s = opaque;
- uint32_t val = s->prom[addr &= 15];
-#ifdef PCNET_DEBUG
- printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
-#endif
- return val;
-}
-
-static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- PCNetState *s = opaque;
- pcnet_poll_timer(s);
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
-#endif
- if (!BCR_DWIO(s)) {
- switch (addr & 0x0f) {
- case 0x00: /* RDP */
- pcnet_csr_writew(s, s->rap, val);
- break;
- case 0x02:
- s->rap = val & 0x7f;
- break;
- case 0x06:
- pcnet_bcr_writew(s, s->rap, val);
- break;
- }
- }
- pcnet_update_irq(s);
-}
-
-static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
-{
- PCNetState *s = opaque;
- uint32_t val = -1;
- pcnet_poll_timer(s);
- if (!BCR_DWIO(s)) {
- switch (addr & 0x0f) {
- case 0x00: /* RDP */
- val = pcnet_csr_readw(s, s->rap);
- break;
- case 0x02:
- val = s->rap;
- break;
- case 0x04:
- pcnet_s_reset(s);
- val = 0;
- break;
- case 0x06:
- val = pcnet_bcr_readw(s, s->rap);
- break;
- }
- }
- pcnet_update_irq(s);
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
-#endif
- return val;
-}
-
-static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- PCNetState *s = opaque;
- pcnet_poll_timer(s);
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
-#endif
- if (BCR_DWIO(s)) {
- switch (addr & 0x0f) {
- case 0x00: /* RDP */
- pcnet_csr_writew(s, s->rap, val & 0xffff);
- break;
- case 0x04:
- s->rap = val & 0x7f;
- break;
- case 0x0c:
- pcnet_bcr_writew(s, s->rap, val & 0xffff);
- break;
- }
- } else
- if ((addr & 0x0f) == 0) {
- /* switch device to dword i/o mode */
- pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
-#ifdef PCNET_DEBUG_IO
- printf("device switched into dword i/o mode\n");
-#endif
- }
- pcnet_update_irq(s);
-}
-
-static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
-{
- PCNetState *s = opaque;
- uint32_t val = -1;
- pcnet_poll_timer(s);
- if (BCR_DWIO(s)) {
- switch (addr & 0x0f) {
- case 0x00: /* RDP */
- val = pcnet_csr_readw(s, s->rap);
- break;
- case 0x04:
- val = s->rap;
- break;
- case 0x08:
- pcnet_s_reset(s);
- val = 0;
- break;
- case 0x0c:
- val = pcnet_bcr_readw(s, s->rap);
- break;
- }
- }
- pcnet_update_irq(s);
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
-#endif
- return val;
-}
-
-static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCNetState *d = (PCNetState *)pci_dev;
-
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
-#endif
-
- register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
- register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
-
- register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
- register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
- register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
- register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
-}
-
-static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PCNetState *d = opaque;
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
-#endif
- if (!(addr & 0x10))
- pcnet_aprom_writeb(d, addr & 0x0f, val);
-}
-
-static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
-{
- PCNetState *d = opaque;
- uint32_t val = -1;
- if (!(addr & 0x10))
- val = pcnet_aprom_readb(d, addr & 0x0f);
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
-#endif
- return val;
-}
-
-static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PCNetState *d = opaque;
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
-#endif
- if (addr & 0x10)
- pcnet_ioport_writew(d, addr & 0x0f, val);
- else {
- addr &= 0x0f;
- pcnet_aprom_writeb(d, addr, val & 0xff);
- pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
- }
-}
-
-static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
- PCNetState *d = opaque;
- uint32_t val = -1;
- if (addr & 0x10)
- val = pcnet_ioport_readw(d, addr & 0x0f);
- else {
- addr &= 0x0f;
- val = pcnet_aprom_readb(d, addr+1);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr);
- }
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
-#endif
- return val;
-}
-
-static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PCNetState *d = opaque;
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
-#endif
- if (addr & 0x10)
- pcnet_ioport_writel(d, addr & 0x0f, val);
- else {
- addr &= 0x0f;
- pcnet_aprom_writeb(d, addr, val & 0xff);
- pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
- pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
- pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
- }
-}
-
-static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
- PCNetState *d = opaque;
- uint32_t val;
- if (addr & 0x10)
- val = pcnet_ioport_readl(d, addr & 0x0f);
- else {
- addr &= 0x0f;
- val = pcnet_aprom_readb(d, addr+3);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr+2);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr+1);
- val <<= 8;
- val |= pcnet_aprom_readb(d, addr);
- }
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
-#endif
- return val;
-}
-
-
-static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
- (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
- (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
- (CPUWriteMemoryFunc *)&pcnet_mmio_writel
-};
-
-static CPUReadMemoryFunc *pcnet_mmio_read[] = {
- (CPUReadMemoryFunc *)&pcnet_mmio_readb,
- (CPUReadMemoryFunc *)&pcnet_mmio_readw,
- (CPUReadMemoryFunc *)&pcnet_mmio_readl
-};
-
-static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCNetState *d = (PCNetState *)pci_dev;
-
-#ifdef PCNET_DEBUG_IO
- printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
-#endif
-
- cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
-}
-
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
-{
- PCNetState *d;
- uint8_t *pci_conf;
-
-#if 0
- printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
- sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
-#endif
-
- d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
- -1, NULL, NULL);
-
- pci_conf = d->dev.config;
-
- *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
- *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);
- *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007);
- *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
- pci_conf[0x08] = 0x10;
- pci_conf[0x09] = 0x00;
- pci_conf[0x0a] = 0x00; // ethernet network controller
- pci_conf[0x0b] = 0x02;
- pci_conf[0x0e] = 0x00; // header_type
-
- *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
- *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
-
- pci_conf[0x3d] = 1; // interrupt pin 0
- pci_conf[0x3e] = 0x06;
- pci_conf[0x3f] = 0xff;
-
- /* Handler for memory-mapped I/O */
- d->mmio_io_addr =
- cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
-
- pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
- PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
-
- pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
- PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
-
- d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
-
- d->nd = nd;
-
- d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
- pcnet_can_receive, d);
-
- snprintf(d->vc->info_str, sizeof(d->vc->info_str),
- "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
- d->nd->macaddr[0],
- d->nd->macaddr[1],
- d->nd->macaddr[2],
- d->nd->macaddr[3],
- d->nd->macaddr[4],
- d->nd->macaddr[5]);
-
- pcnet_h_reset(d);
-}
diff --git a/hw/pcspk.c b/hw/pcspk.c
deleted file mode 100644
index 0d52b31..0000000
--- a/hw/pcspk.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * QEMU PC speaker emulation
- *
- * Copyright (c) 2006 Joachim Henke
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "vl.h"
-
-#define PCSPK_BUF_LEN 1792
-#define PCSPK_SAMPLE_RATE 32000
-#define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
-#define PCSPK_MIN_COUNT ((PIT_FREQ + PCSPK_MAX_FREQ - 1) / PCSPK_MAX_FREQ)
-
-typedef struct {
- uint8_t sample_buf[PCSPK_BUF_LEN];
- QEMUSoundCard card;
- SWVoiceOut *voice;
- PITState *pit;
- unsigned int pit_count;
- unsigned int samples;
- unsigned int play_pos;
- int data_on;
- int dummy_refresh_clock;
-} PCSpkState;
-
-static const char *s_spk = "pcspk";
-static PCSpkState pcspk_state;
-
-static inline void generate_samples(PCSpkState *s)
-{
- unsigned int i;
-
- if (s->pit_count) {
- const uint32_t m = PCSPK_SAMPLE_RATE * s->pit_count;
- const uint32_t n = ((uint64_t)PIT_FREQ << 32) / m;
-
- /* multiple of wavelength for gapless looping */
- s->samples = (PCSPK_BUF_LEN * PIT_FREQ / m * m / (PIT_FREQ >> 1) + 1) >> 1;
- for (i = 0; i < s->samples; ++i)
- s->sample_buf[i] = (64 & (n * i >> 25)) - 32;
- } else {
- s->samples = PCSPK_BUF_LEN;
- for (i = 0; i < PCSPK_BUF_LEN; ++i)
- s->sample_buf[i] = 128; /* silence */
- }
-}
-
-static void pcspk_callback(void *opaque, int free)
-{
- PCSpkState *s = opaque;
- unsigned int n;
-
- if (pit_get_mode(s->pit, 2) != 3)
- return;
-
- n = pit_get_initial_count(s->pit, 2);
- /* avoid frequencies that are not reproducible with sample rate */
- if (n < PCSPK_MIN_COUNT)
- n = 0;
-
- if (s->pit_count != n) {
- s->pit_count = n;
- s->play_pos = 0;
- generate_samples(s);
- }
-
- while (free > 0) {
- n = audio_MIN(s->samples - s->play_pos, (unsigned int)free);
- n = AUD_write(s->voice, &s->sample_buf[s->play_pos], n);
- if (!n)
- break;
- s->play_pos = (s->play_pos + n) % s->samples;
- free -= n;
- }
-}
-
-int pcspk_audio_init(AudioState *audio)
-{
- PCSpkState *s = &pcspk_state;
- audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};
-
- if (!audio) {
- AUD_log(s_spk, "No audio state\n");
- return -1;
- }
- AUD_register_card(audio, s_spk, &s->card);
-
- s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
- if (!s->voice) {
- AUD_log(s_spk, "Could not open voice\n");
- return -1;
- }
-
- return 0;
-}
-
-static uint32_t pcspk_ioport_read(void *opaque, uint32_t addr)
-{
- PCSpkState *s = opaque;
- int out;
-
- s->dummy_refresh_clock ^= (1 << 4);
- out = pit_get_out(s->pit, 2, qemu_get_clock(vm_clock)) << 5;
-
- return pit_get_gate(s->pit, 2) | (s->data_on << 1) | s->dummy_refresh_clock | out;
-}
-
-static void pcspk_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- PCSpkState *s = opaque;
- const int gate = val & 1;
-
- s->data_on = (val >> 1) & 1;
- pit_set_gate(s->pit, 2, gate);
- if (s->voice) {
- if (gate) /* restart */
- s->play_pos = 0;
- AUD_set_active_out(s->voice, gate & s->data_on);
- }
-}
-
-void pcspk_init(PITState *pit)
-{
- PCSpkState *s = &pcspk_state;
-
- s->pit = pit;
- register_ioport_read(0x61, 1, 1, pcspk_ioport_read, s);
- register_ioport_write(0x61, 1, 1, pcspk_ioport_write, s);
-}
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
deleted file mode 100644
index ee2f63a..0000000
--- a/hw/pflash_cfi02.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * CFI parallel flash with AMD command set emulation
- *
- * Copyright (c) 2005 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * For now, this code can emulate flashes of 1, 2 or 4 bytes width.
- * Supported commands/modes are:
- * - flash read
- * - flash write
- * - flash ID read
- * - sector erase
- * - chip erase
- * - unlock bypass command
- * - CFI queries
- *
- * It does not support flash interleaving.
- * It does not implement boot blocs with reduced size
- * It does not implement software data protection as found in many real chips
- * It does not implement erase suspend/resume commands
- * It does not implement multiple sectors erase
- */
-
-#include "vl.h"
-
-//#define PFLASH_DEBUG
-#ifdef PFLASH_DEBUG
-#define DPRINTF(fmt, args...) \
-do { \
- printf("PFLASH: " fmt , ##args); \
-} while (0)
-#else
-#define DPRINTF(fmt, args...) do { } while (0)
-#endif
-
-struct pflash_t {
- BlockDriverState *bs;
- target_ulong base;
- target_ulong sector_len;
- target_ulong total_len;
- int width;
- int wcycle; /* if 0, the flash is read normally */
- int bypass;
- int ro;
- uint8_t cmd;
- uint8_t status;
- uint16_t ident[4];
- uint8_t cfi_len;
- uint8_t cfi_table[0x52];
- QEMUTimer *timer;
- ram_addr_t off;
- int fl_mem;
- void *storage;
-};
-
-static void pflash_timer (void *opaque)
-{
- pflash_t *pfl = opaque;
-
- DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
- /* Reset flash */
- pfl->status ^= 0x80;
- if (pfl->bypass) {
- pfl->wcycle = 2;
- } else {
- cpu_register_physical_memory(pfl->base, pfl->total_len,
- pfl->off | IO_MEM_ROMD | pfl->fl_mem);
- pfl->wcycle = 0;
- }
- pfl->cmd = 0;
-}
-
-static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width)
-{
- target_ulong boff;
- uint32_t ret;
- uint8_t *p;
-
- DPRINTF("%s: offset %08x\n", __func__, offset);
- ret = -1;
- offset -= pfl->base;
- boff = offset & 0xFF;
- if (pfl->width == 2)
- boff = boff >> 1;
- else if (pfl->width == 4)
- boff = boff >> 2;
- switch (pfl->cmd) {
- default:
- /* This should never happen : reset state & treat it as a read*/
- DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
- pfl->wcycle = 0;
- pfl->cmd = 0;
- case 0x80:
- /* We accept reads during second unlock sequence... */
- case 0x00:
- flash_read:
- /* Flash area read */
- p = pfl->storage;
- switch (width) {
- case 1:
- ret = p[offset];
-// DPRINTF("%s: data offset %08x %02x\n", __func__, offset, ret);
- break;
- case 2:
-#if defined(TARGET_WORDS_BIGENDIAN)
- ret = p[offset] << 8;
- ret |= p[offset + 1];
-#else
- ret = p[offset];
- ret |= p[offset + 1] << 8;
-#endif
-// DPRINTF("%s: data offset %08x %04x\n", __func__, offset, ret);
- break;
- case 4:
-#if defined(TARGET_WORDS_BIGENDIAN)
- ret = p[offset] << 24;
- ret |= p[offset + 1] << 16;
- ret |= p[offset + 2] << 8;
- ret |= p[offset + 3];
-#else
- ret = p[offset];
- ret |= p[offset + 1] << 8;
- ret |= p[offset + 1] << 8;
- ret |= p[offset + 2] << 16;
- ret |= p[offset + 3] << 24;
-#endif
-// DPRINTF("%s: data offset %08x %08x\n", __func__, offset, ret);
- break;
- }
- break;
- case 0x90:
- /* flash ID read */
- switch (boff) {
- case 0x00:
- case 0x01:
- ret = pfl->ident[boff & 0x01];
- break;
- case 0x02:
- ret = 0x00; /* Pretend all sectors are unprotected */
- break;
- case 0x0E:
- case 0x0F:
- if (pfl->ident[2 + (boff & 0x01)] == (uint8_t)-1)
- goto flash_read;
- ret = pfl->ident[2 + (boff & 0x01)];
- break;
- default:
- goto flash_read;
- }
- DPRINTF("%s: ID %d %x\n", __func__, boff, ret);
- break;
- case 0xA0:
- case 0x10:
- case 0x30:
- /* Status register read */
- ret = pfl->status;
- DPRINTF("%s: status %x\n", __func__, ret);
- /* Toggle bit 6 */
- pfl->status ^= 0x40;
- break;
- case 0x98:
- /* CFI query mode */
- if (boff > pfl->cfi_len)
- ret = 0;
- else
- ret = pfl->cfi_table[boff];
- break;
- }
-
- return ret;
-}
-
-/* update flash content on disk */
-static void pflash_update(pflash_t *pfl, int offset,
- int size)
-{
- int offset_end;
- if (pfl->bs) {
- offset_end = offset + size;
- /* round to sectors */
- offset = offset >> 9;
- offset_end = (offset_end + 511) >> 9;
- bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),
- offset_end - offset);
- }
-}
-
-static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value,
- int width)
-{
- target_ulong boff;
- uint8_t *p;
- uint8_t cmd;
-
- /* WARNING: when the memory area is in ROMD mode, the offset is a
- ram offset, not a physical address */
- if (pfl->wcycle == 0)
- offset -= (target_ulong)(long)pfl->storage;
- else
- offset -= pfl->base;
-
- cmd = value;
- DPRINTF("%s: offset %08x %08x %d\n", __func__, offset, value, width);
- if (pfl->cmd != 0xA0 && cmd == 0xF0) {
- DPRINTF("%s: flash reset asked (%02x %02x)\n",
- __func__, pfl->cmd, cmd);
- goto reset_flash;
- }
- /* Set the device in I/O access mode */
- cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
- boff = offset & (pfl->sector_len - 1);
- if (pfl->width == 2)
- boff = boff >> 1;
- else if (pfl->width == 4)
- boff = boff >> 2;
- switch (pfl->wcycle) {
- case 0:
- /* We're in read mode */
- check_unlock0:
- if (boff == 0x55 && cmd == 0x98) {
- enter_CFI_mode:
- /* Enter CFI query mode */
- pfl->wcycle = 7;
- pfl->cmd = 0x98;
- return;
- }
- if (boff != 0x555 || cmd != 0xAA) {
- DPRINTF("%s: unlock0 failed %04x %02x %04x\n",
- __func__, boff, cmd, 0x555);
- goto reset_flash;
- }
- DPRINTF("%s: unlock sequence started\n", __func__);
- break;
- case 1:
- /* We started an unlock sequence */
- check_unlock1:
- if (boff != 0x2AA || cmd != 0x55) {
- DPRINTF("%s: unlock1 failed %04x %02x\n", __func__, boff, cmd);
- goto reset_flash;
- }
- DPRINTF("%s: unlock sequence done\n", __func__);
- break;
- case 2:
- /* We finished an unlock sequence */
- if (!pfl->bypass && boff != 0x555) {
- DPRINTF("%s: command failed %04x %02x\n", __func__, boff, cmd);
- goto reset_flash;
- }
- switch (cmd) {
- case 0x20:
- pfl->bypass = 1;
- goto do_bypass;
- case 0x80:
- case 0x90:
- case 0xA0:
- pfl->cmd = cmd;
- DPRINTF("%s: starting command %02x\n", __func__, cmd);
- break;
- default:
- DPRINTF("%s: unknown command %02x\n", __func__, cmd);
- goto reset_flash;
- }
- break;
- case 3:
- switch (pfl->cmd) {
- case 0x80:
- /* We need another unlock sequence */
- goto check_unlock0;
- case 0xA0:
- DPRINTF("%s: write data offset %08x %08x %d\n",
- __func__, offset, value, width);
- p = pfl->storage;
- switch (width) {
- case 1:
- p[offset] &= value;
- pflash_update(pfl, offset, 1);
- break;
- case 2:
-#if defined(TARGET_WORDS_BIGENDIAN)
- p[offset] &= value >> 8;
- p[offset + 1] &= value;
-#else
- p[offset] &= value;
- p[offset + 1] &= value >> 8;
-#endif
- pflash_update(pfl, offset, 2);
- break;
- case 4:
-#if defined(TARGET_WORDS_BIGENDIAN)
- p[offset] &= value >> 24;
- p[offset + 1] &= value >> 16;
- p[offset + 2] &= value >> 8;
- p[offset + 3] &= value;
-#else
- p[offset] &= value;
- p[offset + 1] &= value >> 8;
- p[offset + 2] &= value >> 16;
- p[offset + 3] &= value >> 24;
-#endif
- pflash_update(pfl, offset, 4);
- break;
- }
- pfl->status = 0x00 | ~(value & 0x80);
- /* Let's pretend write is immediate */
- if (pfl->bypass)
- goto do_bypass;
- goto reset_flash;
- case 0x90:
- if (pfl->bypass && cmd == 0x00) {
- /* Unlock bypass reset */
- goto reset_flash;
- }
- /* We can enter CFI query mode from autoselect mode */
- if (boff == 0x55 && cmd == 0x98)
- goto enter_CFI_mode;
- /* No break here */
- default:
- DPRINTF("%s: invalid write for command %02x\n",
- __func__, pfl->cmd);
- goto reset_flash;
- }
- case 4:
- switch (pfl->cmd) {
- case 0xA0:
- /* Ignore writes while flash data write is occuring */
- /* As we suppose write is immediate, this should never happen */
- return;
- case 0x80:
- goto check_unlock1;
- default:
- /* Should never happen */
- DPRINTF("%s: invalid command state %02x (wc 4)\n",
- __func__, pfl->cmd);
- goto reset_flash;
- }
- break;
- case 5:
- switch (cmd) {
- case 0x10:
- if (boff != 0x555) {
- DPRINTF("%s: chip erase: invalid address %04x\n",
- __func__, offset);
- goto reset_flash;
- }
- /* Chip erase */
- DPRINTF("%s: start chip erase\n", __func__);
- memset(pfl->storage, 0xFF, pfl->total_len);
- pfl->status = 0x00;
- pflash_update(pfl, 0, pfl->total_len);
- /* Let's wait 5 seconds before chip erase is done */
- qemu_mod_timer(pfl->timer,
- qemu_get_clock(vm_clock) + (ticks_per_sec * 5));
- break;
- case 0x30:
- /* Sector erase */
- p = pfl->storage;
- offset &= ~(pfl->sector_len - 1);
- DPRINTF("%s: start sector erase at %08x\n", __func__, offset);
- memset(p + offset, 0xFF, pfl->sector_len);
- pflash_update(pfl, offset, pfl->sector_len);
- pfl->status = 0x00;
- /* Let's wait 1/2 second before sector erase is done */
- qemu_mod_timer(pfl->timer,
- qemu_get_clock(vm_clock) + (ticks_per_sec / 2));
- break;
- default:
- DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd);
- goto reset_flash;
- }
- pfl->cmd = cmd;
- break;
- case 6:
- switch (pfl->cmd) {
- case 0x10:
- /* Ignore writes during chip erase */
- return;
- case 0x30:
- /* Ignore writes during sector erase */
- return;
- default:
- /* Should never happen */
- DPRINTF("%s: invalid command state %02x (wc 6)\n",
- __func__, pfl->cmd);
- goto reset_flash;
- }
- break;
- case 7: /* Special value for CFI queries */
- DPRINTF("%s: invalid write in CFI query mode\n", __func__);
- goto reset_flash;
- default:
- /* Should never happen */
- DPRINTF("%s: invalid write state (wc 7)\n", __func__);
- goto reset_flash;
- }
- pfl->wcycle++;
-
- return;
-
- /* Reset flash */
- reset_flash:
- if (pfl->wcycle != 0) {
- cpu_register_physical_memory(pfl->base, pfl->total_len,
- pfl->off | IO_MEM_ROMD | pfl->fl_mem);
- }
- pfl->bypass = 0;
- pfl->wcycle = 0;
- pfl->cmd = 0;
- return;
-
- do_bypass:
- pfl->wcycle = 2;
- pfl->cmd = 0;
- return;
-}
-
-
-static uint32_t pflash_readb (void *opaque, target_phys_addr_t addr)
-{
- return pflash_read(opaque, addr, 1);
-}
-
-static uint32_t pflash_readw (void *opaque, target_phys_addr_t addr)
-{
- pflash_t *pfl = opaque;
-
- return pflash_read(pfl, addr, 2);
-}
-
-static uint32_t pflash_readl (void *opaque, target_phys_addr_t addr)
-{
- pflash_t *pfl = opaque;
-
- return pflash_read(pfl, addr, 4);
-}
-
-static void pflash_writeb (void *opaque, target_phys_addr_t addr,
- uint32_t value)
-{
- pflash_write(opaque, addr, value, 1);
-}
-
-static void pflash_writew (void *opaque, target_phys_addr_t addr,
- uint32_t value)
-{
- pflash_t *pfl = opaque;
-
- pflash_write(pfl, addr, value, 2);
-}
-
-static void pflash_writel (void *opaque, target_phys_addr_t addr,
- uint32_t value)
-{
- pflash_t *pfl = opaque;
-
- pflash_write(pfl, addr, value, 4);
-}
-
-static CPUWriteMemoryFunc *pflash_write_ops[] = {
- &pflash_writeb,
- &pflash_writew,
- &pflash_writel,
-};
-
-static CPUReadMemoryFunc *pflash_read_ops[] = {
- &pflash_readb,
- &pflash_readw,
- &pflash_readl,
-};
-
-/* Count trailing zeroes of a 32 bits quantity */
-static int ctz32 (uint32_t n)
-{
- int ret;
-
- ret = 0;
- if (!(n & 0xFFFF)) {
- ret += 16;
- n = n >> 16;
- }
- if (!(n & 0xFF)) {
- ret += 8;
- n = n >> 8;
- }
- if (!(n & 0xF)) {
- ret += 4;
- n = n >> 4;
- }
- if (!(n & 0x3)) {
- ret += 2;
- n = n >> 2;
- }
- if (!(n & 0x1)) {
- ret++;
- n = n >> 1;
- }
-#if 0 /* This is not necessary as n is never 0 */
- if (!n)
- ret++;
-#endif
-
- return ret;
-}
-
-pflash_t *pflash_register (target_ulong base, ram_addr_t off,
- BlockDriverState *bs,
- target_ulong sector_len, int nb_blocs, int width,
- uint16_t id0, uint16_t id1,
- uint16_t id2, uint16_t id3)
-{
- pflash_t *pfl;
- target_long total_len;
-
- total_len = sector_len * nb_blocs;
- /* XXX: to be fixed */
- if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
- total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
- return NULL;
- pfl = qemu_mallocz(sizeof(pflash_t));
- if (pfl == NULL)
- return NULL;
- pfl->storage = phys_ram_base + off;
- pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops, pfl);
- pfl->off = off;
- cpu_register_physical_memory(base, total_len,
- off | pfl->fl_mem | IO_MEM_ROMD);
- pfl->bs = bs;
- if (pfl->bs) {
- /* read the initial flash content */
- bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
- }
-#if 0 /* XXX: there should be a bit to set up read-only,
- * the same way the hardware does (with WP pin).
- */
- pfl->ro = 1;
-#else
- pfl->ro = 0;
-#endif
- pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
- pfl->base = base;
- pfl->sector_len = sector_len;
- pfl->total_len = total_len;
- pfl->width = width;
- pfl->wcycle = 0;
- pfl->cmd = 0;
- pfl->status = 0;
- pfl->ident[0] = id0;
- pfl->ident[1] = id1;
- pfl->ident[2] = id2;
- pfl->ident[3] = id3;
- /* Hardcoded CFI table (mostly from SG29 Spansion flash) */
- pfl->cfi_len = 0x52;
- /* Standard "QRY" string */
- pfl->cfi_table[0x10] = 'Q';
- pfl->cfi_table[0x11] = 'R';
- pfl->cfi_table[0x12] = 'Y';
- /* Command set (AMD/Fujitsu) */
- pfl->cfi_table[0x13] = 0x02;
- pfl->cfi_table[0x14] = 0x00;
- /* Primary extended table address (none) */
- pfl->cfi_table[0x15] = 0x00;
- pfl->cfi_table[0x16] = 0x00;
- /* Alternate command set (none) */
- pfl->cfi_table[0x17] = 0x00;
- pfl->cfi_table[0x18] = 0x00;
- /* Alternate extended table (none) */
- pfl->cfi_table[0x19] = 0x00;
- pfl->cfi_table[0x1A] = 0x00;
- /* Vcc min */
- pfl->cfi_table[0x1B] = 0x27;
- /* Vcc max */
- pfl->cfi_table[0x1C] = 0x36;
- /* Vpp min (no Vpp pin) */
- pfl->cfi_table[0x1D] = 0x00;
- /* Vpp max (no Vpp pin) */
- pfl->cfi_table[0x1E] = 0x00;
- /* Reserved */
- pfl->cfi_table[0x1F] = 0x07;
- /* Timeout for min size buffer write (16 µs) */
- pfl->cfi_table[0x20] = 0x04;
- /* Typical timeout for block erase (512 ms) */
- pfl->cfi_table[0x21] = 0x09;
- /* Typical timeout for full chip erase (4096 ms) */
- pfl->cfi_table[0x22] = 0x0C;
- /* Reserved */
- pfl->cfi_table[0x23] = 0x01;
- /* Max timeout for buffer write */
- pfl->cfi_table[0x24] = 0x04;
- /* Max timeout for block erase */
- pfl->cfi_table[0x25] = 0x0A;
- /* Max timeout for chip erase */
- pfl->cfi_table[0x26] = 0x0D;
- /* Device size */
- pfl->cfi_table[0x27] = ctz32(total_len) + 1;
- /* Flash device interface (8 & 16 bits) */
- pfl->cfi_table[0x28] = 0x02;
- pfl->cfi_table[0x29] = 0x00;
- /* Max number of bytes in multi-bytes write */
- pfl->cfi_table[0x2A] = 0x05;
- pfl->cfi_table[0x2B] = 0x00;
- /* Number of erase block regions (uniform) */
- pfl->cfi_table[0x2C] = 0x01;
- /* Erase block region 1 */
- pfl->cfi_table[0x2D] = nb_blocs - 1;
- pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
- pfl->cfi_table[0x2F] = sector_len >> 8;
- pfl->cfi_table[0x30] = sector_len >> 16;
-
- return pfl;
-}
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
deleted file mode 100644
index 1f7ad94..0000000
--- a/hw/piix_pci.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * QEMU i440FX/PIIX3 PCI Bridge Emulation
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "vl.h"
-typedef uint32_t pci_addr_t;
-#include "pci_host.h"
-
-typedef PCIHostState I440FXState;
-
-static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
-{
- I440FXState *s = opaque;
- s->config_reg = val;
-}
-
-static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
-{
- I440FXState *s = opaque;
- return s->config_reg;
-}
-
-static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level);
-
-PCIBus *i440fx_init(void)
-{
- PCIBus *b;
- PCIDevice *d;
- I440FXState *s;
-
- s = qemu_mallocz(sizeof(I440FXState));
- b = pci_register_bus(piix3_set_irq, NULL, 0);
- s->bus = b;
-
- register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
- register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
-
- register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
- register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
- register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
- register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
- register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
- register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
-
- d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
- NULL, NULL);
-
- d->config[0x00] = 0x86; // vendor_id
- d->config[0x01] = 0x80;
- d->config[0x02] = 0x37; // device_id
- d->config[0x03] = 0x12;
- d->config[0x08] = 0x02; // revision
- d->config[0x0a] = 0x00; // class_sub = host2pci
- d->config[0x0b] = 0x06; // class_base = PCI_bridge
- d->config[0x0e] = 0x00; // header_type
- return b;
-}
-
-/* PIIX3 PCI to ISA bridge */
-
-static PCIDevice *piix3_dev;
-
-/* just used for simpler irq handling. */
-#define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
-
-static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
-
-/* return the global irq number corresponding to a given device irq
- pin. We could also use the bus number to have a more precise
- mapping. */
-static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
- int slot_addend;
- slot_addend = (pci_dev->devfn >> 3) - 1;
- return (irq_num + slot_addend) & 3;
-}
-
-static inline int get_pci_irq_level(int irq_num)
-{
- int pic_level;
-#if (PCI_IRQ_WORDS == 2)
- pic_level = ((pci_irq_levels[irq_num][0] |
- pci_irq_levels[irq_num][1]) != 0);
-#else
- {
- int i;
- pic_level = 0;
- for(i = 0; i < PCI_IRQ_WORDS; i++) {
- if (pci_irq_levels[irq_num][i]) {
- pic_level = 1;
- break;
- }
- }
- }
-#endif
- return pic_level;
-}
-
-static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level)
-{
- int irq_index, shift, pic_irq, pic_level;
- uint32_t *p;
-
- irq_num = pci_slot_get_pirq(pci_dev, irq_num);
- irq_index = pci_dev->irq_index;
- p = &pci_irq_levels[irq_num][irq_index >> 5];
- shift = (irq_index & 0x1f);
- *p = (*p & ~(1 << shift)) | (level << shift);
-
- /* now we change the pic irq level according to the piix irq mappings */
- /* XXX: optimize */
- pic_irq = piix3_dev->config[0x60 + irq_num];
- if (pic_irq < 16) {
- /* the pic level is the logical OR of all the PCI irqs mapped
- to it */
- pic_level = 0;
- if (pic_irq == piix3_dev->config[0x60])
- pic_level |= get_pci_irq_level(0);
- if (pic_irq == piix3_dev->config[0x61])
- pic_level |= get_pci_irq_level(1);
- if (pic_irq == piix3_dev->config[0x62])
- pic_level |= get_pci_irq_level(2);
- if (pic_irq == piix3_dev->config[0x63])
- pic_level |= get_pci_irq_level(3);
- pic_set_irq(pic_irq, pic_level);
- }
-}
-
-static void piix3_reset(PCIDevice *d)
-{
- uint8_t *pci_conf = d->config;
-
- pci_conf[0x04] = 0x07; // master, memory and I/O
- pci_conf[0x05] = 0x00;
- pci_conf[0x06] = 0x00;
- pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
- pci_conf[0x4c] = 0x4d;
- pci_conf[0x4e] = 0x03;
- pci_conf[0x4f] = 0x00;
- pci_conf[0x60] = 0x80;
- pci_conf[0x69] = 0x02;
- pci_conf[0x70] = 0x80;
- pci_conf[0x76] = 0x0c;
- pci_conf[0x77] = 0x0c;
- pci_conf[0x78] = 0x02;
- pci_conf[0x79] = 0x00;
- pci_conf[0x80] = 0x00;
- pci_conf[0x82] = 0x00;
- pci_conf[0xa0] = 0x08;
- pci_conf[0xa0] = 0x08;
- pci_conf[0xa2] = 0x00;
- pci_conf[0xa3] = 0x00;
- pci_conf[0xa4] = 0x00;
- pci_conf[0xa5] = 0x00;
- pci_conf[0xa6] = 0x00;
- pci_conf[0xa7] = 0x00;
- pci_conf[0xa8] = 0x0f;
- pci_conf[0xaa] = 0x00;
- pci_conf[0xab] = 0x00;
- pci_conf[0xac] = 0x00;
- pci_conf[0xae] = 0x00;
-}
-
-int piix3_init(PCIBus *bus)
-{
- PCIDevice *d;
- uint8_t *pci_conf;
-
- d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
- -1, NULL, NULL);
- register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
-
- piix3_dev = d;
- pci_conf = d->config;
-
- pci_conf[0x00] = 0x86; // Intel
- pci_conf[0x01] = 0x80;
- pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
- pci_conf[0x03] = 0x70;
- pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
- pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
- pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
-
- piix3_reset(d);
- return d->devfn;
-}
-
-/***********************************************************/
-/* XXX: the following should be moved to the PC BIOS */
-
-static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
-{
- return cpu_inb(NULL, addr);
-}
-
-static void isa_outb(uint32_t val, uint32_t addr)
-{
- cpu_outb(NULL, addr, val);
-}
-
-static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
-{
- return cpu_inw(NULL, addr);
-}
-
-static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
-{
- cpu_outw(NULL, addr, val);
-}
-
-static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
-{
- return cpu_inl(NULL, addr);
-}
-
-static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
-{
- cpu_outl(NULL, addr, val);
-}
-
-static uint32_t pci_bios_io_addr;
-static uint32_t pci_bios_mem_addr;
-/* host irqs corresponding to PCI irqs A-D */
-static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
-
-static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
-{
- PCIBus *s = d->bus;
- addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
- pci_data_write(s, addr, val, 4);
-}
-
-static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
-{
- PCIBus *s = d->bus;
- addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
- pci_data_write(s, addr, val, 2);
-}
-
-static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
-{
- PCIBus *s = d->bus;
- addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
- pci_data_write(s, addr, val, 1);
-}
-
-static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
-{
- PCIBus *s = d->bus;
- addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
- return pci_data_read(s, addr, 4);
-}
-
-static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
-{
- PCIBus *s = d->bus;
- addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
- return pci_data_read(s, addr, 2);
-}
-
-static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
-{
- PCIBus *s = d->bus;
- addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
- return pci_data_read(s, addr, 1);
-}
-
-static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
-{
- PCIIORegion *r;
- uint16_t cmd;
- uint32_t ofs;
-
- if ( region_num == PCI_ROM_SLOT ) {
- ofs = 0x30;
- }else{
- ofs = 0x10 + region_num * 4;
- }
-
- pci_config_writel(d, ofs, addr);
- r = &d->io_regions[region_num];
-
- /* enable memory mappings */
- cmd = pci_config_readw(d, PCI_COMMAND);
- if ( region_num == PCI_ROM_SLOT )
- cmd |= 2;
- else if (r->type & PCI_ADDRESS_SPACE_IO)
- cmd |= 1;
- else
- cmd |= 2;
- pci_config_writew(d, PCI_COMMAND, cmd);
-}
-
-static void pci_bios_init_device(PCIDevice *d)
-{
- int class;
- PCIIORegion *r;
- uint32_t *paddr;
- int i, pin, pic_irq, vendor_id, device_id;
-
- class = pci_config_readw(d, PCI_CLASS_DEVICE);
- vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
- device_id = pci_config_readw(d, PCI_DEVICE_ID);
- switch(class) {
- case 0x0101:
- if (vendor_id == 0x8086 && device_id == 0x7010) {
- /* PIIX3 IDE */
- pci_config_writew(d, 0x40, 0x8000); // enable IDE0
- pci_config_writew(d, 0x42, 0x8000); // enable IDE1
- goto default_map;
- } else {
- /* IDE: we map it as in ISA mode */
- pci_set_io_region_addr(d, 0, 0x1f0);
- pci_set_io_region_addr(d, 1, 0x3f4);
- pci_set_io_region_addr(d, 2, 0x170);
- pci_set_io_region_addr(d, 3, 0x374);
- }
- break;
- case 0x0300:
- if (vendor_id != 0x1234)
- goto default_map;
- /* VGA: map frame buffer to default Bochs VBE address */
- pci_set_io_region_addr(d, 0, 0xE0000000);
- break;
- case 0x0800:
- /* PIC */
- vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
- device_id = pci_config_readw(d, PCI_DEVICE_ID);
- if (vendor_id == 0x1014) {
- /* IBM */
- if (device_id == 0x0046 || device_id == 0xFFFF) {
- /* MPIC & MPIC2 */
- pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
- }
- }
- break;
- case 0xff00:
- if (vendor_id == 0x0106b &&
- (device_id == 0x0017 || device_id == 0x0022)) {
- /* macio bridge */
- pci_set_io_region_addr(d, 0, 0x80800000);
- }
- break;
- default:
- default_map:
- /* default memory mappings */
- for(i = 0; i < PCI_NUM_REGIONS; i++) {
- r = &d->io_regions[i];
- if (r->size) {
- if (r->type & PCI_ADDRESS_SPACE_IO)
- paddr = &pci_bios_io_addr;
- else
- paddr = &pci_bios_mem_addr;
- *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
- pci_set_io_region_addr(d, i, *paddr);
- *paddr += r->size;
- }
- }
- break;
- }
-
- /* map the interrupt */
- pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
- if (pin != 0) {
- pin = pci_slot_get_pirq(d, pin - 1);
- pic_irq = pci_irqs[pin];
- pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
- }
-}
-
-/*
- * This function initializes the PCI devices as a normal PCI BIOS
- * would do. It is provided just in case the BIOS has no support for
- * PCI.
- */
-void pci_bios_init(void)
-{
- int i, irq;
- uint8_t elcr[2];
-
- pci_bios_io_addr = 0xc000;
- pci_bios_mem_addr = 0xf0000000;
-
- /* activate IRQ mappings */
- elcr[0] = 0x00;
- elcr[1] = 0x00;
- for(i = 0; i < 4; i++) {
- irq = pci_irqs[i];
- /* set to trigger level */
- elcr[irq >> 3] |= (1 << (irq & 7));
- /* activate irq remapping in PIIX */
- pci_config_writeb(piix3_dev, 0x60 + i, irq);
- }
- isa_outb(elcr[0], 0x4d0);
- isa_outb(elcr[1], 0x4d1);
-
- pci_for_each_device(pci_bios_init_device);
-}
-
diff --git a/hw/pl011.c b/hw/pl011.c
deleted file mode 100644
index 657f03b..0000000
--- a/hw/pl011.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Arm PrimeCell PL011 UART
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GPL.
- */
-
-#include "vl.h"
-
-typedef struct {
- uint32_t base;
- uint32_t readbuff;
- uint32_t flags;
- uint32_t lcr;
- uint32_t cr;
- uint32_t dmacr;
- uint32_t int_enabled;
- uint32_t int_level;
- uint32_t read_fifo[16];
- uint32_t ilpr;
- uint32_t ibrd;
- uint32_t fbrd;
- uint32_t ifl;
- int read_pos;
- int read_count;
- int read_trigger;
- CharDriverState *chr;
- void *pic;
- int irq;
-} pl011_state;
-
-#define PL011_INT_TX 0x20
-#define PL011_INT_RX 0x10
-
-#define PL011_FLAG_TXFE 0x80
-#define PL011_FLAG_RXFF 0x40
-#define PL011_FLAG_TXFF 0x20
-#define PL011_FLAG_RXFE 0x10
-
-static const unsigned char pl011_id[] =
-{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
-
-static void pl011_update(pl011_state *s)
-{
- uint32_t flags;
-
- flags = s->int_level & s->int_enabled;
- pic_set_irq_new(s->pic, s->irq, flags != 0);
-}
-
-static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
-{
- pl011_state *s = (pl011_state *)opaque;
- uint32_t c;
-
- offset -= s->base;
- if (offset >= 0xfe0 && offset < 0x1000) {
- return pl011_id[(offset - 0xfe0) >> 2];
- }
- switch (offset >> 2) {
- case 0: /* UARTDR */
- s->flags &= ~PL011_FLAG_RXFF;
- c = s->read_fifo[s->read_pos];
- if (s->read_count > 0) {
- s->read_count--;
- if (++s->read_pos == 16)
- s->read_pos = 0;
- }
- if (s->read_count == 0) {
- s->flags |= PL011_FLAG_RXFE;
- }
- if (s->read_count == s->read_trigger - 1)
- s->int_level &= ~ PL011_INT_RX;
- pl011_update(s);
- return c;
- case 1: /* UARTCR */
- return 0;
- case 6: /* UARTFR */
- return s->flags;
- case 8: /* UARTILPR */
- return s->ilpr;
- case 9: /* UARTIBRD */
- return s->ibrd;
- case 10: /* UARTFBRD */
- return s->fbrd;
- case 11: /* UARTLCR_H */
- return s->lcr;
- case 12: /* UARTCR */
- return s->cr;
- case 13: /* UARTIFLS */
- return s->ifl;
- case 14: /* UARTIMSC */
- return s->int_enabled;
- case 15: /* UARTRIS */
- return s->int_level;
- case 16: /* UARTMIS */
- return s->int_level & s->int_enabled;
- case 18: /* UARTDMACR */
- return s->dmacr;
- default:
- cpu_abort (cpu_single_env, "pl011_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void pl011_set_read_trigger(pl011_state *s)
-{
-#if 0
- /* The docs say the RX interrupt is triggered when the FIFO exceeds
- the threshold. However linux only reads the FIFO in response to an
- interrupt. Triggering the interrupt when the FIFO is non-empty seems
- to make things work. */
- if (s->lcr & 0x10)
- s->read_trigger = (s->ifl >> 1) & 0x1c;
- else
-#endif
- s->read_trigger = 1;
-}
-
-static void pl011_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- pl011_state *s = (pl011_state *)opaque;
- unsigned char ch;
-
- offset -= s->base;
- switch (offset >> 2) {
- case 0: /* UARTDR */
- /* ??? Check if transmitter is enabled. */
- ch = value;
- if (s->chr)
- qemu_chr_write(s->chr, &ch, 1);
- s->int_level |= PL011_INT_TX;
- pl011_update(s);
- break;
- case 1: /* UARTCR */
- s->cr = value;
- break;
- case 8: /* UARTUARTILPR */
- s->ilpr = value;
- break;
- case 9: /* UARTIBRD */
- s->ibrd = value;
- break;
- case 10: /* UARTFBRD */
- s->fbrd = value;
- break;
- case 11: /* UARTLCR_H */
- s->lcr = value;
- pl011_set_read_trigger(s);
- break;
- case 12: /* UARTCR */
- /* ??? Need to implement the enable and loopback bits. */
- s->cr = value;
- break;
- case 13: /* UARTIFS */
- s->ifl = value;
- pl011_set_read_trigger(s);
- break;
- case 14: /* UARTIMSC */
- s->int_enabled = value;
- pl011_update(s);
- break;
- case 17: /* UARTICR */
- s->int_level &= ~value;
- pl011_update(s);
- break;
- case 18: /* UARTDMACR */
- s->dmacr = value;
- if (value & 3)
- cpu_abort(cpu_single_env, "PL011: DMA not implemented\n");
- break;
- default:
- cpu_abort (cpu_single_env, "pl011_write: Bad offset %x\n", offset);
- }
-}
-
-static int pl011_can_recieve(void *opaque)
-{
- pl011_state *s = (pl011_state *)opaque;
-
- if (s->lcr & 0x10)
- return s->read_count < 16;
- else
- return s->read_count < 1;
-}
-
-static void pl011_recieve(void *opaque, const uint8_t *buf, int size)
-{
- pl011_state *s = (pl011_state *)opaque;
- int slot;
-
- slot = s->read_pos + s->read_count;
- if (slot >= 16)
- slot -= 16;
- s->read_fifo[slot] = *buf;
- s->read_count++;
- s->flags &= ~PL011_FLAG_RXFE;
- if (s->cr & 0x10 || s->read_count == 16) {
- s->flags |= PL011_FLAG_RXFF;
- }
- if (s->read_count == s->read_trigger) {
- s->int_level |= PL011_INT_RX;
- pl011_update(s);
- }
-}
-
-static void pl011_event(void *opaque, int event)
-{
- /* ??? Should probably implement break. */
-}
-
-static CPUReadMemoryFunc *pl011_readfn[] = {
- pl011_read,
- pl011_read,
- pl011_read
-};
-
-static CPUWriteMemoryFunc *pl011_writefn[] = {
- pl011_write,
- pl011_write,
- pl011_write
-};
-
-void pl011_init(uint32_t base, void *pic, int irq,
- CharDriverState *chr)
-{
- int iomemtype;
- pl011_state *s;
-
- s = (pl011_state *)qemu_mallocz(sizeof(pl011_state));
- iomemtype = cpu_register_io_memory(0, pl011_readfn,
- pl011_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- s->base = base;
- s->pic = pic;
- s->irq = irq;
- s->chr = chr;
- s->read_trigger = 1;
- s->ifl = 0x12;
- s->cr = 0x300;
- s->flags = 0x90;
- if (chr){
- qemu_chr_add_read_handler(chr, pl011_can_recieve, pl011_recieve, s);
- qemu_chr_add_event_handler(chr, pl011_event);
- }
- /* ??? Save/restore. */
-}
-
diff --git a/hw/pl050.c b/hw/pl050.c
deleted file mode 100644
index 20451e5..0000000
--- a/hw/pl050.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Arm PrimeCell PL050 Keyboard / Mouse Interface
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GPL.
- */
-
-#include "vl.h"
-
-typedef struct {
- void *dev;
- uint32_t base;
- uint32_t cr;
- uint32_t clk;
- uint32_t last;
- void *pic;
- int pending;
- int irq;
- int is_mouse;
-} pl050_state;
-
-static const unsigned char pl050_id[] =
-{ 0x50, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
-
-static void pl050_update(void *opaque, int level)
-{
- pl050_state *s = (pl050_state *)opaque;
- int raise;
-
- s->pending = level;
- raise = (s->pending && (s->cr & 0x10) != 0)
- || (s->cr & 0x08) != 0;
- pic_set_irq_new(s->pic, s->irq, raise);
-}
-
-static uint32_t pl050_read(void *opaque, target_phys_addr_t offset)
-{
- pl050_state *s = (pl050_state *)opaque;
- offset -= s->base;
- if (offset >= 0xfe0 && offset < 0x1000)
- return pl050_id[(offset - 0xfe0) >> 2];
-
- switch (offset >> 2) {
- case 0: /* KMICR */
- return s->cr;
- case 1: /* KMISTAT */
- /* KMIC and KMID bits not implemented. */
- if (s->pending) {
- return 0x10;
- } else {
- return 0;
- }
- case 2: /* KMIDATA */
- if (s->pending)
- s->last = ps2_read_data(s->dev);
- return s->last;
- case 3: /* KMICLKDIV */
- return s->clk;
- case 4: /* KMIIR */
- return s->pending | 2;
- default:
- cpu_abort (cpu_single_env, "pl050_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void pl050_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- pl050_state *s = (pl050_state *)opaque;
- offset -= s->base;
- switch (offset >> 2) {
- case 0: /* KMICR */
- s->cr = value;
- pl050_update(s, s->pending);
- /* ??? Need to implement the enable/disable bit. */
- break;
- case 2: /* KMIDATA */
- /* ??? This should toggle the TX interrupt line. */
- /* ??? This means kbd/mouse can block each other. */
- if (s->is_mouse) {
- ps2_write_mouse(s->dev, value);
- } else {
- ps2_write_keyboard(s->dev, value);
- }
- break;
- case 3: /* KMICLKDIV */
- s->clk = value;
- return;
- default:
- cpu_abort (cpu_single_env, "pl050_write: Bad offset %x\n", offset);
- }
-}
-static CPUReadMemoryFunc *pl050_readfn[] = {
- pl050_read,
- pl050_read,
- pl050_read
-};
-
-static CPUWriteMemoryFunc *pl050_writefn[] = {
- pl050_write,
- pl050_write,
- pl050_write
-};
-
-void pl050_init(uint32_t base, void *pic, int irq, int is_mouse)
-{
- int iomemtype;
- pl050_state *s;
-
- s = (pl050_state *)qemu_mallocz(sizeof(pl050_state));
- iomemtype = cpu_register_io_memory(0, pl050_readfn,
- pl050_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- s->base = base;
- s->pic = pic;
- s->irq = irq;
- s->is_mouse = is_mouse;
- if (is_mouse)
- s->dev = ps2_mouse_init(pl050_update, s);
- else
- s->dev = ps2_kbd_init(pl050_update, s);
- /* ??? Save/restore. */
-}
-
diff --git a/hw/pl080.c b/hw/pl080.c
deleted file mode 100644
index 49996ca..0000000
--- a/hw/pl080.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Arm PrimeCell PL080 DMA controller
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GPL.
- */
-
-#include "vl.h"
-
-#define PL080_NUM_CHANNELS 8
-#define PL080_CONF_E 0x1
-#define PL080_CONF_M1 0x2
-#define PL080_CONF_M2 0x4
-
-#define PL080_CCONF_H 0x40000
-#define PL080_CCONF_A 0x20000
-#define PL080_CCONF_L 0x10000
-#define PL080_CCONF_ITC 0x08000
-#define PL080_CCONF_IE 0x04000
-#define PL080_CCONF_E 0x00001
-
-#define PL080_CCTRL_I 0x80000000
-#define PL080_CCTRL_DI 0x08000000
-#define PL080_CCTRL_SI 0x04000000
-#define PL080_CCTRL_D 0x02000000
-#define PL080_CCTRL_S 0x01000000
-
-typedef struct {
- uint32_t src;
- uint32_t dest;
- uint32_t lli;
- uint32_t ctrl;
- uint32_t conf;
-} pl080_channel;
-
-typedef struct {
- uint32_t base;
- uint8_t tc_int;
- uint8_t tc_mask;
- uint8_t err_int;
- uint8_t err_mask;
- uint32_t conf;
- uint32_t sync;
- uint32_t req_single;
- uint32_t req_burst;
- pl080_channel chan[PL080_NUM_CHANNELS];
- /* Flag to avoid recursive DMA invocations. */
- int running;
- void *pic;
- int irq;
-} pl080_state;
-
-static const unsigned char pl080_id[] =
-{ 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
-
-static void pl080_update(pl080_state *s)
-{
- if ((s->tc_int & s->tc_mask)
- || (s->err_int & s->err_mask))
- pic_set_irq_new(s->pic, s->irq, 1);
- else
- pic_set_irq_new(s->pic, s->irq, 1);
-}
-
-static void pl080_run(pl080_state *s)
-{
- int c;
- int flow;
- pl080_channel *ch;
- int swidth;
- int dwidth;
- int xsize;
- int n;
- int src_id;
- int dest_id;
- int size;
- char buff[4];
- uint32_t req;
-
- s->tc_mask = 0;
- for (c = 0; c < PL080_NUM_CHANNELS; c++) {
- if (s->chan[c].conf & PL080_CCONF_ITC)
- s->tc_mask |= 1 << c;
- if (s->chan[c].conf & PL080_CCONF_IE)
- s->err_mask |= 1 << c;
- }
-
- if ((s->conf & PL080_CONF_E) == 0)
- return;
-
-cpu_abort(cpu_single_env, "DMA active\n");
- /* If we are already in the middle of a DMA operation then indicate that
- there may be new DMA requests and return immediately. */
- if (s->running) {
- s->running++;
- return;
- }
- s->running = 1;
- while (s->running) {
- for (c = 0; c < PL080_NUM_CHANNELS; c++) {
- ch = &s->chan[c];
-again:
- /* Test if thiws channel has any pending DMA requests. */
- if ((ch->conf & (PL080_CCONF_H | PL080_CCONF_E))
- != PL080_CCONF_E)
- continue;
- flow = (ch->conf >> 11) & 7;
- if (flow >= 4) {
- cpu_abort(cpu_single_env,
- "pl080_run: Peripheral flow control not implemented\n");
- }
- src_id = (ch->conf >> 1) & 0x1f;
- dest_id = (ch->conf >> 6) & 0x1f;
- size = ch->ctrl & 0xfff;
- req = s->req_single | s->req_burst;
- switch (flow) {
- case 0:
- break;
- case 1:
- if ((req & (1u << dest_id)) == 0)
- size = 0;
- break;
- case 2:
- if ((req & (1u << src_id)) == 0)
- size = 0;
- break;
- case 3:
- if ((req & (1u << src_id)) == 0
- || (req & (1u << dest_id)) == 0)
- size = 0;
- break;
- }
- if (!size)
- continue;
-
- /* Transfer one element. */
- /* ??? Should transfer multiple elements for a burst request. */
- /* ??? Unclear what the proper behavior is when source and
- destination widths are different. */
- swidth = 1 << ((ch->ctrl >> 18) & 7);
- dwidth = 1 << ((ch->ctrl >> 21) & 7);
- for (n = 0; n < dwidth; n+= swidth) {
- cpu_physical_memory_read(ch->src, buff + n, swidth);
- if (ch->ctrl & PL080_CCTRL_SI)
- ch->src += swidth;
- }
- xsize = (dwidth < swidth) ? swidth : dwidth;
- /* ??? This may pad the value incorrectly for dwidth < 32. */
- for (n = 0; n < xsize; n += dwidth) {
- cpu_physical_memory_write(ch->dest + n, buff + n, dwidth);
- if (ch->ctrl & PL080_CCTRL_DI)
- ch->dest += swidth;
- }
-
- size--;
- ch->ctrl = (ch->ctrl & 0xfffff000) | size;
- if (size == 0) {
- /* Transfer complete. */
- if (ch->lli) {
- ch->src = ldl_phys(ch->lli);
- ch->dest = ldl_phys(ch->lli + 4);
- ch->ctrl = ldl_phys(ch->lli + 12);
- ch->lli = ldl_phys(ch->lli + 8);
- } else {
- ch->conf &= ~PL080_CCONF_E;
- }
- if (ch->ctrl & PL080_CCTRL_I) {
- s->tc_int |= 1 << c;
- }
- }
- goto again;
- }
- if (--s->running)
- s->running = 1;
- }
-}
-
-static uint32_t pl080_read(void *opaque, target_phys_addr_t offset)
-{
- pl080_state *s = (pl080_state *)opaque;
- uint32_t i;
- uint32_t mask;
-
- offset -= s->base;
- if (offset >= 0xfe0 && offset < 0x1000) {
- return pl080_id[(offset - 0xfe0) >> 2];
- }
- if (offset >= 0x100 && offset < 0x200) {
- i = (offset & 0xe0) >> 5;
- switch (offset >> 2) {
- case 0: /* SrcAddr */
- return s->chan[i].src;
- case 1: /* DestAddr */
- return s->chan[i].dest;
- case 2: /* LLI */
- return s->chan[i].lli;
- case 3: /* Control */
- return s->chan[i].ctrl;
- case 4: /* Configuration */
- return s->chan[i].conf;
- default:
- goto bad_offset;
- }
- }
- switch (offset >> 2) {
- case 0: /* IntStatus */
- return (s->tc_int & s->tc_mask) | (s->err_int & s->err_mask);
- case 1: /* IntTCStatus */
- return (s->tc_int & s->tc_mask);
- case 3: /* IntErrorStatus */
- return (s->err_int & s->err_mask);
- case 5: /* RawIntTCStatus */
- return s->tc_int;
- case 6: /* RawIntErrorStatus */
- return s->err_int;
- case 7: /* EnbldChns */
- mask = 0;
- for (i = 0; i < PL080_NUM_CHANNELS; i++) {
- if (s->chan[i].conf & PL080_CCONF_E)
- mask |= 1 << i;
- }
- return mask;
- case 8: /* SoftBReq */
- case 9: /* SoftSReq */
- case 10: /* SoftLBReq */
- case 11: /* SoftLSReq */
- /* ??? Implement these. */
- return 0;
- case 12: /* Configuration */
- return s->conf;
- case 13: /* Sync */
- return s->sync;
- default:
- bad_offset:
- cpu_abort(cpu_single_env, "pl080_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void pl080_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- pl080_state *s = (pl080_state *)opaque;
- int i;
-
- offset -= s->base;
- if (offset >= 0x100 && offset < 0x200) {
- i = (offset & 0xe0) >> 5;
- switch (offset >> 2) {
- case 0: /* SrcAddr */
- s->chan[i].src = value;
- break;
- case 1: /* DestAddr */
- s->chan[i].dest = value;
- break;
- case 2: /* LLI */
- s->chan[i].lli = value;
- break;
- case 3: /* Control */
- s->chan[i].ctrl = value;
- break;
- case 4: /* Configuration */
- s->chan[i].conf = value;
- pl080_run(s);
- break;
- }
- }
- switch (offset >> 2) {
- case 2: /* IntTCClear */
- s->tc_int &= ~value;
- break;
- case 4: /* IntErrorClear */
- s->err_int &= ~value;
- break;
- case 8: /* SoftBReq */
- case 9: /* SoftSReq */
- case 10: /* SoftLBReq */
- case 11: /* SoftLSReq */
- /* ??? Implement these. */
- cpu_abort(cpu_single_env, "pl080_write: Soft DMA not implemented\n");
- break;
- case 12: /* Configuration */
- s->conf = value;
- if (s->conf & (PL080_CONF_M1 | PL080_CONF_M1)) {
- cpu_abort(cpu_single_env,
- "pl080_write: Big-endian DMA not implemented\n");
- }
- pl080_run(s);
- break;
- case 13: /* Sync */
- s->sync = value;
- break;
- default:
- cpu_abort(cpu_single_env, "pl080_write: Bad offset %x\n", offset);
- }
- pl080_update(s);
-}
-
-static CPUReadMemoryFunc *pl080_readfn[] = {
- pl080_read,
- pl080_read,
- pl080_read
-};
-
-static CPUWriteMemoryFunc *pl080_writefn[] = {
- pl080_write,
- pl080_write,
- pl080_write
-};
-
-void *pl080_init(uint32_t base, void *pic, int irq)
-{
- int iomemtype;
- pl080_state *s;
-
- s = (pl080_state *)qemu_mallocz(sizeof(pl080_state));
- iomemtype = cpu_register_io_memory(0, pl080_readfn,
- pl080_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- s->base = base;
- s->pic = pic;
- s->irq = irq;
- /* ??? Save/restore. */
- return s;
-}
-
diff --git a/hw/pl110.c b/hw/pl110.c
deleted file mode 100644
index ecebe35..0000000
--- a/hw/pl110.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Arm PrimeCell PL110 Color LCD Controller
- *
- * Copyright (c) 2005-2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GNU LGPL
- */
-
-#include "vl.h"
-
-#define PL110_CR_EN 0x001
-#define PL110_CR_BEBO 0x200
-#define PL110_CR_BEPO 0x400
-#define PL110_CR_PWR 0x800
-
-enum pl110_bppmode
-{
- BPP_1,
- BPP_2,
- BPP_4,
- BPP_8,
- BPP_16,
- BPP_32
-};
-
-typedef struct {
- uint32_t base;
- DisplayState *ds;
- /* The Versatile/PB uses a slightly modified PL110 controller. */
- int versatile;
- void *pic;
- uint32_t timing[4];
- uint32_t cr;
- uint32_t upbase;
- uint32_t lpbase;
- uint32_t int_status;
- uint32_t int_mask;
- int cols;
- int rows;
- enum pl110_bppmode bpp;
- int invalidate;
- uint32_t pallette[256];
- uint32_t raw_pallette[128];
- int irq;
-} pl110_state;
-
-static const unsigned char pl110_id[] =
-{ 0x10, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
-
-/* The Arm documentation (DDI0224C) says the CLDC on the Versatile board
- has a different ID. However Linux only looks for the normal ID. */
-#if 0
-static const unsigned char pl110_versatile_id[] =
-{ 0x93, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
-#else
-#define pl110_versatile_id pl110_id
-#endif
-
-static inline uint32_t rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
-}
-
-static inline uint32_t rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
-}
-
-static inline uint32_t rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
-}
-
-static inline uint32_t rgb_to_pixel24(unsigned int r, unsigned int g, unsigned b)
-{
- return (r << 16) | (g << 8) | b;
-}
-
-static inline uint32_t rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
-{
- return (r << 16) | (g << 8) | b;
-}
-
-typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int);
-
-#define BITS 8
-#include "pl110_template.h"
-#define BITS 15
-#include "pl110_template.h"
-#define BITS 16
-#include "pl110_template.h"
-#define BITS 24
-#include "pl110_template.h"
-#define BITS 32
-#include "pl110_template.h"
-
-static int pl110_enabled(pl110_state *s)
-{
- return (s->cr & PL110_CR_EN) && (s->cr & PL110_CR_PWR);
-}
-
-static void pl110_update_display(void *opaque)
-{
- pl110_state *s = (pl110_state *)opaque;
- drawfn* fntable;
- drawfn fn;
- uint32_t *pallette;
- uint32_t addr;
- uint32_t base;
- int dest_width;
- int src_width;
- uint8_t *dest;
- uint8_t *src;
- int first, last = 0;
- int dirty, new_dirty;
- int i;
-
- if (!pl110_enabled(s))
- return;
-
- switch (s->ds->depth) {
- case 0:
- return;
- case 8:
- fntable = pl110_draw_fn_8;
- dest_width = 1;
- break;
- case 15:
- fntable = pl110_draw_fn_15;
- dest_width = 2;
- break;
- case 16:
- fntable = pl110_draw_fn_16;
- dest_width = 2;
- break;
- case 24:
- fntable = pl110_draw_fn_24;
- dest_width = 3;
- break;
- case 32:
- fntable = pl110_draw_fn_32;
- dest_width = 4;
- break;
- default:
- fprintf(stderr, "pl110: Bad color depth\n");
- exit(1);
- }
- if (s->cr & PL110_CR_BEBO)
- fn = fntable[s->bpp + 6];
- else if (s->cr & PL110_CR_BEPO)
- fn = fntable[s->bpp + 12];
- else
- fn = fntable[s->bpp];
-
- src_width = s->cols;
- switch (s->bpp) {
- case BPP_1:
- src_width >>= 3;
- break;
- case BPP_2:
- src_width >>= 2;
- break;
- case BPP_4:
- src_width >>= 1;
- break;
- case BPP_8:
- break;
- case BPP_16:
- src_width <<= 1;
- break;
- case BPP_32:
- src_width <<= 2;
- break;
- }
- dest_width *= s->cols;
- pallette = s->pallette;
- base = s->upbase;
- /* HACK: Arm aliases physical memory at 0x80000000. */
- if (base > 0x80000000)
- base -= 0x80000000;
- src = phys_ram_base + base;
- dest = s->ds->data;
- first = -1;
- addr = base;
-
- dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG);
- for (i = 0; i < s->rows; i++) {
- new_dirty = 0;
- if ((addr & TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) {
- uint32_t tmp;
- for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) {
- new_dirty |= cpu_physical_memory_get_dirty(addr + tmp,
- VGA_DIRTY_FLAG);
- }
- }
-
- if (dirty || new_dirty || s->invalidate) {
- fn(pallette, dest, src, s->cols);
- if (first == -1)
- first = i;
- last = i;
- }
- dirty = new_dirty;
- addr += src_width;
- dest += dest_width;
- src += src_width;
- }
- if (first < 0)
- return;
-
- s->invalidate = 0;
- cpu_physical_memory_reset_dirty(base + first * src_width,
- base + (last + 1) * src_width,
- VGA_DIRTY_FLAG);
- dpy_update(s->ds, 0, first, s->cols, last - first + 1);
-}
-
-static void pl110_invalidate_display(void * opaque)
-{
- pl110_state *s = (pl110_state *)opaque;
- s->invalidate = 1;
-}
-
-static void pl110_update_pallette(pl110_state *s, int n)
-{
- int i;
- uint32_t raw;
- unsigned int r, g, b;
-
- raw = s->raw_pallette[n];
- n <<= 1;
- for (i = 0; i < 2; i++) {
- r = (raw & 0x1f) << 3;
- raw >>= 5;
- g = (raw & 0x1f) << 3;
- raw >>= 5;
- b = (raw & 0x1f) << 3;
- /* The I bit is ignored. */
- raw >>= 6;
- switch (s->ds->depth) {
- case 8:
- s->pallette[n] = rgb_to_pixel8(r, g, b);
- break;
- case 15:
- s->pallette[n] = rgb_to_pixel15(r, g, b);
- break;
- case 16:
- s->pallette[n] = rgb_to_pixel16(r, g, b);
- break;
- case 24:
- case 32:
- s->pallette[n] = rgb_to_pixel32(r, g, b);
- break;
- }
- n++;
- }
-}
-
-static void pl110_resize(pl110_state *s, int width, int height)
-{
- if (width != s->cols || height != s->rows) {
- if (pl110_enabled(s)) {
- dpy_resize(s->ds, width, height);
- }
- }
- s->cols = width;
- s->rows = height;
-}
-
-/* Update interrupts. */
-static void pl110_update(pl110_state *s)
-{
- /* TODO: Implement interrupts. */
-}
-
-static uint32_t pl110_read(void *opaque, target_phys_addr_t offset)
-{
- pl110_state *s = (pl110_state *)opaque;
-
- offset -= s->base;
- if (offset >= 0xfe0 && offset < 0x1000) {
- if (s->versatile)
- return pl110_versatile_id[(offset - 0xfe0) >> 2];
- else
- return pl110_id[(offset - 0xfe0) >> 2];
- }
- if (offset >= 0x200 && offset < 0x400) {
- return s->raw_pallette[(offset - 0x200) >> 2];
- }
- switch (offset >> 2) {
- case 0: /* LCDTiming0 */
- return s->timing[0];
- case 1: /* LCDTiming1 */
- return s->timing[1];
- case 2: /* LCDTiming2 */
- return s->timing[2];
- case 3: /* LCDTiming3 */
- return s->timing[3];
- case 4: /* LCDUPBASE */
- return s->upbase;
- case 5: /* LCDLPBASE */
- return s->lpbase;
- case 6: /* LCDIMSC */
- return s->int_mask;
- case 7: /* LCDControl */
- return s->cr;
- case 8: /* LCDRIS */
- return s->int_status;
- case 9: /* LCDMIS */
- return s->int_status & s->int_mask;
- case 11: /* LCDUPCURR */
- /* TODO: Implement vertical refresh. */
- return s->upbase;
- case 12: /* LCDLPCURR */
- return s->lpbase;
- default:
- cpu_abort (cpu_single_env, "pl110_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void pl110_write(void *opaque, target_phys_addr_t offset,
- uint32_t val)
-{
- pl110_state *s = (pl110_state *)opaque;
- int n;
-
- /* For simplicity invalidate the display whenever a control register
- is writen to. */
- s->invalidate = 1;
- offset -= s->base;
- if (offset >= 0x200 && offset < 0x400) {
- /* Pallette. */
- n = (offset - 0x200) >> 2;
- s->raw_pallette[(offset - 0x200) >> 2] = val;
- pl110_update_pallette(s, n);
- return;
- }
- switch (offset >> 2) {
- case 0: /* LCDTiming0 */
- s->timing[0] = val;
- n = ((val & 0xfc) + 4) * 4;
- pl110_resize(s, n, s->rows);
- break;
- case 1: /* LCDTiming1 */
- s->timing[1] = val;
- n = (val & 0x3ff) + 1;
- pl110_resize(s, s->cols, n);
- break;
- case 2: /* LCDTiming2 */
- s->timing[2] = val;
- break;
- case 3: /* LCDTiming3 */
- s->timing[3] = val;
- break;
- case 4: /* LCDUPBASE */
- s->upbase = val;
- break;
- case 5: /* LCDLPBASE */
- s->lpbase = val;
- break;
- case 6: /* LCDIMSC */
- if (s->versatile)
- goto control;
- imsc:
- s->int_mask = val;
- pl110_update(s);
- break;
- case 7: /* LCDControl */
- if (s->versatile)
- goto imsc;
- control:
- s->cr = val;
- s->bpp = (val >> 1) & 7;
- if (pl110_enabled(s)) {
- dpy_resize(s->ds, s->cols, s->rows);
- }
- break;
- case 10: /* LCDICR */
- s->int_status &= ~val;
- pl110_update(s);
- break;
- default:
- cpu_abort (cpu_single_env, "pl110_write: Bad offset %x\n", offset);
- }
-}
-
-static CPUReadMemoryFunc *pl110_readfn[] = {
- pl110_read,
- pl110_read,
- pl110_read
-};
-
-static CPUWriteMemoryFunc *pl110_writefn[] = {
- pl110_write,
- pl110_write,
- pl110_write
-};
-
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq,
- int versatile)
-{
- pl110_state *s;
- int iomemtype;
-
- s = (pl110_state *)qemu_mallocz(sizeof(pl110_state));
- iomemtype = cpu_register_io_memory(0, pl110_readfn,
- pl110_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- s->base = base;
- s->ds = ds;
- s->versatile = versatile;
- s->pic = pic;
- s->irq = irq;
- graphic_console_init(ds, pl110_update_display, pl110_invalidate_display,
- NULL, s);
- /* ??? Save/restore. */
- return s;
-}
diff --git a/hw/pl110_template.h b/hw/pl110_template.h
deleted file mode 100644
index db05035..0000000
--- a/hw/pl110_template.h
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Arm PrimeCell PL110 Color LCD Controller
- *
- * Copyright (c) 2005 CodeSourcery, LLC.
- * Written by Paul Brook
- *
- * This code is licenced under the GNU LGPL
- *
- * Framebuffer format conversion routines.
- */
-
-#ifndef ORDER
-
-#if BITS == 8
-#define COPY_PIXEL(to, from) *(to++) = from
-#elif BITS == 15 || BITS == 16
-#define COPY_PIXEL(to, from) *(uint16_t *)to = from; to += 2;
-#elif BITS == 24
-#define COPY_PIXEL(to, from) \
- *(to++) = from; *(to++) = (from) >> 8; *(to++) = (from) >> 16
-#elif BITS == 32
-#define COPY_PIXEL(to, from) *(uint32_t *)to = from; to += 4;
-#else
-#error unknown bit depth
-#endif
-
-#define ORDER 0
-#include "pl110_template.h"
-#define ORDER 1
-#include "pl110_template.h"
-#define ORDER 2
-#include "pl110_template.h"
-
-static drawfn glue(pl110_draw_fn_,BITS)[18] =
-{
- glue(pl110_draw_line1_lblp,BITS),
- glue(pl110_draw_line2_lblp,BITS),
- glue(pl110_draw_line4_lblp,BITS),
- glue(pl110_draw_line8_lblp,BITS),
- glue(pl110_draw_line16_lblp,BITS),
- glue(pl110_draw_line32_lblp,BITS),
-
- glue(pl110_draw_line1_bbbp,BITS),
- glue(pl110_draw_line2_bbbp,BITS),
- glue(pl110_draw_line4_bbbp,BITS),
- glue(pl110_draw_line8_bbbp,BITS),
- glue(pl110_draw_line16_bbbp,BITS),
- glue(pl110_draw_line32_bbbp,BITS),
-
- glue(pl110_draw_line1_lbbp,BITS),
- glue(pl110_draw_line2_lbbp,BITS),
- glue(pl110_draw_line4_lbbp,BITS),
- glue(pl110_draw_line8_lbbp,BITS),
- glue(pl110_draw_line16_lbbp,BITS),
- glue(pl110_draw_line32_lbbp,BITS)
-};
-
-#undef BITS
-#undef COPY_PIXEL
-
-#else
-
-#if ORDER == 0
-#define NAME glue(lblp, BITS)
-#ifdef WORDS_BIGENDIAN
-#define SWAP_WORDS 1
-#endif
-#elif ORDER == 1
-#define NAME glue(bbbp, BITS)
-#ifndef WORDS_BIGENDIAN
-#define SWAP_WORDS 1
-#endif
-#else
-#define SWAP_PIXELS 1
-#define NAME glue(lbbp, BITS)
-#ifdef WORDS_BIGENDIAN
-#define SWAP_WORDS 1
-#endif
-#endif
-
-#define FN_2(x, y) FN(x, y) FN(x+1, y)
-#define FN_4(x, y) FN_2(x, y) FN_2(x+1, y)
-#define FN_8(y) FN_4(0, y) FN_4(4, y)
-
-static void glue(pl110_draw_line1_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
-{
- uint32_t data;
- while (width > 0) {
- data = *(uint32_t *)src;
-#ifdef SWAP_PIXELS
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 7 - (x))) & 1]);
-#else
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x) + y)) & 1]);
-#endif
-#ifdef SWAP_WORDS
- FN_8(24)
- FN_8(16)
- FN_8(8)
- FN_8(0)
-#else
- FN_8(0)
- FN_8(8)
- FN_8(16)
- FN_8(24)
-#endif
-#undef FN
- width -= 32;
- src += 4;
- }
-}
-
-static void glue(pl110_draw_line2_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
-{
- uint32_t data;
- while (width > 0) {
- data = *(uint32_t *)src;
-#ifdef SWAP_PIXELS
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 6 - (x)*2)) & 3]);
-#else
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*2 + y)) & 3]);
-#endif
-#ifdef SWAP_WORDS
- FN_4(0, 24)
- FN_4(0, 16)
- FN_4(0, 8)
- FN_4(0, 0)
-#else
- FN_4(0, 0)
- FN_4(0, 8)
- FN_4(0, 16)
- FN_4(0, 24)
-#endif
-#undef FN
- width -= 16;
- src += 4;
- }
-}
-
-static void glue(pl110_draw_line4_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
-{
- uint32_t data;
- while (width > 0) {
- data = *(uint32_t *)src;
-#ifdef SWAP_PIXELS
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 4 - (x)*4)) & 0xf]);
-#else
-#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*4 + y)) & 0xf]);
-#endif
-#ifdef SWAP_WORDS
- FN_2(0, 24)
- FN_2(0, 16)
- FN_2(0, 8)
- FN_2(0, 0)
-#else
- FN_2(0, 0)
- FN_2(0, 8)
- FN_2(0, 16)
- FN_2(0, 24)
-#endif
-#undef FN
- width -= 8;
- src += 4;
- }
-}
-
-static void glue(pl110_draw_line8_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
-{
- uint32_t data;
- while (width > 0) {
- data = *(uint32_t *)src;
-#define FN(x) COPY_PIXEL(d, pallette[(data >> (x)) & 0xff]);
-#ifdef SWAP_WORDS
- FN(24)
- FN(16)
- FN(8)
- FN(0)
-#else
- FN(0)
- FN(8)
- FN(16)
- FN(24)
-#endif
-#undef FN
- width -= 4;
- src += 4;
- }
-}
-
-static void glue(pl110_draw_line16_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
-{
- uint32_t data;
- unsigned int r, g, b;
- while (width > 0) {
- data = *(uint32_t *)src;
-#ifdef SWAP_WORDS
- data = bswap32(data);
-#endif
-#if 0
- r = data & 0x1f;
- data >>= 5;
- g = data & 0x3f;
- data >>= 6;
- b = data & 0x1f;
- data >>= 5;
-#else
- r = (data & 0x1f) << 3;
- data >>= 5;
- g = (data & 0x3f) << 2;
- data >>= 6;
- b = (data & 0x1f) << 3;
- data >>= 5;
-#endif
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
- r = (data & 0x1f) << 3;
- data >>= 5;
- g = (data & 0x3f) << 2;
- data >>= 6;
- b = (data & 0x1f) << 3;
- data >>= 5;
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
- width -= 2;
- src += 4;
- }
-}
-
-static void glue(pl110_draw_line32_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
-{
- uint32_t data;
- unsigned int r, g, b;
- while (width > 0) {
- data = *(uint32_t *)src;
-#ifdef SWAP_WORDS
- r = data & 0xff;
- g = (data >> 8) & 0xff;
- b = (data >> 16) & 0xff;
-#else
- r = (data >> 24) & 0xff;
- g = (data >> 16) & 0xff;
- b = (data >> 8) & 0xff;
-#endif
- COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
- width--;
- src += 4;
- }
-}
-
-#undef SWAP_PIXELS
-#undef NAME
-#undef SWAP_WORDS
-#undef ORDER
-
-#endif
diff --git a/hw/pl190.c b/hw/pl190.c
deleted file mode 100644
index 55c7180..0000000
--- a/hw/pl190.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Arm PrimeCell PL190 Vector Interrupt Controller
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GPL.
- */
-
-#include "vl.h"
-#include "arm_pic.h"
-
-/* The number of virtual priority levels. 16 user vectors plus the
- unvectored IRQ. Chained interrupts would require an additional level
- if implemented. */
-
-#define PL190_NUM_PRIO 17
-
-typedef struct {
- arm_pic_handler handler;
- uint32_t base;
- DisplayState *ds;
- uint32_t level;
- uint32_t soft_level;
- uint32_t irq_enable;
- uint32_t fiq_select;
- uint32_t default_addr;
- uint8_t vect_control[16];
- uint32_t vect_addr[PL190_NUM_PRIO];
- /* Mask containing interrupts with higher priority than this one. */
- uint32_t prio_mask[PL190_NUM_PRIO + 1];
- int protected;
- /* Current priority level. */
- int priority;
- int prev_prio[PL190_NUM_PRIO];
- void *parent;
- int irq;
- int fiq;
-} pl190_state;
-
-static const unsigned char pl190_id[] =
-{ 0x90, 0x11, 0x04, 0x00, 0x0D, 0xf0, 0x05, 0xb1 };
-
-static inline uint32_t pl190_irq_level(pl190_state *s)
-{
- return (s->level | s->soft_level) & s->irq_enable & ~s->fiq_select;
-}
-
-/* Update interrupts. */
-static void pl190_update(pl190_state *s)
-{
- uint32_t level = pl190_irq_level(s);
- int set;
-
- set = (level & s->prio_mask[s->priority]) != 0;
- pic_set_irq_new(s->parent, s->irq, set);
- set = ((s->level | s->soft_level) & s->fiq_select) != 0;
- pic_set_irq_new(s->parent, s->fiq, set);
-}
-
-static void pl190_set_irq(void *opaque, int irq, int level)
-{
- pl190_state *s = (pl190_state *)opaque;
-
- if (level)
- s->level |= 1u << irq;
- else
- s->level &= ~(1u << irq);
- pl190_update(s);
-}
-
-static void pl190_update_vectors(pl190_state *s)
-{
- uint32_t mask;
- int i;
- int n;
-
- mask = 0;
- for (i = 0; i < 16; i++)
- {
- s->prio_mask[i] = mask;
- if (s->vect_control[i] & 0x20)
- {
- n = s->vect_control[i] & 0x1f;
- mask |= 1 << n;
- }
- }
- s->prio_mask[16] = mask;
- pl190_update(s);
-}
-
-static uint32_t pl190_read(void *opaque, target_phys_addr_t offset)
-{
- pl190_state *s = (pl190_state *)opaque;
- int i;
-
- offset -= s->base;
- if (offset >= 0xfe0 && offset < 0x1000) {
- return pl190_id[(offset - 0xfe0) >> 2];
- }
- if (offset >= 0x100 && offset < 0x140) {
- return s->vect_addr[(offset - 0x100) >> 2];
- }
- if (offset >= 0x200 && offset < 0x240) {
- return s->vect_control[(offset - 0x200) >> 2];
- }
- switch (offset >> 2) {
- case 0: /* IRQSTATUS */
- return pl190_irq_level(s);
- case 1: /* FIQSATUS */
- return (s->level | s->soft_level) & s->fiq_select;
- case 2: /* RAWINTR */
- return s->level | s->soft_level;
- case 3: /* INTSELECT */
- return s->fiq_select;
- case 4: /* INTENABLE */
- return s->irq_enable;
- case 6: /* SOFTINT */
- return s->soft_level;
- case 8: /* PROTECTION */
- return s->protected;
- case 12: /* VECTADDR */
- /* Read vector address at the start of an ISR. Increases the
- current priority level to that of the current interrupt. */
- for (i = 0; i < s->priority; i++)
- {
- if ((s->level | s->soft_level) & s->prio_mask[i])
- break;
- }
- /* Reading this value with no pending interrupts is undefined.
- We return the default address. */
- if (i == PL190_NUM_PRIO)
- return s->vect_addr[16];
- if (i < s->priority)
- {
- s->prev_prio[i] = s->priority;
- s->priority = i;
- pl190_update(s);
- }
- return s->vect_addr[s->priority];
- case 13: /* DEFVECTADDR */
- return s->vect_addr[16];
- default:
- cpu_abort (cpu_single_env, "pl190_read: Bad offset %x\n", offset);
- return 0;
- }
-}
-
-static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
-{
- pl190_state *s = (pl190_state *)opaque;
-
- offset -= s->base;
- if (offset >= 0x100 && offset < 0x140) {
- s->vect_addr[(offset - 0x100) >> 2] = val;
- pl190_update_vectors(s);
- return;
- }
- if (offset >= 0x200 && offset < 0x240) {
- s->vect_control[(offset - 0x200) >> 2] = val;
- pl190_update_vectors(s);
- return;
- }
- switch (offset >> 2) {
- case 0: /* SELECT */
- /* This is a readonly register, but linux tries to write to it
- anyway. Ignore the write. */
- break;
- case 3: /* INTSELECT */
- s->fiq_select = val;
- break;
- case 4: /* INTENABLE */
- s->irq_enable |= val;
- break;
- case 5: /* INTENCLEAR */
- s->irq_enable &= ~val;
- break;
- case 6: /* SOFTINT */
- s->soft_level |= val;
- break;
- case 7: /* SOFTINTCLEAR */
- s->soft_level &= ~val;
- break;
- case 8: /* PROTECTION */
- /* TODO: Protection (supervisor only access) is not implemented. */
- s->protected = val & 1;
- break;
- case 12: /* VECTADDR */
- /* Restore the previous priority level. The value written is
- ignored. */
- if (s->priority < PL190_NUM_PRIO)
- s->priority = s->prev_prio[s->priority];
- break;
- case 13: /* DEFVECTADDR */
- s->default_addr = val;
- break;
- case 0xc0: /* ITCR */
- if (val)
- cpu_abort(cpu_single_env, "pl190: Test mode not implemented\n");
- break;
- default:
- cpu_abort(cpu_single_env, "pl190_write: Bad offset %x\n", offset);
- return;
- }
- pl190_update(s);
-}
-
-static CPUReadMemoryFunc *pl190_readfn[] = {
- pl190_read,
- pl190_read,
- pl190_read
-};
-
-static CPUWriteMemoryFunc *pl190_writefn[] = {
- pl190_write,
- pl190_write,
- pl190_write
-};
-
-void pl190_reset(pl190_state *s)
-{
- int i;
-
- for (i = 0; i < 16; i++)
- {
- s->vect_addr[i] = 0;
- s->vect_control[i] = 0;
- }
- s->vect_addr[16] = 0;
- s->prio_mask[17] = 0xffffffff;
- s->priority = PL190_NUM_PRIO;
- pl190_update_vectors(s);
-}
-
-void *pl190_init(uint32_t base, void *parent, int irq, int fiq)
-{
- pl190_state *s;
- int iomemtype;
-
- s = (pl190_state *)qemu_mallocz(sizeof(pl190_state));
- iomemtype = cpu_register_io_memory(0, pl190_readfn,
- pl190_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- s->handler = pl190_set_irq;
- s->base = base;
- s->parent = parent;
- s->irq = irq;
- s->fiq = fiq;
- pl190_reset(s);
- /* ??? Save/restore. */
- return s;
-}
diff --git a/hw/power_supply.h b/hw/power_supply.h
new file mode 100644
index 0000000..b85edc7
--- /dev/null
+++ b/hw/power_supply.h
@@ -0,0 +1,109 @@
+/*
+ * Universal power supply monitor class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#ifndef __LINUX_POWER_SUPPLY_H__
+#define __LINUX_POWER_SUPPLY_H__
+
+/*
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum {
+ POWER_SUPPLY_STATUS_UNKNOWN = 0,
+ POWER_SUPPLY_STATUS_CHARGING,
+ POWER_SUPPLY_STATUS_DISCHARGING,
+ POWER_SUPPLY_STATUS_NOT_CHARGING,
+ POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+ POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+ POWER_SUPPLY_HEALTH_GOOD,
+ POWER_SUPPLY_HEALTH_OVERHEAT,
+ POWER_SUPPLY_HEALTH_DEAD,
+ POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+ POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+};
+
+enum {
+ POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
+ POWER_SUPPLY_TECHNOLOGY_NiMH,
+ POWER_SUPPLY_TECHNOLOGY_LION,
+ POWER_SUPPLY_TECHNOLOGY_LIPO,
+ POWER_SUPPLY_TECHNOLOGY_LiFe,
+ POWER_SUPPLY_TECHNOLOGY_NiCd,
+};
+
+enum {
+ POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
+ POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_LOW,
+ POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
+ POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+};
+
+enum power_supply_property {
+ /* Properties of type `int' */
+ POWER_SUPPLY_PROP_STATUS = 0,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_AVG,
+ POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY,
+ POWER_SUPPLY_PROP_ENERGY_NOW,
+ POWER_SUPPLY_PROP_ENERGY_AVG,
+ POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+ /* Properties of type `const char *' */
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+enum power_supply_type {
+ POWER_SUPPLY_TYPE_BATTERY = 0,
+ POWER_SUPPLY_TYPE_UPS,
+ POWER_SUPPLY_TYPE_MAINS,
+ POWER_SUPPLY_TYPE_USB,
+};
+
+#endif /* __LINUX_POWER_SUPPLY_H__ */
diff --git a/hw/ppc.c b/hw/ppc.c
deleted file mode 100644
index 3743ad7..0000000
--- a/hw/ppc.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * QEMU generic PPC hardware System Emulator
- *
- * Copyright (c) 2003-2004 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-#include "m48t59.h"
-
-/*****************************************************************************/
-/* PPC time base and decrementer emulation */
-//#define DEBUG_TB
-
-struct ppc_tb_t {
- /* Time base management */
- int64_t tb_offset; /* Compensation */
- uint32_t tb_freq; /* TB frequency */
- /* Decrementer management */
- uint64_t decr_next; /* Tick for next decr interrupt */
- struct QEMUTimer *decr_timer;
-};
-
-static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
-{
- /* TB time in tb periods */
- return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
- tb_env->tb_freq, ticks_per_sec);
-}
-
-uint32_t cpu_ppc_load_tbl (CPUState *env)
-{
- ppc_tb_t *tb_env = env->tb_env;
- uint64_t tb;
-
- tb = cpu_ppc_get_tb(tb_env);
-#ifdef DEBUG_TB
- {
- static int last_time;
- int now;
- now = time(NULL);
- if (last_time != now) {
- last_time = now;
- printf("%s: tb=0x%016lx %d %08lx\n",
- __func__, tb, now, tb_env->tb_offset);
- }
- }
-#endif
-
- return tb & 0xFFFFFFFF;
-}
-
-uint32_t cpu_ppc_load_tbu (CPUState *env)
-{
- ppc_tb_t *tb_env = env->tb_env;
- uint64_t tb;
-
- tb = cpu_ppc_get_tb(tb_env);
-#ifdef DEBUG_TB
- printf("%s: tb=0x%016lx\n", __func__, tb);
-#endif
- return tb >> 32;
-}
-
-static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
-{
- tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
- - qemu_get_clock(vm_clock);
-#ifdef DEBUG_TB
- printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
-#endif
-}
-
-void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
-{
- ppc_tb_t *tb_env = env->tb_env;
-
- cpu_ppc_store_tb(tb_env,
- ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
-}
-
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
-{
- ppc_tb_t *tb_env = env->tb_env;
-
- cpu_ppc_store_tb(tb_env,
- ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
-}
-
-uint32_t cpu_ppc_load_decr (CPUState *env)
-{
- ppc_tb_t *tb_env = env->tb_env;
- uint32_t decr;
- int64_t diff;
-
- diff = tb_env->decr_next - qemu_get_clock(vm_clock);
- if (diff >= 0)
- decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
- else
- decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec);
-#if defined(DEBUG_TB)
- printf("%s: 0x%08x\n", __func__, decr);
-#endif
- return decr;
-}
-
-/* When decrementer expires,
- * all we need to do is generate or queue a CPU exception
- */
-static inline void cpu_ppc_decr_excp (CPUState *env)
-{
- /* Raise it */
-#ifdef DEBUG_TB
- printf("raise decrementer exception\n");
-#endif
- cpu_interrupt(env, CPU_INTERRUPT_TIMER);
-}
-
-static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
- uint32_t value, int is_excp)
-{
- ppc_tb_t *tb_env = env->tb_env;
- uint64_t now, next;
-
-#ifdef DEBUG_TB
- printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
-#endif
- now = qemu_get_clock(vm_clock);
- next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
- if (is_excp)
- next += tb_env->decr_next - now;
- if (next == now)
- next++;
- tb_env->decr_next = next;
- /* Adjust timer */
- qemu_mod_timer(tb_env->decr_timer, next);
- /* If we set a negative value and the decrementer was positive,
- * raise an exception.
- */
- if ((value & 0x80000000) && !(decr & 0x80000000))
- cpu_ppc_decr_excp(env);
-}
-
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
-{
- _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
-}
-
-static void cpu_ppc_decr_cb (void *opaque)
-{
- _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
-}
-
-/* Set up (once) timebase frequency (in Hz) */
-ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
-{
- ppc_tb_t *tb_env;
-
- tb_env = qemu_mallocz(sizeof(ppc_tb_t));
- if (tb_env == NULL)
- return NULL;
- env->tb_env = tb_env;
- if (tb_env->tb_freq == 0 || 1) {
- tb_env->tb_freq = freq;
- /* Create new timer */
- tb_env->decr_timer =
- qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
- /* There is a bug in 2.4 kernels:
- * if a decrementer exception is pending when it enables msr_ee,
- * it's not ready to handle it...
- */
- _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
- }
-
- return tb_env;
-}
-
-#if 0
-/*****************************************************************************/
-/* Handle system reset (for now, just stop emulation) */
-void cpu_ppc_reset (CPUState *env)
-{
- printf("Reset asked... Stop emulation\n");
- abort();
-}
-#endif
-
-static void PPC_io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- cpu_outb(NULL, addr & 0xffff, value);
-}
-
-static uint32_t PPC_io_readb (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret = cpu_inb(NULL, addr & 0xffff);
- return ret;
-}
-
-static void PPC_io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap16(value);
-#endif
- cpu_outw(NULL, addr & 0xffff, value);
-}
-
-static uint32_t PPC_io_readw (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret = cpu_inw(NULL, addr & 0xffff);
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = bswap16(ret);
-#endif
- return ret;
-}
-
-static void PPC_io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap32(value);
-#endif
- cpu_outl(NULL, addr & 0xffff, value);
-}
-
-static uint32_t PPC_io_readl (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret = cpu_inl(NULL, addr & 0xffff);
-
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = bswap32(ret);
-#endif
- return ret;
-}
-
-CPUWriteMemoryFunc *PPC_io_write[] = {
- &PPC_io_writeb,
- &PPC_io_writew,
- &PPC_io_writel,
-};
-
-CPUReadMemoryFunc *PPC_io_read[] = {
- &PPC_io_readb,
- &PPC_io_readw,
- &PPC_io_readl,
-};
-
-/*****************************************************************************/
-/* Debug port */
-void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
-{
- addr &= 0xF;
- switch (addr) {
- case 0:
- printf("%c", val);
- break;
- case 1:
- printf("\n");
- fflush(stdout);
- break;
- case 2:
- printf("Set loglevel to %04x\n", val);
- cpu_set_log(val | 0x100);
- break;
- }
-}
-
-/*****************************************************************************/
-/* NVRAM helpers */
-void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
-{
- m48t59_write(nvram, addr, value);
-}
-
-uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
-{
- return m48t59_read(nvram, addr);
-}
-
-void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
-{
- m48t59_write(nvram, addr, value >> 8);
- m48t59_write(nvram, addr + 1, value & 0xFF);
-}
-
-uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
-{
- uint16_t tmp;
-
- tmp = m48t59_read(nvram, addr) << 8;
- tmp |= m48t59_read(nvram, addr + 1);
- return tmp;
-}
-
-void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
-{
- m48t59_write(nvram, addr, value >> 24);
- m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
- m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
- m48t59_write(nvram, addr + 3, value & 0xFF);
-}
-
-uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
-{
- uint32_t tmp;
-
- tmp = m48t59_read(nvram, addr) << 24;
- tmp |= m48t59_read(nvram, addr + 1) << 16;
- tmp |= m48t59_read(nvram, addr + 2) << 8;
- tmp |= m48t59_read(nvram, addr + 3);
- return tmp;
-}
-
-void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
- const unsigned char *str, uint32_t max)
-{
- int i;
-
- for (i = 0; i < max && str[i] != '\0'; i++) {
- m48t59_write(nvram, addr + i, str[i]);
- }
- m48t59_write(nvram, addr + max - 1, '\0');
-}
-
-int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
-{
- int i;
-
- memset(dst, 0, max);
- for (i = 0; i < max; i++) {
- dst[i] = NVRAM_get_byte(nvram, addr + i);
- if (dst[i] == '\0')
- break;
- }
-
- return i;
-}
-
-static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
-{
- uint16_t tmp;
- uint16_t pd, pd1, pd2;
-
- tmp = prev >> 8;
- pd = prev ^ value;
- pd1 = pd & 0x000F;
- pd2 = ((pd >> 4) & 0x000F) ^ pd1;
- tmp ^= (pd1 << 3) | (pd1 << 8);
- tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
-
- return tmp;
-}
-
-uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
-{
- uint32_t i;
- uint16_t crc = 0xFFFF;
- int odd;
-
- odd = count & 1;
- count &= ~1;
- for (i = 0; i != count; i++) {
- crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
- }
- if (odd) {
- crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
- }
-
- return crc;
-}
-
-#define CMDLINE_ADDR 0x017ff000
-
-int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
- const unsigned char *arch,
- uint32_t RAM_size, int boot_device,
- uint32_t kernel_image, uint32_t kernel_size,
- const char *cmdline,
- uint32_t initrd_image, uint32_t initrd_size,
- uint32_t NVRAM_image,
- int width, int height, int depth)
-{
- uint16_t crc;
-
- /* Set parameters for Open Hack'Ware BIOS */
- NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
- NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
- NVRAM_set_word(nvram, 0x14, NVRAM_size);
- NVRAM_set_string(nvram, 0x20, arch, 16);
- NVRAM_set_lword(nvram, 0x30, RAM_size);
- NVRAM_set_byte(nvram, 0x34, boot_device);
- NVRAM_set_lword(nvram, 0x38, kernel_image);
- NVRAM_set_lword(nvram, 0x3C, kernel_size);
- if (cmdline) {
- /* XXX: put the cmdline in NVRAM too ? */
- strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
- NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
- NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
- } else {
- NVRAM_set_lword(nvram, 0x40, 0);
- NVRAM_set_lword(nvram, 0x44, 0);
- }
- NVRAM_set_lword(nvram, 0x48, initrd_image);
- NVRAM_set_lword(nvram, 0x4C, initrd_size);
- NVRAM_set_lword(nvram, 0x50, NVRAM_image);
-
- NVRAM_set_word(nvram, 0x54, width);
- NVRAM_set_word(nvram, 0x56, height);
- NVRAM_set_word(nvram, 0x58, depth);
- crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
- NVRAM_set_word(nvram, 0xFC, crc);
-
- return 0;
-}
diff --git a/hw/ppc_chrp.c b/hw/ppc_chrp.c
deleted file mode 100644
index 42d5995..0000000
--- a/hw/ppc_chrp.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * QEMU PPC CHRP/PMAC hardware System Emulator
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-#define BIOS_FILENAME "ppc_rom.bin"
-#define VGABIOS_FILENAME "video.x"
-#define NVRAM_SIZE 0x2000
-
-#define KERNEL_LOAD_ADDR 0x01000000
-#define INITRD_LOAD_ADDR 0x01800000
-
-/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
- NVRAM */
-
-static int dbdma_mem_index;
-static int cuda_mem_index;
-static int ide0_mem_index = -1;
-static int ide1_mem_index = -1;
-static int openpic_mem_index = -1;
-static int heathrow_pic_mem_index = -1;
-static int macio_nvram_mem_index = -1;
-
-/* DBDMA: currently no op - should suffice right now */
-
-static void dbdma_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- printf("%s: 0x%08x <= 0x%08x\n", __func__, addr, value);
-}
-
-static void dbdma_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static void dbdma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
-{
- printf("%s: 0x%08x => 0x00000000\n", __func__, addr);
- return 0;
-}
-
-static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static CPUWriteMemoryFunc *dbdma_write[] = {
- &dbdma_writeb,
- &dbdma_writew,
- &dbdma_writel,
-};
-
-static CPUReadMemoryFunc *dbdma_read[] = {
- &dbdma_readb,
- &dbdma_readw,
- &dbdma_readl,
-};
-
-/* macio style NVRAM device */
-typedef struct MacIONVRAMState {
- uint8_t data[0x2000];
-} MacIONVRAMState;
-
-static void macio_nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- MacIONVRAMState *s = opaque;
- addr = (addr >> 4) & 0x1fff;
- s->data[addr] = value;
- // printf("macio_nvram_writeb %04x = %02x\n", addr, value);
-}
-
-static uint32_t macio_nvram_readb (void *opaque, target_phys_addr_t addr)
-{
- MacIONVRAMState *s = opaque;
- uint32_t value;
-
- addr = (addr >> 4) & 0x1fff;
- value = s->data[addr];
- // printf("macio_nvram_readb %04x = %02x\n", addr, value);
- return value;
-}
-
-static CPUWriteMemoryFunc *macio_nvram_write[] = {
- &macio_nvram_writeb,
- &macio_nvram_writeb,
- &macio_nvram_writeb,
-};
-
-static CPUReadMemoryFunc *macio_nvram_read[] = {
- &macio_nvram_readb,
- &macio_nvram_readb,
- &macio_nvram_readb,
-};
-
-static MacIONVRAMState *macio_nvram_init(void)
-{
- MacIONVRAMState *s;
- s = qemu_mallocz(sizeof(MacIONVRAMState));
- if (!s)
- return NULL;
- macio_nvram_mem_index = cpu_register_io_memory(0, macio_nvram_read,
- macio_nvram_write, s);
- return s;
-}
-
-static void macio_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- if (heathrow_pic_mem_index >= 0) {
- cpu_register_physical_memory(addr + 0x00000, 0x1000,
- heathrow_pic_mem_index);
- }
- cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
- cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
- if (ide0_mem_index >= 0)
- cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index);
- if (ide1_mem_index >= 0)
- cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index);
- if (openpic_mem_index >= 0) {
- cpu_register_physical_memory(addr + 0x40000, 0x40000,
- openpic_mem_index);
- }
- if (macio_nvram_mem_index >= 0)
- cpu_register_physical_memory(addr + 0x60000, 0x20000, macio_nvram_mem_index);
-}
-
-static void macio_init(PCIBus *bus, int device_id)
-{
- PCIDevice *d;
-
- d = pci_register_device(bus, "macio", sizeof(PCIDevice),
- -1, NULL, NULL);
- /* Note: this code is strongly inspirated from the corresponding code
- in PearPC */
- d->config[0x00] = 0x6b; // vendor_id
- d->config[0x01] = 0x10;
- d->config[0x02] = device_id;
- d->config[0x03] = device_id >> 8;
-
- d->config[0x0a] = 0x00; // class_sub = pci2pci
- d->config[0x0b] = 0xff; // class_base = bridge
- d->config[0x0e] = 0x00; // header_type
-
- d->config[0x3d] = 0x01; // interrupt on pin 1
-
- dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
-
- pci_register_io_region(d, 0, 0x80000,
- PCI_ADDRESS_SPACE_MEM, macio_map);
-}
-
-/* UniN device */
-static void unin_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-}
-
-static uint32_t unin_readl (void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static CPUWriteMemoryFunc *unin_write[] = {
- &unin_writel,
- &unin_writel,
- &unin_writel,
-};
-
-static CPUReadMemoryFunc *unin_read[] = {
- &unin_readl,
- &unin_readl,
- &unin_readl,
-};
-
-/* temporary frame buffer OSI calls for the video.x driver. The right
- solution is to modify the driver to use VGA PCI I/Os */
-static int vga_osi_call(CPUState *env)
-{
- static int vga_vbl_enabled;
- int linesize;
-
- // printf("osi_call R5=%d\n", env->gpr[5]);
-
- /* same handler as PearPC, coming from the original MOL video
- driver. */
- switch(env->gpr[5]) {
- case 4:
- break;
- case 28: /* set_vmode */
- if (env->gpr[6] != 1 || env->gpr[7] != 0)
- env->gpr[3] = 1;
- else
- env->gpr[3] = 0;
- break;
- case 29: /* get_vmode_info */
- if (env->gpr[6] != 0) {
- if (env->gpr[6] != 1 || env->gpr[7] != 0) {
- env->gpr[3] = 1;
- break;
- }
- }
- env->gpr[3] = 0;
- env->gpr[4] = (1 << 16) | 1; /* num_vmodes, cur_vmode */
- env->gpr[5] = (1 << 16) | 0; /* num_depths, cur_depth_mode */
- env->gpr[6] = (graphic_width << 16) | graphic_height; /* w, h */
- env->gpr[7] = 85 << 16; /* refresh rate */
- env->gpr[8] = (graphic_depth + 7) & ~7; /* depth (round to byte) */
- linesize = ((graphic_depth + 7) >> 3) * graphic_width;
- linesize = (linesize + 3) & ~3;
- env->gpr[9] = (linesize << 16) | 0; /* row_bytes, offset */
- break;
- case 31: /* set_video power */
- env->gpr[3] = 0;
- break;
- case 39: /* video_ctrl */
- if (env->gpr[6] == 0 || env->gpr[6] == 1)
- vga_vbl_enabled = env->gpr[6];
- env->gpr[3] = 0;
- break;
- case 47:
- break;
- case 59: /* set_color */
- /* R6 = index, R7 = RGB */
- env->gpr[3] = 0;
- break;
- case 64: /* get color */
- /* R6 = index */
- env->gpr[3] = 0;
- break;
- case 116: /* set hwcursor */
- /* R6 = x, R7 = y, R8 = visible, R9 = data */
- break;
- default:
- fprintf(stderr, "unsupported OSI call R5=%08x\n", env->gpr[5]);
- break;
- }
- return 1; /* osi_call handled */
-}
-
-/* XXX: suppress that */
-static void pic_irq_request(void *opaque, int level)
-{
-}
-
-static uint8_t nvram_chksum(const uint8_t *buf, int n)
-{
- int sum, i;
- sum = 0;
- for(i = 0; i < n; i++)
- sum += buf[i];
- return (sum & 0xff) + (sum >> 8);
-}
-
-/* set a free Mac OS NVRAM partition */
-void pmac_format_nvram_partition(uint8_t *buf, int len)
-{
- char partition_name[12] = "wwwwwwwwwwww";
-
- buf[0] = 0x7f; /* free partition magic */
- buf[1] = 0; /* checksum */
- buf[2] = len >> 8;
- buf[3] = len;
- memcpy(buf + 4, partition_name, 12);
- buf[1] = nvram_chksum(buf, 16);
-}
-
-/* PowerPC CHRP hardware initialisation */
-static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- int is_heathrow)
-{
- CPUState *env;
- char buf[1024];
- SetIRQFunc *set_irq;
- void *pic;
- m48t59_t *nvram;
- int PPC_io_memory, unin_memory;
- int linux_boot, i;
- unsigned long bios_offset, vga_bios_offset;
- uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
- ppc_def_t *def;
- PCIBus *pci_bus;
- const char *arch_name;
- int vga_bios_size, bios_size;
-
- linux_boot = (kernel_filename != NULL);
-
- /* init CPUs */
- env = cpu_init();
- register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
-
- /* Register CPU as a 74x/75x */
- /* XXX: CPU model (or PVR) should be provided on command line */
- // ppc_find_by_name("750gx", &def); // Linux boot OK
- // ppc_find_by_name("750fx", &def); // Linux boot OK
- /* Linux does not boot on 750cxe (and probably other 750cx based)
- * because it assumes it has 8 IBAT & DBAT pairs as it only have 4.
- */
- // ppc_find_by_name("750cxe", &def);
- // ppc_find_by_name("750p", &def);
- // ppc_find_by_name("740p", &def);
- ppc_find_by_name("750", &def);
- // ppc_find_by_name("740", &def);
- // ppc_find_by_name("G3", &def);
- // ppc_find_by_name("604r", &def);
- // ppc_find_by_name("604e", &def);
- // ppc_find_by_name("604", &def);
- if (def == NULL) {
- cpu_abort(env, "Unable to find PowerPC CPU definition\n");
- }
- cpu_ppc_register(env, def);
-
- /* Set time-base frequency to 100 Mhz */
- cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
-
- env->osi_call = vga_osi_call;
-
- /* allocate RAM */
- cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
-
- /* allocate and load BIOS */
- bios_offset = ram_size + vga_ram_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
- bios_size = load_image(buf, phys_ram_base + bios_offset);
- if (bios_size < 0 || bios_size > BIOS_SIZE) {
- fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
- exit(1);
- }
- bios_size = (bios_size + 0xfff) & ~0xfff;
- cpu_register_physical_memory((uint32_t)(-bios_size),
- bios_size, bios_offset | IO_MEM_ROM);
-
- /* allocate and load VGA BIOS */
- vga_bios_offset = bios_offset + bios_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
- vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
- if (vga_bios_size < 0) {
- /* if no bios is present, we can still work */
- fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
- vga_bios_size = 0;
- } else {
- /* set a specific header (XXX: find real Apple format for NDRV
- drivers) */
- phys_ram_base[vga_bios_offset] = 'N';
- phys_ram_base[vga_bios_offset + 1] = 'D';
- phys_ram_base[vga_bios_offset + 2] = 'R';
- phys_ram_base[vga_bios_offset + 3] = 'V';
- cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
- vga_bios_size);
- vga_bios_size += 8;
- }
- vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;
-
- if (linux_boot) {
- kernel_base = KERNEL_LOAD_ADDR;
- /* now we can load the kernel */
- kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
- if (kernel_size < 0) {
- fprintf(stderr, "qemu: could not load kernel '%s'\n",
- kernel_filename);
- exit(1);
- }
- /* load initrd */
- if (initrd_filename) {
- initrd_base = INITRD_LOAD_ADDR;
- initrd_size = load_image(initrd_filename,
- phys_ram_base + initrd_base);
- if (initrd_size < 0) {
- fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- initrd_filename);
- exit(1);
- }
- } else {
- initrd_base = 0;
- initrd_size = 0;
- }
- boot_device = 'm';
- } else {
- kernel_base = 0;
- kernel_size = 0;
- initrd_base = 0;
- initrd_size = 0;
- }
-
- if (is_heathrow) {
- isa_mem_base = 0x80000000;
-
- /* Register 2 MB of ISA IO space */
- PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
- cpu_register_physical_memory(0xfe000000, 0x00200000, PPC_io_memory);
-
- /* init basic PC hardware */
- pic = heathrow_pic_init(&heathrow_pic_mem_index);
- set_irq = heathrow_pic_set_irq;
- pci_bus = pci_grackle_init(0xfec00000, pic);
- vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
- ram_size, vga_ram_size,
- vga_bios_offset, vga_bios_size);
-
- /* XXX: suppress that */
- isa_pic = pic_init(pic_irq_request, NULL);
-
- /* XXX: use Mac Serial port */
- serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
-
- for(i = 0; i < nb_nics; i++) {
- if (!nd_table[i].model)
- nd_table[i].model = "ne2k_pci";
- pci_nic_init(pci_bus, &nd_table[i]);
- }
-
- pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
-
- /* cuda also initialize ADB */
- cuda_mem_index = cuda_init(set_irq, pic, 0x12);
-
- adb_kbd_init(&adb_bus);
- adb_mouse_init(&adb_bus);
-
- {
- MacIONVRAMState *nvr;
- nvr = macio_nvram_init();
- pmac_format_nvram_partition(nvr->data, 0x2000);
- }
-
- macio_init(pci_bus, 0x0017);
-
- nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
-
- arch_name = "HEATHROW";
- } else {
- isa_mem_base = 0x80000000;
-
- /* Register 8 MB of ISA IO space */
- PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
- cpu_register_physical_memory(0xF2000000, 0x00800000, PPC_io_memory);
-
- /* UniN init */
- unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
- cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
-
- pic = openpic_init(NULL, &openpic_mem_index, 1, &env);
- set_irq = openpic_set_irq;
- pci_bus = pci_pmac_init(pic);
- /* init basic PC hardware */
- vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
- ram_size, vga_ram_size,
- vga_bios_offset, vga_bios_size);
-
- /* XXX: suppress that */
- isa_pic = pic_init(pic_irq_request, NULL);
-
- /* XXX: use Mac Serial port */
- serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
-
- for(i = 0; i < nb_nics; i++) {
- pci_ne2000_init(pci_bus, &nd_table[i]);
- }
-
-#if 1
- ide0_mem_index = pmac_ide_init(&bs_table[0], set_irq, pic, 0x13);
- ide1_mem_index = pmac_ide_init(&bs_table[2], set_irq, pic, 0x14);
-#else
- pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
-#endif
- /* cuda also initialize ADB */
- cuda_mem_index = cuda_init(set_irq, pic, 0x19);
-
- adb_kbd_init(&adb_bus);
- adb_mouse_init(&adb_bus);
-
- macio_init(pci_bus, 0x0022);
-
- nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
-
- arch_name = "MAC99";
- }
-
- if (usb_enabled) {
- usb_ohci_init(pci_bus, 3, -1);
- }
-
- if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
- graphic_depth = 15;
-
- PPC_NVRAM_set_params(nvram, NVRAM_SIZE, arch_name, ram_size, boot_device,
- kernel_base, kernel_size,
- kernel_cmdline,
- initrd_base, initrd_size,
- /* XXX: need an option to load a NVRAM image */
- 0,
- graphic_width, graphic_height, graphic_depth);
- /* No PCI init: the BIOS will do it */
-
- /* Special port to get debug messages from Open-Firmware */
- register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
-}
-
-static void ppc_core99_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename)
-{
- ppc_chrp_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, 0);
-}
-
-static void ppc_heathrow_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename,
- int snapshot,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename)
-{
- ppc_chrp_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, 1);
-}
-
-QEMUMachine core99_machine = {
- "mac99",
- "Mac99 based PowerMAC",
- ppc_core99_init,
-};
-
-QEMUMachine heathrow_machine = {
- "g3bw",
- "Heathrow based PowerMAC",
- ppc_heathrow_init,
-};
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
deleted file mode 100644
index a4d7ddf..0000000
--- a/hw/ppc_prep.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * QEMU PPC PREP hardware System Emulator
- *
- * Copyright (c) 2003-2004 Jocelyn Mayer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define HARD_DEBUG_PPC_IO
-//#define DEBUG_PPC_IO
-
-#define BIOS_FILENAME "ppc_rom.bin"
-#define KERNEL_LOAD_ADDR 0x01000000
-#define INITRD_LOAD_ADDR 0x01800000
-
-extern int loglevel;
-extern FILE *logfile;
-
-#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
-#define DEBUG_PPC_IO
-#endif
-
-#if defined (HARD_DEBUG_PPC_IO)
-#define PPC_IO_DPRINTF(fmt, args...) \
-do { \
- if (loglevel & CPU_LOG_IOPORT) { \
- fprintf(logfile, "%s: " fmt, __func__ , ##args); \
- } else { \
- printf("%s : " fmt, __func__ , ##args); \
- } \
-} while (0)
-#elif defined (DEBUG_PPC_IO)
-#define PPC_IO_DPRINTF(fmt, args...) \
-do { \
- if (loglevel & CPU_LOG_IOPORT) { \
- fprintf(logfile, "%s: " fmt, __func__ , ##args); \
- } \
-} while (0)
-#else
-#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
-#endif
-
-/* Constants for devices init */
-static const int ide_iobase[2] = { 0x1f0, 0x170 };
-static const int ide_iobase2[2] = { 0x3f6, 0x376 };
-static const int ide_irq[2] = { 13, 13 };
-
-#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 };
-
-//static PITState *pit;
-
-/* ISA IO ports bridge */
-#define PPC_IO_BASE 0x80000000
-
-/* Speaker port 0x61 */
-int speaker_data_on;
-int dummy_refresh_clock;
-
-static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
-#if 0
- speaker_data_on = (val >> 1) & 1;
- pit_set_gate(pit, 2, val & 1);
-#endif
-}
-
-static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
-{
-#if 0
- int out;
- out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
- dummy_refresh_clock ^= 1;
- return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
- (dummy_refresh_clock << 4);
-#endif
- return 0;
-}
-
-static void pic_irq_request(void *opaque, int level)
-{
- if (level)
- cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
- else
- cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
-}
-
-/* PCI intack register */
-/* Read-only register (?) */
-static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- // printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
-}
-
-static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
-{
- uint32_t retval = 0;
-
- if (addr == 0xBFFFFFF0)
- retval = pic_intack_read(isa_pic);
- // printf("%s: 0x%08x <= %d\n", __func__, addr, retval);
-
- return retval;
-}
-
-static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
-{
- return _PPC_intack_read(addr);
-}
-
-static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- return bswap16(_PPC_intack_read(addr));
-#else
- return _PPC_intack_read(addr);
-#endif
-}
-
-static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- return bswap32(_PPC_intack_read(addr));
-#else
- return _PPC_intack_read(addr);
-#endif
-}
-
-static CPUWriteMemoryFunc *PPC_intack_write[] = {
- &_PPC_intack_write,
- &_PPC_intack_write,
- &_PPC_intack_write,
-};
-
-static CPUReadMemoryFunc *PPC_intack_read[] = {
- &PPC_intack_readb,
- &PPC_intack_readw,
- &PPC_intack_readl,
-};
-
-/* PowerPC control and status registers */
-#if 0 // Not used
-static struct {
- /* IDs */
- uint32_t veni_devi;
- uint32_t revi;
- /* Control and status */
- uint32_t gcsr;
- uint32_t xcfr;
- uint32_t ct32;
- uint32_t mcsr;
- /* General purpose registers */
- uint32_t gprg[6];
- /* Exceptions */
- uint32_t feen;
- uint32_t fest;
- uint32_t fema;
- uint32_t fecl;
- uint32_t eeen;
- uint32_t eest;
- uint32_t eecl;
- uint32_t eeint;
- uint32_t eemck0;
- uint32_t eemck1;
- /* Error diagnostic */
-} XCSR;
-
-static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
- printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
-}
-
-static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap16(value);
-#endif
- printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
-}
-
-static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap32(value);
-#endif
- printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
-}
-
-static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
-{
- uint32_t retval = 0;
-
- printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
-
- return retval;
-}
-
-static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
-{
- uint32_t retval = 0;
-
- printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
-#ifdef TARGET_WORDS_BIGENDIAN
- retval = bswap16(retval);
-#endif
-
- return retval;
-}
-
-static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
-{
- uint32_t retval = 0;
-
- printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
-#ifdef TARGET_WORDS_BIGENDIAN
- retval = bswap32(retval);
-#endif
-
- return retval;
-}
-
-static CPUWriteMemoryFunc *PPC_XCSR_write[] = {
- &PPC_XCSR_writeb,
- &PPC_XCSR_writew,
- &PPC_XCSR_writel,
-};
-
-static CPUReadMemoryFunc *PPC_XCSR_read[] = {
- &PPC_XCSR_readb,
- &PPC_XCSR_readw,
- &PPC_XCSR_readl,
-};
-#endif
-
-/* Fake super-io ports for PREP platform (Intel 82378ZB) */
-typedef struct sysctrl_t {
- m48t59_t *nvram;
- uint8_t state;
- uint8_t syscontrol;
- uint8_t fake_io[2];
- int contiguous_map;
- int endian;
-} sysctrl_t;
-
-enum {
- STATE_HARDFILE = 0x01,
-};
-
-static sysctrl_t *sysctrl;
-
-static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
-{
- sysctrl_t *sysctrl = opaque;
-
- PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
- sysctrl->fake_io[addr - 0x0398] = val;
-}
-
-static uint32_t PREP_io_read (void *opaque, uint32_t addr)
-{
- sysctrl_t *sysctrl = opaque;
-
- PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE,
- sysctrl->fake_io[addr - 0x0398]);
- return sysctrl->fake_io[addr - 0x0398];
-}
-
-static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
-{
- sysctrl_t *sysctrl = opaque;
-
- PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
- switch (addr) {
- case 0x0092:
- /* Special port 92 */
- /* Check soft reset asked */
- if (val & 0x01) {
- // cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET);
- }
- /* Check LE mode */
- if (val & 0x02) {
- sysctrl->endian = 1;
- } else {
- sysctrl->endian = 0;
- }
- break;
- case 0x0800:
- /* Motorola CPU configuration register : read-only */
- break;
- case 0x0802:
- /* Motorola base module feature register : read-only */
- break;
- case 0x0803:
- /* Motorola base module status register : read-only */
- break;
- case 0x0808:
- /* Hardfile light register */
- if (val & 1)
- sysctrl->state |= STATE_HARDFILE;
- else
- sysctrl->state &= ~STATE_HARDFILE;
- break;
- case 0x0810:
- /* Password protect 1 register */
- if (sysctrl->nvram != NULL)
- m48t59_toggle_lock(sysctrl->nvram, 1);
- break;
- case 0x0812:
- /* Password protect 2 register */
- if (sysctrl->nvram != NULL)
- m48t59_toggle_lock(sysctrl->nvram, 2);
- break;
- case 0x0814:
- /* L2 invalidate register */
- // tlb_flush(first_cpu, 1);
- break;
- case 0x081C:
- /* system control register */
- sysctrl->syscontrol = val & 0x0F;
- break;
- case 0x0850:
- /* I/O map type register */
- sysctrl->contiguous_map = val & 0x01;
- break;
- default:
- printf("ERROR: unaffected IO port write: %04lx => %02x\n",
- (long)addr, val);
- break;
- }
-}
-
-static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
-{
- sysctrl_t *sysctrl = opaque;
- uint32_t retval = 0xFF;
-
- switch (addr) {
- case 0x0092:
- /* Special port 92 */
- retval = 0x00;
- break;
- case 0x0800:
- /* Motorola CPU configuration register */
- retval = 0xEF; /* MPC750 */
- break;
- case 0x0802:
- /* Motorola Base module feature register */
- retval = 0xAD; /* No ESCC, PMC slot neither ethernet */
- break;
- case 0x0803:
- /* Motorola base module status register */
- retval = 0xE0; /* Standard MPC750 */
- break;
- case 0x080C:
- /* Equipment present register:
- * no L2 cache
- * no upgrade processor
- * no cards in PCI slots
- * SCSI fuse is bad
- */
- retval = 0x3C;
- break;
- case 0x0810:
- /* Motorola base module extended feature register */
- retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
- break;
- case 0x0814:
- /* L2 invalidate: don't care */
- break;
- case 0x0818:
- /* Keylock */
- retval = 0x00;
- break;
- case 0x081C:
- /* system control register
- * 7 - 6 / 1 - 0: L2 cache enable
- */
- retval = sysctrl->syscontrol;
- break;
- case 0x0823:
- /* */
- retval = 0x03; /* no L2 cache */
- break;
- case 0x0850:
- /* I/O map type register */
- retval = sysctrl->contiguous_map;
- break;
- default:
- printf("ERROR: unaffected IO port: %04lx read\n", (long)addr);
- break;
- }
- PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval);
-
- return retval;
-}
-
-static inline target_phys_addr_t prep_IO_address (sysctrl_t *sysctrl,
- target_phys_addr_t addr)
-{
- if (sysctrl->contiguous_map == 0) {
- /* 64 KB contiguous space for IOs */
- addr &= 0xFFFF;
- } else {
- /* 8 MB non-contiguous space for IOs */
- addr = (addr & 0x1F) | ((addr & 0x007FFF000) >> 7);
- }
-
- return addr;
-}
-
-static void PPC_prep_io_writeb (void *opaque, target_phys_addr_t addr,
- uint32_t value)
-{
- sysctrl_t *sysctrl = opaque;
-
- addr = prep_IO_address(sysctrl, addr);
- cpu_outb(NULL, addr, value);
-}
-
-static uint32_t PPC_prep_io_readb (void *opaque, target_phys_addr_t addr)
-{
- sysctrl_t *sysctrl = opaque;
- uint32_t ret;
-
- addr = prep_IO_address(sysctrl, addr);
- ret = cpu_inb(NULL, addr);
-
- return ret;
-}
-
-static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr,
- uint32_t value)
-{
- sysctrl_t *sysctrl = opaque;
-
- addr = prep_IO_address(sysctrl, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap16(value);
-#endif
- PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value);
- cpu_outw(NULL, addr, value);
-}
-
-static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr)
-{
- sysctrl_t *sysctrl = opaque;
- uint32_t ret;
-
- addr = prep_IO_address(sysctrl, addr);
- ret = cpu_inw(NULL, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = bswap16(ret);
-#endif
- PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret);
-
- return ret;
-}
-
-static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr,
- uint32_t value)
-{
- sysctrl_t *sysctrl = opaque;
-
- addr = prep_IO_address(sysctrl, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
- value = bswap32(value);
-#endif
- PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr, value);
- cpu_outl(NULL, addr, value);
-}
-
-static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr)
-{
- sysctrl_t *sysctrl = opaque;
- uint32_t ret;
-
- addr = prep_IO_address(sysctrl, addr);
- ret = cpu_inl(NULL, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = bswap32(ret);
-#endif
- PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr, ret);
-
- return ret;
-}
-
-CPUWriteMemoryFunc *PPC_prep_io_write[] = {
- &PPC_prep_io_writeb,
- &PPC_prep_io_writew,
- &PPC_prep_io_writel,
-};
-
-CPUReadMemoryFunc *PPC_prep_io_read[] = {
- &PPC_prep_io_readb,
- &PPC_prep_io_readw,
- &PPC_prep_io_readl,
-};
-
-#define NVRAM_SIZE 0x2000
-
-/* PowerPC PREP hardware initialisation */
-static void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- CPUState *env;
- char buf[1024];
- SetIRQFunc *set_irq;
- m48t59_t *nvram;
- int PPC_io_memory;
- int linux_boot, i, nb_nics1, bios_size;
- unsigned long bios_offset;
- uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
- ppc_def_t *def;
- PCIBus *pci_bus;
-
- sysctrl = qemu_mallocz(sizeof(sysctrl_t));
- if (sysctrl == NULL)
- return;
-
- linux_boot = (kernel_filename != NULL);
-
- /* init CPUs */
-
- env = cpu_init();
- register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
-
- /* Register CPU as a 604 */
- /* XXX: CPU model (or PVR) should be provided on command line */
- // ppc_find_by_name("604r", &def);
- // ppc_find_by_name("604e", &def);
- ppc_find_by_name("604", &def);
- if (def == NULL) {
- cpu_abort(env, "Unable to find PowerPC CPU definition\n");
- }
- cpu_ppc_register(env, def);
- /* Set time-base frequency to 100 Mhz */
- cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
-
- /* allocate RAM */
- cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
-
- /* allocate and load BIOS */
- bios_offset = ram_size + vga_ram_size;
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
- bios_size = load_image(buf, phys_ram_base + bios_offset);
- if (bios_size < 0 || bios_size > BIOS_SIZE) {
- fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
- exit(1);
- }
- bios_size = (bios_size + 0xfff) & ~0xfff;
- cpu_register_physical_memory((uint32_t)(-bios_size),
- bios_size, bios_offset | IO_MEM_ROM);
-
- if (linux_boot) {
- kernel_base = KERNEL_LOAD_ADDR;
- /* now we can load the kernel */
- kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
- if (kernel_size < 0) {
- fprintf(stderr, "qemu: could not load kernel '%s'\n",
- kernel_filename);
- exit(1);
- }
- /* load initrd */
- if (initrd_filename) {
- initrd_base = INITRD_LOAD_ADDR;
- initrd_size = load_image(initrd_filename,
- phys_ram_base + initrd_base);
- if (initrd_size < 0) {
- fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- initrd_filename);
- exit(1);
- }
- } else {
- initrd_base = 0;
- initrd_size = 0;
- }
- boot_device = 'm';
- } else {
- kernel_base = 0;
- kernel_size = 0;
- initrd_base = 0;
- initrd_size = 0;
- }
-
- isa_mem_base = 0xc0000000;
- pci_bus = pci_prep_init();
- // pci_bus = i440fx_init();
- /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
- PPC_io_memory = cpu_register_io_memory(0, PPC_prep_io_read,
- PPC_prep_io_write, sysctrl);
- cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
-
- /* init basic PC hardware */
- vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
- vga_ram_size, 0, 0);
- rtc_init(0x70, 8);
- // openpic = openpic_init(0x00000000, 0xF0000000, 1);
- isa_pic = pic_init(pic_irq_request, first_cpu);
- // pit = pit_init(0x40, 0);
-
- serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
- nb_nics1 = nb_nics;
- if (nb_nics1 > NE2000_NB_MAX)
- nb_nics1 = NE2000_NB_MAX;
- for(i = 0; i < nb_nics1; i++) {
- if (nd_table[0].model == NULL
- || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
- isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
- } else {
- fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
- exit (1);
- }
- }
-
- for(i = 0; i < 2; i++) {
- isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
- bs_table[2 * i], bs_table[2 * i + 1]);
- }
- kbd_init();
- DMA_init(1);
- // AUD_init();
- // SB16_init();
-
- fdctrl_init(6, 2, 0, 0x3f0, fd_table);
-
- /* Register speaker port */
- register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
- register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
- /* Register fake IO ports for PREP */
- register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
- register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
- /* System control ports */
- register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
- register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
- register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
- register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
- /* PCI intack location */
- PPC_io_memory = cpu_register_io_memory(0, PPC_intack_read,
- PPC_intack_write, NULL);
- cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
- /* PowerPC control and status register group */
-#if 0
- PPC_io_memory = cpu_register_io_memory(0, PPC_XCSR_read, PPC_XCSR_write, NULL);
- cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
-#endif
-
- if (usb_enabled) {
- usb_ohci_init(pci_bus, 3, -1);
- }
-
- nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
- if (nvram == NULL)
- return;
- sysctrl->nvram = nvram;
-
- /* Initialise NVRAM */
- PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
- kernel_base, kernel_size,
- kernel_cmdline,
- initrd_base, initrd_size,
- /* XXX: need an option to load a NVRAM image */
- 0,
- graphic_width, graphic_height, graphic_depth);
-
- /* Special port to get debug messages from Open-Firmware */
- register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
-}
-
-QEMUMachine prep_machine = {
- "prep",
- "PowerPC PREP platform",
- ppc_prep_init,
-};
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
deleted file mode 100644
index a31b74c..0000000
--- a/hw/prep_pci.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * QEMU PREP PCI host
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "vl.h"
-typedef uint32_t pci_addr_t;
-#include "pci_host.h"
-
-typedef PCIHostState PREPPCIState;
-
-static void pci_prep_addr_writel(void* opaque, uint32_t addr, uint32_t val)
-{
- PREPPCIState *s = opaque;
- s->config_reg = val;
-}
-
-static uint32_t pci_prep_addr_readl(void* opaque, uint32_t addr)
-{
- PREPPCIState *s = opaque;
- return s->config_reg;
-}
-
-static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
-{
- int i;
-
- for(i = 0; i < 11; i++) {
- if ((addr & (1 << (11 + i))) != 0)
- break;
- }
- return (addr & 0x7ff) | (i << 11);
-}
-
-static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PREPPCIState *s = opaque;
- pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 1);
-}
-
-static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PREPPCIState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap16(val);
-#endif
- pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 2);
-}
-
-static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- PREPPCIState *s = opaque;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 4);
-}
-
-static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr)
-{
- PREPPCIState *s = opaque;
- uint32_t val;
- val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 1);
- return val;
-}
-
-static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr)
-{
- PREPPCIState *s = opaque;
- uint32_t val;
- val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 2);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap16(val);
-#endif
- return val;
-}
-
-static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr)
-{
- PREPPCIState *s = opaque;
- uint32_t val;
- val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 4);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- return val;
-}
-
-static CPUWriteMemoryFunc *PPC_PCIIO_write[] = {
- &PPC_PCIIO_writeb,
- &PPC_PCIIO_writew,
- &PPC_PCIIO_writel,
-};
-
-static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
- &PPC_PCIIO_readb,
- &PPC_PCIIO_readw,
- &PPC_PCIIO_readl,
-};
-
-static void prep_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
-{
- /* XXX: we do not simulate the hardware - we rely on the BIOS to
- set correctly for irq line field */
- pic_set_irq(d->config[PCI_INTERRUPT_LINE], level);
-}
-
-PCIBus *pci_prep_init(void)
-{
- PREPPCIState *s;
- PCIDevice *d;
- int PPC_io_memory;
-
- s = qemu_mallocz(sizeof(PREPPCIState));
- s->bus = pci_register_bus(prep_set_irq, NULL, 0);
-
- register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
- register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
-
- register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
- register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
- register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
- register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
- register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
- register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
-
- PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read,
- PPC_PCIIO_write, s);
- cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
-
- /* PCI host bridge */
- d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven",
- sizeof(PCIDevice), 0, NULL, NULL);
- d->config[0x00] = 0x57; // vendor_id : Motorola
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x01; // device_id : Raven
- d->config[0x03] = 0x48;
- d->config[0x08] = 0x00; // revision
- d->config[0x0A] = 0x00; // class_sub = pci host
- d->config[0x0B] = 0x06; // class_base = PCI_bridge
- d->config[0x0C] = 0x08; // cache_line_size
- d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
- d->config[0x34] = 0x00; // capabilities_pointer
-
- return s->bus;
-}
-
diff --git a/hw/ps2.c b/hw/ps2.c
deleted file mode 100644
index 8438a5e..0000000
--- a/hw/ps2.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * QEMU PS/2 keyboard/mouse emulation
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-/* debug PC keyboard */
-//#define DEBUG_KBD
-
-/* debug PC keyboard : only mouse */
-//#define DEBUG_MOUSE
-
-/* Keyboard Commands */
-#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
-#define KBD_CMD_ECHO 0xEE
-#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
-#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
-#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
-#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
-#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
-#define KBD_CMD_RESET 0xFF /* Reset */
-
-/* Keyboard Replies */
-#define KBD_REPLY_POR 0xAA /* Power on reset */
-#define KBD_REPLY_ACK 0xFA /* Command ACK */
-#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
-
-/* Mouse Commands */
-#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
-#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
-#define AUX_SET_RES 0xE8 /* Set resolution */
-#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
-#define AUX_SET_STREAM 0xEA /* Set stream mode */
-#define AUX_POLL 0xEB /* Poll */
-#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
-#define AUX_SET_WRAP 0xEE /* Set wrap mode */
-#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
-#define AUX_GET_TYPE 0xF2 /* Get type */
-#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
-#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
-#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
-#define AUX_SET_DEFAULT 0xF6
-#define AUX_RESET 0xFF /* Reset aux device */
-#define AUX_ACK 0xFA /* Command byte ACK. */
-
-#define MOUSE_STATUS_REMOTE 0x40
-#define MOUSE_STATUS_ENABLED 0x20
-#define MOUSE_STATUS_SCALE21 0x10
-
-#define PS2_QUEUE_SIZE 256
-
-typedef struct {
- uint8_t data[PS2_QUEUE_SIZE];
- int rptr, wptr, count;
-} PS2Queue;
-
-typedef struct {
- PS2Queue queue;
- int32_t write_cmd;
- void (*update_irq)(void *, int);
- void *update_arg;
-} PS2State;
-
-typedef struct {
- PS2State common;
- int scan_enabled;
- /* Qemu uses translated PC scancodes internally. To avoid multiple
- conversions we do the translation (if any) in the PS/2 emulation
- not the keyboard controller. */
- int translate;
-} PS2KbdState;
-
-typedef struct {
- PS2State common;
- uint8_t mouse_status;
- uint8_t mouse_resolution;
- uint8_t mouse_sample_rate;
- uint8_t mouse_wrap;
- uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
- uint8_t mouse_detect_state;
- int mouse_dx; /* current values, needed for 'poll' mode */
- int mouse_dy;
- int mouse_dz;
- uint8_t mouse_buttons;
-} PS2MouseState;
-
-/* Table to convert from PC scancodes to raw scancodes. */
-static const unsigned char ps2_raw_keycode[128] = {
- 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
- 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
- 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
- 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
- 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
- 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
- 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
- 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
-};
-
-void ps2_queue(void *opaque, int b)
-{
- PS2State *s = (PS2State *)opaque;
- PS2Queue *q = &s->queue;
-
- if (q->count >= PS2_QUEUE_SIZE)
- return;
- q->data[q->wptr] = b;
- if (++q->wptr == PS2_QUEUE_SIZE)
- q->wptr = 0;
- q->count++;
- s->update_irq(s->update_arg, 1);
-}
-
-static void ps2_put_keycode(void *opaque, int keycode)
-{
- PS2KbdState *s = opaque;
- if (!s->translate && keycode < 0xe0)
- {
- if (keycode & 0x80)
- ps2_queue(&s->common, 0xf0);
- keycode = ps2_raw_keycode[keycode & 0x7f];
- }
- ps2_queue(&s->common, keycode);
-}
-
-uint32_t ps2_read_data(void *opaque)
-{
- PS2State *s = (PS2State *)opaque;
- PS2Queue *q;
- int val, index;
-
- q = &s->queue;
- if (q->count == 0) {
- /* NOTE: if no data left, we return the last keyboard one
- (needed for EMM386) */
- /* XXX: need a timer to do things correctly */
- index = q->rptr - 1;
- if (index < 0)
- index = PS2_QUEUE_SIZE - 1;
- val = q->data[index];
- } else {
- val = q->data[q->rptr];
- if (++q->rptr == PS2_QUEUE_SIZE)
- q->rptr = 0;
- q->count--;
- /* reading deasserts IRQ */
- s->update_irq(s->update_arg, 0);
- /* reassert IRQs if data left */
- s->update_irq(s->update_arg, q->count != 0);
- }
- return val;
-}
-
-static void ps2_reset_keyboard(PS2KbdState *s)
-{
- s->scan_enabled = 1;
-}
-
-void ps2_write_keyboard(void *opaque, int val)
-{
- PS2KbdState *s = (PS2KbdState *)opaque;
-
- switch(s->common.write_cmd) {
- default:
- case -1:
- switch(val) {
- case 0x00:
- ps2_queue(&s->common, KBD_REPLY_ACK);
- break;
- case 0x05:
- ps2_queue(&s->common, KBD_REPLY_RESEND);
- break;
- case KBD_CMD_GET_ID:
- ps2_queue(&s->common, KBD_REPLY_ACK);
- ps2_queue(&s->common, 0xab);
- ps2_queue(&s->common, 0x83);
- break;
- case KBD_CMD_ECHO:
- ps2_queue(&s->common, KBD_CMD_ECHO);
- break;
- case KBD_CMD_ENABLE:
- s->scan_enabled = 1;
- ps2_queue(&s->common, KBD_REPLY_ACK);
- break;
- case KBD_CMD_SET_LEDS:
- case KBD_CMD_SET_RATE:
- s->common.write_cmd = val;
- ps2_queue(&s->common, KBD_REPLY_ACK);
- break;
- case KBD_CMD_RESET_DISABLE:
- ps2_reset_keyboard(s);
- s->scan_enabled = 0;
- ps2_queue(&s->common, KBD_REPLY_ACK);
- break;
- case KBD_CMD_RESET_ENABLE:
- ps2_reset_keyboard(s);
- s->scan_enabled = 1;
- ps2_queue(&s->common, KBD_REPLY_ACK);
- break;
- case KBD_CMD_RESET:
- ps2_reset_keyboard(s);
- ps2_queue(&s->common, KBD_REPLY_ACK);
- ps2_queue(&s->common, KBD_REPLY_POR);
- break;
- default:
- ps2_queue(&s->common, KBD_REPLY_ACK);
- break;
- }
- break;
- case KBD_CMD_SET_LEDS:
- ps2_queue(&s->common, KBD_REPLY_ACK);
- s->common.write_cmd = -1;
- break;
- case KBD_CMD_SET_RATE:
- ps2_queue(&s->common, KBD_REPLY_ACK);
- s->common.write_cmd = -1;
- break;
- }
-}
-
-/* Set the scancode translation mode.
- 0 = raw scancodes.
- 1 = translated scancodes (used by qemu internally). */
-
-void ps2_keyboard_set_translation(void *opaque, int mode)
-{
- PS2KbdState *s = (PS2KbdState *)opaque;
- s->translate = mode;
-}
-
-static void ps2_mouse_send_packet(PS2MouseState *s)
-{
- unsigned int b;
- int dx1, dy1, dz1;
-
- dx1 = s->mouse_dx;
- dy1 = s->mouse_dy;
- dz1 = s->mouse_dz;
- /* XXX: increase range to 8 bits ? */
- if (dx1 > 127)
- dx1 = 127;
- else if (dx1 < -127)
- dx1 = -127;
- if (dy1 > 127)
- dy1 = 127;
- else if (dy1 < -127)
- dy1 = -127;
- b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
- ps2_queue(&s->common, b);
- ps2_queue(&s->common, dx1 & 0xff);
- ps2_queue(&s->common, dy1 & 0xff);
- /* extra byte for IMPS/2 or IMEX */
- switch(s->mouse_type) {
- default:
- break;
- case 3:
- if (dz1 > 127)
- dz1 = 127;
- else if (dz1 < -127)
- dz1 = -127;
- ps2_queue(&s->common, dz1 & 0xff);
- break;
- case 4:
- if (dz1 > 7)
- dz1 = 7;
- else if (dz1 < -7)
- dz1 = -7;
- b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
- ps2_queue(&s->common, b);
- break;
- }
-
- /* update deltas */
- s->mouse_dx -= dx1;
- s->mouse_dy -= dy1;
- s->mouse_dz -= dz1;
-}
-
-static void ps2_mouse_event(void *opaque,
- int dx, int dy, int dz, int buttons_state)
-{
- PS2MouseState *s = opaque;
-
- /* check if deltas are recorded when disabled */
- if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
- return;
-
- s->mouse_dx += dx;
- s->mouse_dy -= dy;
- s->mouse_dz += dz;
- /* XXX: SDL sometimes generates nul events: we delete them */
- if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
- s->mouse_buttons == buttons_state)
- return;
- s->mouse_buttons = buttons_state;
-
- if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
- (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
- for(;;) {
- /* if not remote, send event. Multiple events are sent if
- too big deltas */
- ps2_mouse_send_packet(s);
- if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
- break;
- }
- }
-}
-
-void ps2_write_mouse(void *opaque, int val)
-{
- PS2MouseState *s = (PS2MouseState *)opaque;
-#ifdef DEBUG_MOUSE
- printf("kbd: write mouse 0x%02x\n", val);
-#endif
- switch(s->common.write_cmd) {
- default:
- case -1:
- /* mouse command */
- if (s->mouse_wrap) {
- if (val == AUX_RESET_WRAP) {
- s->mouse_wrap = 0;
- ps2_queue(&s->common, AUX_ACK);
- return;
- } else if (val != AUX_RESET) {
- ps2_queue(&s->common, val);
- return;
- }
- }
- switch(val) {
- case AUX_SET_SCALE11:
- s->mouse_status &= ~MOUSE_STATUS_SCALE21;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_SET_SCALE21:
- s->mouse_status |= MOUSE_STATUS_SCALE21;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_SET_STREAM:
- s->mouse_status &= ~MOUSE_STATUS_REMOTE;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_SET_WRAP:
- s->mouse_wrap = 1;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_SET_REMOTE:
- s->mouse_status |= MOUSE_STATUS_REMOTE;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_GET_TYPE:
- ps2_queue(&s->common, AUX_ACK);
- ps2_queue(&s->common, s->mouse_type);
- break;
- case AUX_SET_RES:
- case AUX_SET_SAMPLE:
- s->common.write_cmd = val;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_GET_SCALE:
- ps2_queue(&s->common, AUX_ACK);
- ps2_queue(&s->common, s->mouse_status);
- ps2_queue(&s->common, s->mouse_resolution);
- ps2_queue(&s->common, s->mouse_sample_rate);
- break;
- case AUX_POLL:
- ps2_queue(&s->common, AUX_ACK);
- ps2_mouse_send_packet(s);
- break;
- case AUX_ENABLE_DEV:
- s->mouse_status |= MOUSE_STATUS_ENABLED;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_DISABLE_DEV:
- s->mouse_status &= ~MOUSE_STATUS_ENABLED;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_SET_DEFAULT:
- s->mouse_sample_rate = 100;
- s->mouse_resolution = 2;
- s->mouse_status = 0;
- ps2_queue(&s->common, AUX_ACK);
- break;
- case AUX_RESET:
- s->mouse_sample_rate = 100;
- s->mouse_resolution = 2;
- s->mouse_status = 0;
- s->mouse_type = 0;
- ps2_queue(&s->common, AUX_ACK);
- ps2_queue(&s->common, 0xaa);
- ps2_queue(&s->common, s->mouse_type);
- break;
- default:
- break;
- }
- break;
- case AUX_SET_SAMPLE:
- s->mouse_sample_rate = val;
- /* detect IMPS/2 or IMEX */
- switch(s->mouse_detect_state) {
- default:
- case 0:
- if (val == 200)
- s->mouse_detect_state = 1;
- break;
- case 1:
- if (val == 100)
- s->mouse_detect_state = 2;
- else if (val == 200)
- s->mouse_detect_state = 3;
- else
- s->mouse_detect_state = 0;
- break;
- case 2:
- if (val == 80)
- s->mouse_type = 3; /* IMPS/2 */
- s->mouse_detect_state = 0;
- break;
- case 3:
- if (val == 80)
- s->mouse_type = 4; /* IMEX */
- s->mouse_detect_state = 0;
- break;
- }
- ps2_queue(&s->common, AUX_ACK);
- s->common.write_cmd = -1;
- break;
- case AUX_SET_RES:
- s->mouse_resolution = val;
- ps2_queue(&s->common, AUX_ACK);
- s->common.write_cmd = -1;
- break;
- }
-}
-
-static void ps2_reset(void *opaque)
-{
- PS2State *s = (PS2State *)opaque;
- PS2Queue *q;
- s->write_cmd = -1;
- q = &s->queue;
- q->rptr = 0;
- q->wptr = 0;
- q->count = 0;
-}
-
-static void ps2_common_save (QEMUFile *f, PS2State *s)
-{
- qemu_put_be32s (f, &s->write_cmd);
- qemu_put_be32s (f, &s->queue.rptr);
- qemu_put_be32s (f, &s->queue.wptr);
- qemu_put_be32s (f, &s->queue.count);
- qemu_put_buffer (f, s->queue.data, sizeof (s->queue.data));
-}
-
-static void ps2_common_load (QEMUFile *f, PS2State *s)
-{
- qemu_get_be32s (f, &s->write_cmd);
- qemu_get_be32s (f, &s->queue.rptr);
- qemu_get_be32s (f, &s->queue.wptr);
- qemu_get_be32s (f, &s->queue.count);
- qemu_get_buffer (f, s->queue.data, sizeof (s->queue.data));
-}
-
-static void ps2_kbd_save(QEMUFile* f, void* opaque)
-{
- PS2KbdState *s = (PS2KbdState*)opaque;
-
- ps2_common_save (f, &s->common);
- qemu_put_be32s(f, &s->scan_enabled);
- qemu_put_be32s(f, &s->translate);
-}
-
-static void ps2_mouse_save(QEMUFile* f, void* opaque)
-{
- PS2MouseState *s = (PS2MouseState*)opaque;
-
- ps2_common_save (f, &s->common);
- qemu_put_8s(f, &s->mouse_status);
- qemu_put_8s(f, &s->mouse_resolution);
- qemu_put_8s(f, &s->mouse_sample_rate);
- qemu_put_8s(f, &s->mouse_wrap);
- qemu_put_8s(f, &s->mouse_type);
- qemu_put_8s(f, &s->mouse_detect_state);
- qemu_put_be32s(f, &s->mouse_dx);
- qemu_put_be32s(f, &s->mouse_dy);
- qemu_put_be32s(f, &s->mouse_dz);
- qemu_put_8s(f, &s->mouse_buttons);
-}
-
-static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
-{
- PS2KbdState *s = (PS2KbdState*)opaque;
-
- if (version_id != 2)
- return -EINVAL;
-
- ps2_common_load (f, &s->common);
- qemu_get_be32s(f, &s->scan_enabled);
- qemu_get_be32s(f, &s->translate);
- return 0;
-}
-
-static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
-{
- PS2MouseState *s = (PS2MouseState*)opaque;
-
- if (version_id != 2)
- return -EINVAL;
-
- ps2_common_load (f, &s->common);
- qemu_get_8s(f, &s->mouse_status);
- qemu_get_8s(f, &s->mouse_resolution);
- qemu_get_8s(f, &s->mouse_sample_rate);
- qemu_get_8s(f, &s->mouse_wrap);
- qemu_get_8s(f, &s->mouse_type);
- qemu_get_8s(f, &s->mouse_detect_state);
- qemu_get_be32s(f, &s->mouse_dx);
- qemu_get_be32s(f, &s->mouse_dy);
- qemu_get_be32s(f, &s->mouse_dz);
- qemu_get_8s(f, &s->mouse_buttons);
- return 0;
-}
-
-void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
-{
- PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
-
- s->common.update_irq = update_irq;
- s->common.update_arg = update_arg;
- ps2_reset(&s->common);
- register_savevm("ps2kbd", 0, 2, ps2_kbd_save, ps2_kbd_load, s);
- qemu_add_kbd_event_handler(ps2_put_keycode, s);
- qemu_register_reset(ps2_reset, &s->common);
- return s;
-}
-
-void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
-{
- PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
-
- s->common.update_irq = update_irq;
- s->common.update_arg = update_arg;
- ps2_reset(&s->common);
- register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
- qemu_add_mouse_event_handler(ps2_mouse_event, s, 0);
- qemu_register_reset(ps2_reset, &s->common);
- return s;
-}
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
deleted file mode 100644
index 9c613a8..0000000
--- a/hw/rtl8139.c
+++ /dev/null
@@ -1,3471 +0,0 @@
-/**
- * QEMU RTL8139 emulation
- *
- * Copyright (c) 2006 Igor Kovalenko
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
-
- * Modifications:
- * 2006-Jan-28 Mark Malakanov : TSAD and CSCR implementation (for Windows driver)
- *
- * 2006-Apr-28 Juergen Lock : EEPROM emulation changes for FreeBSD driver
- * HW revision ID changes for FreeBSD driver
- *
- * 2006-Jul-01 Igor Kovalenko : Implemented loopback mode for FreeBSD driver
- * Corrected packet transfer reassembly routine for 8139C+ mode
- * Rearranged debugging print statements
- * Implemented PCI timer interrupt (disabled by default)
- * Implemented Tally Counters, increased VM load/save version
- * Implemented IP/TCP/UDP checksum task offloading
- *
- * 2006-Jul-04 Igor Kovalenko : Implemented TCP segmentation offloading
- * Fixed MTU=1500 for produced ethernet frames
- *
- * 2006-Jul-09 Igor Kovalenko : Fixed TCP header length calculation while processing
- * segmentation offloading
- * Removed slirp.h dependency
- * Added rx/tx buffer reset when enabling rx/tx operation
- */
-
-#include "vl.h"
-
-/* debug RTL8139 card */
-//#define DEBUG_RTL8139 1
-
-#define PCI_FREQUENCY 33000000L
-
-/* debug RTL8139 card C+ mode only */
-//#define DEBUG_RTL8139CP 1
-
-/* RTL8139 provides frame CRC with received packet, this feature seems to be
- ignored by most drivers, disabled by default */
-//#define RTL8139_CALCULATE_RXCRC 1
-
-/* Uncomment to enable on-board timer interrupts */
-//#define RTL8139_ONBOARD_TIMER 1
-
-#if defined(RTL8139_CALCULATE_RXCRC)
-/* For crc32 */
-#include <zlib.h>
-#endif
-
-#define SET_MASKED(input, mask, curr) \
- ( ( (input) & ~(mask) ) | ( (curr) & (mask) ) )
-
-/* arg % size for size which is a power of 2 */
-#define MOD2(input, size) \
- ( ( input ) & ( size - 1 ) )
-
-#if defined (DEBUG_RTL8139)
-# define DEBUG_PRINT(x) do { printf x ; } while (0)
-#else
-# define DEBUG_PRINT(x)
-#endif
-
-/* Symbolic offsets to registers. */
-enum RTL8139_registers {
- MAC0 = 0, /* Ethernet hardware address. */
- MAR0 = 8, /* Multicast filter. */
- TxStatus0 = 0x10,/* Transmit status (Four 32bit registers). C mode only */
- /* Dump Tally Conter control register(64bit). C+ mode only */
- TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */
- RxBuf = 0x30,
- ChipCmd = 0x37,
- RxBufPtr = 0x38,
- RxBufAddr = 0x3A,
- IntrMask = 0x3C,
- IntrStatus = 0x3E,
- TxConfig = 0x40,
- RxConfig = 0x44,
- Timer = 0x48, /* A general-purpose counter. */
- RxMissed = 0x4C, /* 24 bits valid, write clears. */
- Cfg9346 = 0x50,
- Config0 = 0x51,
- Config1 = 0x52,
- FlashReg = 0x54,
- MediaStatus = 0x58,
- Config3 = 0x59,
- Config4 = 0x5A, /* absent on RTL-8139A */
- HltClk = 0x5B,
- MultiIntr = 0x5C,
- PCIRevisionID = 0x5E,
- TxSummary = 0x60, /* TSAD register. Transmit Status of All Descriptors*/
- BasicModeCtrl = 0x62,
- BasicModeStatus = 0x64,
- NWayAdvert = 0x66,
- NWayLPAR = 0x68,
- NWayExpansion = 0x6A,
- /* Undocumented registers, but required for proper operation. */
- FIFOTMS = 0x70, /* FIFO Control and test. */
- CSCR = 0x74, /* Chip Status and Configuration Register. */
- PARA78 = 0x78,
- PARA7c = 0x7c, /* Magic transceiver parameter register. */
- Config5 = 0xD8, /* absent on RTL-8139A */
- /* C+ mode */
- TxPoll = 0xD9, /* Tell chip to check Tx descriptors for work */
- RxMaxSize = 0xDA, /* Max size of an Rx packet (8169 only) */
- CpCmd = 0xE0, /* C+ Command register (C+ mode only) */
- IntrMitigate = 0xE2, /* rx/tx interrupt mitigation control */
- RxRingAddrLO = 0xE4, /* 64-bit start addr of Rx ring */
- RxRingAddrHI = 0xE8, /* 64-bit start addr of Rx ring */
- TxThresh = 0xEC, /* Early Tx threshold */
-};
-
-enum ClearBitMasks {
- MultiIntrClear = 0xF000,
- ChipCmdClear = 0xE2,
- Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1),
-};
-
-enum ChipCmdBits {
- CmdReset = 0x10,
- CmdRxEnb = 0x08,
- CmdTxEnb = 0x04,
- RxBufEmpty = 0x01,
-};
-
-/* C+ mode */
-enum CplusCmdBits {
- CPlusRxVLAN = 0x0040, /* enable receive VLAN detagging */
- CPlusRxChkSum = 0x0020, /* enable receive checksum offloading */
- CPlusRxEnb = 0x0002,
- CPlusTxEnb = 0x0001,
-};
-
-/* Interrupt register bits, using my own meaningful names. */
-enum IntrStatusBits {
- PCIErr = 0x8000,
- PCSTimeout = 0x4000,
- RxFIFOOver = 0x40,
- RxUnderrun = 0x20,
- RxOverflow = 0x10,
- TxErr = 0x08,
- TxOK = 0x04,
- RxErr = 0x02,
- RxOK = 0x01,
-
- RxAckBits = RxFIFOOver | RxOverflow | RxOK,
-};
-
-enum TxStatusBits {
- TxHostOwns = 0x2000,
- TxUnderrun = 0x4000,
- TxStatOK = 0x8000,
- TxOutOfWindow = 0x20000000,
- TxAborted = 0x40000000,
- TxCarrierLost = 0x80000000,
-};
-enum RxStatusBits {
- RxMulticast = 0x8000,
- RxPhysical = 0x4000,
- RxBroadcast = 0x2000,
- RxBadSymbol = 0x0020,
- RxRunt = 0x0010,
- RxTooLong = 0x0008,
- RxCRCErr = 0x0004,
- RxBadAlign = 0x0002,
- RxStatusOK = 0x0001,
-};
-
-/* Bits in RxConfig. */
-enum rx_mode_bits {
- AcceptErr = 0x20,
- AcceptRunt = 0x10,
- AcceptBroadcast = 0x08,
- AcceptMulticast = 0x04,
- AcceptMyPhys = 0x02,
- AcceptAllPhys = 0x01,
-};
-
-/* Bits in TxConfig. */
-enum tx_config_bits {
-
- /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
- TxIFGShift = 24,
- TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
- TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
- TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
- TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
-
- TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
- TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
- TxClearAbt = (1 << 0), /* Clear abort (WO) */
- TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */
- TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */
-
- TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
-};
-
-
-/* Transmit Status of All Descriptors (TSAD) Register */
-enum TSAD_bits {
- TSAD_TOK3 = 1<<15, // TOK bit of Descriptor 3
- TSAD_TOK2 = 1<<14, // TOK bit of Descriptor 2
- TSAD_TOK1 = 1<<13, // TOK bit of Descriptor 1
- TSAD_TOK0 = 1<<12, // TOK bit of Descriptor 0
- TSAD_TUN3 = 1<<11, // TUN bit of Descriptor 3
- TSAD_TUN2 = 1<<10, // TUN bit of Descriptor 2
- TSAD_TUN1 = 1<<9, // TUN bit of Descriptor 1
- TSAD_TUN0 = 1<<8, // TUN bit of Descriptor 0
- TSAD_TABT3 = 1<<07, // TABT bit of Descriptor 3
- TSAD_TABT2 = 1<<06, // TABT bit of Descriptor 2
- TSAD_TABT1 = 1<<05, // TABT bit of Descriptor 1
- TSAD_TABT0 = 1<<04, // TABT bit of Descriptor 0
- TSAD_OWN3 = 1<<03, // OWN bit of Descriptor 3
- TSAD_OWN2 = 1<<02, // OWN bit of Descriptor 2
- TSAD_OWN1 = 1<<01, // OWN bit of Descriptor 1
- TSAD_OWN0 = 1<<00, // OWN bit of Descriptor 0
-};
-
-
-/* Bits in Config1 */
-enum Config1Bits {
- Cfg1_PM_Enable = 0x01,
- Cfg1_VPD_Enable = 0x02,
- Cfg1_PIO = 0x04,
- Cfg1_MMIO = 0x08,
- LWAKE = 0x10, /* not on 8139, 8139A */
- Cfg1_Driver_Load = 0x20,
- Cfg1_LED0 = 0x40,
- Cfg1_LED1 = 0x80,
- SLEEP = (1 << 1), /* only on 8139, 8139A */
- PWRDN = (1 << 0), /* only on 8139, 8139A */
-};
-
-/* Bits in Config3 */
-enum Config3Bits {
- Cfg3_FBtBEn = (1 << 0), /* 1 = Fast Back to Back */
- Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */
- Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */
- Cfg3_CardB_En = (1 << 3), /* 1 = enable CardBus registers */
- Cfg3_LinkUp = (1 << 4), /* 1 = wake up on link up */
- Cfg3_Magic = (1 << 5), /* 1 = wake up on Magic Packet (tm) */
- Cfg3_PARM_En = (1 << 6), /* 0 = software can set twister parameters */
- Cfg3_GNTSel = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */
-};
-
-/* Bits in Config4 */
-enum Config4Bits {
- LWPTN = (1 << 2), /* not on 8139, 8139A */
-};
-
-/* Bits in Config5 */
-enum Config5Bits {
- Cfg5_PME_STS = (1 << 0), /* 1 = PCI reset resets PME_Status */
- Cfg5_LANWake = (1 << 1), /* 1 = enable LANWake signal */
- Cfg5_LDPS = (1 << 2), /* 0 = save power when link is down */
- Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */
- Cfg5_UWF = (1 << 4), /* 1 = accept unicast wakeup frame */
- Cfg5_MWF = (1 << 5), /* 1 = accept multicast wakeup frame */
- Cfg5_BWF = (1 << 6), /* 1 = accept broadcast wakeup frame */
-};
-
-enum RxConfigBits {
- /* rx fifo threshold */
- RxCfgFIFOShift = 13,
- RxCfgFIFONone = (7 << RxCfgFIFOShift),
-
- /* Max DMA burst */
- RxCfgDMAShift = 8,
- RxCfgDMAUnlimited = (7 << RxCfgDMAShift),
-
- /* rx ring buffer length */
- RxCfgRcv8K = 0,
- RxCfgRcv16K = (1 << 11),
- RxCfgRcv32K = (1 << 12),
- RxCfgRcv64K = (1 << 11) | (1 << 12),
-
- /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */
- RxNoWrap = (1 << 7),
-};
-
-/* Twister tuning parameters from RealTek.
- Completely undocumented, but required to tune bad links on some boards. */
-/*
-enum CSCRBits {
- CSCR_LinkOKBit = 0x0400,
- CSCR_LinkChangeBit = 0x0800,
- CSCR_LinkStatusBits = 0x0f000,
- CSCR_LinkDownOffCmd = 0x003c0,
- CSCR_LinkDownCmd = 0x0f3c0,
-*/
-enum CSCRBits {
- CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */
- CSCR_LD = 1<<9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/
- CSCR_HEART_BIT = 1<<8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/
- CSCR_JBEN = 1<<7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/
- CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/
- CSCR_F_Connect = 1<<5, /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/
- CSCR_Con_status = 1<<3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/
- CSCR_Con_status_En = 1<<2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/
- CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/
-};
-
-enum Cfg9346Bits {
- Cfg9346_Lock = 0x00,
- Cfg9346_Unlock = 0xC0,
-};
-
-typedef enum {
- CH_8139 = 0,
- CH_8139_K,
- CH_8139A,
- CH_8139A_G,
- CH_8139B,
- CH_8130,
- CH_8139C,
- CH_8100,
- CH_8100B_8139D,
- CH_8101,
-} chip_t;
-
-enum chip_flags {
- HasHltClk = (1 << 0),
- HasLWake = (1 << 1),
-};
-
-#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \
- (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22)
-#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1)
-
-#define RTL8139_PCI_REVID_8139 0x10
-#define RTL8139_PCI_REVID_8139CPLUS 0x20
-
-#define RTL8139_PCI_REVID RTL8139_PCI_REVID_8139CPLUS
-
-/* Size is 64 * 16bit words */
-#define EEPROM_9346_ADDR_BITS 6
-#define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS)
-#define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1)
-
-enum Chip9346Operation
-{
- Chip9346_op_mask = 0xc0, /* 10 zzzzzz */
- Chip9346_op_read = 0x80, /* 10 AAAAAA */
- Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */
- Chip9346_op_ext_mask = 0xf0, /* 11 zzzzzz */
- Chip9346_op_write_enable = 0x30, /* 00 11zzzz */
- Chip9346_op_write_all = 0x10, /* 00 01zzzz */
- Chip9346_op_write_disable = 0x00, /* 00 00zzzz */
-};
-
-enum Chip9346Mode
-{
- Chip9346_none = 0,
- Chip9346_enter_command_mode,
- Chip9346_read_command,
- Chip9346_data_read, /* from output register */
- Chip9346_data_write, /* to input register, then to contents at specified address */
- Chip9346_data_write_all, /* to input register, then filling contents */
-};
-
-typedef struct EEprom9346
-{
- uint16_t contents[EEPROM_9346_SIZE];
- int mode;
- uint32_t tick;
- uint8_t address;
- uint16_t input;
- uint16_t output;
-
- uint8_t eecs;
- uint8_t eesk;
- uint8_t eedi;
- uint8_t eedo;
-} EEprom9346;
-
-typedef struct RTL8139TallyCounters
-{
- /* Tally counters */
- uint64_t TxOk;
- uint64_t RxOk;
- uint64_t TxERR;
- uint32_t RxERR;
- uint16_t MissPkt;
- uint16_t FAE;
- uint32_t Tx1Col;
- uint32_t TxMCol;
- uint64_t RxOkPhy;
- uint64_t RxOkBrd;
- uint32_t RxOkMul;
- uint16_t TxAbt;
- uint16_t TxUndrn;
-} RTL8139TallyCounters;
-
-/* Clears all tally counters */
-static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters);
-
-/* Writes tally counters to specified physical memory address */
-static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* counters);
-
-/* Loads values of tally counters from VM state file */
-static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters *tally_counters);
-
-/* Saves values of tally counters to VM state file */
-static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters *tally_counters);
-
-typedef struct RTL8139State {
- uint8_t phys[8]; /* mac address */
- uint8_t mult[8]; /* multicast mask array */
-
- uint32_t TxStatus[4]; /* TxStatus0 in C mode*/ /* also DTCCR[0] and DTCCR[1] in C+ mode */
- uint32_t TxAddr[4]; /* TxAddr0 */
- uint32_t RxBuf; /* Receive buffer */
- uint32_t RxBufferSize;/* internal variable, receive ring buffer size in C mode */
- uint32_t RxBufPtr;
- uint32_t RxBufAddr;
-
- uint16_t IntrStatus;
- uint16_t IntrMask;
-
- uint32_t TxConfig;
- uint32_t RxConfig;
- uint32_t RxMissed;
-
- uint16_t CSCR;
-
- uint8_t Cfg9346;
- uint8_t Config0;
- uint8_t Config1;
- uint8_t Config3;
- uint8_t Config4;
- uint8_t Config5;
-
- uint8_t clock_enabled;
- uint8_t bChipCmdState;
-
- uint16_t MultiIntr;
-
- uint16_t BasicModeCtrl;
- uint16_t BasicModeStatus;
- uint16_t NWayAdvert;
- uint16_t NWayLPAR;
- uint16_t NWayExpansion;
-
- uint16_t CpCmd;
- uint8_t TxThresh;
-
- int irq;
- PCIDevice *pci_dev;
- VLANClientState *vc;
- uint8_t macaddr[6];
- int rtl8139_mmio_io_addr;
-
- /* C ring mode */
- uint32_t currTxDesc;
-
- /* C+ mode */
- uint32_t currCPlusRxDesc;
- uint32_t currCPlusTxDesc;
-
- uint32_t RxRingAddrLO;
- uint32_t RxRingAddrHI;
-
- EEprom9346 eeprom;
-
- uint32_t TCTR;
- uint32_t TimerInt;
- int64_t TCTR_base;
-
- /* Tally counters */
- RTL8139TallyCounters tally_counters;
-
- /* Non-persistent data */
- uint8_t *cplus_txbuffer;
- int cplus_txbuffer_len;
- int cplus_txbuffer_offset;
-
- /* PCI interrupt timer */
- QEMUTimer *timer;
-
-} RTL8139State;
-
-void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
-{
- DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));
-
- switch (command & Chip9346_op_mask)
- {
- case Chip9346_op_read:
- {
- eeprom->address = command & EEPROM_9346_ADDR_MASK;
- eeprom->output = eeprom->contents[eeprom->address];
- eeprom->eedo = 0;
- eeprom->tick = 0;
- eeprom->mode = Chip9346_data_read;
- DEBUG_PRINT(("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",
- eeprom->address, eeprom->output));
- }
- break;
-
- case Chip9346_op_write:
- {
- eeprom->address = command & EEPROM_9346_ADDR_MASK;
- eeprom->input = 0;
- eeprom->tick = 0;
- eeprom->mode = Chip9346_none; /* Chip9346_data_write */
- DEBUG_PRINT(("RTL8139: eeprom begin write to address 0x%02x\n",
- eeprom->address));
- }
- break;
- default:
- eeprom->mode = Chip9346_none;
- switch (command & Chip9346_op_ext_mask)
- {
- case Chip9346_op_write_enable:
- DEBUG_PRINT(("RTL8139: eeprom write enabled\n"));
- break;
- case Chip9346_op_write_all:
- DEBUG_PRINT(("RTL8139: eeprom begin write all\n"));
- break;
- case Chip9346_op_write_disable:
- DEBUG_PRINT(("RTL8139: eeprom write disabled\n"));
- break;
- }
- break;
- }
-}
-
-void prom9346_shift_clock(EEprom9346 *eeprom)
-{
- int bit = eeprom->eedi?1:0;
-
- ++ eeprom->tick;
-
- DEBUG_PRINT(("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo));
-
- switch (eeprom->mode)
- {
- case Chip9346_enter_command_mode:
- if (bit)
- {
- eeprom->mode = Chip9346_read_command;
- eeprom->tick = 0;
- eeprom->input = 0;
- DEBUG_PRINT(("eeprom: +++ synchronized, begin command read\n"));
- }
- break;
-
- case Chip9346_read_command:
- eeprom->input = (eeprom->input << 1) | (bit & 1);
- if (eeprom->tick == 8)
- {
- prom9346_decode_command(eeprom, eeprom->input & 0xff);
- }
- break;
-
- case Chip9346_data_read:
- eeprom->eedo = (eeprom->output & 0x8000)?1:0;
- eeprom->output <<= 1;
- if (eeprom->tick == 16)
- {
-#if 1
- // the FreeBSD drivers (rl and re) don't explicitly toggle
- // CS between reads (or does setting Cfg9346 to 0 count too?),
- // so we need to enter wait-for-command state here
- eeprom->mode = Chip9346_enter_command_mode;
- eeprom->input = 0;
- eeprom->tick = 0;
-
- DEBUG_PRINT(("eeprom: +++ end of read, awaiting next command\n"));
-#else
- // original behaviour
- ++eeprom->address;
- eeprom->address &= EEPROM_9346_ADDR_MASK;
- eeprom->output = eeprom->contents[eeprom->address];
- eeprom->tick = 0;
-
- DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n",
- eeprom->address, eeprom->output));
-#endif
- }
- break;
-
- case Chip9346_data_write:
- eeprom->input = (eeprom->input << 1) | (bit & 1);
- if (eeprom->tick == 16)
- {
- DEBUG_PRINT(("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
- eeprom->address, eeprom->input));
-
- eeprom->contents[eeprom->address] = eeprom->input;
- eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */
- eeprom->tick = 0;
- eeprom->input = 0;
- }
- break;
-
- case Chip9346_data_write_all:
- eeprom->input = (eeprom->input << 1) | (bit & 1);
- if (eeprom->tick == 16)
- {
- int i;
- for (i = 0; i < EEPROM_9346_SIZE; i++)
- {
- eeprom->contents[i] = eeprom->input;
- }
- DEBUG_PRINT(("RTL8139: eeprom filled with data=0x%04x\n",
- eeprom->input));
-
- eeprom->mode = Chip9346_enter_command_mode;
- eeprom->tick = 0;
- eeprom->input = 0;
- }
- break;
-
- default:
- break;
- }
-}
-
-int prom9346_get_wire(RTL8139State *s)
-{
- EEprom9346 *eeprom = &s->eeprom;
- if (!eeprom->eecs)
- return 0;
-
- return eeprom->eedo;
-}
-
-void prom9346_set_wire(RTL8139State *s, int eecs, int eesk, int eedi)
-{
- EEprom9346 *eeprom = &s->eeprom;
- uint8_t old_eecs = eeprom->eecs;
- uint8_t old_eesk = eeprom->eesk;
-
- eeprom->eecs = eecs;
- eeprom->eesk = eesk;
- eeprom->eedi = eedi;
-
- DEBUG_PRINT(("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
- eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo));
-
- if (!old_eecs && eecs)
- {
- /* Synchronize start */
- eeprom->tick = 0;
- eeprom->input = 0;
- eeprom->output = 0;
- eeprom->mode = Chip9346_enter_command_mode;
-
- DEBUG_PRINT(("=== eeprom: begin access, enter command mode\n"));
- }
-
- if (!eecs)
- {
- DEBUG_PRINT(("=== eeprom: end access\n"));
- return;
- }
-
- if (!old_eesk && eesk)
- {
- /* SK front rules */
- prom9346_shift_clock(eeprom);
- }
-}
-
-static void rtl8139_update_irq(RTL8139State *s)
-{
- int isr;
- isr = (s->IntrStatus & s->IntrMask) & 0xffff;
-
- DEBUG_PRINT(("RTL8139: Set IRQ line %d to %d (%04x %04x)\n",
- s->irq, isr ? 1 : 0, s->IntrStatus, s->IntrMask));
-
- if (s->irq == 16) {
- /* PCI irq */
- pci_set_irq(s->pci_dev, 0, (isr != 0));
- } else {
- /* ISA irq */
- pic_set_irq(s->irq, (isr != 0));
- }
-}
-
-#define POLYNOMIAL 0x04c11db6
-
-/* From FreeBSD */
-/* XXX: optimize */
-static int compute_mcast_idx(const uint8_t *ep)
-{
- uint32_t crc;
- int carry, i, j;
- uint8_t b;
-
- crc = 0xffffffff;
- for (i = 0; i < 6; i++) {
- b = *ep++;
- for (j = 0; j < 8; j++) {
- carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
- crc <<= 1;
- b >>= 1;
- if (carry)
- crc = ((crc ^ POLYNOMIAL) | carry);
- }
- }
- return (crc >> 26);
-}
-
-static int rtl8139_RxWrap(RTL8139State *s)
-{
- /* wrapping enabled; assume 1.5k more buffer space if size < 65536 */
- return (s->RxConfig & (1 << 7));
-}
-
-static int rtl8139_receiver_enabled(RTL8139State *s)
-{
- return s->bChipCmdState & CmdRxEnb;
-}
-
-static int rtl8139_transmitter_enabled(RTL8139State *s)
-{
- return s->bChipCmdState & CmdTxEnb;
-}
-
-static int rtl8139_cp_receiver_enabled(RTL8139State *s)
-{
- return s->CpCmd & CPlusRxEnb;
-}
-
-static int rtl8139_cp_transmitter_enabled(RTL8139State *s)
-{
- return s->CpCmd & CPlusTxEnb;
-}
-
-static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size)
-{
- if (s->RxBufAddr + size > s->RxBufferSize)
- {
- int wrapped = MOD2(s->RxBufAddr + size, s->RxBufferSize);
-
- /* write packet data */
- if (wrapped && s->RxBufferSize < 65536 && !rtl8139_RxWrap(s))
- {
- DEBUG_PRINT((">>> RTL8139: rx packet wrapped in buffer at %d\n", size-wrapped));
-
- if (size > wrapped)
- {
- cpu_physical_memory_write( s->RxBuf + s->RxBufAddr,
- buf, size-wrapped );
- }
-
- /* reset buffer pointer */
- s->RxBufAddr = 0;
-
- cpu_physical_memory_write( s->RxBuf + s->RxBufAddr,
- buf + (size-wrapped), wrapped );
-
- s->RxBufAddr = wrapped;
-
- return;
- }
- }
-
- /* non-wrapping path or overwrapping enabled */
- cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf, size );
-
- s->RxBufAddr += size;
-}
-
-#define MIN_BUF_SIZE 60
-static inline target_phys_addr_t rtl8139_addr64(uint32_t low, uint32_t high)
-{
-#if TARGET_PHYS_ADDR_BITS > 32
- return low | ((target_phys_addr_t)high << 32);
-#else
- return low;
-#endif
-}
-
-static int rtl8139_can_receive(void *opaque)
-{
- RTL8139State *s = opaque;
- int avail;
-
- /* Recieve (drop) packets if card is disabled. */
- if (!s->clock_enabled)
- return 1;
- if (!rtl8139_receiver_enabled(s))
- return 1;
-
- if (rtl8139_cp_receiver_enabled(s)) {
- /* ??? Flow control not implemented in c+ mode.
- This is a hack to work around slirp deficiencies anyway. */
- return 1;
- } else {
- avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr,
- s->RxBufferSize);
- return (avail == 0 || avail >= 1514);
- }
-}
-
-static void rtl8139_do_receive(void *opaque, const uint8_t *buf, int size, int do_interrupt)
-{
- RTL8139State *s = opaque;
-
- uint32_t packet_header = 0;
-
- uint8_t buf1[60];
- static const uint8_t broadcast_macaddr[6] =
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
- DEBUG_PRINT((">>> RTL8139: received len=%d\n", size));
-
- /* test if board clock is stopped */
- if (!s->clock_enabled)
- {
- DEBUG_PRINT(("RTL8139: stopped ==========================\n"));
- return;
- }
-
- /* first check if receiver is enabled */
-
- if (!rtl8139_receiver_enabled(s))
- {
- DEBUG_PRINT(("RTL8139: receiver disabled ================\n"));
- return;
- }
-
- /* XXX: check this */
- if (s->RxConfig & AcceptAllPhys) {
- /* promiscuous: receive all */
- DEBUG_PRINT((">>> RTL8139: packet received in promiscuous mode\n"));
-
- } else {
- if (!memcmp(buf, broadcast_macaddr, 6)) {
- /* broadcast address */
- if (!(s->RxConfig & AcceptBroadcast))
- {
- DEBUG_PRINT((">>> RTL8139: broadcast packet rejected\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxERR;
-
- return;
- }
-
- packet_header |= RxBroadcast;
-
- DEBUG_PRINT((">>> RTL8139: broadcast packet received\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxOkBrd;
-
- } else if (buf[0] & 0x01) {
- /* multicast */
- if (!(s->RxConfig & AcceptMulticast))
- {
- DEBUG_PRINT((">>> RTL8139: multicast packet rejected\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxERR;
-
- return;
- }
-
- int mcast_idx = compute_mcast_idx(buf);
-
- if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
- {
- DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxERR;
-
- return;
- }
-
- packet_header |= RxMulticast;
-
- DEBUG_PRINT((">>> RTL8139: multicast packet received\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxOkMul;
-
- } else if (s->phys[0] == buf[0] &&
- s->phys[1] == buf[1] &&
- s->phys[2] == buf[2] &&
- s->phys[3] == buf[3] &&
- s->phys[4] == buf[4] &&
- s->phys[5] == buf[5]) {
- /* match */
- if (!(s->RxConfig & AcceptMyPhys))
- {
- DEBUG_PRINT((">>> RTL8139: rejecting physical address matching packet\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxERR;
-
- return;
- }
-
- packet_header |= RxPhysical;
-
- DEBUG_PRINT((">>> RTL8139: physical address matching packet received\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxOkPhy;
-
- } else {
-
- DEBUG_PRINT((">>> RTL8139: unknown packet\n"));
-
- /* update tally counter */
- ++s->tally_counters.RxERR;
-
- return;
- }
- }
-
- /* 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;
- }
-
- if (rtl8139_cp_receiver_enabled(s))
- {
- DEBUG_PRINT(("RTL8139: in C+ Rx mode ================\n"));
-
- /* begin C+ receiver mode */
-
-/* w0 ownership flag */
-#define CP_RX_OWN (1<<31)
-/* w0 end of ring flag */
-#define CP_RX_EOR (1<<30)
-/* w0 bits 0...12 : buffer size */
-#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1)
-/* w1 tag available flag */
-#define CP_RX_TAVA (1<<16)
-/* w1 bits 0...15 : VLAN tag */
-#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1)
-/* w2 low 32bit of Rx buffer ptr */
-/* w3 high 32bit of Rx buffer ptr */
-
- int descriptor = s->currCPlusRxDesc;
- target_phys_addr_t cplus_rx_ring_desc;
-
- cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);
- cplus_rx_ring_desc += 16 * descriptor;
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from host memory at %08x %08x = %016" PRIx64 "\n",
- descriptor, s->RxRingAddrHI, s->RxRingAddrLO, (uint64_t)cplus_rx_ring_desc));
-
- uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;
-
- cpu_physical_memory_read(cplus_rx_ring_desc, (uint8_t *)&val, 4);
- rxdw0 = le32_to_cpu(val);
- cpu_physical_memory_read(cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
- rxdw1 = le32_to_cpu(val);
- cpu_physical_memory_read(cplus_rx_ring_desc+8, (uint8_t *)&val, 4);
- rxbufLO = le32_to_cpu(val);
- cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4);
- rxbufHI = le32_to_cpu(val);
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",
- descriptor,
- rxdw0, rxdw1, rxbufLO, rxbufHI));
-
- if (!(rxdw0 & CP_RX_OWN))
- {
- DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", descriptor));
-
- s->IntrStatus |= RxOverflow;
- ++s->RxMissed;
-
- /* update tally counter */
- ++s->tally_counters.RxERR;
- ++s->tally_counters.MissPkt;
-
- rtl8139_update_irq(s);
- return;
- }
-
- uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK;
-
- /* TODO: scatter the packet over available receive ring descriptors space */
-
- if (size+4 > rx_space)
- {
- DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 4\n",
- descriptor, rx_space, size));
-
- s->IntrStatus |= RxOverflow;
- ++s->RxMissed;
-
- /* update tally counter */
- ++s->tally_counters.RxERR;
- ++s->tally_counters.MissPkt;
-
- rtl8139_update_irq(s);
- return;
- }
-
- target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI);
-
- /* receive/copy to target memory */
- cpu_physical_memory_write( rx_addr, buf, size );
-
- if (s->CpCmd & CPlusRxChkSum)
- {
- /* do some packet checksumming */
- }
-
- /* write checksum */
-#if defined (RTL8139_CALCULATE_RXCRC)
- val = cpu_to_le32(crc32(~0, buf, size));
-#else
- val = 0;
-#endif
- cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4);
-
-/* first segment of received packet flag */
-#define CP_RX_STATUS_FS (1<<29)
-/* last segment of received packet flag */
-#define CP_RX_STATUS_LS (1<<28)
-/* multicast packet flag */
-#define CP_RX_STATUS_MAR (1<<26)
-/* physical-matching packet flag */
-#define CP_RX_STATUS_PAM (1<<25)
-/* broadcast packet flag */
-#define CP_RX_STATUS_BAR (1<<24)
-/* runt packet flag */
-#define CP_RX_STATUS_RUNT (1<<19)
-/* crc error flag */
-#define CP_RX_STATUS_CRC (1<<18)
-/* IP checksum error flag */
-#define CP_RX_STATUS_IPF (1<<15)
-/* UDP checksum error flag */
-#define CP_RX_STATUS_UDPF (1<<14)
-/* TCP checksum error flag */
-#define CP_RX_STATUS_TCPF (1<<13)
-
- /* transfer ownership to target */
- rxdw0 &= ~CP_RX_OWN;
-
- /* set first segment bit */
- rxdw0 |= CP_RX_STATUS_FS;
-
- /* set last segment bit */
- rxdw0 |= CP_RX_STATUS_LS;
-
- /* set received packet type flags */
- if (packet_header & RxBroadcast)
- rxdw0 |= CP_RX_STATUS_BAR;
- if (packet_header & RxMulticast)
- rxdw0 |= CP_RX_STATUS_MAR;
- if (packet_header & RxPhysical)
- rxdw0 |= CP_RX_STATUS_PAM;
-
- /* set received size */
- rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK;
- rxdw0 |= (size+4);
-
- /* reset VLAN tag flag */
- rxdw1 &= ~CP_RX_TAVA;
-
- /* update ring data */
- val = cpu_to_le32(rxdw0);
- cpu_physical_memory_write(cplus_rx_ring_desc, (uint8_t *)&val, 4);
- val = cpu_to_le32(rxdw1);
- cpu_physical_memory_write(cplus_rx_ring_desc+4, (uint8_t *)&val, 4);
-
- /* update tally counter */
- ++s->tally_counters.RxOk;
-
- /* seek to next Rx descriptor */
- if (rxdw0 & CP_RX_EOR)
- {
- s->currCPlusRxDesc = 0;
- }
- else
- {
- ++s->currCPlusRxDesc;
- }
-
- DEBUG_PRINT(("RTL8139: done C+ Rx mode ----------------\n"));
-
- }
- else
- {
- DEBUG_PRINT(("RTL8139: in ring Rx mode ================\n"));
-
- /* begin ring receiver mode */
- int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize);
-
- /* if receiver buffer is empty then avail == 0 */
-
- if (avail != 0 && size + 8 >= avail)
- {
- DEBUG_PRINT(("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n",
- s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8));
-
- s->IntrStatus |= RxOverflow;
- ++s->RxMissed;
- rtl8139_update_irq(s);
- return;
- }
-
- packet_header |= RxStatusOK;
-
- packet_header |= (((size+4) << 16) & 0xffff0000);
-
- /* write header */
- uint32_t val = cpu_to_le32(packet_header);
-
- rtl8139_write_buffer(s, (uint8_t *)&val, 4);
-
- rtl8139_write_buffer(s, buf, size);
-
- /* write checksum */
-#if defined (RTL8139_CALCULATE_RXCRC)
- val = cpu_to_le32(crc32(~0, buf, size));
-#else
- val = 0;
-#endif
-
- rtl8139_write_buffer(s, (uint8_t *)&val, 4);
-
- /* correct buffer write pointer */
- s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize);
-
- /* now we can signal we have received something */
-
- DEBUG_PRINT((" received: rx buffer length %d head 0x%04x read 0x%04x\n",
- s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
- }
-
- s->IntrStatus |= RxOK;
-
- if (do_interrupt)
- {
- rtl8139_update_irq(s);
- }
-}
-
-static void rtl8139_receive(void *opaque, const uint8_t *buf, int size)
-{
- rtl8139_do_receive(opaque, buf, size, 1);
-}
-
-static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize)
-{
- s->RxBufferSize = bufferSize;
- s->RxBufPtr = 0;
- s->RxBufAddr = 0;
-}
-
-static void rtl8139_reset(RTL8139State *s)
-{
- int i;
-
- /* restore MAC address */
- memcpy(s->phys, s->macaddr, 6);
-
- /* reset interrupt mask */
- s->IntrStatus = 0;
- s->IntrMask = 0;
-
- rtl8139_update_irq(s);
-
- /* prepare eeprom */
- s->eeprom.contents[0] = 0x8129;
-#if 1
- // PCI vendor and device ID should be mirrored here
- s->eeprom.contents[1] = 0x10ec;
- s->eeprom.contents[2] = 0x8139;
-#endif
- memcpy(&s->eeprom.contents[7], s->macaddr, 6);
-
- /* mark all status registers as owned by host */
- for (i = 0; i < 4; ++i)
- {
- s->TxStatus[i] = TxHostOwns;
- }
-
- s->currTxDesc = 0;
- s->currCPlusRxDesc = 0;
- s->currCPlusTxDesc = 0;
-
- s->RxRingAddrLO = 0;
- s->RxRingAddrHI = 0;
-
- s->RxBuf = 0;
-
- rtl8139_reset_rxring(s, 8192);
-
- /* ACK the reset */
- s->TxConfig = 0;
-
-#if 0
-// s->TxConfig |= HW_REVID(1, 0, 0, 0, 0, 0, 0); // RTL-8139 HasHltClk
- s->clock_enabled = 0;
-#else
- s->TxConfig |= HW_REVID(1, 1, 1, 0, 1, 1, 0); // RTL-8139C+ HasLWake
- s->clock_enabled = 1;
-#endif
-
- s->bChipCmdState = CmdReset; /* RxBufEmpty bit is calculated on read from ChipCmd */;
-
- /* set initial state data */
- s->Config0 = 0x0; /* No boot ROM */
- s->Config1 = 0xC; /* IO mapped and MEM mapped registers available */
- s->Config3 = 0x1; /* fast back-to-back compatible */
- s->Config5 = 0x0;
-
- s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
-
- s->CpCmd = 0x0; /* reset C+ mode */
-
-// s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation
-// s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex
- s->BasicModeCtrl = 0x1000; // autonegotiation
-
- s->BasicModeStatus = 0x7809;
- //s->BasicModeStatus |= 0x0040; /* UTP medium */
- s->BasicModeStatus |= 0x0020; /* autonegotiation completed */
- s->BasicModeStatus |= 0x0004; /* link is up */
-
- s->NWayAdvert = 0x05e1; /* all modes, full duplex */
- s->NWayLPAR = 0x05e1; /* all modes, full duplex */
- s->NWayExpansion = 0x0001; /* autonegotiation supported */
-
- /* also reset timer and disable timer interrupt */
- s->TCTR = 0;
- s->TimerInt = 0;
- s->TCTR_base = 0;
-
- /* reset tally counters */
- RTL8139TallyCounters_clear(&s->tally_counters);
-}
-
-void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters)
-{
- counters->TxOk = 0;
- counters->RxOk = 0;
- counters->TxERR = 0;
- counters->RxERR = 0;
- counters->MissPkt = 0;
- counters->FAE = 0;
- counters->Tx1Col = 0;
- counters->TxMCol = 0;
- counters->RxOkPhy = 0;
- counters->RxOkBrd = 0;
- counters->RxOkMul = 0;
- counters->TxAbt = 0;
- counters->TxUndrn = 0;
-}
-
-static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* tally_counters)
-{
- uint16_t val16;
- uint32_t val32;
- uint64_t val64;
-
- val64 = cpu_to_le64(tally_counters->TxOk);
- cpu_physical_memory_write(tc_addr + 0, (uint8_t *)&val64, 8);
-
- val64 = cpu_to_le64(tally_counters->RxOk);
- cpu_physical_memory_write(tc_addr + 8, (uint8_t *)&val64, 8);
-
- val64 = cpu_to_le64(tally_counters->TxERR);
- cpu_physical_memory_write(tc_addr + 16, (uint8_t *)&val64, 8);
-
- val32 = cpu_to_le32(tally_counters->RxERR);
- cpu_physical_memory_write(tc_addr + 24, (uint8_t *)&val32, 4);
-
- val16 = cpu_to_le16(tally_counters->MissPkt);
- cpu_physical_memory_write(tc_addr + 28, (uint8_t *)&val16, 2);
-
- val16 = cpu_to_le16(tally_counters->FAE);
- cpu_physical_memory_write(tc_addr + 30, (uint8_t *)&val16, 2);
-
- val32 = cpu_to_le32(tally_counters->Tx1Col);
- cpu_physical_memory_write(tc_addr + 32, (uint8_t *)&val32, 4);
-
- val32 = cpu_to_le32(tally_counters->TxMCol);
- cpu_physical_memory_write(tc_addr + 36, (uint8_t *)&val32, 4);
-
- val64 = cpu_to_le64(tally_counters->RxOkPhy);
- cpu_physical_memory_write(tc_addr + 40, (uint8_t *)&val64, 8);
-
- val64 = cpu_to_le64(tally_counters->RxOkBrd);
- cpu_physical_memory_write(tc_addr + 48, (uint8_t *)&val64, 8);
-
- val32 = cpu_to_le32(tally_counters->RxOkMul);
- cpu_physical_memory_write(tc_addr + 56, (uint8_t *)&val32, 4);
-
- val16 = cpu_to_le16(tally_counters->TxAbt);
- cpu_physical_memory_write(tc_addr + 60, (uint8_t *)&val16, 2);
-
- val16 = cpu_to_le16(tally_counters->TxUndrn);
- cpu_physical_memory_write(tc_addr + 62, (uint8_t *)&val16, 2);
-}
-
-/* Loads values of tally counters from VM state file */
-static void RTL8139TallyCounters_load(QEMUFile* f, RTL8139TallyCounters *tally_counters)
-{
- qemu_get_be64s(f, &tally_counters->TxOk);
- qemu_get_be64s(f, &tally_counters->RxOk);
- qemu_get_be64s(f, &tally_counters->TxERR);
- qemu_get_be32s(f, &tally_counters->RxERR);
- qemu_get_be16s(f, &tally_counters->MissPkt);
- qemu_get_be16s(f, &tally_counters->FAE);
- qemu_get_be32s(f, &tally_counters->Tx1Col);
- qemu_get_be32s(f, &tally_counters->TxMCol);
- qemu_get_be64s(f, &tally_counters->RxOkPhy);
- qemu_get_be64s(f, &tally_counters->RxOkBrd);
- qemu_get_be32s(f, &tally_counters->RxOkMul);
- qemu_get_be16s(f, &tally_counters->TxAbt);
- qemu_get_be16s(f, &tally_counters->TxUndrn);
-}
-
-/* Saves values of tally counters to VM state file */
-static void RTL8139TallyCounters_save(QEMUFile* f, RTL8139TallyCounters *tally_counters)
-{
- qemu_put_be64s(f, &tally_counters->TxOk);
- qemu_put_be64s(f, &tally_counters->RxOk);
- qemu_put_be64s(f, &tally_counters->TxERR);
- qemu_put_be32s(f, &tally_counters->RxERR);
- qemu_put_be16s(f, &tally_counters->MissPkt);
- qemu_put_be16s(f, &tally_counters->FAE);
- qemu_put_be32s(f, &tally_counters->Tx1Col);
- qemu_put_be32s(f, &tally_counters->TxMCol);
- qemu_put_be64s(f, &tally_counters->RxOkPhy);
- qemu_put_be64s(f, &tally_counters->RxOkBrd);
- qemu_put_be32s(f, &tally_counters->RxOkMul);
- qemu_put_be16s(f, &tally_counters->TxAbt);
- qemu_put_be16s(f, &tally_counters->TxUndrn);
-}
-
-static void rtl8139_ChipCmd_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xff;
-
- DEBUG_PRINT(("RTL8139: ChipCmd write val=0x%08x\n", val));
-
- if (val & CmdReset)
- {
- DEBUG_PRINT(("RTL8139: ChipCmd reset\n"));
- rtl8139_reset(s);
- }
- if (val & CmdRxEnb)
- {
- DEBUG_PRINT(("RTL8139: ChipCmd enable receiver\n"));
-
- s->currCPlusRxDesc = 0;
- }
- if (val & CmdTxEnb)
- {
- DEBUG_PRINT(("RTL8139: ChipCmd enable transmitter\n"));
-
- s->currCPlusTxDesc = 0;
- }
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0xe3, s->bChipCmdState);
-
- /* Deassert reset pin before next read */
- val &= ~CmdReset;
-
- s->bChipCmdState = val;
-}
-
-static int rtl8139_RxBufferEmpty(RTL8139State *s)
-{
- int unread = MOD2(s->RxBufferSize + s->RxBufAddr - s->RxBufPtr, s->RxBufferSize);
-
- if (unread != 0)
- {
- DEBUG_PRINT(("RTL8139: receiver buffer data available 0x%04x\n", unread));
- return 0;
- }
-
- DEBUG_PRINT(("RTL8139: receiver buffer is empty\n"));
-
- return 1;
-}
-
-static uint32_t rtl8139_ChipCmd_read(RTL8139State *s)
-{
- uint32_t ret = s->bChipCmdState;
-
- if (rtl8139_RxBufferEmpty(s))
- ret |= RxBufEmpty;
-
- DEBUG_PRINT(("RTL8139: ChipCmd read val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xffff;
-
- DEBUG_PRINT(("RTL8139C+ command register write(w) val=0x%04x\n", val));
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0xff84, s->CpCmd);
-
- s->CpCmd = val;
-}
-
-static uint32_t rtl8139_CpCmd_read(RTL8139State *s)
-{
- uint32_t ret = s->CpCmd;
-
- DEBUG_PRINT(("RTL8139C+ command register read(w) val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_IntrMitigate_write(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139C+ IntrMitigate register write(w) val=0x%04x\n", val));
-}
-
-static uint32_t rtl8139_IntrMitigate_read(RTL8139State *s)
-{
- uint32_t ret = 0;
-
- DEBUG_PRINT(("RTL8139C+ IntrMitigate register read(w) val=0x%04x\n", ret));
-
- return ret;
-}
-
-int rtl8139_config_writeable(RTL8139State *s)
-{
- if (s->Cfg9346 & Cfg9346_Unlock)
- {
- return 1;
- }
-
- DEBUG_PRINT(("RTL8139: Configuration registers are write-protected\n"));
-
- return 0;
-}
-
-static void rtl8139_BasicModeCtrl_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xffff;
-
- DEBUG_PRINT(("RTL8139: BasicModeCtrl register write(w) val=0x%04x\n", val));
-
- /* mask unwriteable bits */
- uint32 mask = 0x4cff;
-
- if (1 || !rtl8139_config_writeable(s))
- {
- /* Speed setting and autonegotiation enable bits are read-only */
- mask |= 0x3000;
- /* Duplex mode setting is read-only */
- mask |= 0x0100;
- }
-
- val = SET_MASKED(val, mask, s->BasicModeCtrl);
-
- s->BasicModeCtrl = val;
-}
-
-static uint32_t rtl8139_BasicModeCtrl_read(RTL8139State *s)
-{
- uint32_t ret = s->BasicModeCtrl;
-
- DEBUG_PRINT(("RTL8139: BasicModeCtrl register read(w) val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_BasicModeStatus_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xffff;
-
- DEBUG_PRINT(("RTL8139: BasicModeStatus register write(w) val=0x%04x\n", val));
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0xff3f, s->BasicModeStatus);
-
- s->BasicModeStatus = val;
-}
-
-static uint32_t rtl8139_BasicModeStatus_read(RTL8139State *s)
-{
- uint32_t ret = s->BasicModeStatus;
-
- DEBUG_PRINT(("RTL8139: BasicModeStatus register read(w) val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_Cfg9346_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xff;
-
- DEBUG_PRINT(("RTL8139: Cfg9346 write val=0x%02x\n", val));
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0x31, s->Cfg9346);
-
- uint32_t opmode = val & 0xc0;
- uint32_t eeprom_val = val & 0xf;
-
- if (opmode == 0x80) {
- /* eeprom access */
- int eecs = (eeprom_val & 0x08)?1:0;
- int eesk = (eeprom_val & 0x04)?1:0;
- int eedi = (eeprom_val & 0x02)?1:0;
- prom9346_set_wire(s, eecs, eesk, eedi);
- } else if (opmode == 0x40) {
- /* Reset. */
- val = 0;
- rtl8139_reset(s);
- }
-
- s->Cfg9346 = val;
-}
-
-static uint32_t rtl8139_Cfg9346_read(RTL8139State *s)
-{
- uint32_t ret = s->Cfg9346;
-
- uint32_t opmode = ret & 0xc0;
-
- if (opmode == 0x80)
- {
- /* eeprom access */
- int eedo = prom9346_get_wire(s);
- if (eedo)
- {
- ret |= 0x01;
- }
- else
- {
- ret &= ~0x01;
- }
- }
-
- DEBUG_PRINT(("RTL8139: Cfg9346 read val=0x%02x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_Config0_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xff;
-
- DEBUG_PRINT(("RTL8139: Config0 write val=0x%02x\n", val));
-
- if (!rtl8139_config_writeable(s))
- return;
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0xf8, s->Config0);
-
- s->Config0 = val;
-}
-
-static uint32_t rtl8139_Config0_read(RTL8139State *s)
-{
- uint32_t ret = s->Config0;
-
- DEBUG_PRINT(("RTL8139: Config0 read val=0x%02x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_Config1_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xff;
-
- DEBUG_PRINT(("RTL8139: Config1 write val=0x%02x\n", val));
-
- if (!rtl8139_config_writeable(s))
- return;
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0xC, s->Config1);
-
- s->Config1 = val;
-}
-
-static uint32_t rtl8139_Config1_read(RTL8139State *s)
-{
- uint32_t ret = s->Config1;
-
- DEBUG_PRINT(("RTL8139: Config1 read val=0x%02x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_Config3_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xff;
-
- DEBUG_PRINT(("RTL8139: Config3 write val=0x%02x\n", val));
-
- if (!rtl8139_config_writeable(s))
- return;
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0x8F, s->Config3);
-
- s->Config3 = val;
-}
-
-static uint32_t rtl8139_Config3_read(RTL8139State *s)
-{
- uint32_t ret = s->Config3;
-
- DEBUG_PRINT(("RTL8139: Config3 read val=0x%02x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_Config4_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xff;
-
- DEBUG_PRINT(("RTL8139: Config4 write val=0x%02x\n", val));
-
- if (!rtl8139_config_writeable(s))
- return;
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0x0a, s->Config4);
-
- s->Config4 = val;
-}
-
-static uint32_t rtl8139_Config4_read(RTL8139State *s)
-{
- uint32_t ret = s->Config4;
-
- DEBUG_PRINT(("RTL8139: Config4 read val=0x%02x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_Config5_write(RTL8139State *s, uint32_t val)
-{
- val &= 0xff;
-
- DEBUG_PRINT(("RTL8139: Config5 write val=0x%02x\n", val));
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0x80, s->Config5);
-
- s->Config5 = val;
-}
-
-static uint32_t rtl8139_Config5_read(RTL8139State *s)
-{
- uint32_t ret = s->Config5;
-
- DEBUG_PRINT(("RTL8139: Config5 read val=0x%02x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val)
-{
- if (!rtl8139_transmitter_enabled(s))
- {
- DEBUG_PRINT(("RTL8139: transmitter disabled; no TxConfig write val=0x%08x\n", val));
- return;
- }
-
- DEBUG_PRINT(("RTL8139: TxConfig write val=0x%08x\n", val));
-
- val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig);
-
- s->TxConfig = val;
-}
-
-static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139C TxConfig via write(b) val=0x%02x\n", val));
-
- uint32_t tc = s->TxConfig;
- tc &= 0xFFFFFF00;
- tc |= (val & 0x000000FF);
- rtl8139_TxConfig_write(s, tc);
-}
-
-static uint32_t rtl8139_TxConfig_read(RTL8139State *s)
-{
- uint32_t ret = s->TxConfig;
-
- DEBUG_PRINT(("RTL8139: TxConfig read val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139: RxConfig write val=0x%08x\n", val));
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0xf0fc0040, s->RxConfig);
-
- s->RxConfig = val;
-
- /* reset buffer size and read/write pointers */
- rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3));
-
- DEBUG_PRINT(("RTL8139: RxConfig write reset buffer size to %d\n", s->RxBufferSize));
-}
-
-static uint32_t rtl8139_RxConfig_read(RTL8139State *s)
-{
- uint32_t ret = s->RxConfig;
-
- DEBUG_PRINT(("RTL8139: RxConfig read val=0x%08x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int size, int do_interrupt)
-{
- if (!size)
- {
- DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n"));
- return;
- }
-
- if (TxLoopBack == (s->TxConfig & TxLoopBack))
- {
- DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n"));
- rtl8139_do_receive(s, buf, size, do_interrupt);
- }
- else
- {
- qemu_send_packet(s->vc, buf, size);
- }
-}
-
-static int rtl8139_transmit_one(RTL8139State *s, int descriptor)
-{
- if (!rtl8139_transmitter_enabled(s))
- {
- DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: transmitter disabled\n",
- descriptor));
- return 0;
- }
-
- if (s->TxStatus[descriptor] & TxHostOwns)
- {
- DEBUG_PRINT(("RTL8139: +++ cannot transmit from descriptor %d: owned by host (%08x)\n",
- descriptor, s->TxStatus[descriptor]));
- return 0;
- }
-
- DEBUG_PRINT(("RTL8139: +++ transmitting from descriptor %d\n", descriptor));
-
- int txsize = s->TxStatus[descriptor] & 0x1fff;
- uint8_t txbuffer[0x2000];
-
- DEBUG_PRINT(("RTL8139: +++ transmit reading %d bytes from host memory at 0x%08x\n",
- txsize, s->TxAddr[descriptor]));
-
- cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize);
-
- /* Mark descriptor as transferred */
- s->TxStatus[descriptor] |= TxHostOwns;
- s->TxStatus[descriptor] |= TxStatOK;
-
- rtl8139_transfer_frame(s, txbuffer, txsize, 0);
-
- DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor));
-
- /* update interrupt */
- s->IntrStatus |= TxOK;
- rtl8139_update_irq(s);
-
- return 1;
-}
-
-/* structures and macros for task offloading */
-typedef struct ip_header
-{
- uint8_t ip_ver_len; /* version and header length */
- uint8_t ip_tos; /* type of service */
- uint16_t ip_len; /* total length */
- uint16_t ip_id; /* identification */
- uint16_t ip_off; /* fragment offset field */
- uint8_t ip_ttl; /* time to live */
- uint8_t ip_p; /* protocol */
- uint16_t ip_sum; /* checksum */
- uint32_t ip_src,ip_dst; /* source and dest address */
-} ip_header;
-
-#define IP_HEADER_VERSION_4 4
-#define IP_HEADER_VERSION(ip) ((ip->ip_ver_len >> 4)&0xf)
-#define IP_HEADER_LENGTH(ip) (((ip->ip_ver_len)&0xf) << 2)
-
-typedef struct tcp_header
-{
- uint16_t th_sport; /* source port */
- uint16_t th_dport; /* destination port */
- uint32_t th_seq; /* sequence number */
- uint32_t th_ack; /* acknowledgement number */
- uint16_t th_offset_flags; /* data offset, reserved 6 bits, TCP protocol flags */
- uint16_t th_win; /* window */
- uint16_t th_sum; /* checksum */
- uint16_t th_urp; /* urgent pointer */
-} tcp_header;
-
-typedef struct udp_header
-{
- uint16_t uh_sport; /* source port */
- uint16_t uh_dport; /* destination port */
- uint16_t uh_ulen; /* udp length */
- uint16_t uh_sum; /* udp checksum */
-} udp_header;
-
-typedef struct ip_pseudo_header
-{
- uint32_t ip_src;
- uint32_t ip_dst;
- uint8_t zeros;
- uint8_t ip_proto;
- uint16_t ip_payload;
-} ip_pseudo_header;
-
-#define IP_PROTO_TCP 6
-#define IP_PROTO_UDP 17
-
-#define TCP_HEADER_DATA_OFFSET(tcp) (((be16_to_cpu(tcp->th_offset_flags) >> 12)&0xf) << 2)
-#define TCP_FLAGS_ONLY(flags) ((flags)&0x3f)
-#define TCP_HEADER_FLAGS(tcp) TCP_FLAGS_ONLY(be16_to_cpu(tcp->th_offset_flags))
-
-#define TCP_HEADER_CLEAR_FLAGS(tcp, off) ((tcp)->th_offset_flags &= cpu_to_be16(~TCP_FLAGS_ONLY(off)))
-
-#define TCP_FLAG_FIN 0x01
-#define TCP_FLAG_PUSH 0x08
-
-/* produces ones' complement sum of data */
-static uint16_t ones_complement_sum(uint8_t *data, size_t len)
-{
- uint32_t result = 0;
-
- for (; len > 1; data+=2, len-=2)
- {
- result += *(uint16_t*)data;
- }
-
- /* add the remainder byte */
- if (len)
- {
- uint8_t odd[2] = {*data, 0};
- result += *(uint16_t*)odd;
- }
-
- while (result>>16)
- result = (result & 0xffff) + (result >> 16);
-
- return result;
-}
-
-static uint16_t ip_checksum(void *data, size_t len)
-{
- return ~ones_complement_sum((uint8_t*)data, len);
-}
-
-static int rtl8139_cplus_transmit_one(RTL8139State *s)
-{
- if (!rtl8139_transmitter_enabled(s))
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode: transmitter disabled\n"));
- return 0;
- }
-
- if (!rtl8139_cp_transmitter_enabled(s))
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode: C+ transmitter disabled\n"));
- return 0 ;
- }
-
- int descriptor = s->currCPlusTxDesc;
-
- target_phys_addr_t cplus_tx_ring_desc =
- rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]);
-
- /* Normal priority ring */
- cplus_tx_ring_desc += 16 * descriptor;
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode reading TX descriptor %d from host memory at %08x0x%08x = 0x%8lx\n",
- descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc));
-
- uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
-
- cpu_physical_memory_read(cplus_tx_ring_desc, (uint8_t *)&val, 4);
- txdw0 = le32_to_cpu(val);
- cpu_physical_memory_read(cplus_tx_ring_desc+4, (uint8_t *)&val, 4);
- txdw1 = le32_to_cpu(val);
- cpu_physical_memory_read(cplus_tx_ring_desc+8, (uint8_t *)&val, 4);
- txbufLO = le32_to_cpu(val);
- cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4);
- txbufHI = le32_to_cpu(val);
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n",
- descriptor,
- txdw0, txdw1, txbufLO, txbufHI));
-
-/* w0 ownership flag */
-#define CP_TX_OWN (1<<31)
-/* w0 end of ring flag */
-#define CP_TX_EOR (1<<30)
-/* first segment of received packet flag */
-#define CP_TX_FS (1<<29)
-/* last segment of received packet flag */
-#define CP_TX_LS (1<<28)
-/* large send packet flag */
-#define CP_TX_LGSEN (1<<27)
-/* large send MSS mask, bits 16...25 */
-#define CP_TC_LGSEN_MSS_MASK ((1 << 12) - 1)
-
-/* IP checksum offload flag */
-#define CP_TX_IPCS (1<<18)
-/* UDP checksum offload flag */
-#define CP_TX_UDPCS (1<<17)
-/* TCP checksum offload flag */
-#define CP_TX_TCPCS (1<<16)
-
-/* w0 bits 0...15 : buffer size */
-#define CP_TX_BUFFER_SIZE (1<<16)
-#define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1)
-/* w1 tag available flag */
-#define CP_RX_TAGC (1<<17)
-/* w1 bits 0...15 : VLAN tag */
-#define CP_TX_VLAN_TAG_MASK ((1<<16) - 1)
-/* w2 low 32bit of Rx buffer ptr */
-/* w3 high 32bit of Rx buffer ptr */
-
-/* set after transmission */
-/* FIFO underrun flag */
-#define CP_TX_STATUS_UNF (1<<25)
-/* transmit error summary flag, valid if set any of three below */
-#define CP_TX_STATUS_TES (1<<23)
-/* out-of-window collision flag */
-#define CP_TX_STATUS_OWC (1<<22)
-/* link failure flag */
-#define CP_TX_STATUS_LNKF (1<<21)
-/* excessive collisions flag */
-#define CP_TX_STATUS_EXC (1<<20)
-
- if (!(txdw0 & CP_TX_OWN))
- {
- DEBUG_PRINT(("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", descriptor));
- return 0 ;
- }
-
- DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", descriptor));
-
- if (txdw0 & CP_TX_FS)
- {
- DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is first segment descriptor\n", descriptor));
-
- /* reset internal buffer offset */
- s->cplus_txbuffer_offset = 0;
- }
-
- int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK;
- target_phys_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI);
-
- /* make sure we have enough space to assemble the packet */
- if (!s->cplus_txbuffer)
- {
- s->cplus_txbuffer_len = CP_TX_BUFFER_SIZE;
- s->cplus_txbuffer = malloc(s->cplus_txbuffer_len);
- s->cplus_txbuffer_offset = 0;
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer allocated space %d\n", s->cplus_txbuffer_len));
- }
-
- while (s->cplus_txbuffer && s->cplus_txbuffer_offset + txsize >= s->cplus_txbuffer_len)
- {
- s->cplus_txbuffer_len += CP_TX_BUFFER_SIZE;
- s->cplus_txbuffer = realloc(s->cplus_txbuffer, s->cplus_txbuffer_len);
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmission buffer space changed to %d\n", s->cplus_txbuffer_len));
- }
-
- if (!s->cplus_txbuffer)
- {
- /* out of memory */
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmiter failed to reallocate %d bytes\n", s->cplus_txbuffer_len));
-
- /* update tally counter */
- ++s->tally_counters.TxERR;
- ++s->tally_counters.TxAbt;
-
- return 0;
- }
-
- /* append more data to the packet */
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at %016" PRIx64 " to offset %d\n",
- txsize, (uint64_t)tx_addr, s->cplus_txbuffer_offset));
-
- cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize);
- s->cplus_txbuffer_offset += txsize;
-
- /* seek to next Rx descriptor */
- if (txdw0 & CP_TX_EOR)
- {
- s->currCPlusTxDesc = 0;
- }
- else
- {
- ++s->currCPlusTxDesc;
- if (s->currCPlusTxDesc >= 64)
- s->currCPlusTxDesc = 0;
- }
-
- /* transfer ownership to target */
- txdw0 &= ~CP_RX_OWN;
-
- /* reset error indicator bits */
- txdw0 &= ~CP_TX_STATUS_UNF;
- txdw0 &= ~CP_TX_STATUS_TES;
- txdw0 &= ~CP_TX_STATUS_OWC;
- txdw0 &= ~CP_TX_STATUS_LNKF;
- txdw0 &= ~CP_TX_STATUS_EXC;
-
- /* update ring data */
- val = cpu_to_le32(txdw0);
- cpu_physical_memory_write(cplus_tx_ring_desc, (uint8_t *)&val, 4);
-// val = cpu_to_le32(txdw1);
-// cpu_physical_memory_write(cplus_tx_ring_desc+4, &val, 4);
-
- /* Now decide if descriptor being processed is holding the last segment of packet */
- if (txdw0 & CP_TX_LS)
- {
- DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor));
-
- /* can transfer fully assembled packet */
-
- uint8_t *saved_buffer = s->cplus_txbuffer;
- int saved_size = s->cplus_txbuffer_offset;
- int saved_buffer_len = s->cplus_txbuffer_len;
-
- /* reset the card space to protect from recursive call */
- s->cplus_txbuffer = NULL;
- s->cplus_txbuffer_offset = 0;
- s->cplus_txbuffer_len = 0;
-
- if (txdw0 & (CP_TX_IPCS | CP_TX_UDPCS | CP_TX_TCPCS | CP_TX_LGSEN))
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task checksum\n"));
-
- #define ETH_P_IP 0x0800 /* Internet Protocol packet */
- #define ETH_HLEN 14
- #define ETH_MTU 1500
-
- /* ip packet header */
- ip_header *ip = 0;
- int hlen = 0;
- uint8_t ip_protocol = 0;
- uint16_t ip_data_len = 0;
-
- uint8_t *eth_payload_data = 0;
- size_t eth_payload_len = 0;
-
- int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
- if (proto == ETH_P_IP)
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode has IP packet\n"));
-
- /* not aligned */
- eth_payload_data = saved_buffer + ETH_HLEN;
- eth_payload_len = saved_size - ETH_HLEN;
-
- ip = (ip_header*)eth_payload_data;
-
- if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
- DEBUG_PRINT(("RTL8139: +++ C+ mode packet has bad IP version %d expected %d\n", IP_HEADER_VERSION(ip), IP_HEADER_VERSION_4));
- ip = NULL;
- } else {
- hlen = IP_HEADER_LENGTH(ip);
- ip_protocol = ip->ip_p;
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
- }
- }
-
- if (ip)
- {
- if (txdw0 & CP_TX_IPCS)
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode need IP checksum\n"));
-
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
- /* bad packet header len */
- /* or packet too short */
- }
- else
- {
- ip->ip_sum = 0;
- ip->ip_sum = ip_checksum(ip, hlen);
- DEBUG_PRINT(("RTL8139: +++ C+ mode IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
- }
- }
-
- if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
- {
-#if defined (DEBUG_RTL8139)
- int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
-#endif
- DEBUG_PRINT(("RTL8139: +++ C+ mode offloaded task TSO MTU=%d IP data %d frame data %d specified MSS=%d\n",
- ETH_MTU, ip_data_len, saved_size - ETH_HLEN, large_send_mss));
-
- int tcp_send_offset = 0;
- int send_count = 0;
-
- /* maximum IP header length is 60 bytes */
- uint8_t saved_ip_header[60];
-
- /* save IP header template; data area is used in tcp checksum calculation */
- memcpy(saved_ip_header, eth_payload_data, hlen);
-
- /* a placeholder for checksum calculation routine in tcp case */
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
-
- /* pointer to TCP header */
- tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
-
- int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
-
- /* ETH_MTU = ip header len + tcp header len + payload */
- int tcp_data_len = ip_data_len - tcp_hlen;
- int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP data len %d TCP hlen %d TCP data len %d TCP chunk size %d\n",
- ip_data_len, tcp_hlen, tcp_data_len, tcp_chunk_size));
-
- /* note the cycle below overwrites IP header data,
- but restores it from saved_ip_header before sending packet */
-
- int is_last_frame = 0;
-
- for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
- {
- uint16_t chunk_size = tcp_chunk_size;
-
- /* check if this is the last frame */
- if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
- {
- is_last_frame = 1;
- chunk_size = tcp_data_len - tcp_send_offset;
- }
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP seqno %08x\n", be32_to_cpu(p_tcp_hdr->th_seq)));
-
- /* add 4 TCP pseudoheader fields */
- /* copy IP source and destination fields */
- memcpy(data_to_checksum, saved_ip_header + 12, 8);
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO calculating TCP checksum for packet with %d bytes data\n", tcp_hlen + chunk_size));
-
- if (tcp_send_offset)
- {
- memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
- }
-
- /* keep PUSH and FIN flags only for the last frame */
- if (!is_last_frame)
- {
- TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
- }
-
- /* recalculate TCP checksum */
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
- p_tcpip_hdr->zeros = 0;
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
- p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
-
- p_tcp_hdr->th_sum = 0;
-
- int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO TCP checksum %04x\n", tcp_checksum));
-
- p_tcp_hdr->th_sum = tcp_checksum;
-
- /* restore IP header */
- memcpy(eth_payload_data, saved_ip_header, hlen);
-
- /* set IP data length and recalculate IP checksum */
- ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
-
- /* increment IP id for subsequent frames */
- ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
-
- ip->ip_sum = 0;
- ip->ip_sum = ip_checksum(eth_payload_data, hlen);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO IP header len=%d checksum=%04x\n", hlen, ip->ip_sum));
-
- int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
- DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
- rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0);
-
- /* add transferred count to TCP sequence number */
- p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
- ++send_count;
- }
-
- /* Stop sending this frame */
- saved_size = 0;
- }
- else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode need TCP or UDP checksum\n"));
-
- /* maximum IP header length is 60 bytes */
- uint8_t saved_ip_header[60];
- memcpy(saved_ip_header, eth_payload_data, hlen);
-
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
-
- /* add 4 TCP pseudoheader fields */
- /* copy IP source and destination fields */
- memcpy(data_to_checksum, saved_ip_header + 12, 8);
-
- if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode calculating TCP checksum for packet with %d bytes data\n", ip_data_len));
-
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
- p_tcpip_hdr->zeros = 0;
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
- p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
-
- tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
-
- p_tcp_hdr->th_sum = 0;
-
- int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
- DEBUG_PRINT(("RTL8139: +++ C+ mode TCP checksum %04x\n", tcp_checksum));
-
- p_tcp_hdr->th_sum = tcp_checksum;
- }
- else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode calculating UDP checksum for packet with %d bytes data\n", ip_data_len));
-
- ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
- p_udpip_hdr->zeros = 0;
- p_udpip_hdr->ip_proto = IP_PROTO_UDP;
- p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
-
- udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
-
- p_udp_hdr->uh_sum = 0;
-
- int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
- DEBUG_PRINT(("RTL8139: +++ C+ mode UDP checksum %04x\n", udp_checksum));
-
- p_udp_hdr->uh_sum = udp_checksum;
- }
-
- /* restore IP header */
- memcpy(eth_payload_data, saved_ip_header, hlen);
- }
- }
- }
-
- /* update tally counter */
- ++s->tally_counters.TxOk;
-
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size));
-
- rtl8139_transfer_frame(s, saved_buffer, saved_size, 1);
-
- /* restore card space if there was no recursion and reset offset */
- if (!s->cplus_txbuffer)
- {
- s->cplus_txbuffer = saved_buffer;
- s->cplus_txbuffer_len = saved_buffer_len;
- s->cplus_txbuffer_offset = 0;
- }
- else
- {
- free(saved_buffer);
- }
- }
- else
- {
- DEBUG_PRINT(("RTL8139: +++ C+ mode transmission continue to next descriptor\n"));
- }
-
- return 1;
-}
-
-static void rtl8139_cplus_transmit(RTL8139State *s)
-{
- int txcount = 0;
-
- while (rtl8139_cplus_transmit_one(s))
- {
- ++txcount;
- }
-
- /* Mark transfer completed */
- if (!txcount)
- {
- DEBUG_PRINT(("RTL8139: C+ mode : transmitter queue stalled, current TxDesc = %d\n",
- s->currCPlusTxDesc));
- }
- else
- {
- /* update interrupt status */
- s->IntrStatus |= TxOK;
- rtl8139_update_irq(s);
- }
-}
-
-static void rtl8139_transmit(RTL8139State *s)
-{
- int descriptor = s->currTxDesc, txcount = 0;
-
- /*while*/
- if (rtl8139_transmit_one(s, descriptor))
- {
- ++s->currTxDesc;
- s->currTxDesc %= 4;
- ++txcount;
- }
-
- /* Mark transfer completed */
- if (!txcount)
- {
- DEBUG_PRINT(("RTL8139: transmitter queue stalled, current TxDesc = %d\n", s->currTxDesc));
- }
-}
-
-static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val)
-{
-
- int descriptor = txRegOffset/4;
-
- /* handle C+ transmit mode register configuration */
-
- if (rtl8139_cp_transmitter_enabled(s))
- {
- DEBUG_PRINT(("RTL8139C+ DTCCR write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor));
-
- /* handle Dump Tally Counters command */
- s->TxStatus[descriptor] = val;
-
- if (descriptor == 0 && (val & 0x8))
- {
- target_phys_addr_t tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]);
-
- /* dump tally counters to specified memory location */
- RTL8139TallyCounters_physical_memory_write( tc_addr, &s->tally_counters);
-
- /* mark dump completed */
- s->TxStatus[0] &= ~0x8;
- }
-
- return;
- }
-
- DEBUG_PRINT(("RTL8139: TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor));
-
- /* mask only reserved bits */
- val &= ~0xff00c000; /* these bits are reset on write */
- val = SET_MASKED(val, 0x00c00000, s->TxStatus[descriptor]);
-
- s->TxStatus[descriptor] = val;
-
- /* attempt to start transmission */
- rtl8139_transmit(s);
-}
-
-static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint32_t txRegOffset)
-{
- uint32_t ret = s->TxStatus[txRegOffset/4];
-
- DEBUG_PRINT(("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret));
-
- return ret;
-}
-
-static uint16_t rtl8139_TSAD_read(RTL8139State *s)
-{
- uint16_t ret = 0;
-
- /* Simulate TSAD, it is read only anyway */
-
- ret = ((s->TxStatus[3] & TxStatOK )?TSAD_TOK3:0)
- |((s->TxStatus[2] & TxStatOK )?TSAD_TOK2:0)
- |((s->TxStatus[1] & TxStatOK )?TSAD_TOK1:0)
- |((s->TxStatus[0] & TxStatOK )?TSAD_TOK0:0)
-
- |((s->TxStatus[3] & TxUnderrun)?TSAD_TUN3:0)
- |((s->TxStatus[2] & TxUnderrun)?TSAD_TUN2:0)
- |((s->TxStatus[1] & TxUnderrun)?TSAD_TUN1:0)
- |((s->TxStatus[0] & TxUnderrun)?TSAD_TUN0:0)
-
- |((s->TxStatus[3] & TxAborted )?TSAD_TABT3:0)
- |((s->TxStatus[2] & TxAborted )?TSAD_TABT2:0)
- |((s->TxStatus[1] & TxAborted )?TSAD_TABT1:0)
- |((s->TxStatus[0] & TxAborted )?TSAD_TABT0:0)
-
- |((s->TxStatus[3] & TxHostOwns )?TSAD_OWN3:0)
- |((s->TxStatus[2] & TxHostOwns )?TSAD_OWN2:0)
- |((s->TxStatus[1] & TxHostOwns )?TSAD_OWN1:0)
- |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ;
-
-
- DEBUG_PRINT(("RTL8139: TSAD read val=0x%04x\n", ret));
-
- return ret;
-}
-
-static uint16_t rtl8139_CSCR_read(RTL8139State *s)
-{
- uint16_t ret = s->CSCR;
-
- DEBUG_PRINT(("RTL8139: CSCR read val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val));
-
- s->TxAddr[txAddrOffset/4] = le32_to_cpu(val);
-}
-
-static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset)
-{
- uint32_t ret = cpu_to_le32(s->TxAddr[txAddrOffset/4]);
-
- DEBUG_PRINT(("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret));
-
- return ret;
-}
-
-static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139: RxBufPtr write val=0x%04x\n", val));
-
- /* this value is off by 16 */
- s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
-
- DEBUG_PRINT((" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
- s->RxBufferSize, s->RxBufAddr, s->RxBufPtr));
-}
-
-static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s)
-{
- /* this value is off by 16 */
- uint32_t ret = s->RxBufPtr - 0x10;
-
- DEBUG_PRINT(("RTL8139: RxBufPtr read val=0x%04x\n", ret));
-
- return ret;
-}
-
-static uint32_t rtl8139_RxBufAddr_read(RTL8139State *s)
-{
- /* this value is NOT off by 16 */
- uint32_t ret = s->RxBufAddr;
-
- DEBUG_PRINT(("RTL8139: RxBufAddr read val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139: RxBuf write val=0x%08x\n", val));
-
- s->RxBuf = val;
-
- /* may need to reset rxring here */
-}
-
-static uint32_t rtl8139_RxBuf_read(RTL8139State *s)
-{
- uint32_t ret = s->RxBuf;
-
- DEBUG_PRINT(("RTL8139: RxBuf read val=0x%08x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139: IntrMask write(w) val=0x%04x\n", val));
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0x1e00, s->IntrMask);
-
- s->IntrMask = val;
-
- rtl8139_update_irq(s);
-}
-
-static uint32_t rtl8139_IntrMask_read(RTL8139State *s)
-{
- uint32_t ret = s->IntrMask;
-
- DEBUG_PRINT(("RTL8139: IntrMask read(w) val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139: IntrStatus write(w) val=0x%04x\n", val));
-
-#if 0
-
- /* writing to ISR has no effect */
-
- return;
-
-#else
- uint16_t newStatus = s->IntrStatus & ~val;
-
- /* mask unwriteable bits */
- newStatus = SET_MASKED(newStatus, 0x1e00, s->IntrStatus);
-
- /* writing 1 to interrupt status register bit clears it */
- s->IntrStatus = 0;
- rtl8139_update_irq(s);
-
- s->IntrStatus = newStatus;
- rtl8139_update_irq(s);
-#endif
-}
-
-static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
-{
- uint32_t ret = s->IntrStatus;
-
- DEBUG_PRINT(("RTL8139: IntrStatus read(w) val=0x%04x\n", ret));
-
-#if 0
-
- /* reading ISR clears all interrupts */
- s->IntrStatus = 0;
-
- rtl8139_update_irq(s);
-
-#endif
-
- return ret;
-}
-
-static void rtl8139_MultiIntr_write(RTL8139State *s, uint32_t val)
-{
- DEBUG_PRINT(("RTL8139: MultiIntr write(w) val=0x%04x\n", val));
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0xf000, s->MultiIntr);
-
- s->MultiIntr = val;
-}
-
-static uint32_t rtl8139_MultiIntr_read(RTL8139State *s)
-{
- uint32_t ret = s->MultiIntr;
-
- DEBUG_PRINT(("RTL8139: MultiIntr read(w) val=0x%04x\n", ret));
-
- return ret;
-}
-
-static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
-{
- RTL8139State *s = opaque;
-
- addr &= 0xff;
-
- switch (addr)
- {
- case MAC0 ... MAC0+5:
- s->phys[addr - MAC0] = val;
- break;
- case MAC0+6 ... MAC0+7:
- /* reserved */
- break;
- case MAR0 ... MAR0+7:
- s->mult[addr - MAR0] = val;
- break;
- case ChipCmd:
- rtl8139_ChipCmd_write(s, val);
- break;
- case Cfg9346:
- rtl8139_Cfg9346_write(s, val);
- break;
- case TxConfig: /* windows driver sometimes writes using byte-lenth call */
- rtl8139_TxConfig_writeb(s, val);
- break;
- case Config0:
- rtl8139_Config0_write(s, val);
- break;
- case Config1:
- rtl8139_Config1_write(s, val);
- break;
- case Config3:
- rtl8139_Config3_write(s, val);
- break;
- case Config4:
- rtl8139_Config4_write(s, val);
- break;
- case Config5:
- rtl8139_Config5_write(s, val);
- break;
- case MediaStatus:
- /* ignore */
- DEBUG_PRINT(("RTL8139: not implemented write(b) to MediaStatus val=0x%02x\n", val));
- break;
-
- case HltClk:
- DEBUG_PRINT(("RTL8139: HltClk write val=0x%08x\n", val));
- if (val == 'R')
- {
- s->clock_enabled = 1;
- }
- else if (val == 'H')
- {
- s->clock_enabled = 0;
- }
- break;
-
- case TxThresh:
- DEBUG_PRINT(("RTL8139C+ TxThresh write(b) val=0x%02x\n", val));
- s->TxThresh = val;
- break;
-
- case TxPoll:
- DEBUG_PRINT(("RTL8139C+ TxPoll write(b) val=0x%02x\n", val));
- if (val & (1 << 7))
- {
- DEBUG_PRINT(("RTL8139C+ TxPoll high priority transmission (not implemented)\n"));
- //rtl8139_cplus_transmit(s);
- }
- if (val & (1 << 6))
- {
- DEBUG_PRINT(("RTL8139C+ TxPoll normal priority transmission\n"));
- rtl8139_cplus_transmit(s);
- }
-
- break;
-
- default:
- DEBUG_PRINT(("RTL8139: not implemented write(b) addr=0x%x val=0x%02x\n", addr, val));
- break;
- }
-}
-
-static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
-{
- RTL8139State *s = opaque;
-
- addr &= 0xfe;
-
- switch (addr)
- {
- case IntrMask:
- rtl8139_IntrMask_write(s, val);
- break;
-
- case IntrStatus:
- rtl8139_IntrStatus_write(s, val);
- break;
-
- case MultiIntr:
- rtl8139_MultiIntr_write(s, val);
- break;
-
- case RxBufPtr:
- rtl8139_RxBufPtr_write(s, val);
- break;
-
- case BasicModeCtrl:
- rtl8139_BasicModeCtrl_write(s, val);
- break;
- case BasicModeStatus:
- rtl8139_BasicModeStatus_write(s, val);
- break;
- case NWayAdvert:
- DEBUG_PRINT(("RTL8139: NWayAdvert write(w) val=0x%04x\n", val));
- s->NWayAdvert = val;
- break;
- case NWayLPAR:
- DEBUG_PRINT(("RTL8139: forbidden NWayLPAR write(w) val=0x%04x\n", val));
- break;
- case NWayExpansion:
- DEBUG_PRINT(("RTL8139: NWayExpansion write(w) val=0x%04x\n", val));
- s->NWayExpansion = val;
- break;
-
- case CpCmd:
- rtl8139_CpCmd_write(s, val);
- break;
-
- case IntrMitigate:
- rtl8139_IntrMitigate_write(s, val);
- break;
-
- default:
- DEBUG_PRINT(("RTL8139: ioport write(w) addr=0x%x val=0x%04x via write(b)\n", addr, val));
-
-#ifdef TARGET_WORDS_BIGENDIAN
- rtl8139_io_writeb(opaque, addr, (val >> 8) & 0xff);
- rtl8139_io_writeb(opaque, addr + 1, val & 0xff);
-#else
- rtl8139_io_writeb(opaque, addr, val & 0xff);
- rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
- break;
- }
-}
-
-static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
-{
- RTL8139State *s = opaque;
-
- addr &= 0xfc;
-
- switch (addr)
- {
- case RxMissed:
- DEBUG_PRINT(("RTL8139: RxMissed clearing on write\n"));
- s->RxMissed = 0;
- break;
-
- case TxConfig:
- rtl8139_TxConfig_write(s, val);
- break;
-
- case RxConfig:
- rtl8139_RxConfig_write(s, val);
- break;
-
- case TxStatus0 ... TxStatus0+4*4-1:
- rtl8139_TxStatus_write(s, addr-TxStatus0, val);
- break;
-
- case TxAddr0 ... TxAddr0+4*4-1:
- rtl8139_TxAddr_write(s, addr-TxAddr0, val);
- break;
-
- case RxBuf:
- rtl8139_RxBuf_write(s, val);
- break;
-
- case RxRingAddrLO:
- DEBUG_PRINT(("RTL8139: C+ RxRing low bits write val=0x%08x\n", val));
- s->RxRingAddrLO = val;
- break;
-
- case RxRingAddrHI:
- DEBUG_PRINT(("RTL8139: C+ RxRing high bits write val=0x%08x\n", val));
- s->RxRingAddrHI = val;
- break;
-
- case Timer:
- DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n"));
- s->TCTR = 0;
- s->TCTR_base = qemu_get_clock(vm_clock);
- break;
-
- case FlashReg:
- DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", val));
- s->TimerInt = val;
- break;
-
- default:
- DEBUG_PRINT(("RTL8139: ioport write(l) addr=0x%x val=0x%08x via write(b)\n", addr, val));
-#ifdef TARGET_WORDS_BIGENDIAN
- rtl8139_io_writeb(opaque, addr, (val >> 24) & 0xff);
- rtl8139_io_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- rtl8139_io_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- rtl8139_io_writeb(opaque, addr + 3, val & 0xff);
-#else
- rtl8139_io_writeb(opaque, addr, val & 0xff);
- rtl8139_io_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- rtl8139_io_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- rtl8139_io_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
- break;
- }
-}
-
-static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
-{
- RTL8139State *s = opaque;
- int ret;
-
- addr &= 0xff;
-
- switch (addr)
- {
- case MAC0 ... MAC0+5:
- ret = s->phys[addr - MAC0];
- break;
- case MAC0+6 ... MAC0+7:
- ret = 0;
- break;
- case MAR0 ... MAR0+7:
- ret = s->mult[addr - MAR0];
- break;
- case ChipCmd:
- ret = rtl8139_ChipCmd_read(s);
- break;
- case Cfg9346:
- ret = rtl8139_Cfg9346_read(s);
- break;
- case Config0:
- ret = rtl8139_Config0_read(s);
- break;
- case Config1:
- ret = rtl8139_Config1_read(s);
- break;
- case Config3:
- ret = rtl8139_Config3_read(s);
- break;
- case Config4:
- ret = rtl8139_Config4_read(s);
- break;
- case Config5:
- ret = rtl8139_Config5_read(s);
- break;
-
- case MediaStatus:
- ret = 0xd0;
- DEBUG_PRINT(("RTL8139: MediaStatus read 0x%x\n", ret));
- break;
-
- case HltClk:
- ret = s->clock_enabled;
- DEBUG_PRINT(("RTL8139: HltClk read 0x%x\n", ret));
- break;
-
- case PCIRevisionID:
- ret = RTL8139_PCI_REVID;
- DEBUG_PRINT(("RTL8139: PCI Revision ID read 0x%x\n", ret));
- break;
-
- case TxThresh:
- ret = s->TxThresh;
- DEBUG_PRINT(("RTL8139C+ TxThresh read(b) val=0x%02x\n", ret));
- break;
-
- case 0x43: /* Part of TxConfig register. Windows driver tries to read it */
- ret = s->TxConfig >> 24;
- DEBUG_PRINT(("RTL8139C TxConfig at 0x43 read(b) val=0x%02x\n", ret));
- break;
-
- default:
- DEBUG_PRINT(("RTL8139: not implemented read(b) addr=0x%x\n", addr));
- ret = 0;
- break;
- }
-
- return ret;
-}
-
-static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
-{
- RTL8139State *s = opaque;
- uint32_t ret;
-
- addr &= 0xfe; /* mask lower bit */
-
- switch (addr)
- {
- case IntrMask:
- ret = rtl8139_IntrMask_read(s);
- break;
-
- case IntrStatus:
- ret = rtl8139_IntrStatus_read(s);
- break;
-
- case MultiIntr:
- ret = rtl8139_MultiIntr_read(s);
- break;
-
- case RxBufPtr:
- ret = rtl8139_RxBufPtr_read(s);
- break;
-
- case RxBufAddr:
- ret = rtl8139_RxBufAddr_read(s);
- break;
-
- case BasicModeCtrl:
- ret = rtl8139_BasicModeCtrl_read(s);
- break;
- case BasicModeStatus:
- ret = rtl8139_BasicModeStatus_read(s);
- break;
- case NWayAdvert:
- ret = s->NWayAdvert;
- DEBUG_PRINT(("RTL8139: NWayAdvert read(w) val=0x%04x\n", ret));
- break;
- case NWayLPAR:
- ret = s->NWayLPAR;
- DEBUG_PRINT(("RTL8139: NWayLPAR read(w) val=0x%04x\n", ret));
- break;
- case NWayExpansion:
- ret = s->NWayExpansion;
- DEBUG_PRINT(("RTL8139: NWayExpansion read(w) val=0x%04x\n", ret));
- break;
-
- case CpCmd:
- ret = rtl8139_CpCmd_read(s);
- break;
-
- case IntrMitigate:
- ret = rtl8139_IntrMitigate_read(s);
- break;
-
- case TxSummary:
- ret = rtl8139_TSAD_read(s);
- break;
-
- case CSCR:
- ret = rtl8139_CSCR_read(s);
- break;
-
- default:
- DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x via read(b)\n", addr));
-
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = rtl8139_io_readb(opaque, addr) << 8;
- ret |= rtl8139_io_readb(opaque, addr + 1);
-#else
- ret = rtl8139_io_readb(opaque, addr);
- ret |= rtl8139_io_readb(opaque, addr + 1) << 8;
-#endif
-
- DEBUG_PRINT(("RTL8139: ioport read(w) addr=0x%x val=0x%04x\n", addr, ret));
- break;
- }
-
- return ret;
-}
-
-static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
-{
- RTL8139State *s = opaque;
- uint32_t ret;
-
- addr &= 0xfc; /* also mask low 2 bits */
-
- switch (addr)
- {
- case RxMissed:
- ret = s->RxMissed;
-
- DEBUG_PRINT(("RTL8139: RxMissed read val=0x%08x\n", ret));
- break;
-
- case TxConfig:
- ret = rtl8139_TxConfig_read(s);
- break;
-
- case RxConfig:
- ret = rtl8139_RxConfig_read(s);
- break;
-
- case TxStatus0 ... TxStatus0+4*4-1:
- ret = rtl8139_TxStatus_read(s, addr-TxStatus0);
- break;
-
- case TxAddr0 ... TxAddr0+4*4-1:
- ret = rtl8139_TxAddr_read(s, addr-TxAddr0);
- break;
-
- case RxBuf:
- ret = rtl8139_RxBuf_read(s);
- break;
-
- case RxRingAddrLO:
- ret = s->RxRingAddrLO;
- DEBUG_PRINT(("RTL8139: C+ RxRing low bits read val=0x%08x\n", ret));
- break;
-
- case RxRingAddrHI:
- ret = s->RxRingAddrHI;
- DEBUG_PRINT(("RTL8139: C+ RxRing high bits read val=0x%08x\n", ret));
- break;
-
- case Timer:
- ret = s->TCTR;
- DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret));
- break;
-
- case FlashReg:
- ret = s->TimerInt;
- DEBUG_PRINT(("RTL8139: FlashReg TimerInt read val=0x%08x\n", ret));
- break;
-
- default:
- DEBUG_PRINT(("RTL8139: ioport read(l) addr=0x%x via read(b)\n", addr));
-
-#ifdef TARGET_WORDS_BIGENDIAN
- ret = rtl8139_io_readb(opaque, addr) << 24;
- ret |= rtl8139_io_readb(opaque, addr + 1) << 16;
- ret |= rtl8139_io_readb(opaque, addr + 2) << 8;
- ret |= rtl8139_io_readb(opaque, addr + 3);
-#else
- ret = rtl8139_io_readb(opaque, addr);
- ret |= rtl8139_io_readb(opaque, addr + 1) << 8;
- ret |= rtl8139_io_readb(opaque, addr + 2) << 16;
- ret |= rtl8139_io_readb(opaque, addr + 3) << 24;
-#endif
-
- DEBUG_PRINT(("RTL8139: read(l) addr=0x%x val=%08x\n", addr, ret));
- break;
- }
-
- return ret;
-}
-
-/* */
-
-static void rtl8139_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- rtl8139_io_writeb(opaque, addr & 0xFF, val);
-}
-
-static void rtl8139_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- rtl8139_io_writew(opaque, addr & 0xFF, val);
-}
-
-static void rtl8139_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- rtl8139_io_writel(opaque, addr & 0xFF, val);
-}
-
-static uint32_t rtl8139_ioport_readb(void *opaque, uint32_t addr)
-{
- return rtl8139_io_readb(opaque, addr & 0xFF);
-}
-
-static uint32_t rtl8139_ioport_readw(void *opaque, uint32_t addr)
-{
- return rtl8139_io_readw(opaque, addr & 0xFF);
-}
-
-static uint32_t rtl8139_ioport_readl(void *opaque, uint32_t addr)
-{
- return rtl8139_io_readl(opaque, addr & 0xFF);
-}
-
-/* */
-
-static void rtl8139_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- rtl8139_io_writeb(opaque, addr & 0xFF, val);
-}
-
-static void rtl8139_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- rtl8139_io_writew(opaque, addr & 0xFF, val);
-}
-
-static void rtl8139_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- rtl8139_io_writel(opaque, addr & 0xFF, val);
-}
-
-static uint32_t rtl8139_mmio_readb(void *opaque, target_phys_addr_t addr)
-{
- return rtl8139_io_readb(opaque, addr & 0xFF);
-}
-
-static uint32_t rtl8139_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
- return rtl8139_io_readw(opaque, addr & 0xFF);
-}
-
-static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
- return rtl8139_io_readl(opaque, addr & 0xFF);
-}
-
-/* */
-
-static void rtl8139_save(QEMUFile* f,void* opaque)
-{
- RTL8139State* s=(RTL8139State*)opaque;
- int i;
-
- qemu_put_buffer(f, s->phys, 6);
- qemu_put_buffer(f, s->mult, 8);
-
- for (i=0; i<4; ++i)
- {
- qemu_put_be32s(f, &s->TxStatus[i]); /* TxStatus0 */
- }
- for (i=0; i<4; ++i)
- {
- qemu_put_be32s(f, &s->TxAddr[i]); /* TxAddr0 */
- }
-
- qemu_put_be32s(f, &s->RxBuf); /* Receive buffer */
- qemu_put_be32s(f, &s->RxBufferSize);/* internal variable, receive ring buffer size in C mode */
- qemu_put_be32s(f, &s->RxBufPtr);
- qemu_put_be32s(f, &s->RxBufAddr);
-
- qemu_put_be16s(f, &s->IntrStatus);
- qemu_put_be16s(f, &s->IntrMask);
-
- qemu_put_be32s(f, &s->TxConfig);
- qemu_put_be32s(f, &s->RxConfig);
- qemu_put_be32s(f, &s->RxMissed);
- qemu_put_be16s(f, &s->CSCR);
-
- qemu_put_8s(f, &s->Cfg9346);
- qemu_put_8s(f, &s->Config0);
- qemu_put_8s(f, &s->Config1);
- qemu_put_8s(f, &s->Config3);
- qemu_put_8s(f, &s->Config4);
- qemu_put_8s(f, &s->Config5);
-
- qemu_put_8s(f, &s->clock_enabled);
- qemu_put_8s(f, &s->bChipCmdState);
-
- qemu_put_be16s(f, &s->MultiIntr);
-
- qemu_put_be16s(f, &s->BasicModeCtrl);
- qemu_put_be16s(f, &s->BasicModeStatus);
- qemu_put_be16s(f, &s->NWayAdvert);
- qemu_put_be16s(f, &s->NWayLPAR);
- qemu_put_be16s(f, &s->NWayExpansion);
-
- qemu_put_be16s(f, &s->CpCmd);
- qemu_put_8s(f, &s->TxThresh);
-
- qemu_put_be32s(f, &s->irq);
- qemu_put_buffer(f, s->macaddr, 6);
- qemu_put_be32s(f, &s->rtl8139_mmio_io_addr);
-
- qemu_put_be32s(f, &s->currTxDesc);
- qemu_put_be32s(f, &s->currCPlusRxDesc);
- qemu_put_be32s(f, &s->currCPlusTxDesc);
- qemu_put_be32s(f, &s->RxRingAddrLO);
- qemu_put_be32s(f, &s->RxRingAddrHI);
-
- for (i=0; i<EEPROM_9346_SIZE; ++i)
- {
- qemu_put_be16s(f, &s->eeprom.contents[i]);
- }
- qemu_put_be32s(f, &s->eeprom.mode);
- qemu_put_be32s(f, &s->eeprom.tick);
- qemu_put_8s(f, &s->eeprom.address);
- qemu_put_be16s(f, &s->eeprom.input);
- qemu_put_be16s(f, &s->eeprom.output);
-
- qemu_put_8s(f, &s->eeprom.eecs);
- qemu_put_8s(f, &s->eeprom.eesk);
- qemu_put_8s(f, &s->eeprom.eedi);
- qemu_put_8s(f, &s->eeprom.eedo);
-
- qemu_put_be32s(f, &s->TCTR);
- qemu_put_be32s(f, &s->TimerInt);
- qemu_put_be64s(f, &s->TCTR_base);
-
- RTL8139TallyCounters_save(f, &s->tally_counters);
-}
-
-static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
-{
- RTL8139State* s=(RTL8139State*)opaque;
- int i;
-
- /* just 2 versions for now */
- if (version_id > 2)
- return -EINVAL;
-
- /* saved since version 1 */
- qemu_get_buffer(f, s->phys, 6);
- qemu_get_buffer(f, s->mult, 8);
-
- for (i=0; i<4; ++i)
- {
- qemu_get_be32s(f, &s->TxStatus[i]); /* TxStatus0 */
- }
- for (i=0; i<4; ++i)
- {
- qemu_get_be32s(f, &s->TxAddr[i]); /* TxAddr0 */
- }
-
- qemu_get_be32s(f, &s->RxBuf); /* Receive buffer */
- qemu_get_be32s(f, &s->RxBufferSize);/* internal variable, receive ring buffer size in C mode */
- qemu_get_be32s(f, &s->RxBufPtr);
- qemu_get_be32s(f, &s->RxBufAddr);
-
- qemu_get_be16s(f, &s->IntrStatus);
- qemu_get_be16s(f, &s->IntrMask);
-
- qemu_get_be32s(f, &s->TxConfig);
- qemu_get_be32s(f, &s->RxConfig);
- qemu_get_be32s(f, &s->RxMissed);
- qemu_get_be16s(f, &s->CSCR);
-
- qemu_get_8s(f, &s->Cfg9346);
- qemu_get_8s(f, &s->Config0);
- qemu_get_8s(f, &s->Config1);
- qemu_get_8s(f, &s->Config3);
- qemu_get_8s(f, &s->Config4);
- qemu_get_8s(f, &s->Config5);
-
- qemu_get_8s(f, &s->clock_enabled);
- qemu_get_8s(f, &s->bChipCmdState);
-
- qemu_get_be16s(f, &s->MultiIntr);
-
- qemu_get_be16s(f, &s->BasicModeCtrl);
- qemu_get_be16s(f, &s->BasicModeStatus);
- qemu_get_be16s(f, &s->NWayAdvert);
- qemu_get_be16s(f, &s->NWayLPAR);
- qemu_get_be16s(f, &s->NWayExpansion);
-
- qemu_get_be16s(f, &s->CpCmd);
- qemu_get_8s(f, &s->TxThresh);
-
- qemu_get_be32s(f, &s->irq);
- qemu_get_buffer(f, s->macaddr, 6);
- qemu_get_be32s(f, &s->rtl8139_mmio_io_addr);
-
- qemu_get_be32s(f, &s->currTxDesc);
- qemu_get_be32s(f, &s->currCPlusRxDesc);
- qemu_get_be32s(f, &s->currCPlusTxDesc);
- qemu_get_be32s(f, &s->RxRingAddrLO);
- qemu_get_be32s(f, &s->RxRingAddrHI);
-
- for (i=0; i<EEPROM_9346_SIZE; ++i)
- {
- qemu_get_be16s(f, &s->eeprom.contents[i]);
- }
- qemu_get_be32s(f, &s->eeprom.mode);
- qemu_get_be32s(f, &s->eeprom.tick);
- qemu_get_8s(f, &s->eeprom.address);
- qemu_get_be16s(f, &s->eeprom.input);
- qemu_get_be16s(f, &s->eeprom.output);
-
- qemu_get_8s(f, &s->eeprom.eecs);
- qemu_get_8s(f, &s->eeprom.eesk);
- qemu_get_8s(f, &s->eeprom.eedi);
- qemu_get_8s(f, &s->eeprom.eedo);
-
- /* saved since version 2 */
- if (version_id >= 2)
- {
- qemu_get_be32s(f, &s->TCTR);
- qemu_get_be32s(f, &s->TimerInt);
- qemu_get_be64s(f, &s->TCTR_base);
-
- RTL8139TallyCounters_load(f, &s->tally_counters);
- }
- else
- {
- /* not saved, use default */
- s->TCTR = 0;
- s->TimerInt = 0;
- s->TCTR_base = 0;
-
- RTL8139TallyCounters_clear(&s->tally_counters);
- }
-
- return 0;
-}
-
-/***********************************************************/
-/* PCI RTL8139 definitions */
-
-typedef struct PCIRTL8139State {
- PCIDevice dev;
- RTL8139State rtl8139;
-} PCIRTL8139State;
-
-static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCIRTL8139State *d = (PCIRTL8139State *)pci_dev;
- RTL8139State *s = &d->rtl8139;
-
- cpu_register_physical_memory(addr + 0, 0x100, s->rtl8139_mmio_io_addr);
-}
-
-static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCIRTL8139State *d = (PCIRTL8139State *)pci_dev;
- RTL8139State *s = &d->rtl8139;
-
- register_ioport_write(addr, 0x100, 1, rtl8139_ioport_writeb, s);
- register_ioport_read( addr, 0x100, 1, rtl8139_ioport_readb, s);
-
- register_ioport_write(addr, 0x100, 2, rtl8139_ioport_writew, s);
- register_ioport_read( addr, 0x100, 2, rtl8139_ioport_readw, s);
-
- register_ioport_write(addr, 0x100, 4, rtl8139_ioport_writel, s);
- register_ioport_read( addr, 0x100, 4, rtl8139_ioport_readl, s);
-}
-
-static CPUReadMemoryFunc *rtl8139_mmio_read[3] = {
- rtl8139_mmio_readb,
- rtl8139_mmio_readw,
- rtl8139_mmio_readl,
-};
-
-static CPUWriteMemoryFunc *rtl8139_mmio_write[3] = {
- rtl8139_mmio_writeb,
- rtl8139_mmio_writew,
- rtl8139_mmio_writel,
-};
-
-static inline int64_t rtl8139_get_next_tctr_time(RTL8139State *s, int64_t current_time)
-{
- int64_t next_time = current_time +
- muldiv64(1, ticks_per_sec, PCI_FREQUENCY);
- if (next_time <= current_time)
- next_time = current_time + 1;
- return next_time;
-}
-
-#if RTL8139_ONBOARD_TIMER
-static void rtl8139_timer(void *opaque)
-{
- RTL8139State *s = opaque;
-
- int is_timeout = 0;
-
- int64_t curr_time;
- uint32_t curr_tick;
-
- if (!s->clock_enabled)
- {
- DEBUG_PRINT(("RTL8139: >>> timer: clock is not running\n"));
- return;
- }
-
- curr_time = qemu_get_clock(vm_clock);
-
- curr_tick = muldiv64(curr_time - s->TCTR_base, PCI_FREQUENCY, ticks_per_sec);
-
- if (s->TimerInt && curr_tick >= s->TimerInt)
- {
- if (s->TCTR < s->TimerInt || curr_tick < s->TCTR)
- {
- is_timeout = 1;
- }
- }
-
- s->TCTR = curr_tick;
-
-// DEBUG_PRINT(("RTL8139: >>> timer: tick=%08u\n", s->TCTR));
-
- if (is_timeout)
- {
- DEBUG_PRINT(("RTL8139: >>> timer: timeout tick=%08u\n", s->TCTR));
- s->IntrStatus |= PCSTimeout;
- rtl8139_update_irq(s);
- }
-
- qemu_mod_timer(s->timer,
- rtl8139_get_next_tctr_time(s,curr_time));
-}
-#endif /* RTL8139_ONBOARD_TIMER */
-
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd)
-{
- PCIRTL8139State *d;
- RTL8139State *s;
- uint8_t *pci_conf;
-
- d = (PCIRTL8139State *)pci_register_device(bus,
- "RTL8139", sizeof(PCIRTL8139State),
- -1,
- NULL, NULL);
- pci_conf = d->dev.config;
- pci_conf[0x00] = 0xec; /* Realtek 8139 */
- pci_conf[0x01] = 0x10;
- pci_conf[0x02] = 0x39;
- pci_conf[0x03] = 0x81;
- pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */
- pci_conf[0x08] = RTL8139_PCI_REVID; /* PCI revision ID; >=0x20 is for 8139C+ */
- pci_conf[0x0a] = 0x00; /* ethernet network controller */
- pci_conf[0x0b] = 0x02;
- pci_conf[0x0e] = 0x00; /* header_type */
- pci_conf[0x3d] = 1; /* interrupt pin 0 */
- pci_conf[0x34] = 0xdc;
-
- s = &d->rtl8139;
-
- /* I/O handler for memory-mapped I/O */
- s->rtl8139_mmio_io_addr =
- cpu_register_io_memory(0, rtl8139_mmio_read, rtl8139_mmio_write, s);
-
- pci_register_io_region(&d->dev, 0, 0x100,
- PCI_ADDRESS_SPACE_IO, rtl8139_ioport_map);
-
- pci_register_io_region(&d->dev, 1, 0x100,
- PCI_ADDRESS_SPACE_MEM, rtl8139_mmio_map);
-
- s->irq = 16; /* PCI interrupt */
- s->pci_dev = (PCIDevice *)d;
- memcpy(s->macaddr, nd->macaddr, 6);
- rtl8139_reset(s);
- s->vc = qemu_new_vlan_client(nd->vlan, rtl8139_receive,
- rtl8139_can_receive, s);
-
- snprintf(s->vc->info_str, sizeof(s->vc->info_str),
- "rtl8139 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
- s->macaddr[0],
- s->macaddr[1],
- s->macaddr[2],
- s->macaddr[3],
- s->macaddr[4],
- s->macaddr[5]);
-
- s->cplus_txbuffer = NULL;
- s->cplus_txbuffer_len = 0;
- s->cplus_txbuffer_offset = 0;
-
- /* XXX: instance number ? */
- register_savevm("rtl8139", 0, 2, rtl8139_save, rtl8139_load, s);
- register_savevm("rtl8139_pci", 0, 1, generic_pci_save, generic_pci_load,
- &d->dev);
-
-#if RTL8139_ONBOARD_TIMER
- s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
-
- qemu_mod_timer(s->timer,
- rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock)));
-#endif /* RTL8139_ONBOARD_TIMER */
-}
-
diff --git a/hw/sb16.c b/hw/sb16.c
deleted file mode 100644
index 04325ac..0000000
--- a/hw/sb16.c
+++ /dev/null
@@ -1,1451 +0,0 @@
-/*
- * QEMU Soundblaster 16 emulation
- *
- * Copyright (c) 2003-2005 Vassili Karpov (malc)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
-
-#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
-
-/* #define DEBUG */
-/* #define DEBUG_SB16_MOST */
-
-#ifdef DEBUG
-#define ldebug(...) dolog (__VA_ARGS__)
-#else
-#define ldebug(...)
-#endif
-
-#define IO_READ_PROTO(name) \
- uint32_t name (void *opaque, uint32_t nport)
-#define IO_WRITE_PROTO(name) \
- void name (void *opaque, uint32_t nport, uint32_t val)
-
-static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
-
-static struct {
- int ver_lo;
- int ver_hi;
- int irq;
- int dma;
- int hdma;
- int port;
-} conf = {5, 4, 5, 1, 5, 0x220};
-
-typedef struct SB16State {
- QEMUSoundCard card;
- int irq;
- int dma;
- int hdma;
- int port;
- int ver;
-
- int in_index;
- int out_data_len;
- int fmt_stereo;
- int fmt_signed;
- int fmt_bits;
- audfmt_e fmt;
- int dma_auto;
- int block_size;
- int fifo;
- int freq;
- int time_const;
- int speaker;
- int needed_bytes;
- int cmd;
- int use_hdma;
- int highspeed;
- int can_write;
-
- int v2x6;
-
- uint8_t csp_param;
- uint8_t csp_value;
- uint8_t csp_mode;
- uint8_t csp_regs[256];
- uint8_t csp_index;
- uint8_t csp_reg83[4];
- int csp_reg83r;
- int csp_reg83w;
-
- uint8_t in2_data[10];
- uint8_t out_data[50];
- uint8_t test_reg;
- uint8_t last_read_byte;
- int nzero;
-
- int left_till_irq;
-
- int dma_running;
- int bytes_per_second;
- int align;
- int audio_free;
- SWVoiceOut *voice;
-
- QEMUTimer *aux_ts;
- /* mixer state */
- int mixer_nreg;
- uint8_t mixer_regs[256];
-} SB16State;
-
-static void SB_audio_callback (void *opaque, int free);
-
-static int magic_of_irq (int irq)
-{
- switch (irq) {
- case 5:
- return 2;
- case 7:
- return 4;
- case 9:
- return 1;
- case 10:
- return 8;
- default:
- dolog ("bad irq %d\n", irq);
- return 2;
- }
-}
-
-static int irq_of_magic (int magic)
-{
- switch (magic) {
- case 1:
- return 9;
- case 2:
- return 5;
- case 4:
- return 7;
- case 8:
- return 10;
- default:
- dolog ("bad irq magic %d\n", magic);
- return -1;
- }
-}
-
-#if 0
-static void log_dsp (SB16State *dsp)
-{
- ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
- dsp->fmt_stereo ? "Stereo" : "Mono",
- dsp->fmt_signed ? "Signed" : "Unsigned",
- dsp->fmt_bits,
- dsp->dma_auto ? "Auto" : "Single",
- dsp->block_size,
- dsp->freq,
- dsp->time_const,
- dsp->speaker);
-}
-#endif
-
-static void speaker (SB16State *s, int on)
-{
- s->speaker = on;
- /* AUD_enable (s->voice, on); */
-}
-
-static void control (SB16State *s, int hold)
-{
- int dma = s->use_hdma ? s->hdma : s->dma;
- s->dma_running = hold;
-
- ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
-
- if (hold) {
- DMA_hold_DREQ (dma);
- AUD_set_active_out (s->voice, 1);
- }
- else {
- DMA_release_DREQ (dma);
- AUD_set_active_out (s->voice, 0);
- }
-}
-
-static void aux_timer (void *opaque)
-{
- SB16State *s = opaque;
- s->can_write = 1;
- pic_set_irq (s->irq, 1);
-}
-
-#define DMA8_AUTO 1
-#define DMA8_HIGH 2
-
-static void continue_dma8 (SB16State *s)
-{
- if (s->freq > 0) {
- audsettings_t as;
-
- s->audio_free = 0;
-
- as.freq = s->freq;
- as.nchannels = 1 << s->fmt_stereo;
- as.fmt = s->fmt;
- as.endianness = 0;
-
- s->voice = AUD_open_out (
- &s->card,
- s->voice,
- "sb16",
- s,
- SB_audio_callback,
- &as
- );
- }
-
- control (s, 1);
-}
-
-static void dma_cmd8 (SB16State *s, int mask, int dma_len)
-{
- s->fmt = AUD_FMT_U8;
- s->use_hdma = 0;
- s->fmt_bits = 8;
- s->fmt_signed = 0;
- s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
- if (-1 == s->time_const) {
- if (s->freq <= 0)
- s->freq = 11025;
- }
- else {
- int tmp = (256 - s->time_const);
- s->freq = (1000000 + (tmp / 2)) / tmp;
- }
-
- if (dma_len != -1) {
- s->block_size = dma_len << s->fmt_stereo;
- }
- else {
- /* This is apparently the only way to make both Act1/PL
- and SecondReality/FC work
-
- Act1 sets block size via command 0x48 and it's an odd number
- SR does the same with even number
- Both use stereo, and Creatives own documentation states that
- 0x48 sets block size in bytes less one.. go figure */
- s->block_size &= ~s->fmt_stereo;
- }
-
- s->freq >>= s->fmt_stereo;
- s->left_till_irq = s->block_size;
- s->bytes_per_second = (s->freq << s->fmt_stereo);
- /* s->highspeed = (mask & DMA8_HIGH) != 0; */
- s->dma_auto = (mask & DMA8_AUTO) != 0;
- s->align = (1 << s->fmt_stereo) - 1;
-
- if (s->block_size & s->align) {
- dolog ("warning: misaligned block size %d, alignment %d\n",
- s->block_size, s->align + 1);
- }
-
- ldebug ("freq %d, stereo %d, sign %d, bits %d, "
- "dma %d, auto %d, fifo %d, high %d\n",
- s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
- s->block_size, s->dma_auto, s->fifo, s->highspeed);
-
- continue_dma8 (s);
- speaker (s, 1);
-}
-
-static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
-{
- s->use_hdma = cmd < 0xc0;
- s->fifo = (cmd >> 1) & 1;
- s->dma_auto = (cmd >> 2) & 1;
- s->fmt_signed = (d0 >> 4) & 1;
- s->fmt_stereo = (d0 >> 5) & 1;
-
- switch (cmd >> 4) {
- case 11:
- s->fmt_bits = 16;
- break;
-
- case 12:
- s->fmt_bits = 8;
- break;
- }
-
- if (-1 != s->time_const) {
-#if 1
- int tmp = 256 - s->time_const;
- s->freq = (1000000 + (tmp / 2)) / tmp;
-#else
- /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
- s->freq = 1000000 / ((255 - s->time_const));
-#endif
- s->time_const = -1;
- }
-
- s->block_size = dma_len + 1;
- s->block_size <<= (s->fmt_bits == 16);
- if (!s->dma_auto) {
- /* It is clear that for DOOM and auto-init this value
- shouldn't take stereo into account, while Miles Sound Systems
- setsound.exe with single transfer mode wouldn't work without it
- wonders of SB16 yet again */
- s->block_size <<= s->fmt_stereo;
- }
-
- ldebug ("freq %d, stereo %d, sign %d, bits %d, "
- "dma %d, auto %d, fifo %d, high %d\n",
- s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
- s->block_size, s->dma_auto, s->fifo, s->highspeed);
-
- if (16 == s->fmt_bits) {
- if (s->fmt_signed) {
- s->fmt = AUD_FMT_S16;
- }
- else {
- s->fmt = AUD_FMT_U16;
- }
- }
- else {
- if (s->fmt_signed) {
- s->fmt = AUD_FMT_S8;
- }
- else {
- s->fmt = AUD_FMT_U8;
- }
- }
-
- s->left_till_irq = s->block_size;
-
- s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
- s->highspeed = 0;
- s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
- if (s->block_size & s->align) {
- dolog ("warning: misaligned block size %d, alignment %d\n",
- s->block_size, s->align + 1);
- }
-
- if (s->freq) {
- audsettings_t as;
-
- s->audio_free = 0;
-
- as.freq = s->freq;
- as.nchannels = 1 << s->fmt_stereo;
- as.fmt = s->fmt;
- as.endianness = 0;
-
- s->voice = AUD_open_out (
- &s->card,
- s->voice,
- "sb16",
- s,
- SB_audio_callback,
- &as
- );
- }
-
- control (s, 1);
- speaker (s, 1);
-}
-
-static inline void dsp_out_data (SB16State *s, uint8_t val)
-{
- ldebug ("outdata %#x\n", val);
- if ((size_t) s->out_data_len < sizeof (s->out_data)) {
- s->out_data[s->out_data_len++] = val;
- }
-}
-
-static inline uint8_t dsp_get_data (SB16State *s)
-{
- if (s->in_index) {
- return s->in2_data[--s->in_index];
- }
- else {
- dolog ("buffer underflow\n");
- return 0;
- }
-}
-
-static void command (SB16State *s, uint8_t cmd)
-{
- ldebug ("command %#x\n", cmd);
-
- if (cmd > 0xaf && cmd < 0xd0) {
- if (cmd & 8) {
- dolog ("ADC not yet supported (command %#x)\n", cmd);
- }
-
- switch (cmd >> 4) {
- case 11:
- case 12:
- break;
- default:
- dolog ("%#x wrong bits\n", cmd);
- }
- s->needed_bytes = 3;
- }
- else {
- s->needed_bytes = 0;
-
- switch (cmd) {
- case 0x03:
- dsp_out_data (s, 0x10); /* s->csp_param); */
- goto warn;
-
- case 0x04:
- s->needed_bytes = 1;
- goto warn;
-
- case 0x05:
- s->needed_bytes = 2;
- goto warn;
-
- case 0x08:
- /* __asm__ ("int3"); */
- goto warn;
-
- case 0x0e:
- s->needed_bytes = 2;
- goto warn;
-
- case 0x09:
- dsp_out_data (s, 0xf8);
- goto warn;
-
- case 0x0f:
- s->needed_bytes = 1;
- goto warn;
-
- case 0x10:
- s->needed_bytes = 1;
- goto warn;
-
- case 0x14:
- s->needed_bytes = 2;
- s->block_size = 0;
- break;
-
- case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
- dma_cmd8 (s, DMA8_AUTO, -1);
- break;
-
- case 0x20: /* Direct ADC, Juice/PL */
- dsp_out_data (s, 0xff);
- goto warn;
-
- case 0x35:
- dolog ("0x35 - MIDI command not implemented\n");
- break;
-
- case 0x40:
- s->freq = -1;
- s->time_const = -1;
- s->needed_bytes = 1;
- break;
-
- case 0x41:
- s->freq = -1;
- s->time_const = -1;
- s->needed_bytes = 2;
- break;
-
- case 0x42:
- s->freq = -1;
- s->time_const = -1;
- s->needed_bytes = 2;
- goto warn;
-
- case 0x45:
- dsp_out_data (s, 0xaa);
- goto warn;
-
- case 0x47: /* Continue Auto-Initialize DMA 16bit */
- break;
-
- case 0x48:
- s->needed_bytes = 2;
- break;
-
- case 0x74:
- s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
- dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
- break;
-
- case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
- s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
- break;
-
- case 0x76: /* DMA DAC, 2.6-bit ADPCM */
- s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
- break;
-
- case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
- s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
- break;
-
- case 0x7d:
- dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
- dolog ("not implemented\n");
- break;
-
- case 0x7f:
- dolog (
- "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
- );
- dolog ("not implemented\n");
- break;
-
- case 0x80:
- s->needed_bytes = 2;
- break;
-
- case 0x90:
- case 0x91:
- dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
- break;
-
- case 0xd0: /* halt DMA operation. 8bit */
- control (s, 0);
- break;
-
- case 0xd1: /* speaker on */
- speaker (s, 1);
- break;
-
- case 0xd3: /* speaker off */
- speaker (s, 0);
- break;
-
- case 0xd4: /* continue DMA operation. 8bit */
- /* KQ6 (or maybe Sierras audblst.drv in general) resets
- the frequency between halt/continue */
- continue_dma8 (s);
- break;
-
- case 0xd5: /* halt DMA operation. 16bit */
- control (s, 0);
- break;
-
- case 0xd6: /* continue DMA operation. 16bit */
- control (s, 1);
- break;
-
- case 0xd9: /* exit auto-init DMA after this block. 16bit */
- s->dma_auto = 0;
- break;
-
- case 0xda: /* exit auto-init DMA after this block. 8bit */
- s->dma_auto = 0;
- break;
-
- case 0xe0: /* DSP identification */
- s->needed_bytes = 1;
- break;
-
- case 0xe1:
- dsp_out_data (s, s->ver & 0xff);
- dsp_out_data (s, s->ver >> 8);
- break;
-
- case 0xe2:
- s->needed_bytes = 1;
- goto warn;
-
- case 0xe3:
- {
- int i;
- for (i = sizeof (e3) - 1; i >= 0; --i)
- dsp_out_data (s, e3[i]);
- }
- break;
-
- case 0xe4: /* write test reg */
- s->needed_bytes = 1;
- break;
-
- case 0xe7:
- dolog ("Attempt to probe for ESS (0xe7)?\n");
- break;
-
- case 0xe8: /* read test reg */
- dsp_out_data (s, s->test_reg);
- break;
-
- case 0xf2:
- case 0xf3:
- dsp_out_data (s, 0xaa);
- s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
- pic_set_irq (s->irq, 1);
- break;
-
- case 0xf9:
- s->needed_bytes = 1;
- goto warn;
-
- case 0xfa:
- dsp_out_data (s, 0);
- goto warn;
-
- case 0xfc: /* FIXME */
- dsp_out_data (s, 0);
- goto warn;
-
- default:
- dolog ("Unrecognized command %#x\n", cmd);
- break;
- }
- }
-
- if (!s->needed_bytes) {
- ldebug ("\n");
- }
-
- exit:
- if (!s->needed_bytes) {
- s->cmd = -1;
- }
- else {
- s->cmd = cmd;
- }
- return;
-
- warn:
- dolog ("warning: command %#x,%d is not truly understood yet\n",
- cmd, s->needed_bytes);
- goto exit;
-
-}
-
-static uint16_t dsp_get_lohi (SB16State *s)
-{
- uint8_t hi = dsp_get_data (s);
- uint8_t lo = dsp_get_data (s);
- return (hi << 8) | lo;
-}
-
-static uint16_t dsp_get_hilo (SB16State *s)
-{
- uint8_t lo = dsp_get_data (s);
- uint8_t hi = dsp_get_data (s);
- return (hi << 8) | lo;
-}
-
-static void complete (SB16State *s)
-{
- int d0, d1, d2;
- ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
- s->cmd, s->in_index, s->needed_bytes);
-
- if (s->cmd > 0xaf && s->cmd < 0xd0) {
- d2 = dsp_get_data (s);
- d1 = dsp_get_data (s);
- d0 = dsp_get_data (s);
-
- if (s->cmd & 8) {
- dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
- s->cmd, d0, d1, d2);
- }
- else {
- ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
- s->cmd, d0, d1, d2);
- dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
- }
- }
- else {
- switch (s->cmd) {
- case 0x04:
- s->csp_mode = dsp_get_data (s);
- s->csp_reg83r = 0;
- s->csp_reg83w = 0;
- ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
- break;
-
- case 0x05:
- s->csp_param = dsp_get_data (s);
- s->csp_value = dsp_get_data (s);
- ldebug ("CSP command 0x05: param=%#x value=%#x\n",
- s->csp_param,
- s->csp_value);
- break;
-
- case 0x0e:
- d0 = dsp_get_data (s);
- d1 = dsp_get_data (s);
- ldebug ("write CSP register %d <- %#x\n", d1, d0);
- if (d1 == 0x83) {
- ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
- s->csp_reg83[s->csp_reg83r % 4] = d0;
- s->csp_reg83r += 1;
- }
- else {
- s->csp_regs[d1] = d0;
- }
- break;
-
- case 0x0f:
- d0 = dsp_get_data (s);
- ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
- d0, s->csp_regs[d0], s->csp_mode);
- if (d0 == 0x83) {
- ldebug ("0x83[%d] -> %#x\n",
- s->csp_reg83w,
- s->csp_reg83[s->csp_reg83w % 4]);
- dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
- s->csp_reg83w += 1;
- }
- else {
- dsp_out_data (s, s->csp_regs[d0]);
- }
- break;
-
- case 0x10:
- d0 = dsp_get_data (s);
- dolog ("cmd 0x10 d0=%#x\n", d0);
- break;
-
- case 0x14:
- dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
- break;
-
- case 0x40:
- s->time_const = dsp_get_data (s);
- ldebug ("set time const %d\n", s->time_const);
- break;
-
- case 0x42: /* FT2 sets output freq with this, go figure */
-#if 0
- dolog ("cmd 0x42 might not do what it think it should\n");
-#endif
- case 0x41:
- s->freq = dsp_get_hilo (s);
- ldebug ("set freq %d\n", s->freq);
- break;
-
- case 0x48:
- s->block_size = dsp_get_lohi (s) + 1;
- ldebug ("set dma block len %d\n", s->block_size);
- break;
-
- case 0x74:
- case 0x75:
- case 0x76:
- case 0x77:
- /* ADPCM stuff, ignore */
- break;
-
- case 0x80:
- {
- int freq, samples, bytes;
- int64_t ticks;
-
- freq = s->freq > 0 ? s->freq : 11025;
- samples = dsp_get_lohi (s) + 1;
- bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
- ticks = (bytes * ticks_per_sec) / freq;
- if (ticks < ticks_per_sec / 1024) {
- pic_set_irq (s->irq, 1);
- }
- else {
- if (s->aux_ts) {
- qemu_mod_timer (
- s->aux_ts,
- qemu_get_clock (vm_clock) + ticks
- );
- }
- }
- ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
- }
- break;
-
- case 0xe0:
- d0 = dsp_get_data (s);
- s->out_data_len = 0;
- ldebug ("E0 data = %#x\n", d0);
- dsp_out_data (s, ~d0);
- break;
-
- case 0xe2:
- d0 = dsp_get_data (s);
- ldebug ("E2 = %#x\n", d0);
- break;
-
- case 0xe4:
- s->test_reg = dsp_get_data (s);
- break;
-
- case 0xf9:
- d0 = dsp_get_data (s);
- ldebug ("command 0xf9 with %#x\n", d0);
- switch (d0) {
- case 0x0e:
- dsp_out_data (s, 0xff);
- break;
-
- case 0x0f:
- dsp_out_data (s, 0x07);
- break;
-
- case 0x37:
- dsp_out_data (s, 0x38);
- break;
-
- default:
- dsp_out_data (s, 0x00);
- break;
- }
- break;
-
- default:
- dolog ("complete: unrecognized command %#x\n", s->cmd);
- return;
- }
- }
-
- ldebug ("\n");
- s->cmd = -1;
- return;
-}
-
-static void legacy_reset (SB16State *s)
-{
- audsettings_t as;
-
- s->freq = 11025;
- s->fmt_signed = 0;
- s->fmt_bits = 8;
- s->fmt_stereo = 0;
-
- as.freq = s->freq;
- as.nchannels = 1;
- as.fmt = AUD_FMT_U8;
- as.endianness = 0;
-
- s->voice = AUD_open_out (
- &s->card,
- s->voice,
- "sb16",
- s,
- SB_audio_callback,
- &as
- );
-
- /* Not sure about that... */
- /* AUD_set_active_out (s->voice, 1); */
-}
-
-static void reset (SB16State *s)
-{
- pic_set_irq (s->irq, 0);
- if (s->dma_auto) {
- pic_set_irq (s->irq, 1);
- pic_set_irq (s->irq, 0);
- }
-
- s->mixer_regs[0x82] = 0;
- s->dma_auto = 0;
- s->in_index = 0;
- s->out_data_len = 0;
- s->left_till_irq = 0;
- s->needed_bytes = 0;
- s->block_size = -1;
- s->nzero = 0;
- s->highspeed = 0;
- s->v2x6 = 0;
- s->cmd = -1;
-
- dsp_out_data(s, 0xaa);
- speaker (s, 0);
- control (s, 0);
- legacy_reset (s);
-}
-
-static IO_WRITE_PROTO (dsp_write)
-{
- SB16State *s = opaque;
- int iport;
-
- iport = nport - s->port;
-
- ldebug ("write %#x <- %#x\n", nport, val);
- switch (iport) {
- case 0x06:
- switch (val) {
- case 0x00:
- if (s->v2x6 == 1) {
- if (0 && s->highspeed) {
- s->highspeed = 0;
- pic_set_irq (s->irq, 0);
- control (s, 0);
- }
- else {
- reset (s);
- }
- }
- s->v2x6 = 0;
- break;
-
- case 0x01:
- case 0x03: /* FreeBSD kludge */
- s->v2x6 = 1;
- break;
-
- case 0xc6:
- s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
- break;
-
- case 0xb8: /* Panic */
- reset (s);
- break;
-
- case 0x39:
- dsp_out_data (s, 0x38);
- reset (s);
- s->v2x6 = 0x39;
- break;
-
- default:
- s->v2x6 = val;
- break;
- }
- break;
-
- case 0x0c: /* write data or command | write status */
-/* if (s->highspeed) */
-/* break; */
-
- if (0 == s->needed_bytes) {
- command (s, val);
-#if 0
- if (0 == s->needed_bytes) {
- log_dsp (s);
- }
-#endif
- }
- else {
- if (s->in_index == sizeof (s->in2_data)) {
- dolog ("in data overrun\n");
- }
- else {
- s->in2_data[s->in_index++] = val;
- if (s->in_index == s->needed_bytes) {
- s->needed_bytes = 0;
- complete (s);
-#if 0
- log_dsp (s);
-#endif
- }
- }
- }
- break;
-
- default:
- ldebug ("(nport=%#x, val=%#x)\n", nport, val);
- break;
- }
-}
-
-static IO_READ_PROTO (dsp_read)
-{
- SB16State *s = opaque;
- int iport, retval, ack = 0;
-
- iport = nport - s->port;
-
- switch (iport) {
- case 0x06: /* reset */
- retval = 0xff;
- break;
-
- case 0x0a: /* read data */
- if (s->out_data_len) {
- retval = s->out_data[--s->out_data_len];
- s->last_read_byte = retval;
- }
- else {
- if (s->cmd != -1) {
- dolog ("empty output buffer for command %#x\n",
- s->cmd);
- }
- retval = s->last_read_byte;
- /* goto error; */
- }
- break;
-
- case 0x0c: /* 0 can write */
- retval = s->can_write ? 0 : 0x80;
- break;
-
- case 0x0d: /* timer interrupt clear */
- /* dolog ("timer interrupt clear\n"); */
- retval = 0;
- break;
-
- case 0x0e: /* data available status | irq 8 ack */
- retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
- if (s->mixer_regs[0x82] & 1) {
- ack = 1;
- s->mixer_regs[0x82] &= 1;
- pic_set_irq (s->irq, 0);
- }
- break;
-
- case 0x0f: /* irq 16 ack */
- retval = 0xff;
- if (s->mixer_regs[0x82] & 2) {
- ack = 1;
- s->mixer_regs[0x82] &= 2;
- pic_set_irq (s->irq, 0);
- }
- break;
-
- default:
- goto error;
- }
-
- if (!ack) {
- ldebug ("read %#x -> %#x\n", nport, retval);
- }
-
- return retval;
-
- error:
- dolog ("warning: dsp_read %#x error\n", nport);
- return 0xff;
-}
-
-static void reset_mixer (SB16State *s)
-{
- int i;
-
- memset (s->mixer_regs, 0xff, 0x7f);
- memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
-
- s->mixer_regs[0x02] = 4; /* master volume 3bits */
- s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
- s->mixer_regs[0x08] = 0; /* CD volume 3bits */
- s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
-
- /* d5=input filt, d3=lowpass filt, d1,d2=input source */
- s->mixer_regs[0x0c] = 0;
-
- /* d5=output filt, d1=stereo switch */
- s->mixer_regs[0x0e] = 0;
-
- /* voice volume L d5,d7, R d1,d3 */
- s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
- /* master ... */
- s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
- /* MIDI ... */
- s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
-
- for (i = 0x30; i < 0x48; i++) {
- s->mixer_regs[i] = 0x20;
- }
-}
-
-static IO_WRITE_PROTO(mixer_write_indexb)
-{
- SB16State *s = opaque;
- (void) nport;
- s->mixer_nreg = val;
-}
-
-static IO_WRITE_PROTO(mixer_write_datab)
-{
- SB16State *s = opaque;
-
- (void) nport;
- ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
-
- switch (s->mixer_nreg) {
- case 0x00:
- reset_mixer (s);
- break;
-
- case 0x80:
- {
- int irq = irq_of_magic (val);
- ldebug ("setting irq to %d (val=%#x)\n", irq, val);
- if (irq > 0) {
- s->irq = irq;
- }
- }
- break;
-
- case 0x81:
- {
- int dma, hdma;
-
- dma = lsbindex (val & 0xf);
- hdma = lsbindex (val & 0xf0);
- if (dma != s->dma || hdma != s->hdma) {
- dolog (
- "attempt to change DMA "
- "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
- dma, s->dma, hdma, s->hdma, val);
- }
-#if 0
- s->dma = dma;
- s->hdma = hdma;
-#endif
- }
- break;
-
- case 0x82:
- dolog ("attempt to write into IRQ status register (val=%#x)\n",
- val);
- return;
-
- default:
- if (s->mixer_nreg >= 0x80) {
- ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
- }
- break;
- }
-
- s->mixer_regs[s->mixer_nreg] = val;
-}
-
-static IO_WRITE_PROTO(mixer_write_indexw)
-{
- mixer_write_indexb (opaque, nport, val & 0xff);
- mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
-}
-
-static IO_READ_PROTO(mixer_read)
-{
- SB16State *s = opaque;
-
- (void) nport;
-#ifndef DEBUG_SB16_MOST
- if (s->mixer_nreg != 0x82) {
- ldebug ("mixer_read[%#x] -> %#x\n",
- s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
- }
-#else
- ldebug ("mixer_read[%#x] -> %#x\n",
- s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
-#endif
- return s->mixer_regs[s->mixer_nreg];
-}
-
-static int write_audio (SB16State *s, int nchan, int dma_pos,
- int dma_len, int len)
-{
- int temp, net;
- uint8_t tmpbuf[4096];
-
- temp = len;
- net = 0;
-
- while (temp) {
- int left = dma_len - dma_pos;
- int copied;
- size_t to_copy;
-
- to_copy = audio_MIN (temp, left);
- if (to_copy > sizeof (tmpbuf)) {
- to_copy = sizeof (tmpbuf);
- }
-
- copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
- copied = AUD_write (s->voice, tmpbuf, copied);
-
- temp -= copied;
- dma_pos = (dma_pos + copied) % dma_len;
- net += copied;
-
- if (!copied) {
- break;
- }
- }
-
- return net;
-}
-
-static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
-{
- SB16State *s = opaque;
- int till, copy, written, free;
-
- if (s->left_till_irq < 0) {
- s->left_till_irq = s->block_size;
- }
-
- if (s->voice) {
- free = s->audio_free & ~s->align;
- if ((free <= 0) || !dma_len) {
- return dma_pos;
- }
- }
- else {
- free = dma_len;
- }
-
- copy = free;
- till = s->left_till_irq;
-
-#ifdef DEBUG_SB16_MOST
- dolog ("pos:%06d %d till:%d len:%d\n",
- dma_pos, free, till, dma_len);
-#endif
-
- if (till <= copy) {
- if (0 == s->dma_auto) {
- copy = till;
- }
- }
-
- written = write_audio (s, nchan, dma_pos, dma_len, copy);
- dma_pos = (dma_pos + written) % dma_len;
- s->left_till_irq -= written;
-
- if (s->left_till_irq <= 0) {
- s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
- pic_set_irq (s->irq, 1);
- if (0 == s->dma_auto) {
- control (s, 0);
- speaker (s, 0);
- }
- }
-
-#ifdef DEBUG_SB16_MOST
- ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
- dma_pos, free, dma_len, s->left_till_irq, copy, written,
- s->block_size);
-#endif
-
- while (s->left_till_irq <= 0) {
- s->left_till_irq = s->block_size + s->left_till_irq;
- }
-
- return dma_pos;
-}
-
-static void SB_audio_callback (void *opaque, int free)
-{
- SB16State *s = opaque;
- s->audio_free = free;
-}
-
-static void SB_save (QEMUFile *f, void *opaque)
-{
- SB16State *s = opaque;
-
- qemu_put_be32s (f, &s->irq);
- qemu_put_be32s (f, &s->dma);
- qemu_put_be32s (f, &s->hdma);
- qemu_put_be32s (f, &s->port);
- qemu_put_be32s (f, &s->ver);
- qemu_put_be32s (f, &s->in_index);
- qemu_put_be32s (f, &s->out_data_len);
- qemu_put_be32s (f, &s->fmt_stereo);
- qemu_put_be32s (f, &s->fmt_signed);
- qemu_put_be32s (f, &s->fmt_bits);
- qemu_put_be32s (f, &s->fmt);
- qemu_put_be32s (f, &s->dma_auto);
- qemu_put_be32s (f, &s->block_size);
- qemu_put_be32s (f, &s->fifo);
- qemu_put_be32s (f, &s->freq);
- qemu_put_be32s (f, &s->time_const);
- qemu_put_be32s (f, &s->speaker);
- qemu_put_be32s (f, &s->needed_bytes);
- qemu_put_be32s (f, &s->cmd);
- qemu_put_be32s (f, &s->use_hdma);
- qemu_put_be32s (f, &s->highspeed);
- qemu_put_be32s (f, &s->can_write);
- qemu_put_be32s (f, &s->v2x6);
-
- qemu_put_8s (f, &s->csp_param);
- qemu_put_8s (f, &s->csp_value);
- qemu_put_8s (f, &s->csp_mode);
- qemu_put_8s (f, &s->csp_param);
- qemu_put_buffer (f, s->csp_regs, 256);
- qemu_put_8s (f, &s->csp_index);
- qemu_put_buffer (f, s->csp_reg83, 4);
- qemu_put_be32s (f, &s->csp_reg83r);
- qemu_put_be32s (f, &s->csp_reg83w);
-
- qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
- qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
- qemu_put_8s (f, &s->test_reg);
- qemu_put_8s (f, &s->last_read_byte);
-
- qemu_put_be32s (f, &s->nzero);
- qemu_put_be32s (f, &s->left_till_irq);
- qemu_put_be32s (f, &s->dma_running);
- qemu_put_be32s (f, &s->bytes_per_second);
- qemu_put_be32s (f, &s->align);
-
- qemu_put_be32s (f, &s->mixer_nreg);
- qemu_put_buffer (f, s->mixer_regs, 256);
-}
-
-static int SB_load (QEMUFile *f, void *opaque, int version_id)
-{
- SB16State *s = opaque;
-
- if (version_id != 1) {
- return -EINVAL;
- }
-
- qemu_get_be32s (f, &s->irq);
- qemu_get_be32s (f, &s->dma);
- qemu_get_be32s (f, &s->hdma);
- qemu_get_be32s (f, &s->port);
- qemu_get_be32s (f, &s->ver);
- qemu_get_be32s (f, &s->in_index);
- qemu_get_be32s (f, &s->out_data_len);
- qemu_get_be32s (f, &s->fmt_stereo);
- qemu_get_be32s (f, &s->fmt_signed);
- qemu_get_be32s (f, &s->fmt_bits);
- qemu_get_be32s (f, &s->fmt);
- qemu_get_be32s (f, &s->dma_auto);
- qemu_get_be32s (f, &s->block_size);
- qemu_get_be32s (f, &s->fifo);
- qemu_get_be32s (f, &s->freq);
- qemu_get_be32s (f, &s->time_const);
- qemu_get_be32s (f, &s->speaker);
- qemu_get_be32s (f, &s->needed_bytes);
- qemu_get_be32s (f, &s->cmd);
- qemu_get_be32s (f, &s->use_hdma);
- qemu_get_be32s (f, &s->highspeed);
- qemu_get_be32s (f, &s->can_write);
- qemu_get_be32s (f, &s->v2x6);
-
- qemu_get_8s (f, &s->csp_param);
- qemu_get_8s (f, &s->csp_value);
- qemu_get_8s (f, &s->csp_mode);
- qemu_get_8s (f, &s->csp_param);
- qemu_get_buffer (f, s->csp_regs, 256);
- qemu_get_8s (f, &s->csp_index);
- qemu_get_buffer (f, s->csp_reg83, 4);
- qemu_get_be32s (f, &s->csp_reg83r);
- qemu_get_be32s (f, &s->csp_reg83w);
-
- qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
- qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
- qemu_get_8s (f, &s->test_reg);
- qemu_get_8s (f, &s->last_read_byte);
-
- qemu_get_be32s (f, &s->nzero);
- qemu_get_be32s (f, &s->left_till_irq);
- qemu_get_be32s (f, &s->dma_running);
- qemu_get_be32s (f, &s->bytes_per_second);
- qemu_get_be32s (f, &s->align);
-
- qemu_get_be32s (f, &s->mixer_nreg);
- qemu_get_buffer (f, s->mixer_regs, 256);
-
- if (s->voice) {
- AUD_close_out (&s->card, s->voice);
- s->voice = NULL;
- }
-
- if (s->dma_running) {
- if (s->freq) {
- audsettings_t as;
-
- s->audio_free = 0;
-
- as.freq = s->freq;
- as.nchannels = 1 << s->fmt_stereo;
- as.fmt = s->fmt;
- as.endianness = 0;
-
- s->voice = AUD_open_out (
- &s->card,
- s->voice,
- "sb16",
- s,
- SB_audio_callback,
- &as
- );
- }
-
- control (s, 1);
- speaker (s, s->speaker);
- }
- return 0;
-}
-
-int SB16_init (AudioState *audio)
-{
- SB16State *s;
- int i;
- static const uint8_t dsp_write_ports[] = {0x6, 0xc};
- static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
-
- if (!audio) {
- dolog ("No audio state\n");
- return -1;
- }
-
- s = qemu_mallocz (sizeof (*s));
- if (!s) {
- dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
- sizeof (*s));
- return -1;
- }
-
- s->cmd = -1;
- s->irq = conf.irq;
- s->dma = conf.dma;
- s->hdma = conf.hdma;
- s->port = conf.port;
- s->ver = conf.ver_lo | (conf.ver_hi << 8);
-
- s->mixer_regs[0x80] = magic_of_irq (s->irq);
- s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
- s->mixer_regs[0x82] = 2 << 5;
-
- s->csp_regs[5] = 1;
- s->csp_regs[9] = 0xf8;
-
- reset_mixer (s);
- s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
- if (!s->aux_ts) {
- dolog ("warning: Could not create auxiliary timer\n");
- }
-
- for (i = 0; i < LENOFA (dsp_write_ports); i++) {
- register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
- }
-
- for (i = 0; i < LENOFA (dsp_read_ports); i++) {
- register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
- }
-
- register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
- register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
- register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
- register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
-
- DMA_register_channel (s->hdma, SB_read_DMA, s);
- DMA_register_channel (s->dma, SB_read_DMA, s);
- s->can_write = 1;
-
- register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
- AUD_register_card (audio, "sb16", &s->card);
- return 0;
-}
diff --git a/hw/sd.h b/hw/sd.h
new file mode 100644
index 0000000..f310062
--- /dev/null
+++ b/hw/sd.h
@@ -0,0 +1,83 @@
+/*
+ * include/linux/mmc/sd.h
+ *
+ * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef MMC_SD_H
+#define MMC_SD_H
+
+/* SD commands type argument response */
+ /* class 0 */
+/* This is basically the same command as for MMC with some quirks. */
+#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
+#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
+
+ /* class 10 */
+#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
+
+ /* Application commands */
+#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
+#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
+#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
+#define SD_APP_SEND_SCR 51 /* adtc R1 */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ * [31] Check (0) or switch (1)
+ * [30:24] Reserved (0)
+ * [23:20] Function group 6
+ * [19:16] Function group 5
+ * [15:12] Function group 4
+ * [11:8] Function group 3
+ * [7:4] Function group 2
+ * [3:0] Function group 1
+ */
+
+/*
+ * SD_SEND_IF_COND argument format:
+ *
+ * [31:12] Reserved (0)
+ * [11:8] Host Voltage Supply Flags
+ * [7:0] Check Pattern (0xAA)
+ */
+
+/*
+ * SCR field definitions
+ */
+
+#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */
+
+/*
+ * SD bus widths
+ */
+#define SD_BUS_WIDTH_1 0
+#define SD_BUS_WIDTH_4 2
+
+/*
+ * SD_SWITCH mode
+ */
+#define SD_SWITCH_CHECK 0
+#define SD_SWITCH_SET 1
+
+/*
+ * SD_SWITCH function groups
+ */
+#define SD_SWITCH_GRP_ACCESS 0
+
+/*
+ * SD_SWITCH access modes
+ */
+#define SD_SWITCH_ACCESS_DEF 0
+#define SD_SWITCH_ACCESS_HS 1
+
+#endif
+
diff --git a/hw/serial.c b/hw/serial.c
deleted file mode 100644
index f36beb2..0000000
--- a/hw/serial.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * QEMU 16450 UART emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define DEBUG_SERIAL
-
-#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
-
-#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
-#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
-#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
-#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
-
-#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
-#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
-
-#define UART_IIR_MSI 0x00 /* Modem status interrupt */
-#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
-#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
-#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
-
-/*
- * These are the definitions for the Modem Control Register
- */
-#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
-#define UART_MCR_OUT2 0x08 /* Out2 complement */
-#define UART_MCR_OUT1 0x04 /* Out1 complement */
-#define UART_MCR_RTS 0x02 /* RTS complement */
-#define UART_MCR_DTR 0x01 /* DTR complement */
-
-/*
- * These are the definitions for the Modem Status Register
- */
-#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
-#define UART_MSR_RI 0x40 /* Ring Indicator */
-#define UART_MSR_DSR 0x20 /* Data Set Ready */
-#define UART_MSR_CTS 0x10 /* Clear to Send */
-#define UART_MSR_DDCD 0x08 /* Delta DCD */
-#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
-#define UART_MSR_DDSR 0x02 /* Delta DSR */
-#define UART_MSR_DCTS 0x01 /* Delta CTS */
-#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
-
-#define UART_LSR_TEMT 0x40 /* Transmitter empty */
-#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
-#define UART_LSR_BI 0x10 /* Break interrupt indicator */
-#define UART_LSR_FE 0x08 /* Frame error indicator */
-#define UART_LSR_PE 0x04 /* Parity error indicator */
-#define UART_LSR_OE 0x02 /* Overrun error indicator */
-#define UART_LSR_DR 0x01 /* Receiver data ready */
-
-struct SerialState {
- uint8_t divider;
- uint8_t rbr; /* receive register */
- uint8_t ier;
- uint8_t iir; /* read only */
- uint8_t lcr;
- uint8_t mcr;
- uint8_t lsr; /* read only */
- uint8_t msr; /* read only */
- uint8_t scr;
- /* NOTE: this hidden state is necessary for tx irq generation as
- it can be reset while reading iir */
- int thr_ipending;
- SetIRQFunc *set_irq;
- void *irq_opaque;
- int irq;
- CharDriverState *chr;
- int last_break_enable;
- target_ulong base;
- int it_shift;
-};
-
-static void serial_update_irq(SerialState *s)
-{
- 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)) {
- s->iir = UART_IIR_THRI;
- } else {
- s->iir = UART_IIR_NO_INT;
- }
- if (s->iir != UART_IIR_NO_INT) {
- s->set_irq(s->irq_opaque, s->irq, 1);
- } else {
- s->set_irq(s->irq_opaque, s->irq, 0);
- }
-}
-
-static void serial_update_parameters(SerialState *s)
-{
- int speed, parity, data_bits, stop_bits;
- QEMUSerialSetParams ssp;
-
- if (s->lcr & 0x08) {
- if (s->lcr & 0x10)
- parity = 'E';
- else
- parity = 'O';
- } else {
- parity = 'N';
- }
- if (s->lcr & 0x04)
- stop_bits = 2;
- else
- stop_bits = 1;
- data_bits = (s->lcr & 0x03) + 5;
- if (s->divider == 0)
- return;
- speed = 115200 / s->divider;
- ssp.speed = speed;
- ssp.parity = parity;
- ssp.data_bits = data_bits;
- ssp.stop_bits = stop_bits;
- qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-#if 0
- printf("speed=%d parity=%c data=%d stop=%d\n",
- speed, parity, data_bits, stop_bits);
-#endif
-}
-
-static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- SerialState *s = opaque;
- unsigned char ch;
-
- addr &= 7;
-#ifdef DEBUG_SERIAL
- printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);
-#endif
- switch(addr) {
- default:
- case 0:
- if (s->lcr & UART_LCR_DLAB) {
- s->divider = (s->divider & 0xff00) | val;
- serial_update_parameters(s);
- } else {
- s->thr_ipending = 0;
- s->lsr &= ~UART_LSR_THRE;
- serial_update_irq(s);
- ch = val;
- qemu_chr_write(s->chr, &ch, 1);
- s->thr_ipending = 1;
- s->lsr |= UART_LSR_THRE;
- s->lsr |= UART_LSR_TEMT;
- serial_update_irq(s);
- }
- break;
- case 1:
- if (s->lcr & UART_LCR_DLAB) {
- s->divider = (s->divider & 0x00ff) | (val << 8);
- serial_update_parameters(s);
- } else {
- s->ier = val & 0x0f;
- if (s->lsr & UART_LSR_THRE) {
- s->thr_ipending = 1;
- }
- serial_update_irq(s);
- }
- break;
- case 2:
- break;
- case 3:
- {
- int break_enable;
- s->lcr = val;
- serial_update_parameters(s);
- break_enable = (val >> 6) & 1;
- if (break_enable != s->last_break_enable) {
- s->last_break_enable = break_enable;
- qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
- &break_enable);
- }
- }
- break;
- case 4:
- s->mcr = val & 0x1f;
- break;
- case 5:
- break;
- case 6:
- break;
- case 7:
- s->scr = val;
- break;
- }
-}
-
-static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
-{
- SerialState *s = opaque;
- uint32_t ret;
-
- addr &= 7;
- switch(addr) {
- default:
- case 0:
- if (s->lcr & UART_LCR_DLAB) {
- ret = s->divider & 0xff;
- } else {
- ret = s->rbr;
- s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
- serial_update_irq(s);
- }
- break;
- case 1:
- if (s->lcr & UART_LCR_DLAB) {
- ret = (s->divider >> 8) & 0xff;
- } else {
- ret = s->ier;
- }
- break;
- case 2:
- ret = s->iir;
- /* reset THR pending bit */
- if ((ret & 0x7) == UART_IIR_THRI)
- s->thr_ipending = 0;
- serial_update_irq(s);
- break;
- case 3:
- ret = s->lcr;
- break;
- case 4:
- ret = s->mcr;
- break;
- case 5:
- ret = s->lsr;
- break;
- case 6:
- if (s->mcr & UART_MCR_LOOP) {
- /* in loopback, the modem output pins are connected to the
- inputs */
- ret = (s->mcr & 0x0c) << 4;
- ret |= (s->mcr & 0x02) << 3;
- ret |= (s->mcr & 0x01) << 5;
- } else {
- ret = s->msr;
- }
- break;
- case 7:
- ret = s->scr;
- break;
- }
-#ifdef DEBUG_SERIAL
- printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);
-#endif
- return ret;
-}
-
-static int serial_can_receive(SerialState *s)
-{
- return !(s->lsr & UART_LSR_DR);
-}
-
-static void serial_receive_byte(SerialState *s, int ch)
-{
- s->rbr = ch;
- s->lsr |= UART_LSR_DR;
- serial_update_irq(s);
-}
-
-static void serial_receive_break(SerialState *s)
-{
- s->rbr = 0;
- s->lsr |= UART_LSR_BI | UART_LSR_DR;
- serial_update_irq(s);
-}
-
-static int serial_can_receive1(void *opaque)
-{
- 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]);
-}
-
-static void serial_event(void *opaque, int event)
-{
- SerialState *s = opaque;
- if (event == CHR_EVENT_BREAK)
- serial_receive_break(s);
-}
-
-static void serial_save(QEMUFile *f, void *opaque)
-{
- SerialState *s = opaque;
-
- qemu_put_8s(f,&s->divider);
- qemu_put_8s(f,&s->rbr);
- qemu_put_8s(f,&s->ier);
- qemu_put_8s(f,&s->iir);
- qemu_put_8s(f,&s->lcr);
- qemu_put_8s(f,&s->mcr);
- qemu_put_8s(f,&s->lsr);
- qemu_put_8s(f,&s->msr);
- qemu_put_8s(f,&s->scr);
-}
-
-static int serial_load(QEMUFile *f, void *opaque, int version_id)
-{
- SerialState *s = opaque;
-
- if(version_id != 1)
- return -EINVAL;
-
- qemu_get_8s(f,&s->divider);
- qemu_get_8s(f,&s->rbr);
- qemu_get_8s(f,&s->ier);
- qemu_get_8s(f,&s->iir);
- qemu_get_8s(f,&s->lcr);
- qemu_get_8s(f,&s->mcr);
- qemu_get_8s(f,&s->lsr);
- qemu_get_8s(f,&s->msr);
- qemu_get_8s(f,&s->scr);
-
- return 0;
-}
-
-/* If fd is zero, it means that the serial device uses the console */
-SerialState *serial_init(SetIRQFunc *set_irq, void *opaque,
- int base, int irq, CharDriverState *chr)
-{
- SerialState *s;
-
- s = qemu_mallocz(sizeof(SerialState));
- if (!s)
- return NULL;
- s->set_irq = set_irq;
- s->irq_opaque = opaque;
- s->irq = irq;
- s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
- s->iir = UART_IIR_NO_INT;
- s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
-
- register_savevm("serial", base, 1, serial_save, serial_load, s);
-
- register_ioport_write(base, 8, 1, serial_ioport_write, s);
- register_ioport_read(base, 8, 1, serial_ioport_read, s);
- s->chr = chr;
- qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
- qemu_chr_add_event_handler(chr, serial_event);
- return s;
-}
-
-/* Memory mapped interface */
-static uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr)
-{
- SerialState *s = opaque;
-
- return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;
-}
-
-static void serial_mm_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- SerialState *s = opaque;
-
- serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);
-}
-
-static uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr)
-{
- SerialState *s = opaque;
-
- return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;
-}
-
-static void serial_mm_writew (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- SerialState *s = opaque;
-
- serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);
-}
-
-static uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr)
-{
- SerialState *s = opaque;
-
- return serial_ioport_read(s, (addr - s->base) >> s->it_shift);
-}
-
-static void serial_mm_writel (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- SerialState *s = opaque;
-
- serial_ioport_write(s, (addr - s->base) >> s->it_shift, value);
-}
-
-static CPUReadMemoryFunc *serial_mm_read[] = {
- &serial_mm_readb,
- &serial_mm_readw,
- &serial_mm_readl,
-};
-
-static CPUWriteMemoryFunc *serial_mm_write[] = {
- &serial_mm_writeb,
- &serial_mm_writew,
- &serial_mm_writel,
-};
-
-SerialState *serial_mm_init (SetIRQFunc *set_irq, void *opaque,
- target_ulong base, int it_shift,
- int irq, CharDriverState *chr)
-{
- SerialState *s;
- int s_io_memory;
-
- s = qemu_mallocz(sizeof(SerialState));
- if (!s)
- return NULL;
- s->set_irq = set_irq;
- s->irq_opaque = opaque;
- s->irq = irq;
- s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
- s->iir = UART_IIR_NO_INT;
- s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
- s->base = base;
- s->it_shift = it_shift;
-
- register_savevm("serial", base, 1, serial_save, serial_load, s);
-
- s_io_memory = cpu_register_io_memory(0, serial_mm_read,
- serial_mm_write, s);
- cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
- s->chr = chr;
- qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
- qemu_chr_add_event_handler(chr, serial_event);
- return s;
-}
diff --git a/hw/sh7750.c b/hw/sh7750.c
deleted file mode 100644
index 21f9bc0..0000000
--- a/hw/sh7750.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * SH7750 device
- *
- * Copyright (c) 2005 Samuel Tardieu
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include <stdio.h>
-#include <assert.h>
-#include "vl.h"
-#include "sh7750_regs.h"
-#include "sh7750_regnames.h"
-
-typedef struct {
- uint8_t data[16];
- uint8_t length; /* Number of characters in the FIFO */
- uint8_t write_idx; /* Index of first character to write */
- uint8_t read_idx; /* Index of first character to read */
-} fifo;
-
-#define NB_DEVICES 4
-
-typedef struct SH7750State {
- /* CPU */
- CPUSH4State *cpu;
- /* Peripheral frequency in Hz */
- uint32_t periph_freq;
- /* SDRAM controller */
- uint16_t rfcr;
- /* First serial port */
- CharDriverState *serial1;
- uint8_t scscr1;
- uint8_t scsmr1;
- uint8_t scbrr1;
- uint8_t scssr1;
- uint8_t scssr1_read;
- uint8_t sctsr1;
- uint8_t sctsr1_loaded;
- uint8_t sctdr1;
- uint8_t scrdr1;
- /* Second serial port */
- CharDriverState *serial2;
- uint16_t sclsr2;
- uint16_t scscr2;
- uint16_t scfcr2;
- uint16_t scfsr2;
- uint16_t scsmr2;
- uint8_t scbrr2;
- fifo serial2_receive_fifo;
- fifo serial2_transmit_fifo;
- /* Timers */
- uint8_t tstr;
- /* Timer 0 */
- QEMUTimer *timer0;
- uint16_t tcr0;
- uint32_t tcor0;
- uint32_t tcnt0;
- /* IO ports */
- uint16_t gpioic;
- uint32_t pctra;
- uint32_t pctrb;
- uint16_t portdira; /* Cached */
- uint16_t portpullupa; /* Cached */
- uint16_t portdirb; /* Cached */
- uint16_t portpullupb; /* Cached */
- uint16_t pdtra;
- uint16_t pdtrb;
- uint16_t periph_pdtra; /* Imposed by the peripherals */
- uint16_t periph_portdira; /* Direction seen from the peripherals */
- uint16_t periph_pdtrb; /* Imposed by the peripherals */
- uint16_t periph_portdirb; /* Direction seen from the peripherals */
- sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */
- /* Cache */
- uint32_t ccr;
-} SH7750State;
-
-/**********************************************************************
- Timers
-**********************************************************************/
-
-/* XXXXX At this time, timer0 works in underflow only mode, that is
- the value of tcnt0 is read at alarm computation time and cannot
- be read back by the guest OS */
-
-static void start_timer0(SH7750State * s)
-{
- uint64_t now, next, prescaler;
-
- if ((s->tcr0 & 6) == 6) {
- fprintf(stderr, "rtc clock for timer 0 not supported\n");
- assert(0);
- }
-
- if ((s->tcr0 & 7) == 5) {
- fprintf(stderr, "timer 0 configuration not supported\n");
- assert(0);
- }
-
- if ((s->tcr0 & 4) == 4)
- prescaler = 1024;
- else
- prescaler = 4 << (s->tcr0 & 3);
-
- now = qemu_get_clock(vm_clock);
- /* XXXXX */
- next =
- now + muldiv64(prescaler * s->tcnt0, ticks_per_sec,
- s->periph_freq);
- if (next == now)
- next = now + 1;
- fprintf(stderr, "now=%016" PRIx64 ", next=%016" PRIx64 "\n", now, next);
- fprintf(stderr, "timer will underflow in %f seconds\n",
- (float) (next - now) / (float) ticks_per_sec);
-
- qemu_mod_timer(s->timer0, next);
-}
-
-static void timer_start_changed(SH7750State * s)
-{
- if (s->tstr & SH7750_TSTR_STR0) {
- start_timer0(s);
- } else {
- fprintf(stderr, "timer 0 is stopped\n");
- qemu_del_timer(s->timer0);
- }
-}
-
-static void timer0_cb(void *opaque)
-{
- SH7750State *s = opaque;
-
- s->tcnt0 = (uint32_t) 0; /* XXXXX */
- if (--s->tcnt0 == (uint32_t) - 1) {
- fprintf(stderr, "timer 0 underflow\n");
- s->tcnt0 = s->tcor0;
- s->tcr0 |= SH7750_TCR_UNF;
- if (s->tcr0 & SH7750_TCR_UNIE) {
- fprintf(stderr,
- "interrupt generation for timer 0 not supported\n");
- assert(0);
- }
- }
- start_timer0(s);
-}
-
-static void init_timers(SH7750State * s)
-{
- s->tcor0 = 0xffffffff;
- s->tcnt0 = 0xffffffff;
- s->timer0 = qemu_new_timer(vm_clock, &timer0_cb, s);
-}
-
-/**********************************************************************
- First serial port
-**********************************************************************/
-
-static int serial1_can_receive(void *opaque)
-{
- SH7750State *s = opaque;
-
- return s->scscr1 & SH7750_SCSCR_RE;
-}
-
-static void serial1_receive_char(SH7750State * s, uint8_t c)
-{
- if (s->scssr1 & SH7750_SCSSR1_RDRF) {
- s->scssr1 |= SH7750_SCSSR1_ORER;
- return;
- }
-
- s->scrdr1 = c;
- s->scssr1 |= SH7750_SCSSR1_RDRF;
-}
-
-static void serial1_receive(void *opaque, const uint8_t * buf, int size)
-{
- SH7750State *s = opaque;
- int i;
-
- for (i = 0; i < size; i++) {
- serial1_receive_char(s, buf[i]);
- }
-}
-
-static void serial1_event(void *opaque, int event)
-{
- assert(0);
-}
-
-static void serial1_maybe_send(SH7750State * s)
-{
- uint8_t c;
-
- if (s->scssr1 & SH7750_SCSSR1_TDRE)
- return;
- c = s->sctdr1;
- s->scssr1 |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
- if (s->scscr1 & SH7750_SCSCR_TIE) {
- fprintf(stderr, "interrupts for serial port 1 not implemented\n");
- assert(0);
- }
- /* XXXXX Check for errors in write */
- qemu_chr_write(s->serial1, &c, 1);
-}
-
-static void serial1_change_scssr1(SH7750State * s, uint8_t mem_value)
-{
- uint8_t new_flags;
-
- /* If transmit disable, TDRE and TEND stays up */
- if ((s->scscr1 & SH7750_SCSCR_TE) == 0) {
- mem_value |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
- }
-
- /* Only clear bits which have been read before and do not set any bit
- in the flags */
- new_flags = s->scssr1 & ~s->scssr1_read; /* Preserve unread flags */
- new_flags &= mem_value | ~s->scssr1_read; /* Clear read flags */
-
- s->scssr1 = (new_flags & 0xf8) | (mem_value & 1);
- s->scssr1_read &= mem_value;
-
- /* If TDRE has been cleared, TEND will also be cleared */
- if ((s->scssr1 & SH7750_SCSSR1_TDRE) == 0) {
- s->scssr1 &= ~SH7750_SCSSR1_TEND;
- }
-
- /* Check for transmission to start */
- serial1_maybe_send(s);
-}
-
-static void serial1_update_parameters(SH7750State * s)
-{
- QEMUSerialSetParams ssp;
-
- if (s->scsmr1 & SH7750_SCSMR_CHR_7)
- ssp.data_bits = 7;
- else
- ssp.data_bits = 8;
- if (s->scsmr1 & SH7750_SCSMR_PE) {
- if (s->scsmr1 & SH7750_SCSMR_PM_ODD)
- ssp.parity = 'O';
- else
- ssp.parity = 'E';
- } else
- ssp.parity = 'N';
- if (s->scsmr1 & SH7750_SCSMR_STOP_2)
- ssp.stop_bits = 2;
- else
- ssp.stop_bits = 1;
- fprintf(stderr, "SCSMR1=%04x SCBRR1=%02x\n", s->scsmr1, s->scbrr1);
- ssp.speed = s->periph_freq /
- (32 * s->scbrr1 * (1 << (2 * (s->scsmr1 & 3)))) - 1;
- fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
- ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
- qemu_chr_ioctl(s->serial1, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr1_changed(SH7750State * s)
-{
- if (s->scscr1 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
- if (!s->serial1) {
- fprintf(stderr, "serial port 1 not bound to anything\n");
- assert(0);
- }
- serial1_update_parameters(s);
- }
- if ((s->scscr1 & SH7750_SCSCR_RE) == 0) {
- s->scssr1 |= SH7750_SCSSR1_TDRE;
- }
-}
-
-static void init_serial1(SH7750State * s, int serial_nb)
-{
- CharDriverState *chr;
-
- s->scssr1 = 0x84;
- chr = serial_hds[serial_nb];
- if (!chr) {
- fprintf(stderr,
- "no serial port associated to SH7750 first serial port\n");
- return;
- }
-
- s->serial1 = chr;
- qemu_chr_add_read_handler(chr, serial1_can_receive,
- serial1_receive, s);
- qemu_chr_add_event_handler(chr, serial1_event);
-}
-
-/**********************************************************************
- Second serial port
-**********************************************************************/
-
-static int serial2_can_receive(void *opaque)
-{
- SH7750State *s = opaque;
- static uint8_t max_fifo_size[] = { 15, 1, 4, 6, 8, 10, 12, 14 };
-
- return s->serial2_receive_fifo.length <
- max_fifo_size[(s->scfcr2 >> 9) & 7];
-}
-
-static void serial2_adjust_receive_flags(SH7750State * s)
-{
- static uint8_t max_fifo_size[] = { 1, 4, 8, 14 };
-
- /* XXXXX Add interrupt generation */
- if (s->serial2_receive_fifo.length >=
- max_fifo_size[(s->scfcr2 >> 7) & 3]) {
- s->scfsr2 |= SH7750_SCFSR2_RDF;
- s->scfsr2 &= ~SH7750_SCFSR2_DR;
- } else {
- s->scfsr2 &= ~SH7750_SCFSR2_RDF;
- if (s->serial2_receive_fifo.length > 0)
- s->scfsr2 |= SH7750_SCFSR2_DR;
- else
- s->scfsr2 &= ~SH7750_SCFSR2_DR;
- }
-}
-
-static void serial2_append_char(SH7750State * s, uint8_t c)
-{
- if (s->serial2_receive_fifo.length == 16) {
- /* Overflow */
- s->sclsr2 |= SH7750_SCLSR2_ORER;
- return;
- }
-
- s->serial2_receive_fifo.data[s->serial2_receive_fifo.write_idx++] = c;
- s->serial2_receive_fifo.length++;
- serial2_adjust_receive_flags(s);
-}
-
-static void serial2_receive(void *opaque, const uint8_t * buf, int size)
-{
- SH7750State *s = opaque;
- int i;
-
- for (i = 0; i < size; i++)
- serial2_append_char(s, buf[i]);
-}
-
-static void serial2_event(void *opaque, int event)
-{
- /* XXXXX */
- assert(0);
-}
-
-static void serial2_update_parameters(SH7750State * s)
-{
- QEMUSerialSetParams ssp;
-
- if (s->scsmr2 & SH7750_SCSMR_CHR_7)
- ssp.data_bits = 7;
- else
- ssp.data_bits = 8;
- if (s->scsmr2 & SH7750_SCSMR_PE) {
- if (s->scsmr2 & SH7750_SCSMR_PM_ODD)
- ssp.parity = 'O';
- else
- ssp.parity = 'E';
- } else
- ssp.parity = 'N';
- if (s->scsmr2 & SH7750_SCSMR_STOP_2)
- ssp.stop_bits = 2;
- else
- ssp.stop_bits = 1;
- fprintf(stderr, "SCSMR2=%04x SCBRR2=%02x\n", s->scsmr2, s->scbrr2);
- ssp.speed = s->periph_freq /
- (32 * s->scbrr2 * (1 << (2 * (s->scsmr2 & 3)))) - 1;
- fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
- ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
- qemu_chr_ioctl(s->serial2, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
-static void scscr2_changed(SH7750State * s)
-{
- if (s->scscr2 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
- if (!s->serial2) {
- fprintf(stderr, "serial port 2 not bound to anything\n");
- assert(0);
- }
- serial2_update_parameters(s);
- }
-}
-
-static void init_serial2(SH7750State * s, int serial_nb)
-{
- CharDriverState *chr;
-
- s->scfsr2 = 0x0060;
-
- chr = serial_hds[serial_nb];
- if (!chr) {
- fprintf(stderr,
- "no serial port associated to SH7750 second serial port\n");
- return;
- }
-
- s->serial2 = chr;
- qemu_chr_add_read_handler(chr, serial2_can_receive,
- serial2_receive, s);
- qemu_chr_add_event_handler(chr, serial2_event);
-}
-
-static void init_serial_ports(SH7750State * s)
-{
- init_serial1(s, 0);
- init_serial2(s, 1);
-}
-
-/**********************************************************************
- I/O ports
-**********************************************************************/
-
-int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
-{
- int i;
-
- for (i = 0; i < NB_DEVICES; i++) {
- if (s->devices[i] == NULL) {
- s->devices[i] = device;
- return 0;
- }
- }
- return -1;
-}
-
-static uint16_t portdir(uint32_t v)
-{
-#define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
- return
- EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
- EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
- EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
- EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
- EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
- EVENPORTMASK(0);
-}
-
-static uint16_t portpullup(uint32_t v)
-{
-#define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
- return
- ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
- ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
- ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
- ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
- ODDPORTMASK(1) | ODDPORTMASK(0);
-}
-
-static uint16_t porta_lines(SH7750State * s)
-{
- return (s->portdira & s->pdtra) | /* CPU */
- (s->periph_portdira & s->periph_pdtra) | /* Peripherals */
- (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
-}
-
-static uint16_t portb_lines(SH7750State * s)
-{
- return (s->portdirb & s->pdtrb) | /* CPU */
- (s->periph_portdirb & s->periph_pdtrb) | /* Peripherals */
- (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
-}
-
-static void gen_port_interrupts(SH7750State * s)
-{
- /* XXXXX interrupts not generated */
-}
-
-static void porta_changed(SH7750State * s, uint16_t prev)
-{
- uint16_t currenta, changes;
- int i, r = 0;
-
-#if 0
- fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
- prev, porta_lines(s));
- fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
-#endif
- currenta = porta_lines(s);
- if (currenta == prev)
- return;
- changes = currenta ^ prev;
-
- for (i = 0; i < NB_DEVICES; i++) {
- if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
- r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
- &s->periph_pdtra,
- &s->periph_portdira,
- &s->periph_pdtrb,
- &s->periph_portdirb);
- }
- }
-
- if (r)
- gen_port_interrupts(s);
-}
-
-static void portb_changed(SH7750State * s, uint16_t prev)
-{
- uint16_t currentb, changes;
- int i, r = 0;
-
- currentb = portb_lines(s);
- if (currentb == prev)
- return;
- changes = currentb ^ prev;
-
- for (i = 0; i < NB_DEVICES; i++) {
- if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
- r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
- &s->periph_pdtra,
- &s->periph_portdira,
- &s->periph_pdtrb,
- &s->periph_portdirb);
- }
- }
-
- if (r)
- gen_port_interrupts(s);
-}
-
-/**********************************************************************
- Memory
-**********************************************************************/
-
-static void error_access(const char *kind, target_phys_addr_t addr)
-{
- fprintf(stderr, "%s to %s (0x%08x) not supported\n",
- kind, regname(addr), addr);
-}
-
-static void ignore_access(const char *kind, target_phys_addr_t addr)
-{
- fprintf(stderr, "%s to %s (0x%08x) ignored\n",
- kind, regname(addr), addr);
-}
-
-static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- SH7750State *s = opaque;
- uint8_t r;
-
- switch (addr) {
- case SH7750_SCSSR1_A7:
- r = s->scssr1;
- s->scssr1_read |= r;
- return s->scssr1;
- case SH7750_SCRDR1_A7:
- s->scssr1 &= ~SH7750_SCSSR1_RDRF;
- return s->scrdr1;
- default:
- error_access("byte read", addr);
- assert(0);
- }
-}
-
-static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
-{
- SH7750State *s = opaque;
- uint16_t r;
-
- switch (addr) {
- case SH7750_RFCR_A7:
- fprintf(stderr,
- "Read access to refresh count register, incrementing\n");
- return s->rfcr++;
- case SH7750_TCR0_A7:
- return s->tcr0;
- case SH7750_SCLSR2_A7:
- /* Read and clear overflow bit */
- r = s->sclsr2;
- s->sclsr2 = 0;
- return r;
- case SH7750_SCSFR2_A7:
- return s->scfsr2;
- case SH7750_PDTRA_A7:
- return porta_lines(s);
- case SH7750_PDTRB_A7:
- return portb_lines(s);
- default:
- error_access("word read", addr);
- assert(0);
- }
-}
-
-static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- SH7750State *s = opaque;
-
- switch (addr) {
- case SH7750_MMUCR_A7:
- return s->cpu->mmucr;
- case SH7750_PTEH_A7:
- return s->cpu->pteh;
- case SH7750_PTEL_A7:
- return s->cpu->ptel;
- case SH7750_TTB_A7:
- return s->cpu->ttb;
- case SH7750_TEA_A7:
- return s->cpu->tea;
- case SH7750_TRA_A7:
- return s->cpu->tra;
- case SH7750_EXPEVT_A7:
- return s->cpu->expevt;
- case SH7750_INTEVT_A7:
- return s->cpu->intevt;
- case SH7750_CCR_A7:
- return s->ccr;
- case 0x1f000030: /* Processor version PVR */
- return 0x00050000; /* SH7750R */
- case 0x1f000040: /* Processor version CVR */
- return 0x00110000; /* Minimum caches */
- case 0x1f000044: /* Processor version PRR */
- return 0x00000100; /* SH7750R */
- default:
- error_access("long read", addr);
- assert(0);
- }
-}
-
-static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
- uint32_t mem_value)
-{
- SH7750State *s = opaque;
-
- switch (addr) {
- /* PRECHARGE ? XXXXX */
- case SH7750_PRECHARGE0_A7:
- case SH7750_PRECHARGE1_A7:
- ignore_access("byte write", addr);
- return;
- case SH7750_SCBRR2_A7:
- s->scbrr2 = mem_value;
- return;
- case SH7750_TSTR_A7:
- s->tstr = mem_value;
- timer_start_changed(s);
- return;
- case SH7750_SCSCR1_A7:
- s->scscr1 = mem_value;
- scscr1_changed(s);
- return;
- case SH7750_SCSMR1_A7:
- s->scsmr1 = mem_value;
- return;
- case SH7750_SCBRR1_A7:
- s->scbrr1 = mem_value;
- return;
- case SH7750_SCTDR1_A7:
- s->scssr1 &= ~SH7750_SCSSR1_TEND;
- s->sctdr1 = mem_value;
- return;
- case SH7750_SCSSR1_A7:
- serial1_change_scssr1(s, mem_value);
- return;
- default:
- error_access("byte write", addr);
- assert(0);
- }
-}
-
-static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
- uint32_t mem_value)
-{
- SH7750State *s = opaque;
- uint16_t temp;
-
- switch (addr) {
- /* SDRAM controller */
- case SH7750_SCBRR1_A7:
- case SH7750_SCBRR2_A7:
- case SH7750_BCR2_A7:
- case SH7750_BCR3_A7:
- case SH7750_RTCOR_A7:
- case SH7750_RTCNT_A7:
- case SH7750_RTCSR_A7:
- ignore_access("word write", addr);
- return;
- /* IO ports */
- case SH7750_PDTRA_A7:
- temp = porta_lines(s);
- s->pdtra = mem_value;
- porta_changed(s, temp);
- return;
- case SH7750_PDTRB_A7:
- temp = portb_lines(s);
- s->pdtrb = mem_value;
- portb_changed(s, temp);
- return;
- case SH7750_RFCR_A7:
- fprintf(stderr, "Write access to refresh count register\n");
- s->rfcr = mem_value;
- return;
- case SH7750_SCLSR2_A7:
- s->sclsr2 = mem_value;
- return;
- case SH7750_SCSCR2_A7:
- s->scscr2 = mem_value;
- scscr2_changed(s);
- return;
- case SH7750_SCFCR2_A7:
- s->scfcr2 = mem_value;
- return;
- case SH7750_SCSMR2_A7:
- s->scsmr2 = mem_value;
- return;
- case SH7750_TCR0_A7:
- s->tcr0 = mem_value;
- return;
- case SH7750_GPIOIC_A7:
- s->gpioic = mem_value;
- if (mem_value != 0) {
- fprintf(stderr, "I/O interrupts not implemented\n");
- assert(0);
- }
- return;
- default:
- error_access("word write", addr);
- assert(0);
- }
-}
-
-static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
- uint32_t mem_value)
-{
- SH7750State *s = opaque;
- uint16_t temp;
-
- switch (addr) {
- /* SDRAM controller */
- case SH7750_BCR1_A7:
- case SH7750_BCR4_A7:
- case SH7750_WCR1_A7:
- case SH7750_WCR2_A7:
- case SH7750_WCR3_A7:
- case SH7750_MCR_A7:
- ignore_access("long write", addr);
- return;
- /* IO ports */
- case SH7750_PCTRA_A7:
- temp = porta_lines(s);
- s->pctra = mem_value;
- s->portdira = portdir(mem_value);
- s->portpullupa = portpullup(mem_value);
- porta_changed(s, temp);
- return;
- case SH7750_PCTRB_A7:
- temp = portb_lines(s);
- s->pctrb = mem_value;
- s->portdirb = portdir(mem_value);
- s->portpullupb = portpullup(mem_value);
- portb_changed(s, temp);
- return;
- case SH7750_TCNT0_A7:
- s->tcnt0 = mem_value & 0xf;
- return;
- case SH7750_MMUCR_A7:
- s->cpu->mmucr = mem_value;
- return;
- case SH7750_PTEH_A7:
- s->cpu->pteh = mem_value;
- return;
- case SH7750_PTEL_A7:
- s->cpu->ptel = mem_value;
- return;
- case SH7750_TTB_A7:
- s->cpu->ttb = mem_value;
- return;
- case SH7750_TEA_A7:
- s->cpu->tea = mem_value;
- return;
- case SH7750_TRA_A7:
- s->cpu->tra = mem_value & 0x000007ff;
- return;
- case SH7750_EXPEVT_A7:
- s->cpu->expevt = mem_value & 0x000007ff;
- return;
- case SH7750_INTEVT_A7:
- s->cpu->intevt = mem_value & 0x000007ff;
- return;
- case SH7750_CCR_A7:
- s->ccr = mem_value;
- return;
- default:
- error_access("long write", addr);
- assert(0);
- }
-}
-
-static CPUReadMemoryFunc *sh7750_mem_read[] = {
- sh7750_mem_readb,
- sh7750_mem_readw,
- sh7750_mem_readl
-};
-
-static CPUWriteMemoryFunc *sh7750_mem_write[] = {
- sh7750_mem_writeb,
- sh7750_mem_writew,
- sh7750_mem_writel
-};
-
-SH7750State *sh7750_init(CPUSH4State * cpu)
-{
- SH7750State *s;
- int sh7750_io_memory;
-
- s = qemu_mallocz(sizeof(SH7750State));
- s->cpu = cpu;
- s->periph_freq = 60000000; /* 60MHz */
- sh7750_io_memory = cpu_register_io_memory(0,
- sh7750_mem_read,
- sh7750_mem_write, s);
- cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
- init_timers(s);
- init_serial_ports(s);
- return s;
-}
diff --git a/hw/sh7750_regnames.c b/hw/sh7750_regnames.c
deleted file mode 100644
index 5fcb0d6..0000000
--- a/hw/sh7750_regnames.c
+++ /dev/null
@@ -1,128 +0,0 @@
-#include "vl.h"
-#include "sh7750_regs.h"
-
-#define REGNAME(r) {r, #r},
-
-typedef struct {
- uint32_t regaddr;
- const char *regname;
-} regname_t;
-
-static regname_t regnames[] = {
- REGNAME(SH7750_PTEH_A7)
- REGNAME(SH7750_PTEL_A7)
- REGNAME(SH7750_PTEA_A7)
- REGNAME(SH7750_TTB_A7)
- REGNAME(SH7750_TEA_A7)
- REGNAME(SH7750_MMUCR_A7)
- REGNAME(SH7750_CCR_A7)
- REGNAME(SH7750_QACR0_A7)
- REGNAME(SH7750_QACR1_A7)
- REGNAME(SH7750_TRA_A7)
- REGNAME(SH7750_EXPEVT_A7)
- REGNAME(SH7750_INTEVT_A7)
- REGNAME(SH7750_STBCR_A7)
- REGNAME(SH7750_STBCR2_A7)
- REGNAME(SH7750_FRQCR_A7)
- REGNAME(SH7750_WTCNT_A7)
- REGNAME(SH7750_WTCSR_A7)
- REGNAME(SH7750_R64CNT_A7)
- REGNAME(SH7750_RSECCNT_A7)
- REGNAME(SH7750_RMINCNT_A7)
- REGNAME(SH7750_RHRCNT_A7)
- REGNAME(SH7750_RWKCNT_A7)
- REGNAME(SH7750_RDAYCNT_A7)
- REGNAME(SH7750_RMONCNT_A7)
- REGNAME(SH7750_RYRCNT_A7)
- REGNAME(SH7750_RSECAR_A7)
- REGNAME(SH7750_RMINAR_A7)
- REGNAME(SH7750_RHRAR_A7)
- REGNAME(SH7750_RWKAR_A7)
- REGNAME(SH7750_RDAYAR_A7)
- REGNAME(SH7750_RMONAR_A7)
- REGNAME(SH7750_RCR1_A7)
- REGNAME(SH7750_RCR2_A7)
- REGNAME(SH7750_TOCR_A7)
- REGNAME(SH7750_TSTR_A7)
- REGNAME(SH7750_TCOR0_A7)
- REGNAME(SH7750_TCOR1_A7)
- REGNAME(SH7750_TCOR2_A7)
- REGNAME(SH7750_TCNT0_A7)
- REGNAME(SH7750_TCNT1_A7)
- REGNAME(SH7750_TCNT2_A7)
- REGNAME(SH7750_TCR0_A7)
- REGNAME(SH7750_TCR1_A7)
- REGNAME(SH7750_TCR2_A7)
- REGNAME(SH7750_TCPR2_A7)
- REGNAME(SH7750_BCR1_A7)
- REGNAME(SH7750_BCR2_A7)
- REGNAME(SH7750_WCR1_A7)
- REGNAME(SH7750_WCR2_A7)
- REGNAME(SH7750_WCR3_A7)
- REGNAME(SH7750_MCR_A7)
- REGNAME(SH7750_PCR_A7)
- REGNAME(SH7750_RTCSR_A7)
- REGNAME(SH7750_RTCNT_A7)
- REGNAME(SH7750_RTCOR_A7)
- REGNAME(SH7750_RFCR_A7)
- REGNAME(SH7750_SAR0_A7)
- REGNAME(SH7750_SAR1_A7)
- REGNAME(SH7750_SAR2_A7)
- REGNAME(SH7750_SAR3_A7)
- REGNAME(SH7750_DAR0_A7)
- REGNAME(SH7750_DAR1_A7)
- REGNAME(SH7750_DAR2_A7)
- REGNAME(SH7750_DAR3_A7)
- REGNAME(SH7750_DMATCR0_A7)
- REGNAME(SH7750_DMATCR1_A7)
- REGNAME(SH7750_DMATCR2_A7)
- REGNAME(SH7750_DMATCR3_A7)
- REGNAME(SH7750_CHCR0_A7)
- REGNAME(SH7750_CHCR1_A7)
- REGNAME(SH7750_CHCR2_A7)
- REGNAME(SH7750_CHCR3_A7)
- REGNAME(SH7750_DMAOR_A7)
- REGNAME(SH7750_SCRDR1_A7)
- REGNAME(SH7750_SCRDR2_A7)
- REGNAME(SH7750_SCTDR1_A7)
- REGNAME(SH7750_SCTDR2_A7)
- REGNAME(SH7750_SCSMR1_A7)
- REGNAME(SH7750_SCSMR2_A7)
- REGNAME(SH7750_SCSCR1_A7)
- REGNAME(SH7750_SCSCR2_A7)
- REGNAME(SH7750_SCSSR1_A7)
- REGNAME(SH7750_SCSFR2_A7)
- REGNAME(SH7750_SCSPTR1_A7)
- REGNAME(SH7750_SCSPTR2_A7)
- REGNAME(SH7750_SCBRR1_A7)
- REGNAME(SH7750_SCBRR2_A7)
- REGNAME(SH7750_SCFCR2_A7)
- REGNAME(SH7750_SCFDR2_A7)
- REGNAME(SH7750_SCLSR2_A7)
- REGNAME(SH7750_SCSCMR1_A7)
- REGNAME(SH7750_PCTRA_A7)
- REGNAME(SH7750_PDTRA_A7)
- REGNAME(SH7750_PCTRB_A7)
- REGNAME(SH7750_PDTRB_A7)
- REGNAME(SH7750_GPIOIC_A7)
- REGNAME(SH7750_ICR_A7)
- REGNAME(SH7750_IPRA_A7)
- REGNAME(SH7750_IPRB_A7)
- REGNAME(SH7750_IPRC_A7)
- REGNAME(SH7750_BCR3_A7)
- REGNAME(SH7750_BCR4_A7)
- REGNAME(SH7750_PRECHARGE0_A7)
- REGNAME(SH7750_PRECHARGE1_A7) {(uint32_t) - 1, 0}
-};
-
-const char *regname(uint32_t addr)
-{
- unsigned int i;
-
- for (i = 0; regnames[i].regaddr != (uint32_t) - 1; i++) {
- if (regnames[i].regaddr == addr)
- return regnames[i].regname;
- }
-
- return "<unknown reg>";
-}
diff --git a/hw/sh7750_regnames.h b/hw/sh7750_regnames.h
deleted file mode 100644
index 7463709..0000000
--- a/hw/sh7750_regnames.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _SH7750_REGNAMES_H
-#define _SH7750_REGNAMES_H
-
-const char *regname(uint32_t addr);
-
-#endif /* _SH7750_REGNAMES_H */
diff --git a/hw/sh7750_regs.h b/hw/sh7750_regs.h
deleted file mode 100644
index 44ae95b..0000000
--- a/hw/sh7750_regs.h
+++ /dev/null
@@ -1,1623 +0,0 @@
-/*
- * SH-7750 memory-mapped registers
- * This file based on information provided in the following document:
- * "Hitachi SuperH (tm) RISC engine. SH7750 Series (SH7750, SH7750S)
- * Hardware Manual"
- * Document Number ADE-602-124C, Rev. 4.0, 4/21/00, Hitachi Ltd.
- *
- * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
- * Author: Alexandra Kossovsky <sasha@oktet.ru>
- * Victor V. Vengerov <vvv@oktet.ru>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.com/license/LICENSE.
- *
- * @(#) sh7750_regs.h,v 1.2.4.1 2003/09/04 18:46:00 joel Exp
- */
-
-#ifndef __SH7750_REGS_H__
-#define __SH7750_REGS_H__
-
-/*
- * All register has 2 addresses: in 0xff000000 - 0xffffffff (P4 address) and
- * in 0x1f000000 - 0x1fffffff (area 7 address)
- */
-#define SH7750_P4_BASE 0xff000000 /* Accessable only in
- priveleged mode */
-#define SH7750_A7_BASE 0x1f000000 /* Accessable only using TLB */
-
-#define SH7750_P4_REG32(ofs) (SH7750_P4_BASE + (ofs))
-#define SH7750_A7_REG32(ofs) (SH7750_A7_BASE + (ofs))
-
-/*
- * MMU Registers
- */
-
-/* Page Table Entry High register - PTEH */
-#define SH7750_PTEH_REGOFS 0x000000 /* offset */
-#define SH7750_PTEH SH7750_P4_REG32(SH7750_PTEH_REGOFS)
-#define SH7750_PTEH_A7 SH7750_A7_REG32(SH7750_PTEH_REGOFS)
-#define SH7750_PTEH_VPN 0xfffffd00 /* Virtual page number */
-#define SH7750_PTEH_VPN_S 10
-#define SH7750_PTEH_ASID 0x000000ff /* Address space identifier */
-#define SH7750_PTEH_ASID_S 0
-
-/* Page Table Entry Low register - PTEL */
-#define SH7750_PTEL_REGOFS 0x000004 /* offset */
-#define SH7750_PTEL SH7750_P4_REG32(SH7750_PTEL_REGOFS)
-#define SH7750_PTEL_A7 SH7750_A7_REG32(SH7750_PTEL_REGOFS)
-#define SH7750_PTEL_PPN 0x1ffffc00 /* Physical page number */
-#define SH7750_PTEL_PPN_S 10
-#define SH7750_PTEL_V 0x00000100 /* Validity (0-entry is invalid) */
-#define SH7750_PTEL_SZ1 0x00000080 /* Page size bit 1 */
-#define SH7750_PTEL_SZ0 0x00000010 /* Page size bit 0 */
-#define SH7750_PTEL_SZ_1KB 0x00000000 /* 1-kbyte page */
-#define SH7750_PTEL_SZ_4KB 0x00000010 /* 4-kbyte page */
-#define SH7750_PTEL_SZ_64KB 0x00000080 /* 64-kbyte page */
-#define SH7750_PTEL_SZ_1MB 0x00000090 /* 1-Mbyte page */
-#define SH7750_PTEL_PR 0x00000060 /* Protection Key Data */
-#define SH7750_PTEL_PR_ROPO 0x00000000 /* read-only in priv mode */
-#define SH7750_PTEL_PR_RWPO 0x00000020 /* read-write in priv mode */
-#define SH7750_PTEL_PR_ROPU 0x00000040 /* read-only in priv or user mode */
-#define SH7750_PTEL_PR_RWPU 0x00000060 /* read-write in priv or user mode */
-#define SH7750_PTEL_C 0x00000008 /* Cacheability
- (0 - page not cacheable) */
-#define SH7750_PTEL_D 0x00000004 /* Dirty bit (1 - write has been
- performed to a page) */
-#define SH7750_PTEL_SH 0x00000002 /* Share Status bit (1 - page are
- shared by processes) */
-#define SH7750_PTEL_WT 0x00000001 /* Write-through bit, specifies the
- cache write mode:
- 0 - Copy-back mode
- 1 - Write-through mode */
-
-/* Page Table Entry Assistance register - PTEA */
-#define SH7750_PTEA_REGOFS 0x000034 /* offset */
-#define SH7750_PTEA SH7750_P4_REG32(SH7750_PTEA_REGOFS)
-#define SH7750_PTEA_A7 SH7750_A7_REG32(SH7750_PTEA_REGOFS)
-#define SH7750_PTEA_TC 0x00000008 /* Timing Control bit
- 0 - use area 5 wait states
- 1 - use area 6 wait states */
-#define SH7750_PTEA_SA 0x00000007 /* Space Attribute bits: */
-#define SH7750_PTEA_SA_UNDEF 0x00000000 /* 0 - undefined */
-#define SH7750_PTEA_SA_IOVAR 0x00000001 /* 1 - variable-size I/O space */
-#define SH7750_PTEA_SA_IO8 0x00000002 /* 2 - 8-bit I/O space */
-#define SH7750_PTEA_SA_IO16 0x00000003 /* 3 - 16-bit I/O space */
-#define SH7750_PTEA_SA_CMEM8 0x00000004 /* 4 - 8-bit common memory space */
-#define SH7750_PTEA_SA_CMEM16 0x00000005 /* 5 - 16-bit common memory space */
-#define SH7750_PTEA_SA_AMEM8 0x00000006 /* 6 - 8-bit attr memory space */
-#define SH7750_PTEA_SA_AMEM16 0x00000007 /* 7 - 16-bit attr memory space */
-
-
-/* Translation table base register */
-#define SH7750_TTB_REGOFS 0x000008 /* offset */
-#define SH7750_TTB SH7750_P4_REG32(SH7750_TTB_REGOFS)
-#define SH7750_TTB_A7 SH7750_A7_REG32(SH7750_TTB_REGOFS)
-
-/* TLB exeption address register - TEA */
-#define SH7750_TEA_REGOFS 0x00000c /* offset */
-#define SH7750_TEA SH7750_P4_REG32(SH7750_TEA_REGOFS)
-#define SH7750_TEA_A7 SH7750_A7_REG32(SH7750_TEA_REGOFS)
-
-/* MMU control register - MMUCR */
-#define SH7750_MMUCR_REGOFS 0x000010 /* offset */
-#define SH7750_MMUCR SH7750_P4_REG32(SH7750_MMUCR_REGOFS)
-#define SH7750_MMUCR_A7 SH7750_A7_REG32(SH7750_MMUCR_REGOFS)
-#define SH7750_MMUCR_AT 0x00000001 /* Address translation bit */
-#define SH7750_MMUCR_TI 0x00000004 /* TLB invalidate */
-#define SH7750_MMUCR_SV 0x00000100 /* Single Virtual Mode bit */
-#define SH7750_MMUCR_SQMD 0x00000200 /* Store Queue Mode bit */
-#define SH7750_MMUCR_URC 0x0000FC00 /* UTLB Replace Counter */
-#define SH7750_MMUCR_URC_S 10
-#define SH7750_MMUCR_URB 0x00FC0000 /* UTLB Replace Boundary */
-#define SH7750_MMUCR_URB_S 18
-#define SH7750_MMUCR_LRUI 0xFC000000 /* Least Recently Used ITLB */
-#define SH7750_MMUCR_LRUI_S 26
-
-
-
-
-/*
- * Cache registers
- * IC -- instructions cache
- * OC -- operand cache
- */
-
-/* Cache Control Register - CCR */
-#define SH7750_CCR_REGOFS 0x00001c /* offset */
-#define SH7750_CCR SH7750_P4_REG32(SH7750_CCR_REGOFS)
-#define SH7750_CCR_A7 SH7750_A7_REG32(SH7750_CCR_REGOFS)
-
-#define SH7750_CCR_IIX 0x00008000 /* IC index enable bit */
-#define SH7750_CCR_ICI 0x00000800 /* IC invalidation bit:
- set it to clear IC */
-#define SH7750_CCR_ICE 0x00000100 /* IC enable bit */
-#define SH7750_CCR_OIX 0x00000080 /* OC index enable bit */
-#define SH7750_CCR_ORA 0x00000020 /* OC RAM enable bit
- if you set OCE = 0,
- you should set ORA = 0 */
-#define SH7750_CCR_OCI 0x00000008 /* OC invalidation bit */
-#define SH7750_CCR_CB 0x00000004 /* Copy-back bit for P1 area */
-#define SH7750_CCR_WT 0x00000002 /* Write-through bit for P0,U0,P3 area */
-#define SH7750_CCR_OCE 0x00000001 /* OC enable bit */
-
-/* Queue address control register 0 - QACR0 */
-#define SH7750_QACR0_REGOFS 0x000038 /* offset */
-#define SH7750_QACR0 SH7750_P4_REG32(SH7750_QACR0_REGOFS)
-#define SH7750_QACR0_A7 SH7750_A7_REG32(SH7750_QACR0_REGOFS)
-
-/* Queue address control register 1 - QACR1 */
-#define SH7750_QACR1_REGOFS 0x00003c /* offset */
-#define SH7750_QACR1 SH7750_P4_REG32(SH7750_QACR1_REGOFS)
-#define SH7750_QACR1_A7 SH7750_A7_REG32(SH7750_QACR1_REGOFS)
-
-
-/*
- * Exeption-related registers
- */
-
-/* Immediate data for TRAPA instuction - TRA */
-#define SH7750_TRA_REGOFS 0x000020 /* offset */
-#define SH7750_TRA SH7750_P4_REG32(SH7750_TRA_REGOFS)
-#define SH7750_TRA_A7 SH7750_A7_REG32(SH7750_TRA_REGOFS)
-
-#define SH7750_TRA_IMM 0x000003fd /* Immediate data operand */
-#define SH7750_TRA_IMM_S 2
-
-/* Exeption event register - EXPEVT */
-#define SH7750_EXPEVT_REGOFS 0x000024
-#define SH7750_EXPEVT SH7750_P4_REG32(SH7750_EXPEVT_REGOFS)
-#define SH7750_EXPEVT_A7 SH7750_A7_REG32(SH7750_EXPEVT_REGOFS)
-
-#define SH7750_EXPEVT_EX 0x00000fff /* Exeption code */
-#define SH7750_EXPEVT_EX_S 0
-
-/* Interrupt event register */
-#define SH7750_INTEVT_REGOFS 0x000028
-#define SH7750_INTEVT SH7750_P4_REG32(SH7750_INTEVT_REGOFS)
-#define SH7750_INTEVT_A7 SH7750_A7_REG32(SH7750_INTEVT_REGOFS)
-#define SH7750_INTEVT_EX 0x00000fff /* Exeption code */
-#define SH7750_INTEVT_EX_S 0
-
-/*
- * Exception/interrupt codes
- */
-#define SH7750_EVT_TO_NUM(evt) ((evt) >> 5)
-
-/* Reset exception category */
-#define SH7750_EVT_POWER_ON_RST 0x000 /* Power-on reset */
-#define SH7750_EVT_MANUAL_RST 0x020 /* Manual reset */
-#define SH7750_EVT_TLB_MULT_HIT 0x140 /* TLB multiple-hit exception */
-
-/* General exception category */
-#define SH7750_EVT_USER_BREAK 0x1E0 /* User break */
-#define SH7750_EVT_IADDR_ERR 0x0E0 /* Instruction address error */
-#define SH7750_EVT_TLB_READ_MISS 0x040 /* ITLB miss exception /
- DTLB miss exception (read) */
-#define SH7750_EVT_TLB_READ_PROTV 0x0A0 /* ITLB protection violation /
- DTLB protection violation (read) */
-#define SH7750_EVT_ILLEGAL_INSTR 0x180 /* General Illegal Instruction
- exception */
-#define SH7750_EVT_SLOT_ILLEGAL_INSTR 0x1A0 /* Slot Illegal Instruction
- exception */
-#define SH7750_EVT_FPU_DISABLE 0x800 /* General FPU disable exception */
-#define SH7750_EVT_SLOT_FPU_DISABLE 0x820 /* Slot FPU disable exception */
-#define SH7750_EVT_DATA_READ_ERR 0x0E0 /* Data address error (read) */
-#define SH7750_EVT_DATA_WRITE_ERR 0x100 /* Data address error (write) */
-#define SH7750_EVT_DTLB_WRITE_MISS 0x060 /* DTLB miss exception (write) */
-#define SH7750_EVT_DTLB_WRITE_PROTV 0x0C0 /* DTLB protection violation
- exception (write) */
-#define SH7750_EVT_FPU_EXCEPTION 0x120 /* FPU exception */
-#define SH7750_EVT_INITIAL_PGWRITE 0x080 /* Initial Page Write exception */
-#define SH7750_EVT_TRAPA 0x160 /* Unconditional trap (TRAPA) */
-
-/* Interrupt exception category */
-#define SH7750_EVT_NMI 0x1C0 /* Non-maskable interrupt */
-#define SH7750_EVT_IRQ0 0x200 /* External Interrupt 0 */
-#define SH7750_EVT_IRQ1 0x220 /* External Interrupt 1 */
-#define SH7750_EVT_IRQ2 0x240 /* External Interrupt 2 */
-#define SH7750_EVT_IRQ3 0x260 /* External Interrupt 3 */
-#define SH7750_EVT_IRQ4 0x280 /* External Interrupt 4 */
-#define SH7750_EVT_IRQ5 0x2A0 /* External Interrupt 5 */
-#define SH7750_EVT_IRQ6 0x2C0 /* External Interrupt 6 */
-#define SH7750_EVT_IRQ7 0x2E0 /* External Interrupt 7 */
-#define SH7750_EVT_IRQ8 0x300 /* External Interrupt 8 */
-#define SH7750_EVT_IRQ9 0x320 /* External Interrupt 9 */
-#define SH7750_EVT_IRQA 0x340 /* External Interrupt A */
-#define SH7750_EVT_IRQB 0x360 /* External Interrupt B */
-#define SH7750_EVT_IRQC 0x380 /* External Interrupt C */
-#define SH7750_EVT_IRQD 0x3A0 /* External Interrupt D */
-#define SH7750_EVT_IRQE 0x3C0 /* External Interrupt E */
-
-/* Peripheral Module Interrupts - Timer Unit (TMU) */
-#define SH7750_EVT_TUNI0 0x400 /* TMU Underflow Interrupt 0 */
-#define SH7750_EVT_TUNI1 0x420 /* TMU Underflow Interrupt 1 */
-#define SH7750_EVT_TUNI2 0x440 /* TMU Underflow Interrupt 2 */
-#define SH7750_EVT_TICPI2 0x460 /* TMU Input Capture Interrupt 2 */
-
-/* Peripheral Module Interrupts - Real-Time Clock (RTC) */
-#define SH7750_EVT_RTC_ATI 0x480 /* Alarm Interrupt Request */
-#define SH7750_EVT_RTC_PRI 0x4A0 /* Periodic Interrupt Request */
-#define SH7750_EVT_RTC_CUI 0x4C0 /* Carry Interrupt Request */
-
-/* Peripheral Module Interrupts - Serial Communication Interface (SCI) */
-#define SH7750_EVT_SCI_ERI 0x4E0 /* Receive Error */
-#define SH7750_EVT_SCI_RXI 0x500 /* Receive Data Register Full */
-#define SH7750_EVT_SCI_TXI 0x520 /* Transmit Data Register Empty */
-#define SH7750_EVT_SCI_TEI 0x540 /* Transmit End */
-
-/* Peripheral Module Interrupts - Watchdog Timer (WDT) */
-#define SH7750_EVT_WDT_ITI 0x560 /* Interval Timer Interrupt
- (used when WDT operates in
- interval timer mode) */
-
-/* Peripheral Module Interrupts - Memory Refresh Unit (REF) */
-#define SH7750_EVT_REF_RCMI 0x580 /* Compare-match Interrupt */
-#define SH7750_EVT_REF_ROVI 0x5A0 /* Refresh Counter Overflow
- interrupt */
-
-/* Peripheral Module Interrupts - Hitachi User Debug Interface (H-UDI) */
-#define SH7750_EVT_HUDI 0x600 /* UDI interrupt */
-
-/* Peripheral Module Interrupts - General-Purpose I/O (GPIO) */
-#define SH7750_EVT_GPIO 0x620 /* GPIO Interrupt */
-
-/* Peripheral Module Interrupts - DMA Controller (DMAC) */
-#define SH7750_EVT_DMAC_DMTE0 0x640 /* DMAC 0 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMTE1 0x660 /* DMAC 1 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMTE2 0x680 /* DMAC 2 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMTE3 0x6A0 /* DMAC 3 Transfer End Interrupt */
-#define SH7750_EVT_DMAC_DMAE 0x6C0 /* DMAC Address Error Interrupt */
-
-/* Peripheral Module Interrupts - Serial Communication Interface with FIFO */
-/* (SCIF) */
-#define SH7750_EVT_SCIF_ERI 0x700 /* Receive Error */
-#define SH7750_EVT_SCIF_RXI 0x720 /* Receive FIFO Data Full or
- Receive Data ready interrupt */
-#define SH7750_EVT_SCIF_BRI 0x740 /* Break or overrun error */
-#define SH7750_EVT_SCIF_TXI 0x760 /* Transmit FIFO Data Empty */
-
-/*
- * Power Management
- */
-#define SH7750_STBCR_REGOFS 0xC00004 /* offset */
-#define SH7750_STBCR SH7750_P4_REG32(SH7750_STBCR_REGOFS)
-#define SH7750_STBCR_A7 SH7750_A7_REG32(SH7750_STBCR_REGOFS)
-
-#define SH7750_STBCR_STBY 0x80 /* Specifies a transition to standby mode:
- 0 - Transition to SLEEP mode on SLEEP
- 1 - Transition to STANDBY mode on SLEEP */
-#define SH7750_STBCR_PHZ 0x40 /* State of peripheral module pins in
- standby mode:
- 0 - normal state
- 1 - high-impendance state */
-
-#define SH7750_STBCR_PPU 0x20 /* Peripheral module pins pull-up controls */
-#define SH7750_STBCR_MSTP4 0x10 /* Stopping the clock supply to DMAC */
-#define SH7750_STBCR_DMAC_STP SH7750_STBCR_MSTP4
-#define SH7750_STBCR_MSTP3 0x08 /* Stopping the clock supply to SCIF */
-#define SH7750_STBCR_SCIF_STP SH7750_STBCR_MSTP3
-#define SH7750_STBCR_MSTP2 0x04 /* Stopping the clock supply to TMU */
-#define SH7750_STBCR_TMU_STP SH7750_STBCR_MSTP2
-#define SH7750_STBCR_MSTP1 0x02 /* Stopping the clock supply to RTC */
-#define SH7750_STBCR_RTC_STP SH7750_STBCR_MSTP1
-#define SH7750_STBCR_MSPT0 0x01 /* Stopping the clock supply to SCI */
-#define SH7750_STBCR_SCI_STP SH7750_STBCR_MSTP0
-
-#define SH7750_STBCR_STBY 0x80
-
-
-#define SH7750_STBCR2_REGOFS 0xC00010 /* offset */
-#define SH7750_STBCR2 SH7750_P4_REG32(SH7750_STBCR2_REGOFS)
-#define SH7750_STBCR2_A7 SH7750_A7_REG32(SH7750_STBCR2_REGOFS)
-
-#define SH7750_STBCR2_DSLP 0x80 /* Specifies transition to deep sleep mode:
- 0 - transition to sleep or standby mode
- as it is specified in STBY bit
- 1 - transition to deep sleep mode on
- execution of SLEEP instruction */
-#define SH7750_STBCR2_MSTP6 0x02 /* Stopping the clock supply to Store Queue
- in the cache controller */
-#define SH7750_STBCR2_SQ_STP SH7750_STBCR2_MSTP6
-#define SH7750_STBCR2_MSTP5 0x01 /* Stopping the clock supply to the User
- Break Controller (UBC) */
-#define SH7750_STBCR2_UBC_STP SH7750_STBCR2_MSTP5
-
-/*
- * Clock Pulse Generator (CPG)
- */
-#define SH7750_FRQCR_REGOFS 0xC00000 /* offset */
-#define SH7750_FRQCR SH7750_P4_REG32(SH7750_FRQCR_REGOFS)
-#define SH7750_FRQCR_A7 SH7750_A7_REG32(SH7750_FRQCR_REGOFS)
-
-#define SH7750_FRQCR_CKOEN 0x0800 /* Clock Output Enable
- 0 - CKIO pin goes to HiZ/pullup
- 1 - Clock is output from CKIO */
-#define SH7750_FRQCR_PLL1EN 0x0400 /* PLL circuit 1 enable */
-#define SH7750_FRQCR_PLL2EN 0x0200 /* PLL circuit 2 enable */
-
-#define SH7750_FRQCR_IFC 0x01C0 /* CPU clock frequency division ratio: */
-#define SH7750_FRQCR_IFCDIV1 0x0000 /* 0 - * 1 */
-#define SH7750_FRQCR_IFCDIV2 0x0040 /* 1 - * 1/2 */
-#define SH7750_FRQCR_IFCDIV3 0x0080 /* 2 - * 1/3 */
-#define SH7750_FRQCR_IFCDIV4 0x00C0 /* 3 - * 1/4 */
-#define SH7750_FRQCR_IFCDIV6 0x0100 /* 4 - * 1/6 */
-#define SH7750_FRQCR_IFCDIV8 0x0140 /* 5 - * 1/8 */
-
-#define SH7750_FRQCR_BFC 0x0038 /* Bus clock frequency division ratio: */
-#define SH7750_FRQCR_BFCDIV1 0x0000 /* 0 - * 1 */
-#define SH7750_FRQCR_BFCDIV2 0x0008 /* 1 - * 1/2 */
-#define SH7750_FRQCR_BFCDIV3 0x0010 /* 2 - * 1/3 */
-#define SH7750_FRQCR_BFCDIV4 0x0018 /* 3 - * 1/4 */
-#define SH7750_FRQCR_BFCDIV6 0x0020 /* 4 - * 1/6 */
-#define SH7750_FRQCR_BFCDIV8 0x0028 /* 5 - * 1/8 */
-
-#define SH7750_FRQCR_PFC 0x0007 /* Peripheral module clock frequency
- division ratio: */
-#define SH7750_FRQCR_PFCDIV2 0x0000 /* 0 - * 1/2 */
-#define SH7750_FRQCR_PFCDIV3 0x0001 /* 1 - * 1/3 */
-#define SH7750_FRQCR_PFCDIV4 0x0002 /* 2 - * 1/4 */
-#define SH7750_FRQCR_PFCDIV6 0x0003 /* 3 - * 1/6 */
-#define SH7750_FRQCR_PFCDIV8 0x0004 /* 4 - * 1/8 */
-
-/*
- * Watchdog Timer (WDT)
- */
-
-/* Watchdog Timer Counter register - WTCNT */
-#define SH7750_WTCNT_REGOFS 0xC00008 /* offset */
-#define SH7750_WTCNT SH7750_P4_REG32(SH7750_WTCNT_REGOFS)
-#define SH7750_WTCNT_A7 SH7750_A7_REG32(SH7750_WTCNT_REGOFS)
-#define SH7750_WTCNT_KEY 0x5A00 /* When WTCNT byte register written,
- you have to set the upper byte to
- 0x5A */
-
-/* Watchdog Timer Control/Status register - WTCSR */
-#define SH7750_WTCSR_REGOFS 0xC0000C /* offset */
-#define SH7750_WTCSR SH7750_P4_REG32(SH7750_WTCSR_REGOFS)
-#define SH7750_WTCSR_A7 SH7750_A7_REG32(SH7750_WTCSR_REGOFS)
-#define SH7750_WTCSR_KEY 0xA500 /* When WTCSR byte register written,
- you have to set the upper byte to
- 0xA5 */
-#define SH7750_WTCSR_TME 0x80 /* Timer enable (1-upcount start) */
-#define SH7750_WTCSR_MODE 0x40 /* Timer Mode Select: */
-#define SH7750_WTCSR_MODE_WT 0x40 /* Watchdog Timer Mode */
-#define SH7750_WTCSR_MODE_IT 0x00 /* Interval Timer Mode */
-#define SH7750_WTCSR_RSTS 0x20 /* Reset Select: */
-#define SH7750_WTCSR_RST_MAN 0x20 /* Manual Reset */
-#define SH7750_WTCSR_RST_PWR 0x00 /* Power-on Reset */
-#define SH7750_WTCSR_WOVF 0x10 /* Watchdog Timer Overflow Flag */
-#define SH7750_WTCSR_IOVF 0x08 /* Interval Timer Overflow Flag */
-#define SH7750_WTCSR_CKS 0x07 /* Clock Select: */
-#define SH7750_WTCSR_CKS_DIV32 0x00 /* 1/32 of frequency divider 2 input */
-#define SH7750_WTCSR_CKS_DIV64 0x01 /* 1/64 */
-#define SH7750_WTCSR_CKS_DIV128 0x02 /* 1/128 */
-#define SH7750_WTCSR_CKS_DIV256 0x03 /* 1/256 */
-#define SH7750_WTCSR_CKS_DIV512 0x04 /* 1/512 */
-#define SH7750_WTCSR_CKS_DIV1024 0x05 /* 1/1024 */
-#define SH7750_WTCSR_CKS_DIV2048 0x06 /* 1/2048 */
-#define SH7750_WTCSR_CKS_DIV4096 0x07 /* 1/4096 */
-
-/*
- * Real-Time Clock (RTC)
- */
-/* 64-Hz Counter Register (byte, read-only) - R64CNT */
-#define SH7750_R64CNT_REGOFS 0xC80000 /* offset */
-#define SH7750_R64CNT SH7750_P4_REG32(SH7750_R64CNT_REGOFS)
-#define SH7750_R64CNT_A7 SH7750_A7_REG32(SH7750_R64CNT_REGOFS)
-
-/* Second Counter Register (byte, BCD-coded) - RSECCNT */
-#define SH7750_RSECCNT_REGOFS 0xC80004 /* offset */
-#define SH7750_RSECCNT SH7750_P4_REG32(SH7750_RSECCNT_REGOFS)
-#define SH7750_RSECCNT_A7 SH7750_A7_REG32(SH7750_RSECCNT_REGOFS)
-
-/* Minute Counter Register (byte, BCD-coded) - RMINCNT */
-#define SH7750_RMINCNT_REGOFS 0xC80008 /* offset */
-#define SH7750_RMINCNT SH7750_P4_REG32(SH7750_RMINCNT_REGOFS)
-#define SH7750_RMINCNT_A7 SH7750_A7_REG32(SH7750_RMINCNT_REGOFS)
-
-/* Hour Counter Register (byte, BCD-coded) - RHRCNT */
-#define SH7750_RHRCNT_REGOFS 0xC8000C /* offset */
-#define SH7750_RHRCNT SH7750_P4_REG32(SH7750_RHRCNT_REGOFS)
-#define SH7750_RHRCNT_A7 SH7750_A7_REG32(SH7750_RHRCNT_REGOFS)
-
-/* Day-of-Week Counter Register (byte) - RWKCNT */
-#define SH7750_RWKCNT_REGOFS 0xC80010 /* offset */
-#define SH7750_RWKCNT SH7750_P4_REG32(SH7750_RWKCNT_REGOFS)
-#define SH7750_RWKCNT_A7 SH7750_A7_REG32(SH7750_RWKCNT_REGOFS)
-
-#define SH7750_RWKCNT_SUN 0 /* Sunday */
-#define SH7750_RWKCNT_MON 1 /* Monday */
-#define SH7750_RWKCNT_TUE 2 /* Tuesday */
-#define SH7750_RWKCNT_WED 3 /* Wednesday */
-#define SH7750_RWKCNT_THU 4 /* Thursday */
-#define SH7750_RWKCNT_FRI 5 /* Friday */
-#define SH7750_RWKCNT_SAT 6 /* Saturday */
-
-/* Day Counter Register (byte, BCD-coded) - RDAYCNT */
-#define SH7750_RDAYCNT_REGOFS 0xC80014 /* offset */
-#define SH7750_RDAYCNT SH7750_P4_REG32(SH7750_RDAYCNT_REGOFS)
-#define SH7750_RDAYCNT_A7 SH7750_A7_REG32(SH7750_RDAYCNT_REGOFS)
-
-/* Month Counter Register (byte, BCD-coded) - RMONCNT */
-#define SH7750_RMONCNT_REGOFS 0xC80018 /* offset */
-#define SH7750_RMONCNT SH7750_P4_REG32(SH7750_RMONCNT_REGOFS)
-#define SH7750_RMONCNT_A7 SH7750_A7_REG32(SH7750_RMONCNT_REGOFS)
-
-/* Year Counter Register (half, BCD-coded) - RYRCNT */
-#define SH7750_RYRCNT_REGOFS 0xC8001C /* offset */
-#define SH7750_RYRCNT SH7750_P4_REG32(SH7750_RYRCNT_REGOFS)
-#define SH7750_RYRCNT_A7 SH7750_A7_REG32(SH7750_RYRCNT_REGOFS)
-
-/* Second Alarm Register (byte, BCD-coded) - RSECAR */
-#define SH7750_RSECAR_REGOFS 0xC80020 /* offset */
-#define SH7750_RSECAR SH7750_P4_REG32(SH7750_RSECAR_REGOFS)
-#define SH7750_RSECAR_A7 SH7750_A7_REG32(SH7750_RSECAR_REGOFS)
-#define SH7750_RSECAR_ENB 0x80 /* Second Alarm Enable */
-
-/* Minute Alarm Register (byte, BCD-coded) - RMINAR */
-#define SH7750_RMINAR_REGOFS 0xC80024 /* offset */
-#define SH7750_RMINAR SH7750_P4_REG32(SH7750_RMINAR_REGOFS)
-#define SH7750_RMINAR_A7 SH7750_A7_REG32(SH7750_RMINAR_REGOFS)
-#define SH7750_RMINAR_ENB 0x80 /* Minute Alarm Enable */
-
-/* Hour Alarm Register (byte, BCD-coded) - RHRAR */
-#define SH7750_RHRAR_REGOFS 0xC80028 /* offset */
-#define SH7750_RHRAR SH7750_P4_REG32(SH7750_RHRAR_REGOFS)
-#define SH7750_RHRAR_A7 SH7750_A7_REG32(SH7750_RHRAR_REGOFS)
-#define SH7750_RHRAR_ENB 0x80 /* Hour Alarm Enable */
-
-/* Day-of-Week Alarm Register (byte) - RWKAR */
-#define SH7750_RWKAR_REGOFS 0xC8002C /* offset */
-#define SH7750_RWKAR SH7750_P4_REG32(SH7750_RWKAR_REGOFS)
-#define SH7750_RWKAR_A7 SH7750_A7_REG32(SH7750_RWKAR_REGOFS)
-#define SH7750_RWKAR_ENB 0x80 /* Day-of-week Alarm Enable */
-
-#define SH7750_RWKAR_SUN 0 /* Sunday */
-#define SH7750_RWKAR_MON 1 /* Monday */
-#define SH7750_RWKAR_TUE 2 /* Tuesday */
-#define SH7750_RWKAR_WED 3 /* Wednesday */
-#define SH7750_RWKAR_THU 4 /* Thursday */
-#define SH7750_RWKAR_FRI 5 /* Friday */
-#define SH7750_RWKAR_SAT 6 /* Saturday */
-
-/* Day Alarm Register (byte, BCD-coded) - RDAYAR */
-#define SH7750_RDAYAR_REGOFS 0xC80030 /* offset */
-#define SH7750_RDAYAR SH7750_P4_REG32(SH7750_RDAYAR_REGOFS)
-#define SH7750_RDAYAR_A7 SH7750_A7_REG32(SH7750_RDAYAR_REGOFS)
-#define SH7750_RDAYAR_ENB 0x80 /* Day Alarm Enable */
-
-/* Month Counter Register (byte, BCD-coded) - RMONAR */
-#define SH7750_RMONAR_REGOFS 0xC80034 /* offset */
-#define SH7750_RMONAR SH7750_P4_REG32(SH7750_RMONAR_REGOFS)
-#define SH7750_RMONAR_A7 SH7750_A7_REG32(SH7750_RMONAR_REGOFS)
-#define SH7750_RMONAR_ENB 0x80 /* Month Alarm Enable */
-
-/* RTC Control Register 1 (byte) - RCR1 */
-#define SH7750_RCR1_REGOFS 0xC80038 /* offset */
-#define SH7750_RCR1 SH7750_P4_REG32(SH7750_RCR1_REGOFS)
-#define SH7750_RCR1_A7 SH7750_A7_REG32(SH7750_RCR1_REGOFS)
-#define SH7750_RCR1_CF 0x80 /* Carry Flag */
-#define SH7750_RCR1_CIE 0x10 /* Carry Interrupt Enable */
-#define SH7750_RCR1_AIE 0x08 /* Alarm Interrupt Enable */
-#define SH7750_RCR1_AF 0x01 /* Alarm Flag */
-
-/* RTC Control Register 2 (byte) - RCR2 */
-#define SH7750_RCR2_REGOFS 0xC8003C /* offset */
-#define SH7750_RCR2 SH7750_P4_REG32(SH7750_RCR2_REGOFS)
-#define SH7750_RCR2_A7 SH7750_A7_REG32(SH7750_RCR2_REGOFS)
-#define SH7750_RCR2_PEF 0x80 /* Periodic Interrupt Flag */
-#define SH7750_RCR2_PES 0x70 /* Periodic Interrupt Enable: */
-#define SH7750_RCR2_PES_DIS 0x00 /* Periodic Interrupt Disabled */
-#define SH7750_RCR2_PES_DIV256 0x10 /* Generated at 1/256 sec interval */
-#define SH7750_RCR2_PES_DIV64 0x20 /* Generated at 1/64 sec interval */
-#define SH7750_RCR2_PES_DIV16 0x30 /* Generated at 1/16 sec interval */
-#define SH7750_RCR2_PES_DIV4 0x40 /* Generated at 1/4 sec interval */
-#define SH7750_RCR2_PES_DIV2 0x50 /* Generated at 1/2 sec interval */
-#define SH7750_RCR2_PES_x1 0x60 /* Generated at 1 sec interval */
-#define SH7750_RCR2_PES_x2 0x70 /* Generated at 2 sec interval */
-#define SH7750_RCR2_RTCEN 0x08 /* RTC Crystal Oscillator is Operated */
-#define SH7750_RCR2_ADJ 0x04 /* 30-Second Adjastment */
-#define SH7750_RCR2_RESET 0x02 /* Frequency divider circuits are reset */
-#define SH7750_RCR2_START 0x01 /* 0 - sec, min, hr, day-of-week, month,
- year counters are stopped
- 1 - sec, min, hr, day-of-week, month,
- year counters operate normally */
-
-
-/*
- * Timer Unit (TMU)
- */
-/* Timer Output Control Register (byte) - TOCR */
-#define SH7750_TOCR_REGOFS 0xD80000 /* offset */
-#define SH7750_TOCR SH7750_P4_REG32(SH7750_TOCR_REGOFS)
-#define SH7750_TOCR_A7 SH7750_A7_REG32(SH7750_TOCR_REGOFS)
-#define SH7750_TOCR_TCOE 0x01 /* Timer Clock Pin Control:
- 0 - TCLK is used as external clock
- input or input capture control
- 1 - TCLK is used as on-chip RTC
- output clock pin */
-
-/* Timer Start Register (byte) - TSTR */
-#define SH7750_TSTR_REGOFS 0xD80004 /* offset */
-#define SH7750_TSTR SH7750_P4_REG32(SH7750_TSTR_REGOFS)
-#define SH7750_TSTR_A7 SH7750_A7_REG32(SH7750_TSTR_REGOFS)
-#define SH7750_TSTR_STR2 0x04 /* TCNT2 performs count operations */
-#define SH7750_TSTR_STR1 0x02 /* TCNT1 performs count operations */
-#define SH7750_TSTR_STR0 0x01 /* TCNT0 performs count operations */
-#define SH7750_TSTR_STR(n) (1 << (n))
-
-/* Timer Constant Register - TCOR0, TCOR1, TCOR2 */
-#define SH7750_TCOR_REGOFS(n) (0xD80008 + ((n)*12)) /* offset */
-#define SH7750_TCOR(n) SH7750_P4_REG32(SH7750_TCOR_REGOFS(n))
-#define SH7750_TCOR_A7(n) SH7750_A7_REG32(SH7750_TCOR_REGOFS(n))
-#define SH7750_TCOR0 SH7750_TCOR(0)
-#define SH7750_TCOR1 SH7750_TCOR(1)
-#define SH7750_TCOR2 SH7750_TCOR(2)
-#define SH7750_TCOR0_A7 SH7750_TCOR_A7(0)
-#define SH7750_TCOR1_A7 SH7750_TCOR_A7(1)
-#define SH7750_TCOR2_A7 SH7750_TCOR_A7(2)
-
-/* Timer Counter Register - TCNT0, TCNT1, TCNT2 */
-#define SH7750_TCNT_REGOFS(n) (0xD8000C + ((n)*12)) /* offset */
-#define SH7750_TCNT(n) SH7750_P4_REG32(SH7750_TCNT_REGOFS(n))
-#define SH7750_TCNT_A7(n) SH7750_A7_REG32(SH7750_TCNT_REGOFS(n))
-#define SH7750_TCNT0 SH7750_TCNT(0)
-#define SH7750_TCNT1 SH7750_TCNT(1)
-#define SH7750_TCNT2 SH7750_TCNT(2)
-#define SH7750_TCNT0_A7 SH7750_TCNT_A7(0)
-#define SH7750_TCNT1_A7 SH7750_TCNT_A7(1)
-#define SH7750_TCNT2_A7 SH7750_TCNT_A7(2)
-
-/* Timer Control Register (half) - TCR0, TCR1, TCR2 */
-#define SH7750_TCR_REGOFS(n) (0xD80010 + ((n)*12)) /* offset */
-#define SH7750_TCR(n) SH7750_P4_REG32(SH7750_TCR_REGOFS(n))
-#define SH7750_TCR_A7(n) SH7750_A7_REG32(SH7750_TCR_REGOFS(n))
-#define SH7750_TCR0 SH7750_TCR(0)
-#define SH7750_TCR1 SH7750_TCR(1)
-#define SH7750_TCR2 SH7750_TCR(2)
-#define SH7750_TCR0_A7 SH7750_TCR_A7(0)
-#define SH7750_TCR1_A7 SH7750_TCR_A7(1)
-#define SH7750_TCR2_A7 SH7750_TCR_A7(2)
-
-#define SH7750_TCR2_ICPF 0x200 /* Input Capture Interrupt Flag
- (1 - input capture has occured) */
-#define SH7750_TCR_UNF 0x100 /* Underflow flag */
-#define SH7750_TCR2_ICPE 0x0C0 /* Input Capture Control: */
-#define SH7750_TCR2_ICPE_DIS 0x000 /* Input Capture function is not used */
-#define SH7750_TCR2_ICPE_NOINT 0x080 /* Input Capture function is used, but
- input capture interrupt is not
- enabled */
-#define SH7750_TCR2_ICPE_INT 0x0C0 /* Input Capture function is used,
- input capture interrupt enabled */
-#define SH7750_TCR_UNIE 0x020 /* Underflow Interrupt Control
- (1 - underflow interrupt enabled) */
-#define SH7750_TCR_CKEG 0x018 /* Clock Edge selection: */
-#define SH7750_TCR_CKEG_RAISE 0x000 /* Count/capture on rising edge */
-#define SH7750_TCR_CKEG_FALL 0x008 /* Count/capture on falling edge */
-#define SH7750_TCR_CKEG_BOTH 0x018 /* Count/capture on both rising and
- falling edges */
-#define SH7750_TCR_TPSC 0x007 /* Timer prescaler */
-#define SH7750_TCR_TPSC_DIV4 0x000 /* Counts on peripheral clock/4 */
-#define SH7750_TCR_TPSC_DIV16 0x001 /* Counts on peripheral clock/16 */
-#define SH7750_TCR_TPSC_DIV64 0x002 /* Counts on peripheral clock/64 */
-#define SH7750_TCR_TPSC_DIV256 0x003 /* Counts on peripheral clock/256 */
-#define SH7750_TCR_TPSC_DIV1024 0x004 /* Counts on peripheral clock/1024 */
-#define SH7750_TCR_TPSC_RTC 0x006 /* Counts on on-chip RTC output clk */
-#define SH7750_TCR_TPSC_EXT 0x007 /* Counts on external clock */
-
-/* Input Capture Register (read-only) - TCPR2 */
-#define SH7750_TCPR2_REGOFS 0xD8002C /* offset */
-#define SH7750_TCPR2 SH7750_P4_REG32(SH7750_TCPR2_REGOFS)
-#define SH7750_TCPR2_A7 SH7750_A7_REG32(SH7750_TCPR2_REGOFS)
-
-/*
- * Bus State Controller - BSC
- */
-/* Bus Control Register 1 - BCR1 */
-#define SH7750_BCR1_REGOFS 0x800000 /* offset */
-#define SH7750_BCR1 SH7750_P4_REG32(SH7750_BCR1_REGOFS)
-#define SH7750_BCR1_A7 SH7750_A7_REG32(SH7750_BCR1_REGOFS)
-#define SH7750_BCR1_ENDIAN 0x80000000 /* Endianness (1 - little endian) */
-#define SH7750_BCR1_MASTER 0x40000000 /* Master/Slave mode (1-master) */
-#define SH7750_BCR1_A0MPX 0x20000000 /* Area 0 Memory Type (0-SRAM,1-MPX) */
-#define SH7750_BCR1_IPUP 0x02000000 /* Input Pin Pull-up Control:
- 0 - pull-up resistor is on for
- control input pins
- 1 - pull-up resistor is off */
-#define SH7750_BCR1_OPUP 0x01000000 /* Output Pin Pull-up Control:
- 0 - pull-up resistor is on for
- control output pins
- 1 - pull-up resistor is off */
-#define SH7750_BCR1_A1MBC 0x00200000 /* Area 1 SRAM Byte Control Mode:
- 0 - Area 1 SRAM is set to
- normal mode
- 1 - Area 1 SRAM is set to byte
- control mode */
-#define SH7750_BCR1_A4MBC 0x00100000 /* Area 4 SRAM Byte Control Mode:
- 0 - Area 4 SRAM is set to
- normal mode
- 1 - Area 4 SRAM is set to byte
- control mode */
-#define SH7750_BCR1_BREQEN 0x00080000 /* BREQ Enable:
- 0 - External requests are not
- accepted
- 1 - External requests are
- accepted */
-#define SH7750_BCR1_PSHR 0x00040000 /* Partial Sharing Bit:
- 0 - Master Mode
- 1 - Partial-sharing Mode */
-#define SH7750_BCR1_MEMMPX 0x00020000 /* Area 1 to 6 MPX Interface:
- 0 - SRAM/burst ROM interface
- 1 - MPX interface */
-#define SH7750_BCR1_HIZMEM 0x00008000 /* High Impendance Control. Specifies
- the state of A[25:0], BS\, CSn\,
- RD/WR\, CE2A\, CE2B\ in standby
- mode and when bus is released:
- 0 - signals go to High-Z mode
- 1 - signals driven */
-#define SH7750_BCR1_HIZCNT 0x00004000 /* High Impendance Control. Specifies
- the state of the RAS\, RAS2\, WEn\,
- CASn\, DQMn, RD\, CASS\, FRAME\,
- RD2\ signals in standby mode and
- when bus is released:
- 0 - signals go to High-Z mode
- 1 - signals driven */
-#define SH7750_BCR1_A0BST 0x00003800 /* Area 0 Burst ROM Control */
-#define SH7750_BCR1_A0BST_SRAM 0x0000 /* Area 0 accessed as SRAM i/f */
-#define SH7750_BCR1_A0BST_ROM4 0x0800 /* Area 0 accessed as burst ROM
- interface, 4 cosequtive access */
-#define SH7750_BCR1_A0BST_ROM8 0x1000 /* Area 0 accessed as burst ROM
- interface, 8 cosequtive access */
-#define SH7750_BCR1_A0BST_ROM16 0x1800 /* Area 0 accessed as burst ROM
- interface, 16 cosequtive access */
-#define SH7750_BCR1_A0BST_ROM32 0x2000 /* Area 0 accessed as burst ROM
- interface, 32 cosequtive access */
-
-#define SH7750_BCR1_A5BST 0x00000700 /* Area 5 Burst ROM Control */
-#define SH7750_BCR1_A5BST_SRAM 0x0000 /* Area 5 accessed as SRAM i/f */
-#define SH7750_BCR1_A5BST_ROM4 0x0100 /* Area 5 accessed as burst ROM
- interface, 4 cosequtive access */
-#define SH7750_BCR1_A5BST_ROM8 0x0200 /* Area 5 accessed as burst ROM
- interface, 8 cosequtive access */
-#define SH7750_BCR1_A5BST_ROM16 0x0300 /* Area 5 accessed as burst ROM
- interface, 16 cosequtive access */
-#define SH7750_BCR1_A5BST_ROM32 0x0400 /* Area 5 accessed as burst ROM
- interface, 32 cosequtive access */
-
-#define SH7750_BCR1_A6BST 0x000000E0 /* Area 6 Burst ROM Control */
-#define SH7750_BCR1_A6BST_SRAM 0x0000 /* Area 6 accessed as SRAM i/f */
-#define SH7750_BCR1_A6BST_ROM4 0x0020 /* Area 6 accessed as burst ROM
- interface, 4 cosequtive access */
-#define SH7750_BCR1_A6BST_ROM8 0x0040 /* Area 6 accessed as burst ROM
- interface, 8 cosequtive access */
-#define SH7750_BCR1_A6BST_ROM16 0x0060 /* Area 6 accessed as burst ROM
- interface, 16 cosequtive access */
-#define SH7750_BCR1_A6BST_ROM32 0x0080 /* Area 6 accessed as burst ROM
- interface, 32 cosequtive access */
-
-#define SH7750_BCR1_DRAMTP 0x001C /* Area 2 and 3 Memory Type */
-#define SH7750_BCR1_DRAMTP_2SRAM_3SRAM 0x0000 /* Area 2 and 3 are SRAM or MPX
- interface. */
-#define SH7750_BCR1_DRAMTP_2SRAM_3SDRAM 0x0008 /* Area 2 - SRAM/MPX, Area 3 -
- synchronous DRAM */
-#define SH7750_BCR1_DRAMTP_2SDRAM_3SDRAM 0x000C /* Area 2 and 3 are synchronous
- DRAM interface */
-#define SH7750_BCR1_DRAMTP_2SRAM_3DRAM 0x0010 /* Area 2 - SRAM/MPX, Area 3 -
- DRAM interface */
-#define SH7750_BCR1_DRAMTP_2DRAM_3DRAM 0x0014 /* Area 2 and 3 are DRAM
- interface */
-
-#define SH7750_BCR1_A56PCM 0x00000001 /* Area 5 and 6 Bus Type:
- 0 - SRAM interface
- 1 - PCMCIA interface */
-
-/* Bus Control Register 2 (half) - BCR2 */
-#define SH7750_BCR2_REGOFS 0x800004 /* offset */
-#define SH7750_BCR2 SH7750_P4_REG32(SH7750_BCR2_REGOFS)
-#define SH7750_BCR2_A7 SH7750_A7_REG32(SH7750_BCR2_REGOFS)
-
-#define SH7750_BCR2_A0SZ 0xC000 /* Area 0 Bus Width */
-#define SH7750_BCR2_A0SZ_S 14
-#define SH7750_BCR2_A6SZ 0x3000 /* Area 6 Bus Width */
-#define SH7750_BCR2_A6SZ_S 12
-#define SH7750_BCR2_A5SZ 0x0C00 /* Area 5 Bus Width */
-#define SH7750_BCR2_A5SZ_S 10
-#define SH7750_BCR2_A4SZ 0x0300 /* Area 4 Bus Width */
-#define SH7750_BCR2_A4SZ_S 8
-#define SH7750_BCR2_A3SZ 0x00C0 /* Area 3 Bus Width */
-#define SH7750_BCR2_A3SZ_S 6
-#define SH7750_BCR2_A2SZ 0x0030 /* Area 2 Bus Width */
-#define SH7750_BCR2_A2SZ_S 4
-#define SH7750_BCR2_A1SZ 0x000C /* Area 1 Bus Width */
-#define SH7750_BCR2_A1SZ_S 2
-#define SH7750_BCR2_SZ_64 0 /* 64 bits */
-#define SH7750_BCR2_SZ_8 1 /* 8 bits */
-#define SH7750_BCR2_SZ_16 2 /* 16 bits */
-#define SH7750_BCR2_SZ_32 3 /* 32 bits */
-#define SH7750_BCR2_PORTEN 0x0001 /* Port Function Enable :
- 0 - D51-D32 are not used as a port
- 1 - D51-D32 are used as a port */
-
-/* Wait Control Register 1 - WCR1 */
-#define SH7750_WCR1_REGOFS 0x800008 /* offset */
-#define SH7750_WCR1 SH7750_P4_REG32(SH7750_WCR1_REGOFS)
-#define SH7750_WCR1_A7 SH7750_A7_REG32(SH7750_WCR1_REGOFS)
-#define SH7750_WCR1_DMAIW 0x70000000 /* DACK Device Inter-Cycle Idle
- specification */
-#define SH7750_WCR1_DMAIW_S 28
-#define SH7750_WCR1_A6IW 0x07000000 /* Area 6 Inter-Cycle Idle spec. */
-#define SH7750_WCR1_A6IW_S 24
-#define SH7750_WCR1_A5IW 0x00700000 /* Area 5 Inter-Cycle Idle spec. */
-#define SH7750_WCR1_A5IW_S 20
-#define SH7750_WCR1_A4IW 0x00070000 /* Area 4 Inter-Cycle Idle spec. */
-#define SH7750_WCR1_A4IW_S 16
-#define SH7750_WCR1_A3IW 0x00007000 /* Area 3 Inter-Cycle Idle spec. */
-#define SH7750_WCR1_A3IW_S 12
-#define SH7750_WCR1_A2IW 0x00000700 /* Area 2 Inter-Cycle Idle spec. */
-#define SH7750_WCR1_A2IW_S 8
-#define SH7750_WCR1_A1IW 0x00000070 /* Area 1 Inter-Cycle Idle spec. */
-#define SH7750_WCR1_A1IW_S 4
-#define SH7750_WCR1_A0IW 0x00000007 /* Area 0 Inter-Cycle Idle spec. */
-#define SH7750_WCR1_A0IW_S 0
-
-/* Wait Control Register 2 - WCR2 */
-#define SH7750_WCR2_REGOFS 0x80000C /* offset */
-#define SH7750_WCR2 SH7750_P4_REG32(SH7750_WCR2_REGOFS)
-#define SH7750_WCR2_A7 SH7750_A7_REG32(SH7750_WCR2_REGOFS)
-
-#define SH7750_WCR2_A6W 0xE0000000 /* Area 6 Wait Control */
-#define SH7750_WCR2_A6W_S 29
-#define SH7750_WCR2_A6B 0x1C000000 /* Area 6 Burst Pitch */
-#define SH7750_WCR2_A6B_S 26
-#define SH7750_WCR2_A5W 0x03800000 /* Area 5 Wait Control */
-#define SH7750_WCR2_A5W_S 23
-#define SH7750_WCR2_A5B 0x00700000 /* Area 5 Burst Pitch */
-#define SH7750_WCR2_A5B_S 20
-#define SH7750_WCR2_A4W 0x000E0000 /* Area 4 Wait Control */
-#define SH7750_WCR2_A4W_S 17
-#define SH7750_WCR2_A3W 0x0000E000 /* Area 3 Wait Control */
-#define SH7750_WCR2_A3W_S 13
-#define SH7750_WCR2_A2W 0x00000E00 /* Area 2 Wait Control */
-#define SH7750_WCR2_A2W_S 9
-#define SH7750_WCR2_A1W 0x000001C0 /* Area 1 Wait Control */
-#define SH7750_WCR2_A1W_S 6
-#define SH7750_WCR2_A0W 0x00000038 /* Area 0 Wait Control */
-#define SH7750_WCR2_A0W_S 3
-#define SH7750_WCR2_A0B 0x00000007 /* Area 0 Burst Pitch */
-#define SH7750_WCR2_A0B_S 0
-
-#define SH7750_WCR2_WS0 0 /* 0 wait states inserted */
-#define SH7750_WCR2_WS1 1 /* 1 wait states inserted */
-#define SH7750_WCR2_WS2 2 /* 2 wait states inserted */
-#define SH7750_WCR2_WS3 3 /* 3 wait states inserted */
-#define SH7750_WCR2_WS6 4 /* 6 wait states inserted */
-#define SH7750_WCR2_WS9 5 /* 9 wait states inserted */
-#define SH7750_WCR2_WS12 6 /* 12 wait states inserted */
-#define SH7750_WCR2_WS15 7 /* 15 wait states inserted */
-
-#define SH7750_WCR2_BPWS0 0 /* 0 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS1 1 /* 1 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS2 2 /* 2 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS3 3 /* 3 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS4 4 /* 4 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS5 5 /* 5 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS6 6 /* 6 wait states inserted from 2nd access */
-#define SH7750_WCR2_BPWS7 7 /* 7 wait states inserted from 2nd access */
-
-/* DRAM CAS\ Assertion Delay (area 3,2) */
-#define SH7750_WCR2_DRAM_CAS_ASW1 0 /* 1 cycle */
-#define SH7750_WCR2_DRAM_CAS_ASW2 1 /* 2 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW3 2 /* 3 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW4 3 /* 4 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW7 4 /* 7 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW10 5 /* 10 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW13 6 /* 13 cycles */
-#define SH7750_WCR2_DRAM_CAS_ASW16 7 /* 16 cycles */
-
-/* SDRAM CAS\ Latency Cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT1 1 /* 1 cycle */
-#define SH7750_WCR2_SDRAM_CAS_LAT2 2 /* 2 cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT3 3 /* 3 cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT4 4 /* 4 cycles */
-#define SH7750_WCR2_SDRAM_CAS_LAT5 5 /* 5 cycles */
-
-/* Wait Control Register 3 - WCR3 */
-#define SH7750_WCR3_REGOFS 0x800010 /* offset */
-#define SH7750_WCR3 SH7750_P4_REG32(SH7750_WCR3_REGOFS)
-#define SH7750_WCR3_A7 SH7750_A7_REG32(SH7750_WCR3_REGOFS)
-
-#define SH7750_WCR3_A6S 0x04000000 /* Area 6 Write Strobe Setup time */
-#define SH7750_WCR3_A6H 0x03000000 /* Area 6 Data Hold Time */
-#define SH7750_WCR3_A6H_S 24
-#define SH7750_WCR3_A5S 0x00400000 /* Area 5 Write Strobe Setup time */
-#define SH7750_WCR3_A5H 0x00300000 /* Area 5 Data Hold Time */
-#define SH7750_WCR3_A5H_S 20
-#define SH7750_WCR3_A4S 0x00040000 /* Area 4 Write Strobe Setup time */
-#define SH7750_WCR3_A4H 0x00030000 /* Area 4 Data Hold Time */
-#define SH7750_WCR3_A4H_S 16
-#define SH7750_WCR3_A3S 0x00004000 /* Area 3 Write Strobe Setup time */
-#define SH7750_WCR3_A3H 0x00003000 /* Area 3 Data Hold Time */
-#define SH7750_WCR3_A3H_S 12
-#define SH7750_WCR3_A2S 0x00000400 /* Area 2 Write Strobe Setup time */
-#define SH7750_WCR3_A2H 0x00000300 /* Area 2 Data Hold Time */
-#define SH7750_WCR3_A2H_S 8
-#define SH7750_WCR3_A1S 0x00000040 /* Area 1 Write Strobe Setup time */
-#define SH7750_WCR3_A1H 0x00000030 /* Area 1 Data Hold Time */
-#define SH7750_WCR3_A1H_S 4
-#define SH7750_WCR3_A0S 0x00000004 /* Area 0 Write Strobe Setup time */
-#define SH7750_WCR3_A0H 0x00000003 /* Area 0 Data Hold Time */
-#define SH7750_WCR3_A0H_S 0
-
-#define SH7750_WCR3_DHWS_0 0 /* 0 wait states data hold time */
-#define SH7750_WCR3_DHWS_1 1 /* 1 wait states data hold time */
-#define SH7750_WCR3_DHWS_2 2 /* 2 wait states data hold time */
-#define SH7750_WCR3_DHWS_3 3 /* 3 wait states data hold time */
-
-#define SH7750_MCR_REGOFS 0x800014 /* offset */
-#define SH7750_MCR SH7750_P4_REG32(SH7750_MCR_REGOFS)
-#define SH7750_MCR_A7 SH7750_A7_REG32(SH7750_MCR_REGOFS)
-
-#define SH7750_MCR_RASD 0x80000000 /* RAS Down mode */
-#define SH7750_MCR_MRSET 0x40000000 /* SDRAM Mode Register Set */
-#define SH7750_MCR_PALL 0x00000000 /* SDRAM Precharge All cmd. Mode */
-#define SH7750_MCR_TRC 0x38000000 /* RAS Precharge Time at End of
- Refresh: */
-#define SH7750_MCR_TRC_0 0x00000000 /* 0 */
-#define SH7750_MCR_TRC_3 0x08000000 /* 3 */
-#define SH7750_MCR_TRC_6 0x10000000 /* 6 */
-#define SH7750_MCR_TRC_9 0x18000000 /* 9 */
-#define SH7750_MCR_TRC_12 0x20000000 /* 12 */
-#define SH7750_MCR_TRC_15 0x28000000 /* 15 */
-#define SH7750_MCR_TRC_18 0x30000000 /* 18 */
-#define SH7750_MCR_TRC_21 0x38000000 /* 21 */
-
-#define SH7750_MCR_TCAS 0x00800000 /* CAS Negation Period */
-#define SH7750_MCR_TCAS_1 0x00000000 /* 1 */
-#define SH7750_MCR_TCAS_2 0x00800000 /* 2 */
-
-#define SH7750_MCR_TPC 0x00380000 /* DRAM: RAS Precharge Period
- SDRAM: minimum number of cycles
- until the next bank active cmd
- is output after precharging */
-#define SH7750_MCR_TPC_S 19
-#define SH7750_MCR_TPC_SDRAM_1 0x00000000 /* 1 cycle */
-#define SH7750_MCR_TPC_SDRAM_2 0x00080000 /* 2 cycles */
-#define SH7750_MCR_TPC_SDRAM_3 0x00100000 /* 3 cycles */
-#define SH7750_MCR_TPC_SDRAM_4 0x00180000 /* 4 cycles */
-#define SH7750_MCR_TPC_SDRAM_5 0x00200000 /* 5 cycles */
-#define SH7750_MCR_TPC_SDRAM_6 0x00280000 /* 6 cycles */
-#define SH7750_MCR_TPC_SDRAM_7 0x00300000 /* 7 cycles */
-#define SH7750_MCR_TPC_SDRAM_8 0x00380000 /* 8 cycles */
-
-#define SH7750_MCR_RCD 0x00030000 /* DRAM: RAS-CAS Assertion Delay time
- SDRAM: bank active-read/write cmd
- delay time */
-#define SH7750_MCR_RCD_DRAM_2 0x00000000 /* DRAM delay 2 clocks */
-#define SH7750_MCR_RCD_DRAM_3 0x00010000 /* DRAM delay 3 clocks */
-#define SH7750_MCR_RCD_DRAM_4 0x00020000 /* DRAM delay 4 clocks */
-#define SH7750_MCR_RCD_DRAM_5 0x00030000 /* DRAM delay 5 clocks */
-#define SH7750_MCR_RCD_SDRAM_2 0x00010000 /* DRAM delay 2 clocks */
-#define SH7750_MCR_RCD_SDRAM_3 0x00020000 /* DRAM delay 3 clocks */
-#define SH7750_MCR_RCD_SDRAM_4 0x00030000 /* DRAM delay 4 clocks */
-
-#define SH7750_MCR_TRWL 0x0000E000 /* SDRAM Write Precharge Delay */
-#define SH7750_MCR_TRWL_1 0x00000000 /* 1 */
-#define SH7750_MCR_TRWL_2 0x00002000 /* 2 */
-#define SH7750_MCR_TRWL_3 0x00004000 /* 3 */
-#define SH7750_MCR_TRWL_4 0x00006000 /* 4 */
-#define SH7750_MCR_TRWL_5 0x00008000 /* 5 */
-
-#define SH7750_MCR_TRAS 0x00001C00 /* DRAM: CAS-Before-RAS Refresh RAS
- asserting period
- SDRAM: Command interval after
- synchronous DRAM refresh */
-#define SH7750_MCR_TRAS_DRAM_2 0x00000000 /* 2 */
-#define SH7750_MCR_TRAS_DRAM_3 0x00000400 /* 3 */
-#define SH7750_MCR_TRAS_DRAM_4 0x00000800 /* 4 */
-#define SH7750_MCR_TRAS_DRAM_5 0x00000C00 /* 5 */
-#define SH7750_MCR_TRAS_DRAM_6 0x00001000 /* 6 */
-#define SH7750_MCR_TRAS_DRAM_7 0x00001400 /* 7 */
-#define SH7750_MCR_TRAS_DRAM_8 0x00001800 /* 8 */
-#define SH7750_MCR_TRAS_DRAM_9 0x00001C00 /* 9 */
-
-#define SH7750_MCR_TRAS_SDRAM_TRC_4 0x00000000 /* 4 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_5 0x00000400 /* 5 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_6 0x00000800 /* 6 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_7 0x00000C00 /* 7 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_8 0x00001000 /* 8 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_9 0x00001400 /* 9 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_10 0x00001800 /* 10 + TRC */
-#define SH7750_MCR_TRAS_SDRAM_TRC_11 0x00001C00 /* 11 + TRC */
-
-#define SH7750_MCR_BE 0x00000200 /* Burst Enable */
-#define SH7750_MCR_SZ 0x00000180 /* Memory Data Size */
-#define SH7750_MCR_SZ_64 0x00000000 /* 64 bits */
-#define SH7750_MCR_SZ_16 0x00000100 /* 16 bits */
-#define SH7750_MCR_SZ_32 0x00000180 /* 32 bits */
-
-#define SH7750_MCR_AMX 0x00000078 /* Address Multiplexing */
-#define SH7750_MCR_AMX_S 3
-#define SH7750_MCR_AMX_DRAM_8BIT_COL 0x00000000 /* 8-bit column addr */
-#define SH7750_MCR_AMX_DRAM_9BIT_COL 0x00000008 /* 9-bit column addr */
-#define SH7750_MCR_AMX_DRAM_10BIT_COL 0x00000010 /* 10-bit column addr */
-#define SH7750_MCR_AMX_DRAM_11BIT_COL 0x00000018 /* 11-bit column addr */
-#define SH7750_MCR_AMX_DRAM_12BIT_COL 0x00000020 /* 12-bit column addr */
-/* See SH7750 Hardware Manual for SDRAM address multiplexor selection */
-
-#define SH7750_MCR_RFSH 0x00000004 /* Refresh Control */
-#define SH7750_MCR_RMODE 0x00000002 /* Refresh Mode: */
-#define SH7750_MCR_RMODE_NORMAL 0x00000000 /* Normal Refresh Mode */
-#define SH7750_MCR_RMODE_SELF 0x00000002 /* Self-Refresh Mode */
-#define SH7750_MCR_RMODE_EDO 0x00000001 /* EDO Mode */
-
-/* SDRAM Mode Set address */
-#define SH7750_SDRAM_MODE_A2_BASE 0xFF900000
-#define SH7750_SDRAM_MODE_A3_BASE 0xFF940000
-#define SH7750_SDRAM_MODE_A2_32BIT(x) (SH7750_SDRAM_MODE_A2_BASE + ((x) << 2))
-#define SH7750_SDRAM_MODE_A3_32BIT(x) (SH7750_SDRAM_MODE_A3_BASE + ((x) << 2))
-#define SH7750_SDRAM_MODE_A2_64BIT(x) (SH7750_SDRAM_MODE_A2_BASE + ((x) << 3))
-#define SH7750_SDRAM_MODE_A3_64BIT(x) (SH7750_SDRAM_MODE_A3_BASE + ((x) << 3))
-
-
-/* PCMCIA Control Register (half) - PCR */
-#define SH7750_PCR_REGOFS 0x800018 /* offset */
-#define SH7750_PCR SH7750_P4_REG32(SH7750_PCR_REGOFS)
-#define SH7750_PCR_A7 SH7750_A7_REG32(SH7750_PCR_REGOFS)
-
-#define SH7750_PCR_A5PCW 0xC000 /* Area 5 PCMCIA Wait - Number of wait
- states to be added to the number of
- waits specified by WCR2 in a low-speed
- PCMCIA wait cycle */
-#define SH7750_PCR_A5PCW_0 0x0000 /* 0 waits inserted */
-#define SH7750_PCR_A5PCW_15 0x4000 /* 15 waits inserted */
-#define SH7750_PCR_A5PCW_30 0x8000 /* 30 waits inserted */
-#define SH7750_PCR_A5PCW_50 0xC000 /* 50 waits inserted */
-
-#define SH7750_PCR_A6PCW 0x3000 /* Area 6 PCMCIA Wait - Number of wait
- states to be added to the number of
- waits specified by WCR2 in a low-speed
- PCMCIA wait cycle */
-#define SH7750_PCR_A6PCW_0 0x0000 /* 0 waits inserted */
-#define SH7750_PCR_A6PCW_15 0x1000 /* 15 waits inserted */
-#define SH7750_PCR_A6PCW_30 0x2000 /* 30 waits inserted */
-#define SH7750_PCR_A6PCW_50 0x3000 /* 50 waits inserted */
-
-#define SH7750_PCR_A5TED 0x0E00 /* Area 5 Address-OE\/WE\ Assertion Delay,
- delay time from address output to
- OE\/WE\ assertion on the connected
- PCMCIA interface */
-#define SH7750_PCR_A5TED_S 9
-#define SH7750_PCR_A6TED 0x01C0 /* Area 6 Address-OE\/WE\ Assertion Delay */
-#define SH7750_PCR_A6TED_S 6
-
-#define SH7750_PCR_TED_0WS 0 /* 0 Waits inserted */
-#define SH7750_PCR_TED_1WS 1 /* 1 Waits inserted */
-#define SH7750_PCR_TED_2WS 2 /* 2 Waits inserted */
-#define SH7750_PCR_TED_3WS 3 /* 3 Waits inserted */
-#define SH7750_PCR_TED_6WS 4 /* 6 Waits inserted */
-#define SH7750_PCR_TED_9WS 5 /* 9 Waits inserted */
-#define SH7750_PCR_TED_12WS 6 /* 12 Waits inserted */
-#define SH7750_PCR_TED_15WS 7 /* 15 Waits inserted */
-
-#define SH7750_PCR_A5TEH 0x0038 /* Area 5 OE\/WE\ Negation Address delay,
- address hold delay time from OE\/WE\
- negation in a write on the connected
- PCMCIA interface */
-#define SH7750_PCR_A5TEH_S 3
-
-#define SH7750_PCR_A6TEH 0x0007 /* Area 6 OE\/WE\ Negation Address delay */
-#define SH7750_PCR_A6TEH_S 0
-
-#define SH7750_PCR_TEH_0WS 0 /* 0 Waits inserted */
-#define SH7750_PCR_TEH_1WS 1 /* 1 Waits inserted */
-#define SH7750_PCR_TEH_2WS 2 /* 2 Waits inserted */
-#define SH7750_PCR_TEH_3WS 3 /* 3 Waits inserted */
-#define SH7750_PCR_TEH_6WS 4 /* 6 Waits inserted */
-#define SH7750_PCR_TEH_9WS 5 /* 9 Waits inserted */
-#define SH7750_PCR_TEH_12WS 6 /* 12 Waits inserted */
-#define SH7750_PCR_TEH_15WS 7 /* 15 Waits inserted */
-
-/* Refresh Timer Control/Status Register (half) - RTSCR */
-#define SH7750_RTCSR_REGOFS 0x80001C /* offset */
-#define SH7750_RTCSR SH7750_P4_REG32(SH7750_RTCSR_REGOFS)
-#define SH7750_RTCSR_A7 SH7750_A7_REG32(SH7750_RTCSR_REGOFS)
-
-#define SH7750_RTCSR_KEY 0xA500 /* RTCSR write key */
-#define SH7750_RTCSR_CMF 0x0080 /* Compare-Match Flag (indicates a
- match between the refresh timer
- counter and refresh time constant) */
-#define SH7750_RTCSR_CMIE 0x0040 /* Compare-Match Interrupt Enable */
-#define SH7750_RTCSR_CKS 0x0038 /* Refresh Counter Clock Selects */
-#define SH7750_RTCSR_CKS_DIS 0x0000 /* Clock Input Disabled */
-#define SH7750_RTCSR_CKS_CKIO_DIV4 0x0008 /* Bus Clock / 4 */
-#define SH7750_RTCSR_CKS_CKIO_DIV16 0x0010 /* Bus Clock / 16 */
-#define SH7750_RTCSR_CKS_CKIO_DIV64 0x0018 /* Bus Clock / 64 */
-#define SH7750_RTCSR_CKS_CKIO_DIV256 0x0020 /* Bus Clock / 256 */
-#define SH7750_RTCSR_CKS_CKIO_DIV1024 0x0028 /* Bus Clock / 1024 */
-#define SH7750_RTCSR_CKS_CKIO_DIV2048 0x0030 /* Bus Clock / 2048 */
-#define SH7750_RTCSR_CKS_CKIO_DIV4096 0x0038 /* Bus Clock / 4096 */
-
-#define SH7750_RTCSR_OVF 0x0004 /* Refresh Count Overflow Flag */
-#define SH7750_RTCSR_OVIE 0x0002 /* Refresh Count Overflow Interrupt
- Enable */
-#define SH7750_RTCSR_LMTS 0x0001 /* Refresh Count Overflow Limit Select */
-#define SH7750_RTCSR_LMTS_1024 0x0000 /* Count Limit is 1024 */
-#define SH7750_RTCSR_LMTS_512 0x0001 /* Count Limit is 512 */
-
-/* Refresh Timer Counter (half) - RTCNT */
-#define SH7750_RTCNT_REGOFS 0x800020 /* offset */
-#define SH7750_RTCNT SH7750_P4_REG32(SH7750_RTCNT_REGOFS)
-#define SH7750_RTCNT_A7 SH7750_A7_REG32(SH7750_RTCNT_REGOFS)
-
-#define SH7750_RTCNT_KEY 0xA500 /* RTCNT write key */
-
-/* Refresh Time Constant Register (half) - RTCOR */
-#define SH7750_RTCOR_REGOFS 0x800024 /* offset */
-#define SH7750_RTCOR SH7750_P4_REG32(SH7750_RTCOR_REGOFS)
-#define SH7750_RTCOR_A7 SH7750_A7_REG32(SH7750_RTCOR_REGOFS)
-
-#define SH7750_RTCOR_KEY 0xA500 /* RTCOR write key */
-
-/* Refresh Count Register (half) - RFCR */
-#define SH7750_RFCR_REGOFS 0x800028 /* offset */
-#define SH7750_RFCR SH7750_P4_REG32(SH7750_RFCR_REGOFS)
-#define SH7750_RFCR_A7 SH7750_A7_REG32(SH7750_RFCR_REGOFS)
-
-#define SH7750_RFCR_KEY 0xA400 /* RFCR write key */
-
-/*
- * Direct Memory Access Controller (DMAC)
- */
-
-/* DMA Source Address Register - SAR0, SAR1, SAR2, SAR3 */
-#define SH7750_SAR_REGOFS(n) (0xA00000 + ((n)*16)) /* offset */
-#define SH7750_SAR(n) SH7750_P4_REG32(SH7750_SAR_REGOFS(n))
-#define SH7750_SAR_A7(n) SH7750_A7_REG32(SH7750_SAR_REGOFS(n))
-#define SH7750_SAR0 SH7750_SAR(0)
-#define SH7750_SAR1 SH7750_SAR(1)
-#define SH7750_SAR2 SH7750_SAR(2)
-#define SH7750_SAR3 SH7750_SAR(3)
-#define SH7750_SAR0_A7 SH7750_SAR_A7(0)
-#define SH7750_SAR1_A7 SH7750_SAR_A7(1)
-#define SH7750_SAR2_A7 SH7750_SAR_A7(2)
-#define SH7750_SAR3_A7 SH7750_SAR_A7(3)
-
-/* DMA Destination Address Register - DAR0, DAR1, DAR2, DAR3 */
-#define SH7750_DAR_REGOFS(n) (0xA00004 + ((n)*16)) /* offset */
-#define SH7750_DAR(n) SH7750_P4_REG32(SH7750_DAR_REGOFS(n))
-#define SH7750_DAR_A7(n) SH7750_A7_REG32(SH7750_DAR_REGOFS(n))
-#define SH7750_DAR0 SH7750_DAR(0)
-#define SH7750_DAR1 SH7750_DAR(1)
-#define SH7750_DAR2 SH7750_DAR(2)
-#define SH7750_DAR3 SH7750_DAR(3)
-#define SH7750_DAR0_A7 SH7750_DAR_A7(0)
-#define SH7750_DAR1_A7 SH7750_DAR_A7(1)
-#define SH7750_DAR2_A7 SH7750_DAR_A7(2)
-#define SH7750_DAR3_A7 SH7750_DAR_A7(3)
-
-/* DMA Transfer Count Register - DMATCR0, DMATCR1, DMATCR2, DMATCR3 */
-#define SH7750_DMATCR_REGOFS(n) (0xA00008 + ((n)*16)) /* offset */
-#define SH7750_DMATCR(n) SH7750_P4_REG32(SH7750_DMATCR_REGOFS(n))
-#define SH7750_DMATCR_A7(n) SH7750_A7_REG32(SH7750_DMATCR_REGOFS(n))
-#define SH7750_DMATCR0_P4 SH7750_DMATCR(0)
-#define SH7750_DMATCR1_P4 SH7750_DMATCR(1)
-#define SH7750_DMATCR2_P4 SH7750_DMATCR(2)
-#define SH7750_DMATCR3_P4 SH7750_DMATCR(3)
-#define SH7750_DMATCR0_A7 SH7750_DMATCR_A7(0)
-#define SH7750_DMATCR1_A7 SH7750_DMATCR_A7(1)
-#define SH7750_DMATCR2_A7 SH7750_DMATCR_A7(2)
-#define SH7750_DMATCR3_A7 SH7750_DMATCR_A7(3)
-
-/* DMA Channel Control Register - CHCR0, CHCR1, CHCR2, CHCR3 */
-#define SH7750_CHCR_REGOFS(n) (0xA0000C + ((n)*16)) /* offset */
-#define SH7750_CHCR(n) SH7750_P4_REG32(SH7750_CHCR_REGOFS(n))
-#define SH7750_CHCR_A7(n) SH7750_A7_REG32(SH7750_CHCR_REGOFS(n))
-#define SH7750_CHCR0 SH7750_CHCR(0)
-#define SH7750_CHCR1 SH7750_CHCR(1)
-#define SH7750_CHCR2 SH7750_CHCR(2)
-#define SH7750_CHCR3 SH7750_CHCR(3)
-#define SH7750_CHCR0_A7 SH7750_CHCR_A7(0)
-#define SH7750_CHCR1_A7 SH7750_CHCR_A7(1)
-#define SH7750_CHCR2_A7 SH7750_CHCR_A7(2)
-#define SH7750_CHCR3_A7 SH7750_CHCR_A7(3)
-
-#define SH7750_CHCR_SSA 0xE0000000 /* Source Address Space Attribute */
-#define SH7750_CHCR_SSA_PCMCIA 0x00000000 /* Reserved in PCMCIA access */
-#define SH7750_CHCR_SSA_DYNBSZ 0x20000000 /* Dynamic Bus Sizing I/O space */
-#define SH7750_CHCR_SSA_IO8 0x40000000 /* 8-bit I/O space */
-#define SH7750_CHCR_SSA_IO16 0x60000000 /* 16-bit I/O space */
-#define SH7750_CHCR_SSA_CMEM8 0x80000000 /* 8-bit common memory space */
-#define SH7750_CHCR_SSA_CMEM16 0xA0000000 /* 16-bit common memory space */
-#define SH7750_CHCR_SSA_AMEM8 0xC0000000 /* 8-bit attribute memory space */
-#define SH7750_CHCR_SSA_AMEM16 0xE0000000 /* 16-bit attribute memory space */
-
-#define SH7750_CHCR_STC 0x10000000 /* Source Address Wait Control Select,
- specifies CS5 or CS6 space wait
- control for PCMCIA access */
-
-#define SH7750_CHCR_DSA 0x0E000000 /* Source Address Space Attribute */
-#define SH7750_CHCR_DSA_PCMCIA 0x00000000 /* Reserved in PCMCIA access */
-#define SH7750_CHCR_DSA_DYNBSZ 0x02000000 /* Dynamic Bus Sizing I/O space */
-#define SH7750_CHCR_DSA_IO8 0x04000000 /* 8-bit I/O space */
-#define SH7750_CHCR_DSA_IO16 0x06000000 /* 16-bit I/O space */
-#define SH7750_CHCR_DSA_CMEM8 0x08000000 /* 8-bit common memory space */
-#define SH7750_CHCR_DSA_CMEM16 0x0A000000 /* 16-bit common memory space */
-#define SH7750_CHCR_DSA_AMEM8 0x0C000000 /* 8-bit attribute memory space */
-#define SH7750_CHCR_DSA_AMEM16 0x0E000000 /* 16-bit attribute memory space */
-
-#define SH7750_CHCR_DTC 0x01000000 /* Destination Address Wait Control
- Select, specifies CS5 or CS6
- space wait control for PCMCIA
- access */
-
-#define SH7750_CHCR_DS 0x00080000 /* DREQ\ Select : */
-#define SH7750_CHCR_DS_LOWLVL 0x00000000 /* Low Level Detection */
-#define SH7750_CHCR_DS_FALL 0x00080000 /* Falling Edge Detection */
-
-#define SH7750_CHCR_RL 0x00040000 /* Request Check Level: */
-#define SH7750_CHCR_RL_ACTH 0x00000000 /* DRAK is an active high out */
-#define SH7750_CHCR_RL_ACTL 0x00040000 /* DRAK is an active low out */
-
-#define SH7750_CHCR_AM 0x00020000 /* Acknowledge Mode: */
-#define SH7750_CHCR_AM_RD 0x00000000 /* DACK is output in read cycle */
-#define SH7750_CHCR_AM_WR 0x00020000 /* DACK is output in write cycle */
-
-#define SH7750_CHCR_AL 0x00010000 /* Acknowledge Level: */
-#define SH7750_CHCR_AL_ACTH 0x00000000 /* DACK is an active high out */
-#define SH7750_CHCR_AL_ACTL 0x00010000 /* DACK is an active low out */
-
-#define SH7750_CHCR_DM 0x0000C000 /* Destination Address Mode: */
-#define SH7750_CHCR_DM_FIX 0x00000000 /* Destination Addr Fixed */
-#define SH7750_CHCR_DM_INC 0x00004000 /* Destination Addr Incremented */
-#define SH7750_CHCR_DM_DEC 0x00008000 /* Destination Addr Decremented */
-
-#define SH7750_CHCR_SM 0x00003000 /* Source Address Mode: */
-#define SH7750_CHCR_SM_FIX 0x00000000 /* Source Addr Fixed */
-#define SH7750_CHCR_SM_INC 0x00001000 /* Source Addr Incremented */
-#define SH7750_CHCR_SM_DEC 0x00002000 /* Source Addr Decremented */
-
-#define SH7750_CHCR_RS 0x00000F00 /* Request Source Select: */
-#define SH7750_CHCR_RS_ER_DA_EA_TO_EA 0x000 /* External Request, Dual Address
- Mode (External Addr Space->
- External Addr Space) */
-#define SH7750_CHCR_RS_ER_SA_EA_TO_ED 0x200 /* External Request, Single
- Address Mode (External Addr
- Space -> External Device) */
-#define SH7750_CHCR_RS_ER_SA_ED_TO_EA 0x300 /* External Request, Single
- Address Mode, (External
- Device -> External Addr
- Space) */
-#define SH7750_CHCR_RS_AR_EA_TO_EA 0x400 /* Auto-Request (External Addr
- Space -> External Addr Space) */
-
-#define SH7750_CHCR_RS_AR_EA_TO_OCP 0x500 /* Auto-Request (External Addr
- Space -> On-chip Peripheral
- Module) */
-#define SH7750_CHCR_RS_AR_OCP_TO_EA 0x600 /* Auto-Request (On-chip
- Peripheral Module ->
- External Addr Space */
-#define SH7750_CHCR_RS_SCITX_EA_TO_SC 0x800 /* SCI Transmit-Data-Empty intr
- transfer request (external
- address space -> SCTDR1) */
-#define SH7750_CHCR_RS_SCIRX_SC_TO_EA 0x900 /* SCI Receive-Data-Full intr
- transfer request (SCRDR1 ->
- External Addr Space) */
-#define SH7750_CHCR_RS_SCIFTX_EA_TO_SC 0xA00 /* SCIF Transmit-Data-Empty intr
- transfer request (external
- address space -> SCFTDR1) */
-#define SH7750_CHCR_RS_SCIFRX_SC_TO_EA 0xB00 /* SCIF Receive-Data-Full intr
- transfer request (SCFRDR2 ->
- External Addr Space) */
-#define SH7750_CHCR_RS_TMU2_EA_TO_EA 0xC00 /* TMU Channel 2 (input capture
- interrupt), (external address
- space -> external address
- space) */
-#define SH7750_CHCR_RS_TMU2_EA_TO_OCP 0xD00 /* TMU Channel 2 (input capture
- interrupt), (external address
- space -> on-chip peripheral
- module) */
-#define SH7750_CHCR_RS_TMU2_OCP_TO_EA 0xE00 /* TMU Channel 2 (input capture
- interrupt), (on-chip
- peripheral module -> external
- address space) */
-
-#define SH7750_CHCR_TM 0x00000080 /* Transmit mode: */
-#define SH7750_CHCR_TM_CSTEAL 0x00000000 /* Cycle Steal Mode */
-#define SH7750_CHCR_TM_BURST 0x00000080 /* Burst Mode */
-
-#define SH7750_CHCR_TS 0x00000070 /* Transmit Size: */
-#define SH7750_CHCR_TS_QUAD 0x00000000 /* Quadword Size (64 bits) */
-#define SH7750_CHCR_TS_BYTE 0x00000010 /* Byte Size (8 bit) */
-#define SH7750_CHCR_TS_WORD 0x00000020 /* Word Size (16 bit) */
-#define SH7750_CHCR_TS_LONG 0x00000030 /* Longword Size (32 bit) */
-#define SH7750_CHCR_TS_BLOCK 0x00000040 /* 32-byte block transfer */
-
-#define SH7750_CHCR_IE 0x00000004 /* Interrupt Enable */
-#define SH7750_CHCR_TE 0x00000002 /* Transfer End */
-#define SH7750_CHCR_DE 0x00000001 /* DMAC Enable */
-
-/* DMA Operation Register - DMAOR */
-#define SH7750_DMAOR_REGOFS 0xA00040 /* offset */
-#define SH7750_DMAOR SH7750_P4_REG32(SH7750_DMAOR_REGOFS)
-#define SH7750_DMAOR_A7 SH7750_A7_REG32(SH7750_DMAOR_REGOFS)
-
-#define SH7750_DMAOR_DDT 0x00008000 /* On-Demand Data Transfer Mode */
-
-#define SH7750_DMAOR_PR 0x00000300 /* Priority Mode: */
-#define SH7750_DMAOR_PR_0123 0x00000000 /* CH0 > CH1 > CH2 > CH3 */
-#define SH7750_DMAOR_PR_0231 0x00000100 /* CH0 > CH2 > CH3 > CH1 */
-#define SH7750_DMAOR_PR_2013 0x00000200 /* CH2 > CH0 > CH1 > CH3 */
-#define SH7750_DMAOR_PR_RR 0x00000300 /* Round-robin mode */
-
-#define SH7750_DMAOR_COD 0x00000010 /* Check Overrun for DREQ\ */
-#define SH7750_DMAOR_AE 0x00000004 /* Address Error flag */
-#define SH7750_DMAOR_NMIF 0x00000002 /* NMI Flag */
-#define SH7750_DMAOR_DME 0x00000001 /* DMAC Master Enable */
-
-/*
- * Serial Communication Interface - SCI
- * Serial Communication Interface with FIFO - SCIF
- */
-/* SCI Receive Data Register (byte, read-only) - SCRDR1, SCFRDR2 */
-#define SH7750_SCRDR_REGOFS(n) ((n) == 1 ? 0xE00014 : 0xE80014) /* offset */
-#define SH7750_SCRDR(n) SH7750_P4_REG32(SH7750_SCRDR_REGOFS(n))
-#define SH7750_SCRDR1 SH7750_SCRDR(1)
-#define SH7750_SCRDR2 SH7750_SCRDR(2)
-#define SH7750_SCRDR_A7(n) SH7750_A7_REG32(SH7750_SCRDR_REGOFS(n))
-#define SH7750_SCRDR1_A7 SH7750_SCRDR_A7(1)
-#define SH7750_SCRDR2_A7 SH7750_SCRDR_A7(2)
-
-/* SCI Transmit Data Register (byte) - SCTDR1, SCFTDR2 */
-#define SH7750_SCTDR_REGOFS(n) ((n) == 1 ? 0xE0000C : 0xE8000C) /* offset */
-#define SH7750_SCTDR(n) SH7750_P4_REG32(SH7750_SCTDR_REGOFS(n))
-#define SH7750_SCTDR1 SH7750_SCTDR(1)
-#define SH7750_SCTDR2 SH7750_SCTDR(2)
-#define SH7750_SCTDR_A7(n) SH7750_A7_REG32(SH7750_SCTDR_REGOFS(n))
-#define SH7750_SCTDR1_A7 SH7750_SCTDR_A7(1)
-#define SH7750_SCTDR2_A7 SH7750_SCTDR_A7(2)
-
-/* SCI Serial Mode Register - SCSMR1(byte), SCSMR2(half) */
-#define SH7750_SCSMR_REGOFS(n) ((n) == 1 ? 0xE00000 : 0xE80000) /* offset */
-#define SH7750_SCSMR(n) SH7750_P4_REG32(SH7750_SCSMR_REGOFS(n))
-#define SH7750_SCSMR1 SH7750_SCSMR(1)
-#define SH7750_SCSMR2 SH7750_SCSMR(2)
-#define SH7750_SCSMR_A7(n) SH7750_A7_REG32(SH7750_SCSMR_REGOFS(n))
-#define SH7750_SCSMR1_A7 SH7750_SCSMR_A7(1)
-#define SH7750_SCSMR2_A7 SH7750_SCSMR_A7(2)
-
-#define SH7750_SCSMR1_CA 0x80 /* Communication Mode (C/A\): */
-#define SH7750_SCSMR1_CA_ASYNC 0x00 /* Asynchronous Mode */
-#define SH7750_SCSMR1_CA_SYNC 0x80 /* Synchronous Mode */
-#define SH7750_SCSMR_CHR 0x40 /* Character Length: */
-#define SH7750_SCSMR_CHR_8 0x00 /* 8-bit data */
-#define SH7750_SCSMR_CHR_7 0x40 /* 7-bit data */
-#define SH7750_SCSMR_PE 0x20 /* Parity Enable */
-#define SH7750_SCSMR_PM 0x10 /* Parity Mode: */
-#define SH7750_SCSMR_PM_EVEN 0x00 /* Even Parity */
-#define SH7750_SCSMR_PM_ODD 0x10 /* Odd Parity */
-#define SH7750_SCSMR_STOP 0x08 /* Stop Bit Length: */
-#define SH7750_SCSMR_STOP_1 0x00 /* 1 stop bit */
-#define SH7750_SCSMR_STOP_2 0x08 /* 2 stop bit */
-#define SH7750_SCSMR1_MP 0x04 /* Multiprocessor Mode */
-#define SH7750_SCSMR_CKS 0x03 /* Clock Select */
-#define SH7750_SCSMR_CKS_S 0
-#define SH7750_SCSMR_CKS_DIV1 0x00 /* Periph clock */
-#define SH7750_SCSMR_CKS_DIV4 0x01 /* Periph clock / 4 */
-#define SH7750_SCSMR_CKS_DIV16 0x02 /* Periph clock / 16 */
-#define SH7750_SCSMR_CKS_DIV64 0x03 /* Periph clock / 64 */
-
-/* SCI Serial Control Register - SCSCR1(byte), SCSCR2(half) */
-#define SH7750_SCSCR_REGOFS(n) ((n) == 1 ? 0xE00008 : 0xE80008) /* offset */
-#define SH7750_SCSCR(n) SH7750_P4_REG32(SH7750_SCSCR_REGOFS(n))
-#define SH7750_SCSCR1 SH7750_SCSCR(1)
-#define SH7750_SCSCR2 SH7750_SCSCR(2)
-#define SH7750_SCSCR_A7(n) SH7750_A7_REG32(SH7750_SCSCR_REGOFS(n))
-#define SH7750_SCSCR1_A7 SH7750_SCSCR_A7(1)
-#define SH7750_SCSCR2_A7 SH7750_SCSCR_A7(2)
-
-#define SH7750_SCSCR_TIE 0x80 /* Transmit Interrupt Enable */
-#define SH7750_SCSCR_RIE 0x40 /* Receive Interrupt Enable */
-#define SH7750_SCSCR_TE 0x20 /* Transmit Enable */
-#define SH7750_SCSCR_RE 0x10 /* Receive Enable */
-#define SH7750_SCSCR1_MPIE 0x08 /* Multiprocessor Interrupt Enable */
-#define SH7750_SCSCR2_REIE 0x08 /* Receive Error Interrupt Enable */
-#define SH7750_SCSCR1_TEIE 0x04 /* Transmit End Interrupt Enable */
-#define SH7750_SCSCR1_CKE 0x03 /* Clock Enable: */
-#define SH7750_SCSCR_CKE_INTCLK 0x00 /* Use Internal Clock */
-#define SH7750_SCSCR_CKE_EXTCLK 0x02 /* Use External Clock from SCK */
-#define SH7750_SCSCR1_CKE_ASYNC_SCK_CLKOUT 0x01 /* Use SCK as a clock output
- in asynchronous mode */
-
-/* SCI Serial Status Register - SCSSR1(byte), SCSFR2(half) */
-#define SH7750_SCSSR_REGOFS(n) ((n) == 1 ? 0xE00010 : 0xE80010) /* offset */
-#define SH7750_SCSSR(n) SH7750_P4_REG32(SH7750_SCSSR_REGOFS(n))
-#define SH7750_SCSSR1 SH7750_SCSSR(1)
-#define SH7750_SCSFR2 SH7750_SCSSR(2)
-#define SH7750_SCSSR_A7(n) SH7750_A7_REG32(SH7750_SCSSR_REGOFS(n))
-#define SH7750_SCSSR1_A7 SH7750_SCSSR_A7(1)
-#define SH7750_SCSFR2_A7 SH7750_SCSSR_A7(2)
-
-#define SH7750_SCSSR1_TDRE 0x80 /* Transmit Data Register Empty */
-#define SH7750_SCSSR1_RDRF 0x40 /* Receive Data Register Full */
-#define SH7750_SCSSR1_ORER 0x20 /* Overrun Error */
-#define SH7750_SCSSR1_FER 0x10 /* Framing Error */
-#define SH7750_SCSSR1_PER 0x08 /* Parity Error */
-#define SH7750_SCSSR1_TEND 0x04 /* Transmit End */
-#define SH7750_SCSSR1_MPB 0x02 /* Multiprocessor Bit */
-#define SH7750_SCSSR1_MPBT 0x01 /* Multiprocessor Bit Transfer */
-
-#define SH7750_SCFSR2_PERN 0xF000 /* Number of Parity Errors */
-#define SH7750_SCFSR2_PERN_S 12
-#define SH7750_SCFSR2_FERN 0x0F00 /* Number of Framing Errors */
-#define SH7750_SCFSR2_FERN_S 8
-#define SH7750_SCFSR2_ER 0x0080 /* Receive Error */
-#define SH7750_SCFSR2_TEND 0x0040 /* Transmit End */
-#define SH7750_SCFSR2_TDFE 0x0020 /* Transmit FIFO Data Empty */
-#define SH7750_SCFSR2_BRK 0x0010 /* Break Detect */
-#define SH7750_SCFSR2_FER 0x0008 /* Framing Error */
-#define SH7750_SCFSR2_PER 0x0004 /* Parity Error */
-#define SH7750_SCFSR2_RDF 0x0002 /* Receive FIFO Data Full */
-#define SH7750_SCFSR2_DR 0x0001 /* Receive Data Ready */
-
-/* SCI Serial Port Register - SCSPTR1(byte) */
-#define SH7750_SCSPTR1_REGOFS 0xE0001C /* offset */
-#define SH7750_SCSPTR1 SH7750_P4_REG32(SH7750_SCSPTR1_REGOFS)
-#define SH7750_SCSPTR1_A7 SH7750_A7_REG32(SH7750_SCSPTR1_REGOFS)
-
-#define SH7750_SCSPTR1_EIO 0x80 /* Error Interrupt Only */
-#define SH7750_SCSPTR1_SPB1IO 0x08 /* 1: Output SPB1DT bit to SCK pin */
-#define SH7750_SCSPTR1_SPB1DT 0x04 /* Serial Port Clock Port Data */
-#define SH7750_SCSPTR1_SPB0IO 0x02 /* 1: Output SPB0DT bit to TxD pin */
-#define SH7750_SCSPTR1_SPB0DT 0x01 /* Serial Port Break Data */
-
-/* SCIF Serial Port Register - SCSPTR2(half) */
-#define SH7750_SCSPTR2_REGOFS 0xE80020 /* offset */
-#define SH7750_SCSPTR2 SH7750_P4_REG32(SH7750_SCSPTR2_REGOFS)
-#define SH7750_SCSPTR2_A7 SH7750_A7_REG32(SH7750_SCSPTR2_REGOFS)
-
-#define SH7750_SCSPTR2_RTSIO 0x80 /* 1: Output RTSDT bit to RTS2\ pin */
-#define SH7750_SCSPTR2_RTSDT 0x40 /* RTS Port Data */
-#define SH7750_SCSPTR2_CTSIO 0x20 /* 1: Output CTSDT bit to CTS2\ pin */
-#define SH7750_SCSPTR2_CTSDT 0x10 /* CTS Port Data */
-#define SH7750_SCSPTR2_SPB2IO 0x02 /* 1: Output SPBDT bit to TxD2 pin */
-#define SH7750_SCSPTR2_SPB2DT 0x01 /* Serial Port Break Data */
-
-/* SCI Bit Rate Register - SCBRR1(byte), SCBRR2(byte) */
-#define SH7750_SCBRR_REGOFS(n) ((n) == 1 ? 0xE00004 : 0xE80004) /* offset */
-#define SH7750_SCBRR(n) SH7750_P4_REG32(SH7750_SCBRR_REGOFS(n))
-#define SH7750_SCBRR1 SH7750_SCBRR_P4(1)
-#define SH7750_SCBRR2 SH7750_SCBRR_P4(2)
-#define SH7750_SCBRR_A7(n) SH7750_A7_REG32(SH7750_SCBRR_REGOFS(n))
-#define SH7750_SCBRR1_A7 SH7750_SCBRR_A7(1)
-#define SH7750_SCBRR2_A7 SH7750_SCBRR_A7(2)
-
-/* SCIF FIFO Control Register - SCFCR2(half) */
-#define SH7750_SCFCR2_REGOFS 0xE80018 /* offset */
-#define SH7750_SCFCR2 SH7750_P4_REG32(SH7750_SCFCR2_REGOFS)
-#define SH7750_SCFCR2_A7 SH7750_A7_REG32(SH7750_SCFCR2_REGOFS)
-
-#define SH7750_SCFCR2_RSTRG 0x700 /* RTS2\ Output Active Trigger; RTS2\
- signal goes to high level when the
- number of received data stored in
- FIFO exceeds the trigger number */
-#define SH7750_SCFCR2_RSTRG_15 0x000 /* 15 bytes */
-#define SH7750_SCFCR2_RSTRG_1 0x000 /* 1 byte */
-#define SH7750_SCFCR2_RSTRG_4 0x000 /* 4 bytes */
-#define SH7750_SCFCR2_RSTRG_6 0x000 /* 6 bytes */
-#define SH7750_SCFCR2_RSTRG_8 0x000 /* 8 bytes */
-#define SH7750_SCFCR2_RSTRG_10 0x000 /* 10 bytes */
-#define SH7750_SCFCR2_RSTRG_14 0x000 /* 14 bytes */
-
-#define SH7750_SCFCR2_RTRG 0x0C0 /* Receive FIFO Data Number Trigger,
- Receive Data Full (RDF) Flag sets
- when number of receive data bytes is
- equal or greater than the trigger
- number */
-#define SH7750_SCFCR2_RTRG_1 0x000 /* 1 byte */
-#define SH7750_SCFCR2_RTRG_4 0x040 /* 4 bytes */
-#define SH7750_SCFCR2_RTRG_8 0x080 /* 8 bytes */
-#define SH7750_SCFCR2_RTRG_14 0x0C0 /* 14 bytes */
-
-#define SH7750_SCFCR2_TTRG 0x030 /* Transmit FIFO Data Number Trigger,
- Transmit FIFO Data Register Empty (TDFE)
- flag sets when the number of remaining
- transmit data bytes is equal or less
- than the trigger number */
-#define SH7750_SCFCR2_TTRG_8 0x000 /* 8 bytes */
-#define SH7750_SCFCR2_TTRG_4 0x010 /* 4 bytes */
-#define SH7750_SCFCR2_TTRG_2 0x020 /* 2 bytes */
-#define SH7750_SCFCR2_TTRG_1 0x030 /* 1 byte */
-
-#define SH7750_SCFCR2_MCE 0x008 /* Modem Control Enable */
-#define SH7750_SCFCR2_TFRST 0x004 /* Transmit FIFO Data Register Reset,
- invalidates the transmit data in the
- transmit FIFO */
-#define SH7750_SCFCR2_RFRST 0x002 /* Receive FIFO Data Register Reset,
- invalidates the receive data in the
- receive FIFO data register and resets
- it to the empty state */
-#define SH7750_SCFCR2_LOOP 0x001 /* Loopback Test */
-
-/* SCIF FIFO Data Count Register - SCFDR2(half, read-only) */
-#define SH7750_SCFDR2_REGOFS 0xE8001C /* offset */
-#define SH7750_SCFDR2 SH7750_P4_REG32(SH7750_SCFDR2_REGOFS)
-#define SH7750_SCFDR2_A7 SH7750_A7_REG32(SH7750_SCFDR2_REGOFS)
-
-#define SH7750_SCFDR2_T 0x1F00 /* Number of untransmitted data bytes
- in transmit FIFO */
-#define SH7750_SCFDR2_T_S 8
-#define SH7750_SCFDR2_R 0x001F /* Number of received data bytes in
- receive FIFO */
-#define SH7750_SCFDR2_R_S 0
-
-/* SCIF Line Status Register - SCLSR2(half, read-only) */
-#define SH7750_SCLSR2_REGOFS 0xE80024 /* offset */
-#define SH7750_SCLSR2 SH7750_P4_REG32(SH7750_SCLSR2_REGOFS)
-#define SH7750_SCLSR2_A7 SH7750_A7_REG32(SH7750_SCLSR2_REGOFS)
-
-#define SH7750_SCLSR2_ORER 0x0001 /* Overrun Error */
-
-/*
- * SCI-based Smart Card Interface
- */
-/* Smart Card Mode Register - SCSCMR1(byte) */
-#define SH7750_SCSCMR1_REGOFS 0xE00018 /* offset */
-#define SH7750_SCSCMR1 SH7750_P4_REG32(SH7750_SCSCMR1_REGOFS)
-#define SH7750_SCSCMR1_A7 SH7750_A7_REG32(SH7750_SCSCMR1_REGOFS)
-
-#define SH7750_SCSCMR1_SDIR 0x08 /* Smart Card Data Transfer Direction: */
-#define SH7750_SCSCMR1_SDIR_LSBF 0x00 /* LSB-first */
-#define SH7750_SCSCMR1_SDIR_MSBF 0x08 /* MSB-first */
-
-#define SH7750_SCSCMR1_SINV 0x04 /* Smart Card Data Inversion */
-#define SH7750_SCSCMR1_SMIF 0x01 /* Smart Card Interface Mode Select */
-
-/* Smart-card specific bits in other registers */
-/* SCSMR1: */
-#define SH7750_SCSMR1_GSM 0x80 /* GSM mode select */
-
-/* SCSSR1: */
-#define SH7750_SCSSR1_ERS 0x10 /* Error Signal Status */
-
-/*
- * I/O Ports
- */
-/* Port Control Register A - PCTRA */
-#define SH7750_PCTRA_REGOFS 0x80002C /* offset */
-#define SH7750_PCTRA SH7750_P4_REG32(SH7750_PCTRA_REGOFS)
-#define SH7750_PCTRA_A7 SH7750_A7_REG32(SH7750_PCTRA_REGOFS)
-
-#define SH7750_PCTRA_PBPUP(n) 0 /* Bit n is pulled up */
-#define SH7750_PCTRA_PBNPUP(n) (1 << ((n)*2+1)) /* Bit n is not pulled up */
-#define SH7750_PCTRA_PBINP(n) 0 /* Bit n is an input */
-#define SH7750_PCTRA_PBOUT(n) (1 << ((n)*2)) /* Bit n is an output */
-
-/* Port Data Register A - PDTRA(half) */
-#define SH7750_PDTRA_REGOFS 0x800030 /* offset */
-#define SH7750_PDTRA SH7750_P4_REG32(SH7750_PDTRA_REGOFS)
-#define SH7750_PDTRA_A7 SH7750_A7_REG32(SH7750_PDTRA_REGOFS)
-
-#define SH7750_PDTRA_BIT(n) (1 << (n))
-
-/* Port Control Register B - PCTRB */
-#define SH7750_PCTRB_REGOFS 0x800040 /* offset */
-#define SH7750_PCTRB SH7750_P4_REG32(SH7750_PCTRB_REGOFS)
-#define SH7750_PCTRB_A7 SH7750_A7_REG32(SH7750_PCTRB_REGOFS)
-
-#define SH7750_PCTRB_PBPUP(n) 0 /* Bit n is pulled up */
-#define SH7750_PCTRB_PBNPUP(n) (1 << ((n-16)*2+1)) /* Bit n is not pulled up */
-#define SH7750_PCTRB_PBINP(n) 0 /* Bit n is an input */
-#define SH7750_PCTRB_PBOUT(n) (1 << ((n-16)*2)) /* Bit n is an output */
-
-/* Port Data Register B - PDTRB(half) */
-#define SH7750_PDTRB_REGOFS 0x800044 /* offset */
-#define SH7750_PDTRB SH7750_P4_REG32(SH7750_PDTRB_REGOFS)
-#define SH7750_PDTRB_A7 SH7750_A7_REG32(SH7750_PDTRB_REGOFS)
-
-#define SH7750_PDTRB_BIT(n) (1 << ((n)-16))
-
-/* GPIO Interrupt Control Register - GPIOIC(half) */
-#define SH7750_GPIOIC_REGOFS 0x800048 /* offset */
-#define SH7750_GPIOIC SH7750_P4_REG32(SH7750_GPIOIC_REGOFS)
-#define SH7750_GPIOIC_A7 SH7750_A7_REG32(SH7750_GPIOIC_REGOFS)
-
-#define SH7750_GPIOIC_PTIREN(n) (1 << (n)) /* Port n is used as a GPIO int */
-
-/*
- * Interrupt Controller - INTC
- */
-/* Interrupt Control Register - ICR (half) */
-#define SH7750_ICR_REGOFS 0xD00000 /* offset */
-#define SH7750_ICR SH7750_P4_REG32(SH7750_ICR_REGOFS)
-#define SH7750_ICR_A7 SH7750_A7_REG32(SH7750_ICR_REGOFS)
-
-#define SH7750_ICR_NMIL 0x8000 /* NMI Input Level */
-#define SH7750_ICR_MAI 0x4000 /* NMI Interrupt Mask */
-
-#define SH7750_ICR_NMIB 0x0200 /* NMI Block Mode: */
-#define SH7750_ICR_NMIB_BLK 0x0000 /* NMI requests held pending while
- SR.BL bit is set to 1 */
-#define SH7750_ICR_NMIB_NBLK 0x0200 /* NMI requests detected when SR.BL bit
- set to 1 */
-
-#define SH7750_ICR_NMIE 0x0100 /* NMI Edge Select: */
-#define SH7750_ICR_NMIE_FALL 0x0000 /* Interrupt request detected on falling
- edge of NMI input */
-#define SH7750_ICR_NMIE_RISE 0x0100 /* Interrupt request detected on rising
- edge of NMI input */
-
-#define SH7750_ICR_IRLM 0x0080 /* IRL Pin Mode: */
-#define SH7750_ICR_IRLM_ENC 0x0000 /* IRL\ pins used as a level-encoded
- interrupt requests */
-#define SH7750_ICR_IRLM_RAW 0x0080 /* IRL\ pins used as a four independent
- interrupt requests */
-
-/* Interrupt Priority Register A - IPRA (half) */
-#define SH7750_IPRA_REGOFS 0xD00004 /* offset */
-#define SH7750_IPRA SH7750_P4_REG32(SH7750_IPRA_REGOFS)
-#define SH7750_IPRA_A7 SH7750_A7_REG32(SH7750_IPRA_REGOFS)
-
-#define SH7750_IPRA_TMU0 0xF000 /* TMU0 interrupt priority */
-#define SH7750_IPRA_TMU0_S 12
-#define SH7750_IPRA_TMU1 0x0F00 /* TMU1 interrupt priority */
-#define SH7750_IPRA_TMU1_S 8
-#define SH7750_IPRA_TMU2 0x00F0 /* TMU2 interrupt priority */
-#define SH7750_IPRA_TMU2_S 4
-#define SH7750_IPRA_RTC 0x000F /* RTC interrupt priority */
-#define SH7750_IPRA_RTC_S 0
-
-/* Interrupt Priority Register B - IPRB (half) */
-#define SH7750_IPRB_REGOFS 0xD00008 /* offset */
-#define SH7750_IPRB SH7750_P4_REG32(SH7750_IPRB_REGOFS)
-#define SH7750_IPRB_A7 SH7750_A7_REG32(SH7750_IPRB_REGOFS)
-
-#define SH7750_IPRB_WDT 0xF000 /* WDT interrupt priority */
-#define SH7750_IPRB_WDT_S 12
-#define SH7750_IPRB_REF 0x0F00 /* Memory Refresh unit interrupt
- priority */
-#define SH7750_IPRB_REF_S 8
-#define SH7750_IPRB_SCI1 0x00F0 /* SCI1 interrupt priority */
-#define SH7750_IPRB_SCI1_S 4
-
-/* Interrupt Priority Register ó - IPRó (half) */
-#define SH7750_IPRC_REGOFS 0xD00004 /* offset */
-#define SH7750_IPRC SH7750_P4_REG32(SH7750_IPRC_REGOFS)
-#define SH7750_IPRC_A7 SH7750_A7_REG32(SH7750_IPRC_REGOFS)
-
-#define SH7750_IPRC_GPIO 0xF000 /* GPIO interrupt priority */
-#define SH7750_IPRC_GPIO_S 12
-#define SH7750_IPRC_DMAC 0x0F00 /* DMAC interrupt priority */
-#define SH7750_IPRC_DMAC_S 8
-#define SH7750_IPRC_SCIF 0x00F0 /* SCIF interrupt priority */
-#define SH7750_IPRC_SCIF_S 4
-#define SH7750_IPRC_HUDI 0x000F /* H-UDI interrupt priority */
-#define SH7750_IPRC_HUDI_S 0
-
-
-/*
- * User Break Controller registers
- */
-#define SH7750_BARA 0x200000 /* Break address regiser A */
-#define SH7750_BAMRA 0x200004 /* Break address mask regiser A */
-#define SH7750_BBRA 0x200008 /* Break bus cycle regiser A */
-#define SH7750_BARB 0x20000c /* Break address regiser B */
-#define SH7750_BAMRB 0x200010 /* Break address mask regiser B */
-#define SH7750_BBRB 0x200014 /* Break bus cycle regiser B */
-#define SH7750_BASRB 0x000018 /* Break ASID regiser B */
-#define SH7750_BDRB 0x200018 /* Break data regiser B */
-#define SH7750_BDMRB 0x20001c /* Break data mask regiser B */
-#define SH7750_BRCR 0x200020 /* Break control register */
-
-#define SH7750_BRCR_UDBE 0x0001 /* User break debug enable bit */
-
-/*
- * Missing in RTEMS, added for QEMU
- */
-#define SH7750_BCR3_A7 0x1f800050
-#define SH7750_BCR4_A7 0x1e0a00f0
-#define SH7750_PRECHARGE0_A7 0x1f900088
-#define SH7750_PRECHARGE1_A7 0x1f940088
-
-#endif
diff --git a/hw/shix.c b/hw/shix.c
deleted file mode 100644
index 9577c09..0000000
--- a/hw/shix.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * SHIX 2.0 board description
- *
- * Copyright (c) 2005 Samuel Tardieu
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-/*
- Shix 2.0 board by Alexis Polti, described at
- http://perso.enst.fr/~polti/realisations/shix20/
-
- More information in target-sh4/README.sh4
-*/
-#include "vl.h"
-
-#define BIOS_FILENAME "shix_bios.bin"
-#define BIOS_ADDRESS 0xA0000000
-
-void DMA_run(void)
-{
- /* XXXXX */
-}
-
-void irq_info(void)
-{
- /* XXXXX */
-}
-
-void pic_set_irq(int irq, int level)
-{
- /* XXXXX */
-}
-
-void pic_info()
-{
- /* XXXXX */
-}
-
-void vga_update_display()
-{
- /* XXXXX */
-}
-
-void vga_invalidate_display()
-{
- /* XXXXX */
-}
-
-void vga_screen_dump(const char *filename)
-{
- /* XXXXX */
-}
-
-void shix_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState * ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- int ret;
- CPUState *env;
- struct SH7750State *s;
-
- printf("Initializing CPU\n");
- env = cpu_init();
-
- /* Allocate memory space */
- printf("Allocating ROM\n");
- cpu_register_physical_memory(0x00000000, 0x00004000, IO_MEM_ROM);
- printf("Allocating SDRAM 1\n");
- cpu_register_physical_memory(0x08000000, 0x01000000, 0x00004000);
- printf("Allocating SDRAM 2\n");
- cpu_register_physical_memory(0x0c000000, 0x01000000, 0x01004000);
-
- /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
- printf("%s: load BIOS '%s'\n", __func__, BIOS_FILENAME);
- ret = load_image(BIOS_FILENAME, phys_ram_base);
- if (ret < 0) { /* Check bios size */
- fprintf(stderr, "ret=%d\n", ret);
- fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
- BIOS_FILENAME);
- exit(1);
- }
-
- /* Register peripherals */
- s = sh7750_init(env);
- /* XXXXX Check success */
- tc58128_init(s, "shix_linux_nand.bin", NULL);
- fprintf(stderr, "initialization terminated\n");
-}
-
-QEMUMachine shix_machine = {
- "shix",
- "shix card",
- shix_init
-};
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
deleted file mode 100644
index 288fb50..0000000
--- a/hw/slavio_intctl.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * QEMU Sparc SLAVIO interrupt controller emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-//#define DEBUG_IRQ_COUNT
-//#define DEBUG_IRQ
-
-#ifdef DEBUG_IRQ
-#define DPRINTF(fmt, args...) \
-do { printf("IRQ: " fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...)
-#endif
-
-/*
- * Registers of interrupt controller in sun4m.
- *
- * This is the interrupt controller part of chip STP2001 (Slave I/O), also
- * produced as NCR89C105. See
- * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
- *
- * There is a system master controller and one for each cpu.
- *
- */
-
-#define MAX_CPUS 16
-
-typedef struct SLAVIO_INTCTLState {
- uint32_t intreg_pending[MAX_CPUS];
- uint32_t intregm_pending;
- uint32_t intregm_disabled;
- uint32_t target_cpu;
-#ifdef DEBUG_IRQ_COUNT
- uint64_t irq_count[32];
-#endif
- CPUState *cpu_envs[MAX_CPUS];
-} SLAVIO_INTCTLState;
-
-#define INTCTL_MAXADDR 0xf
-#define INTCTLM_MAXADDR 0xf
-static void slavio_check_interrupts(void *opaque);
-
-// per-cpu interrupt controller
-static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- SLAVIO_INTCTLState *s = opaque;
- uint32_t saddr;
- int cpu;
-
- cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
- saddr = (addr & INTCTL_MAXADDR) >> 2;
- switch (saddr) {
- case 0:
- return s->intreg_pending[cpu];
- default:
- break;
- }
- return 0;
-}
-
-static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- SLAVIO_INTCTLState *s = opaque;
- uint32_t saddr;
- int cpu;
-
- cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
- saddr = (addr & INTCTL_MAXADDR) >> 2;
- switch (saddr) {
- case 1: // clear pending softints
- if (val & 0x4000)
- val |= 80000000;
- val &= 0xfffe0000;
- s->intreg_pending[cpu] &= ~val;
- DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
- break;
- case 2: // set softint
- val &= 0xfffe0000;
- s->intreg_pending[cpu] |= val;
- slavio_check_interrupts(s);
- DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
- break;
- default:
- break;
- }
-}
-
-static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
- slavio_intctl_mem_readl,
- slavio_intctl_mem_readl,
- slavio_intctl_mem_readl,
-};
-
-static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
- slavio_intctl_mem_writel,
- slavio_intctl_mem_writel,
- slavio_intctl_mem_writel,
-};
-
-// master system interrupt controller
-static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- SLAVIO_INTCTLState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & INTCTLM_MAXADDR) >> 2;
- switch (saddr) {
- case 0:
- return s->intregm_pending & 0x7fffffff;
- case 1:
- return s->intregm_disabled;
- case 4:
- return s->target_cpu;
- default:
- break;
- }
- return 0;
-}
-
-static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- SLAVIO_INTCTLState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & INTCTLM_MAXADDR) >> 2;
- switch (saddr) {
- case 2: // clear (enable)
- // Force clear unused bits
- val &= ~0x4fb2007f;
- s->intregm_disabled &= ~val;
- DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
- slavio_check_interrupts(s);
- break;
- case 3: // set (disable, clear pending)
- // Force clear unused bits
- val &= ~0x4fb2007f;
- s->intregm_disabled |= val;
- s->intregm_pending &= ~val;
- DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
- break;
- case 4:
- s->target_cpu = val & (MAX_CPUS - 1);
- DPRINTF("Set master irq cpu %d\n", s->target_cpu);
- break;
- default:
- break;
- }
-}
-
-static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
- slavio_intctlm_mem_readl,
- slavio_intctlm_mem_readl,
- slavio_intctlm_mem_readl,
-};
-
-static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
- slavio_intctlm_mem_writel,
- slavio_intctlm_mem_writel,
- slavio_intctlm_mem_writel,
-};
-
-void slavio_pic_info(void *opaque)
-{
- SLAVIO_INTCTLState *s = opaque;
- int i;
-
- for (i = 0; i < MAX_CPUS; i++) {
- term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
- }
- term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
-}
-
-void slavio_irq_info(void *opaque)
-{
-#ifndef DEBUG_IRQ_COUNT
- term_printf("irq statistic code not compiled.\n");
-#else
- SLAVIO_INTCTLState *s = opaque;
- int i;
- int64_t count;
-
- term_printf("IRQ statistics:\n");
- for (i = 0; i < 32; i++) {
- count = s->irq_count[i];
- if (count > 0)
- term_printf("%2d: %" PRId64 "\n", i, count);
- }
-#endif
-}
-
-static const uint32_t intbit_to_level[32] = {
- 2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
- 6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 15, 0,
-};
-
-static void slavio_check_interrupts(void *opaque)
-{
- CPUState *env;
- SLAVIO_INTCTLState *s = opaque;
- uint32_t pending = s->intregm_pending;
- unsigned int i, j, max = 0;
-
- pending &= ~s->intregm_disabled;
-
- if (pending && !(s->intregm_disabled & 0x80000000)) {
- for (i = 0; i < 32; i++) {
- if (pending & (1 << i)) {
- if (max < intbit_to_level[i])
- max = intbit_to_level[i];
- }
- }
- env = s->cpu_envs[s->target_cpu];
- if (!env) {
- DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending);
- }
- else {
- if (env->halted)
- env->halted = 0;
- if (env->interrupt_index == 0) {
- DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max);
-#ifdef DEBUG_IRQ_COUNT
- s->irq_count[max]++;
-#endif
- env->interrupt_index = TT_EXTINT | max;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- }
- else
- DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
- }
- }
- else
- DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
-
- for (i = 0; i < MAX_CPUS; i++) {
- max = 0;
- env = s->cpu_envs[i];
- if (!env)
- continue;
- for (j = 17; j < 32; j++) {
- if (s->intreg_pending[i] & (1 << j)) {
- if (max < j - 16)
- max = j - 16;
- }
- }
- if (max > 0) {
- if (env->halted)
- env->halted = 0;
- if (env->interrupt_index == 0) {
- DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending);
-#ifdef DEBUG_IRQ_COUNT
- s->irq_count[max]++;
-#endif
- env->interrupt_index = TT_EXTINT | max;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- }
- }
- }
-}
-
-/*
- * "irq" here is the bit number in the system interrupt register to
- * separate serial and keyboard interrupts sharing a level.
- */
-void slavio_pic_set_irq(void *opaque, int irq, int level)
-{
- SLAVIO_INTCTLState *s = opaque;
-
- DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
- if (irq < 32) {
- uint32_t mask = 1 << irq;
- uint32_t pil = intbit_to_level[irq];
- if (pil > 0) {
- if (level) {
- s->intregm_pending |= mask;
- s->intreg_pending[s->target_cpu] |= 1 << pil;
- }
- else {
- s->intregm_pending &= ~mask;
- s->intreg_pending[s->target_cpu] &= ~(1 << pil);
- }
- }
- }
- slavio_check_interrupts(s);
-}
-
-void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
-{
- SLAVIO_INTCTLState *s = opaque;
-
- DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level);
- if (cpu == (unsigned int)-1) {
- slavio_pic_set_irq(opaque, irq, level);
- return;
- }
- if (irq < 32) {
- uint32_t pil = intbit_to_level[irq];
- if (pil > 0) {
- if (level) {
- s->intreg_pending[cpu] |= 1 << pil;
- }
- else {
- s->intreg_pending[cpu] &= ~(1 << pil);
- }
- }
- }
- slavio_check_interrupts(s);
-}
-
-static void slavio_intctl_save(QEMUFile *f, void *opaque)
-{
- SLAVIO_INTCTLState *s = opaque;
- int i;
-
- for (i = 0; i < MAX_CPUS; i++) {
- qemu_put_be32s(f, &s->intreg_pending[i]);
- }
- qemu_put_be32s(f, &s->intregm_pending);
- qemu_put_be32s(f, &s->intregm_disabled);
- qemu_put_be32s(f, &s->target_cpu);
-}
-
-static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
-{
- SLAVIO_INTCTLState *s = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- for (i = 0; i < MAX_CPUS; i++) {
- qemu_get_be32s(f, &s->intreg_pending[i]);
- }
- qemu_get_be32s(f, &s->intregm_pending);
- qemu_get_be32s(f, &s->intregm_disabled);
- qemu_get_be32s(f, &s->target_cpu);
- return 0;
-}
-
-static void slavio_intctl_reset(void *opaque)
-{
- SLAVIO_INTCTLState *s = opaque;
- int i;
-
- for (i = 0; i < MAX_CPUS; i++) {
- s->intreg_pending[i] = 0;
- }
- s->intregm_disabled = ~0xffb2007f;
- s->intregm_pending = 0;
- s->target_cpu = 0;
-}
-
-void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env)
-{
- SLAVIO_INTCTLState *s = opaque;
- s->cpu_envs[cpu] = env;
-}
-
-void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
-{
- int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
- SLAVIO_INTCTLState *s;
-
- s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
- if (!s)
- return NULL;
-
- for (i = 0; i < MAX_CPUS; i++) {
- slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
- cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
- }
-
- slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
- cpu_register_physical_memory(addrg, INTCTLM_MAXADDR, slavio_intctlm_io_memory);
-
- register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
- qemu_register_reset(slavio_intctl_reset, s);
- slavio_intctl_reset(s);
- return s;
-}
-
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
deleted file mode 100644
index 904f44e..0000000
--- a/hw/slavio_misc.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * QEMU Sparc SLAVIO aux io port emulation
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-/* debug misc */
-//#define DEBUG_MISC
-
-/*
- * This is the auxio port, chip control and system control part of
- * chip STP2001 (Slave I/O), also produced as NCR89C105. See
- * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
- *
- * This also includes the PMC CPU idle controller.
- */
-
-#ifdef DEBUG_MISC
-#define MISC_DPRINTF(fmt, args...) \
-do { printf("MISC: " fmt , ##args); } while (0)
-#else
-#define MISC_DPRINTF(fmt, args...)
-#endif
-
-typedef struct MiscState {
- int irq;
- uint8_t config;
- uint8_t aux1, aux2;
- uint8_t diag, mctrl, sysctrl;
-} MiscState;
-
-#define MISC_MAXADDR 1
-
-static void slavio_misc_update_irq(void *opaque)
-{
- MiscState *s = opaque;
-
- if ((s->aux2 & 0x4) && (s->config & 0x8)) {
- pic_set_irq(s->irq, 1);
- } else {
- pic_set_irq(s->irq, 0);
- }
-}
-
-static void slavio_misc_reset(void *opaque)
-{
- MiscState *s = opaque;
-
- // Diagnostic and system control registers not cleared in reset
- s->config = s->aux1 = s->aux2 = s->mctrl = 0;
-}
-
-void slavio_set_power_fail(void *opaque, int power_failing)
-{
- MiscState *s = opaque;
-
- MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
- if (power_failing && (s->config & 0x8)) {
- s->aux2 |= 0x4;
- } else {
- s->aux2 &= ~0x4;
- }
- slavio_misc_update_irq(s);
-}
-
-static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- MiscState *s = opaque;
-
- switch (addr & 0xfff0000) {
- case 0x1800000:
- MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
- s->config = val & 0xff;
- slavio_misc_update_irq(s);
- break;
- case 0x1900000:
- MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
- s->aux1 = val & 0xff;
- break;
- case 0x1910000:
- val &= 0x3;
- MISC_DPRINTF("Write aux2 %2.2x\n", val);
- val |= s->aux2 & 0x4;
- if (val & 0x2) // Clear Power Fail int
- val &= 0x1;
- s->aux2 = val;
- if (val & 1)
- qemu_system_shutdown_request();
- slavio_misc_update_irq(s);
- break;
- case 0x1a00000:
- MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
- s->diag = val & 0xff;
- break;
- case 0x1b00000:
- MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
- s->mctrl = val & 0xff;
- break;
- case 0x1f00000:
- MISC_DPRINTF("Write system control %2.2x\n", val & 0xff);
- if (val & 1) {
- s->sysctrl = 0x2;
- qemu_system_reset_request();
- }
- break;
- case 0xa000000:
- MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
-#if 0
- // XXX almost works
- cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-#endif
- break;
- }
-}
-
-static uint32_t slavio_misc_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- MiscState *s = opaque;
- uint32_t ret = 0;
-
- switch (addr & 0xfff0000) {
- case 0x1800000:
- ret = s->config;
- MISC_DPRINTF("Read config %2.2x\n", ret);
- break;
- case 0x1900000:
- ret = s->aux1;
- MISC_DPRINTF("Read aux1 %2.2x\n", ret);
- break;
- case 0x1910000:
- ret = s->aux2;
- MISC_DPRINTF("Read aux2 %2.2x\n", ret);
- break;
- case 0x1a00000:
- ret = s->diag;
- MISC_DPRINTF("Read diag %2.2x\n", ret);
- break;
- case 0x1b00000:
- ret = s->mctrl;
- MISC_DPRINTF("Read modem control %2.2x\n", ret);
- break;
- case 0x1f00000:
- MISC_DPRINTF("Read system control %2.2x\n", ret);
- ret = s->sysctrl;
- break;
- case 0xa000000:
- MISC_DPRINTF("Read power management %2.2x\n", ret);
- break;
- }
- return ret;
-}
-
-static CPUReadMemoryFunc *slavio_misc_mem_read[3] = {
- slavio_misc_mem_readb,
- slavio_misc_mem_readb,
- slavio_misc_mem_readb,
-};
-
-static CPUWriteMemoryFunc *slavio_misc_mem_write[3] = {
- slavio_misc_mem_writeb,
- slavio_misc_mem_writeb,
- slavio_misc_mem_writeb,
-};
-
-static void slavio_misc_save(QEMUFile *f, void *opaque)
-{
- MiscState *s = opaque;
-
- qemu_put_be32s(f, &s->irq);
- qemu_put_8s(f, &s->config);
- qemu_put_8s(f, &s->aux1);
- qemu_put_8s(f, &s->aux2);
- qemu_put_8s(f, &s->diag);
- qemu_put_8s(f, &s->mctrl);
- qemu_put_8s(f, &s->sysctrl);
-}
-
-static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
-{
- MiscState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->irq);
- qemu_get_8s(f, &s->config);
- qemu_get_8s(f, &s->aux1);
- qemu_get_8s(f, &s->aux2);
- qemu_get_8s(f, &s->diag);
- qemu_get_8s(f, &s->mctrl);
- qemu_get_8s(f, &s->sysctrl);
- return 0;
-}
-
-void *slavio_misc_init(uint32_t base, int irq)
-{
- int slavio_misc_io_memory;
- MiscState *s;
-
- s = qemu_mallocz(sizeof(MiscState));
- if (!s)
- return NULL;
-
- slavio_misc_io_memory = cpu_register_io_memory(0, slavio_misc_mem_read, slavio_misc_mem_write, s);
- // Slavio control
- cpu_register_physical_memory(base + 0x1800000, MISC_MAXADDR, slavio_misc_io_memory);
- // AUX 1
- cpu_register_physical_memory(base + 0x1900000, MISC_MAXADDR, slavio_misc_io_memory);
- // AUX 2
- cpu_register_physical_memory(base + 0x1910000, MISC_MAXADDR, slavio_misc_io_memory);
- // Diagnostics
- cpu_register_physical_memory(base + 0x1a00000, MISC_MAXADDR, slavio_misc_io_memory);
- // Modem control
- cpu_register_physical_memory(base + 0x1b00000, MISC_MAXADDR, slavio_misc_io_memory);
- // System control
- cpu_register_physical_memory(base + 0x1f00000, MISC_MAXADDR, slavio_misc_io_memory);
- // Power management
- cpu_register_physical_memory(base + 0xa000000, MISC_MAXADDR, slavio_misc_io_memory);
-
- s->irq = irq;
-
- register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load, s);
- qemu_register_reset(slavio_misc_reset, s);
- slavio_misc_reset(s);
- return s;
-}
diff --git a/hw/slavio_serial.c b/hw/slavio_serial.c
deleted file mode 100644
index b13e7c4..0000000
--- a/hw/slavio_serial.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * QEMU Sparc SLAVIO serial port emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-/* debug serial */
-//#define DEBUG_SERIAL
-
-/* debug keyboard */
-//#define DEBUG_KBD
-
-/* debug mouse */
-//#define DEBUG_MOUSE
-
-/*
- * This is the serial port, mouse and keyboard part of chip STP2001
- * (Slave I/O), also produced as NCR89C105. See
- * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
- *
- * The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
- * mouse and keyboard ports don't implement all functions and they are
- * only asynchronous. There is no DMA.
- *
- */
-
-#ifdef DEBUG_SERIAL
-#define SER_DPRINTF(fmt, args...) \
-do { printf("SER: " fmt , ##args); } while (0)
-#define pic_set_irq(irq, level) \
-do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
-#else
-#define SER_DPRINTF(fmt, args...)
-#endif
-#ifdef DEBUG_KBD
-#define KBD_DPRINTF(fmt, args...) \
-do { printf("KBD: " fmt , ##args); } while (0)
-#else
-#define KBD_DPRINTF(fmt, args...)
-#endif
-#ifdef DEBUG_MOUSE
-#define MS_DPRINTF(fmt, args...) \
-do { printf("SER: " fmt , ##args); } while (0)
-#else
-#define MS_DPRINTF(fmt, args...)
-#endif
-
-typedef enum {
- chn_a, chn_b,
-} chn_id_t;
-
-typedef enum {
- ser, kbd, mouse,
-} chn_type_t;
-
-#define KBD_QUEUE_SIZE 256
-
-typedef struct {
- uint8_t data[KBD_QUEUE_SIZE];
- int rptr, wptr, count;
-} KBDQueue;
-
-typedef struct ChannelState {
- int irq;
- int reg;
- int rxint, txint;
- chn_id_t chn; // this channel, A (base+4) or B (base+0)
- chn_type_t type;
- struct ChannelState *otherchn;
- uint8_t rx, tx, wregs[16], rregs[16];
- KBDQueue queue;
- CharDriverState *chr;
-} ChannelState;
-
-struct SerialState {
- struct ChannelState chn[2];
-};
-
-#define SERIAL_MAXADDR 7
-
-static void handle_kbd_command(ChannelState *s, int val);
-static int serial_can_receive(void *opaque);
-static void serial_receive_byte(ChannelState *s, int ch);
-
-static void put_queue(void *opaque, int b)
-{
- ChannelState *s = opaque;
- KBDQueue *q = &s->queue;
-
- KBD_DPRINTF("put: 0x%02x\n", b);
- if (q->count >= KBD_QUEUE_SIZE)
- return;
- q->data[q->wptr] = b;
- if (++q->wptr == KBD_QUEUE_SIZE)
- q->wptr = 0;
- q->count++;
- serial_receive_byte(s, 0);
-}
-
-static uint32_t get_queue(void *opaque)
-{
- ChannelState *s = opaque;
- KBDQueue *q = &s->queue;
- int val;
-
- if (q->count == 0) {
- return 0;
- } else {
- val = q->data[q->rptr];
- if (++q->rptr == KBD_QUEUE_SIZE)
- q->rptr = 0;
- q->count--;
- }
- KBD_DPRINTF("get 0x%02x\n", val);
- if (q->count > 0)
- serial_receive_byte(s, 0);
- return val;
-}
-
-static void slavio_serial_update_irq(ChannelState *s)
-{
- if ((s->wregs[1] & 1) && // interrupts enabled
- (((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
- ((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
- s->rxint == 1) || // rx ints enabled, pending
- ((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
- pic_set_irq(s->irq, 1);
- } else {
- pic_set_irq(s->irq, 0);
- }
-}
-
-static void slavio_serial_reset_chn(ChannelState *s)
-{
- int i;
-
- s->reg = 0;
- for (i = 0; i < SERIAL_MAXADDR; i++) {
- s->rregs[i] = 0;
- s->wregs[i] = 0;
- }
- s->wregs[4] = 4;
- s->wregs[9] = 0xc0;
- s->wregs[11] = 8;
- s->wregs[14] = 0x30;
- s->wregs[15] = 0xf8;
- s->rregs[0] = 0x44;
- s->rregs[1] = 6;
-
- s->rx = s->tx = 0;
- s->rxint = s->txint = 0;
-}
-
-static void slavio_serial_reset(void *opaque)
-{
- SerialState *s = opaque;
- slavio_serial_reset_chn(&s->chn[0]);
- slavio_serial_reset_chn(&s->chn[1]);
-}
-
-static inline void clr_rxint(ChannelState *s)
-{
- s->rxint = 0;
- if (s->chn == 0)
- s->rregs[3] &= ~0x20;
- else {
- s->otherchn->rregs[3] &= ~4;
- }
- slavio_serial_update_irq(s);
-}
-
-static inline void set_rxint(ChannelState *s)
-{
- s->rxint = 1;
- if (s->chn == 0)
- s->rregs[3] |= 0x20;
- else {
- s->otherchn->rregs[3] |= 4;
- }
- slavio_serial_update_irq(s);
-}
-
-static inline void clr_txint(ChannelState *s)
-{
- s->txint = 0;
- if (s->chn == 0)
- s->rregs[3] &= ~0x10;
- else {
- s->otherchn->rregs[3] &= ~2;
- }
- slavio_serial_update_irq(s);
-}
-
-static inline void set_txint(ChannelState *s)
-{
- s->txint = 1;
- if (s->chn == 0)
- s->rregs[3] |= 0x10;
- else {
- s->otherchn->rregs[3] |= 2;
- }
- slavio_serial_update_irq(s);
-}
-
-static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- SerialState *ser = opaque;
- ChannelState *s;
- uint32_t saddr;
- int newreg, channel;
-
- val &= 0xff;
- saddr = (addr & 3) >> 1;
- channel = (addr & SERIAL_MAXADDR) >> 2;
- s = &ser->chn[channel];
- switch (saddr) {
- case 0:
- SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, val & 0xff);
- newreg = 0;
- switch (s->reg) {
- case 0:
- newreg = val & 7;
- val &= 0x38;
- switch (val) {
- case 8:
- newreg |= 0x8;
- break;
- case 0x20:
- clr_rxint(s);
- break;
- case 0x28:
- clr_txint(s);
- break;
- case 0x38:
- clr_rxint(s);
- clr_txint(s);
- break;
- default:
- break;
- }
- break;
- case 1 ... 8:
- case 10 ... 15:
- s->wregs[s->reg] = val;
- break;
- case 9:
- switch (val & 0xc0) {
- case 0:
- default:
- break;
- case 0x40:
- slavio_serial_reset_chn(&ser->chn[1]);
- return;
- case 0x80:
- slavio_serial_reset_chn(&ser->chn[0]);
- return;
- case 0xc0:
- slavio_serial_reset(ser);
- return;
- }
- break;
- default:
- break;
- }
- if (s->reg == 0)
- s->reg = newreg;
- else
- s->reg = 0;
- break;
- case 1:
- SER_DPRINTF("Write channel %c, ch %d\n", channel? 'b' : 'a', val);
- if (s->wregs[5] & 8) { // tx enabled
- s->tx = val;
- if (s->chr)
- qemu_chr_write(s->chr, &s->tx, 1);
- else if (s->type == kbd) {
- handle_kbd_command(s, val);
- }
- s->txint = 1;
- s->rregs[0] |= 4; // Tx buffer empty
- s->rregs[1] |= 1; // All sent
- set_txint(s);
- slavio_serial_update_irq(s);
- }
- break;
- default:
- break;
- }
-}
-
-static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- SerialState *ser = opaque;
- ChannelState *s;
- uint32_t saddr;
- uint32_t ret;
- int channel;
-
- saddr = (addr & 3) >> 1;
- channel = (addr & SERIAL_MAXADDR) >> 2;
- s = &ser->chn[channel];
- switch (saddr) {
- case 0:
- SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", channel? 'b' : 'a', s->reg, s->rregs[s->reg]);
- ret = s->rregs[s->reg];
- s->reg = 0;
- return ret;
- case 1:
- s->rregs[0] &= ~1;
- clr_rxint(s);
- if (s->type == kbd)
- ret = get_queue(s);
- else
- ret = s->rx;
- SER_DPRINTF("Read channel %c, ch %d\n", channel? 'b' : 'a', ret);
- return ret;
- default:
- break;
- }
- return 0;
-}
-
-static int serial_can_receive(void *opaque)
-{
- ChannelState *s = opaque;
- if (((s->wregs[3] & 1) == 0) // Rx not enabled
- || ((s->rregs[0] & 1) == 1)) // char already available
- return 0;
- else
- return 1;
-}
-
-static void serial_receive_byte(ChannelState *s, int ch)
-{
- SER_DPRINTF("put ch %d\n", ch);
- s->rregs[0] |= 1;
- s->rx = ch;
- set_rxint(s);
-}
-
-static void serial_receive_break(ChannelState *s)
-{
- s->rregs[0] |= 0x80;
- slavio_serial_update_irq(s);
-}
-
-static void serial_receive1(void *opaque, const uint8_t *buf, int size)
-{
- ChannelState *s = opaque;
- serial_receive_byte(s, buf[0]);
-}
-
-static void serial_event(void *opaque, int event)
-{
- ChannelState *s = opaque;
- if (event == CHR_EVENT_BREAK)
- serial_receive_break(s);
-}
-
-static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
- slavio_serial_mem_readb,
- slavio_serial_mem_readb,
- slavio_serial_mem_readb,
-};
-
-static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
- slavio_serial_mem_writeb,
- slavio_serial_mem_writeb,
- slavio_serial_mem_writeb,
-};
-
-static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
-{
- qemu_put_be32s(f, &s->irq);
- qemu_put_be32s(f, &s->reg);
- qemu_put_be32s(f, &s->rxint);
- qemu_put_be32s(f, &s->txint);
- qemu_put_8s(f, &s->rx);
- qemu_put_8s(f, &s->tx);
- qemu_put_buffer(f, s->wregs, 16);
- qemu_put_buffer(f, s->rregs, 16);
-}
-
-static void slavio_serial_save(QEMUFile *f, void *opaque)
-{
- SerialState *s = opaque;
-
- slavio_serial_save_chn(f, &s->chn[0]);
- slavio_serial_save_chn(f, &s->chn[1]);
-}
-
-static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
-{
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->irq);
- qemu_get_be32s(f, &s->reg);
- qemu_get_be32s(f, &s->rxint);
- qemu_get_be32s(f, &s->txint);
- qemu_get_8s(f, &s->rx);
- qemu_get_8s(f, &s->tx);
- qemu_get_buffer(f, s->wregs, 16);
- qemu_get_buffer(f, s->rregs, 16);
- return 0;
-}
-
-static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
-{
- SerialState *s = opaque;
- int ret;
-
- ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
- if (ret != 0)
- return ret;
- ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
- return ret;
-
-}
-
-SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
-{
- int slavio_serial_io_memory, i;
- SerialState *s;
-
- s = qemu_mallocz(sizeof(SerialState));
- if (!s)
- return NULL;
-
- slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
- cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
-
- s->chn[0].chr = chr1;
- s->chn[1].chr = chr2;
-
- for (i = 0; i < 2; i++) {
- s->chn[i].irq = irq;
- s->chn[i].chn = 1 - i;
- s->chn[i].type = ser;
- if (s->chn[i].chr) {
- qemu_chr_add_read_handler(s->chn[i].chr, serial_can_receive, serial_receive1, &s->chn[i]);
- qemu_chr_add_event_handler(s->chn[i].chr, serial_event);
- }
- }
- s->chn[0].otherchn = &s->chn[1];
- s->chn[1].otherchn = &s->chn[0];
- register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
- qemu_register_reset(slavio_serial_reset, s);
- slavio_serial_reset(s);
- return s;
-}
-
-static const uint8_t keycodes[128] = {
- 127, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 89, 76, 77, 78,
- 79, 80, 81, 82, 83, 84, 85, 86, 87, 42, 99, 88, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 47, 19, 121, 119, 5, 6, 8, 10, 12,
- 14, 16, 17, 18, 7, 98, 23, 68, 69, 70, 71, 91, 92, 93, 125, 112,
- 113, 114, 94, 50, 0, 0, 124, 9, 11, 0, 0, 0, 0, 0, 0, 0,
- 90, 0, 46, 22, 13, 111, 52, 20, 96, 24, 28, 74, 27, 123, 44, 66,
- 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67,
-};
-
-static void sunkbd_event(void *opaque, int ch)
-{
- ChannelState *s = opaque;
- int release = ch & 0x80;
-
- ch = keycodes[ch & 0x7f];
- KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press");
- put_queue(s, ch | release);
-}
-
-static void handle_kbd_command(ChannelState *s, int val)
-{
- KBD_DPRINTF("Command %d\n", val);
- switch (val) {
- case 1: // Reset, return type code
- put_queue(s, 0xff);
- put_queue(s, 5); // Type 5
- break;
- case 7: // Query layout
- put_queue(s, 0xfe);
- put_queue(s, 0x20); // XXX, layout?
- break;
- default:
- break;
- }
-}
-
-static void sunmouse_event(void *opaque,
- int dx, int dy, int dz, int buttons_state)
-{
- ChannelState *s = opaque;
- int ch;
-
- // XXX
- ch = 0x42;
- serial_receive_byte(s, ch);
-}
-
-void slavio_serial_ms_kbd_init(int base, int irq)
-{
- int slavio_serial_io_memory, i;
- SerialState *s;
-
- s = qemu_mallocz(sizeof(SerialState));
- if (!s)
- return;
- for (i = 0; i < 2; i++) {
- s->chn[i].irq = irq;
- s->chn[i].chn = 1 - i;
- s->chn[i].chr = NULL;
- }
- s->chn[0].otherchn = &s->chn[1];
- s->chn[1].otherchn = &s->chn[0];
- s->chn[0].type = mouse;
- s->chn[1].type = kbd;
-
- slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
- cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
-
- qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0);
- qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
- qemu_register_reset(slavio_serial_reset, s);
- slavio_serial_reset(s);
-}
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
deleted file mode 100644
index 976f0d4..0000000
--- a/hw/slavio_timer.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * QEMU Sparc SLAVIO timer controller emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define DEBUG_TIMER
-
-#ifdef DEBUG_TIMER
-#define DPRINTF(fmt, args...) \
-do { printf("TIMER: " fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...)
-#endif
-
-/*
- * Registers of hardware timer in sun4m.
- *
- * This is the timer/counter part of chip STP2001 (Slave I/O), also
- * produced as NCR89C105. See
- * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
- *
- * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
- * are zero. Bit 31 is 1 when count has been reached.
- *
- * Per-CPU timers interrupt local CPU, system timer uses normal
- * interrupt routing.
- *
- */
-
-typedef struct SLAVIO_TIMERState {
- uint32_t limit, count, counthigh;
- int64_t count_load_time;
- int64_t expire_time;
- int64_t stop_time, tick_offset;
- QEMUTimer *irq_timer;
- int irq;
- int reached, stopped;
- int mode; // 0 = processor, 1 = user, 2 = system
- unsigned int cpu;
-} SLAVIO_TIMERState;
-
-#define TIMER_MAXADDR 0x1f
-#define CNT_FREQ 2000000
-
-// Update count, set irq, update expire_time
-static void slavio_timer_get_out(SLAVIO_TIMERState *s)
-{
- int out;
- int64_t diff, ticks, count;
- uint32_t limit;
-
- // There are three clock tick units: CPU ticks, register units
- // (nanoseconds), and counter ticks (500 ns).
- if (s->mode == 1 && s->stopped)
- ticks = s->stop_time;
- else
- ticks = qemu_get_clock(vm_clock) - s->tick_offset;
-
- out = (ticks > s->expire_time);
- if (out)
- s->reached = 0x80000000;
- if (!s->limit)
- limit = 0x7fffffff;
- else
- limit = s->limit;
-
- // Convert register units to counter ticks
- limit = limit >> 9;
-
- // Convert cpu ticks to counter ticks
- diff = muldiv64(ticks - s->count_load_time, CNT_FREQ, ticks_per_sec);
-
- // Calculate what the counter should be, convert to register
- // units
- count = diff % limit;
- s->count = count << 9;
- s->counthigh = count >> 22;
-
- // Expire time: CPU ticks left to next interrupt
- // Convert remaining counter ticks to CPU ticks
- s->expire_time = ticks + muldiv64(limit - count, ticks_per_sec, CNT_FREQ);
-
- DPRINTF("irq %d limit %d reached %d d %" PRId64 " count %d s->c %x diff %" PRId64 " stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
-
- if (s->mode != 1)
- pic_set_irq_cpu(s->irq, out, s->cpu);
-}
-
-// timer callback
-static void slavio_timer_irq(void *opaque)
-{
- SLAVIO_TIMERState *s = opaque;
-
- if (!s->irq_timer)
- return;
- slavio_timer_get_out(s);
- if (s->mode != 1)
- qemu_mod_timer(s->irq_timer, s->expire_time);
-}
-
-static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- SLAVIO_TIMERState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & TIMER_MAXADDR) >> 2;
- switch (saddr) {
- case 0:
- // read limit (system counter mode) or read most signifying
- // part of counter (user mode)
- if (s->mode != 1) {
- // clear irq
- pic_set_irq_cpu(s->irq, 0, s->cpu);
- s->count_load_time = qemu_get_clock(vm_clock);
- s->reached = 0;
- return s->limit;
- }
- else {
- slavio_timer_get_out(s);
- return s->counthigh & 0x7fffffff;
- }
- case 1:
- // read counter and reached bit (system mode) or read lsbits
- // of counter (user mode)
- slavio_timer_get_out(s);
- if (s->mode != 1)
- return (s->count & 0x7fffffff) | s->reached;
- else
- return s->count;
- case 3:
- // read start/stop status
- return s->stopped;
- case 4:
- // read user/system mode
- return s->mode & 1;
- default:
- return 0;
- }
-}
-
-static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- SLAVIO_TIMERState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & TIMER_MAXADDR) >> 2;
- switch (saddr) {
- case 0:
- // set limit, reset counter
- s->count_load_time = qemu_get_clock(vm_clock);
- // fall through
- case 2:
- // set limit without resetting counter
- if (!val)
- s->limit = 0x7fffffff;
- else
- s->limit = val & 0x7fffffff;
- slavio_timer_irq(s);
- break;
- case 3:
- // start/stop user counter
- if (s->mode == 1) {
- if (val & 1) {
- s->stop_time = qemu_get_clock(vm_clock);
- s->stopped = 1;
- }
- else {
- if (s->stopped)
- s->tick_offset += qemu_get_clock(vm_clock) - s->stop_time;
- s->stopped = 0;
- }
- }
- break;
- case 4:
- // bit 0: user (1) or system (0) counter mode
- if (s->mode == 0 || s->mode == 1)
- s->mode = val & 1;
- break;
- default:
- break;
- }
-}
-
-static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
- slavio_timer_mem_readl,
- slavio_timer_mem_readl,
- slavio_timer_mem_readl,
-};
-
-static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
- slavio_timer_mem_writel,
- slavio_timer_mem_writel,
- slavio_timer_mem_writel,
-};
-
-static void slavio_timer_save(QEMUFile *f, void *opaque)
-{
- SLAVIO_TIMERState *s = opaque;
-
- qemu_put_be32s(f, &s->limit);
- qemu_put_be32s(f, &s->count);
- qemu_put_be32s(f, &s->counthigh);
- qemu_put_be64s(f, &s->count_load_time);
- qemu_put_be64s(f, &s->expire_time);
- qemu_put_be64s(f, &s->stop_time);
- qemu_put_be64s(f, &s->tick_offset);
- qemu_put_be32s(f, &s->irq);
- qemu_put_be32s(f, &s->reached);
- qemu_put_be32s(f, &s->stopped);
- qemu_put_be32s(f, &s->mode);
-}
-
-static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
-{
- SLAVIO_TIMERState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->limit);
- qemu_get_be32s(f, &s->count);
- qemu_get_be32s(f, &s->counthigh);
- qemu_get_be64s(f, &s->count_load_time);
- qemu_get_be64s(f, &s->expire_time);
- qemu_get_be64s(f, &s->stop_time);
- qemu_get_be64s(f, &s->tick_offset);
- qemu_get_be32s(f, &s->irq);
- qemu_get_be32s(f, &s->reached);
- qemu_get_be32s(f, &s->stopped);
- qemu_get_be32s(f, &s->mode);
- return 0;
-}
-
-static void slavio_timer_reset(void *opaque)
-{
- SLAVIO_TIMERState *s = opaque;
-
- s->limit = 0;
- s->count = 0;
- s->count_load_time = qemu_get_clock(vm_clock);;
- s->stop_time = s->count_load_time;
- s->tick_offset = 0;
- s->reached = 0;
- s->mode &= 2;
- s->stopped = 1;
- slavio_timer_get_out(s);
-}
-
-void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu)
-{
- int slavio_timer_io_memory;
- SLAVIO_TIMERState *s;
-
- s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
- if (!s)
- return;
- s->irq = irq;
- s->mode = mode;
- s->cpu = cpu;
- s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s);
-
- slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
- slavio_timer_mem_write, s);
- cpu_register_physical_memory(addr, TIMER_MAXADDR, slavio_timer_io_memory);
- register_savevm("slavio_timer", addr, 1, slavio_timer_save, slavio_timer_load, s);
- qemu_register_reset(slavio_timer_reset, s);
- slavio_timer_reset(s);
-}
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 214e92e..28b5c5d 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -8,6 +8,7 @@
*/
#include "vl.h"
+#include "irq.h"
/* For crc32 */
#include <zlib.h>
@@ -24,8 +25,7 @@ typedef struct {
uint16_t gpr;
uint16_t ptr;
uint16_t ercv;
- void *pic;
- int irq;
+ qemu_irq irq;
int bank;
int packet_num;
int tx_alloc;
@@ -86,7 +86,7 @@ static void smc91c111_update(smc91c111_state *s)
if (s->tx_fifo_done_len != 0)
s->int_level |= INT_TX;
level = (s->int_level & s->int_mask) != 0;
- pic_set_irq_new(s->pic, s->irq, level);
+ qemu_set_irq(s->irq, level);
}
/* Try to allocate a packet. Returns 0x80 on failure. */
@@ -159,7 +159,6 @@ static void smc91c111_do_tx(smc91c111_state *s)
int len;
int control;
int add_crc;
- uint32_t crc;
int packetnum;
uint8_t *p;
@@ -192,7 +191,7 @@ static void smc91c111_do_tx(smc91c111_state *s)
about. */
add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0;
if (add_crc) {
- crc = crc32(~0, p, len);
+ uint32_t crc = crc32(~0, p, len);
memcpy(p + len, &crc, 4);
len += 4;
}
@@ -692,7 +691,7 @@ static CPUWriteMemoryFunc *smc91c111_writefn[] = {
smc91c111_writel
};
-void smc91c111_init(NICInfo *nd, uint32_t base, void *pic, int irq)
+void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
{
smc91c111_state *s;
int iomemtype;
@@ -702,7 +701,6 @@ void smc91c111_init(NICInfo *nd, uint32_t base, void *pic, int irq)
smc91c111_writefn, s);
cpu_register_physical_memory(base, 16, iomemtype);
s->base = base;
- s->pic = pic;
s->irq = irq;
memcpy(s->macaddr, nd->macaddr, 6);
diff --git a/hw/sun4m.c b/hw/sun4m.c
deleted file mode 100644
index 203732f..0000000
--- a/hw/sun4m.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * QEMU Sun4m System Emulator
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-#define KERNEL_LOAD_ADDR 0x00004000
-#define CMDLINE_ADDR 0x007ff000
-#define INITRD_LOAD_ADDR 0x00800000
-#define PROM_SIZE_MAX (256 * 1024)
-#define PROM_ADDR 0xffd00000
-#define PROM_FILENAME "openbios-sparc32"
-#define PHYS_JJ_EEPROM 0x71200000 /* m48t08 */
-#define PHYS_JJ_IDPROM_OFF 0x1FD8
-#define PHYS_JJ_EEPROM_SIZE 0x2000
-// IRQs are not PIL ones, but master interrupt controller register
-// bits
-#define PHYS_JJ_IOMMU 0x10000000 /* I/O MMU */
-#define PHYS_JJ_TCX_FB 0x50000000 /* TCX frame buffer */
-#define PHYS_JJ_SLAVIO 0x70000000 /* Slavio base */
-#define PHYS_JJ_ESPDMA 0x78400000 /* ESP DMA controller */
-#define PHYS_JJ_ESP 0x78800000 /* ESP SCSI */
-#define PHYS_JJ_ESP_IRQ 18
-#define PHYS_JJ_LEDMA 0x78400010 /* Lance DMA controller */
-#define PHYS_JJ_LE 0x78C00000 /* Lance ethernet */
-#define PHYS_JJ_LE_IRQ 16
-#define PHYS_JJ_CLOCK 0x71D00000 /* Per-CPU timer/counter, L14 */
-#define PHYS_JJ_CLOCK_IRQ 7
-#define PHYS_JJ_CLOCK1 0x71D10000 /* System timer/counter, L10 */
-#define PHYS_JJ_CLOCK1_IRQ 19
-#define PHYS_JJ_INTR0 0x71E00000 /* Per-CPU interrupt control registers */
-#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
-#define PHYS_JJ_MS_KBD 0x71000000 /* Mouse and keyboard */
-#define PHYS_JJ_MS_KBD_IRQ 14
-#define PHYS_JJ_SER 0x71100000 /* Serial */
-#define PHYS_JJ_SER_IRQ 15
-#define PHYS_JJ_FDC 0x71400000 /* Floppy */
-#define PHYS_JJ_FLOPPY_IRQ 22
-#define PHYS_JJ_ME_IRQ 30 /* Module error, power fail */
-#define MAX_CPUS 16
-
-/* TSC handling */
-
-uint64_t cpu_get_tsc()
-{
- return qemu_get_clock(vm_clock);
-}
-
-int DMA_get_channel_mode (int nchan)
-{
- return 0;
-}
-int DMA_read_memory (int nchan, void *buf, int pos, int size)
-{
- return 0;
-}
-int DMA_write_memory (int nchan, void *buf, int pos, int size)
-{
- return 0;
-}
-void DMA_hold_DREQ (int nchan) {}
-void DMA_release_DREQ (int nchan) {}
-void DMA_schedule(int nchan) {}
-void DMA_run (void) {}
-void DMA_init (int high_page_enable) {}
-void DMA_register_channel (int nchan,
- DMA_transfer_handler transfer_handler,
- void *opaque)
-{
-}
-
-static void nvram_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
-{
- m48t59_write(nvram, addr++, (value >> 8) & 0xff);
- m48t59_write(nvram, addr++, value & 0xff);
-}
-
-static void nvram_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
-{
- m48t59_write(nvram, addr++, value >> 24);
- m48t59_write(nvram, addr++, (value >> 16) & 0xff);
- m48t59_write(nvram, addr++, (value >> 8) & 0xff);
- m48t59_write(nvram, addr++, value & 0xff);
-}
-
-static void nvram_set_string (m48t59_t *nvram, uint32_t addr,
- const unsigned char *str, uint32_t max)
-{
- unsigned int i;
-
- for (i = 0; i < max && str[i] != '\0'; i++) {
- m48t59_write(nvram, addr + i, str[i]);
- }
- m48t59_write(nvram, addr + max - 1, '\0');
-}
-
-static m48t59_t *nvram;
-
-extern int nographic;
-
-static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
- int boot_device, uint32_t RAM_size,
- uint32_t kernel_size,
- int width, int height, int depth)
-{
- unsigned char tmp = 0;
- int i, j;
-
- // Try to match PPC NVRAM
- nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
- nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */
- // NVRAM_size, arch not applicable
- m48t59_write(nvram, 0x2D, smp_cpus & 0xff);
- m48t59_write(nvram, 0x2E, 0);
- m48t59_write(nvram, 0x2F, nographic & 0xff);
- nvram_set_lword(nvram, 0x30, RAM_size);
- m48t59_write(nvram, 0x34, boot_device & 0xff);
- nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR);
- nvram_set_lword(nvram, 0x3C, kernel_size);
- if (cmdline) {
- strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
- nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
- nvram_set_lword(nvram, 0x44, strlen(cmdline));
- }
- // initrd_image, initrd_size passed differently
- nvram_set_word(nvram, 0x54, width);
- nvram_set_word(nvram, 0x56, height);
- nvram_set_word(nvram, 0x58, depth);
-
- // Sun4m specific use
- i = 0x1fd8;
- m48t59_write(nvram, i++, 0x01);
- m48t59_write(nvram, i++, 0x80); /* Sun4m OBP */
- j = 0;
- m48t59_write(nvram, i++, macaddr[j++]);
- m48t59_write(nvram, i++, macaddr[j++]);
- m48t59_write(nvram, i++, macaddr[j++]);
- m48t59_write(nvram, i++, macaddr[j++]);
- m48t59_write(nvram, i++, macaddr[j++]);
- m48t59_write(nvram, i, macaddr[j]);
-
- /* Calculate checksum */
- for (i = 0x1fd8; i < 0x1fe7; i++) {
- tmp ^= m48t59_read(nvram, i);
- }
- m48t59_write(nvram, 0x1fe7, tmp);
-}
-
-static void *slavio_intctl;
-
-void pic_info()
-{
- slavio_pic_info(slavio_intctl);
-}
-
-void irq_info()
-{
- slavio_irq_info(slavio_intctl);
-}
-
-void pic_set_irq(int irq, int level)
-{
- slavio_pic_set_irq(slavio_intctl, irq, level);
-}
-
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
- pic_set_irq(irq, level);
-}
-
-void pic_set_irq_cpu(int irq, int level, unsigned int cpu)
-{
- slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
-}
-
-static void *iommu;
-
-uint32_t iommu_translate(uint32_t addr)
-{
- return iommu_translate_local(iommu, addr);
-}
-
-static void *slavio_misc;
-
-void qemu_system_powerdown(void)
-{
- slavio_set_power_fail(slavio_misc, 1);
-}
-
-static void main_cpu_reset(void *opaque)
-{
- CPUState *env = opaque;
- cpu_reset(env);
-}
-
-/* Sun4m hardware initialisation */
-static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- CPUState *env, *envs[MAX_CPUS];
- char buf[1024];
- int ret, linux_boot;
- unsigned int i;
- long vram_size = 0x100000, prom_offset, initrd_size, kernel_size;
-
- linux_boot = (kernel_filename != NULL);
-
- /* init CPUs */
- for(i = 0; i < smp_cpus; i++) {
- env = cpu_init();
- envs[i] = env;
- if (i != 0)
- env->halted = 1;
- register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
- qemu_register_reset(main_cpu_reset, env);
- }
- /* allocate RAM */
- cpu_register_physical_memory(0, ram_size, 0);
-
- iommu = iommu_init(PHYS_JJ_IOMMU);
- slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
- for(i = 0; i < smp_cpus; i++) {
- slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
- }
-
- tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
- if (nd_table[0].vlan) {
- if (nd_table[0].model == NULL
- || strcmp(nd_table[0].model, "lance") == 0) {
- lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
- } else {
- fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
- exit (1);
- }
- }
- nvram = m48t59_init(0, PHYS_JJ_EEPROM, 0, PHYS_JJ_EEPROM_SIZE, 8);
- for (i = 0; i < MAX_CPUS; i++) {
- slavio_timer_init(PHYS_JJ_CLOCK + i * TARGET_PAGE_SIZE, PHYS_JJ_CLOCK_IRQ, 0, i);
- }
- slavio_timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ, 2, (unsigned int)-1);
- slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
- // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
- // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
- slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]);
- fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
- esp_init(bs_table, PHYS_JJ_ESP_IRQ, PHYS_JJ_ESP, PHYS_JJ_ESPDMA);
- slavio_misc = slavio_misc_init(PHYS_JJ_SLAVIO, PHYS_JJ_ME_IRQ);
-
- prom_offset = ram_size + vram_size;
- cpu_register_physical_memory(PROM_ADDR,
- (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK,
- prom_offset | IO_MEM_ROM);
-
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
- ret = load_elf(buf, 0, NULL);
- if (ret < 0) {
- fprintf(stderr, "qemu: could not load prom '%s'\n",
- buf);
- exit(1);
- }
-
- kernel_size = 0;
- if (linux_boot) {
- kernel_size = load_elf(kernel_filename, -0xf0000000, NULL);
- if (kernel_size < 0)
- kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
- if (kernel_size < 0)
- kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
- if (kernel_size < 0) {
- fprintf(stderr, "qemu: could not load kernel '%s'\n",
- kernel_filename);
- exit(1);
- }
-
- /* load initrd */
- initrd_size = 0;
- if (initrd_filename) {
- initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
- if (initrd_size < 0) {
- fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- initrd_filename);
- exit(1);
- }
- }
- if (initrd_size > 0) {
- for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
- if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
- == 0x48647253) { // HdrS
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
- break;
- }
- }
- }
- }
- nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, boot_device, ram_size, kernel_size, graphic_width, graphic_height, graphic_depth);
-}
-
-QEMUMachine sun4m_machine = {
- "sun4m",
- "Sun4m platform",
- sun4m_init,
-};
diff --git a/hw/sun4u.c b/hw/sun4u.c
deleted file mode 100644
index 6d41369..0000000
--- a/hw/sun4u.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * QEMU Sun4u System Emulator
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-#include "m48t59.h"
-
-#define KERNEL_LOAD_ADDR 0x00404000
-#define CMDLINE_ADDR 0x003ff000
-#define INITRD_LOAD_ADDR 0x00300000
-#define PROM_SIZE_MAX (512 * 1024)
-#define PROM_ADDR 0x1fff0000000ULL
-#define APB_SPECIAL_BASE 0x1fe00000000ULL
-#define APB_MEM_BASE 0x1ff00000000ULL
-#define VGA_BASE (APB_MEM_BASE + 0x400000ULL)
-#define PROM_FILENAME "openbios-sparc64"
-#define NVRAM_SIZE 0x2000
-
-/* TSC handling */
-
-uint64_t cpu_get_tsc()
-{
- return qemu_get_clock(vm_clock);
-}
-
-int DMA_get_channel_mode (int nchan)
-{
- return 0;
-}
-int DMA_read_memory (int nchan, void *buf, int pos, int size)
-{
- return 0;
-}
-int DMA_write_memory (int nchan, void *buf, int pos, int size)
-{
- return 0;
-}
-void DMA_hold_DREQ (int nchan) {}
-void DMA_release_DREQ (int nchan) {}
-void DMA_schedule(int nchan) {}
-void DMA_run (void) {}
-void DMA_init (int high_page_enable) {}
-void DMA_register_channel (int nchan,
- DMA_transfer_handler transfer_handler,
- void *opaque)
-{
-}
-
-/* NVRAM helpers */
-void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
-{
- m48t59_write(nvram, addr, value);
-}
-
-uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
-{
- return m48t59_read(nvram, addr);
-}
-
-void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
-{
- m48t59_write(nvram, addr, value >> 8);
- m48t59_write(nvram, addr + 1, value & 0xFF);
-}
-
-uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
-{
- uint16_t tmp;
-
- tmp = m48t59_read(nvram, addr) << 8;
- tmp |= m48t59_read(nvram, addr + 1);
-
- return tmp;
-}
-
-void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
-{
- m48t59_write(nvram, addr, value >> 24);
- m48t59_write(nvram, addr + 1, (value >> 16) & 0xFF);
- m48t59_write(nvram, addr + 2, (value >> 8) & 0xFF);
- m48t59_write(nvram, addr + 3, value & 0xFF);
-}
-
-uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
-{
- uint32_t tmp;
-
- tmp = m48t59_read(nvram, addr) << 24;
- tmp |= m48t59_read(nvram, addr + 1) << 16;
- tmp |= m48t59_read(nvram, addr + 2) << 8;
- tmp |= m48t59_read(nvram, addr + 3);
-
- return tmp;
-}
-
-void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
- const unsigned char *str, uint32_t max)
-{
- int i;
-
- for (i = 0; i < max && str[i] != '\0'; i++) {
- m48t59_write(nvram, addr + i, str[i]);
- }
- m48t59_write(nvram, addr + max - 1, '\0');
-}
-
-int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
-{
- int i;
-
- memset(dst, 0, max);
- for (i = 0; i < max; i++) {
- dst[i] = NVRAM_get_byte(nvram, addr + i);
- if (dst[i] == '\0')
- break;
- }
-
- return i;
-}
-
-static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
-{
- uint16_t tmp;
- uint16_t pd, pd1, pd2;
-
- tmp = prev >> 8;
- pd = prev ^ value;
- pd1 = pd & 0x000F;
- pd2 = ((pd >> 4) & 0x000F) ^ pd1;
- tmp ^= (pd1 << 3) | (pd1 << 8);
- tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
-
- return tmp;
-}
-
-uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
-{
- uint32_t i;
- uint16_t crc = 0xFFFF;
- int odd;
-
- odd = count & 1;
- count &= ~1;
- for (i = 0; i != count; i++) {
- crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
- }
- if (odd) {
- crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
- }
-
- return crc;
-}
-
-extern int nographic;
-
-int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
- const unsigned char *arch,
- uint32_t RAM_size, int boot_device,
- uint32_t kernel_image, uint32_t kernel_size,
- const char *cmdline,
- uint32_t initrd_image, uint32_t initrd_size,
- uint32_t NVRAM_image,
- int width, int height, int depth)
-{
- uint16_t crc;
-
- /* Set parameters for Open Hack'Ware BIOS */
- NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
- NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
- NVRAM_set_word(nvram, 0x14, NVRAM_size);
- NVRAM_set_string(nvram, 0x20, arch, 16);
- NVRAM_set_byte(nvram, 0x2f, nographic & 0xff);
- NVRAM_set_lword(nvram, 0x30, RAM_size);
- NVRAM_set_byte(nvram, 0x34, boot_device);
- NVRAM_set_lword(nvram, 0x38, kernel_image);
- NVRAM_set_lword(nvram, 0x3C, kernel_size);
- if (cmdline) {
- /* XXX: put the cmdline in NVRAM too ? */
- strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
- NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
- NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
- } else {
- NVRAM_set_lword(nvram, 0x40, 0);
- NVRAM_set_lword(nvram, 0x44, 0);
- }
- NVRAM_set_lword(nvram, 0x48, initrd_image);
- NVRAM_set_lword(nvram, 0x4C, initrd_size);
- NVRAM_set_lword(nvram, 0x50, NVRAM_image);
-
- NVRAM_set_word(nvram, 0x54, width);
- NVRAM_set_word(nvram, 0x56, height);
- NVRAM_set_word(nvram, 0x58, depth);
- crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
- NVRAM_set_word(nvram, 0xFC, crc);
-
- return 0;
-}
-
-void pic_info()
-{
-}
-
-void irq_info()
-{
-}
-
-void pic_set_irq(int irq, int level)
-{
-}
-
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
-}
-
-void qemu_system_powerdown(void)
-{
-}
-
-static void main_cpu_reset(void *opaque)
-{
- CPUState *env = opaque;
- cpu_reset(env);
-}
-
-static const int ide_iobase[2] = { 0x1f0, 0x170 };
-static const int ide_iobase2[2] = { 0x3f6, 0x376 };
-static const int ide_irq[2] = { 14, 15 };
-
-static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
-static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
-
-static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
-static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
-
-static fdctrl_t *floppy_controller;
-
-/* Sun4u hardware initialisation */
-static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- CPUState *env;
- char buf[1024];
- m48t59_t *nvram;
- int ret, linux_boot;
- unsigned int i;
- long prom_offset, initrd_size, kernel_size;
- PCIBus *pci_bus;
-
- linux_boot = (kernel_filename != NULL);
-
- env = cpu_init();
- register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
- qemu_register_reset(main_cpu_reset, env);
-
- /* allocate RAM */
- cpu_register_physical_memory(0, ram_size, 0);
-
- prom_offset = ram_size + vga_ram_size;
- cpu_register_physical_memory(PROM_ADDR,
- (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
- prom_offset | IO_MEM_ROM);
-
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
- ret = load_elf(buf, 0, NULL);
- if (ret < 0) {
- fprintf(stderr, "qemu: could not load prom '%s'\n",
- buf);
- exit(1);
- }
-
- kernel_size = 0;
- initrd_size = 0;
- if (linux_boot) {
- /* XXX: put correct offset */
- kernel_size = load_elf(kernel_filename, 0, NULL);
- if (kernel_size < 0)
- kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
- if (kernel_size < 0)
- kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
- if (kernel_size < 0) {
- fprintf(stderr, "qemu: could not load kernel '%s'\n",
- kernel_filename);
- exit(1);
- }
-
- /* load initrd */
- if (initrd_filename) {
- initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
- if (initrd_size < 0) {
- fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- initrd_filename);
- exit(1);
- }
- }
- if (initrd_size > 0) {
- for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
- if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i)
- == 0x48647253) { // HdrS
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR);
- stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size);
- break;
- }
- }
- }
- }
- pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL);
- isa_mem_base = VGA_BASE;
- pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size);
-
- for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- if (serial_hds[i]) {
- serial_init(&pic_set_irq_new, NULL,
- serial_io[i], serial_irq[i], serial_hds[i]);
- }
- }
-
- for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
- if (parallel_hds[i]) {
- parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
- }
- }
-
- for(i = 0; i < nb_nics; i++) {
- if (!nd_table[i].model)
- nd_table[i].model = "ne2k_pci";
- pci_nic_init(pci_bus, &nd_table[i]);
- }
-
- pci_cmd646_ide_init(pci_bus, bs_table, 1);
- kbd_init();
- floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
- nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
- sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device,
- KERNEL_LOAD_ADDR, kernel_size,
- kernel_cmdline,
- INITRD_LOAD_ADDR, initrd_size,
- /* XXX: need an option to load a NVRAM image */
- 0,
- graphic_width, graphic_height, graphic_depth);
-
-}
-
-QEMUMachine sun4u_machine = {
- "sun4u",
- "Sun4u platform",
- sun4u_init,
-};
diff --git a/hw/tc58128.c b/hw/tc58128.c
deleted file mode 100644
index a8b26f7..0000000
--- a/hw/tc58128.c
+++ /dev/null
@@ -1,181 +0,0 @@
-#include <assert.h>
-#include "vl.h"
-
-#define CE1 0x0100
-#define CE2 0x0200
-#define RE 0x0400
-#define WE 0x0800
-#define ALE 0x1000
-#define CLE 0x2000
-#define RDY1 0x4000
-#define RDY2 0x8000
-#define RDY(n) ((n) == 0 ? RDY1 : RDY2)
-
-typedef enum { WAIT, READ1, READ2, READ3 } state_t;
-
-typedef struct {
- uint8_t *flash_contents;
- state_t state;
- uint32_t address;
- uint8_t address_cycle;
-} tc58128_dev;
-
-static tc58128_dev tc58128_devs[2];
-
-#define FLASH_SIZE (16*1024*1024)
-
-void init_dev(tc58128_dev * dev, char *filename)
-{
- int ret, blocks;
-
- dev->state = WAIT;
- dev->flash_contents = qemu_mallocz(FLASH_SIZE);
- memset(dev->flash_contents, 0xff, FLASH_SIZE);
- if (!dev->flash_contents) {
- fprintf(stderr, "could not alloc memory for flash\n");
- exit(1);
- }
- if (filename) {
- /* Load flash image skipping the first block */
- ret = load_image(filename, dev->flash_contents + 528 * 32);
- if (ret < 0) {
- fprintf(stderr, "ret=%d\n", ret);
- fprintf(stderr, "qemu: could not load flash image %s\n",
- filename);
- exit(1);
- } else {
- /* Build first block with number of blocks */
- blocks = (ret + 528 * 32 - 1) / (528 * 32);
- dev->flash_contents[0] = blocks & 0xff;
- dev->flash_contents[1] = (blocks >> 8) & 0xff;
- dev->flash_contents[2] = (blocks >> 16) & 0xff;
- dev->flash_contents[3] = (blocks >> 24) & 0xff;
- fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
- filename);
- }
- }
-}
-
-void handle_command(tc58128_dev * dev, uint8_t command)
-{
- switch (command) {
- case 0xff:
- fprintf(stderr, "reset flash device\n");
- dev->state = WAIT;
- break;
- case 0x00:
- fprintf(stderr, "read mode 1\n");
- dev->state = READ1;
- dev->address_cycle = 0;
- break;
- case 0x01:
- fprintf(stderr, "read mode 2\n");
- dev->state = READ2;
- dev->address_cycle = 0;
- break;
- case 0x50:
- fprintf(stderr, "read mode 3\n");
- dev->state = READ3;
- dev->address_cycle = 0;
- break;
- default:
- fprintf(stderr, "unknown flash command 0x%02x\n", command);
- assert(0);
- }
-}
-
-void handle_address(tc58128_dev * dev, uint8_t data)
-{
- switch (dev->state) {
- case READ1:
- case READ2:
- case READ3:
- switch (dev->address_cycle) {
- case 0:
- dev->address = data;
- if (dev->state == READ2)
- dev->address |= 0x100;
- else if (dev->state == READ3)
- dev->address |= 0x200;
- break;
- case 1:
- dev->address += data * 528 * 0x100;
- break;
- case 2:
- dev->address += data * 528;
- fprintf(stderr, "address pointer in flash: 0x%08x\n",
- dev->address);
- break;
- default:
- /* Invalid data */
- assert(0);
- }
- dev->address_cycle++;
- break;
- default:
- assert(0);
- }
-}
-
-uint8_t handle_read(tc58128_dev * dev)
-{
-#if 0
- if (dev->address % 0x100000 == 0)
- fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
-#endif
- return dev->flash_contents[dev->address++];
-}
-
-/* We never mark the device as busy, so interrupts cannot be triggered
- XXXXX */
-
-int tc58128_cb(uint16_t porta, uint16_t portb,
- uint16_t * periph_pdtra, uint16_t * periph_portadir,
- uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
-{
- int dev;
-
- if ((porta & CE1) == 0)
- dev = 0;
- else if ((porta & CE2) == 0)
- dev = 1;
- else
- return 0; /* No device selected */
-
- if ((porta & RE) && (porta & WE)) {
- /* Nothing to do, assert ready and return to input state */
- *periph_portadir &= 0xff00;
- *periph_portadir |= RDY(dev);
- *periph_pdtra |= RDY(dev);
- return 1;
- }
-
- if (porta & CLE) {
- /* Command */
- assert((porta & WE) == 0);
- handle_command(&tc58128_devs[dev], porta & 0x00ff);
- } else if (porta & ALE) {
- assert((porta & WE) == 0);
- handle_address(&tc58128_devs[dev], porta & 0x00ff);
- } else if ((porta & RE) == 0) {
- *periph_portadir |= 0x00ff;
- *periph_pdtra &= 0xff00;
- *periph_pdtra |= handle_read(&tc58128_devs[dev]);
- } else {
- assert(0);
- }
- return 1;
-}
-
-static sh7750_io_device tc58128 = {
- RE | WE, /* Port A triggers */
- 0, /* Port B triggers */
- tc58128_cb /* Callback */
-};
-
-int tc58128_init(struct SH7750State *s, char *zone1, char *zone2)
-{
- init_dev(&tc58128_devs[0], zone1);
- init_dev(&tc58128_devs[1], zone2);
- return sh7750_register_io_device(s, &tc58128);
-}
diff --git a/hw/tcx.c b/hw/tcx.c
deleted file mode 100644
index a3a2114..0000000
--- a/hw/tcx.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * QEMU TCX Frame buffer
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-#define MAXX 1024
-#define MAXY 768
-#define TCX_DAC_NREGS 16
-
-typedef struct TCXState {
- uint32_t addr;
- DisplayState *ds;
- uint8_t *vram;
- unsigned long vram_offset;
- uint16_t width, height;
- uint8_t r[256], g[256], b[256];
- uint8_t dac_index, dac_state;
-} TCXState;
-
-static void tcx_screen_dump(void *opaque, const char *filename);
-
-static void tcx_draw_line32(TCXState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- int x;
- uint8_t val;
-
- for(x = 0; x < width; x++) {
- val = *s++;
- *d++ = s1->b[val];
- *d++ = s1->g[val];
- *d++ = s1->r[val];
- d++;
- }
-}
-
-static void tcx_draw_line24(TCXState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- int x;
- uint8_t val;
-
- for(x = 0; x < width; x++) {
- val = *s++;
- *d++ = s1->b[val];
- *d++ = s1->g[val];
- *d++ = s1->r[val];
- }
-}
-
-static void tcx_draw_line8(TCXState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- int x;
- uint8_t val;
-
- for(x = 0; x < width; x++) {
- val = *s++;
- /* XXX translate between palettes? */
- *d++ = val;
- }
-}
-
-/* Fixed line length 1024 allows us to do nice tricks not possible on
- VGA... */
-static void tcx_update_display(void *opaque)
-{
- TCXState *ts = opaque;
- uint32_t page;
- int y, page_min, page_max, y_start, dd, ds;
- uint8_t *d, *s;
- void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);
-
- if (ts->ds->depth == 0)
- return;
- page = ts->vram_offset;
- y_start = -1;
- page_min = 0x7fffffff;
- page_max = -1;
- d = ts->ds->data;
- s = ts->vram;
- dd = ts->ds->linesize;
- ds = 1024;
-
- switch (ts->ds->depth) {
- case 32:
- f = tcx_draw_line32;
- break;
- case 24:
- f = tcx_draw_line24;
- break;
- default:
- case 8:
- f = tcx_draw_line8;
- break;
- case 0:
- return;
- }
-
- for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
- if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
- if (y_start < 0)
- y_start = y;
- if (page < page_min)
- page_min = page;
- if (page > page_max)
- page_max = page;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- f(ts, d, s, ts->width);
- d += dd;
- s += ds;
- } else {
- if (y_start >= 0) {
- /* flush to display */
- dpy_update(ts->ds, 0, y_start,
- ts->width, y - y_start);
- y_start = -1;
- }
- d += dd * 4;
- s += ds * 4;
- }
- }
- if (y_start >= 0) {
- /* flush to display */
- dpy_update(ts->ds, 0, y_start,
- ts->width, y - y_start);
- }
- /* reset modified pages */
- if (page_max != -1) {
- cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
- VGA_DIRTY_FLAG);
- }
-}
-
-static void tcx_invalidate_display(void *opaque)
-{
- TCXState *s = opaque;
- int i;
-
- for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
- cpu_physical_memory_set_dirty(s->vram_offset + i);
- }
-}
-
-static void tcx_save(QEMUFile *f, void *opaque)
-{
- TCXState *s = opaque;
-
- qemu_put_be32s(f, (uint32_t *)&s->addr);
- qemu_put_be32s(f, (uint32_t *)&s->vram);
- qemu_put_be16s(f, (uint16_t *)&s->height);
- qemu_put_be16s(f, (uint16_t *)&s->width);
- qemu_put_buffer(f, s->r, 256);
- qemu_put_buffer(f, s->g, 256);
- qemu_put_buffer(f, s->b, 256);
- qemu_put_8s(f, &s->dac_index);
- qemu_put_8s(f, &s->dac_state);
-}
-
-static int tcx_load(QEMUFile *f, void *opaque, int version_id)
-{
- TCXState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, (uint32_t *)&s->addr);
- qemu_get_be32s(f, (uint32_t *)&s->vram);
- qemu_get_be16s(f, (uint16_t *)&s->height);
- qemu_get_be16s(f, (uint16_t *)&s->width);
- qemu_get_buffer(f, s->r, 256);
- qemu_get_buffer(f, s->g, 256);
- qemu_get_buffer(f, s->b, 256);
- qemu_get_8s(f, &s->dac_index);
- qemu_get_8s(f, &s->dac_state);
- return 0;
-}
-
-static void tcx_reset(void *opaque)
-{
- TCXState *s = opaque;
-
- /* Initialize palette */
- memset(s->r, 0, 256);
- memset(s->g, 0, 256);
- memset(s->b, 0, 256);
- s->r[255] = s->g[255] = s->b[255] = 255;
- memset(s->vram, 0, MAXX*MAXY);
- cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,
- VGA_DIRTY_FLAG);
- s->dac_index = 0;
- s->dac_state = 0;
-}
-
-static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
-{
- return 0;
-}
-
-static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- TCXState *s = opaque;
- uint32_t saddr;
-
- saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;
- switch (saddr) {
- case 0:
- s->dac_index = val >> 24;
- s->dac_state = 0;
- break;
- case 1:
- switch (s->dac_state) {
- case 0:
- s->r[s->dac_index] = val >> 24;
- s->dac_state++;
- break;
- case 1:
- s->g[s->dac_index] = val >> 24;
- s->dac_state++;
- break;
- case 2:
- s->b[s->dac_index] = val >> 24;
- default:
- s->dac_state = 0;
- break;
- }
- break;
- default:
- break;
- }
- return;
-}
-
-static CPUReadMemoryFunc *tcx_dac_read[3] = {
- tcx_dac_readl,
- tcx_dac_readl,
- tcx_dac_readl,
-};
-
-static CPUWriteMemoryFunc *tcx_dac_write[3] = {
- tcx_dac_writel,
- tcx_dac_writel,
- tcx_dac_writel,
-};
-
-void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
- unsigned long vram_offset, int vram_size, int width, int height)
-{
- TCXState *s;
- int io_memory;
-
- s = qemu_mallocz(sizeof(TCXState));
- if (!s)
- return;
- s->ds = ds;
- s->addr = addr;
- s->vram = vram_base;
- s->vram_offset = vram_offset;
- s->width = width;
- s->height = height;
-
- cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset);
- io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
- cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory);
-
- graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display,
- tcx_screen_dump, s);
- register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
- qemu_register_reset(tcx_reset, s);
- tcx_reset(s);
- dpy_resize(s->ds, width, height);
-}
-
-static void tcx_screen_dump(void *opaque, const char *filename)
-{
- TCXState *s = opaque;
- FILE *f;
- uint8_t *d, *d1, v;
- int y, x;
-
- f = fopen(filename, "wb");
- if (!f)
- return;
- fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
- d1 = s->vram;
- for(y = 0; y < s->height; y++) {
- d = d1;
- for(x = 0; x < s->width; x++) {
- v = *d;
- fputc(s->r[v], f);
- fputc(s->g[v], f);
- fputc(s->b[v], f);
- d++;
- }
- d1 += MAXX;
- }
- fclose(f);
- return;
-}
-
-
-
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
deleted file mode 100644
index a7e3600..0000000
--- a/hw/unin_pci.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * QEMU Uninorth PCI host (for all Mac99 and newer machines)
- *
- * Copyright (c) 2006 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-typedef target_phys_addr_t pci_addr_t;
-#include "pci_host.h"
-
-typedef PCIHostState UNINState;
-
-static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- UNINState *s = opaque;
- int i;
-
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
-
- for (i = 11; i < 32; i++) {
- if ((val & (1 << i)) != 0)
- break;
- }
-#if 0
- s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11);
-#else
- s->config_reg = 0x80000000 | (0 << 16) | (val & 0x7FC) | (i << 11);
-#endif
-}
-
-static uint32_t pci_unin_main_config_readl (void *opaque,
- target_phys_addr_t addr)
-{
- UNINState *s = opaque;
- uint32_t val;
- int devfn;
-
- devfn = (s->config_reg >> 8) & 0xFF;
- val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
-
- return val;
-}
-
-static CPUWriteMemoryFunc *pci_unin_main_config_write[] = {
- &pci_unin_main_config_writel,
- &pci_unin_main_config_writel,
- &pci_unin_main_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_main_config_read[] = {
- &pci_unin_main_config_readl,
- &pci_unin_main_config_readl,
- &pci_unin_main_config_readl,
-};
-
-static CPUWriteMemoryFunc *pci_unin_main_write[] = {
- &pci_host_data_writeb,
- &pci_host_data_writew,
- &pci_host_data_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_main_read[] = {
- &pci_host_data_readb,
- &pci_host_data_readw,
- &pci_host_data_readl,
-};
-
-#if 0
-
-static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- UNINState *s = opaque;
-
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- s->config_reg = 0x80000000 | (val & ~0x00000001);
-}
-
-static uint32_t pci_unin_config_readl (void *opaque,
- target_phys_addr_t addr)
-{
- UNINState *s = opaque;
- uint32_t val;
-
- val = (s->config_reg | 0x00000001) & ~0x80000000;
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
-
- return val;
-}
-
-static CPUWriteMemoryFunc *pci_unin_config_write[] = {
- &pci_unin_config_writel,
- &pci_unin_config_writel,
- &pci_unin_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_config_read[] = {
- &pci_unin_config_readl,
- &pci_unin_config_readl,
- &pci_unin_config_readl,
-};
-
-static CPUWriteMemoryFunc *pci_unin_write[] = {
- &pci_host_pci_writeb,
- &pci_host_pci_writew,
- &pci_host_pci_writel,
-};
-
-static CPUReadMemoryFunc *pci_unin_read[] = {
- &pci_host_pci_readb,
- &pci_host_pci_readw,
- &pci_host_pci_readl,
-};
-#endif
-
-static void pci_unin_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
-{
- openpic_set_irq(pic, d->config[PCI_INTERRUPT_LINE], level);
-}
-
-PCIBus *pci_pmac_init(void *pic)
-{
- UNINState *s;
- PCIDevice *d;
- int pci_mem_config, pci_mem_data;
-
- /* Use values found on a real PowerMac */
- /* Uninorth main bus */
- s = qemu_mallocz(sizeof(UNINState));
- s->bus = pci_register_bus(pci_unin_set_irq, NULL, 11 << 3);
-
- pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read,
- pci_unin_main_config_write, s);
- pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
- pci_unin_main_write, s);
- cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config);
- cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data);
- d = pci_register_device(s->bus, "Uni-north main", sizeof(PCIDevice),
- 11 << 3, NULL, NULL);
- d->config[0x00] = 0x6b; // vendor_id : Apple
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x1F; // device_id
- d->config[0x03] = 0x00;
- d->config[0x08] = 0x00; // revision
- d->config[0x0A] = 0x00; // class_sub = pci host
- d->config[0x0B] = 0x06; // class_base = PCI_bridge
- d->config[0x0C] = 0x08; // cache_line_size
- d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
- d->config[0x34] = 0x00; // capabilities_pointer
-
-#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly
- /* pci-to-pci bridge */
- d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
- NULL, NULL);
- d->config[0x00] = 0x11; // vendor_id : TI
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x26; // device_id
- d->config[0x03] = 0x00;
- d->config[0x08] = 0x05; // revision
- d->config[0x0A] = 0x04; // class_sub = pci2pci
- d->config[0x0B] = 0x06; // class_base = PCI_bridge
- d->config[0x0C] = 0x08; // cache_line_size
- d->config[0x0D] = 0x20; // latency_timer
- d->config[0x0E] = 0x01; // header_type
-
- d->config[0x18] = 0x01; // primary_bus
- d->config[0x19] = 0x02; // secondary_bus
- d->config[0x1A] = 0x02; // subordinate_bus
- d->config[0x1B] = 0x20; // secondary_latency_timer
- d->config[0x1C] = 0x11; // io_base
- d->config[0x1D] = 0x01; // io_limit
- d->config[0x20] = 0x00; // memory_base
- d->config[0x21] = 0x80;
- d->config[0x22] = 0x00; // memory_limit
- d->config[0x23] = 0x80;
- d->config[0x24] = 0x01; // prefetchable_memory_base
- d->config[0x25] = 0x80;
- d->config[0x26] = 0xF1; // prefectchable_memory_limit
- d->config[0x27] = 0x7F;
- // d->config[0x34] = 0xdc // capabilities_pointer
-#endif
-#if 0 // XXX: not needed for now
- /* Uninorth AGP bus */
- s = &pci_bridge[1];
- pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
- pci_unin_config_write, s);
- pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
- pci_unin_write, s);
- cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
- cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);
-
- d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3,
- NULL, NULL);
- d->config[0x00] = 0x6b; // vendor_id : Apple
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x20; // device_id
- d->config[0x03] = 0x00;
- d->config[0x08] = 0x00; // revision
- d->config[0x0A] = 0x00; // class_sub = pci host
- d->config[0x0B] = 0x06; // class_base = PCI_bridge
- d->config[0x0C] = 0x08; // cache_line_size
- d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
- // d->config[0x34] = 0x80; // capabilities_pointer
-#endif
-
-#if 0 // XXX: not needed for now
- /* Uninorth internal bus */
- s = &pci_bridge[2];
- pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
- pci_unin_config_write, s);
- pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
- pci_unin_write, s);
- cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config);
- cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data);
-
- d = pci_register_device("Uni-north internal", sizeof(PCIDevice),
- 3, 11 << 3, NULL, NULL);
- d->config[0x00] = 0x6b; // vendor_id : Apple
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x1E; // device_id
- d->config[0x03] = 0x00;
- d->config[0x08] = 0x00; // revision
- d->config[0x0A] = 0x00; // class_sub = pci host
- d->config[0x0B] = 0x06; // class_base = PCI_bridge
- d->config[0x0C] = 0x08; // cache_line_size
- d->config[0x0D] = 0x10; // latency_timer
- d->config[0x0E] = 0x00; // header_type
- d->config[0x34] = 0x00; // capabilities_pointer
-#endif
- return s->bus;
-}
-
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 8fc0b74..93f46db 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -323,10 +323,16 @@ static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
return l;
}
-static void usb_mouse_handle_reset(USBDevice *dev)
+static void usb_mouse_handle_reset(USBDevice *dev, int destroy)
{
USBMouseState *s = (USBMouseState *)dev;
+ if (destroy) {
+ qemu_add_mouse_event_handler(NULL, NULL, 0);
+ qemu_free(s);
+ return;
+ }
+
s->dx = 0;
s->dy = 0;
s->dz = 0;
@@ -500,14 +506,6 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
return ret;
}
-static void usb_mouse_handle_destroy(USBDevice *dev)
-{
- USBMouseState *s = (USBMouseState *)dev;
-
- qemu_add_mouse_event_handler(NULL, NULL, 0);
- qemu_free(s);
-}
-
USBDevice *usb_tablet_init(void)
{
USBMouseState *s;
@@ -521,7 +519,6 @@ USBDevice *usb_tablet_init(void)
s->dev.handle_reset = usb_mouse_handle_reset;
s->dev.handle_control = usb_mouse_handle_control;
s->dev.handle_data = usb_mouse_handle_data;
- s->dev.handle_destroy = usb_mouse_handle_destroy;
s->kind = USB_TABLET;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
@@ -542,7 +539,6 @@ USBDevice *usb_mouse_init(void)
s->dev.handle_reset = usb_mouse_handle_reset;
s->dev.handle_control = usb_mouse_handle_control;
s->dev.handle_data = usb_mouse_handle_data;
- s->dev.handle_destroy = usb_mouse_handle_destroy;
s->kind = USB_MOUSE;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 8350931..2eba905 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -199,9 +199,11 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
}
}
-static void usb_hub_handle_reset(USBDevice *dev)
+static void usb_hub_handle_reset(USBDevice *dev, int destroy)
{
/* XXX: do it */
+ if (destroy)
+ qemu_free(dev);
}
static int usb_hub_handle_control(USBDevice *dev, int request, int value,
@@ -523,13 +525,6 @@ static int usb_hub_handle_packet(USBDevice *dev, int pid,
return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
}
-static void usb_hub_handle_destroy(USBDevice *dev)
-{
- USBHubState *s = (USBHubState *)dev;
-
- qemu_free(s);
-}
-
USBDevice *usb_hub_init(int nb_ports)
{
USBHubState *s;
@@ -548,7 +543,6 @@ USBDevice *usb_hub_init(int nb_ports)
s->dev.handle_reset = usb_hub_handle_reset;
s->dev.handle_control = usb_hub_handle_control;
s->dev.handle_data = usb_hub_handle_data;
- s->dev.handle_destroy = usb_hub_handle_destroy;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub");
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index ff2047d..3dccfb9 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -112,12 +112,16 @@ static void usb_msd_command_complete(void *opaque, uint32_t tag, int fail)
s->mode = USB_MSDM_CSW;
}
-static void usb_msd_handle_reset(USBDevice *dev)
+static void usb_msd_handle_reset(USBDevice *dev, int destroy)
{
MSDState *s = (MSDState *)dev;
DPRINTF("Reset\n");
s->mode = USB_MSDM_CBW;
+ if (destroy) {
+ scsi_disk_destroy(s->scsi_dev);
+ qemu_free(s);
+ }
}
static int usb_msd_handle_control(USBDevice *dev, int request, int value,
@@ -365,13 +369,6 @@ static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep,
return ret;
}
-static void usb_msd_handle_destroy(USBDevice *dev)
-{
- MSDState *s = (MSDState *)dev;
-
- scsi_disk_destroy(s->scsi_dev);
- qemu_free(s);
-}
USBDevice *usb_msd_init(const char *filename)
{
@@ -391,12 +388,11 @@ USBDevice *usb_msd_init(const char *filename)
s->dev.handle_reset = usb_msd_handle_reset;
s->dev.handle_control = usb_msd_handle_control;
s->dev.handle_data = usb_msd_handle_data;
- s->dev.handle_destroy = usb_msd_handle_destroy;
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
filename);
s->scsi_dev = scsi_disk_init(bdrv, usb_msd_command_complete, s);
- usb_msd_handle_reset((USBDevice *)s);
+ usb_msd_handle_reset((USBDevice *)s, 0);
return (USBDevice *)s;
}
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
deleted file mode 100644
index 1a6e013..0000000
--- a/hw/usb-uhci.c
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * USB UHCI controller emulation
- *
- * Copyright (c) 2005 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-
-//#define DEBUG
-//#define DEBUG_PACKET
-
-#define UHCI_CMD_GRESET (1 << 2)
-#define UHCI_CMD_HCRESET (1 << 1)
-#define UHCI_CMD_RS (1 << 0)
-
-#define UHCI_STS_HCHALTED (1 << 5)
-#define UHCI_STS_HCPERR (1 << 4)
-#define UHCI_STS_HSERR (1 << 3)
-#define UHCI_STS_RD (1 << 2)
-#define UHCI_STS_USBERR (1 << 1)
-#define UHCI_STS_USBINT (1 << 0)
-
-#define TD_CTRL_SPD (1 << 29)
-#define TD_CTRL_ERROR_SHIFT 27
-#define TD_CTRL_IOS (1 << 25)
-#define TD_CTRL_IOC (1 << 24)
-#define TD_CTRL_ACTIVE (1 << 23)
-#define TD_CTRL_STALL (1 << 22)
-#define TD_CTRL_BABBLE (1 << 20)
-#define TD_CTRL_NAK (1 << 19)
-#define TD_CTRL_TIMEOUT (1 << 18)
-
-#define UHCI_PORT_RESET (1 << 9)
-#define UHCI_PORT_LSDA (1 << 8)
-#define UHCI_PORT_ENC (1 << 3)
-#define UHCI_PORT_EN (1 << 2)
-#define UHCI_PORT_CSC (1 << 1)
-#define UHCI_PORT_CCS (1 << 0)
-
-#define FRAME_TIMER_FREQ 1000
-
-#define FRAME_MAX_LOOPS 100
-
-#define NB_PORTS 2
-
-typedef struct UHCIPort {
- USBPort port;
- uint16_t ctrl;
-} UHCIPort;
-
-typedef struct UHCIState {
- PCIDevice dev;
- uint16_t cmd; /* cmd register */
- uint16_t status;
- uint16_t intr; /* interrupt enable register */
- uint16_t frnum; /* frame number */
- uint32_t fl_base_addr; /* frame list base address */
- uint8_t sof_timing;
- uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
- QEMUTimer *frame_timer;
- UHCIPort ports[NB_PORTS];
-} UHCIState;
-
-typedef struct UHCI_TD {
- uint32_t link;
- uint32_t ctrl; /* see TD_CTRL_xxx */
- uint32_t token;
- uint32_t buffer;
-} UHCI_TD;
-
-typedef struct UHCI_QH {
- uint32_t link;
- uint32_t el_link;
-} UHCI_QH;
-
-static void uhci_attach(USBPort *port1, USBDevice *dev);
-
-static void uhci_update_irq(UHCIState *s)
-{
- int level;
- if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
- ((s->status2 & 2) && (s->intr & (1 << 3))) ||
- ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
- ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
- (s->status & UHCI_STS_HSERR) ||
- (s->status & UHCI_STS_HCPERR)) {
- level = 1;
- } else {
- level = 0;
- }
- pci_set_irq(&s->dev, 3, level);
-}
-
-static void uhci_reset(UHCIState *s)
-{
- uint8_t *pci_conf;
- int i;
- UHCIPort *port;
-
- pci_conf = s->dev.config;
-
- pci_conf[0x6a] = 0x01; /* usb clock */
- pci_conf[0x6b] = 0x00;
- s->cmd = 0;
- s->status = 0;
- s->status2 = 0;
- s->intr = 0;
- s->fl_base_addr = 0;
- s->sof_timing = 64;
- for(i = 0; i < NB_PORTS; i++) {
- port = &s->ports[i];
- port->ctrl = 0x0080;
- if (port->port.dev)
- uhci_attach(&port->port, port->port.dev);
- }
-}
-
-static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
- UHCIState *s = opaque;
-
- addr &= 0x1f;
- switch(addr) {
- case 0x0c:
- s->sof_timing = val;
- break;
- }
-}
-
-static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
-{
- UHCIState *s = opaque;
- uint32_t val;
-
- addr &= 0x1f;
- switch(addr) {
- case 0x0c:
- val = s->sof_timing;
- break;
- default:
- val = 0xff;
- break;
- }
- return val;
-}
-
-static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
- UHCIState *s = opaque;
-
- addr &= 0x1f;
-#ifdef DEBUG
- printf("uhci writew port=0x%04x val=0x%04x\n", addr, val);
-#endif
- switch(addr) {
- case 0x00:
- if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
- /* start frame processing */
- qemu_mod_timer(s->frame_timer, qemu_get_clock(vm_clock));
- s->status &= ~UHCI_STS_HCHALTED;
- } else if (!(val & UHCI_CMD_RS)) {
- s->status |= UHCI_STS_HCHALTED;
- }
- if (val & UHCI_CMD_GRESET) {
- UHCIPort *port;
- USBDevice *dev;
- int i;
-
- /* send reset on the USB bus */
- for(i = 0; i < NB_PORTS; i++) {
- port = &s->ports[i];
- dev = port->port.dev;
- if (dev) {
- dev->handle_packet(dev,
- USB_MSG_RESET, 0, 0, NULL, 0);
- }
- }
- uhci_reset(s);
- return;
- }
- if (val & UHCI_CMD_HCRESET) {
- uhci_reset(s);
- return;
- }
- s->cmd = val;
- break;
- case 0x02:
- s->status &= ~val;
- /* XXX: the chip spec is not coherent, so we add a hidden
- register to distinguish between IOC and SPD */
- if (val & UHCI_STS_USBINT)
- s->status2 = 0;
- uhci_update_irq(s);
- break;
- case 0x04:
- s->intr = val;
- uhci_update_irq(s);
- break;
- case 0x06:
- if (s->status & UHCI_STS_HCHALTED)
- s->frnum = val & 0x7ff;
- break;
- case 0x10 ... 0x1f:
- {
- UHCIPort *port;
- USBDevice *dev;
- int n;
-
- n = (addr >> 1) & 7;
- if (n >= NB_PORTS)
- return;
- port = &s->ports[n];
- dev = port->port.dev;
- if (dev) {
- /* port reset */
- if ( (val & UHCI_PORT_RESET) &&
- !(port->ctrl & UHCI_PORT_RESET) ) {
- dev->handle_packet(dev,
- USB_MSG_RESET, 0, 0, NULL, 0);
- }
- }
- port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
- /* some bits are reset when a '1' is written to them */
- port->ctrl &= ~(val & 0x000a);
- }
- break;
- }
-}
-
-static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
-{
- UHCIState *s = opaque;
- uint32_t val;
-
- addr &= 0x1f;
- switch(addr) {
- case 0x00:
- val = s->cmd;
- break;
- case 0x02:
- val = s->status;
- break;
- case 0x04:
- val = s->intr;
- break;
- case 0x06:
- val = s->frnum;
- break;
- case 0x10 ... 0x1f:
- {
- UHCIPort *port;
- int n;
- n = (addr >> 1) & 7;
- if (n >= NB_PORTS)
- goto read_default;
- port = &s->ports[n];
- val = port->ctrl;
- }
- break;
- default:
- read_default:
- val = 0xff7f; /* disabled port */
- break;
- }
-#ifdef DEBUG
- printf("uhci readw port=0x%04x val=0x%04x\n", addr, val);
-#endif
- return val;
-}
-
-static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
-{
- UHCIState *s = opaque;
-
- addr &= 0x1f;
-#ifdef DEBUG
- printf("uhci writel port=0x%04x val=0x%08x\n", addr, val);
-#endif
- switch(addr) {
- case 0x08:
- s->fl_base_addr = val & ~0xfff;
- break;
- }
-}
-
-static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
-{
- UHCIState *s = opaque;
- uint32_t val;
-
- addr &= 0x1f;
- switch(addr) {
- case 0x08:
- val = s->fl_base_addr;
- break;
- default:
- val = 0xffffffff;
- break;
- }
- return val;
-}
-
-static void uhci_attach(USBPort *port1, USBDevice *dev)
-{
- UHCIState *s = port1->opaque;
- UHCIPort *port = &s->ports[port1->index];
-
- if (dev) {
- if (port->port.dev) {
- usb_attach(port1, NULL);
- }
- /* set connect status */
- port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
-
- /* update speed */
- if (dev->speed == USB_SPEED_LOW)
- port->ctrl |= UHCI_PORT_LSDA;
- else
- port->ctrl &= ~UHCI_PORT_LSDA;
- port->port.dev = dev;
- /* send the attach message */
- dev->handle_packet(dev,
- USB_MSG_ATTACH, 0, 0, NULL, 0);
- } else {
- /* set connect status */
- if (port->ctrl & UHCI_PORT_CCS) {
- port->ctrl &= ~UHCI_PORT_CCS;
- port->ctrl |= UHCI_PORT_CSC;
- }
- /* disable port */
- if (port->ctrl & UHCI_PORT_EN) {
- port->ctrl &= ~UHCI_PORT_EN;
- port->ctrl |= UHCI_PORT_ENC;
- }
- dev = port->port.dev;
- if (dev) {
- /* send the detach message */
- dev->handle_packet(dev,
- USB_MSG_DETACH, 0, 0, NULL, 0);
- }
- port->port.dev = NULL;
- }
-}
-
-static int uhci_broadcast_packet(UHCIState *s, uint8_t pid,
- uint8_t devaddr, uint8_t devep,
- uint8_t *data, int len)
-{
- UHCIPort *port;
- USBDevice *dev;
- int i, ret;
-
-#ifdef DEBUG_PACKET
- {
- const char *pidstr;
- switch(pid) {
- case USB_TOKEN_SETUP: pidstr = "SETUP"; break;
- case USB_TOKEN_IN: pidstr = "IN"; break;
- case USB_TOKEN_OUT: pidstr = "OUT"; break;
- default: pidstr = "?"; break;
- }
- printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",
- s->frnum, pidstr, devaddr, devep, len);
- if (pid != USB_TOKEN_IN) {
- printf(" data_out=");
- for(i = 0; i < len; i++) {
- printf(" %02x", data[i]);
- }
- printf("\n");
- }
- }
-#endif
- for(i = 0; i < NB_PORTS; i++) {
- port = &s->ports[i];
- dev = port->port.dev;
- if (dev && (port->ctrl & UHCI_PORT_EN)) {
- ret = dev->handle_packet(dev, pid,
- devaddr, devep,
- data, len);
- if (ret != USB_RET_NODEV) {
-#ifdef DEBUG_PACKET
- {
- printf(" ret=%d ", ret);
- if (pid == USB_TOKEN_IN && ret > 0) {
- printf("data_in=");
- for(i = 0; i < ret; i++) {
- printf(" %02x", data[i]);
- }
- }
- printf("\n");
- }
-#endif
- return ret;
- }
- }
- }
- return USB_RET_NODEV;
-}
-
-/* return -1 if fatal error (frame must be stopped)
- 0 if TD successful
- 1 if TD unsuccessful or inactive
-*/
-static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
-{
- uint8_t pid;
- uint8_t buf[1280];
- int len, max_len, err, ret;
-
- if (td->ctrl & TD_CTRL_IOC) {
- *int_mask |= 0x01;
- }
-
- if (!(td->ctrl & TD_CTRL_ACTIVE))
- return 1;
-
- /* TD is active */
- max_len = ((td->token >> 21) + 1) & 0x7ff;
- pid = td->token & 0xff;
- switch(pid) {
- case USB_TOKEN_OUT:
- case USB_TOKEN_SETUP:
- cpu_physical_memory_read(td->buffer, buf, max_len);
- ret = uhci_broadcast_packet(s, pid,
- (td->token >> 8) & 0x7f,
- (td->token >> 15) & 0xf,
- buf, max_len);
- len = max_len;
- break;
- case USB_TOKEN_IN:
- ret = uhci_broadcast_packet(s, pid,
- (td->token >> 8) & 0x7f,
- (td->token >> 15) & 0xf,
- buf, max_len);
- if (ret >= 0) {
- len = ret;
- if (len > max_len) {
- len = max_len;
- ret = USB_RET_BABBLE;
- }
- if (len > 0) {
- /* write the data back */
- cpu_physical_memory_write(td->buffer, buf, len);
- }
- } else {
- len = 0;
- }
- break;
- default:
- /* invalid pid : frame interrupted */
- s->status |= UHCI_STS_HCPERR;
- uhci_update_irq(s);
- return -1;
- }
- if (td->ctrl & TD_CTRL_IOS)
- td->ctrl &= ~TD_CTRL_ACTIVE;
- if (ret >= 0) {
- td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
- td->ctrl &= ~TD_CTRL_ACTIVE;
- if (pid == USB_TOKEN_IN &&
- (td->ctrl & TD_CTRL_SPD) &&
- len < max_len) {
- *int_mask |= 0x02;
- /* short packet: do not update QH */
- return 1;
- } else {
- /* success */
- return 0;
- }
- } else {
- switch(ret) {
- default:
- case USB_RET_NODEV:
- do_timeout:
- td->ctrl |= TD_CTRL_TIMEOUT;
- err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
- if (err != 0) {
- err--;
- if (err == 0) {
- td->ctrl &= ~TD_CTRL_ACTIVE;
- s->status |= UHCI_STS_USBERR;
- uhci_update_irq(s);
- }
- }
- td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
- (err << TD_CTRL_ERROR_SHIFT);
- return 1;
- case USB_RET_NAK:
- td->ctrl |= TD_CTRL_NAK;
- if (pid == USB_TOKEN_SETUP)
- goto do_timeout;
- return 1;
- case USB_RET_STALL:
- td->ctrl |= TD_CTRL_STALL;
- td->ctrl &= ~TD_CTRL_ACTIVE;
- return 1;
- case USB_RET_BABBLE:
- td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
- td->ctrl &= ~TD_CTRL_ACTIVE;
- /* frame interrupted */
- return -1;
- }
- }
-}
-
-static void uhci_frame_timer(void *opaque)
-{
- UHCIState *s = opaque;
- int64_t expire_time;
- uint32_t frame_addr, link, old_td_ctrl, val;
- int int_mask, cnt, ret;
- UHCI_TD td;
- UHCI_QH qh;
-
- if (!(s->cmd & UHCI_CMD_RS)) {
- qemu_del_timer(s->frame_timer);
- /* set hchalted bit in status - UHCI11D 2.1.2 */
- s->status |= UHCI_STS_HCHALTED;
- return;
- }
- frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
- cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
- le32_to_cpus(&link);
- int_mask = 0;
- cnt = FRAME_MAX_LOOPS;
- while ((link & 1) == 0) {
- if (--cnt == 0)
- break;
- /* valid frame */
- if (link & 2) {
- /* QH */
- cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
- le32_to_cpus(&qh.link);
- le32_to_cpus(&qh.el_link);
- depth_first:
- if (qh.el_link & 1) {
- /* no element : go to next entry */
- link = qh.link;
- } else if (qh.el_link & 2) {
- /* QH */
- link = qh.el_link;
- } else {
- /* TD */
- if (--cnt == 0)
- break;
- cpu_physical_memory_read(qh.el_link & ~0xf,
- (uint8_t *)&td, sizeof(td));
- le32_to_cpus(&td.link);
- le32_to_cpus(&td.ctrl);
- le32_to_cpus(&td.token);
- le32_to_cpus(&td.buffer);
- old_td_ctrl = td.ctrl;
- ret = uhci_handle_td(s, &td, &int_mask);
- /* update the status bits of the TD */
- if (old_td_ctrl != td.ctrl) {
- val = cpu_to_le32(td.ctrl);
- cpu_physical_memory_write((qh.el_link & ~0xf) + 4,
- (const uint8_t *)&val,
- sizeof(val));
- }
- if (ret < 0)
- break; /* interrupted frame */
- if (ret == 0) {
- /* update qh element link */
- qh.el_link = td.link;
- val = cpu_to_le32(qh.el_link);
- cpu_physical_memory_write((link & ~0xf) + 4,
- (const uint8_t *)&val,
- sizeof(val));
- if (qh.el_link & 4) {
- /* depth first */
- goto depth_first;
- }
- }
- /* go to next entry */
- link = qh.link;
- }
- } else {
- /* TD */
- cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
- le32_to_cpus(&td.link);
- le32_to_cpus(&td.ctrl);
- le32_to_cpus(&td.token);
- le32_to_cpus(&td.buffer);
- old_td_ctrl = td.ctrl;
- ret = uhci_handle_td(s, &td, &int_mask);
- /* update the status bits of the TD */
- if (old_td_ctrl != td.ctrl) {
- val = cpu_to_le32(td.ctrl);
- cpu_physical_memory_write((link & ~0xf) + 4,
- (const uint8_t *)&val,
- sizeof(val));
- }
- if (ret < 0)
- break; /* interrupted frame */
- link = td.link;
- }
- }
- s->frnum = (s->frnum + 1) & 0x7ff;
- if (int_mask) {
- s->status2 |= int_mask;
- s->status |= UHCI_STS_USBINT;
- uhci_update_irq(s);
- }
- /* prepare the timer for the next frame */
- expire_time = qemu_get_clock(vm_clock) +
- (ticks_per_sec / FRAME_TIMER_FREQ);
- qemu_mod_timer(s->frame_timer, expire_time);
-}
-
-static void uhci_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- UHCIState *s = (UHCIState *)pci_dev;
-
- register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
- register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
- register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
- register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
- register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
- register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
-}
-
-void usb_uhci_init(PCIBus *bus, int devfn)
-{
- UHCIState *s;
- uint8_t *pci_conf;
- int i;
-
- s = (UHCIState *)pci_register_device(bus,
- "USB-UHCI", sizeof(UHCIState),
- devfn, NULL, NULL);
- pci_conf = s->dev.config;
- pci_conf[0x00] = 0x86;
- pci_conf[0x01] = 0x80;
- pci_conf[0x02] = 0x20;
- pci_conf[0x03] = 0x70;
- pci_conf[0x08] = 0x01; // revision number
- pci_conf[0x09] = 0x00;
- pci_conf[0x0a] = 0x03;
- pci_conf[0x0b] = 0x0c;
- pci_conf[0x0e] = 0x00; // header_type
- pci_conf[0x3d] = 4; // interrupt pin 3
- pci_conf[0x60] = 0x10; // release number
-
- for(i = 0; i < NB_PORTS; i++) {
- qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
- }
- s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
-
- uhci_reset(s);
-
- /* Use region 4 for consistency with real hardware. BSD guests seem
- to rely on this. */
- pci_register_io_region(&s->dev, 4, 0x20,
- PCI_ADDRESS_SPACE_IO, uhci_map);
-}
diff --git a/hw/usb.c b/hw/usb.c
index 34aac5f..a00d945 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -55,7 +55,10 @@ int usb_generic_handle_packet(USBDevice *s, int pid,
s->remote_wakeup = 0;
s->addr = 0;
s->state = USB_STATE_DEFAULT;
- s->handle_reset(s);
+ s->handle_reset(s, 0);
+ break;
+ case USB_MSG_DESTROY:
+ s->handle_reset(s, 1);
break;
case USB_TOKEN_SETUP:
if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
diff --git a/hw/usb.h b/hw/usb.h
index 98fde06..b0887d6 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -29,6 +29,7 @@
#define USB_MSG_ATTACH 0x100
#define USB_MSG_DETACH 0x101
#define USB_MSG_RESET 0x102
+#define USB_MSG_DESTROY 0x103
#define USB_RET_NODEV (-1)
#define USB_RET_NAK (-2)
@@ -116,14 +117,12 @@ struct USBDevice {
int (*handle_packet)(USBDevice *dev, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t *data, int len);
- void (*handle_destroy)(USBDevice *dev);
-
int speed;
/* The following fields are used by the generic USB device
layer. They are here just to avoid creating a new structure for
them. */
- void (*handle_reset)(USBDevice *dev);
+ void (*handle_reset)(USBDevice *dev, int destroy);
int (*handle_control)(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data);
int (*handle_data)(USBDevice *dev, int pid, uint8_t devep,
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
deleted file mode 100644
index 34a4bc6..0000000
--- a/hw/versatile_pci.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * ARM Versatile/PB PCI host controller
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the LGPL.
- */
-
-#include "vl.h"
-
-static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr)
-{
- return addr & 0xf8ff;
-}
-
-static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
- pci_data_write(opaque, vpb_pci_config_addr (addr), val, 1);
-}
-
-static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap16(val);
-#endif
- pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
-}
-
-static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr,
- uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- pci_data_write(opaque, vpb_pci_config_addr (addr), val, 4);
-}
-
-static uint32_t pci_vpb_config_readb (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
- val = pci_data_read(opaque, vpb_pci_config_addr (addr), 1);
- return val;
-}
-
-static uint32_t pci_vpb_config_readw (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
- val = pci_data_read(opaque, vpb_pci_config_addr (addr), 2);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap16(val);
-#endif
- return val;
-}
-
-static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr)
-{
- uint32_t val;
- val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
-#ifdef TARGET_WORDS_BIGENDIAN
- val = bswap32(val);
-#endif
- return val;
-}
-
-static CPUWriteMemoryFunc *pci_vpb_config_write[] = {
- &pci_vpb_config_writeb,
- &pci_vpb_config_writew,
- &pci_vpb_config_writel,
-};
-
-static CPUReadMemoryFunc *pci_vpb_config_read[] = {
- &pci_vpb_config_readb,
- &pci_vpb_config_readw,
- &pci_vpb_config_readl,
-};
-
-static void pci_vpb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
-{
- pic_set_irq_new(pic, 27 + irq_num, level);
-}
-
-PCIBus *pci_vpb_init(void *pic)
-{
- PCIBus *s;
- PCIDevice *d;
- int mem_config;
-
- s = pci_register_bus(pci_vpb_set_irq, pic, 11 << 3);
- /* ??? Register memory space. */
-
- mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
- pci_vpb_config_write, s);
- /* Selfconfig area. */
- cpu_register_physical_memory(0x41000000, 0x10000, mem_config);
- /* Normal config area. */
- cpu_register_physical_memory(0x42000000, 0x10000, mem_config);
-
- d = pci_register_device(s, "Versatile/PB PCI Controller",
- sizeof(PCIDevice), -1, NULL, NULL);
- d->config[0x00] = 0xee; // vendor_id
- d->config[0x01] = 0x10;
- d->config[0x02] = 0x00; // device_id
- d->config[0x03] = 0x03;
- d->config[0x04] = 0x00;
- d->config[0x05] = 0x00;
- d->config[0x06] = 0x20;
- d->config[0x07] = 0x02;
- d->config[0x08] = 0x00; // revision
- d->config[0x09] = 0x00; // programming i/f
- d->config[0x0A] = 0x40; // class_sub = pci host
- d->config[0x0B] = 0x0b; // class_base = PCI_bridge
- d->config[0x0D] = 0x10; // latency_timer
-
- return s;
-}
-
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
deleted file mode 100644
index 28ec137..0000000
--- a/hw/versatilepb.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * ARM Versatile Platform/Application Baseboard System emulation.
- *
- * Copyright (c) 2005-2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licenced under the GPL.
- */
-
-#include "vl.h"
-#include "arm_pic.h"
-
-#define LOCK_VALUE 0xa05f
-
-/* Primary interrupt controller. */
-
-typedef struct vpb_sic_state
-{
- arm_pic_handler handler;
- uint32_t base;
- uint32_t level;
- uint32_t mask;
- uint32_t pic_enable;
- void *parent;
- int irq;
-} vpb_sic_state;
-
-static void vpb_sic_update(vpb_sic_state *s)
-{
- uint32_t flags;
-
- flags = s->level & s->mask;
- pic_set_irq_new(s->parent, s->irq, flags != 0);
-}
-
-static void vpb_sic_update_pic(vpb_sic_state *s)
-{
- int i;
- uint32_t mask;
-
- for (i = 21; i <= 30; i++) {
- mask = 1u << i;
- if (!(s->pic_enable & mask))
- continue;
- pic_set_irq_new(s->parent, i, (s->level & mask) != 0);
- }
-}
-
-static void vpb_sic_set_irq(void *opaque, int irq, int level)
-{
- vpb_sic_state *s = (vpb_sic_state *)opaque;
- if (level)
- s->level |= 1u << irq;
- else
- s->level &= ~(1u << irq);
- if (s->pic_enable & (1u << irq))
- pic_set_irq_new(s->parent, irq, level);
- vpb_sic_update(s);
-}
-
-static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset)
-{
- vpb_sic_state *s = (vpb_sic_state *)opaque;
-
- offset -= s->base;
- switch (offset >> 2) {
- case 0: /* STATUS */
- return s->level & s->mask;
- case 1: /* RAWSTAT */
- return s->level;
- case 2: /* ENABLE */
- return s->mask;
- case 4: /* SOFTINT */
- return s->level & 1;
- case 8: /* PICENABLE */
- return s->pic_enable;
- default:
- printf ("vpb_sic_read: Bad register offset 0x%x\n", offset);
- return 0;
- }
-}
-
-static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
- uint32_t value)
-{
- vpb_sic_state *s = (vpb_sic_state *)opaque;
- offset -= s->base;
-
- switch (offset >> 2) {
- case 2: /* ENSET */
- s->mask |= value;
- break;
- case 3: /* ENCLR */
- s->mask &= ~value;
- break;
- case 4: /* SOFTINTSET */
- if (value)
- s->mask |= 1;
- break;
- case 5: /* SOFTINTCLR */
- if (value)
- s->mask &= ~1u;
- break;
- case 8: /* PICENSET */
- s->pic_enable |= (value & 0x7fe00000);
- vpb_sic_update_pic(s);
- break;
- case 9: /* PICENCLR */
- s->pic_enable &= ~value;
- vpb_sic_update_pic(s);
- break;
- default:
- printf ("vpb_sic_write: Bad register offset 0x%x\n", offset);
- return;
- }
- vpb_sic_update(s);
-}
-
-static CPUReadMemoryFunc *vpb_sic_readfn[] = {
- vpb_sic_read,
- vpb_sic_read,
- vpb_sic_read
-};
-
-static CPUWriteMemoryFunc *vpb_sic_writefn[] = {
- vpb_sic_write,
- vpb_sic_write,
- vpb_sic_write
-};
-
-static vpb_sic_state *vpb_sic_init(uint32_t base, void *parent, int irq)
-{
- vpb_sic_state *s;
- int iomemtype;
-
- s = (vpb_sic_state *)qemu_mallocz(sizeof(vpb_sic_state));
- if (!s)
- return NULL;
- s->handler = vpb_sic_set_irq;
- s->base = base;
- s->parent = parent;
- s->irq = irq;
- iomemtype = cpu_register_io_memory(0, vpb_sic_readfn,
- vpb_sic_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- /* ??? Save/restore. */
- return s;
-}
-
-/* System controller. */
-
-typedef struct {
- uint32_t base;
- uint32_t leds;
- uint16_t lockval;
- uint32_t cfgdata1;
- uint32_t cfgdata2;
- uint32_t flags;
- uint32_t nvflags;
- uint32_t resetlevel;
-} vpb_sys_state;
-
-static uint32_t vpb_sys_read(void *opaque, target_phys_addr_t offset)
-{
- vpb_sys_state *s = (vpb_sys_state *)opaque;
-
- offset -= s->base;
- switch (offset) {
- case 0x00: /* ID */
- return 0x41007004;
- case 0x04: /* SW */
- /* General purpose hardware switches.
- We don't have a useful way of exposing these to the user. */
- return 0;
- case 0x08: /* LED */
- return s->leds;
- case 0x20: /* LOCK */
- return s->lockval;
- case 0x0c: /* OSC0 */
- case 0x10: /* OSC1 */
- case 0x14: /* OSC2 */
- case 0x18: /* OSC3 */
- case 0x1c: /* OSC4 */
- case 0x24: /* 100HZ */
- /* ??? Implement these. */
- return 0;
- case 0x28: /* CFGDATA1 */
- return s->cfgdata1;
- case 0x2c: /* CFGDATA2 */
- return s->cfgdata2;
- case 0x30: /* FLAGS */
- return s->flags;
- case 0x38: /* NVFLAGS */
- return s->nvflags;
- case 0x40: /* RESETCTL */
- return s->resetlevel;
- case 0x44: /* PCICTL */
- return 1;
- case 0x48: /* MCI */
- return 0;
- case 0x4c: /* FLASH */
- return 0;
- case 0x50: /* CLCD */
- return 0x1000;
- case 0x54: /* CLCDSER */
- return 0;
- case 0x58: /* BOOTCS */
- return 0;
- case 0x5c: /* 24MHz */
- /* ??? not implemented. */
- return 0;
- case 0x60: /* MISC */
- return 0;
- case 0x64: /* DMAPSR0 */
- case 0x68: /* DMAPSR1 */
- case 0x6c: /* DMAPSR2 */
- case 0x8c: /* OSCRESET0 */
- case 0x90: /* OSCRESET1 */
- case 0x94: /* OSCRESET2 */
- case 0x98: /* OSCRESET3 */
- case 0x9c: /* OSCRESET4 */
- case 0xc0: /* SYS_TEST_OSC0 */
- case 0xc4: /* SYS_TEST_OSC1 */
- case 0xc8: /* SYS_TEST_OSC2 */
- case 0xcc: /* SYS_TEST_OSC3 */
- case 0xd0: /* SYS_TEST_OSC4 */
- return 0;
- default:
- printf ("vpb_sys_read: Bad register offset 0x%x\n", offset);
- return 0;
- }
-}
-
-static void vpb_sys_write(void *opaque, target_phys_addr_t offset,
- uint32_t val)
-{
- vpb_sys_state *s = (vpb_sys_state *)opaque;
- offset -= s->base;
-
- switch (offset) {
- case 0x08: /* LED */
- s->leds = val;
- case 0x0c: /* OSC0 */
- case 0x10: /* OSC1 */
- case 0x14: /* OSC2 */
- case 0x18: /* OSC3 */
- case 0x1c: /* OSC4 */
- /* ??? */
- break;
- case 0x20: /* LOCK */
- if (val == LOCK_VALUE)
- s->lockval = val;
- else
- s->lockval = val & 0x7fff;
- break;
- case 0x28: /* CFGDATA1 */
- /* ??? Need to implement this. */
- s->cfgdata1 = val;
- break;
- case 0x2c: /* CFGDATA2 */
- /* ??? Need to implement this. */
- s->cfgdata2 = val;
- break;
- case 0x30: /* FLAGSSET */
- s->flags |= val;
- break;
- case 0x34: /* FLAGSCLR */
- s->flags &= ~val;
- break;
- case 0x38: /* NVFLAGSSET */
- s->nvflags |= val;
- break;
- case 0x3c: /* NVFLAGSCLR */
- s->nvflags &= ~val;
- break;
- case 0x40: /* RESETCTL */
- if (s->lockval == LOCK_VALUE) {
- s->resetlevel = val;
- if (val & 0x100)
- cpu_abort(cpu_single_env, "Board reset\n");
- }
- break;
- case 0x44: /* PCICTL */
- /* nothing to do. */
- break;
- case 0x4c: /* FLASH */
- case 0x50: /* CLCD */
- case 0x54: /* CLCDSER */
- case 0x64: /* DMAPSR0 */
- case 0x68: /* DMAPSR1 */
- case 0x6c: /* DMAPSR2 */
- case 0x8c: /* OSCRESET0 */
- case 0x90: /* OSCRESET1 */
- case 0x94: /* OSCRESET2 */
- case 0x98: /* OSCRESET3 */
- case 0x9c: /* OSCRESET4 */
- break;
- default:
- printf ("vpb_sys_write: Bad register offset 0x%x\n", offset);
- return;
- }
-}
-
-static CPUReadMemoryFunc *vpb_sys_readfn[] = {
- vpb_sys_read,
- vpb_sys_read,
- vpb_sys_read
-};
-
-static CPUWriteMemoryFunc *vpb_sys_writefn[] = {
- vpb_sys_write,
- vpb_sys_write,
- vpb_sys_write
-};
-
-static vpb_sys_state *vpb_sys_init(uint32_t base)
-{
- vpb_sys_state *s;
- int iomemtype;
-
- s = (vpb_sys_state *)qemu_mallocz(sizeof(vpb_sys_state));
- if (!s)
- return NULL;
- s->base = base;
- iomemtype = cpu_register_io_memory(0, vpb_sys_readfn,
- vpb_sys_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
- /* ??? Save/restore. */
- return s;
-}
-
-/* Board init. */
-
-/* The AB and PB boards both use the same core, just with different
- peripherans and expansion busses. For now we emulate a subset of the
- PB peripherals and just change the board ID. */
-
-static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename, int board_id)
-{
- CPUState *env;
- void *pic;
- void *sic;
- void *scsi_hba;
- PCIBus *pci_bus;
- NICInfo *nd;
- int n;
- int done_smc = 0;
-
- env = cpu_init();
- cpu_arm_set_model(env, ARM_CPUID_ARM926);
- /* ??? RAM shoud repeat to fill physical memory space. */
- /* SDRAM at address zero. */
- cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
-
- vpb_sys_init(0x10000000);
- pic = arm_pic_init_cpu(env);
- pic = pl190_init(0x10140000, pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
- sic = vpb_sic_init(0x10003000, pic, 31);
- pl050_init(0x10006000, sic, 3, 0);
- pl050_init(0x10007000, sic, 4, 1);
-
- pci_bus = pci_vpb_init(sic);
- /* The Versatile PCI bridge does not provide access to PCI IO space,
- so many of the qemu PCI devices are not useable. */
- for(n = 0; n < nb_nics; n++) {
- nd = &nd_table[n];
- if (!nd->model)
- nd->model = done_smc ? "rtl8139" : "smc91c111";
- if (strcmp(nd->model, "smc91c111") == 0) {
- smc91c111_init(nd, 0x10010000, sic, 25);
- } else {
- pci_nic_init(pci_bus, nd);
- }
- }
- if (usb_enabled) {
- usb_ohci_init(pci_bus, 3, -1);
- }
- scsi_hba = lsi_scsi_init(pci_bus, -1);
- for (n = 0; n < MAX_DISKS; n++) {
- if (bs_table[n]) {
- lsi_scsi_attach(scsi_hba, bs_table[n], n);
- }
- }
-
- pl011_init(0x101f1000, pic, 12, serial_hds[0]);
- pl011_init(0x101f2000, pic, 13, serial_hds[1]);
- pl011_init(0x101f3000, pic, 14, serial_hds[2]);
- pl011_init(0x10009000, sic, 6, serial_hds[3]);
-
- pl080_init(0x10130000, pic, 17);
- sp804_init(0x101e2000, pic, 4);
- sp804_init(0x101e3000, pic, 5);
-
- /* The versatile/PB actually has a modified Color LCD controller
- that includes hardware cursor support from the PL111. */
- pl110_init(ds, 0x10120000, pic, 16, 1);
-
- /* Memory map for Versatile/PB: */
- /* 0x10000000 System registers. */
- /* 0x10001000 PCI controller config registers. */
- /* 0x10002000 Serial bus interface. */
- /* 0x10003000 Secondary interrupt controller. */
- /* 0x10004000 AACI (audio). */
- /* 0x10005000 MMCI0. */
- /* 0x10006000 KMI0 (keyboard). */
- /* 0x10007000 KMI1 (mouse). */
- /* 0x10008000 Character LCD Interface. */
- /* 0x10009000 UART3. */
- /* 0x1000a000 Smart card 1. */
- /* 0x1000b000 MMCI1. */
- /* 0x10010000 Ethernet. */
- /* 0x10020000 USB. */
- /* 0x10100000 SSMC. */
- /* 0x10110000 MPMC. */
- /* 0x10120000 CLCD Controller. */
- /* 0x10130000 DMA Controller. */
- /* 0x10140000 Vectored interrupt controller. */
- /* 0x101d0000 AHB Monitor Interface. */
- /* 0x101e0000 System Controller. */
- /* 0x101e1000 Watchdog Interface. */
- /* 0x101e2000 Timer 0/1. */
- /* 0x101e3000 Timer 2/3. */
- /* 0x101e4000 GPIO port 0. */
- /* 0x101e5000 GPIO port 1. */
- /* 0x101e6000 GPIO port 2. */
- /* 0x101e7000 GPIO port 3. */
- /* 0x101e8000 RTC. */
- /* 0x101f0000 Smart card 0. */
- /* 0x101f1000 UART0. */
- /* 0x101f2000 UART1. */
- /* 0x101f3000 UART2. */
- /* 0x101f4000 SSPI. */
-
- arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
- initrd_filename, board_id);
-}
-
-static void vpb_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- versatile_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, 0x183);
-}
-
-static void vab_init(int ram_size, int vga_ram_size, int boot_device,
- DisplayState *ds, const char **fd_filename, int snapshot,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename)
-{
- versatile_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline,
- initrd_filename, 0x25e);
-}
-
-QEMUMachine versatilepb_machine = {
- "versatilepb",
- "ARM Versatile/PB (ARM926EJ-S)",
- vpb_init,
-};
-
-QEMUMachine versatileab_machine = {
- "versatileab",
- "ARM Versatile/AB (ARM926EJ-S)",
- vab_init,
-};
diff --git a/hw/vga.c b/hw/vga.c
deleted file mode 100644
index 8f748b3..0000000
--- a/hw/vga.c
+++ /dev/null
@@ -1,1945 +0,0 @@
-/*
- * QEMU VGA Emulator.
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#include "vl.h"
-#include "vga_int.h"
-
-//#define DEBUG_VGA
-//#define DEBUG_VGA_MEM
-//#define DEBUG_VGA_REG
-
-//#define DEBUG_BOCHS_VBE
-
-/* force some bits to zero */
-const uint8_t sr_mask[8] = {
- (uint8_t)~0xfc,
- (uint8_t)~0xc2,
- (uint8_t)~0xf0,
- (uint8_t)~0xc0,
- (uint8_t)~0xf1,
- (uint8_t)~0xff,
- (uint8_t)~0xff,
- (uint8_t)~0x00,
-};
-
-const uint8_t gr_mask[16] = {
- (uint8_t)~0xf0, /* 0x00 */
- (uint8_t)~0xf0, /* 0x01 */
- (uint8_t)~0xf0, /* 0x02 */
- (uint8_t)~0xe0, /* 0x03 */
- (uint8_t)~0xfc, /* 0x04 */
- (uint8_t)~0x84, /* 0x05 */
- (uint8_t)~0xf0, /* 0x06 */
- (uint8_t)~0xf0, /* 0x07 */
- (uint8_t)~0x00, /* 0x08 */
- (uint8_t)~0xff, /* 0x09 */
- (uint8_t)~0xff, /* 0x0a */
- (uint8_t)~0xff, /* 0x0b */
- (uint8_t)~0xff, /* 0x0c */
- (uint8_t)~0xff, /* 0x0d */
- (uint8_t)~0xff, /* 0x0e */
- (uint8_t)~0xff, /* 0x0f */
-};
-
-#define cbswap_32(__x) \
-((uint32_t)( \
- (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
- (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
- (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
- (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
-
-#ifdef WORDS_BIGENDIAN
-#define PAT(x) cbswap_32(x)
-#else
-#define PAT(x) (x)
-#endif
-
-#ifdef WORDS_BIGENDIAN
-#define BIG 1
-#else
-#define BIG 0
-#endif
-
-#ifdef WORDS_BIGENDIAN
-#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
-#else
-#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
-#endif
-
-static const uint32_t mask16[16] = {
- PAT(0x00000000),
- PAT(0x000000ff),
- PAT(0x0000ff00),
- PAT(0x0000ffff),
- PAT(0x00ff0000),
- PAT(0x00ff00ff),
- PAT(0x00ffff00),
- PAT(0x00ffffff),
- PAT(0xff000000),
- PAT(0xff0000ff),
- PAT(0xff00ff00),
- PAT(0xff00ffff),
- PAT(0xffff0000),
- PAT(0xffff00ff),
- PAT(0xffffff00),
- PAT(0xffffffff),
-};
-
-#undef PAT
-
-#ifdef WORDS_BIGENDIAN
-#define PAT(x) (x)
-#else
-#define PAT(x) cbswap_32(x)
-#endif
-
-static const uint32_t dmask16[16] = {
- PAT(0x00000000),
- PAT(0x000000ff),
- PAT(0x0000ff00),
- PAT(0x0000ffff),
- PAT(0x00ff0000),
- PAT(0x00ff00ff),
- PAT(0x00ffff00),
- PAT(0x00ffffff),
- PAT(0xff000000),
- PAT(0xff0000ff),
- PAT(0xff00ff00),
- PAT(0xff00ffff),
- PAT(0xffff0000),
- PAT(0xffff00ff),
- PAT(0xffffff00),
- PAT(0xffffffff),
-};
-
-static const uint32_t dmask4[4] = {
- PAT(0x00000000),
- PAT(0x0000ffff),
- PAT(0xffff0000),
- PAT(0xffffffff),
-};
-
-static uint32_t expand4[256];
-static uint16_t expand2[256];
-static uint8_t expand4to8[16];
-
-VGAState *vga_state;
-int vga_io_memory;
-
-static void vga_screen_dump(void *opaque, const char *filename);
-
-static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
-{
- VGAState *s = opaque;
- int val, index;
-
- /* check port range access depending on color/monochrome mode */
- if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
- (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
- val = 0xff;
- } else {
- switch(addr) {
- case 0x3c0:
- if (s->ar_flip_flop == 0) {
- val = s->ar_index;
- } else {
- val = 0;
- }
- break;
- case 0x3c1:
- index = s->ar_index & 0x1f;
- if (index < 21)
- val = s->ar[index];
- else
- val = 0;
- break;
- case 0x3c2:
- val = s->st00;
- break;
- case 0x3c4:
- val = s->sr_index;
- break;
- case 0x3c5:
- val = s->sr[s->sr_index];
-#ifdef DEBUG_VGA_REG
- printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
-#endif
- break;
- case 0x3c7:
- val = s->dac_state;
- break;
- case 0x3c8:
- val = s->dac_write_index;
- break;
- case 0x3c9:
- val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
- if (++s->dac_sub_index == 3) {
- s->dac_sub_index = 0;
- s->dac_read_index++;
- }
- break;
- case 0x3ca:
- val = s->fcr;
- break;
- case 0x3cc:
- val = s->msr;
- break;
- case 0x3ce:
- val = s->gr_index;
- break;
- case 0x3cf:
- val = s->gr[s->gr_index];
-#ifdef DEBUG_VGA_REG
- printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
-#endif
- break;
- case 0x3b4:
- case 0x3d4:
- val = s->cr_index;
- break;
- case 0x3b5:
- case 0x3d5:
- val = s->cr[s->cr_index];
-#ifdef DEBUG_VGA_REG
- printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
-#endif
- break;
- case 0x3ba:
- case 0x3da:
- /* just toggle to fool polling */
- s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
- val = s->st01;
- s->ar_flip_flop = 0;
- break;
- default:
- val = 0x00;
- break;
- }
- }
-#if defined(DEBUG_VGA)
- printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
-#endif
- return val;
-}
-
-static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
- VGAState *s = opaque;
- int index;
-
- /* check port range access depending on color/monochrome mode */
- if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
- (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
- return;
-
-#ifdef DEBUG_VGA
- printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
-#endif
-
- switch(addr) {
- case 0x3c0:
- if (s->ar_flip_flop == 0) {
- val &= 0x3f;
- s->ar_index = val;
- } else {
- index = s->ar_index & 0x1f;
- switch(index) {
- case 0x00 ... 0x0f:
- s->ar[index] = val & 0x3f;
- break;
- case 0x10:
- s->ar[index] = val & ~0x10;
- break;
- case 0x11:
- s->ar[index] = val;
- break;
- case 0x12:
- s->ar[index] = val & ~0xc0;
- break;
- case 0x13:
- s->ar[index] = val & ~0xf0;
- break;
- case 0x14:
- s->ar[index] = val & ~0xf0;
- break;
- default:
- break;
- }
- }
- s->ar_flip_flop ^= 1;
- break;
- case 0x3c2:
- s->msr = val & ~0x10;
- break;
- case 0x3c4:
- s->sr_index = val & 7;
- break;
- case 0x3c5:
-#ifdef DEBUG_VGA_REG
- printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
-#endif
- s->sr[s->sr_index] = val & sr_mask[s->sr_index];
- break;
- case 0x3c7:
- s->dac_read_index = val;
- s->dac_sub_index = 0;
- s->dac_state = 3;
- break;
- case 0x3c8:
- s->dac_write_index = val;
- s->dac_sub_index = 0;
- s->dac_state = 0;
- break;
- case 0x3c9:
- s->dac_cache[s->dac_sub_index] = val;
- if (++s->dac_sub_index == 3) {
- memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
- s->dac_sub_index = 0;
- s->dac_write_index++;
- }
- break;
- case 0x3ce:
- s->gr_index = val & 0x0f;
- break;
- case 0x3cf:
-#ifdef DEBUG_VGA_REG
- printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
-#endif
- s->gr[s->gr_index] = val & gr_mask[s->gr_index];
- break;
- case 0x3b4:
- case 0x3d4:
- s->cr_index = val;
- break;
- case 0x3b5:
- case 0x3d5:
-#ifdef DEBUG_VGA_REG
- printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
-#endif
- /* handle CR0-7 protection */
- if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
- /* can always write bit 4 of CR7 */
- if (s->cr_index == 7)
- s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
- return;
- }
- switch(s->cr_index) {
- case 0x01: /* horizontal display end */
- case 0x07:
- case 0x09:
- case 0x0c:
- case 0x0d:
- case 0x12: /* veritcal display end */
- s->cr[s->cr_index] = val;
- break;
- default:
- s->cr[s->cr_index] = val;
- break;
- }
- break;
- case 0x3ba:
- case 0x3da:
- s->fcr = val & 0x10;
- break;
- }
-}
-
-#ifdef CONFIG_BOCHS_VBE
-static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
-{
- VGAState *s = opaque;
- uint32_t val;
- val = s->vbe_index;
- return val;
-}
-
-static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
-{
- VGAState *s = opaque;
- uint32_t val;
-
- if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
- switch(s->vbe_index) {
- /* XXX: do not hardcode ? */
- case VBE_DISPI_INDEX_XRES:
- val = VBE_DISPI_MAX_XRES;
- break;
- case VBE_DISPI_INDEX_YRES:
- val = VBE_DISPI_MAX_YRES;
- break;
- case VBE_DISPI_INDEX_BPP:
- val = VBE_DISPI_MAX_BPP;
- break;
- default:
- val = s->vbe_regs[s->vbe_index];
- break;
- }
- } else {
- val = s->vbe_regs[s->vbe_index];
- }
- } else {
- val = 0;
- }
-#ifdef DEBUG_BOCHS_VBE
- printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
-#endif
- return val;
-}
-
-static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
-{
- VGAState *s = opaque;
- s->vbe_index = val;
-}
-
-static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
-{
- VGAState *s = opaque;
-
- if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
-#ifdef DEBUG_BOCHS_VBE
- printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
-#endif
- switch(s->vbe_index) {
- case VBE_DISPI_INDEX_ID:
- if (val == VBE_DISPI_ID0 ||
- val == VBE_DISPI_ID1 ||
- val == VBE_DISPI_ID2) {
- s->vbe_regs[s->vbe_index] = val;
- }
- break;
- case VBE_DISPI_INDEX_XRES:
- if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
- s->vbe_regs[s->vbe_index] = val;
- }
- break;
- case VBE_DISPI_INDEX_YRES:
- if (val <= VBE_DISPI_MAX_YRES) {
- s->vbe_regs[s->vbe_index] = val;
- }
- break;
- case VBE_DISPI_INDEX_BPP:
- if (val == 0)
- val = 8;
- if (val == 4 || val == 8 || val == 15 ||
- val == 16 || val == 24 || val == 32) {
- s->vbe_regs[s->vbe_index] = val;
- }
- break;
- case VBE_DISPI_INDEX_BANK:
- val &= s->vbe_bank_mask;
- s->vbe_regs[s->vbe_index] = val;
- s->bank_offset = (val << 16);
- break;
- case VBE_DISPI_INDEX_ENABLE:
- if ((val & VBE_DISPI_ENABLED) &&
- !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
- int h, shift_control;
-
- s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
- s->vbe_regs[VBE_DISPI_INDEX_XRES];
- s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
- s->vbe_regs[VBE_DISPI_INDEX_YRES];
- s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
- s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
-
- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
- s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
- else
- s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
- ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
- s->vbe_start_addr = 0;
-
- /* clear the screen (should be done in BIOS) */
- if (!(val & VBE_DISPI_NOCLEARMEM)) {
- memset(s->vram_ptr, 0,
- s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
- }
-
- /* we initialize the VGA graphic mode (should be done
- in BIOS) */
- s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
- s->cr[0x17] |= 3; /* no CGA modes */
- s->cr[0x13] = s->vbe_line_offset >> 3;
- /* width */
- s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
- /* height (only meaningful if < 1024) */
- h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
- s->cr[0x12] = h;
- s->cr[0x07] = (s->cr[0x07] & ~0x42) |
- ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
- /* line compare to 1023 */
- s->cr[0x18] = 0xff;
- s->cr[0x07] |= 0x10;
- s->cr[0x09] |= 0x40;
-
- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
- shift_control = 0;
- s->sr[0x01] &= ~8; /* no double line */
- } else {
- shift_control = 2;
- s->sr[4] |= 0x08; /* set chain 4 mode */
- s->sr[2] |= 0x0f; /* activate all planes */
- }
- s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
- s->cr[0x09] &= ~0x9f; /* no double scan */
- } else {
- /* XXX: the bios should do that */
- s->bank_offset = 0;
- }
- s->vbe_regs[s->vbe_index] = val;
- break;
- case VBE_DISPI_INDEX_VIRT_WIDTH:
- {
- int w, h, line_offset;
-
- if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
- return;
- w = val;
- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
- line_offset = w >> 1;
- else
- line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
- h = s->vram_size / line_offset;
- /* XXX: support weird bochs semantics ? */
- if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
- return;
- s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
- s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
- s->vbe_line_offset = line_offset;
- }
- break;
- case VBE_DISPI_INDEX_X_OFFSET:
- case VBE_DISPI_INDEX_Y_OFFSET:
- {
- int x;
- s->vbe_regs[s->vbe_index] = val;
- s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
- x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
- if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
- s->vbe_start_addr += x >> 1;
- else
- s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
- s->vbe_start_addr >>= 2;
- }
- break;
- default:
- break;
- }
- }
-}
-#endif
-
-/* called for accesses between 0xa0000 and 0xc0000 */
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
-{
- VGAState *s = opaque;
- int memory_map_mode, plane;
- uint32_t ret;
-
- /* convert to VGA memory offset */
- memory_map_mode = (s->gr[6] >> 2) & 3;
- addr &= 0x1ffff;
- switch(memory_map_mode) {
- case 0:
- break;
- case 1:
- if (addr >= 0x10000)
- return 0xff;
- addr += s->bank_offset;
- break;
- case 2:
- addr -= 0x10000;
- if (addr >= 0x8000)
- return 0xff;
- break;
- default:
- case 3:
- addr -= 0x18000;
- if (addr >= 0x8000)
- return 0xff;
- break;
- }
-
- if (s->sr[4] & 0x08) {
- /* chain 4 mode : simplest access */
- ret = s->vram_ptr[addr];
- } else if (s->gr[5] & 0x10) {
- /* odd/even mode (aka text mode mapping) */
- plane = (s->gr[4] & 2) | (addr & 1);
- ret = s->vram_ptr[((addr & ~1) << 1) | plane];
- } else {
- /* standard VGA latched access */
- s->latch = ((uint32_t *)s->vram_ptr)[addr];
-
- if (!(s->gr[5] & 0x08)) {
- /* read mode 0 */
- plane = s->gr[4];
- ret = GET_PLANE(s->latch, plane);
- } else {
- /* read mode 1 */
- ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
- ret |= ret >> 16;
- ret |= ret >> 8;
- ret = (~ret) & 0xff;
- }
- }
- return ret;
-}
-
-static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = vga_mem_readb(opaque, addr) << 8;
- v |= vga_mem_readb(opaque, addr + 1);
-#else
- v = vga_mem_readb(opaque, addr);
- v |= vga_mem_readb(opaque, addr + 1) << 8;
-#endif
- return v;
-}
-
-static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = vga_mem_readb(opaque, addr) << 24;
- v |= vga_mem_readb(opaque, addr + 1) << 16;
- v |= vga_mem_readb(opaque, addr + 2) << 8;
- v |= vga_mem_readb(opaque, addr + 3);
-#else
- v = vga_mem_readb(opaque, addr);
- v |= vga_mem_readb(opaque, addr + 1) << 8;
- v |= vga_mem_readb(opaque, addr + 2) << 16;
- v |= vga_mem_readb(opaque, addr + 3) << 24;
-#endif
- return v;
-}
-
-/* called for accesses between 0xa0000 and 0xc0000 */
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
- VGAState *s = opaque;
- int memory_map_mode, plane, write_mode, b, func_select, mask;
- uint32_t write_mask, bit_mask, set_mask;
-
-#ifdef DEBUG_VGA_MEM
- printf("vga: [0x%x] = 0x%02x\n", addr, val);
-#endif
- /* convert to VGA memory offset */
- memory_map_mode = (s->gr[6] >> 2) & 3;
- addr &= 0x1ffff;
- switch(memory_map_mode) {
- case 0:
- break;
- case 1:
- if (addr >= 0x10000)
- return;
- addr += s->bank_offset;
- break;
- case 2:
- addr -= 0x10000;
- if (addr >= 0x8000)
- return;
- break;
- default:
- case 3:
- addr -= 0x18000;
- if (addr >= 0x8000)
- return;
- break;
- }
-
- if (s->sr[4] & 0x08) {
- /* chain 4 mode : simplest access */
- plane = addr & 3;
- mask = (1 << plane);
- if (s->sr[2] & mask) {
- s->vram_ptr[addr] = val;
-#ifdef DEBUG_VGA_MEM
- printf("vga: chain4: [0x%x]\n", addr);
-#endif
- s->plane_updated |= mask; /* only used to detect font change */
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
- }
- } else if (s->gr[5] & 0x10) {
- /* odd/even mode (aka text mode mapping) */
- plane = (s->gr[4] & 2) | (addr & 1);
- mask = (1 << plane);
- if (s->sr[2] & mask) {
- addr = ((addr & ~1) << 1) | plane;
- s->vram_ptr[addr] = val;
-#ifdef DEBUG_VGA_MEM
- printf("vga: odd/even: [0x%x]\n", addr);
-#endif
- s->plane_updated |= mask; /* only used to detect font change */
- cpu_physical_memory_set_dirty(s->vram_offset + addr);
- }
- } else {
- /* standard VGA latched access */
- write_mode = s->gr[5] & 3;
- switch(write_mode) {
- default:
- case 0:
- /* rotate */
- b = s->gr[3] & 7;
- val = ((val >> b) | (val << (8 - b))) & 0xff;
- val |= val << 8;
- val |= val << 16;
-
- /* apply set/reset mask */
- set_mask = mask16[s->gr[1]];
- val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
- bit_mask = s->gr[8];
- break;
- case 1:
- val = s->latch;
- goto do_write;
- case 2:
- val = mask16[val & 0x0f];
- bit_mask = s->gr[8];
- break;
- case 3:
- /* rotate */
- b = s->gr[3] & 7;
- val = (val >> b) | (val << (8 - b));
-
- bit_mask = s->gr[8] & val;
- val = mask16[s->gr[0]];
- break;
- }
-
- /* apply logical operation */
- func_select = s->gr[3] >> 3;
- switch(func_select) {
- case 0:
- default:
- /* nothing to do */
- break;
- case 1:
- /* and */
- val &= s->latch;
- break;
- case 2:
- /* or */
- val |= s->latch;
- break;
- case 3:
- /* xor */
- val ^= s->latch;
- break;
- }
-
- /* apply bit mask */
- bit_mask |= bit_mask << 8;
- bit_mask |= bit_mask << 16;
- val = (val & bit_mask) | (s->latch & ~bit_mask);
-
- do_write:
- /* mask data according to sr[2] */
- mask = s->sr[2];
- s->plane_updated |= mask; /* only used to detect font change */
- write_mask = mask16[mask];
- ((uint32_t *)s->vram_ptr)[addr] =
- (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
- (val & write_mask);
-#ifdef DEBUG_VGA_MEM
- printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
- addr * 4, write_mask, val);
-#endif
- cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
- }
-}
-
-static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
- vga_mem_writeb(opaque, addr + 1, val & 0xff);
-#else
- vga_mem_writeb(opaque, addr, val & 0xff);
- vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
-}
-
-static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
- vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- vga_mem_writeb(opaque, addr + 3, val & 0xff);
-#else
- vga_mem_writeb(opaque, addr, val & 0xff);
- vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
-}
-
-typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
- const uint8_t *font_ptr, int h,
- uint32_t fgcol, uint32_t bgcol);
-typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
- const uint8_t *font_ptr, int h,
- uint32_t fgcol, uint32_t bgcol, int dup9);
-typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width);
-
-static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
-}
-
-static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
-}
-
-static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
-{
- return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
-}
-
-static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
-{
- return (r << 16) | (g << 8) | b;
-}
-
-static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b)
-{
- return (b << 16) | (g << 8) | r;
-}
-
-#define DEPTH 8
-#include "vga_template.h"
-
-#define DEPTH 15
-#include "vga_template.h"
-
-#define DEPTH 16
-#include "vga_template.h"
-
-#define DEPTH 32
-#include "vga_template.h"
-
-#define BGR_FORMAT
-#define DEPTH 32
-#include "vga_template.h"
-
-static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel8(r, g, b);
- col |= col << 8;
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel15(r, g, b);
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel16(r, g, b);
- col |= col << 16;
- return col;
-}
-
-static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel32(r, g, b);
- return col;
-}
-
-static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
-{
- unsigned int col;
- col = rgb_to_pixel32bgr(r, g, b);
- return col;
-}
-
-/* return true if the palette was modified */
-static int update_palette16(VGAState *s)
-{
- int full_update, i;
- uint32_t v, col, *palette;
-
- full_update = 0;
- palette = s->last_palette;
- for(i = 0; i < 16; i++) {
- v = s->ar[i];
- if (s->ar[0x10] & 0x80)
- v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
- else
- v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
- v = v * 3;
- col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
- c6_to_8(s->palette[v + 1]),
- c6_to_8(s->palette[v + 2]));
- if (col != palette[i]) {
- full_update = 1;
- palette[i] = col;
- }
- }
- return full_update;
-}
-
-/* return true if the palette was modified */
-static int update_palette256(VGAState *s)
-{
- int full_update, i;
- uint32_t v, col, *palette;
-
- full_update = 0;
- palette = s->last_palette;
- v = 0;
- for(i = 0; i < 256; i++) {
- col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
- c6_to_8(s->palette[v + 1]),
- c6_to_8(s->palette[v + 2]));
- if (col != palette[i]) {
- full_update = 1;
- palette[i] = col;
- }
- v += 3;
- }
- return full_update;
-}
-
-static void vga_get_offsets(VGAState *s,
- uint32_t *pline_offset,
- uint32_t *pstart_addr)
-{
- uint32_t start_addr, line_offset;
-#ifdef CONFIG_BOCHS_VBE
- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
- line_offset = s->vbe_line_offset;
- start_addr = s->vbe_start_addr;
- } else
-#endif
- {
- /* compute line_offset in bytes */
- line_offset = s->cr[0x13];
- line_offset <<= 3;
-
- /* starting address */
- start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
- }
- *pline_offset = line_offset;
- *pstart_addr = start_addr;
-}
-
-/* update start_addr and line_offset. Return TRUE if modified */
-static int update_basic_params(VGAState *s)
-{
- int full_update;
- uint32_t start_addr, line_offset, line_compare;
-
- full_update = 0;
-
- s->get_offsets(s, &line_offset, &start_addr);
- /* line compare */
- line_compare = s->cr[0x18] |
- ((s->cr[0x07] & 0x10) << 4) |
- ((s->cr[0x09] & 0x40) << 3);
-
- if (line_offset != s->line_offset ||
- start_addr != s->start_addr ||
- line_compare != s->line_compare) {
- s->line_offset = line_offset;
- s->start_addr = start_addr;
- s->line_compare = line_compare;
- full_update = 1;
- }
- return full_update;
-}
-
-#define NB_DEPTHS 5
-
-static inline int get_depth_index(DisplayState *s)
-{
- switch(s->depth) {
- default:
- case 8:
- return 0;
- case 15:
- return 1;
- case 16:
- return 2;
- case 32:
- if (s->bgr)
- return 4;
- else
- return 3;
- }
-}
-
-static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
- vga_draw_glyph8_8,
- vga_draw_glyph8_16,
- vga_draw_glyph8_16,
- vga_draw_glyph8_32,
- vga_draw_glyph8_32,
-};
-
-static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
- vga_draw_glyph16_8,
- vga_draw_glyph16_16,
- vga_draw_glyph16_16,
- vga_draw_glyph16_32,
- vga_draw_glyph16_32,
-};
-
-static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
- vga_draw_glyph9_8,
- vga_draw_glyph9_16,
- vga_draw_glyph9_16,
- vga_draw_glyph9_32,
- vga_draw_glyph9_32,
-};
-
-static const uint8_t cursor_glyph[32 * 4] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
-
-/*
- * Text mode update
- * Missing:
- * - double scan
- * - double width
- * - underline
- * - flashing
- */
-static void vga_draw_text(VGAState *s, int full_update)
-{
- int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
- int cx_min, cx_max, linesize, x_incr;
- uint32_t offset, fgcol, bgcol, v, cursor_offset;
- uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
- const uint8_t *font_ptr, *font_base[2];
- int dup9, line_offset, depth_index;
- uint32_t *palette;
- uint32_t *ch_attr_ptr;
- vga_draw_glyph8_func *vga_draw_glyph8;
- vga_draw_glyph9_func *vga_draw_glyph9;
-
- full_update |= update_palette16(s);
- palette = s->last_palette;
-
- /* compute font data address (in plane 2) */
- v = s->sr[3];
- offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
- if (offset != s->font_offsets[0]) {
- s->font_offsets[0] = offset;
- full_update = 1;
- }
- font_base[0] = s->vram_ptr + offset;
-
- offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
- font_base[1] = s->vram_ptr + offset;
- if (offset != s->font_offsets[1]) {
- s->font_offsets[1] = offset;
- full_update = 1;
- }
- if (s->plane_updated & (1 << 2)) {
- /* if the plane 2 was modified since the last display, it
- indicates the font may have been modified */
- s->plane_updated = 0;
- full_update = 1;
- }
- full_update |= update_basic_params(s);
-
- line_offset = s->line_offset;
- s1 = s->vram_ptr + (s->start_addr * 4);
-
- /* total width & height */
- cheight = (s->cr[9] & 0x1f) + 1;
- cw = 8;
- if (!(s->sr[1] & 0x01))
- cw = 9;
- if (s->sr[1] & 0x08)
- cw = 16; /* NOTE: no 18 pixel wide */
- x_incr = cw * ((s->ds->depth + 7) >> 3);
- width = (s->cr[0x01] + 1);
- if (s->cr[0x06] == 100) {
- /* ugly hack for CGA 160x100x16 - explain me the logic */
- height = 100;
- } else {
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
- height = (height + 1) / cheight;
- }
- if ((height * width) > CH_ATTR_SIZE) {
- /* better than nothing: exit if transient size is too big */
- return;
- }
-
- if (width != s->last_width || height != s->last_height ||
- cw != s->last_cw || cheight != s->last_ch) {
- s->last_scr_width = width * cw;
- s->last_scr_height = height * cheight;
- dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
- s->last_width = width;
- s->last_height = height;
- s->last_ch = cheight;
- s->last_cw = cw;
- full_update = 1;
- }
- cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
- if (cursor_offset != s->cursor_offset ||
- s->cr[0xa] != s->cursor_start ||
- s->cr[0xb] != s->cursor_end) {
- /* if the cursor position changed, we update the old and new
- chars */
- if (s->cursor_offset < CH_ATTR_SIZE)
- s->last_ch_attr[s->cursor_offset] = -1;
- if (cursor_offset < CH_ATTR_SIZE)
- s->last_ch_attr[cursor_offset] = -1;
- s->cursor_offset = cursor_offset;
- s->cursor_start = s->cr[0xa];
- s->cursor_end = s->cr[0xb];
- }
- cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
-
- depth_index = get_depth_index(s->ds);
- if (cw == 16)
- vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
- else
- vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
- vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
-
- dest = s->ds->data;
- linesize = s->ds->linesize;
- ch_attr_ptr = s->last_ch_attr;
- for(cy = 0; cy < height; cy++) {
- d1 = dest;
- src = s1;
- cx_min = width;
- cx_max = -1;
- for(cx = 0; cx < width; cx++) {
- ch_attr = *(uint16_t *)src;
- if (full_update || ch_attr != *ch_attr_ptr) {
- if (cx < cx_min)
- cx_min = cx;
- if (cx > cx_max)
- cx_max = cx;
- *ch_attr_ptr = ch_attr;
-#ifdef WORDS_BIGENDIAN
- ch = ch_attr >> 8;
- cattr = ch_attr & 0xff;
-#else
- ch = ch_attr & 0xff;
- cattr = ch_attr >> 8;
-#endif
- font_ptr = font_base[(cattr >> 3) & 1];
- font_ptr += 32 * 4 * ch;
- bgcol = palette[cattr >> 4];
- fgcol = palette[cattr & 0x0f];
- if (cw != 9) {
- vga_draw_glyph8(d1, linesize,
- font_ptr, cheight, fgcol, bgcol);
- } else {
- dup9 = 0;
- if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
- dup9 = 1;
- vga_draw_glyph9(d1, linesize,
- font_ptr, cheight, fgcol, bgcol, dup9);
- }
- if (src == cursor_ptr &&
- !(s->cr[0x0a] & 0x20)) {
- int line_start, line_last, h;
- /* draw the cursor */
- line_start = s->cr[0x0a] & 0x1f;
- line_last = s->cr[0x0b] & 0x1f;
- /* XXX: check that */
- if (line_last > cheight - 1)
- line_last = cheight - 1;
- if (line_last >= line_start && line_start < cheight) {
- h = line_last - line_start + 1;
- d = d1 + linesize * line_start;
- if (cw != 9) {
- vga_draw_glyph8(d, linesize,
- cursor_glyph, h, fgcol, bgcol);
- } else {
- vga_draw_glyph9(d, linesize,
- cursor_glyph, h, fgcol, bgcol, 1);
- }
- }
- }
- }
- d1 += x_incr;
- src += 4;
- ch_attr_ptr++;
- }
- if (cx_max != -1) {
- dpy_update(s->ds, cx_min * cw, cy * cheight,
- (cx_max - cx_min + 1) * cw, cheight);
- }
- dest += linesize * cheight;
- s1 += line_offset;
- }
-}
-
-enum {
- VGA_DRAW_LINE2,
- VGA_DRAW_LINE2D2,
- VGA_DRAW_LINE4,
- VGA_DRAW_LINE4D2,
- VGA_DRAW_LINE8D2,
- VGA_DRAW_LINE8,
- VGA_DRAW_LINE15,
- VGA_DRAW_LINE16,
- VGA_DRAW_LINE24,
- VGA_DRAW_LINE32,
- VGA_DRAW_LINE_NB,
-};
-
-static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
- vga_draw_line2_8,
- vga_draw_line2_16,
- vga_draw_line2_16,
- vga_draw_line2_32,
- vga_draw_line2_32,
-
- vga_draw_line2d2_8,
- vga_draw_line2d2_16,
- vga_draw_line2d2_16,
- vga_draw_line2d2_32,
- vga_draw_line2d2_32,
-
- vga_draw_line4_8,
- vga_draw_line4_16,
- vga_draw_line4_16,
- vga_draw_line4_32,
- vga_draw_line4_32,
-
- vga_draw_line4d2_8,
- vga_draw_line4d2_16,
- vga_draw_line4d2_16,
- vga_draw_line4d2_32,
- vga_draw_line4d2_32,
-
- vga_draw_line8d2_8,
- vga_draw_line8d2_16,
- vga_draw_line8d2_16,
- vga_draw_line8d2_32,
- vga_draw_line8d2_32,
-
- vga_draw_line8_8,
- vga_draw_line8_16,
- vga_draw_line8_16,
- vga_draw_line8_32,
- vga_draw_line8_32,
-
- vga_draw_line15_8,
- vga_draw_line15_15,
- vga_draw_line15_16,
- vga_draw_line15_32,
- vga_draw_line15_32bgr,
-
- vga_draw_line16_8,
- vga_draw_line16_15,
- vga_draw_line16_16,
- vga_draw_line16_32,
- vga_draw_line16_32bgr,
-
- vga_draw_line24_8,
- vga_draw_line24_15,
- vga_draw_line24_16,
- vga_draw_line24_32,
- vga_draw_line24_32bgr,
-
- vga_draw_line32_8,
- vga_draw_line32_15,
- vga_draw_line32_16,
- vga_draw_line32_32,
- vga_draw_line32_32bgr,
-};
-
-typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
-
-static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
- rgb_to_pixel8_dup,
- rgb_to_pixel15_dup,
- rgb_to_pixel16_dup,
- rgb_to_pixel32_dup,
- rgb_to_pixel32bgr_dup,
-};
-
-static int vga_get_bpp(VGAState *s)
-{
- int ret;
-#ifdef CONFIG_BOCHS_VBE
- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
- ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
- } else
-#endif
- {
- ret = 0;
- }
- return ret;
-}
-
-static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
-{
- int width, height;
-
-#ifdef CONFIG_BOCHS_VBE
- if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
- width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
- height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
- } else
-#endif
- {
- width = (s->cr[0x01] + 1) * 8;
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
- height = (height + 1);
- }
- *pwidth = width;
- *pheight = height;
-}
-
-void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
-{
- int y;
- if (y1 >= VGA_MAX_HEIGHT)
- return;
- if (y2 >= VGA_MAX_HEIGHT)
- y2 = VGA_MAX_HEIGHT;
- for(y = y1; y < y2; y++) {
- s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
- }
-}
-
-/*
- * graphic modes
- */
-static void vga_draw_graphic(VGAState *s, int full_update)
-{
- int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
- int width, height, shift_control, line_offset, page0, page1, bwidth;
- int disp_width, multi_scan, multi_run;
- uint8_t *d;
- uint32_t v, addr1, addr;
- vga_draw_line_func *vga_draw_line;
-
- full_update |= update_basic_params(s);
-
- s->get_resolution(s, &width, &height);
- disp_width = width;
-
- shift_control = (s->gr[0x05] >> 5) & 3;
- double_scan = (s->cr[0x09] >> 7);
- if (shift_control != 1) {
- multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
- } else {
- /* in CGA modes, multi_scan is ignored */
- /* XXX: is it correct ? */
- multi_scan = double_scan;
- }
- multi_run = multi_scan;
- if (shift_control != s->shift_control ||
- double_scan != s->double_scan) {
- full_update = 1;
- s->shift_control = shift_control;
- s->double_scan = double_scan;
- }
-
- if (shift_control == 0) {
- full_update |= update_palette16(s);
- if (s->sr[0x01] & 8) {
- v = VGA_DRAW_LINE4D2;
- disp_width <<= 1;
- } else {
- v = VGA_DRAW_LINE4;
- }
- } else if (shift_control == 1) {
- full_update |= update_palette16(s);
- if (s->sr[0x01] & 8) {
- v = VGA_DRAW_LINE2D2;
- disp_width <<= 1;
- } else {
- v = VGA_DRAW_LINE2;
- }
- } else {
- switch(s->get_bpp(s)) {
- default:
- case 0:
- full_update |= update_palette256(s);
- v = VGA_DRAW_LINE8D2;
- break;
- case 8:
- full_update |= update_palette256(s);
- v = VGA_DRAW_LINE8;
- break;
- case 15:
- v = VGA_DRAW_LINE15;
- break;
- case 16:
- v = VGA_DRAW_LINE16;
- break;
- case 24:
- v = VGA_DRAW_LINE24;
- break;
- case 32:
- v = VGA_DRAW_LINE32;
- break;
- }
- }
- vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
-
- if (disp_width != s->last_width ||
- height != s->last_height) {
- dpy_resize(s->ds, disp_width, height);
- s->last_scr_width = disp_width;
- s->last_scr_height = height;
- s->last_width = disp_width;
- s->last_height = height;
- full_update = 1;
- }
- if (s->cursor_invalidate)
- s->cursor_invalidate(s);
-
- line_offset = s->line_offset;
-#if 0
- printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
- width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
-#endif
- addr1 = (s->start_addr * 4);
- bwidth = width * 4;
- y_start = -1;
- page_min = 0x7fffffff;
- page_max = -1;
- d = s->ds->data;
- linesize = s->ds->linesize;
- y1 = 0;
- for(y = 0; y < height; y++) {
- addr = addr1;
- if (!(s->cr[0x17] & 1)) {
- int shift;
- /* CGA compatibility handling */
- shift = 14 + ((s->cr[0x17] >> 6) & 1);
- addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
- }
- if (!(s->cr[0x17] & 2)) {
- addr = (addr & ~0x8000) | ((y1 & 2) << 14);
- }
- page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
- page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
- update = full_update |
- cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
- cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
- if ((page1 - page0) > TARGET_PAGE_SIZE) {
- /* if wide line, can use another page */
- update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
- VGA_DIRTY_FLAG);
- }
- /* explicit invalidation for the hardware cursor */
- update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
- if (update) {
- if (y_start < 0)
- y_start = y;
- if (page0 < page_min)
- page_min = page0;
- if (page1 > page_max)
- page_max = page1;
- vga_draw_line(s, d, s->vram_ptr + addr, width);
- if (s->cursor_draw_line)
- s->cursor_draw_line(s, d, y);
- } else {
- if (y_start >= 0) {
- /* flush to display */
- dpy_update(s->ds, 0, y_start,
- disp_width, y - y_start);
- y_start = -1;
- }
- }
- if (!multi_run) {
- mask = (s->cr[0x17] & 3) ^ 3;
- if ((y1 & mask) == mask)
- addr1 += line_offset;
- y1++;
- multi_run = multi_scan;
- } else {
- multi_run--;
- }
- /* line compare acts on the displayed lines */
- if (y == s->line_compare)
- addr1 = 0;
- d += linesize;
- }
- if (y_start >= 0) {
- /* flush to display */
- dpy_update(s->ds, 0, y_start,
- disp_width, y - y_start);
- }
- /* reset modified pages */
- if (page_max != -1) {
- cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
- VGA_DIRTY_FLAG);
- }
- memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
-}
-
-static void vga_draw_blank(VGAState *s, int full_update)
-{
- int i, w, val;
- uint8_t *d;
-
- if (!full_update)
- return;
- if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
- return;
- if (s->ds->depth == 8)
- val = s->rgb_to_pixel(0, 0, 0);
- else
- val = 0;
- w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
- d = s->ds->data;
- for(i = 0; i < s->last_scr_height; i++) {
- memset(d, val, w);
- d += s->ds->linesize;
- }
- dpy_update(s->ds, 0, 0,
- s->last_scr_width, s->last_scr_height);
-}
-
-#define GMODE_TEXT 0
-#define GMODE_GRAPH 1
-#define GMODE_BLANK 2
-
-static void vga_update_display(void *opaque)
-{
- VGAState *s = (VGAState *)opaque;
- int full_update, graphic_mode;
-
- if (s->ds->depth == 0) {
- /* nothing to do */
- } else {
- s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(s->ds)];
-
- full_update = 0;
- if (!(s->ar_index & 0x20)) {
- graphic_mode = GMODE_BLANK;
- } else {
- graphic_mode = s->gr[6] & 1;
- }
- if (graphic_mode != s->graphic_mode) {
- s->graphic_mode = graphic_mode;
- full_update = 1;
- }
- switch(graphic_mode) {
- case GMODE_TEXT:
- vga_draw_text(s, full_update);
- break;
- case GMODE_GRAPH:
- vga_draw_graphic(s, full_update);
- break;
- case GMODE_BLANK:
- default:
- vga_draw_blank(s, full_update);
- break;
- }
- }
-}
-
-/* force a full display refresh */
-static void vga_invalidate_display(void *opaque)
-{
- VGAState *s = (VGAState *)opaque;
-
- s->last_width = -1;
- s->last_height = -1;
-}
-
-static void vga_reset(VGAState *s)
-{
- memset(s, 0, sizeof(VGAState));
- s->graphic_mode = -1; /* force full update */
-}
-
-static CPUReadMemoryFunc *vga_mem_read[3] = {
- vga_mem_readb,
- vga_mem_readw,
- vga_mem_readl,
-};
-
-static CPUWriteMemoryFunc *vga_mem_write[3] = {
- vga_mem_writeb,
- vga_mem_writew,
- vga_mem_writel,
-};
-
-static void vga_save(QEMUFile *f, void *opaque)
-{
- VGAState *s = opaque;
- int i;
-
- qemu_put_be32s(f, &s->latch);
- qemu_put_8s(f, &s->sr_index);
- qemu_put_buffer(f, s->sr, 8);
- qemu_put_8s(f, &s->gr_index);
- qemu_put_buffer(f, s->gr, 16);
- qemu_put_8s(f, &s->ar_index);
- qemu_put_buffer(f, s->ar, 21);
- qemu_put_be32s(f, &s->ar_flip_flop);
- qemu_put_8s(f, &s->cr_index);
- qemu_put_buffer(f, s->cr, 256);
- qemu_put_8s(f, &s->msr);
- qemu_put_8s(f, &s->fcr);
- qemu_put_8s(f, &s->st00);
- qemu_put_8s(f, &s->st01);
-
- qemu_put_8s(f, &s->dac_state);
- qemu_put_8s(f, &s->dac_sub_index);
- qemu_put_8s(f, &s->dac_read_index);
- qemu_put_8s(f, &s->dac_write_index);
- qemu_put_buffer(f, s->dac_cache, 3);
- qemu_put_buffer(f, s->palette, 768);
-
- qemu_put_be32s(f, &s->bank_offset);
-#ifdef CONFIG_BOCHS_VBE
- qemu_put_byte(f, 1);
- qemu_put_be16s(f, &s->vbe_index);
- for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
- qemu_put_be16s(f, &s->vbe_regs[i]);
- qemu_put_be32s(f, &s->vbe_start_addr);
- qemu_put_be32s(f, &s->vbe_line_offset);
- qemu_put_be32s(f, &s->vbe_bank_mask);
-#else
- qemu_put_byte(f, 0);
-#endif
-}
-
-static int vga_load(QEMUFile *f, void *opaque, int version_id)
-{
- VGAState *s = opaque;
- int is_vbe, i;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->latch);
- qemu_get_8s(f, &s->sr_index);
- qemu_get_buffer(f, s->sr, 8);
- qemu_get_8s(f, &s->gr_index);
- qemu_get_buffer(f, s->gr, 16);
- qemu_get_8s(f, &s->ar_index);
- qemu_get_buffer(f, s->ar, 21);
- qemu_get_be32s(f, &s->ar_flip_flop);
- qemu_get_8s(f, &s->cr_index);
- qemu_get_buffer(f, s->cr, 256);
- qemu_get_8s(f, &s->msr);
- qemu_get_8s(f, &s->fcr);
- qemu_get_8s(f, &s->st00);
- qemu_get_8s(f, &s->st01);
-
- qemu_get_8s(f, &s->dac_state);
- qemu_get_8s(f, &s->dac_sub_index);
- qemu_get_8s(f, &s->dac_read_index);
- qemu_get_8s(f, &s->dac_write_index);
- qemu_get_buffer(f, s->dac_cache, 3);
- qemu_get_buffer(f, s->palette, 768);
-
- qemu_get_be32s(f, &s->bank_offset);
- is_vbe = qemu_get_byte(f);
-#ifdef CONFIG_BOCHS_VBE
- if (!is_vbe)
- return -EINVAL;
- qemu_get_be16s(f, &s->vbe_index);
- for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
- qemu_get_be16s(f, &s->vbe_regs[i]);
- qemu_get_be32s(f, &s->vbe_start_addr);
- qemu_get_be32s(f, &s->vbe_line_offset);
- qemu_get_be32s(f, &s->vbe_bank_mask);
-#else
- if (is_vbe)
- return -EINVAL;
-#endif
-
- /* force refresh */
- s->graphic_mode = -1;
- return 0;
-}
-
-static void vga_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- VGAState *s = vga_state;
- if (region_num == PCI_ROM_SLOT) {
- cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
- } else {
- cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
- }
-}
-
-void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size)
-{
- int i, j, v, b;
-
- for(i = 0;i < 256; i++) {
- v = 0;
- for(j = 0; j < 8; j++) {
- v |= ((i >> j) & 1) << (j * 4);
- }
- expand4[i] = v;
-
- v = 0;
- for(j = 0; j < 4; j++) {
- v |= ((i >> (2 * j)) & 3) << (j * 4);
- }
- expand2[i] = v;
- }
- for(i = 0; i < 16; i++) {
- v = 0;
- for(j = 0; j < 4; j++) {
- b = ((i >> j) & 1);
- v |= b << (2 * j);
- v |= b << (2 * j + 1);
- }
- expand4to8[i] = v;
- }
-
- vga_reset(s);
-
- s->vram_ptr = vga_ram_base;
- s->vram_offset = vga_ram_offset;
- s->vram_size = vga_ram_size;
- s->ds = ds;
- s->get_bpp = vga_get_bpp;
- s->get_offsets = vga_get_offsets;
- s->get_resolution = vga_get_resolution;
- graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
- vga_screen_dump, s);
- /* XXX: currently needed for display */
- vga_state = s;
-}
-
-
-int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size,
- unsigned long vga_bios_offset, int vga_bios_size)
-{
- VGAState *s;
-
- s = qemu_mallocz(sizeof(VGAState));
- if (!s)
- return -1;
-
- vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
-
- register_savevm("vga", 0, 1, vga_save, vga_load, s);
-
- register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
-
- register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
- register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
- register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
- register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
-
- register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
-
- register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
- register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
- register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
- register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
- s->bank_offset = 0;
-
-#ifdef CONFIG_BOCHS_VBE
- s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
- s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
-#if defined (TARGET_I386)
- register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
- register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
-
- register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
- register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
-
- /* old Bochs IO ports */
- register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
- register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
-
- register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
- register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
-#else
- register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
- register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
-
- register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
- register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
-#endif
-#endif /* CONFIG_BOCHS_VBE */
-
- vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
- cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
- vga_io_memory);
-
- if (bus) {
- PCIDevice *d;
- uint8_t *pci_conf;
-
- d = pci_register_device(bus, "VGA",
- sizeof(PCIDevice),
- -1, NULL, NULL);
- pci_conf = d->config;
- pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
- pci_conf[0x01] = 0x12;
- pci_conf[0x02] = 0x11;
- pci_conf[0x03] = 0x11;
- pci_conf[0x0a] = 0x00; // VGA controller
- pci_conf[0x0b] = 0x03;
- pci_conf[0x0e] = 0x00; // header_type
-
- /* XXX: vga_ram_size must be a power of two */
- pci_register_io_region(d, 0, vga_ram_size,
- PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
- if (vga_bios_size != 0) {
- unsigned int bios_total_size;
- s->bios_offset = vga_bios_offset;
- s->bios_size = vga_bios_size;
- /* must be a power of two */
- bios_total_size = 1;
- while (bios_total_size < vga_bios_size)
- bios_total_size <<= 1;
- pci_register_io_region(d, PCI_ROM_SLOT, bios_total_size,
- PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
- }
- } else {
-#ifdef CONFIG_BOCHS_VBE
- /* XXX: use optimized standard vga accesses */
- cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
- vga_ram_size, vga_ram_offset);
-#endif
- }
- return 0;
-}
-
-/********************************************************/
-/* vga screen dump */
-
-static int vga_save_w, vga_save_h;
-
-static void vga_save_dpy_update(DisplayState *s,
- int x, int y, int w, int h)
-{
-}
-
-static void vga_save_dpy_resize(DisplayState *s, int w, int h)
-{
- s->linesize = w * 4;
- s->data = qemu_malloc(h * s->linesize);
- vga_save_w = w;
- vga_save_h = h;
-}
-
-static void vga_save_dpy_refresh(DisplayState *s)
-{
-}
-
-static int ppm_save(const char *filename, uint8_t *data,
- int w, int h, int linesize)
-{
- FILE *f;
- uint8_t *d, *d1;
- unsigned int v;
- int y, x;
-
- f = fopen(filename, "wb");
- if (!f)
- return -1;
- fprintf(f, "P6\n%d %d\n%d\n",
- w, h, 255);
- d1 = data;
- for(y = 0; y < h; y++) {
- d = d1;
- for(x = 0; x < w; x++) {
- v = *(uint32_t *)d;
- fputc((v >> 16) & 0xff, f);
- fputc((v >> 8) & 0xff, f);
- fputc((v) & 0xff, f);
- d += 4;
- }
- d1 += linesize;
- }
- fclose(f);
- return 0;
-}
-
-/* save the vga display in a PPM image even if no display is
- available */
-static void vga_screen_dump(void *opaque, const char *filename)
-{
- VGAState *s = (VGAState *)opaque;
- DisplayState *saved_ds, ds1, *ds = &ds1;
-
- /* XXX: this is a little hackish */
- vga_invalidate_display(s);
- saved_ds = s->ds;
-
- memset(ds, 0, sizeof(DisplayState));
- ds->dpy_update = vga_save_dpy_update;
- ds->dpy_resize = vga_save_dpy_resize;
- ds->dpy_refresh = vga_save_dpy_refresh;
- ds->depth = 32;
-
- s->ds = ds;
- s->graphic_mode = -1;
- vga_update_display(s);
-
- if (ds->data) {
- ppm_save(filename, ds->data, vga_save_w, vga_save_h,
- s->ds->linesize);
- qemu_free(ds->data);
- }
- s->ds = saved_ds;
-}
diff --git a/hw/vga_int.h b/hw/vga_int.h
deleted file mode 100644
index b33ab57..0000000
--- a/hw/vga_int.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * QEMU internal VGA defines.
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#define MSR_COLOR_EMULATION 0x01
-#define MSR_PAGE_SELECT 0x20
-
-#define ST01_V_RETRACE 0x08
-#define ST01_DISP_ENABLE 0x01
-
-/* bochs VBE support */
-#define CONFIG_BOCHS_VBE
-
-#define VBE_DISPI_MAX_XRES 1600
-#define VBE_DISPI_MAX_YRES 1200
-#define VBE_DISPI_MAX_BPP 32
-
-#define VBE_DISPI_INDEX_ID 0x0
-#define VBE_DISPI_INDEX_XRES 0x1
-#define VBE_DISPI_INDEX_YRES 0x2
-#define VBE_DISPI_INDEX_BPP 0x3
-#define VBE_DISPI_INDEX_ENABLE 0x4
-#define VBE_DISPI_INDEX_BANK 0x5
-#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
-#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
-#define VBE_DISPI_INDEX_X_OFFSET 0x8
-#define VBE_DISPI_INDEX_Y_OFFSET 0x9
-#define VBE_DISPI_INDEX_NB 0xa
-
-#define VBE_DISPI_ID0 0xB0C0
-#define VBE_DISPI_ID1 0xB0C1
-#define VBE_DISPI_ID2 0xB0C2
-
-#define VBE_DISPI_DISABLED 0x00
-#define VBE_DISPI_ENABLED 0x01
-#define VBE_DISPI_GETCAPS 0x02
-#define VBE_DISPI_8BIT_DAC 0x20
-#define VBE_DISPI_LFB_ENABLED 0x40
-#define VBE_DISPI_NOCLEARMEM 0x80
-
-#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
-
-#ifdef CONFIG_BOCHS_VBE
-
-#define VGA_STATE_COMMON_BOCHS_VBE \
- uint16_t vbe_index; \
- uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \
- uint32_t vbe_start_addr; \
- uint32_t vbe_line_offset; \
- uint32_t vbe_bank_mask;
-
-#else
-
-#define VGA_STATE_COMMON_BOCHS_VBE
-
-#endif /* !CONFIG_BOCHS_VBE */
-
-#define CH_ATTR_SIZE (160 * 100)
-#define VGA_MAX_HEIGHT 2048
-
-#define VGA_STATE_COMMON \
- uint8_t *vram_ptr; \
- unsigned long vram_offset; \
- unsigned int vram_size; \
- unsigned long bios_offset; \
- unsigned int bios_size; \
- uint32_t latch; \
- uint8_t sr_index; \
- uint8_t sr[256]; \
- uint8_t gr_index; \
- uint8_t gr[256]; \
- uint8_t ar_index; \
- uint8_t ar[21]; \
- int ar_flip_flop; \
- uint8_t cr_index; \
- uint8_t cr[256]; /* CRT registers */ \
- uint8_t msr; /* Misc Output Register */ \
- uint8_t fcr; /* Feature Control Register */ \
- uint8_t st00; /* status 0 */ \
- uint8_t st01; /* status 1 */ \
- uint8_t dac_state; \
- uint8_t dac_sub_index; \
- uint8_t dac_read_index; \
- uint8_t dac_write_index; \
- uint8_t dac_cache[3]; /* used when writing */ \
- uint8_t palette[768]; \
- int32_t bank_offset; \
- int (*get_bpp)(struct VGAState *s); \
- void (*get_offsets)(struct VGAState *s, \
- uint32_t *pline_offset, \
- uint32_t *pstart_addr); \
- void (*get_resolution)(struct VGAState *s, \
- int *pwidth, \
- int *pheight); \
- VGA_STATE_COMMON_BOCHS_VBE \
- /* display refresh support */ \
- DisplayState *ds; \
- uint32_t font_offsets[2]; \
- int graphic_mode; \
- uint8_t shift_control; \
- uint8_t double_scan; \
- uint32_t line_offset; \
- uint32_t line_compare; \
- uint32_t start_addr; \
- uint32_t plane_updated; \
- uint8_t last_cw, last_ch; \
- uint32_t last_width, last_height; /* in chars or pixels */ \
- uint32_t last_scr_width, last_scr_height; /* in pixels */ \
- uint8_t cursor_start, cursor_end; \
- uint32_t cursor_offset; \
- unsigned int (*rgb_to_pixel)(unsigned int r, \
- unsigned int g, unsigned b); \
- /* hardware mouse cursor support */ \
- uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \
- void (*cursor_invalidate)(struct VGAState *s); \
- void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \
- /* tell for each page if it has been updated since the last time */ \
- uint32_t last_palette[256]; \
- uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
-
-
-typedef struct VGAState {
- VGA_STATE_COMMON
-} VGAState;
-
-static inline int c6_to_8(int v)
-{
- int b;
- v &= 0x3f;
- b = v & 1;
- return (v << 2) | (b << 1) | b;
-}
-
-void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size);
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
-void vga_invalidate_scanlines(VGAState *s, int y1, int y2);
-
-void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
- int poffset, int w,
- unsigned int color0, unsigned int color1,
- unsigned int color_xor);
-
-extern const uint8_t sr_mask[8];
-extern const uint8_t gr_mask[16];
diff --git a/hw/vga_template.h b/hw/vga_template.h
deleted file mode 100644
index e7e8cb8..0000000
--- a/hw/vga_template.h
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * QEMU VGA Emulator templates
- *
- * Copyright (c) 2003 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if DEPTH == 8
-#define BPP 1
-#define PIXEL_TYPE uint8_t
-#elif DEPTH == 15 || DEPTH == 16
-#define BPP 2
-#define PIXEL_TYPE uint16_t
-#elif DEPTH == 32
-#define BPP 4
-#define PIXEL_TYPE uint32_t
-#else
-#error unsupport depth
-#endif
-
-#ifdef BGR_FORMAT
-#define PIXEL_NAME glue(DEPTH, bgr)
-#else
-#define PIXEL_NAME DEPTH
-#endif /* BGR_FORMAT */
-
-#if DEPTH != 15 && !defined(BGR_FORMAT)
-
-static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
- uint32_t font_data,
- uint32_t xorcol,
- uint32_t bgcol)
-{
-#if BPP == 1
- ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
- ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
-#elif BPP == 2
- ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
- ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
- ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
- ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
-#else
- ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
- ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
-#endif
-}
-
-static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
- const uint8_t *font_ptr, int h,
- uint32_t fgcol, uint32_t bgcol)
-{
- uint32_t font_data, xorcol;
-
- xorcol = bgcol ^ fgcol;
- do {
- font_data = font_ptr[0];
- glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
- font_ptr += 4;
- d += linesize;
- } while (--h);
-}
-
-static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
- const uint8_t *font_ptr, int h,
- uint32_t fgcol, uint32_t bgcol)
-{
- uint32_t font_data, xorcol;
-
- xorcol = bgcol ^ fgcol;
- do {
- font_data = font_ptr[0];
- glue(vga_draw_glyph_line_, DEPTH)(d,
- expand4to8[font_data >> 4],
- xorcol, bgcol);
- glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
- expand4to8[font_data & 0x0f],
- xorcol, bgcol);
- font_ptr += 4;
- d += linesize;
- } while (--h);
-}
-
-static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
- const uint8_t *font_ptr, int h,
- uint32_t fgcol, uint32_t bgcol, int dup9)
-{
- uint32_t font_data, xorcol, v;
-
- xorcol = bgcol ^ fgcol;
- do {
- font_data = font_ptr[0];
-#if BPP == 1
- cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
- v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
- cpu_to_32wu(((uint32_t *)d)+1, v);
- if (dup9)
- ((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
- else
- ((uint8_t *)d)[8] = bgcol;
-
-#elif BPP == 2
- cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
- cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
- cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
- v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
- cpu_to_32wu(((uint32_t *)d)+3, v);
- if (dup9)
- ((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
- else
- ((uint16_t *)d)[8] = bgcol;
-#else
- ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
- ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
- v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
- ((uint32_t *)d)[7] = v;
- if (dup9)
- ((uint32_t *)d)[8] = v;
- else
- ((uint32_t *)d)[8] = bgcol;
-#endif
- font_ptr += 4;
- d += linesize;
- } while (--h);
-}
-
-/*
- * 4 color mode
- */
-static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- uint32_t plane_mask, *palette, data, v;
- int x;
-
- palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
- width >>= 3;
- for(x = 0; x < width; x++) {
- data = ((uint32_t *)s)[0];
- data &= plane_mask;
- v = expand2[GET_PLANE(data, 0)];
- v |= expand2[GET_PLANE(data, 2)] << 2;
- ((PIXEL_TYPE *)d)[0] = palette[v >> 12];
- ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
- ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
- ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
-
- v = expand2[GET_PLANE(data, 1)];
- v |= expand2[GET_PLANE(data, 3)] << 2;
- ((PIXEL_TYPE *)d)[4] = palette[v >> 12];
- ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
- ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
- ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
- d += BPP * 8;
- s += 4;
- }
-}
-
-#if BPP == 1
-#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
-#elif BPP == 2
-#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
-#else
-#define PUT_PIXEL2(d, n, v) \
-((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
-#endif
-
-/*
- * 4 color mode, dup2 horizontal
- */
-static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- uint32_t plane_mask, *palette, data, v;
- int x;
-
- palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
- width >>= 3;
- for(x = 0; x < width; x++) {
- data = ((uint32_t *)s)[0];
- data &= plane_mask;
- v = expand2[GET_PLANE(data, 0)];
- v |= expand2[GET_PLANE(data, 2)] << 2;
- PUT_PIXEL2(d, 0, palette[v >> 12]);
- PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
- PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
- PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
-
- v = expand2[GET_PLANE(data, 1)];
- v |= expand2[GET_PLANE(data, 3)] << 2;
- PUT_PIXEL2(d, 4, palette[v >> 12]);
- PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
- PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
- PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
- d += BPP * 16;
- s += 4;
- }
-}
-
-/*
- * 16 color mode
- */
-static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- uint32_t plane_mask, data, v, *palette;
- int x;
-
- palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
- width >>= 3;
- for(x = 0; x < width; x++) {
- data = ((uint32_t *)s)[0];
- data &= plane_mask;
- v = expand4[GET_PLANE(data, 0)];
- v |= expand4[GET_PLANE(data, 1)] << 1;
- v |= expand4[GET_PLANE(data, 2)] << 2;
- v |= expand4[GET_PLANE(data, 3)] << 3;
- ((PIXEL_TYPE *)d)[0] = palette[v >> 28];
- ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
- ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
- ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
- ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
- ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
- ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
- ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
- d += BPP * 8;
- s += 4;
- }
-}
-
-/*
- * 16 color mode, dup2 horizontal
- */
-static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- uint32_t plane_mask, data, v, *palette;
- int x;
-
- palette = s1->last_palette;
- plane_mask = mask16[s1->ar[0x12] & 0xf];
- width >>= 3;
- for(x = 0; x < width; x++) {
- data = ((uint32_t *)s)[0];
- data &= plane_mask;
- v = expand4[GET_PLANE(data, 0)];
- v |= expand4[GET_PLANE(data, 1)] << 1;
- v |= expand4[GET_PLANE(data, 2)] << 2;
- v |= expand4[GET_PLANE(data, 3)] << 3;
- PUT_PIXEL2(d, 0, palette[v >> 28]);
- PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
- PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
- PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
- PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
- PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
- PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
- PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
- d += BPP * 16;
- s += 4;
- }
-}
-
-/*
- * 256 color mode, double pixels
- *
- * XXX: add plane_mask support (never used in standard VGA modes)
- */
-static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- uint32_t *palette;
- int x;
-
- palette = s1->last_palette;
- width >>= 3;
- for(x = 0; x < width; x++) {
- PUT_PIXEL2(d, 0, palette[s[0]]);
- PUT_PIXEL2(d, 1, palette[s[1]]);
- PUT_PIXEL2(d, 2, palette[s[2]]);
- PUT_PIXEL2(d, 3, palette[s[3]]);
- d += BPP * 8;
- s += 4;
- }
-}
-
-/*
- * standard 256 color mode
- *
- * XXX: add plane_mask support (never used in standard VGA modes)
- */
-static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- uint32_t *palette;
- int x;
-
- palette = s1->last_palette;
- width >>= 3;
- for(x = 0; x < width; x++) {
- ((PIXEL_TYPE *)d)[0] = palette[s[0]];
- ((PIXEL_TYPE *)d)[1] = palette[s[1]];
- ((PIXEL_TYPE *)d)[2] = palette[s[2]];
- ((PIXEL_TYPE *)d)[3] = palette[s[3]];
- ((PIXEL_TYPE *)d)[4] = palette[s[4]];
- ((PIXEL_TYPE *)d)[5] = palette[s[5]];
- ((PIXEL_TYPE *)d)[6] = palette[s[6]];
- ((PIXEL_TYPE *)d)[7] = palette[s[7]];
- d += BPP * 8;
- s += 8;
- }
-}
-
-void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
- const uint8_t *src1,
- int poffset, int w,
- unsigned int color0,
- unsigned int color1,
- unsigned int color_xor)
-{
- const uint8_t *plane0, *plane1;
- int x, b0, b1;
- uint8_t *d;
-
- d = d1;
- plane0 = src1;
- plane1 = src1 + poffset;
- for(x = 0; x < w; x++) {
- b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
- b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
-#if DEPTH == 8
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- d[0] ^= color_xor;
- break;
- case 2:
- d[0] = color0;
- break;
- case 3:
- d[0] = color1;
- break;
- }
-#elif DEPTH == 16
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- ((uint16_t *)d)[0] ^= color_xor;
- break;
- case 2:
- ((uint16_t *)d)[0] = color0;
- break;
- case 3:
- ((uint16_t *)d)[0] = color1;
- break;
- }
-#elif DEPTH == 32
- switch(b0 | (b1 << 1)) {
- case 0:
- break;
- case 1:
- ((uint32_t *)d)[0] ^= color_xor;
- break;
- case 2:
- ((uint32_t *)d)[0] = color0;
- break;
- case 3:
- ((uint32_t *)d)[0] = color1;
- break;
- }
-#else
-#error unsupported depth
-#endif
- d += BPP;
- }
-}
-
-#endif /* DEPTH != 15 */
-
-
-/* XXX: optimize */
-
-/*
- * 15 bit color
- */
-static void glue(vga_draw_line15_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
-#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
- memcpy(d, s, width * 2);
-#else
- int w;
- uint32_t v, r, g, b;
-
- w = width;
- do {
- v = lduw_raw((void *)s);
- r = (v >> 7) & 0xf8;
- g = (v >> 2) & 0xf8;
- b = (v << 3) & 0xf8;
- ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
- s += 2;
- d += BPP;
- } while (--w != 0);
-#endif
-}
-
-/*
- * 16 bit color
- */
-static void glue(vga_draw_line16_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
-#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
- memcpy(d, s, width * 2);
-#else
- int w;
- uint32_t v, r, g, b;
-
- w = width;
- do {
- v = lduw_raw((void *)s);
- r = (v >> 8) & 0xf8;
- g = (v >> 3) & 0xfc;
- b = (v << 3) & 0xf8;
- ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
- s += 2;
- d += BPP;
- } while (--w != 0);
-#endif
-}
-
-/*
- * 24 bit color
- */
-static void glue(vga_draw_line24_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
- int w;
- uint32_t r, g, b;
-
- w = width;
- do {
-#if defined(TARGET_WORDS_BIGENDIAN)
- r = s[0];
- g = s[1];
- b = s[2];
-#else
- b = s[0];
- g = s[1];
- r = s[2];
-#endif
- ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
- s += 3;
- d += BPP;
- } while (--w != 0);
-}
-
-/*
- * 32 bit color
- */
-static void glue(vga_draw_line32_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
- const uint8_t *s, int width)
-{
-#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT)
- memcpy(d, s, width * 4);
-#else
- int w;
- uint32_t r, g, b;
-
- w = width;
- do {
-#if defined(TARGET_WORDS_BIGENDIAN)
- r = s[1];
- g = s[2];
- b = s[3];
-#else
- b = s[0];
- g = s[1];
- r = s[2];
-#endif
- ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
- s += 4;
- d += BPP;
- } while (--w != 0);
-#endif
-}
-
-#undef PUT_PIXEL2
-#undef DEPTH
-#undef BPP
-#undef PIXEL_TYPE
-#undef PIXEL_NAME
-#undef BGR_FORMAT