[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Patch: Sparc system support (2/3)
From: |
Blue Swirl |
Subject: |
[Qemu-devel] Patch: Sparc system support (2/3) |
Date: |
Sat, 18 Sep 2004 09:37:24 +0200 |
Hi,
Contents: IOMMU, TCX frame buffer (basic), interrupt controllers, timers
(incomplete), and Lance Ethernet emulation. Bound together to emulate Sun4m
architecture.
diff -ruN qemu-0.6.0.orig/hw/iommu.c qemu-0.6.0/hw/iommu.c
--- qemu-0.6.0.orig/hw/iommu.c 1970-01-01 01:00:00.000000000 +0100
+++ qemu-0.6.0/hw/iommu.c 2004-09-15 19:50:27.000000000 +0200
@@ -0,0 +1,141 @@
+/*
+ * QEMU iommu 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"
+#include "iommu.h"
+
+/* debug iommu */
+//#define DEBUG_IOMMU
+
+#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (PAGE_SIZE - 1)
+
+typedef struct IOMMUState {
+ uint32_t regs[sizeof(struct iommu_regs)];
+} IOMMUState;
+
+static IOMMUState *ps;
+
+static int iommu_io_memory;
+
+static void iommu_reset(IOMMUState *s)
+{
+}
+
+static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ IOMMUState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_IOMMU) >> 2;
+ switch (saddr) {
+ default:
+ 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 - PHYS_JJ_IOMMU) >> 2;
+ switch (saddr) {
+ 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(uint32_t addr)
+{
+ uint32_t *iopte = (void *)(ps->regs[1] << 4), pa, iostart;
+
+ switch (ps->regs[0] & IOMMU_CTRL_RNGE) {
+ case IOMMU_RNGE_16MB:
+ iostart = 0xff000000;
+ break;
+ case IOMMU_RNGE_32MB:
+ iostart = 0xfe000000;
+ break;
+ case IOMMU_RNGE_64MB:
+ iostart = 0xfc000000;
+ break;
+ case IOMMU_RNGE_128MB:
+ iostart = 0xf8000000;
+ break;
+ case IOMMU_RNGE_256MB:
+ iostart = 0xf0000000;
+ break;
+ case IOMMU_RNGE_512MB:
+ iostart = 0xe0000000;
+ break;
+ case IOMMU_RNGE_1GB:
+ iostart = 0xc0000000;
+ break;
+ default:
+ case IOMMU_RNGE_2GB:
+ iostart = 0x80000000;
+ break;
+ }
+
+ iopte += ((addr - iostart) >> PAGE_SHIFT);
+ cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
+ bswap32s(&pa);
+ pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
+ //return pa + PAGE_SIZE;
+ return pa + (addr & PAGE_MASK);
+}
+
+void iommu_init()
+{
+ IOMMUState *s;
+
+ s = qemu_mallocz(sizeof(IOMMUState));
+ if (!s)
+ return;
+
+ iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read,
iommu_mem_write, s);
+ cpu_register_physical_memory(PHYS_JJ_IOMMU, sizeof(struct iommu_regs),
+ iommu_io_memory);
+
+ iommu_reset(s);
+ ps = s;
+}
+
diff -ruN qemu-0.6.0.orig/hw/iommu.h qemu-0.6.0/hw/iommu.h
--- qemu-0.6.0.orig/hw/iommu.h 1970-01-01 01:00:00.000000000 +0100
+++ qemu-0.6.0/hw/iommu.h 2004-09-11 19:13:34.000000000 +0200
@@ -0,0 +1,97 @@
+/* iommu.h: Definitions for the sun4m IOMMU.
+ *
+ * Copyright (C) 1996 David S. Miller (address@hidden)
+ * Adapted for Proll by Pete Zaitcev in 1999 (== made worse than original).
+ */
+
+/* #include <asm/page.h> */
+
+/* The iommu handles all virtual to physical address translations
+ * that occur between the SBUS and physical memory. Access by
+ * the cpu to IO registers and similar go over the mbus so are
+ * translated by the on chip SRMMU. The iommu and the srmmu do
+ * not need to have the same translations at all, in fact most
+ * of the time the translations they handle are a disjunct set.
+ * Basically the iommu handles all dvma sbus activity.
+ */
+
+/* The IOMMU registers occupy three pages in IO space. */
+struct iommu_regs {
+ /* First page */
+ volatile unsigned long control; /* IOMMU control */
+ volatile unsigned long base; /* Physical base of iopte page table
*/
+ volatile unsigned long _unused1[3];
+ volatile unsigned long tlbflush; /* write only */
+ volatile unsigned long pageflush; /* write only */
+ volatile unsigned long _unused2[1017];
+ /* Second page */
+ volatile unsigned long afsr; /* Async-fault status register */
+ volatile unsigned long afar; /* Async-fault physical address */
+ volatile unsigned long _unused3[2];
+ volatile unsigned long sbuscfg0; /* SBUS configuration registers,
per-slot */
+ volatile unsigned long sbuscfg1;
+ volatile unsigned long sbuscfg2;
+ volatile unsigned long sbuscfg3;
+ volatile unsigned long mfsr; /* Memory-fault status register */
+ volatile unsigned long mfar; /* Memory-fault physical address */
+ volatile unsigned long _unused4[1014];
+ /* Third page */
+ volatile unsigned long mid; /* IOMMU module-id */
+};
+
+#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
+#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
+#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_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
+#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after
transaction */
+#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8
us. */
+#define IOMMU_AFSR_BE 0x10000000 /* Write access received error
acknowledge */
+#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error
*/
+#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by
hardware */
+#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
+#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress
*/
+#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
+
+#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_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
+#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity
error */
+#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred
*/
+#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error
occurred
+ on the even word of the access, low
bit
+ indicated odd word caused the parity
error */
+#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode
*/
+#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked
cacheable */
+#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type
*/
+
+#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
+#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration
*/
+#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration
*/
+#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration
*/
+#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration
*/
+#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration
*/
+#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
+
+/* 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 */
diff -ruN qemu-0.6.0.orig/hw/lance.c qemu-0.6.0/hw/lance.c
--- qemu-0.6.0.orig/hw/lance.c 1970-01-01 01:00:00.000000000 +0100
+++ qemu-0.6.0/hw/lance.c 2004-09-14 22:06:22.000000000 +0200
@@ -0,0 +1,446 @@
+/*
+ * QEMU Lance 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 LANCE card */
+//#define DEBUG_LANCE
+
+#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
+#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused
SCSI */
+#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */
+
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 4
+#define LANCE_LOG_RX_BUFFERS 4
+#endif
+
+#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
+#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
+
+
+#define LE_CSR0 0
+#define LE_CSR1 1
+#define LE_CSR2 2
+#define LE_CSR3 3
+#define LE_MAXREG (LE_CSR3 + 1)
+
+#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
+#if 0
+/* Structure to describe the current status of DMA registers on the Sparc
*/
+struct sparc_dma_registers {
+ uint32_t cond_reg; /* DMA condition register */
+ uint32_t st_addr; /* Start address of this transfer */
+ uint32_t cnt; /* How many bytes to transfer */
+ uint32_t dma_test; /* DMA test register */
+};
+#endif
+
+typedef struct LEDMAState {
+ uint32_t regs[LEDMA_REGS];
+} LEDMAState;
+
+typedef struct LANCEState {
+ NetDriverState *nd;
+ uint32_t leptr;
+ uint16_t addr;
+ uint16_t regs[LE_MAXREG];
+ uint8_t phys[6]; /* mac address */
+ int irq;
+ LEDMAState *ledma;
+} LANCEState;
+
+static int lance_io_memory;
+
+static unsigned int rxptr, txptr;
+
+static void lance_send(void *opaque);
+
+static void lance_reset(LANCEState *s)
+{
+ memcpy(s->phys, s->nd->macaddr, 6);
+ rxptr = 0;
+ txptr = 0;
+ s->regs[LE_CSR0] = LE_C0_STOP;
+}
+
+static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ LANCEState *s = opaque;
+ uint32_t saddr;
+
+ saddr = addr - PHYS_JJ_LE;
+ switch (saddr >> 1) {
+ case LE_RDP:
+ return s->regs[s->addr];
+ case LE_RAP:
+ return s->addr;
+ default:
+ 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 clear, reg;
+
+ saddr = addr - PHYS_JJ_LE;
+ switch (saddr >> 1) {
+ case LE_RDP:
+ 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;
+
+ // trigger bits
+ //if (val & LE_C0_TDMD)
+
+ if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] &
LE_C0_INEA))
+ pic_set_irq(s->irq, 1);
+ 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:
+ if (val < LE_MAXREG)
+ s->addr = val;
+ break;
+ default:
+ 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,
+};
+
+
+/* return the max buffer size if the LANCE can receive more data */
+static int lance_can_receive(void *opaque)
+{
+ LANCEState *s = opaque;
+ void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+ struct lance_init_block *ib;
+ int i;
+ uint16_t temp;
+
+ if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
+ return 0;
+
+ ib = (void *) iommu_translate(dmaptr);
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ cpu_physical_memory_rw(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1,
0);
+ if (temp == (LE_R1_OWN)) {
+ return RX_BUFF_SIZE;
+ }
+ }
+ return 0;
+}
+
+#define MIN_BUF_SIZE 60
+
+static void lance_receive(void *opaque, const uint8_t *buf, int size)
+{
+ LANCEState *s = opaque;
+ void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+ struct lance_init_block *ib;
+ unsigned int i, old_rxptr;
+ uint16_t temp;
+
+ if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
+ return;
+
+ ib = (void *) iommu_translate(dmaptr);
+
+ old_rxptr = rxptr;
+ for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1)
& RX_RING_MOD_MASK) {
+ cpu_physical_memory_rw(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1,
0);
+ if (temp == (LE_R1_OWN)) {
+ rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
+ temp = size;
+ bswap16s(&temp);
+ cpu_physical_memory_rw(&ib->brx_ring[i].mblength, (void *) &temp, 2,
1);
+ cpu_physical_memory_rw(&ib->rx_buf[i], buf, size, 1);
+ temp = LE_R1_POK;
+ cpu_physical_memory_rw(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1,
1);
+ s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
+ if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] &
LE_C0_INEA))
+ pic_set_irq(s->irq, 1);
+ return;
+ }
+ }
+}
+
+static void lance_send(void *opaque)
+{
+ LANCEState *s = opaque;
+ void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+ struct lance_init_block *ib;
+ unsigned int i, old_txptr;
+ uint16_t temp;
+ char pkt_buf[PKT_BUF_SZ];
+
+ if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
+ return;
+
+ ib = (void *) iommu_translate(dmaptr);
+
+ old_txptr = txptr;
+ for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1)
& TX_RING_MOD_MASK) {
+ cpu_physical_memory_rw(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1,
0);
+ if (temp == (LE_T1_POK|LE_T1_OWN)) {
+ cpu_physical_memory_rw(&ib->btx_ring[i].length, (void *) &temp, 2,
0);
+ bswap16s(&temp);
+ temp = (~temp) + 1;
+ cpu_physical_memory_rw(&ib->tx_buf[i], pkt_buf, temp, 0);
+ qemu_send_packet(s->nd, pkt_buf, temp);
+ temp = LE_T1_POK;
+ cpu_physical_memory_rw(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1,
1);
+ txptr = (txptr + 1) & TX_RING_MOD_MASK;
+ s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
+ }
+ }
+}
+
+static int ledma_io_memory;
+
+static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ LEDMAState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_LEDMA) >> 2;
+ if (saddr < LEDMA_REGS)
+ return s->regs[saddr];
+ else
+ return 0;
+}
+
+static void ledma_mem_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
+{
+ LEDMAState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_LEDMA) >> 2;
+ if (saddr < LEDMA_REGS)
+ s->regs[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,
+};
+
+void lance_init(NetDriverState *nd, int irq)
+{
+ LANCEState *s;
+ LEDMAState *led;
+
+ s = qemu_mallocz(sizeof(LANCEState));
+ if (!s)
+ return;
+
+ lance_io_memory = cpu_register_io_memory(0, lance_mem_read,
lance_mem_write, s);
+ cpu_register_physical_memory(PHYS_JJ_LE, 8,
+ lance_io_memory);
+ led = qemu_mallocz(sizeof(LEDMAState));
+ if (!led)
+ return;
+
+ ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read,
ledma_mem_write, led);
+ cpu_register_physical_memory(PHYS_JJ_LEDMA, 16,
+ ledma_io_memory);
+
+ s->nd = nd;
+ s->ledma = led;
+ s->irq = irq;
+
+ lance_reset(s);
+ qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
+}
+
diff -ruN qemu-0.6.0.orig/hw/sched.c qemu-0.6.0/hw/sched.c
--- qemu-0.6.0.orig/hw/sched.c 1970-01-01 01:00:00.000000000 +0100
+++ qemu-0.6.0/hw/sched.c 2004-09-12 23:06:48.000000000 +0200
@@ -0,0 +1,346 @@
+/*
+ * QEMU interrupt controller & 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 PHYS_JJ_CLOCK 0x71D00000
+#define PHYS_JJ_CLOCK1 0x71D10000
+#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
+#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
+
+/* These registers are used for sending/receiving irqs from/to
+ * different cpu's.
+ */
+struct sun4m_intreg_percpu {
+ unsigned int tbt; /* Intrs pending for this cpu, by PIL. */
+ /* These next two registers are WRITE-ONLY and are only
+ * "on bit" sensitive, "off bits" written have NO affect.
+ */
+ unsigned int clear; /* Clear this cpus irqs here. */
+ unsigned int set; /* Set this cpus irqs here. */
+};
+/*
+ * djhr
+ * Actually the clear and set fields in this struct are misleading..
+ * according to the SLAVIO manual (and the same applies for the SEC)
+ * the clear field clears bits in the mask which will ENABLE that IRQ
+ * the set field sets bits in the mask to DISABLE the IRQ.
+ *
+ * Also the undirected_xx address in the SLAVIO is defined as
+ * RESERVED and write only..
+ *
+ * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
+ * sun4m machines, for MP the layout makes more sense.
+ */
+struct sun4m_intreg_master {
+ unsigned int tbt; /* IRQ's that are pending, see sun4m masks. */
+ unsigned int irqs; /* Master IRQ bits. */
+
+ /* Again, like the above, two these registers are WRITE-ONLY. */
+ unsigned int clear; /* Clear master IRQ's by setting bits here. */
+ unsigned int set; /* Set master IRQ's by setting bits here. */
+
+ /* This register is both READ and WRITE. */
+ unsigned int undirected_target; /* Which cpu gets undirected irqs. */
+};
+/*
+ * Registers of hardware timer in sun4m.
+ */
+struct sun4m_timer_percpu {
+ volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
+ volatile unsigned int l14_cur_count;
+};
+
+struct sun4m_timer_global {
+ volatile unsigned int l10_timer_limit;
+ volatile unsigned int l10_cur_count;
+};
+
+#define SUN4M_INT_ENABLE 0x80000000
+#define SUN4M_INT_E14 0x00000080
+#define SUN4M_INT_E10 0x00080000
+
+#define SUN4M_HARD_INT(x) (0x000000001 << (x))
+#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
+
+#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
+#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
+#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */
+#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */
+#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */
+#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */
+#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */
+#define SUN4M_INT_REALTIME 0x00080000 /* system timer */
+#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */
+#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */
+#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */
+#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */
+#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */
+
+#define SUN4M_INT_SBUS(x) (1 << (x+7))
+#define SUN4M_INT_VME(x) (1 << (x))
+
+typedef struct SCHEDState {
+ uint32_t intreg_pending;
+ uint32_t intreg_enabled;
+ uint32_t intregm_pending;
+ uint32_t intregm_enabled;
+ uint32_t timer_regs[2];
+ uint32_t timerm_regs[2];
+} SCHEDState;
+
+static SCHEDState *ps;
+
+static int intreg_io_memory, intregm_io_memory,
+ timer_io_memory, timerm_io_memory;
+
+static void sched_reset(SCHEDState *s)
+{
+}
+
+static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_INTR0) >> 2;
+ switch (saddr) {
+ case 0:
+ return s->intreg_pending;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void intreg_mem_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_INTR0) >> 2;
+ switch (saddr) {
+ case 0:
+ s->intreg_pending = val;
+ break;
+ case 1: // clear
+ s->intreg_enabled &= ~val;
+ break;
+ case 2: // set
+ s->intreg_enabled |= val;
+ break;
+ default:
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *intreg_mem_read[3] = {
+ intreg_mem_readl,
+ intreg_mem_readl,
+ intreg_mem_readl,
+};
+
+static CPUWriteMemoryFunc *intreg_mem_write[3] = {
+ intreg_mem_writel,
+ intreg_mem_writel,
+ intreg_mem_writel,
+};
+
+static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_INTR_G) >> 2;
+ switch (saddr) {
+ case 0:
+ return s->intregm_pending;
+ break;
+ case 1:
+ return s->intregm_enabled;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void intregm_mem_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_INTR_G) >> 2;
+ switch (saddr) {
+ case 0:
+ s->intregm_pending = val;
+ break;
+ case 1:
+ s->intregm_enabled = val;
+ break;
+ case 2: // clear
+ s->intregm_enabled &= ~val;
+ break;
+ case 3: // set
+ s->intregm_enabled |= val;
+ break;
+ default:
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *intregm_mem_read[3] = {
+ intregm_mem_readl,
+ intregm_mem_readl,
+ intregm_mem_readl,
+};
+
+static CPUWriteMemoryFunc *intregm_mem_write[3] = {
+ intregm_mem_writel,
+ intregm_mem_writel,
+ intregm_mem_writel,
+};
+
+static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_CLOCK) >> 2;
+ switch (saddr) {
+ default:
+ return s->timer_regs[saddr];
+ break;
+ }
+ return 0;
+}
+
+static void timer_mem_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_CLOCK) >> 2;
+ switch (saddr) {
+ default:
+ s->timer_regs[saddr] = val;
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *timer_mem_read[3] = {
+ timer_mem_readl,
+ timer_mem_readl,
+ timer_mem_readl,
+};
+
+static CPUWriteMemoryFunc *timer_mem_write[3] = {
+ timer_mem_writel,
+ timer_mem_writel,
+ timer_mem_writel,
+};
+
+static uint32_t timerm_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
+ switch (saddr) {
+ default:
+ return s->timerm_regs[saddr];
+ break;
+ }
+ return 0;
+}
+
+static void timerm_mem_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
+ switch (saddr) {
+ default:
+ s->timerm_regs[saddr] = val;
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *timerm_mem_read[3] = {
+ timerm_mem_readl,
+ timerm_mem_readl,
+ timerm_mem_readl,
+};
+
+static CPUWriteMemoryFunc *timerm_mem_write[3] = {
+ timerm_mem_writel,
+ timerm_mem_writel,
+ timerm_mem_writel,
+};
+
+void pic_info() {}
+void irq_info() {}
+
+static const unsigned int intr_to_mask[16] = {
+ 0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+void pic_set_irq(int irq, int level)
+{
+ if (irq < 16) {
+ unsigned int mask = intr_to_mask[irq];
+ ps->intreg_pending |= 1 << irq;
+ if (ps->intregm_enabled & mask) {
+ cpu_single_env->interrupt_index = irq;
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+ }
+ }
+}
+
+void sched_init()
+{
+ SCHEDState *s;
+
+ s = qemu_mallocz(sizeof(SCHEDState));
+ if (!s)
+ return;
+
+ intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read,
intreg_mem_write, s);
+ cpu_register_physical_memory(PHYS_JJ_INTR0, 3, intreg_io_memory);
+
+ intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read,
intregm_mem_write, s);
+ cpu_register_physical_memory(PHYS_JJ_INTR_G, 5, intregm_io_memory);
+
+ timer_io_memory = cpu_register_io_memory(0, timer_mem_read,
timer_mem_write, s);
+ cpu_register_physical_memory(PHYS_JJ_CLOCK, 2, timer_io_memory);
+
+ timerm_io_memory = cpu_register_io_memory(0, timerm_mem_read,
timerm_mem_write, s);
+ cpu_register_physical_memory(PHYS_JJ_CLOCK1, 2, timerm_io_memory);
+
+ sched_reset(s);
+ ps = s;
+}
+
diff -ruN qemu-0.6.0.orig/hw/sun4m.c qemu-0.6.0/hw/sun4m.c
--- qemu-0.6.0.orig/hw/sun4m.c 1970-01-01 01:00:00.000000000 +0100
+++ qemu-0.6.0/hw/sun4m.c 2004-09-12 22:10:12.000000000 +0200
@@ -0,0 +1,127 @@
+/*
+ * QEMU Sun4m 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"
+
+#define KERNEL_LOAD_ADDR 0x00004000
+#define MMU_CONTEXT_TBL 0x00003000
+#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
+#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
+#define ROMVEC_DATA (MMU_CONTEXT_TBL + 0x1800)
+
+/* TSC handling */
+
+uint64_t cpu_get_tsc()
+{
+ return qemu_get_clock(vm_clock);
+}
+
+void DMA_run() {}
+void SB16_run() {}
+void vga_invalidate_display() {}
+void vga_screen_dump(const char *filename) {}
+int serial_can_receive(SerialState *s) { return 0; }
+void serial_receive_byte(SerialState *s, int ch) {}
+void serial_receive_break(SerialState *s) {}
+
+int load_kernel(const char *filename, uint8_t *addr)
+{
+ int fd, size;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ /* 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;
+}
+
+/* SUN 4 hardware initialisation */
+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)
+{
+ int ret, linux_boot;
+
+ linux_boot = (kernel_filename != NULL);
+
+ /* allocate RAM */
+ cpu_register_physical_memory(0, ram_size, 0);
+ iommu_init();
+ sched_init();
+ tcx_init(ds);
+ lance_init(&nd_table[0], 6);
+
+#if 0
+ bios_size = get_image_size("prom");
+ ret = load_image("prom", phys_ram_base);
+ if (ret != bios_size) {
+ bios_error:
+ fprintf(stderr, "qemu: could not load prom '%s'\n", buf);
+ exit(1);
+ }
+#endif
+ if (linux_boot) {
+ ret = load_kernel(kernel_filename,
+ phys_ram_base + KERNEL_LOAD_ADDR);
+ if (ret < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ kernel_filename);
+ exit(1);
+ }
+ }
+ /* Setup a MMU entry for entire address space */
+ stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
+ stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
+#if 0
+ stl_raw(phys_ram_base + MMU_L1PTP + (0x50 << 2), (MMU_L2PTP >> 4) | 1);
// frame buffer at 50..
+#endif
+ stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1);
// ff.. == 00..
+ /* 3 = U:RWX S:RWX */
+ stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
+#if 0
+ stl_raw(phys_ram_base + MMU_L2PTP + 0x84, (PHYS_JJ_TCX_FB >> 4) \
+ | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
+ stl_raw(phys_ram_base + MMU_L2PTP + 0x88, (PHYS_JJ_TCX_FB >> 4) \
+ | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
+ stl_raw(phys_ram_base + MMU_L2PTP + 0x140, (PHYS_JJ_TCX_FB >> 4) \
+ | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
+ // "Empirical constant"
+ stl_raw(phys_ram_base + ROMVEC_DATA, 0x10010407);
+
+ // Version: V3 prom
+ stl_raw(phys_ram_base + ROMVEC_DATA + 4, 3);
+
+ stl_raw(phys_ram_base + ROMVEC_DATA + 0x1c, ROMVEC_DATA+0x400);
+ stl_raw(phys_ram_base + ROMVEC_DATA + 0x400, ROMVEC_DATA+0x404);
+ stl_raw(phys_ram_base + ROMVEC_DATA + 0x404, 0x81c3e008); // retl
+ stl_raw(phys_ram_base + ROMVEC_DATA + 0x408, 0x01000000); // nop
+#endif
+}
diff -ruN qemu-0.6.0.orig/hw/tcx.c qemu-0.6.0/hw/tcx.c
--- qemu-0.6.0.orig/hw/tcx.c 1970-01-01 01:00:00.000000000 +0100
+++ qemu-0.6.0/hw/tcx.c 2004-09-14 21:03:47.000000000 +0200
@@ -0,0 +1,176 @@
+/*
+ * QEMU Sun4m 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"
+
+#define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */
+#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */
+
+#define MAXX 1024
+#define MAXY 768
+#define XSZ (8*80)
+#define YSZ (24*11)
+#define XOFF (MAXX-XSZ)
+#define YOFF (MAXY-YSZ)
+
+#define DEBUG_VGA_MEM
+
+typedef struct TCXState {
+ uint8_t *vram_ptr;
+ unsigned long vram_offset;
+ unsigned int vram_size;
+ DisplayState *ds;
+} TCXState;
+
+static TCXState *ts;
+
+static int tcx_io_memory;
+
+void vga_update_display()
+{
+ dpy_update(ts->ds, 0, 0, XSZ, YSZ);
+}
+
+static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ TCXState *s = opaque;
+ uint32_t saddr;
+ unsigned int x, y;
+ char *sptr;
+
+ saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
+ y = saddr / MAXX;
+ x = saddr - y * MAXX;
+ if (x < MAXX && y < MAXY) {
+ sptr = s->ds->data;
+ if (sptr)
+ return sptr[y * s->ds->linesize + x*4];
+ }
+ return 0;
+}
+
+static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = tcx_mem_readb(opaque, addr) << 8;
+ v |= tcx_mem_readb(opaque, addr + 1);
+#else
+ v = tcx_mem_readb(opaque, addr);
+ v |= tcx_mem_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = tcx_mem_readb(opaque, addr) << 24;
+ v |= tcx_mem_readb(opaque, addr + 1) << 16;
+ v |= tcx_mem_readb(opaque, addr + 2) << 8;
+ v |= tcx_mem_readb(opaque, addr + 3);
+#else
+ v = tcx_mem_readb(opaque, addr);
+ v |= tcx_mem_readb(opaque, addr + 1) << 8;
+ v |= tcx_mem_readb(opaque, addr + 2) << 16;
+ v |= tcx_mem_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+/* called for accesses between 0xa0000 and 0xc0000 */
+static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t
val)
+{
+ TCXState *s = opaque;
+ uint32_t saddr;
+ unsigned int x, y;
+ char *sptr;
+
+ saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
+ y = saddr / MAXX;
+ x = saddr - y * MAXX;
+ if (x < MAXX && y < MAXY) {
+ sptr = s->ds->data;
+ if (sptr) {
+ sptr[y * s->ds->linesize + x*4] = val;
+ sptr[y * s->ds->linesize + x*4+1] = val;
+ sptr[y * s->ds->linesize + x*4+2] = val;
+ cpu_physical_memory_set_dirty(addr);
+ }
+ }
+}
+
+static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t
val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, val & 0xff);
+#else
+ tcx_mem_writeb(opaque, addr, val & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t
val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ tcx_mem_writeb(opaque, addr + 3, val & 0xff);
+#else
+ tcx_mem_writeb(opaque, addr, val & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+static CPUReadMemoryFunc *tcx_mem_read[3] = {
+ tcx_mem_readb,
+ tcx_mem_readw,
+ tcx_mem_readl,
+};
+
+static CPUWriteMemoryFunc *tcx_mem_write[3] = {
+ tcx_mem_writeb,
+ tcx_mem_writew,
+ tcx_mem_writel,
+};
+
+void tcx_init(DisplayState *ds)
+{
+ TCXState *s;
+
+ s = qemu_mallocz(sizeof(TCXState));
+ if (!s)
+ return;
+ s->ds = ds;
+ ts = s;
+ tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write,
s);
+ cpu_register_physical_memory(PHYS_JJ_TCX_FB, 0x100000,
+ tcx_io_memory);
+ dpy_resize(s->ds, XSZ, YSZ);
+}
+
_________________________________________________________________
STOP MORE SPAM with the new MSN 8 and get 2 months FREE*
http://join.msn.com/?page=features/junkmail
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] Patch: Sparc system support (2/3),
Blue Swirl <=