Commit 420557e8981347368427849ff89ecd3fe537dafa

Authored by bellard
1 parent 6d5e216d

full system SPARC emulation (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1085 c046a42c-6fe2-441c-8c8c-71466251a162
hw/iommu.c 0 → 100644
  1 +/*
  2 + * QEMU SPARC iommu emulation
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +/* debug iommu */
  27 +//#define DEBUG_IOMMU
  28 +
  29 +/* The IOMMU registers occupy three pages in IO space. */
  30 +struct iommu_regs {
  31 + /* First page */
  32 + volatile unsigned long control; /* IOMMU control */
  33 + volatile unsigned long base; /* Physical base of iopte page table */
  34 + volatile unsigned long _unused1[3];
  35 + volatile unsigned long tlbflush; /* write only */
  36 + volatile unsigned long pageflush; /* write only */
  37 + volatile unsigned long _unused2[1017];
  38 + /* Second page */
  39 + volatile unsigned long afsr; /* Async-fault status register */
  40 + volatile unsigned long afar; /* Async-fault physical address */
  41 + volatile unsigned long _unused3[2];
  42 + volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */
  43 + volatile unsigned long sbuscfg1;
  44 + volatile unsigned long sbuscfg2;
  45 + volatile unsigned long sbuscfg3;
  46 + volatile unsigned long mfsr; /* Memory-fault status register */
  47 + volatile unsigned long mfar; /* Memory-fault physical address */
  48 + volatile unsigned long _unused4[1014];
  49 + /* Third page */
  50 + volatile unsigned long mid; /* IOMMU module-id */
  51 +};
  52 +
  53 +#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
  54 +#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
  55 +#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
  56 +#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
  57 +#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
  58 +#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
  59 +#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
  60 +#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
  61 +#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
  62 +#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
  63 +#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
  64 +#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
  65 +
  66 +#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
  67 +#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */
  68 +#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */
  69 +#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */
  70 +#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
  71 +#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
  72 +#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */
  73 +#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
  74 +#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
  75 +#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
  76 +
  77 +#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
  78 +#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
  79 +#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
  80 +#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
  81 + produced by this device as pure
  82 + physical. */
  83 +
  84 +#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
  85 +#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
  86 +#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */
  87 +#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */
  88 +#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred
  89 + on the even word of the access, low bit
  90 + indicated odd word caused the parity error */
  91 +#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */
  92 +#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */
  93 +#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */
  94 +
  95 +#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
  96 +#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */
  97 +#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */
  98 +#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */
  99 +#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */
  100 +#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */
  101 +#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
  102 +
  103 +/* The format of an iopte in the page tables */
  104 +#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
  105 +#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
  106 +#define IOPTE_WRITE 0x00000004 /* Writeable */
  107 +#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
  108 +#define IOPTE_WAZ 0x00000001 /* Write as zeros */
  109 +
  110 +#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
  111 +#define PAGE_SHIFT 12
  112 +#define PAGE_SIZE (1 << PAGE_SHIFT)
  113 +#define PAGE_MASK (PAGE_SIZE - 1)
  114 +
  115 +typedef struct IOMMUState {
  116 + uint32_t regs[sizeof(struct iommu_regs)];
  117 +} IOMMUState;
  118 +
  119 +static IOMMUState *ps;
  120 +
  121 +static int iommu_io_memory;
  122 +
  123 +static void iommu_reset(IOMMUState *s)
  124 +{
  125 +}
  126 +
  127 +static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
  128 +{
  129 + IOMMUState *s = opaque;
  130 + uint32_t saddr;
  131 +
  132 + saddr = (addr - PHYS_JJ_IOMMU) >> 2;
  133 + switch (saddr) {
  134 + default:
  135 + return s->regs[saddr];
  136 + break;
  137 + }
  138 + return 0;
  139 +}
  140 +
  141 +static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  142 +{
  143 + IOMMUState *s = opaque;
  144 + uint32_t saddr;
  145 +
  146 + saddr = (addr - PHYS_JJ_IOMMU) >> 2;
  147 + switch (saddr) {
  148 + default:
  149 + s->regs[saddr] = val;
  150 + break;
  151 + }
  152 +}
  153 +
  154 +static CPUReadMemoryFunc *iommu_mem_read[3] = {
  155 + iommu_mem_readw,
  156 + iommu_mem_readw,
  157 + iommu_mem_readw,
  158 +};
  159 +
  160 +static CPUWriteMemoryFunc *iommu_mem_write[3] = {
  161 + iommu_mem_writew,
  162 + iommu_mem_writew,
  163 + iommu_mem_writew,
  164 +};
  165 +
  166 +uint32_t iommu_translate(uint32_t addr)
  167 +{
  168 + uint32_t *iopte = (void *)(ps->regs[1] << 4), pa, iostart;
  169 +
  170 + switch (ps->regs[0] & IOMMU_CTRL_RNGE) {
  171 + case IOMMU_RNGE_16MB:
  172 + iostart = 0xff000000;
  173 + break;
  174 + case IOMMU_RNGE_32MB:
  175 + iostart = 0xfe000000;
  176 + break;
  177 + case IOMMU_RNGE_64MB:
  178 + iostart = 0xfc000000;
  179 + break;
  180 + case IOMMU_RNGE_128MB:
  181 + iostart = 0xf8000000;
  182 + break;
  183 + case IOMMU_RNGE_256MB:
  184 + iostart = 0xf0000000;
  185 + break;
  186 + case IOMMU_RNGE_512MB:
  187 + iostart = 0xe0000000;
  188 + break;
  189 + case IOMMU_RNGE_1GB:
  190 + iostart = 0xc0000000;
  191 + break;
  192 + default:
  193 + case IOMMU_RNGE_2GB:
  194 + iostart = 0x80000000;
  195 + break;
  196 + }
  197 +
  198 + iopte += ((addr - iostart) >> PAGE_SHIFT);
  199 + cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
  200 + bswap32s(&pa);
  201 + pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
  202 + //return pa + PAGE_SIZE;
  203 + return pa + (addr & PAGE_MASK);
  204 +}
  205 +
  206 +void iommu_init()
  207 +{
  208 + IOMMUState *s;
  209 +
  210 + s = qemu_mallocz(sizeof(IOMMUState));
  211 + if (!s)
  212 + return;
  213 +
  214 + iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
  215 + cpu_register_physical_memory(PHYS_JJ_IOMMU, sizeof(struct iommu_regs),
  216 + iommu_io_memory);
  217 +
  218 + iommu_reset(s);
  219 + ps = s;
  220 +}
  221 +
... ...
hw/lance.c 0 → 100644
  1 +/*
  2 + * QEMU Lance emulation
  3 + *
  4 + * Copyright (c) 2003-2004 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +/* debug LANCE card */
  27 +#define DEBUG_LANCE
  28 +
  29 +#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
  30 +#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused SCSI */
  31 +#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */
  32 +
  33 +#ifndef LANCE_LOG_TX_BUFFERS
  34 +#define LANCE_LOG_TX_BUFFERS 4
  35 +#define LANCE_LOG_RX_BUFFERS 4
  36 +#endif
  37 +
  38 +#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
  39 +#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
  40 +
  41 +
  42 +#define LE_CSR0 0
  43 +#define LE_CSR1 1
  44 +#define LE_CSR2 2
  45 +#define LE_CSR3 3
  46 +#define LE_MAXREG (LE_CSR3 + 1)
  47 +
  48 +#define LE_RDP 0
  49 +#define LE_RAP 1
  50 +
  51 +#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */
  52 +
  53 +#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */
  54 +#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */
  55 +#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */
  56 +#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */
  57 +#define LE_C0_MERR 0x0800 /* ME: Memory error */
  58 +#define LE_C0_RINT 0x0400 /* Received interrupt */
  59 +#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */
  60 +#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */
  61 +#define LE_C0_INTR 0x0080 /* Interrupt or error */
  62 +#define LE_C0_INEA 0x0040 /* Interrupt enable */
  63 +#define LE_C0_RXON 0x0020 /* Receiver on */
  64 +#define LE_C0_TXON 0x0010 /* Transmitter on */
  65 +#define LE_C0_TDMD 0x0008 /* Transmitter demand */
  66 +#define LE_C0_STOP 0x0004 /* Stop the card */
  67 +#define LE_C0_STRT 0x0002 /* Start the card */
  68 +#define LE_C0_INIT 0x0001 /* Init the card */
  69 +
  70 +#define LE_C3_BSWP 0x4 /* SWAP */
  71 +#define LE_C3_ACON 0x2 /* ALE Control */
  72 +#define LE_C3_BCON 0x1 /* Byte control */
  73 +
  74 +/* Receive message descriptor 1 */
  75 +#define LE_R1_OWN 0x80 /* Who owns the entry */
  76 +#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */
  77 +#define LE_R1_FRA 0x20 /* FRA: Frame error */
  78 +#define LE_R1_OFL 0x10 /* OFL: Frame overflow */
  79 +#define LE_R1_CRC 0x08 /* CRC error */
  80 +#define LE_R1_BUF 0x04 /* BUF: Buffer error */
  81 +#define LE_R1_SOP 0x02 /* Start of packet */
  82 +#define LE_R1_EOP 0x01 /* End of packet */
  83 +#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */
  84 +
  85 +#define LE_T1_OWN 0x80 /* Lance owns the packet */
  86 +#define LE_T1_ERR 0x40 /* Error summary */
  87 +#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */
  88 +#define LE_T1_EONE 0x08 /* Error: one retry needed */
  89 +#define LE_T1_EDEF 0x04 /* Error: deferred */
  90 +#define LE_T1_SOP 0x02 /* Start of packet */
  91 +#define LE_T1_EOP 0x01 /* End of packet */
  92 +#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */
  93 +
  94 +#define LE_T3_BUF 0x8000 /* Buffer error */
  95 +#define LE_T3_UFL 0x4000 /* Error underflow */
  96 +#define LE_T3_LCOL 0x1000 /* Error late collision */
  97 +#define LE_T3_CLOS 0x0800 /* Error carrier loss */
  98 +#define LE_T3_RTY 0x0400 /* Error retry */
  99 +#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */
  100 +
  101 +#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
  102 +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
  103 +#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
  104 +
  105 +#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
  106 +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
  107 +#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
  108 +
  109 +#define PKT_BUF_SZ 1544
  110 +#define RX_BUFF_SIZE PKT_BUF_SZ
  111 +#define TX_BUFF_SIZE PKT_BUF_SZ
  112 +
  113 +struct lance_rx_desc {
  114 + unsigned short rmd0; /* low address of packet */
  115 + unsigned char rmd1_bits; /* descriptor bits */
  116 + unsigned char rmd1_hadr; /* high address of packet */
  117 + short length; /* This length is 2s complement (negative)!
  118 + * Buffer length
  119 + */
  120 + unsigned short mblength; /* This is the actual number of bytes received */
  121 +};
  122 +
  123 +struct lance_tx_desc {
  124 + unsigned short tmd0; /* low address of packet */
  125 + unsigned char tmd1_bits; /* descriptor bits */
  126 + unsigned char tmd1_hadr; /* high address of packet */
  127 + short length; /* Length is 2s complement (negative)! */
  128 + unsigned short misc;
  129 +};
  130 +
  131 +/* The LANCE initialization block, described in databook. */
  132 +/* On the Sparc, this block should be on a DMA region */
  133 +struct lance_init_block {
  134 + unsigned short mode; /* Pre-set mode (reg. 15) */
  135 + unsigned char phys_addr[6]; /* Physical ethernet address */
  136 + unsigned filter[2]; /* Multicast filter. */
  137 +
  138 + /* Receive and transmit ring base, along with extra bits. */
  139 + unsigned short rx_ptr; /* receive descriptor addr */
  140 + unsigned short rx_len; /* receive len and high addr */
  141 + unsigned short tx_ptr; /* transmit descriptor addr */
  142 + unsigned short tx_len; /* transmit len and high addr */
  143 +
  144 + /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
  145 + struct lance_rx_desc brx_ring[RX_RING_SIZE];
  146 + struct lance_tx_desc btx_ring[TX_RING_SIZE];
  147 +
  148 + char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
  149 + char pad[2]; /* align rx_buf for copy_and_sum(). */
  150 + char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
  151 +};
  152 +
  153 +#define LEDMA_REGS 4
  154 +#if 0
  155 +/* Structure to describe the current status of DMA registers on the Sparc */
  156 +struct sparc_dma_registers {
  157 + uint32_t cond_reg; /* DMA condition register */
  158 + uint32_t st_addr; /* Start address of this transfer */
  159 + uint32_t cnt; /* How many bytes to transfer */
  160 + uint32_t dma_test; /* DMA test register */
  161 +};
  162 +#endif
  163 +
  164 +typedef struct LEDMAState {
  165 + uint32_t regs[LEDMA_REGS];
  166 +} LEDMAState;
  167 +
  168 +typedef struct LANCEState {
  169 + NetDriverState *nd;
  170 + uint32_t leptr;
  171 + uint16_t addr;
  172 + uint16_t regs[LE_MAXREG];
  173 + uint8_t phys[6]; /* mac address */
  174 + int irq;
  175 + LEDMAState *ledma;
  176 +} LANCEState;
  177 +
  178 +static int lance_io_memory;
  179 +
  180 +static unsigned int rxptr, txptr;
  181 +
  182 +static void lance_send(void *opaque);
  183 +
  184 +static void lance_reset(LANCEState *s)
  185 +{
  186 + memcpy(s->phys, s->nd->macaddr, 6);
  187 + rxptr = 0;
  188 + txptr = 0;
  189 + s->regs[LE_CSR0] = LE_C0_STOP;
  190 +}
  191 +
  192 +static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
  193 +{
  194 + LANCEState *s = opaque;
  195 + uint32_t saddr;
  196 +
  197 + saddr = addr - PHYS_JJ_LE;
  198 + switch (saddr >> 1) {
  199 + case LE_RDP:
  200 + return s->regs[s->addr];
  201 + case LE_RAP:
  202 + return s->addr;
  203 + default:
  204 + break;
  205 + }
  206 + return 0;
  207 +}
  208 +
  209 +static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  210 +{
  211 + LANCEState *s = opaque;
  212 + uint32_t saddr;
  213 + uint16_t clear, reg;
  214 +
  215 + saddr = addr - PHYS_JJ_LE;
  216 + switch (saddr >> 1) {
  217 + case LE_RDP:
  218 + switch(s->addr) {
  219 + case LE_CSR0:
  220 + if (val & LE_C0_STOP) {
  221 + s->regs[LE_CSR0] = LE_C0_STOP;
  222 + break;
  223 + }
  224 +
  225 + reg = s->regs[LE_CSR0];
  226 +
  227 + // 1 = clear for some bits
  228 + reg &= ~(val & 0x7f00);
  229 +
  230 + // generated bits
  231 + reg &= ~(LE_C0_ERR | LE_C0_INTR);
  232 + if (reg & 0x7100)
  233 + reg |= LE_C0_ERR;
  234 + if (reg & 0x7f00)
  235 + reg |= LE_C0_INTR;
  236 +
  237 + // direct bit
  238 + reg &= ~LE_C0_INEA;
  239 + reg |= val & LE_C0_INEA;
  240 +
  241 + // exclusive bits
  242 + if (val & LE_C0_INIT) {
  243 + reg |= LE_C0_IDON | LE_C0_INIT;
  244 + reg &= ~LE_C0_STOP;
  245 + }
  246 + else if (val & LE_C0_STRT) {
  247 + reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
  248 + reg &= ~LE_C0_STOP;
  249 + }
  250 +
  251 + s->regs[LE_CSR0] = reg;
  252 +
  253 + // trigger bits
  254 + //if (val & LE_C0_TDMD)
  255 +
  256 + if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
  257 + pic_set_irq(s->irq, 1);
  258 + break;
  259 + case LE_CSR1:
  260 + s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
  261 + s->regs[s->addr] = val;
  262 + break;
  263 + case LE_CSR2:
  264 + s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
  265 + s->regs[s->addr] = val;
  266 + break;
  267 + case LE_CSR3:
  268 + s->regs[s->addr] = val;
  269 + break;
  270 + }
  271 + break;
  272 + case LE_RAP:
  273 + if (val < LE_MAXREG)
  274 + s->addr = val;
  275 + break;
  276 + default:
  277 + break;
  278 + }
  279 + lance_send(s);
  280 +}
  281 +
  282 +static CPUReadMemoryFunc *lance_mem_read[3] = {
  283 + lance_mem_readw,
  284 + lance_mem_readw,
  285 + lance_mem_readw,
  286 +};
  287 +
  288 +static CPUWriteMemoryFunc *lance_mem_write[3] = {
  289 + lance_mem_writew,
  290 + lance_mem_writew,
  291 + lance_mem_writew,
  292 +};
  293 +
  294 +
  295 +/* return the max buffer size if the LANCE can receive more data */
  296 +static int lance_can_receive(void *opaque)
  297 +{
  298 + LANCEState *s = opaque;
  299 + void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
  300 + struct lance_init_block *ib;
  301 + int i;
  302 + uint16_t temp;
  303 +
  304 + if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
  305 + return 0;
  306 +
  307 + ib = (void *) iommu_translate(dmaptr);
  308 +
  309 + for (i = 0; i < RX_RING_SIZE; i++) {
  310 + cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
  311 + temp &= 0xff;
  312 + if (temp == (LE_R1_OWN)) {
  313 +#ifdef DEBUG_LANCE
  314 + fprintf(stderr, "lance: can receive %d\n", RX_BUFF_SIZE);
  315 +#endif
  316 + return RX_BUFF_SIZE;
  317 + }
  318 + }
  319 +#ifdef DEBUG_LANCE
  320 + fprintf(stderr, "lance: cannot receive\n");
  321 +#endif
  322 + return 0;
  323 +}
  324 +
  325 +#define MIN_BUF_SIZE 60
  326 +
  327 +static void lance_receive(void *opaque, const uint8_t *buf, int size)
  328 +{
  329 + LANCEState *s = opaque;
  330 + void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
  331 + struct lance_init_block *ib;
  332 + unsigned int i, old_rxptr, j;
  333 + uint16_t temp;
  334 +
  335 + if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
  336 + return;
  337 +
  338 + ib = (void *) iommu_translate(dmaptr);
  339 +
  340 + old_rxptr = rxptr;
  341 + for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
  342 + cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
  343 + if (temp == (LE_R1_OWN)) {
  344 + rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
  345 + temp = size;
  346 + bswap16s(&temp);
  347 + cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2);
  348 +#if 0
  349 + cpu_physical_memory_write(&ib->rx_buf[i], buf, size);
  350 +#else
  351 + for (j = 0; j < size; j++) {
  352 + cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
  353 + }
  354 +#endif
  355 + temp = LE_R1_POK;
  356 + cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
  357 + s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
  358 + if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
  359 + pic_set_irq(s->irq, 1);
  360 +#ifdef DEBUG_LANCE
  361 + fprintf(stderr, "lance: got packet, len %d\n", size);
  362 +#endif
  363 + return;
  364 + }
  365 + }
  366 +}
  367 +
  368 +static void lance_send(void *opaque)
  369 +{
  370 + LANCEState *s = opaque;
  371 + void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
  372 + struct lance_init_block *ib;
  373 + unsigned int i, old_txptr, j;
  374 + uint16_t temp;
  375 + char pkt_buf[PKT_BUF_SZ];
  376 +
  377 + if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
  378 + return;
  379 +
  380 + ib = (void *) iommu_translate(dmaptr);
  381 +
  382 + old_txptr = txptr;
  383 + for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
  384 + cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
  385 + if (temp == (LE_T1_POK|LE_T1_OWN)) {
  386 + cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2);
  387 + bswap16s(&temp);
  388 + temp = (~temp) + 1;
  389 +#if 0
  390 + cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp);
  391 +#else
  392 + for (j = 0; j < temp; j++) {
  393 + cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
  394 + }
  395 +#endif
  396 +
  397 +#ifdef DEBUG_LANCE
  398 + fprintf(stderr, "lance: sending packet, len %d\n", temp);
  399 +#endif
  400 + qemu_send_packet(s->nd, pkt_buf, temp);
  401 + temp = LE_T1_POK;
  402 + cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
  403 + txptr = (txptr + 1) & TX_RING_MOD_MASK;
  404 + s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
  405 + }
  406 + }
  407 +}
  408 +
  409 +static int ledma_io_memory;
  410 +
  411 +static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
  412 +{
  413 + LEDMAState *s = opaque;
  414 + uint32_t saddr;
  415 +
  416 + saddr = (addr - PHYS_JJ_LEDMA) >> 2;
  417 + if (saddr < LEDMA_REGS)
  418 + return s->regs[saddr];
  419 + else
  420 + return 0;
  421 +}
  422 +
  423 +static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  424 +{
  425 + LEDMAState *s = opaque;
  426 + uint32_t saddr;
  427 +
  428 + saddr = (addr - PHYS_JJ_LEDMA) >> 2;
  429 + if (saddr < LEDMA_REGS)
  430 + s->regs[saddr] = val;
  431 +}
  432 +
  433 +static CPUReadMemoryFunc *ledma_mem_read[3] = {
  434 + ledma_mem_readl,
  435 + ledma_mem_readl,
  436 + ledma_mem_readl,
  437 +};
  438 +
  439 +static CPUWriteMemoryFunc *ledma_mem_write[3] = {
  440 + ledma_mem_writel,
  441 + ledma_mem_writel,
  442 + ledma_mem_writel,
  443 +};
  444 +
  445 +void lance_init(NetDriverState *nd, int irq)
  446 +{
  447 + LANCEState *s;
  448 + LEDMAState *led;
  449 +
  450 + s = qemu_mallocz(sizeof(LANCEState));
  451 + if (!s)
  452 + return;
  453 +
  454 + lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
  455 + cpu_register_physical_memory(PHYS_JJ_LE, 8,
  456 + lance_io_memory);
  457 + led = qemu_mallocz(sizeof(LEDMAState));
  458 + if (!led)
  459 + return;
  460 +
  461 + ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
  462 + cpu_register_physical_memory(PHYS_JJ_LEDMA, 16,
  463 + ledma_io_memory);
  464 +
  465 + s->nd = nd;
  466 + s->ledma = led;
  467 + s->irq = irq;
  468 +
  469 + lance_reset(s);
  470 + qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
  471 +}
  472 +
