Commit 91cc029598b7cd37c726175e05df7e45e9df6ffb
1 parent
c03b0f0f
initial sparc32 lance and pcnet merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2142 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
327 additions
and
588 deletions
hw/lance.c deleted
100644 → 0
| 1 | -/* | ||
| 2 | - * QEMU Lance emulation | ||
| 3 | - * | ||
| 4 | - * Copyright (c) 2003-2005 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 | -#ifdef DEBUG_LANCE | ||
| 30 | -#define DPRINTF(fmt, args...) \ | ||
| 31 | -do { printf("LANCE: " fmt , ##args); } while (0) | ||
| 32 | -#else | ||
| 33 | -#define DPRINTF(fmt, args...) | ||
| 34 | -#endif | ||
| 35 | - | ||
| 36 | -#ifndef LANCE_LOG_TX_BUFFERS | ||
| 37 | -#define LANCE_LOG_TX_BUFFERS 4 | ||
| 38 | -#define LANCE_LOG_RX_BUFFERS 4 | ||
| 39 | -#endif | ||
| 40 | - | ||
| 41 | -#define LE_CSR0 0 | ||
| 42 | -#define LE_CSR1 1 | ||
| 43 | -#define LE_CSR2 2 | ||
| 44 | -#define LE_CSR3 3 | ||
| 45 | -#define LE_NREGS (LE_CSR3 + 1) | ||
| 46 | -#define LE_MAXREG LE_CSR3 | ||
| 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 | -#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) | ||
| 155 | - | ||
| 156 | -typedef struct LANCEState { | ||
| 157 | - VLANClientState *vc; | ||
| 158 | - uint8_t macaddr[6]; /* init mac address */ | ||
| 159 | - uint32_t leptr; | ||
| 160 | - uint16_t addr; | ||
| 161 | - uint16_t regs[LE_NREGS]; | ||
| 162 | - uint8_t phys[6]; /* mac address */ | ||
| 163 | - int irq; | ||
| 164 | - unsigned int rxptr, txptr; | ||
| 165 | - uint32_t ledmaregs[LEDMA_REGS]; | ||
| 166 | -} LANCEState; | ||
| 167 | - | ||
| 168 | -static void lance_send(void *opaque); | ||
| 169 | - | ||
| 170 | -static void lance_reset(void *opaque) | ||
| 171 | -{ | ||
| 172 | - LANCEState *s = opaque; | ||
| 173 | - memcpy(s->phys, s->macaddr, 6); | ||
| 174 | - s->rxptr = 0; | ||
| 175 | - s->txptr = 0; | ||
| 176 | - memset(s->regs, 0, LE_NREGS * 2); | ||
| 177 | - s->regs[LE_CSR0] = LE_C0_STOP; | ||
| 178 | - memset(s->ledmaregs, 0, LEDMA_REGS * 4); | ||
| 179 | -} | ||
| 180 | - | ||
| 181 | -static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) | ||
| 182 | -{ | ||
| 183 | - LANCEState *s = opaque; | ||
| 184 | - uint32_t saddr; | ||
| 185 | - | ||
| 186 | - saddr = addr & LE_MAXREG; | ||
| 187 | - switch (saddr >> 1) { | ||
| 188 | - case LE_RDP: | ||
| 189 | - DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]); | ||
| 190 | - return s->regs[s->addr]; | ||
| 191 | - case LE_RAP: | ||
| 192 | - DPRINTF("read areg = %4.4x\n", s->addr); | ||
| 193 | - return s->addr; | ||
| 194 | - default: | ||
| 195 | - DPRINTF("read unknown(%d)\n", saddr >> 1); | ||
| 196 | - break; | ||
| 197 | - } | ||
| 198 | - return 0; | ||
| 199 | -} | ||
| 200 | - | ||
| 201 | -static void lance_mem_writew(void *opaque, target_phys_addr_t addr, | ||
| 202 | - uint32_t val) | ||
| 203 | -{ | ||
| 204 | - LANCEState *s = opaque; | ||
| 205 | - uint32_t saddr; | ||
| 206 | - uint16_t reg; | ||
| 207 | - | ||
| 208 | - saddr = addr & LE_MAXREG; | ||
| 209 | - switch (saddr >> 1) { | ||
| 210 | - case LE_RDP: | ||
| 211 | - DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val); | ||
| 212 | - switch (s->addr) { | ||
| 213 | - case LE_CSR0: | ||
| 214 | - if (val & LE_C0_STOP) { | ||
| 215 | - s->regs[LE_CSR0] = LE_C0_STOP; | ||
| 216 | - break; | ||
| 217 | - } | ||
| 218 | - | ||
| 219 | - reg = s->regs[LE_CSR0]; | ||
| 220 | - | ||
| 221 | - // 1 = clear for some bits | ||
| 222 | - reg &= ~(val & 0x7f00); | ||
| 223 | - | ||
| 224 | - // generated bits | ||
| 225 | - reg &= ~(LE_C0_ERR | LE_C0_INTR); | ||
| 226 | - if (reg & 0x7100) | ||
| 227 | - reg |= LE_C0_ERR; | ||
| 228 | - if (reg & 0x7f00) | ||
| 229 | - reg |= LE_C0_INTR; | ||
| 230 | - | ||
| 231 | - // direct bit | ||
| 232 | - reg &= ~LE_C0_INEA; | ||
| 233 | - reg |= val & LE_C0_INEA; | ||
| 234 | - | ||
| 235 | - // exclusive bits | ||
| 236 | - if (val & LE_C0_INIT) { | ||
| 237 | - reg |= LE_C0_IDON | LE_C0_INIT; | ||
| 238 | - reg &= ~LE_C0_STOP; | ||
| 239 | - } else if (val & LE_C0_STRT) { | ||
| 240 | - reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON; | ||
| 241 | - reg &= ~LE_C0_STOP; | ||
| 242 | - } | ||
| 243 | - | ||
| 244 | - s->regs[LE_CSR0] = reg; | ||
| 245 | - break; | ||
| 246 | - case LE_CSR1: | ||
| 247 | - s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff); | ||
| 248 | - s->regs[s->addr] = val; | ||
| 249 | - break; | ||
| 250 | - case LE_CSR2: | ||
| 251 | - s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16); | ||
| 252 | - s->regs[s->addr] = val; | ||
| 253 | - break; | ||
| 254 | - case LE_CSR3: | ||
| 255 | - s->regs[s->addr] = val; | ||
| 256 | - break; | ||
| 257 | - } | ||
| 258 | - break; | ||
| 259 | - case LE_RAP: | ||
| 260 | - DPRINTF("write areg = %4.4x\n", val); | ||
| 261 | - if (val < LE_NREGS) | ||
| 262 | - s->addr = val; | ||
| 263 | - break; | ||
| 264 | - default: | ||
| 265 | - DPRINTF("write unknown(%d) = %4.4x\n", saddr >> 1, val); | ||
| 266 | - break; | ||
| 267 | - } | ||
| 268 | - lance_send(s); | ||
| 269 | -} | ||
| 270 | - | ||
| 271 | -static CPUReadMemoryFunc *lance_mem_read[3] = { | ||
| 272 | - lance_mem_readw, | ||
| 273 | - lance_mem_readw, | ||
| 274 | - lance_mem_readw, | ||
| 275 | -}; | ||
| 276 | - | ||
| 277 | -static CPUWriteMemoryFunc *lance_mem_write[3] = { | ||
| 278 | - lance_mem_writew, | ||
| 279 | - lance_mem_writew, | ||
| 280 | - lance_mem_writew, | ||
| 281 | -}; | ||
| 282 | - | ||
| 283 | - | ||
| 284 | -#define MIN_BUF_SIZE 60 | ||
| 285 | - | ||
| 286 | -static int lance_can_receive(void *opaque) | ||
| 287 | -{ | ||
| 288 | - return 1; | ||
| 289 | -} | ||
| 290 | - | ||
| 291 | -static void lance_receive(void *opaque, const uint8_t * buf, int size) | ||
| 292 | -{ | ||
| 293 | - LANCEState *s = opaque; | ||
| 294 | - uint32_t dmaptr = s->leptr + s->ledmaregs[3]; | ||
| 295 | - struct lance_init_block *ib; | ||
| 296 | - unsigned int i, old_rxptr; | ||
| 297 | - uint16_t temp16; | ||
| 298 | - uint8_t temp8; | ||
| 299 | - | ||
| 300 | - DPRINTF("receive size %d\n", size); | ||
| 301 | - if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) | ||
| 302 | - return; | ||
| 303 | - | ||
| 304 | - ib = (void *) iommu_translate(dmaptr); | ||
| 305 | - | ||
| 306 | - old_rxptr = s->rxptr; | ||
| 307 | - for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); | ||
| 308 | - i = (i + 1) & RX_RING_MOD_MASK) { | ||
| 309 | - cpu_physical_memory_read((uint32_t) & ib->brx_ring[i].rmd1_bits, | ||
| 310 | - (void *) &temp8, 1); | ||
| 311 | - if (temp8 == (LE_R1_OWN)) { | ||
| 312 | - s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK; | ||
| 313 | - temp16 = size + 4; | ||
| 314 | - bswap16s(&temp16); | ||
| 315 | - cpu_physical_memory_write((uint32_t) & ib->brx_ring[i]. | ||
| 316 | - mblength, (void *) &temp16, 2); | ||
| 317 | - cpu_physical_memory_write((uint32_t) & ib->rx_buf[i], buf, | ||
| 318 | - size); | ||
| 319 | - temp8 = LE_R1_POK; | ||
| 320 | - cpu_physical_memory_write((uint32_t) & ib->brx_ring[i]. | ||
| 321 | - rmd1_bits, (void *) &temp8, 1); | ||
| 322 | - s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR; | ||
| 323 | - if (s->regs[LE_CSR0] & LE_C0_INEA) | ||
| 324 | - pic_set_irq(s->irq, 1); | ||
| 325 | - DPRINTF("got packet, len %d\n", size); | ||
| 326 | - return; | ||
| 327 | - } | ||
| 328 | - } | ||
| 329 | -} | ||
| 330 | - | ||
| 331 | -static void lance_send(void *opaque) | ||
| 332 | -{ | ||
| 333 | - LANCEState *s = opaque; | ||
| 334 | - uint32_t dmaptr = s->leptr + s->ledmaregs[3]; | ||
| 335 | - struct lance_init_block *ib; | ||
| 336 | - unsigned int i, old_txptr; | ||
| 337 | - uint16_t temp16; | ||
| 338 | - uint8_t temp8; | ||
| 339 | - char pkt_buf[PKT_BUF_SZ]; | ||
| 340 | - | ||
| 341 | - DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]); | ||
| 342 | - if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) | ||
| 343 | - return; | ||
| 344 | - | ||
| 345 | - ib = (void *) iommu_translate(dmaptr); | ||
| 346 | - | ||
| 347 | - DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", | ||
| 348 | - dmaptr, ib, &ib->btx_ring); | ||
| 349 | - old_txptr = s->txptr; | ||
| 350 | - for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); | ||
| 351 | - i = (i + 1) & TX_RING_MOD_MASK) { | ||
| 352 | - cpu_physical_memory_read((uint32_t) & ib->btx_ring[i].tmd1_bits, | ||
| 353 | - (void *) &temp8, 1); | ||
| 354 | - if (temp8 == (LE_T1_POK | LE_T1_OWN)) { | ||
| 355 | - cpu_physical_memory_read((uint32_t) & ib->btx_ring[i].length, | ||
| 356 | - (void *) &temp16, 2); | ||
| 357 | - bswap16s(&temp16); | ||
| 358 | - temp16 = (~temp16) + 1; | ||
| 359 | - cpu_physical_memory_read((uint32_t) & ib->tx_buf[i], pkt_buf, | ||
| 360 | - temp16); | ||
| 361 | - DPRINTF("sending packet, len %d\n", temp16); | ||
| 362 | - qemu_send_packet(s->vc, pkt_buf, temp16); | ||
| 363 | - temp8 = LE_T1_POK; | ||
| 364 | - cpu_physical_memory_write((uint32_t) & ib->btx_ring[i]. | ||
| 365 | - tmd1_bits, (void *) &temp8, 1); | ||
| 366 | - s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK; | ||
| 367 | - s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR; | ||
| 368 | - } | ||
| 369 | - } | ||
| 370 | - if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) | ||
| 371 | - pic_set_irq(s->irq, 1); | ||
| 372 | -} | ||
| 373 | - | ||
| 374 | -static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr) | ||
| 375 | -{ | ||
| 376 | - LANCEState *s = opaque; | ||
| 377 | - uint32_t saddr; | ||
| 378 | - | ||
| 379 | - saddr = (addr & LEDMA_MAXADDR) >> 2; | ||
| 380 | - return s->ledmaregs[saddr]; | ||
| 381 | -} | ||
| 382 | - | ||
| 383 | -static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, | ||
| 384 | - uint32_t val) | ||
| 385 | -{ | ||
| 386 | - LANCEState *s = opaque; | ||
| 387 | - uint32_t saddr; | ||
| 388 | - | ||
| 389 | - saddr = (addr & LEDMA_MAXADDR) >> 2; | ||
| 390 | - s->ledmaregs[saddr] = val; | ||
| 391 | -} | ||
| 392 | - | ||
| 393 | -static CPUReadMemoryFunc *ledma_mem_read[3] = { | ||
| 394 | - ledma_mem_readl, | ||
| 395 | - ledma_mem_readl, | ||
| 396 | - ledma_mem_readl, | ||
| 397 | -}; | ||
| 398 | - | ||
| 399 | -static CPUWriteMemoryFunc *ledma_mem_write[3] = { | ||
| 400 | - ledma_mem_writel, | ||
| 401 | - ledma_mem_writel, | ||
| 402 | - ledma_mem_writel, | ||
| 403 | -}; | ||
| 404 | - | ||
| 405 | -static void lance_save(QEMUFile * f, void *opaque) | ||
| 406 | -{ | ||
| 407 | - LANCEState *s = opaque; | ||
| 408 | - int i; | ||
| 409 | - | ||
| 410 | - qemu_put_be32s(f, &s->leptr); | ||
| 411 | - qemu_put_be16s(f, &s->addr); | ||
| 412 | - for (i = 0; i < LE_NREGS; i++) | ||
| 413 | - qemu_put_be16s(f, &s->regs[i]); | ||
| 414 | - qemu_put_buffer(f, s->phys, 6); | ||
| 415 | - qemu_put_be32s(f, &s->irq); | ||
| 416 | - for (i = 0; i < LEDMA_REGS; i++) | ||
| 417 | - qemu_put_be32s(f, &s->ledmaregs[i]); | ||
| 418 | -} | ||
| 419 | - | ||
| 420 | -static int lance_load(QEMUFile * f, void *opaque, int version_id) | ||
| 421 | -{ | ||
| 422 | - LANCEState *s = opaque; | ||
| 423 | - int i; | ||
| 424 | - | ||
| 425 | - if (version_id != 1) | ||
| 426 | - return -EINVAL; | ||
| 427 | - | ||
| 428 | - qemu_get_be32s(f, &s->leptr); | ||
| 429 | - qemu_get_be16s(f, &s->addr); | ||
| 430 | - for (i = 0; i < LE_NREGS; i++) | ||
| 431 | - qemu_get_be16s(f, &s->regs[i]); | ||
| 432 | - qemu_get_buffer(f, s->phys, 6); | ||
| 433 | - qemu_get_be32s(f, &s->irq); | ||
| 434 | - for (i = 0; i < LEDMA_REGS; i++) | ||
| 435 | - qemu_get_be32s(f, &s->ledmaregs[i]); | ||
| 436 | - return 0; | ||
| 437 | -} | ||
| 438 | - | ||
| 439 | -void lance_init(NICInfo * nd, int irq, uint32_t leaddr, uint32_t ledaddr) | ||
| 440 | -{ | ||
| 441 | - LANCEState *s; | ||
| 442 | - int lance_io_memory, ledma_io_memory; | ||
| 443 | - | ||
| 444 | - s = qemu_mallocz(sizeof(LANCEState)); | ||
| 445 | - if (!s) | ||
| 446 | - return; | ||
| 447 | - | ||
| 448 | - s->irq = irq; | ||
| 449 | - | ||
| 450 | - lance_io_memory = | ||
| 451 | - cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); | ||
| 452 | - cpu_register_physical_memory(leaddr, 4, lance_io_memory); | ||
| 453 | - | ||
| 454 | - ledma_io_memory = | ||
| 455 | - cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); | ||
| 456 | - cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); | ||
| 457 | - | ||
| 458 | - memcpy(s->macaddr, nd->macaddr, 6); | ||
| 459 | - | ||
| 460 | - lance_reset(s); | ||
| 461 | - | ||
| 462 | - s->vc = | ||
| 463 | - qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, | ||
| 464 | - s); | ||
| 465 | - | ||
| 466 | - snprintf(s->vc->info_str, sizeof(s->vc->info_str), | ||
| 467 | - "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | ||
| 468 | - s->macaddr[0], | ||
| 469 | - s->macaddr[1], | ||
| 470 | - s->macaddr[2], s->macaddr[3], s->macaddr[4], s->macaddr[5]); | ||
| 471 | - | ||
| 472 | - register_savevm("lance", leaddr, 1, lance_save, lance_load, s); | ||
| 473 | - qemu_register_reset(lance_reset, s); | ||
| 474 | -} |
hw/pcnet.c
| @@ -27,6 +27,16 @@ | @@ -27,6 +27,16 @@ | ||
| 27 | * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 | 27 | * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | +/* | ||
| 31 | + * On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also | ||
| 32 | + * produced as NCR89C100. See | ||
| 33 | + * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt | ||
| 34 | + * and | ||
| 35 | + * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt | ||
| 36 | + */ | ||
| 37 | + | ||
| 38 | +/* TODO: remove little endian host assumptions */ | ||
| 39 | + | ||
| 30 | #include "vl.h" | 40 | #include "vl.h" |
| 31 | 41 | ||
| 32 | //#define PCNET_DEBUG | 42 | //#define PCNET_DEBUG |
| @@ -46,11 +56,12 @@ typedef struct PCNetState_st PCNetState; | @@ -46,11 +56,12 @@ typedef struct PCNetState_st PCNetState; | ||
| 46 | 56 | ||
| 47 | struct PCNetState_st { | 57 | struct PCNetState_st { |
| 48 | PCIDevice dev; | 58 | PCIDevice dev; |
| 59 | + PCIDevice *pci_dev; | ||
| 49 | VLANClientState *vc; | 60 | VLANClientState *vc; |
| 50 | NICInfo *nd; | 61 | NICInfo *nd; |
| 51 | QEMUTimer *poll_timer; | 62 | QEMUTimer *poll_timer; |
| 52 | - int mmio_io_addr, rap, isr, lnkst; | ||
| 53 | - target_phys_addr_t rdra, tdra; | 63 | + int mmio_index, rap, isr, lnkst; |
| 64 | + uint32_t rdra, tdra; | ||
| 54 | uint8_t prom[16]; | 65 | uint8_t prom[16]; |
| 55 | uint16_t csr[128]; | 66 | uint16_t csr[128]; |
| 56 | uint16_t bcr[32]; | 67 | uint16_t bcr[32]; |
| @@ -58,6 +69,12 @@ struct PCNetState_st { | @@ -58,6 +69,12 @@ struct PCNetState_st { | ||
| 58 | int xmit_pos, recv_pos; | 69 | int xmit_pos, recv_pos; |
| 59 | uint8_t buffer[4096]; | 70 | uint8_t buffer[4096]; |
| 60 | int tx_busy; | 71 | int tx_busy; |
| 72 | + void (*set_irq_cb)(void *s, int isr); | ||
| 73 | + void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, | ||
| 74 | + uint8_t *buf, int len); | ||
| 75 | + void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, | ||
| 76 | + uint8_t *buf, int len); | ||
| 77 | + void *dma_opaque; | ||
| 61 | }; | 78 | }; |
| 62 | 79 | ||
| 63 | /* XXX: using bitfields for target memory structures is almost surely | 80 | /* XXX: using bitfields for target memory structures is almost surely |
| @@ -99,6 +116,7 @@ struct qemu_ether_header { | @@ -99,6 +116,7 @@ struct qemu_ether_header { | ||
| 99 | #define CSR_TXON(S) !!(((S)->csr[0])&0x0010) | 116 | #define CSR_TXON(S) !!(((S)->csr[0])&0x0010) |
| 100 | #define CSR_RXON(S) !!(((S)->csr[0])&0x0020) | 117 | #define CSR_RXON(S) !!(((S)->csr[0])&0x0020) |
| 101 | #define CSR_INEA(S) !!(((S)->csr[0])&0x0040) | 118 | #define CSR_INEA(S) !!(((S)->csr[0])&0x0040) |
| 119 | +#define CSR_BIGENDIAN(S) !!(((S)->csr[3])&0x0004) | ||
| 102 | #define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020) | 120 | #define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020) |
| 103 | #define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040) | 121 | #define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040) |
| 104 | #define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800) | 122 | #define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800) |
| @@ -147,35 +165,19 @@ struct qemu_ether_header { | @@ -147,35 +165,19 @@ struct qemu_ether_header { | ||
| 147 | 165 | ||
| 148 | struct pcnet_initblk16 { | 166 | struct pcnet_initblk16 { |
| 149 | uint16_t mode; | 167 | uint16_t mode; |
| 150 | - uint16_t padr1; | ||
| 151 | - uint16_t padr2; | ||
| 152 | - uint16_t padr3; | ||
| 153 | - uint16_t ladrf1; | ||
| 154 | - uint16_t ladrf2; | ||
| 155 | - uint16_t ladrf3; | ||
| 156 | - uint16_t ladrf4; | ||
| 157 | - unsigned PACKED_FIELD(rdra:24); | ||
| 158 | - unsigned PACKED_FIELD(res1:5); | ||
| 159 | - unsigned PACKED_FIELD(rlen:3); | ||
| 160 | - unsigned PACKED_FIELD(tdra:24); | ||
| 161 | - unsigned PACKED_FIELD(res2:5); | ||
| 162 | - unsigned PACKED_FIELD(tlen:3); | 168 | + uint16_t padr[3]; |
| 169 | + uint16_t ladrf[4]; | ||
| 170 | + uint32_t rdra; | ||
| 171 | + uint32_t tdra; | ||
| 163 | }; | 172 | }; |
| 164 | 173 | ||
| 165 | struct pcnet_initblk32 { | 174 | struct pcnet_initblk32 { |
| 166 | uint16_t mode; | 175 | uint16_t mode; |
| 167 | - unsigned PACKED_FIELD(res1:4); | ||
| 168 | - unsigned PACKED_FIELD(rlen:4); | ||
| 169 | - unsigned PACKED_FIELD(res2:4); | ||
| 170 | - unsigned PACKED_FIELD(tlen:4); | ||
| 171 | - uint16_t padr1; | ||
| 172 | - uint16_t padr2; | ||
| 173 | - uint16_t padr3; | 176 | + uint8_t rlen; |
| 177 | + uint8_t tlen; | ||
| 178 | + uint16_t padr[3]; | ||
| 174 | uint16_t _res; | 179 | uint16_t _res; |
| 175 | - uint16_t ladrf1; | ||
| 176 | - uint16_t ladrf2; | ||
| 177 | - uint16_t ladrf3; | ||
| 178 | - uint16_t ladrf4; | 180 | + uint16_t ladrf[4]; |
| 179 | uint32_t rdra; | 181 | uint32_t rdra; |
| 180 | uint32_t tdra; | 182 | uint32_t tdra; |
| 181 | }; | 183 | }; |
| @@ -255,22 +257,32 @@ static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_p | @@ -255,22 +257,32 @@ static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_p | ||
| 255 | { | 257 | { |
| 256 | if (!BCR_SWSTYLE(s)) { | 258 | if (!BCR_SWSTYLE(s)) { |
| 257 | uint16_t xda[4]; | 259 | uint16_t xda[4]; |
| 258 | - cpu_physical_memory_read(addr, | 260 | + s->phys_mem_read(s->dma_opaque, addr, |
| 259 | (void *)&xda[0], sizeof(xda)); | 261 | (void *)&xda[0], sizeof(xda)); |
| 260 | - ((uint32_t *)tmd)[0] = (xda[0]&0xffff) | | 262 | + if (CSR_BIGENDIAN(s)) { |
| 263 | + ((uint32_t *)tmd)[0] = be16_to_cpu(xda[0]) | | ||
| 264 | + ((be16_to_cpu(xda[1]) & 0x00ff) << 16); | ||
| 265 | + ((uint32_t *)tmd)[1] = be16_to_cpu(xda[2]) | | ||
| 266 | + ((be16_to_cpu(xda[1]) & 0xff00) << 16); | ||
| 267 | + ((uint32_t *)tmd)[2] = | ||
| 268 | + (be16_to_cpu(xda[3]) & 0xffff) << 16; | ||
| 269 | + ((uint32_t *)tmd)[3] = 0; | ||
| 270 | + } else { | ||
| 271 | + ((uint32_t *)tmd)[0] = (xda[0]&0xffff) | | ||
| 261 | ((xda[1]&0x00ff) << 16); | 272 | ((xda[1]&0x00ff) << 16); |
| 262 | - ((uint32_t *)tmd)[1] = (xda[2]&0xffff)| | 273 | + ((uint32_t *)tmd)[1] = (xda[2]&0xffff)| |
| 263 | ((xda[1] & 0xff00) << 16); | 274 | ((xda[1] & 0xff00) << 16); |
| 264 | - ((uint32_t *)tmd)[2] = | 275 | + ((uint32_t *)tmd)[2] = |
| 265 | (xda[3] & 0xffff) << 16; | 276 | (xda[3] & 0xffff) << 16; |
| 266 | - ((uint32_t *)tmd)[3] = 0; | 277 | + ((uint32_t *)tmd)[3] = 0; |
| 278 | + } | ||
| 267 | } | 279 | } |
| 268 | else | 280 | else |
| 269 | if (BCR_SWSTYLE(s) != 3) | 281 | if (BCR_SWSTYLE(s) != 3) |
| 270 | - cpu_physical_memory_read(addr, (void *)tmd, 16); | 282 | + s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, 16); |
| 271 | else { | 283 | else { |
| 272 | uint32_t xda[4]; | 284 | uint32_t xda[4]; |
| 273 | - cpu_physical_memory_read(addr, | 285 | + s->phys_mem_read(s->dma_opaque, addr, |
| 274 | (void *)&xda[0], sizeof(xda)); | 286 | (void *)&xda[0], sizeof(xda)); |
| 275 | ((uint32_t *)tmd)[0] = xda[2]; | 287 | ((uint32_t *)tmd)[0] = xda[2]; |
| 276 | ((uint32_t *)tmd)[1] = xda[1]; | 288 | ((uint32_t *)tmd)[1] = xda[1]; |
| @@ -283,24 +295,32 @@ static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_ | @@ -283,24 +295,32 @@ static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_ | ||
| 283 | { | 295 | { |
| 284 | if (!BCR_SWSTYLE(s)) { | 296 | if (!BCR_SWSTYLE(s)) { |
| 285 | uint16_t xda[4]; | 297 | uint16_t xda[4]; |
| 286 | - xda[0] = ((uint32_t *)tmd)[0] & 0xffff; | ||
| 287 | - xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) | | ||
| 288 | - ((((uint32_t *)tmd)[1]>>16)&0xff00); | ||
| 289 | - xda[2] = ((uint32_t *)tmd)[1] & 0xffff; | ||
| 290 | - xda[3] = ((uint32_t *)tmd)[2] >> 16; | ||
| 291 | - cpu_physical_memory_write(addr, | 298 | + if (CSR_BIGENDIAN(s)) { |
| 299 | + xda[0] = cpu_to_be16(((uint32_t *)tmd)[0] & 0xffff); | ||
| 300 | + xda[1] = cpu_to_be16(((((uint32_t *)tmd)[0] >> 16) & 0x00ff) | | ||
| 301 | + ((((uint32_t *)tmd)[1] >> 16) & 0xff00)); | ||
| 302 | + xda[2] = cpu_to_be16(((uint32_t *)tmd)[1] & 0xffff); | ||
| 303 | + xda[3] = cpu_to_be16(((uint32_t *)tmd)[2] >> 16); | ||
| 304 | + } else { | ||
| 305 | + xda[0] = ((uint32_t *)tmd)[0] & 0xffff; | ||
| 306 | + xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) | | ||
| 307 | + ((((uint32_t *)tmd)[1]>>16)&0xff00); | ||
| 308 | + xda[2] = ((uint32_t *)tmd)[1] & 0xffff; | ||
| 309 | + xda[3] = ((uint32_t *)tmd)[2] >> 16; | ||
| 310 | + } | ||
| 311 | + s->phys_mem_write(s->dma_opaque, addr, | ||
| 292 | (void *)&xda[0], sizeof(xda)); | 312 | (void *)&xda[0], sizeof(xda)); |
| 293 | } | 313 | } |
| 294 | else { | 314 | else { |
| 295 | if (BCR_SWSTYLE(s) != 3) | 315 | if (BCR_SWSTYLE(s) != 3) |
| 296 | - cpu_physical_memory_write(addr, (void *)tmd, 16); | 316 | + s->phys_mem_write(s->dma_opaque, addr, (void *)tmd, 16); |
| 297 | else { | 317 | else { |
| 298 | uint32_t xda[4]; | 318 | uint32_t xda[4]; |
| 299 | xda[0] = ((uint32_t *)tmd)[2]; | 319 | xda[0] = ((uint32_t *)tmd)[2]; |
| 300 | xda[1] = ((uint32_t *)tmd)[1]; | 320 | xda[1] = ((uint32_t *)tmd)[1]; |
| 301 | xda[2] = ((uint32_t *)tmd)[0]; | 321 | xda[2] = ((uint32_t *)tmd)[0]; |
| 302 | xda[3] = ((uint32_t *)tmd)[3]; | 322 | xda[3] = ((uint32_t *)tmd)[3]; |
| 303 | - cpu_physical_memory_write(addr, | 323 | + s->phys_mem_write(s->dma_opaque, addr, |
| 304 | (void *)&xda[0], sizeof(xda)); | 324 | (void *)&xda[0], sizeof(xda)); |
| 305 | } | 325 | } |
| 306 | } | 326 | } |
| @@ -310,21 +330,30 @@ static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_p | @@ -310,21 +330,30 @@ static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_p | ||
| 310 | { | 330 | { |
| 311 | if (!BCR_SWSTYLE(s)) { | 331 | if (!BCR_SWSTYLE(s)) { |
| 312 | uint16_t rda[4]; | 332 | uint16_t rda[4]; |
| 313 | - cpu_physical_memory_read(addr, | 333 | + s->phys_mem_read(s->dma_opaque, addr, |
| 314 | (void *)&rda[0], sizeof(rda)); | 334 | (void *)&rda[0], sizeof(rda)); |
| 315 | - ((uint32_t *)rmd)[0] = (rda[0]&0xffff)| | 335 | + if (CSR_BIGENDIAN(s)) { |
| 336 | + ((uint32_t *)rmd)[0] = (be16_to_cpu(rda[0]) & 0xffff) | | ||
| 337 | + ((be16_to_cpu(rda[1]) & 0x00ff) << 16); | ||
| 338 | + ((uint32_t *)rmd)[1] = (be16_to_cpu(rda[2]) & 0xffff) | | ||
| 339 | + ((be16_to_cpu(rda[1]) & 0xff00) << 16); | ||
| 340 | + ((uint32_t *)rmd)[2] = be16_to_cpu(rda[3]) & 0xffff; | ||
| 341 | + ((uint32_t *)rmd)[3] = 0; | ||
| 342 | + } else { | ||
| 343 | + ((uint32_t *)rmd)[0] = (rda[0]&0xffff)| | ||
| 316 | ((rda[1] & 0x00ff) << 16); | 344 | ((rda[1] & 0x00ff) << 16); |
| 317 | - ((uint32_t *)rmd)[1] = (rda[2]&0xffff)| | 345 | + ((uint32_t *)rmd)[1] = (rda[2]&0xffff)| |
| 318 | ((rda[1] & 0xff00) << 16); | 346 | ((rda[1] & 0xff00) << 16); |
| 319 | - ((uint32_t *)rmd)[2] = rda[3] & 0xffff; | ||
| 320 | - ((uint32_t *)rmd)[3] = 0; | 347 | + ((uint32_t *)rmd)[2] = rda[3] & 0xffff; |
| 348 | + ((uint32_t *)rmd)[3] = 0; | ||
| 349 | + } | ||
| 321 | } | 350 | } |
| 322 | else | 351 | else |
| 323 | if (BCR_SWSTYLE(s) != 3) | 352 | if (BCR_SWSTYLE(s) != 3) |
| 324 | - cpu_physical_memory_read(addr, (void *)rmd, 16); | 353 | + s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, 16); |
| 325 | else { | 354 | else { |
| 326 | uint32_t rda[4]; | 355 | uint32_t rda[4]; |
| 327 | - cpu_physical_memory_read(addr, | 356 | + s->phys_mem_read(s->dma_opaque, addr, |
| 328 | (void *)&rda[0], sizeof(rda)); | 357 | (void *)&rda[0], sizeof(rda)); |
| 329 | ((uint32_t *)rmd)[0] = rda[2]; | 358 | ((uint32_t *)rmd)[0] = rda[2]; |
| 330 | ((uint32_t *)rmd)[1] = rda[1]; | 359 | ((uint32_t *)rmd)[1] = rda[1]; |
| @@ -336,25 +365,33 @@ static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_p | @@ -336,25 +365,33 @@ static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_p | ||
| 336 | static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr) | 365 | static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr) |
| 337 | { | 366 | { |
| 338 | if (!BCR_SWSTYLE(s)) { | 367 | if (!BCR_SWSTYLE(s)) { |
| 339 | - uint16_t rda[4]; \ | ||
| 340 | - rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \ | ||
| 341 | - rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\ | ||
| 342 | - ((((uint32_t *)rmd)[1]>>16)&0xff00);\ | ||
| 343 | - rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \ | ||
| 344 | - rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \ | ||
| 345 | - cpu_physical_memory_write(addr, \ | ||
| 346 | - (void *)&rda[0], sizeof(rda)); \ | 368 | + uint16_t rda[4]; |
| 369 | + if (CSR_BIGENDIAN(s)) { | ||
| 370 | + rda[0] = cpu_to_be16(((uint32_t *)rmd)[0] & 0xffff); | ||
| 371 | + rda[1] = cpu_to_be16(((((uint32_t *)rmd)[0] >> 16) & 0xff) | | ||
| 372 | + ((((uint32_t *)rmd)[1] >> 16) & 0xff00)); | ||
| 373 | + rda[2] = cpu_to_be16(((uint32_t *)rmd)[1] & 0xffff); | ||
| 374 | + rda[3] = cpu_to_be16(((uint32_t *)rmd)[2] & 0xffff); | ||
| 375 | + } else { | ||
| 376 | + rda[0] = ((uint32_t *)rmd)[0] & 0xffff; | ||
| 377 | + rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)| | ||
| 378 | + ((((uint32_t *)rmd)[1]>>16)&0xff00); | ||
| 379 | + rda[2] = ((uint32_t *)rmd)[1] & 0xffff; | ||
| 380 | + rda[3] = ((uint32_t *)rmd)[2] & 0xffff; | ||
| 381 | + } | ||
| 382 | + s->phys_mem_write(s->dma_opaque, addr, | ||
| 383 | + (void *)&rda[0], sizeof(rda)); | ||
| 347 | } | 384 | } |
| 348 | else { | 385 | else { |
| 349 | if (BCR_SWSTYLE(s) != 3) | 386 | if (BCR_SWSTYLE(s) != 3) |
| 350 | - cpu_physical_memory_write(addr, (void *)rmd, 16); | 387 | + s->phys_mem_write(s->dma_opaque, addr, (void *)rmd, 16); |
| 351 | else { | 388 | else { |
| 352 | uint32_t rda[4]; | 389 | uint32_t rda[4]; |
| 353 | rda[0] = ((uint32_t *)rmd)[2]; | 390 | rda[0] = ((uint32_t *)rmd)[2]; |
| 354 | rda[1] = ((uint32_t *)rmd)[1]; | 391 | rda[1] = ((uint32_t *)rmd)[1]; |
| 355 | rda[2] = ((uint32_t *)rmd)[0]; | 392 | rda[2] = ((uint32_t *)rmd)[0]; |
| 356 | rda[3] = ((uint32_t *)rmd)[3]; | 393 | rda[3] = ((uint32_t *)rmd)[3]; |
| 357 | - cpu_physical_memory_write(addr, | 394 | + s->phys_mem_write(s->dma_opaque, addr, |
| 358 | (void *)&rda[0], sizeof(rda)); | 395 | (void *)&rda[0], sizeof(rda)); |
| 359 | } | 396 | } |
| 360 | } | 397 | } |
| @@ -391,7 +428,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | @@ -391,7 +428,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | ||
| 391 | case 0x00: \ | 428 | case 0x00: \ |
| 392 | do { \ | 429 | do { \ |
| 393 | uint16_t rda[4]; \ | 430 | uint16_t rda[4]; \ |
| 394 | - cpu_physical_memory_read((ADDR), \ | 431 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ |
| 395 | (void *)&rda[0], sizeof(rda)); \ | 432 | (void *)&rda[0], sizeof(rda)); \ |
| 396 | (RES) |= (rda[2] & 0xf000)!=0xf000; \ | 433 | (RES) |= (rda[2] & 0xf000)!=0xf000; \ |
| 397 | (RES) |= (rda[3] & 0xf000)!=0x0000; \ | 434 | (RES) |= (rda[3] & 0xf000)!=0x0000; \ |
| @@ -401,7 +438,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | @@ -401,7 +438,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | ||
| 401 | case 0x02: \ | 438 | case 0x02: \ |
| 402 | do { \ | 439 | do { \ |
| 403 | uint32_t rda[4]; \ | 440 | uint32_t rda[4]; \ |
| 404 | - cpu_physical_memory_read((ADDR), \ | 441 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ |
| 405 | (void *)&rda[0], sizeof(rda)); \ | 442 | (void *)&rda[0], sizeof(rda)); \ |
| 406 | (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ | 443 | (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ |
| 407 | (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \ | 444 | (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \ |
| @@ -410,7 +447,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | @@ -410,7 +447,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | ||
| 410 | case 0x03: \ | 447 | case 0x03: \ |
| 411 | do { \ | 448 | do { \ |
| 412 | uint32_t rda[4]; \ | 449 | uint32_t rda[4]; \ |
| 413 | - cpu_physical_memory_read((ADDR), \ | 450 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ |
| 414 | (void *)&rda[0], sizeof(rda)); \ | 451 | (void *)&rda[0], sizeof(rda)); \ |
| 415 | (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \ | 452 | (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \ |
| 416 | (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ | 453 | (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ |
| @@ -424,7 +461,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | @@ -424,7 +461,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | ||
| 424 | case 0x00: \ | 461 | case 0x00: \ |
| 425 | do { \ | 462 | do { \ |
| 426 | uint16_t xda[4]; \ | 463 | uint16_t xda[4]; \ |
| 427 | - cpu_physical_memory_read((ADDR), \ | 464 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ |
| 428 | (void *)&xda[0], sizeof(xda)); \ | 465 | (void *)&xda[0], sizeof(xda)); \ |
| 429 | (RES) |= (xda[2] & 0xf000)!=0xf000;\ | 466 | (RES) |= (xda[2] & 0xf000)!=0xf000;\ |
| 430 | } while (0); \ | 467 | } while (0); \ |
| @@ -434,7 +471,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | @@ -434,7 +471,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ | ||
| 434 | case 0x03: \ | 471 | case 0x03: \ |
| 435 | do { \ | 472 | do { \ |
| 436 | uint32_t xda[4]; \ | 473 | uint32_t xda[4]; \ |
| 437 | - cpu_physical_memory_read((ADDR), \ | 474 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ |
| 438 | (void *)&xda[0], sizeof(xda)); \ | 475 | (void *)&xda[0], sizeof(xda)); \ |
| 439 | (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \ | 476 | (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \ |
| 440 | } while (0); \ | 477 | } while (0); \ |
| @@ -721,51 +758,86 @@ static void pcnet_update_irq(PCNetState *s) | @@ -721,51 +758,86 @@ static void pcnet_update_irq(PCNetState *s) | ||
| 721 | printf("pcnet: INTA=%d\n", isr); | 758 | printf("pcnet: INTA=%d\n", isr); |
| 722 | #endif | 759 | #endif |
| 723 | } | 760 | } |
| 724 | - pci_set_irq(&s->dev, 0, isr); | ||
| 725 | - s->isr = isr; | 761 | + s->set_irq_cb(s, isr); |
| 762 | + s->isr = isr; | ||
| 726 | } | 763 | } |
| 727 | 764 | ||
| 728 | static void pcnet_init(PCNetState *s) | 765 | static void pcnet_init(PCNetState *s) |
| 729 | { | 766 | { |
| 767 | + int rlen, tlen; | ||
| 768 | + uint16_t *padr, *ladrf, mode; | ||
| 769 | + uint32_t rdra, tdra; | ||
| 770 | + | ||
| 730 | #ifdef PCNET_DEBUG | 771 | #ifdef PCNET_DEBUG |
| 731 | printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s))); | 772 | printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s))); |
| 732 | #endif | 773 | #endif |
| 733 | 774 | ||
| 734 | -#define PCNET_INIT() do { \ | ||
| 735 | - cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)), \ | ||
| 736 | - (uint8_t *)&initblk, sizeof(initblk)); \ | ||
| 737 | - s->csr[15] = le16_to_cpu(initblk.mode); \ | ||
| 738 | - CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \ | ||
| 739 | - CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \ | ||
| 740 | - s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \ | ||
| 741 | - s->csr[ 8] = le16_to_cpu(initblk.ladrf1); \ | ||
| 742 | - s->csr[ 9] = le16_to_cpu(initblk.ladrf2); \ | ||
| 743 | - s->csr[10] = le16_to_cpu(initblk.ladrf3); \ | ||
| 744 | - s->csr[11] = le16_to_cpu(initblk.ladrf4); \ | ||
| 745 | - s->csr[12] = le16_to_cpu(initblk.padr1); \ | ||
| 746 | - s->csr[13] = le16_to_cpu(initblk.padr2); \ | ||
| 747 | - s->csr[14] = le16_to_cpu(initblk.padr3); \ | ||
| 748 | - s->rdra = PHYSADDR(s,initblk.rdra); \ | ||
| 749 | - s->tdra = PHYSADDR(s,initblk.tdra); \ | ||
| 750 | -} while (0) | ||
| 751 | - | ||
| 752 | if (BCR_SSIZE32(s)) { | 775 | if (BCR_SSIZE32(s)) { |
| 753 | struct pcnet_initblk32 initblk; | 776 | struct pcnet_initblk32 initblk; |
| 754 | - PCNET_INIT(); | ||
| 755 | -#ifdef PCNET_DEBUG | ||
| 756 | - printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n", | ||
| 757 | - initblk.rlen, initblk.tlen); | ||
| 758 | -#endif | 777 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)), |
| 778 | + (uint8_t *)&initblk, sizeof(initblk)); | ||
| 779 | + mode = initblk.mode; | ||
| 780 | + rlen = initblk.rlen >> 4; | ||
| 781 | + tlen = initblk.tlen >> 4; | ||
| 782 | + ladrf = initblk.ladrf; | ||
| 783 | + padr = initblk.padr; | ||
| 784 | + if (CSR_BIGENDIAN(s)) { | ||
| 785 | + rdra = be32_to_cpu(initblk.rdra); | ||
| 786 | + tdra = be32_to_cpu(initblk.tdra); | ||
| 787 | + } else { | ||
| 788 | + rdra = le32_to_cpu(initblk.rdra); | ||
| 789 | + tdra = le32_to_cpu(initblk.tdra); | ||
| 790 | + } | ||
| 791 | + s->rdra = PHYSADDR(s,initblk.rdra); | ||
| 792 | + s->tdra = PHYSADDR(s,initblk.tdra); | ||
| 759 | } else { | 793 | } else { |
| 760 | struct pcnet_initblk16 initblk; | 794 | struct pcnet_initblk16 initblk; |
| 761 | - PCNET_INIT(); | ||
| 762 | -#ifdef PCNET_DEBUG | ||
| 763 | - printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n", | ||
| 764 | - initblk.rlen, initblk.tlen); | 795 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)), |
| 796 | + (uint8_t *)&initblk, sizeof(initblk)); | ||
| 797 | + mode = initblk.mode; | ||
| 798 | + ladrf = initblk.ladrf; | ||
| 799 | + padr = initblk.padr; | ||
| 800 | + if (CSR_BIGENDIAN(s)) { | ||
| 801 | + rdra = be32_to_cpu(initblk.rdra); | ||
| 802 | + tdra = be32_to_cpu(initblk.tdra); | ||
| 803 | + } else { | ||
| 804 | + rdra = le32_to_cpu(initblk.rdra); | ||
| 805 | + tdra = le32_to_cpu(initblk.tdra); | ||
| 806 | + } | ||
| 807 | + rlen = rdra >> 29; | ||
| 808 | + tlen = tdra >> 29; | ||
| 809 | + rdra &= 0x00ffffff; | ||
| 810 | + tdra &= 0x00ffffff; | ||
| 811 | + } | ||
| 812 | + | ||
| 813 | +#if defined(PCNET_DEBUG) | ||
| 814 | + printf("rlen=%d tlen=%d\n", | ||
| 815 | + rlen, tlen); | ||
| 765 | #endif | 816 | #endif |
| 817 | + CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512; | ||
| 818 | + CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512; | ||
| 819 | + s->csr[ 6] = (tlen << 12) | (rlen << 8); | ||
| 820 | + if (CSR_BIGENDIAN(s)) { | ||
| 821 | + s->csr[15] = be16_to_cpu(mode); | ||
| 822 | + s->csr[ 8] = be16_to_cpu(ladrf[0]); | ||
| 823 | + s->csr[ 9] = be16_to_cpu(ladrf[1]); | ||
| 824 | + s->csr[10] = be16_to_cpu(ladrf[2]); | ||
| 825 | + s->csr[11] = be16_to_cpu(ladrf[3]); | ||
| 826 | + s->csr[12] = be16_to_cpu(padr[0]); | ||
| 827 | + s->csr[13] = be16_to_cpu(padr[1]); | ||
| 828 | + s->csr[14] = be16_to_cpu(padr[2]); | ||
| 829 | + } else { | ||
| 830 | + s->csr[15] = le16_to_cpu(mode); | ||
| 831 | + s->csr[ 8] = le16_to_cpu(ladrf[0]); | ||
| 832 | + s->csr[ 9] = le16_to_cpu(ladrf[1]); | ||
| 833 | + s->csr[10] = le16_to_cpu(ladrf[2]); | ||
| 834 | + s->csr[11] = le16_to_cpu(ladrf[3]); | ||
| 835 | + s->csr[12] = le16_to_cpu(padr[0]); | ||
| 836 | + s->csr[13] = le16_to_cpu(padr[1]); | ||
| 837 | + s->csr[14] = le16_to_cpu(padr[2]); | ||
| 766 | } | 838 | } |
| 767 | - | ||
| 768 | -#undef PCNET_INIT | 839 | + s->rdra = PHYSADDR(s, rdra); |
| 840 | + s->tdra = PHYSADDR(s, tdra); | ||
| 769 | 841 | ||
| 770 | CSR_RCVRC(s) = CSR_RCVRL(s); | 842 | CSR_RCVRC(s) = CSR_RCVRL(s); |
| 771 | CSR_XMTRC(s) = CSR_XMTRL(s); | 843 | CSR_XMTRC(s) = CSR_XMTRL(s); |
| @@ -1035,7 +1107,7 @@ static void pcnet_receive(void *opaque, const uint8_t *buf, int size) | @@ -1035,7 +1107,7 @@ static void pcnet_receive(void *opaque, const uint8_t *buf, int size) | ||
| 1035 | #define PCNET_RECV_STORE() do { \ | 1107 | #define PCNET_RECV_STORE() do { \ |
| 1036 | int count = MIN(4096 - rmd.rmd1.bcnt,size); \ | 1108 | int count = MIN(4096 - rmd.rmd1.bcnt,size); \ |
| 1037 | target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \ | 1109 | target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \ |
| 1038 | - cpu_physical_memory_write(rbadr, src, count); \ | 1110 | + s->phys_mem_write(s->dma_opaque, rbadr, src, count); \ |
| 1039 | src += count; size -= count; \ | 1111 | src += count; size -= count; \ |
| 1040 | rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \ | 1112 | rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \ |
| 1041 | RMDSTORE(&rmd, PHYSADDR(s,crda)); \ | 1113 | RMDSTORE(&rmd, PHYSADDR(s,crda)); \ |
| @@ -1125,14 +1197,14 @@ static void pcnet_transmit(PCNetState *s) | @@ -1125,14 +1197,14 @@ static void pcnet_transmit(PCNetState *s) | ||
| 1125 | if (tmd.tmd1.stp) { | 1197 | if (tmd.tmd1.stp) { |
| 1126 | s->xmit_pos = 0; | 1198 | s->xmit_pos = 0; |
| 1127 | if (!tmd.tmd1.enp) { | 1199 | if (!tmd.tmd1.enp) { |
| 1128 | - cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr), | 1200 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr), |
| 1129 | s->buffer, 4096 - tmd.tmd1.bcnt); | 1201 | s->buffer, 4096 - tmd.tmd1.bcnt); |
| 1130 | s->xmit_pos += 4096 - tmd.tmd1.bcnt; | 1202 | s->xmit_pos += 4096 - tmd.tmd1.bcnt; |
| 1131 | } | 1203 | } |
| 1132 | xmit_cxda = PHYSADDR(s,CSR_CXDA(s)); | 1204 | xmit_cxda = PHYSADDR(s,CSR_CXDA(s)); |
| 1133 | } | 1205 | } |
| 1134 | if (tmd.tmd1.enp && (s->xmit_pos >= 0)) { | 1206 | if (tmd.tmd1.enp && (s->xmit_pos >= 0)) { |
| 1135 | - cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr), | 1207 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr), |
| 1136 | s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt); | 1208 | s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt); |
| 1137 | s->xmit_pos += 4096 - tmd.tmd1.bcnt; | 1209 | s->xmit_pos += 4096 - tmd.tmd1.bcnt; |
| 1138 | #ifdef PCNET_DEBUG | 1210 | #ifdef PCNET_DEBUG |
| @@ -1426,8 +1498,9 @@ static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) | @@ -1426,8 +1498,9 @@ static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) | ||
| 1426 | return val; | 1498 | return val; |
| 1427 | } | 1499 | } |
| 1428 | 1500 | ||
| 1429 | -static void pcnet_h_reset(PCNetState *s) | 1501 | +void pcnet_h_reset(void *opaque) |
| 1430 | { | 1502 | { |
| 1503 | + PCNetState *s = opaque; | ||
| 1431 | int i; | 1504 | int i; |
| 1432 | uint16_t checksum; | 1505 | uint16_t checksum; |
| 1433 | 1506 | ||
| @@ -1703,6 +1776,90 @@ static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) | @@ -1703,6 +1776,90 @@ static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) | ||
| 1703 | } | 1776 | } |
| 1704 | 1777 | ||
| 1705 | 1778 | ||
| 1779 | +static void pcnet_save(QEMUFile *f, void *opaque) | ||
| 1780 | +{ | ||
| 1781 | + PCNetState *s = opaque; | ||
| 1782 | + unsigned int i; | ||
| 1783 | + | ||
| 1784 | + if (s->pci_dev) | ||
| 1785 | + pci_device_save(s->pci_dev, f); | ||
| 1786 | + | ||
| 1787 | + qemu_put_be32s(f, &s->rap); | ||
| 1788 | + qemu_put_be32s(f, &s->isr); | ||
| 1789 | + qemu_put_be32s(f, &s->lnkst); | ||
| 1790 | + qemu_put_be32s(f, &s->rdra); | ||
| 1791 | + qemu_put_be32s(f, &s->tdra); | ||
| 1792 | + qemu_put_buffer(f, s->prom, 16); | ||
| 1793 | + for (i = 0; i < 128; i++) | ||
| 1794 | + qemu_put_be16s(f, &s->csr[i]); | ||
| 1795 | + for (i = 0; i < 32; i++) | ||
| 1796 | + qemu_put_be16s(f, &s->bcr[i]); | ||
| 1797 | + qemu_put_be64s(f, &s->timer); | ||
| 1798 | + qemu_put_be32s(f, &s->xmit_pos); | ||
| 1799 | + qemu_put_be32s(f, &s->recv_pos); | ||
| 1800 | + qemu_put_buffer(f, s->buffer, 4096); | ||
| 1801 | + qemu_put_be32s(f, &s->tx_busy); | ||
| 1802 | + qemu_put_timer(f, s->poll_timer); | ||
| 1803 | +} | ||
| 1804 | + | ||
| 1805 | +static int pcnet_load(QEMUFile *f, void *opaque, int version_id) | ||
| 1806 | +{ | ||
| 1807 | + PCNetState *s = opaque; | ||
| 1808 | + int i, ret; | ||
| 1809 | + | ||
| 1810 | + if (version_id != 2) | ||
| 1811 | + return -EINVAL; | ||
| 1812 | + | ||
| 1813 | + if (s->pci_dev) { | ||
| 1814 | + ret = pci_device_load(s->pci_dev, f); | ||
| 1815 | + if (ret < 0) | ||
| 1816 | + return ret; | ||
| 1817 | + } | ||
| 1818 | + | ||
| 1819 | + qemu_get_be32s(f, &s->rap); | ||
| 1820 | + qemu_get_be32s(f, &s->isr); | ||
| 1821 | + qemu_get_be32s(f, &s->lnkst); | ||
| 1822 | + qemu_get_be32s(f, &s->rdra); | ||
| 1823 | + qemu_get_be32s(f, &s->tdra); | ||
| 1824 | + qemu_get_buffer(f, s->prom, 16); | ||
| 1825 | + for (i = 0; i < 128; i++) | ||
| 1826 | + qemu_get_be16s(f, &s->csr[i]); | ||
| 1827 | + for (i = 0; i < 32; i++) | ||
| 1828 | + qemu_get_be16s(f, &s->bcr[i]); | ||
| 1829 | + qemu_get_be64s(f, &s->timer); | ||
| 1830 | + qemu_get_be32s(f, &s->xmit_pos); | ||
| 1831 | + qemu_get_be32s(f, &s->recv_pos); | ||
| 1832 | + qemu_get_buffer(f, s->buffer, 4096); | ||
| 1833 | + qemu_get_be32s(f, &s->tx_busy); | ||
| 1834 | + qemu_get_timer(f, s->poll_timer); | ||
| 1835 | + | ||
| 1836 | + return 0; | ||
| 1837 | +} | ||
| 1838 | + | ||
| 1839 | +static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str) | ||
| 1840 | +{ | ||
| 1841 | + d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); | ||
| 1842 | + | ||
| 1843 | + d->nd = nd; | ||
| 1844 | + | ||
| 1845 | + d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, | ||
| 1846 | + pcnet_can_receive, d); | ||
| 1847 | + | ||
| 1848 | + snprintf(d->vc->info_str, sizeof(d->vc->info_str), | ||
| 1849 | + "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | ||
| 1850 | + d->nd->macaddr[0], | ||
| 1851 | + d->nd->macaddr[1], | ||
| 1852 | + d->nd->macaddr[2], | ||
| 1853 | + d->nd->macaddr[3], | ||
| 1854 | + d->nd->macaddr[4], | ||
| 1855 | + d->nd->macaddr[5]); | ||
| 1856 | + | ||
| 1857 | + pcnet_h_reset(d); | ||
| 1858 | + register_savevm("pcnet", 0, 2, pcnet_save, pcnet_load, d); | ||
| 1859 | +} | ||
| 1860 | + | ||
| 1861 | +/* PCI interface */ | ||
| 1862 | + | ||
| 1706 | static CPUWriteMemoryFunc *pcnet_mmio_write[] = { | 1863 | static CPUWriteMemoryFunc *pcnet_mmio_write[] = { |
| 1707 | (CPUWriteMemoryFunc *)&pcnet_mmio_writeb, | 1864 | (CPUWriteMemoryFunc *)&pcnet_mmio_writeb, |
| 1708 | (CPUWriteMemoryFunc *)&pcnet_mmio_writew, | 1865 | (CPUWriteMemoryFunc *)&pcnet_mmio_writew, |
| @@ -1724,7 +1881,26 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, | @@ -1724,7 +1881,26 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, | ||
| 1724 | printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size); | 1881 | printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size); |
| 1725 | #endif | 1882 | #endif |
| 1726 | 1883 | ||
| 1727 | - cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr); | 1884 | + cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index); |
| 1885 | +} | ||
| 1886 | + | ||
| 1887 | +static void pcnet_pci_set_irq_cb(void *opaque, int isr) | ||
| 1888 | +{ | ||
| 1889 | + PCNetState *s = opaque; | ||
| 1890 | + | ||
| 1891 | + pci_set_irq(&s->dev, 0, isr); | ||
| 1892 | +} | ||
| 1893 | + | ||
| 1894 | +static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr, | ||
| 1895 | + uint8_t *buf, int len) | ||
| 1896 | +{ | ||
| 1897 | + cpu_physical_memory_write(addr, buf, len); | ||
| 1898 | +} | ||
| 1899 | + | ||
| 1900 | +static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, | ||
| 1901 | + uint8_t *buf, int len) | ||
| 1902 | +{ | ||
| 1903 | + cpu_physical_memory_read(addr, buf, len); | ||
| 1728 | } | 1904 | } |
| 1729 | 1905 | ||
| 1730 | void pci_pcnet_init(PCIBus *bus, NICInfo *nd) | 1906 | void pci_pcnet_init(PCIBus *bus, NICInfo *nd) |
| @@ -1760,7 +1936,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd) | @@ -1760,7 +1936,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd) | ||
| 1760 | pci_conf[0x3f] = 0xff; | 1936 | pci_conf[0x3f] = 0xff; |
| 1761 | 1937 | ||
| 1762 | /* Handler for memory-mapped I/O */ | 1938 | /* Handler for memory-mapped I/O */ |
| 1763 | - d->mmio_io_addr = | 1939 | + d->mmio_index = |
| 1764 | cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d); | 1940 | cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d); |
| 1765 | 1941 | ||
| 1766 | pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, | 1942 | pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, |
| @@ -1769,21 +1945,58 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd) | @@ -1769,21 +1945,58 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd) | ||
| 1769 | pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, | 1945 | pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, |
| 1770 | PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map); | 1946 | PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map); |
| 1771 | 1947 | ||
| 1772 | - d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); | 1948 | + d->set_irq_cb = pcnet_pci_set_irq_cb; |
| 1949 | + d->phys_mem_read = pci_physical_memory_read; | ||
| 1950 | + d->phys_mem_write = pci_physical_memory_write; | ||
| 1951 | + d->pci_dev = &d->dev; | ||
| 1773 | 1952 | ||
| 1774 | - d->nd = nd; | 1953 | + pcnet_common_init(d, nd, "pcnet"); |
| 1954 | +} | ||
| 1775 | 1955 | ||
| 1776 | - d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, | ||
| 1777 | - pcnet_can_receive, d); | ||
| 1778 | - | ||
| 1779 | - snprintf(d->vc->info_str, sizeof(d->vc->info_str), | ||
| 1780 | - "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | ||
| 1781 | - d->nd->macaddr[0], | ||
| 1782 | - d->nd->macaddr[1], | ||
| 1783 | - d->nd->macaddr[2], | ||
| 1784 | - d->nd->macaddr[3], | ||
| 1785 | - d->nd->macaddr[4], | ||
| 1786 | - d->nd->macaddr[5]); | 1956 | +/* SPARC32 interface */ |
| 1787 | 1957 | ||
| 1788 | - pcnet_h_reset(d); | 1958 | +#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure |
| 1959 | + | ||
| 1960 | +static CPUReadMemoryFunc *lance_mem_read[3] = { | ||
| 1961 | + (CPUReadMemoryFunc *)&pcnet_ioport_readw, | ||
| 1962 | + (CPUReadMemoryFunc *)&pcnet_ioport_readw, | ||
| 1963 | + (CPUReadMemoryFunc *)&pcnet_ioport_readw, | ||
| 1964 | +}; | ||
| 1965 | + | ||
| 1966 | +static CPUWriteMemoryFunc *lance_mem_write[3] = { | ||
| 1967 | + (CPUWriteMemoryFunc *)&pcnet_ioport_writew, | ||
| 1968 | + (CPUWriteMemoryFunc *)&pcnet_ioport_writew, | ||
| 1969 | + (CPUWriteMemoryFunc *)&pcnet_ioport_writew, | ||
| 1970 | +}; | ||
| 1971 | + | ||
| 1972 | +static void pcnet_sparc_set_irq_cb(void *opaque, int isr) | ||
| 1973 | +{ | ||
| 1974 | + PCNetState *s = opaque; | ||
| 1975 | + | ||
| 1976 | + ledma_set_irq(s->dma_opaque, isr); | ||
| 1977 | +} | ||
| 1978 | + | ||
| 1979 | +void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque) | ||
| 1980 | +{ | ||
| 1981 | + PCNetState *d; | ||
| 1982 | + int lance_io_memory; | ||
| 1983 | + | ||
| 1984 | + d = qemu_mallocz(sizeof(PCNetState)); | ||
| 1985 | + if (!d) | ||
| 1986 | + return NULL; | ||
| 1987 | + | ||
| 1988 | + lance_io_memory = | ||
| 1989 | + cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d); | ||
| 1990 | + | ||
| 1991 | + d->dma_opaque = dma_opaque; | ||
| 1992 | + cpu_register_physical_memory(leaddr, 4, lance_io_memory); | ||
| 1993 | + | ||
| 1994 | + d->set_irq_cb = pcnet_sparc_set_irq_cb; | ||
| 1995 | + d->phys_mem_read = ledma_memory_read; | ||
| 1996 | + d->phys_mem_write = ledma_memory_write; | ||
| 1997 | + | ||
| 1998 | + pcnet_common_init(d, nd, "lance"); | ||
| 1999 | + | ||
| 2000 | + return d; | ||
| 1789 | } | 2001 | } |
| 2002 | +#endif /* TARGET_SPARC */ |