... ...
hw/m48t08.c 0 → 100644
  1 +/*
  2 + * QEMU M48T08 NVRAM emulation for Sparc platform
  3 + *
  4 + * Copyright (c) 2003-2004 Jocelyn Mayer
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +#include "m48t08.h"
  26 +
  27 +//#define DEBUG_NVRAM
  28 +
  29 +#if defined(DEBUG_NVRAM)
  30 +#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
  31 +#else
  32 +#define NVRAM_PRINTF(fmt, args...) do { } while (0)
  33 +#endif
  34 +
  35 +#define NVRAM_MAX_MEM 0xfff0
  36 +
  37 +struct m48t08_t {
  38 + /* Hardware parameters */
  39 + int mem_index;
  40 + uint32_t mem_base;
  41 + uint16_t size;
  42 + /* RTC management */
  43 + time_t time_offset;
  44 + time_t stop_time;
  45 + /* NVRAM storage */
  46 + uint8_t lock;
  47 + uint16_t addr;
  48 + uint8_t *buffer;
  49 +};
  50 +
  51 +/* Fake timer functions */
  52 +/* Generic helpers for BCD */
  53 +static inline uint8_t toBCD (uint8_t value)
  54 +{
  55 + return (((value / 10) % 10) << 4) | (value % 10);
  56 +}
  57 +
  58 +static inline uint8_t fromBCD (uint8_t BCD)
  59 +{
  60 + return ((BCD >> 4) * 10) + (BCD & 0x0F);
  61 +}
  62 +
  63 +/* RTC management helpers */
  64 +static void get_time (m48t08_t *NVRAM, struct tm *tm)
  65 +{
  66 + time_t t;
  67 +
  68 + t = time(NULL) + NVRAM->time_offset;
  69 +#ifdef _WIN32
  70 + memcpy(tm,localtime(&t),sizeof(*tm));
  71 +#else
  72 + localtime_r (&t, tm) ;
  73 +#endif
  74 +}
  75 +
  76 +static void set_time (m48t08_t *NVRAM, struct tm *tm)
  77 +{
  78 + time_t now, new_time;
  79 +
  80 + new_time = mktime(tm);
  81 + now = time(NULL);
  82 + NVRAM->time_offset = new_time - now;
  83 +}
  84 +
  85 +/* Direct access to NVRAM */
  86 +void m48t08_write (m48t08_t *NVRAM, uint32_t val)
  87 +{
  88 + struct tm tm;
  89 + int tmp;
  90 +
  91 + if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000)
  92 + NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
  93 + switch (NVRAM->addr) {
  94 + case 0x1FF8:
  95 + /* control */
  96 + NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
  97 + break;
  98 + case 0x1FF9:
  99 + /* seconds (BCD) */
  100 + tmp = fromBCD(val & 0x7F);
  101 + if (tmp >= 0 && tmp <= 59) {
  102 + get_time(NVRAM, &tm);
  103 + tm.tm_sec = tmp;
  104 + set_time(NVRAM, &tm);
  105 + }
  106 + if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
  107 + if (val & 0x80) {
  108 + NVRAM->stop_time = time(NULL);
  109 + } else {
  110 + NVRAM->time_offset += NVRAM->stop_time - time(NULL);
  111 + NVRAM->stop_time = 0;
  112 + }
  113 + }
  114 + NVRAM->buffer[0x1FF9] = val & 0x80;
  115 + break;
  116 + case 0x1FFA:
  117 + /* minutes (BCD) */
  118 + tmp = fromBCD(val & 0x7F);
  119 + if (tmp >= 0 && tmp <= 59) {
  120 + get_time(NVRAM, &tm);
  121 + tm.tm_min = tmp;
  122 + set_time(NVRAM, &tm);
  123 + }
  124 + break;
  125 + case 0x1FFB:
  126 + /* hours (BCD) */
  127 + tmp = fromBCD(val & 0x3F);
  128 + if (tmp >= 0 && tmp <= 23) {
  129 + get_time(NVRAM, &tm);
  130 + tm.tm_hour = tmp;
  131 + set_time(NVRAM, &tm);
  132 + }
  133 + break;
  134 + case 0x1FFC:
  135 + /* day of the week / century */
  136 + tmp = fromBCD(val & 0x07);
  137 + get_time(NVRAM, &tm);
  138 + tm.tm_wday = tmp;
  139 + set_time(NVRAM, &tm);
  140 + NVRAM->buffer[0x1FFC] = val & 0x40;
  141 + break;
  142 + case 0x1FFD:
  143 + /* date */
  144 + tmp = fromBCD(val & 0x1F);
  145 + if (tmp != 0) {
  146 + get_time(NVRAM, &tm);
  147 + tm.tm_mday = tmp;
  148 + set_time(NVRAM, &tm);
  149 + }
  150 + break;
  151 + case 0x1FFE:
  152 + /* month */
  153 + tmp = fromBCD(val & 0x1F);
  154 + if (tmp >= 1 && tmp <= 12) {
  155 + get_time(NVRAM, &tm);
  156 + tm.tm_mon = tmp - 1;
  157 + set_time(NVRAM, &tm);
  158 + }
  159 + break;
  160 + case 0x1FFF:
  161 + /* year */
  162 + tmp = fromBCD(val);
  163 + if (tmp >= 0 && tmp <= 99) {
  164 + get_time(NVRAM, &tm);
  165 + tm.tm_year = fromBCD(val);
  166 + set_time(NVRAM, &tm);
  167 + }
  168 + break;
  169 + default:
  170 + /* Check lock registers state */
  171 + if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
  172 + break;
  173 + if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
  174 + break;
  175 + if (NVRAM->addr < NVRAM_MAX_MEM ||
  176 + (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
  177 + NVRAM->buffer[NVRAM->addr] = val & 0xFF;
  178 + }
  179 + break;
  180 + }
  181 +}
  182 +
  183 +uint32_t m48t08_read (m48t08_t *NVRAM)
  184 +{
  185 + struct tm tm;
  186 + uint32_t retval = 0xFF;
  187 +
  188 + switch (NVRAM->addr) {
  189 + case 0x1FF8:
  190 + /* control */
  191 + goto do_read;
  192 + case 0x1FF9:
  193 + /* seconds (BCD) */
  194 + get_time(NVRAM, &tm);
  195 + retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
  196 + break;
  197 + case 0x1FFA:
  198 + /* minutes (BCD) */
  199 + get_time(NVRAM, &tm);
  200 + retval = toBCD(tm.tm_min);
  201 + break;
  202 + case 0x1FFB:
  203 + /* hours (BCD) */
  204 + get_time(NVRAM, &tm);
  205 + retval = toBCD(tm.tm_hour);
  206 + break;
  207 + case 0x1FFC:
  208 + /* day of the week / century */
  209 + get_time(NVRAM, &tm);
  210 + retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
  211 + break;
  212 + case 0x1FFD:
  213 + /* date */
  214 + get_time(NVRAM, &tm);
  215 + retval = toBCD(tm.tm_mday);
  216 + break;
  217 + case 0x1FFE:
  218 + /* month */
  219 + get_time(NVRAM, &tm);
  220 + retval = toBCD(tm.tm_mon + 1);
  221 + break;
  222 + case 0x1FFF:
  223 + /* year */
  224 + get_time(NVRAM, &tm);
  225 + retval = toBCD(tm.tm_year);
  226 + break;
  227 + default:
  228 + /* Check lock registers state */
  229 + if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
  230 + break;
  231 + if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
  232 + break;
  233 + if (NVRAM->addr < NVRAM_MAX_MEM ||
  234 + (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
  235 + do_read:
  236 + retval = NVRAM->buffer[NVRAM->addr];
  237 + }
  238 + break;
  239 + }
  240 + if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000)
  241 + NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
  242 +
  243 + return retval;
  244 +}
  245 +
  246 +void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr)
  247 +{
  248 + NVRAM->addr = addr;
  249 +}
  250 +
  251 +void m48t08_toggle_lock (m48t08_t *NVRAM, int lock)
  252 +{
  253 + NVRAM->lock ^= 1 << lock;
  254 +}
  255 +
  256 +static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
  257 +{
  258 + m48t08_t *NVRAM = opaque;
  259 +
  260 + addr -= NVRAM->mem_base;
  261 + if (addr < NVRAM_MAX_MEM)
  262 + NVRAM->buffer[addr] = value;
  263 +}
  264 +
  265 +static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
  266 +{
  267 + m48t08_t *NVRAM = opaque;
  268 +
  269 + addr -= NVRAM->mem_base;
  270 + if (addr < NVRAM_MAX_MEM) {
  271 + NVRAM->buffer[addr] = value >> 8;
  272 + NVRAM->buffer[addr + 1] = value;
  273 + }
  274 +}
  275 +
  276 +static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
  277 +{
  278 + m48t08_t *NVRAM = opaque;
  279 +
  280 + addr -= NVRAM->mem_base;
  281 + if (addr < NVRAM_MAX_MEM) {
  282 + NVRAM->buffer[addr] = value >> 24;
  283 + NVRAM->buffer[addr + 1] = value >> 16;
  284 + NVRAM->buffer[addr + 2] = value >> 8;
  285 + NVRAM->buffer[addr + 3] = value;
  286 + }
  287 +}
  288 +
  289 +static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
  290 +{
  291 + m48t08_t *NVRAM = opaque;
  292 + uint32_t retval = 0;
  293 +
  294 + addr -= NVRAM->mem_base;
  295 + if (addr < NVRAM_MAX_MEM)
  296 + retval = NVRAM->buffer[addr];
  297 +
  298 + return retval;
  299 +}
  300 +
  301 +static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
  302 +{
  303 + m48t08_t *NVRAM = opaque;
  304 + uint32_t retval = 0;
  305 +
  306 + addr -= NVRAM->mem_base;
  307 + if (addr < NVRAM_MAX_MEM) {
  308 + retval = NVRAM->buffer[addr] << 8;
  309 + retval |= NVRAM->buffer[addr + 1];
  310 + }
  311 +
  312 + return retval;
  313 +}
  314 +
  315 +static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
  316 +{
  317 + m48t08_t *NVRAM = opaque;
  318 + uint32_t retval = 0;
  319 +
  320 + addr -= NVRAM->mem_base;
  321 + if (addr < NVRAM_MAX_MEM) {
  322 + retval = NVRAM->buffer[addr] << 24;
  323 + retval |= NVRAM->buffer[addr + 1] << 16;
  324 + retval |= NVRAM->buffer[addr + 2] << 8;
  325 + retval |= NVRAM->buffer[addr + 3];
  326 + }
  327 +
  328 + return retval;
  329 +}
  330 +
  331 +static CPUWriteMemoryFunc *nvram_write[] = {
  332 + &nvram_writeb,
  333 + &nvram_writew,
  334 + &nvram_writel,
  335 +};
  336 +
  337 +static CPUReadMemoryFunc *nvram_read[] = {
  338 + &nvram_readb,
  339 + &nvram_readw,
  340 + &nvram_readl,
  341 +};
  342 +
  343 +/* Initialisation routine */
  344 +m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
  345 +{
  346 + m48t08_t *s;
  347 + int i;
  348 + unsigned char tmp = 0;
  349 +
  350 + s = qemu_mallocz(sizeof(m48t08_t));
  351 + if (!s)
  352 + return NULL;
  353 + s->buffer = qemu_mallocz(size);
  354 + if (!s->buffer) {
  355 + qemu_free(s);
  356 + return NULL;
  357 + }
  358 + s->size = size;
  359 + s->mem_base = mem_base;
  360 + s->addr = 0;
  361 + if (mem_base != 0) {
  362 + s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
  363 + cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
  364 + }
  365 + s->lock = 0;
  366 +
  367 + i = 0x1fd8;
  368 + s->buffer[i++] = 0x01;
  369 + s->buffer[i++] = 0x80; /* Sun4m OBP */
  370 + /* XXX: Ethernet address, etc */
  371 +
  372 + /* Calculate checksum */
  373 + for (i = 0x1fd8; i < 0x1fe7; i++) {
  374 + tmp ^= s->buffer[i];
  375 + }
  376 + s->buffer[0x1fe7] = tmp;
  377 + return s;
  378 +}
  379 +
  380 +#if 0
  381 +struct idprom
  382 +{
  383 + unsigned char id_format; /* Format identifier (always 0x01) */
  384 + unsigned char id_machtype; /* Machine type */
  385 + unsigned char id_ethaddr[6]; /* Hardware ethernet address */
  386 + long id_date; /* Date of manufacture */
  387 + unsigned int id_sernum:24; /* Unique serial number */
  388 + unsigned char id_cksum; /* Checksum - xor of the data bytes */
  389 + unsigned char reserved[16];
  390 +};
  391 +#endif
... ...
hw/m48t08.h 0 → 100644
  1 +#if !defined (__M48T08_H__)
  2 +#define __M48T08_H__
  3 +
  4 +typedef struct m48t08_t m48t08_t;
  5 +
  6 +void m48t08_write (m48t08_t *NVRAM, uint32_t val);
  7 +uint32_t m48t08_read (m48t08_t *NVRAM);
  8 +void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr);
  9 +void m48t08_toggle_lock (m48t08_t *NVRAM, int lock);
  10 +m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size);
  11 +
  12 +#endif /* !defined (__M48T08_H__) */
... ...
hw/magic-load.c 0 → 100644
  1 +/* This is the Linux kernel elf-loading code, ported into user space */
  2 +#include "vl.h"
  3 +#include "disas.h"
  4 +
  5 +/* XXX: this code is not used as it is under the GPL license. Please
  6 + remove or recode it */
  7 +//#define USE_ELF_LOADER
  8 +
  9 +#ifdef USE_ELF_LOADER
  10 +/* should probably go in elf.h */
  11 +#ifndef ELIBBAD
  12 +#define ELIBBAD 80
  13 +#endif
  14 +
  15 +
  16 +#define ELF_START_MMAP 0x80000000
  17 +
  18 +#define elf_check_arch(x) ( (x) == EM_SPARC )
  19 +
  20 +#define ELF_CLASS ELFCLASS32
  21 +#define ELF_DATA ELFDATA2MSB
  22 +#define ELF_ARCH EM_SPARC
  23 +
  24 +#include "elf.h"
  25 +
  26 +/*
  27 + * This structure is used to hold the arguments that are
  28 + * used when loading binaries.
  29 + */
  30 +struct linux_binprm {
  31 + char buf[128];
  32 + int fd;
  33 +};
  34 +
  35 +#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
  36 +#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
  37 +#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
  38 +
  39 +#ifdef BSWAP_NEEDED
  40 +static void bswap_ehdr(Elf32_Ehdr *ehdr)
  41 +{
  42 + bswap16s(&ehdr->e_type); /* Object file type */
  43 + bswap16s(&ehdr->e_machine); /* Architecture */
  44 + bswap32s(&ehdr->e_version); /* Object file version */
  45 + bswap32s(&ehdr->e_entry); /* Entry point virtual address */
  46 + bswap32s(&ehdr->e_phoff); /* Program header table file offset */
  47 + bswap32s(&ehdr->e_shoff); /* Section header table file offset */
  48 + bswap32s(&ehdr->e_flags); /* Processor-specific flags */
  49 + bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
  50 + bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
  51 + bswap16s(&ehdr->e_phnum); /* Program header table entry count */
  52 + bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
  53 + bswap16s(&ehdr->e_shnum); /* Section header table entry count */
  54 + bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
  55 +}
  56 +
  57 +static void bswap_phdr(Elf32_Phdr *phdr)
  58 +{
  59 + bswap32s(&phdr->p_type); /* Segment type */
  60 + bswap32s(&phdr->p_offset); /* Segment file offset */
  61 + bswap32s(&phdr->p_vaddr); /* Segment virtual address */
  62 + bswap32s(&phdr->p_paddr); /* Segment physical address */
  63 + bswap32s(&phdr->p_filesz); /* Segment size in file */
  64 + bswap32s(&phdr->p_memsz); /* Segment size in memory */
  65 + bswap32s(&phdr->p_flags); /* Segment flags */
  66 + bswap32s(&phdr->p_align); /* Segment alignment */
  67 +}
  68 +
  69 +static void bswap_shdr(Elf32_Shdr *shdr)
  70 +{
  71 + bswap32s(&shdr->sh_name);
  72 + bswap32s(&shdr->sh_type);
  73 + bswap32s(&shdr->sh_flags);
  74 + bswap32s(&shdr->sh_addr);
  75 + bswap32s(&shdr->sh_offset);
  76 + bswap32s(&shdr->sh_size);
  77 + bswap32s(&shdr->sh_link);
  78 + bswap32s(&shdr->sh_info);
  79 + bswap32s(&shdr->sh_addralign);
  80 + bswap32s(&shdr->sh_entsize);
  81 +}
  82 +
  83 +static void bswap_sym(Elf32_Sym *sym)
  84 +{
  85 + bswap32s(&sym->st_name);
  86 + bswap32s(&sym->st_value);
  87 + bswap32s(&sym->st_size);
  88 + bswap16s(&sym->st_shndx);
  89 +}
  90 +#endif
  91 +
  92 +static int prepare_binprm(struct linux_binprm *bprm)
  93 +{
  94 + int retval;
  95 +
  96 + memset(bprm->buf, 0, sizeof(bprm->buf));
  97 + retval = lseek(bprm->fd, 0L, SEEK_SET);
  98 + if(retval >= 0) {
  99 + retval = read(bprm->fd, bprm->buf, 128);
  100 + }
  101 + if(retval < 0) {
  102 + perror("prepare_binprm");
  103 + exit(-1);
  104 + /* return(-errno); */
  105 + }
  106 + else {
  107 + return(retval);
  108 + }
  109 +}
  110 +
  111 +/* Best attempt to load symbols from this ELF object. */
  112 +static void load_symbols(struct elfhdr *hdr, int fd)
  113 +{
  114 + unsigned int i;
  115 + struct elf_shdr sechdr, symtab, strtab;
  116 + char *strings;
  117 +
  118 + lseek(fd, hdr->e_shoff, SEEK_SET);
  119 + for (i = 0; i < hdr->e_shnum; i++) {
  120 + if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
  121 + return;
  122 +#ifdef BSWAP_NEEDED
  123 + bswap_shdr(&sechdr);
  124 +#endif
  125 + if (sechdr.sh_type == SHT_SYMTAB) {
  126 + symtab = sechdr;
  127 + lseek(fd, hdr->e_shoff
  128 + + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
  129 + if (read(fd, &strtab, sizeof(strtab))
  130 + != sizeof(strtab))
  131 + return;
  132 +#ifdef BSWAP_NEEDED
  133 + bswap_shdr(&strtab);
  134 +#endif
  135 + goto found;
  136 + }
  137 + }
  138 + return; /* Shouldn't happen... */
  139 +
  140 + found:
  141 + /* Now know where the strtab and symtab are. Snarf them. */
  142 + disas_symtab = qemu_malloc(symtab.sh_size);
  143 + disas_strtab = strings = qemu_malloc(strtab.sh_size);
  144 + if (!disas_symtab || !disas_strtab)
  145 + return;
  146 +
  147 + lseek(fd, symtab.sh_offset, SEEK_SET);
  148 + if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size)
  149 + return;
  150 +
  151 +#ifdef BSWAP_NEEDED
  152 + for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++)
  153 + bswap_sym(disas_symtab + sizeof(struct elf_sym)*i);
  154 +#endif
  155 +
  156 + lseek(fd, strtab.sh_offset, SEEK_SET);
  157 + if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
  158 + return;
  159 + disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
  160 +}
  161 +
  162 +static int load_elf_binary(struct linux_binprm * bprm, uint8_t *addr)
  163 +{
  164 + struct elfhdr elf_ex;
  165 + unsigned long startaddr = addr;
  166 + int i;
  167 + struct elf_phdr * elf_ppnt;
  168 + struct elf_phdr *elf_phdata;
  169 + int retval;
  170 +
  171 + elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
  172 +#ifdef BSWAP_NEEDED
  173 + bswap_ehdr(&elf_ex);
  174 +#endif
  175 +
  176 + if (elf_ex.e_ident[0] != 0x7f ||
  177 + strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
  178 + return -ENOEXEC;
  179 + }
  180 +
  181 + /* First of all, some simple consistency checks */
  182 + if (! elf_check_arch(elf_ex.e_machine)) {
  183 + return -ENOEXEC;
  184 + }
  185 +
  186 + /* Now read in all of the header information */
  187 + elf_phdata = (struct elf_phdr *)qemu_malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
  188 + if (elf_phdata == NULL) {
  189 + return -ENOMEM;
  190 + }
  191 +
  192 + retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
  193 + if(retval > 0) {
  194 + retval = read(bprm->fd, (char *) elf_phdata,
  195 + elf_ex.e_phentsize * elf_ex.e_phnum);
  196 + }
  197 +
  198 + if (retval < 0) {
  199 + perror("load_elf_binary");
  200 + exit(-1);
  201 + qemu_free (elf_phdata);
  202 + return -errno;
  203 + }
  204 +
  205 +#ifdef BSWAP_NEEDED
  206 + elf_ppnt = elf_phdata;
  207 + for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
  208 + bswap_phdr(elf_ppnt);
  209 + }
  210 +#endif
  211 + elf_ppnt = elf_phdata;
  212 +
  213 + /* Now we do a little grungy work by mmaping the ELF image into
  214 + * the correct location in memory. At this point, we assume that
  215 + * the image should be loaded at fixed address, not at a variable
  216 + * address.
  217 + */
  218 +
  219 + for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
  220 + unsigned long error, offset, len;
  221 +
  222 + if (elf_ppnt->p_type != PT_LOAD)
  223 + continue;
  224 +#if 0
  225 + error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
  226 + elf_prot,
  227 + (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
  228 + bprm->fd,
  229 + (elf_ppnt->p_offset -
  230 + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
  231 +#endif
  232 + //offset = elf_ppnt->p_offset - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr);
  233 + offset = 0x4000;
  234 + lseek(bprm->fd, offset, SEEK_SET);
  235 + len = elf_ppnt->p_filesz + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr);
  236 + error = read(bprm->fd, addr, len);
  237 +
  238 + if (error == -1) {
  239 + perror("mmap");
  240 + exit(-1);
  241 + }
  242 + addr += len;
  243 + }
  244 +
  245 + qemu_free(elf_phdata);
  246 +
  247 + load_symbols(&elf_ex, bprm->fd);
  248 +
  249 + return addr-startaddr;
  250 +}
  251 +
  252 +int elf_exec(const char * filename, uint8_t *addr)
  253 +{
  254 + struct linux_binprm bprm;
  255 + int retval;
  256 +
  257 + retval = open(filename, O_RDONLY);
  258 + if (retval < 0)
  259 + return retval;
  260 + bprm.fd = retval;
  261 +
  262 + retval = prepare_binprm(&bprm);
  263 +
  264 + if(retval>=0) {
  265 + retval = load_elf_binary(&bprm, addr);
  266 + }
  267 + return retval;
  268 +}
  269 +#endif
  270 +
  271 +int load_kernel(const char *filename, uint8_t *addr)
  272 +{
  273 + int fd, size;
  274 +
  275 + fd = open(filename, O_RDONLY | O_BINARY);
  276 + if (fd < 0)
  277 + return -1;
  278 + /* load 32 bit code */
  279 + size = read(fd, addr, 16 * 1024 * 1024);
  280 + if (size < 0)
  281 + goto fail;
  282 + close(fd);
  283 + return size;
  284 + fail:
  285 + close(fd);
  286 + return -1;
  287 +}
  288 +
  289 +static char saved_kfn[1024];
  290 +static uint32_t saved_addr;
  291 +static int magic_state;
  292 +
  293 +static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
  294 +{
  295 + int ret;
  296 +
  297 + if (magic_state == 0) {
  298 +#ifdef USE_ELF_LOADER
  299 + ret = elf_exec(saved_kfn, saved_addr);
  300 +#else
  301 + ret = load_kernel(saved_kfn, (uint8_t *)saved_addr);
  302 +#endif
  303 + if (ret < 0) {
  304 + fprintf(stderr, "qemu: could not load kernel '%s'\n",
  305 + saved_kfn);
  306 + }
  307 + magic_state = 1; /* No more magic */
  308 + tb_flush();
  309 + }
  310 + return ret;
  311 +}
  312 +
  313 +static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  314 +{
  315 +}
  316 +
  317 +
  318 +static CPUReadMemoryFunc *magic_mem_read[3] = {
  319 + magic_mem_readl,
  320 + magic_mem_readl,
  321 + magic_mem_readl,
  322 +};
  323 +
  324 +static CPUWriteMemoryFunc *magic_mem_write[3] = {
  325 + magic_mem_writel,
  326 + magic_mem_writel,
  327 + magic_mem_writel,
  328 +};
  329 +
  330 +void magic_init(const char *kfn, int kloadaddr)
  331 +{
  332 + int magic_io_memory;
  333 +
  334 + strcpy(saved_kfn, kfn);
  335 + saved_addr = kloadaddr;
  336 + magic_state = 0;
  337 + magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, 0);
  338 + cpu_register_physical_memory(0x20000000, 4,
  339 + magic_io_memory);
  340 +}
  341 +
... ...
hw/sched.c 0 → 100644
  1 +/*
  2 + * QEMU interrupt controller & timer emulation
  3 + *
  4 + * Copyright (c) 2003-2004 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +#define PHYS_JJ_CLOCK 0x71D00000
  27 +#define PHYS_JJ_CLOCK1 0x71D10000
  28 +#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
  29 +#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
  30 +
  31 +/* These registers are used for sending/receiving irqs from/to
  32 + * different cpu's.
  33 + */
  34 +struct sun4m_intreg_percpu {
  35 + unsigned int tbt; /* Intrs pending for this cpu, by PIL. */
  36 + /* These next two registers are WRITE-ONLY and are only
  37 + * "on bit" sensitive, "off bits" written have NO affect.
  38 + */
  39 + unsigned int clear; /* Clear this cpus irqs here. */
  40 + unsigned int set; /* Set this cpus irqs here. */
  41 +};
  42 +/*
  43 + * djhr
  44 + * Actually the clear and set fields in this struct are misleading..
  45 + * according to the SLAVIO manual (and the same applies for the SEC)
  46 + * the clear field clears bits in the mask which will ENABLE that IRQ
  47 + * the set field sets bits in the mask to DISABLE the IRQ.
  48 + *
  49 + * Also the undirected_xx address in the SLAVIO is defined as
  50 + * RESERVED and write only..
  51 + *
  52 + * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
  53 + * sun4m machines, for MP the layout makes more sense.
  54 + */
  55 +struct sun4m_intreg_master {
  56 + unsigned int tbt; /* IRQ's that are pending, see sun4m masks. */
  57 + unsigned int irqs; /* Master IRQ bits. */
  58 +
  59 + /* Again, like the above, two these registers are WRITE-ONLY. */
  60 + unsigned int clear; /* Clear master IRQ's by setting bits here. */
  61 + unsigned int set; /* Set master IRQ's by setting bits here. */
  62 +
  63 + /* This register is both READ and WRITE. */
  64 + unsigned int undirected_target; /* Which cpu gets undirected irqs. */
  65 +};
  66 +/*
  67 + * Registers of hardware timer in sun4m.
  68 + */
  69 +struct sun4m_timer_percpu {
  70 + volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
  71 + volatile unsigned int l14_cur_count;
  72 +};
  73 +
  74 +struct sun4m_timer_global {
  75 + volatile unsigned int l10_timer_limit;
  76 + volatile unsigned int l10_cur_count;
  77 +};
  78 +
  79 +#define SUN4M_INT_ENABLE 0x80000000
  80 +#define SUN4M_INT_E14 0x00000080
  81 +#define SUN4M_INT_E10 0x00080000
  82 +
  83 +#define SUN4M_HARD_INT(x) (0x000000001 << (x))
  84 +#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
  85 +
  86 +#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
  87 +#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
  88 +#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */
  89 +#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */
  90 +#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */
  91 +#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */
  92 +#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */
  93 +#define SUN4M_INT_REALTIME 0x00080000 /* system timer */
  94 +#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */
  95 +#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */
  96 +#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */
  97 +#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */
  98 +#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */
  99 +
  100 +#define SUN4M_INT_SBUS(x) (1 << (x+7))
  101 +#define SUN4M_INT_VME(x) (1 << (x))
  102 +
  103 +typedef struct SCHEDState {
  104 + uint32_t intreg_pending;
  105 + uint32_t intreg_enabled;
  106 + uint32_t intregm_pending;
  107 + uint32_t intregm_enabled;
  108 + uint32_t timer_regs[2];
  109 + uint32_t timerm_regs[2];
  110 +} SCHEDState;
  111 +
  112 +static SCHEDState *ps;
  113 +
  114 +static int intreg_io_memory, intregm_io_memory,
  115 + timer_io_memory, timerm_io_memory;
  116 +
  117 +static void sched_reset(SCHEDState *s)
  118 +{
  119 +}
  120 +
  121 +static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
  122 +{
  123 + SCHEDState *s = opaque;
  124 + uint32_t saddr;
  125 +
  126 + saddr = (addr - PHYS_JJ_INTR0) >> 2;
  127 + switch (saddr) {
  128 + case 0:
  129 + return s->intreg_pending;
  130 + break;
  131 + default:
  132 + break;
  133 + }
  134 + return 0;
  135 +}
  136 +
  137 +static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  138 +{
  139 + SCHEDState *s = opaque;
  140 + uint32_t saddr;
  141 +
  142 + saddr = (addr - PHYS_JJ_INTR0) >> 2;
  143 + switch (saddr) {
  144 + case 0:
  145 + s->intreg_pending = val;
  146 + break;
  147 + case 1: // clear
  148 + s->intreg_enabled &= ~val;
  149 + break;
  150 + case 2: // set
  151 + s->intreg_enabled |= val;
  152 + break;
  153 + default:
  154 + break;
  155 + }
  156 +}
  157 +
  158 +static CPUReadMemoryFunc *intreg_mem_read[3] = {
  159 + intreg_mem_readl,
  160 + intreg_mem_readl,
  161 + intreg_mem_readl,
  162 +};
  163 +
  164 +static CPUWriteMemoryFunc *intreg_mem_write[3] = {
  165 + intreg_mem_writel,
  166 + intreg_mem_writel,
  167 + intreg_mem_writel,
  168 +};
  169 +
  170 +static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
  171 +{
  172 + SCHEDState *s = opaque;
  173 + uint32_t saddr;
  174 +
  175 + saddr = (addr - PHYS_JJ_INTR_G) >> 2;
  176 + switch (saddr) {
  177 + case 0:
  178 + return s->intregm_pending;
  179 + break;
  180 + case 1:
  181 + return s->intregm_enabled;
  182 + break;
  183 + default:
  184 + break;
  185 + }
  186 + return 0;
  187 +}
  188 +
  189 +static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  190 +{
  191 + SCHEDState *s = opaque;
  192 + uint32_t saddr;
  193 +
  194 + saddr = (addr - PHYS_JJ_INTR_G) >> 2;
  195 + switch (saddr) {
  196 + case 0:
  197 + s->intregm_pending = val;
  198 + break;
  199 + case 1:
  200 + s->intregm_enabled = val;
  201 + break;
  202 + case 2: // clear
  203 + s->intregm_enabled &= ~val;
  204 + break;
  205 + case 3: // set
  206 + s->intregm_enabled |= val;
  207 + break;
  208 + default:
  209 + break;
  210 + }
  211 +}
  212 +
  213 +static CPUReadMemoryFunc *intregm_mem_read[3] = {
  214 + intregm_mem_readl,
  215 + intregm_mem_readl,
  216 + intregm_mem_readl,
  217 +};
  218 +
  219 +static CPUWriteMemoryFunc *intregm_mem_write[3] = {
  220 + intregm_mem_writel,
  221 + intregm_mem_writel,
  222 + intregm_mem_writel,
  223 +};
  224 +
  225 +static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
  226 +{
  227 + SCHEDState *s = opaque;
  228 + uint32_t saddr;
  229 +
  230 + saddr = (addr - PHYS_JJ_CLOCK) >> 2;
  231 + switch (saddr) {
  232 + default:
  233 + return s->timer_regs[saddr];
  234 + break;
  235 + }
  236 + return 0;
  237 +}
  238 +
  239 +static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  240 +{
  241 + SCHEDState *s = opaque;
  242 + uint32_t saddr;
  243 +
  244 + saddr = (addr - PHYS_JJ_CLOCK) >> 2;
  245 + switch (saddr) {
  246 + default:
  247 + s->timer_regs[saddr] = val;
  248 + break;
  249 + }
  250 +}
  251 +
  252 +static CPUReadMemoryFunc *timer_mem_read[3] = {
  253 + timer_mem_readl,
  254 + timer_mem_readl,
  255 + timer_mem_readl,
  256 +};
  257 +
  258 +static CPUWriteMemoryFunc *timer_mem_write[3] = {
  259 + timer_mem_writel,
  260 + timer_mem_writel,
  261 + timer_mem_writel,
  262 +};
  263 +
  264 +static uint32_t timerm_mem_readl(void *opaque, target_phys_addr_t addr)
  265 +{
  266 + SCHEDState *s = opaque;
  267 + uint32_t saddr;
  268 +
  269 + saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
  270 + switch (saddr) {
  271 + default:
  272 + return s->timerm_regs[saddr];
  273 + break;
  274 + }
  275 + return 0;
  276 +}
  277 +
  278 +static void timerm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  279 +{
  280 + SCHEDState *s = opaque;
  281 + uint32_t saddr;
  282 +
  283 + saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
  284 + switch (saddr) {
  285 + default:
  286 + s->timerm_regs[saddr] = val;
  287 + break;
  288 + }
  289 +}
  290 +
  291 +static CPUReadMemoryFunc *timerm_mem_read[3] = {
  292 + timerm_mem_readl,
  293 + timerm_mem_readl,
  294 + timerm_mem_readl,
  295 +};
  296 +
  297 +static CPUWriteMemoryFunc *timerm_mem_write[3] = {
  298 + timerm_mem_writel,
  299 + timerm_mem_writel,
  300 + timerm_mem_writel,
  301 +};
  302 +
  303 +void pic_info() {}
  304 +void irq_info() {}
  305 +
  306 +static const unsigned int intr_to_mask[16] = {
  307 + 0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
  308 + 0, 0, 0, 0, 0, 0, 0, 0,
  309 +};
  310 +
  311 +void pic_set_irq(int irq, int level)
  312 +{
  313 + if (irq < 16) {
  314 + unsigned int mask = intr_to_mask[irq];
  315 + ps->intreg_pending |= 1 << irq;
  316 + if (ps->intregm_enabled & mask) {
  317 + cpu_single_env->interrupt_index = irq;
  318 + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
  319 + }
  320 + }
  321 +}
  322 +
  323 +void sched_init()
  324 +{
  325 + SCHEDState *s;
  326 +
  327 + s = qemu_mallocz(sizeof(SCHEDState));
  328 + if (!s)
  329 + return;
  330 +
  331 + intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s);
  332 + cpu_register_physical_memory(PHYS_JJ_INTR0, 3, intreg_io_memory);
  333 +
  334 + intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
  335 + cpu_register_physical_memory(PHYS_JJ_INTR_G, 5, intregm_io_memory);
  336 +
  337 + timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
  338 + cpu_register_physical_memory(PHYS_JJ_CLOCK, 2, timer_io_memory);
  339 +
  340 + timerm_io_memory = cpu_register_io_memory(0, timerm_mem_read, timerm_mem_write, s);
  341 + cpu_register_physical_memory(PHYS_JJ_CLOCK1, 2, timerm_io_memory);
  342 +
  343 + sched_reset(s);
  344 + ps = s;
  345 +}
  346 +
... ...
hw/sun4m.c 0 → 100644
  1 +/*
  2 + * QEMU Sun4m System Emulator
  3 + *
  4 + * Copyright (c) 2003-2004 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +#include "m48t08.h"
  26 +
  27 +#define KERNEL_LOAD_ADDR 0x00004000
  28 +#define MMU_CONTEXT_TBL 0x00003000
  29 +#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
  30 +#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
  31 +#define ROMVEC_DATA (MMU_CONTEXT_TBL + 0x1800)
  32 +#define PROM_ADDR 0xffd04000
  33 +#define PROM_FILENAME "proll.bin"
  34 +#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
  35 +#define PHYS_JJ_IDPROM_OFF 0x1FD8
  36 +#define PHYS_JJ_EEPROM_SIZE 0x2000
  37 +
  38 +/* TSC handling */
  39 +
  40 +uint64_t cpu_get_tsc()
  41 +{
  42 + return qemu_get_clock(vm_clock);
  43 +}
  44 +
  45 +void DMA_run() {}
  46 +void SB16_run() {}
  47 +void vga_invalidate_display() {}
  48 +void vga_screen_dump(const char *filename) {}
  49 +int serial_can_receive(SerialState *s) { return 0; }
  50 +void serial_receive_byte(SerialState *s, int ch) {}
  51 +void serial_receive_break(SerialState *s) {}
  52 +
  53 +static m48t08_t *nvram;
  54 +
  55 +/* Sun4m hardware initialisation */
  56 +void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
  57 + DisplayState *ds, const char **fd_filename, int snapshot,
  58 + const char *kernel_filename, const char *kernel_cmdline,
  59 + const char *initrd_filename)
  60 +{
  61 + char buf[1024];
  62 + int ret, linux_boot, bios_size;
  63 + unsigned long bios_offset;
  64 +
  65 + linux_boot = (kernel_filename != NULL);
  66 +
  67 + /* allocate RAM */
  68 + cpu_register_physical_memory(0, ram_size, 0);
  69 + bios_offset = ram_size;
  70 +
  71 + iommu_init();
  72 + sched_init();
  73 + tcx_init(ds);
  74 + lance_init(&nd_table[0], 6);
  75 + nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
  76 +
  77 + magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
  78 +
  79 +#if 0
  80 + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
  81 + bios_size = get_image_size(buf);
  82 + ret = load_image(buf, phys_ram_base + bios_offset);
  83 + if (ret != bios_size) {
  84 + fprintf(stderr, "qemu: could not load prom '%s'\n", buf);
  85 + exit(1);
  86 + }
  87 + cpu_register_physical_memory(PROM_ADDR,
  88 + bios_size, bios_offset | IO_MEM_ROM);
  89 +#endif
  90 +
  91 + /* We load Proll as the kernel and start it. It will issue a magic
  92 + IO to load the real kernel */
  93 + if (linux_boot) {
  94 + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
  95 + ret = load_kernel(buf,
  96 + phys_ram_base + KERNEL_LOAD_ADDR);
  97 + if (ret < 0) {
  98 + fprintf(stderr, "qemu: could not load kernel '%s'\n",
  99 + buf);
  100 + exit(1);
  101 + }
  102 + }
  103 + /* Setup a MMU entry for entire address space */
  104 + stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
  105 + stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
  106 +#if 0
  107 + stl_raw(phys_ram_base + MMU_L1PTP + (0x50 << 2), (MMU_L2PTP >> 4) | 1); // frame buffer at 50..
  108 +#endif
  109 + stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
  110 + /* 3 = U:RWX S:RWX */
  111 + stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
  112 +#if 0
  113 + stl_raw(phys_ram_base + MMU_L2PTP + 0x84, (PHYS_JJ_TCX_FB >> 4) \
  114 + | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
  115 + stl_raw(phys_ram_base + MMU_L2PTP + 0x88, (PHYS_JJ_TCX_FB >> 4) \
  116 + | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
  117 + stl_raw(phys_ram_base + MMU_L2PTP + 0x140, (PHYS_JJ_TCX_FB >> 4) \
  118 + | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
  119 + // "Empirical constant"
  120 + stl_raw(phys_ram_base + ROMVEC_DATA, 0x10010407);
  121 +
  122 + // Version: V3 prom
  123 + stl_raw(phys_ram_base + ROMVEC_DATA + 4, 3);
  124 +
  125 + stl_raw(phys_ram_base + ROMVEC_DATA + 0x1c, ROMVEC_DATA+0x400);
  126 + stl_raw(phys_ram_base + ROMVEC_DATA + 0x400, ROMVEC_DATA+0x404);
  127 + stl_raw(phys_ram_base + ROMVEC_DATA + 0x404, 0x81c3e008); // retl
  128 + stl_raw(phys_ram_base + ROMVEC_DATA + 0x408, 0x01000000); // nop
  129 +#endif
  130 +}
... ...
hw/tcx.c 0 → 100644
  1 +/*
  2 + * QEMU Sun4m System Emulator
  3 + *
  4 + * Copyright (c) 2003-2004 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +#define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */
  27 +#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */
  28 +
  29 +#define MAXX 1024
  30 +#define MAXY 768
  31 +#define XSZ (8*80)
  32 +#define YSZ (24*11)
  33 +#define XOFF (MAXX-XSZ)
  34 +#define YOFF (MAXY-YSZ)
  35 +
  36 +#define DEBUG_VGA_MEM
  37 +
  38 +typedef struct TCXState {
  39 + uint8_t *vram_ptr;
  40 + unsigned long vram_offset;
  41 + unsigned int vram_size;
  42 + DisplayState *ds;
  43 +} TCXState;
  44 +
  45 +static TCXState *ts;
  46 +
  47 +static int tcx_io_memory;
  48 +
  49 +void vga_update_display()
  50 +{
  51 + dpy_update(ts->ds, 0, 0, XSZ, YSZ);
  52 +}
  53 +
  54 +static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
  55 +{
  56 + TCXState *s = opaque;
  57 + uint32_t saddr;
  58 + unsigned int x, y;
  59 + char *sptr;
  60 +
  61 + saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
  62 + y = saddr / MAXX;
  63 + x = saddr - y * MAXX;
  64 + if (x < MAXX && y < MAXY) {
  65 + sptr = s->ds->data;
  66 + if (sptr)
  67 + return sptr[y * s->ds->linesize + x*4];
  68 + }
  69 + return 0;
  70 +}
  71 +
  72 +static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr)
  73 +{
  74 + uint32_t v;
  75 +#ifdef TARGET_WORDS_BIGENDIAN
  76 + v = tcx_mem_readb(opaque, addr) << 8;
  77 + v |= tcx_mem_readb(opaque, addr + 1);
  78 +#else
  79 + v = tcx_mem_readb(opaque, addr);
  80 + v |= tcx_mem_readb(opaque, addr + 1) << 8;
  81 +#endif
  82 + return v;
  83 +}
  84 +
  85 +static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
  86 +{
  87 + uint32_t v;
  88 +#ifdef TARGET_WORDS_BIGENDIAN
  89 + v = tcx_mem_readb(opaque, addr) << 24;
  90 + v |= tcx_mem_readb(opaque, addr + 1) << 16;
  91 + v |= tcx_mem_readb(opaque, addr + 2) << 8;
  92 + v |= tcx_mem_readb(opaque, addr + 3);
  93 +#else
  94 + v = tcx_mem_readb(opaque, addr);
  95 + v |= tcx_mem_readb(opaque, addr + 1) << 8;
  96 + v |= tcx_mem_readb(opaque, addr + 2) << 16;
  97 + v |= tcx_mem_readb(opaque, addr + 3) << 24;
  98 +#endif
  99 + return v;
  100 +}
  101 +
  102 +/* called for accesses between 0xa0000 and 0xc0000 */
  103 +static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  104 +{
  105 + TCXState *s = opaque;
  106 + uint32_t saddr;
  107 + unsigned int x, y;
  108 + char *sptr;
  109 +
  110 + saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
  111 + y = saddr / MAXX;
  112 + x = saddr - y * MAXX;
  113 + if (x < MAXX && y < MAXY) {
  114 + sptr = s->ds->data;
  115 + if (sptr) {
  116 + sptr[y * s->ds->linesize + x*4] = val;
  117 + sptr[y * s->ds->linesize + x*4+1] = val;
  118 + sptr[y * s->ds->linesize + x*4+2] = val;
  119 + cpu_physical_memory_set_dirty(addr);
  120 + }
  121 + }
  122 +}
  123 +
  124 +static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  125 +{
  126 +#ifdef TARGET_WORDS_BIGENDIAN
  127 + tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff);
  128 + tcx_mem_writeb(opaque, addr + 1, val & 0xff);
  129 +#else
  130 + tcx_mem_writeb(opaque, addr, val & 0xff);
  131 + tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  132 +#endif
  133 +}
  134 +
  135 +static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  136 +{
  137 +#ifdef TARGET_WORDS_BIGENDIAN
  138 + tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff);
  139 + tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
  140 + tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
  141 + tcx_mem_writeb(opaque, addr + 3, val & 0xff);
  142 +#else
  143 + tcx_mem_writeb(opaque, addr, val & 0xff);
  144 + tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  145 + tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  146 + tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  147 +#endif
  148 +}
  149 +
  150 +static CPUReadMemoryFunc *tcx_mem_read[3] = {
  151 + tcx_mem_readb,
  152 + tcx_mem_readw,
  153 + tcx_mem_readl,
  154 +};
  155 +
  156 +static CPUWriteMemoryFunc *tcx_mem_write[3] = {
  157 + tcx_mem_writeb,
  158 + tcx_mem_writew,
  159 + tcx_mem_writel,
  160 +};
  161 +
  162 +void tcx_init(DisplayState *ds)
  163 +{
  164 + TCXState *s;
  165 +
  166 + s = qemu_mallocz(sizeof(TCXState));
  167 + if (!s)
  168 + return;
  169 + s->ds = ds;
  170 + ts = s;
  171 + tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
  172 + cpu_register_physical_memory(PHYS_JJ_TCX_FB, 0x100000,
  173 + tcx_io_memory);
  174 + dpy_resize(s->ds, XSZ, YSZ);
  175 +}
  176 +
... ...