|
|
1.1 root 1: /*
2: * QEMU AMD PC-Net II (Am79C970A) emulation
1.1.1.3 ! root 3: *
1.1 root 4: * Copyright (c) 2004 Antony T Curtis
1.1.1.3 ! root 5: *
1.1 root 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: */
1.1.1.3 ! root 24:
1.1 root 25: /* This software was written to be compatible with the specification:
26: * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
27: * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
28: */
1.1.1.3 ! root 29:
1.1.1.2 root 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:
1.1.1.3 ! root 38: #include "hw.h"
! 39: #include "pci.h"
! 40: #include "net.h"
! 41: #include "qemu-timer.h"
1.1 root 42:
43: //#define PCNET_DEBUG
44: //#define PCNET_DEBUG_IO
45: //#define PCNET_DEBUG_BCR
46: //#define PCNET_DEBUG_CSR
47: //#define PCNET_DEBUG_RMD
48: //#define PCNET_DEBUG_TMD
49: //#define PCNET_DEBUG_MATCH
50:
51:
52: #define PCNET_IOPORT_SIZE 0x20
53: #define PCNET_PNPMMIO_SIZE 0x20
54:
55:
56: typedef struct PCNetState_st PCNetState;
57:
58: struct PCNetState_st {
59: PCIDevice dev;
1.1.1.2 root 60: PCIDevice *pci_dev;
1.1 root 61: VLANClientState *vc;
62: NICInfo *nd;
63: QEMUTimer *poll_timer;
1.1.1.2 root 64: int mmio_index, rap, isr, lnkst;
65: uint32_t rdra, tdra;
1.1 root 66: uint8_t prom[16];
67: uint16_t csr[128];
68: uint16_t bcr[32];
69: uint64_t timer;
70: int xmit_pos, recv_pos;
71: uint8_t buffer[4096];
72: int tx_busy;
1.1.1.3 ! root 73: qemu_irq irq;
1.1.1.2 root 74: void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
75: uint8_t *buf, int len, int do_bswap);
76: void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
77: uint8_t *buf, int len, int do_bswap);
78: void *dma_opaque;
1.1 root 79: };
80:
81: struct qemu_ether_header {
82: uint8_t ether_dhost[6];
83: uint8_t ether_shost[6];
84: uint16_t ether_type;
85: };
86:
87: /* BUS CONFIGURATION REGISTERS */
88: #define BCR_MSRDA 0
89: #define BCR_MSWRA 1
90: #define BCR_MC 2
91: #define BCR_LNKST 4
92: #define BCR_LED1 5
93: #define BCR_LED2 6
94: #define BCR_LED3 7
95: #define BCR_FDC 9
96: #define BCR_BSBC 18
97: #define BCR_EECAS 19
98: #define BCR_SWS 20
99: #define BCR_PLAT 22
100:
101: #define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080)
102: #define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100)
103: #define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF)
104:
105: #define CSR_INIT(S) !!(((S)->csr[0])&0x0001)
106: #define CSR_STRT(S) !!(((S)->csr[0])&0x0002)
107: #define CSR_STOP(S) !!(((S)->csr[0])&0x0004)
108: #define CSR_TDMD(S) !!(((S)->csr[0])&0x0008)
109: #define CSR_TXON(S) !!(((S)->csr[0])&0x0010)
110: #define CSR_RXON(S) !!(((S)->csr[0])&0x0020)
111: #define CSR_INEA(S) !!(((S)->csr[0])&0x0040)
1.1.1.2 root 112: #define CSR_BSWP(S) !!(((S)->csr[3])&0x0004)
1.1 root 113: #define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020)
114: #define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040)
115: #define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
116: #define CSR_DPOLL(S) !!(((S)->csr[4])&0x1000)
117: #define CSR_SPND(S) !!(((S)->csr[5])&0x0001)
118: #define CSR_LTINTEN(S) !!(((S)->csr[5])&0x4000)
119: #define CSR_TOKINTD(S) !!(((S)->csr[5])&0x8000)
120: #define CSR_DRX(S) !!(((S)->csr[15])&0x0001)
121: #define CSR_DTX(S) !!(((S)->csr[15])&0x0002)
122: #define CSR_LOOP(S) !!(((S)->csr[15])&0x0004)
123: #define CSR_DRCVPA(S) !!(((S)->csr[15])&0x2000)
124: #define CSR_DRCVBC(S) !!(((S)->csr[15])&0x4000)
125: #define CSR_PROM(S) !!(((S)->csr[15])&0x8000)
126:
127: #define CSR_CRBC(S) ((S)->csr[40])
128: #define CSR_CRST(S) ((S)->csr[41])
129: #define CSR_CXBC(S) ((S)->csr[42])
130: #define CSR_CXST(S) ((S)->csr[43])
131: #define CSR_NRBC(S) ((S)->csr[44])
132: #define CSR_NRST(S) ((S)->csr[45])
133: #define CSR_POLL(S) ((S)->csr[46])
134: #define CSR_PINT(S) ((S)->csr[47])
135: #define CSR_RCVRC(S) ((S)->csr[72])
136: #define CSR_XMTRC(S) ((S)->csr[74])
137: #define CSR_RCVRL(S) ((S)->csr[76])
138: #define CSR_XMTRL(S) ((S)->csr[78])
139: #define CSR_MISSC(S) ((S)->csr[112])
140:
141: #define CSR_IADR(S) ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
142: #define CSR_CRBA(S) ((S)->csr[18] | ((S)->csr[19] << 16))
143: #define CSR_CXBA(S) ((S)->csr[20] | ((S)->csr[21] << 16))
144: #define CSR_NRBA(S) ((S)->csr[22] | ((S)->csr[23] << 16))
145: #define CSR_BADR(S) ((S)->csr[24] | ((S)->csr[25] << 16))
146: #define CSR_NRDA(S) ((S)->csr[26] | ((S)->csr[27] << 16))
147: #define CSR_CRDA(S) ((S)->csr[28] | ((S)->csr[29] << 16))
148: #define CSR_BADX(S) ((S)->csr[30] | ((S)->csr[31] << 16))
149: #define CSR_NXDA(S) ((S)->csr[32] | ((S)->csr[33] << 16))
150: #define CSR_CXDA(S) ((S)->csr[34] | ((S)->csr[35] << 16))
151: #define CSR_NNRD(S) ((S)->csr[36] | ((S)->csr[37] << 16))
152: #define CSR_NNXD(S) ((S)->csr[38] | ((S)->csr[39] << 16))
153: #define CSR_PXDA(S) ((S)->csr[60] | ((S)->csr[61] << 16))
154: #define CSR_NXBA(S) ((S)->csr[64] | ((S)->csr[65] << 16))
155:
156: #define PHYSADDR(S,A) \
157: (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
158:
159: struct pcnet_initblk16 {
160: uint16_t mode;
1.1.1.2 root 161: uint16_t padr[3];
162: uint16_t ladrf[4];
163: uint32_t rdra;
164: uint32_t tdra;
1.1 root 165: };
166:
167: struct pcnet_initblk32 {
168: uint16_t mode;
1.1.1.2 root 169: uint8_t rlen;
170: uint8_t tlen;
171: uint16_t padr[3];
1.1 root 172: uint16_t _res;
1.1.1.2 root 173: uint16_t ladrf[4];
1.1 root 174: uint32_t rdra;
175: uint32_t tdra;
176: };
177:
178: struct pcnet_TMD {
1.1.1.3 ! root 179: uint32_t tbadr;
! 180: int16_t length;
! 181: int16_t status;
! 182: uint32_t misc;
! 183: uint32_t res;
1.1 root 184: };
185:
1.1.1.3 ! root 186: #define TMDL_BCNT_MASK 0x0fff
! 187: #define TMDL_BCNT_SH 0
! 188: #define TMDL_ONES_MASK 0xf000
! 189: #define TMDL_ONES_SH 12
! 190:
! 191: #define TMDS_BPE_MASK 0x0080
! 192: #define TMDS_BPE_SH 7
! 193: #define TMDS_ENP_MASK 0x0100
! 194: #define TMDS_ENP_SH 8
! 195: #define TMDS_STP_MASK 0x0200
! 196: #define TMDS_STP_SH 9
! 197: #define TMDS_DEF_MASK 0x0400
! 198: #define TMDS_DEF_SH 10
! 199: #define TMDS_ONE_MASK 0x0800
! 200: #define TMDS_ONE_SH 11
! 201: #define TMDS_LTINT_MASK 0x1000
! 202: #define TMDS_LTINT_SH 12
! 203: #define TMDS_NOFCS_MASK 0x2000
! 204: #define TMDS_NOFCS_SH 13
! 205: #define TMDS_ERR_MASK 0x4000
! 206: #define TMDS_ERR_SH 14
! 207: #define TMDS_OWN_MASK 0x8000
! 208: #define TMDS_OWN_SH 15
! 209:
! 210: #define TMDM_TRC_MASK 0x0000000f
! 211: #define TMDM_TRC_SH 0
! 212: #define TMDM_TDR_MASK 0x03ff0000
! 213: #define TMDM_TDR_SH 16
! 214: #define TMDM_RTRY_MASK 0x04000000
! 215: #define TMDM_RTRY_SH 26
! 216: #define TMDM_LCAR_MASK 0x08000000
! 217: #define TMDM_LCAR_SH 27
! 218: #define TMDM_LCOL_MASK 0x10000000
! 219: #define TMDM_LCOL_SH 28
! 220: #define TMDM_EXDEF_MASK 0x20000000
! 221: #define TMDM_EXDEF_SH 29
! 222: #define TMDM_UFLO_MASK 0x40000000
! 223: #define TMDM_UFLO_SH 30
! 224: #define TMDM_BUFF_MASK 0x80000000
! 225: #define TMDM_BUFF_SH 31
! 226:
1.1 root 227: struct pcnet_RMD {
1.1.1.3 ! root 228: uint32_t rbadr;
! 229: int16_t buf_length;
! 230: int16_t status;
! 231: uint32_t msg_length;
! 232: uint32_t res;
1.1 root 233: };
234:
1.1.1.3 ! root 235: #define RMDL_BCNT_MASK 0x0fff
! 236: #define RMDL_BCNT_SH 0
! 237: #define RMDL_ONES_MASK 0xf000
! 238: #define RMDL_ONES_SH 12
! 239:
! 240: #define RMDS_BAM_MASK 0x0010
! 241: #define RMDS_BAM_SH 4
! 242: #define RMDS_LFAM_MASK 0x0020
! 243: #define RMDS_LFAM_SH 5
! 244: #define RMDS_PAM_MASK 0x0040
! 245: #define RMDS_PAM_SH 6
! 246: #define RMDS_BPE_MASK 0x0080
! 247: #define RMDS_BPE_SH 7
! 248: #define RMDS_ENP_MASK 0x0100
! 249: #define RMDS_ENP_SH 8
! 250: #define RMDS_STP_MASK 0x0200
! 251: #define RMDS_STP_SH 9
! 252: #define RMDS_BUFF_MASK 0x0400
! 253: #define RMDS_BUFF_SH 10
! 254: #define RMDS_CRC_MASK 0x0800
! 255: #define RMDS_CRC_SH 11
! 256: #define RMDS_OFLO_MASK 0x1000
! 257: #define RMDS_OFLO_SH 12
! 258: #define RMDS_FRAM_MASK 0x2000
! 259: #define RMDS_FRAM_SH 13
! 260: #define RMDS_ERR_MASK 0x4000
! 261: #define RMDS_ERR_SH 14
! 262: #define RMDS_OWN_MASK 0x8000
! 263: #define RMDS_OWN_SH 15
! 264:
! 265: #define RMDM_MCNT_MASK 0x00000fff
! 266: #define RMDM_MCNT_SH 0
! 267: #define RMDM_ZEROS_MASK 0x0000f000
! 268: #define RMDM_ZEROS_SH 12
! 269: #define RMDM_RPC_MASK 0x00ff0000
! 270: #define RMDM_RPC_SH 16
! 271: #define RMDM_RCC_MASK 0xff000000
! 272: #define RMDM_RCC_SH 24
! 273:
! 274: #define SET_FIELD(regp, name, field, value) \
! 275: (*(regp) = (*(regp) & ~(name ## _ ## field ## _MASK)) \
! 276: | ((value) << name ## _ ## field ## _SH))
! 277:
! 278: #define GET_FIELD(reg, name, field) \
! 279: (((reg) & name ## _ ## field ## _MASK) >> name ## _ ## field ## _SH)
1.1 root 280:
1.1.1.3 ! root 281: #define PRINT_TMD(T) printf( \
! 282: "TMD0 : TBADR=0x%08x\n" \
1.1 root 283: "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, " \
284: "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n" \
285: " BPE=%d, BCNT=%d\n" \
286: "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, " \
287: "LCA=%d, RTR=%d,\n" \
288: " TDR=%d, TRC=%d\n", \
1.1.1.3 ! root 289: (T)->tbadr, \
! 290: GET_FIELD((T)->status, TMDS, OWN), \
! 291: GET_FIELD((T)->status, TMDS, ERR), \
! 292: GET_FIELD((T)->status, TMDS, NOFCS), \
! 293: GET_FIELD((T)->status, TMDS, LTINT), \
! 294: GET_FIELD((T)->status, TMDS, ONE), \
! 295: GET_FIELD((T)->status, TMDS, DEF), \
! 296: GET_FIELD((T)->status, TMDS, STP), \
! 297: GET_FIELD((T)->status, TMDS, ENP), \
! 298: GET_FIELD((T)->status, TMDS, BPE), \
! 299: 4096-GET_FIELD((T)->length, TMDL, BCNT), \
! 300: GET_FIELD((T)->misc, TMDM, BUFF), \
! 301: GET_FIELD((T)->misc, TMDM, UFLO), \
! 302: GET_FIELD((T)->misc, TMDM, EXDEF), \
! 303: GET_FIELD((T)->misc, TMDM, LCOL), \
! 304: GET_FIELD((T)->misc, TMDM, LCAR), \
! 305: GET_FIELD((T)->misc, TMDM, RTRY), \
! 306: GET_FIELD((T)->misc, TMDM, TDR), \
! 307: GET_FIELD((T)->misc, TMDM, TRC))
1.1 root 308:
1.1.1.3 ! root 309: #define PRINT_RMD(R) printf( \
! 310: "RMD0 : RBADR=0x%08x\n" \
1.1 root 311: "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, " \
312: "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n " \
1.1.1.3 ! root 313: "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
1.1 root 314: "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n", \
1.1.1.3 ! root 315: (R)->rbadr, \
! 316: GET_FIELD((R)->status, RMDS, OWN), \
! 317: GET_FIELD((R)->status, RMDS, ERR), \
! 318: GET_FIELD((R)->status, RMDS, FRAM), \
! 319: GET_FIELD((R)->status, RMDS, OFLO), \
! 320: GET_FIELD((R)->status, RMDS, CRC), \
! 321: GET_FIELD((R)->status, RMDS, BUFF), \
! 322: GET_FIELD((R)->status, RMDS, STP), \
! 323: GET_FIELD((R)->status, RMDS, ENP), \
! 324: GET_FIELD((R)->status, RMDS, BPE), \
! 325: GET_FIELD((R)->status, RMDS, PAM), \
! 326: GET_FIELD((R)->status, RMDS, LFAM), \
! 327: GET_FIELD((R)->status, RMDS, BAM), \
! 328: GET_FIELD((R)->buf_length, RMDL, ONES), \
! 329: 4096-GET_FIELD((R)->buf_length, RMDL, BCNT), \
! 330: GET_FIELD((R)->msg_length, RMDM, RCC), \
! 331: GET_FIELD((R)->msg_length, RMDM, RPC), \
! 332: GET_FIELD((R)->msg_length, RMDM, MCNT), \
! 333: GET_FIELD((R)->msg_length, RMDM, ZEROS))
1.1 root 334:
1.1.1.3 ! root 335: static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
1.1.1.2 root 336: target_phys_addr_t addr)
1.1 root 337: {
1.1.1.3 ! root 338: if (!BCR_SSIZE32(s)) {
! 339: struct {
! 340: uint32_t tbadr;
! 341: int16_t length;
! 342: int16_t status;
! 343: } xda;
! 344: s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
! 345: tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
! 346: tmd->length = le16_to_cpu(xda.length);
! 347: tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
! 348: tmd->misc = le16_to_cpu(xda.status) << 16;
! 349: tmd->res = 0;
1.1.1.2 root 350: } else {
1.1.1.3 ! root 351: s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
! 352: le32_to_cpus(&tmd->tbadr);
! 353: le16_to_cpus((uint16_t *)&tmd->length);
! 354: le16_to_cpus((uint16_t *)&tmd->status);
! 355: le32_to_cpus(&tmd->misc);
! 356: le32_to_cpus(&tmd->res);
! 357: if (BCR_SWSTYLE(s) == 3) {
! 358: uint32_t tmp = tmd->tbadr;
! 359: tmd->tbadr = tmd->misc;
! 360: tmd->misc = tmp;
1.1.1.2 root 361: }
1.1 root 362: }
363: }
364:
1.1.1.3 ! root 365: static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd,
1.1.1.2 root 366: target_phys_addr_t addr)
1.1 root 367: {
1.1.1.3 ! root 368: if (!BCR_SSIZE32(s)) {
! 369: struct {
! 370: uint32_t tbadr;
! 371: int16_t length;
! 372: int16_t status;
! 373: } xda;
! 374: xda.tbadr = cpu_to_le32((tmd->tbadr & 0xffffff) |
! 375: ((tmd->status & 0xff00) << 16));
! 376: xda.length = cpu_to_le16(tmd->length);
! 377: xda.status = cpu_to_le16(tmd->misc >> 16);
! 378: s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
1.1.1.2 root 379: } else {
1.1.1.3 ! root 380: struct {
! 381: uint32_t tbadr;
! 382: int16_t length;
! 383: int16_t status;
! 384: uint32_t misc;
! 385: uint32_t res;
! 386: } xda;
! 387: xda.tbadr = cpu_to_le32(tmd->tbadr);
! 388: xda.length = cpu_to_le16(tmd->length);
! 389: xda.status = cpu_to_le16(tmd->status);
! 390: xda.misc = cpu_to_le32(tmd->misc);
! 391: xda.res = cpu_to_le32(tmd->res);
! 392: if (BCR_SWSTYLE(s) == 3) {
! 393: uint32_t tmp = xda.tbadr;
! 394: xda.tbadr = xda.misc;
! 395: xda.misc = tmp;
1.1 root 396: }
1.1.1.3 ! root 397: s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
1.1 root 398: }
399: }
400:
1.1.1.3 ! root 401: static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
1.1.1.2 root 402: target_phys_addr_t addr)
1.1 root 403: {
1.1.1.3 ! root 404: if (!BCR_SSIZE32(s)) {
! 405: struct {
! 406: uint32_t rbadr;
! 407: int16_t buf_length;
! 408: int16_t msg_length;
! 409: } rda;
! 410: s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
! 411: rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
! 412: rmd->buf_length = le16_to_cpu(rda.buf_length);
! 413: rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
! 414: rmd->msg_length = le16_to_cpu(rda.msg_length);
! 415: rmd->res = 0;
1.1.1.2 root 416: } else {
1.1.1.3 ! root 417: s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
! 418: le32_to_cpus(&rmd->rbadr);
! 419: le16_to_cpus((uint16_t *)&rmd->buf_length);
! 420: le16_to_cpus((uint16_t *)&rmd->status);
! 421: le32_to_cpus(&rmd->msg_length);
! 422: le32_to_cpus(&rmd->res);
! 423: if (BCR_SWSTYLE(s) == 3) {
! 424: uint32_t tmp = rmd->rbadr;
! 425: rmd->rbadr = rmd->msg_length;
! 426: rmd->msg_length = tmp;
1.1.1.2 root 427: }
1.1 root 428: }
429: }
430:
1.1.1.3 ! root 431: static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
1.1.1.2 root 432: target_phys_addr_t addr)
1.1 root 433: {
1.1.1.3 ! root 434: if (!BCR_SSIZE32(s)) {
! 435: struct {
! 436: uint32_t rbadr;
! 437: int16_t buf_length;
! 438: int16_t msg_length;
! 439: } rda;
! 440: rda.rbadr = cpu_to_le32((rmd->rbadr & 0xffffff) |
! 441: ((rmd->status & 0xff00) << 16));
! 442: rda.buf_length = cpu_to_le16(rmd->buf_length);
! 443: rda.msg_length = cpu_to_le16(rmd->msg_length);
! 444: s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
1.1.1.2 root 445: } else {
1.1.1.3 ! root 446: struct {
! 447: uint32_t rbadr;
! 448: int16_t buf_length;
! 449: int16_t status;
! 450: uint32_t msg_length;
! 451: uint32_t res;
! 452: } rda;
! 453: rda.rbadr = cpu_to_le32(rmd->rbadr);
! 454: rda.buf_length = cpu_to_le16(rmd->buf_length);
! 455: rda.status = cpu_to_le16(rmd->status);
! 456: rda.msg_length = cpu_to_le32(rmd->msg_length);
! 457: rda.res = cpu_to_le32(rmd->res);
! 458: if (BCR_SWSTYLE(s) == 3) {
! 459: uint32_t tmp = rda.rbadr;
! 460: rda.rbadr = rda.msg_length;
! 461: rda.msg_length = tmp;
1.1 root 462: }
1.1.1.3 ! root 463: s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
1.1 root 464: }
465: }
466:
467:
468: #define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
469:
470: #define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
471:
472: #define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
473:
474: #define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
475:
476: #if 1
477:
478: #define CHECK_RMD(ADDR,RES) do { \
479: struct pcnet_RMD rmd; \
480: RMDLOAD(&rmd,(ADDR)); \
1.1.1.3 ! root 481: (RES) |= (GET_FIELD(rmd.buf_length, RMDL, ONES) != 15) \
! 482: || (GET_FIELD(rmd.msg_length, RMDM, ZEROS) != 0); \
1.1 root 483: } while (0)
484:
485: #define CHECK_TMD(ADDR,RES) do { \
486: struct pcnet_TMD tmd; \
487: TMDLOAD(&tmd,(ADDR)); \
1.1.1.3 ! root 488: (RES) |= (GET_FIELD(tmd.length, TMDL, ONES) != 15); \
1.1 root 489: } while (0)
490:
491: #else
492:
493: #define CHECK_RMD(ADDR,RES) do { \
494: switch (BCR_SWSTYLE(s)) { \
495: case 0x00: \
496: do { \
497: uint16_t rda[4]; \
1.1.1.3 ! root 498: s->phys_mem_read(s->dma_opaque, (ADDR), \
! 499: (void *)&rda[0], sizeof(rda), 0); \
1.1 root 500: (RES) |= (rda[2] & 0xf000)!=0xf000; \
501: (RES) |= (rda[3] & 0xf000)!=0x0000; \
502: } while (0); \
503: break; \
504: case 0x01: \
505: case 0x02: \
506: do { \
507: uint32_t rda[4]; \
1.1.1.3 ! root 508: s->phys_mem_read(s->dma_opaque, (ADDR), \
1.1.1.2 root 509: (void *)&rda[0], sizeof(rda), 0); \
1.1 root 510: (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
511: (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
512: } while (0); \
513: break; \
514: case 0x03: \
515: do { \
516: uint32_t rda[4]; \
1.1.1.3 ! root 517: s->phys_mem_read(s->dma_opaque, (ADDR), \
1.1.1.2 root 518: (void *)&rda[0], sizeof(rda), 0); \
1.1 root 519: (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
520: (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
521: } while (0); \
522: break; \
523: } \
524: } while (0)
525:
526: #define CHECK_TMD(ADDR,RES) do { \
527: switch (BCR_SWSTYLE(s)) { \
528: case 0x00: \
529: do { \
530: uint16_t xda[4]; \
1.1.1.3 ! root 531: s->phys_mem_read(s->dma_opaque, (ADDR), \
! 532: (void *)&xda[0], sizeof(xda), 0); \
! 533: (RES) |= (xda[2] & 0xf000)!=0xf000; \
1.1 root 534: } while (0); \
535: break; \
536: case 0x01: \
537: case 0x02: \
538: case 0x03: \
539: do { \
540: uint32_t xda[4]; \
1.1.1.3 ! root 541: s->phys_mem_read(s->dma_opaque, (ADDR), \
! 542: (void *)&xda[0], sizeof(xda), 0); \
1.1 root 543: (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
544: } while (0); \
545: break; \
546: } \
547: } while (0)
548:
549: #endif
550:
551: #define PRINT_PKTHDR(BUF) do { \
1.1.1.3 ! root 552: struct qemu_ether_header *hdr = (void *)(BUF); \
! 553: printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
! 554: "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
! 555: "type=0x%04x\n", \
1.1 root 556: hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
557: hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
558: hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
559: hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
1.1.1.3 ! root 560: be16_to_cpu(hdr->ether_type)); \
1.1 root 561: } while (0)
562:
563: #define MULTICAST_FILTER_LEN 8
564:
565: static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
566: {
567: #define LNC_POLYNOMIAL 0xEDB88320UL
568: uint32_t crc = 0xFFFFFFFF;
569: int idx, bit;
570: uint8_t data;
571:
572: for (idx = 0; idx < 6; idx++) {
573: for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
574: crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
575: data >>= 1;
576: }
577: }
578: return crc;
579: #undef LNC_POLYNOMIAL
580: }
581:
582: #define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
583:
584: /* generated using the AUTODIN II polynomial
585: * x^32 + x^26 + x^23 + x^22 + x^16 +
586: * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
587: */
588: static const uint32_t crctab[256] = {
589: 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
590: 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
591: 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
592: 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
593: 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
594: 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
595: 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
596: 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
597: 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
598: 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
599: 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
600: 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
601: 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
602: 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
603: 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
604: 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
605: 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
606: 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
607: 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
608: 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
609: 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
610: 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
611: 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
612: 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
613: 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
614: 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
615: 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
616: 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
617: 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
618: 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
619: 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
620: 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
621: 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
622: 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
623: 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
624: 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
625: 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
626: 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
627: 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
628: 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
629: 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
630: 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
631: 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
632: 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
633: 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
634: 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
635: 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
636: 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
637: 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
638: 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
639: 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
640: 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
641: 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
642: 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
643: 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
644: 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
645: 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
646: 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
647: 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
648: 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
649: 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
650: 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
651: 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
652: 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
653: };
654:
655: static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
656: {
657: struct qemu_ether_header *hdr = (void *)buf;
1.1.1.3 ! root 658: uint8_t padr[6] = {
1.1 root 659: s->csr[12] & 0xff, s->csr[12] >> 8,
660: s->csr[13] & 0xff, s->csr[13] >> 8,
1.1.1.3 ! root 661: s->csr[14] & 0xff, s->csr[14] >> 8
1.1 root 662: };
663: int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
664: #ifdef PCNET_DEBUG_MATCH
665: printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
666: "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
667: hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
668: hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
669: padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
670: printf("padr_match result=%d\n", result);
671: #endif
672: return result;
673: }
674:
675: static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
676: {
1.1.1.2 root 677: static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1.1 root 678: struct qemu_ether_header *hdr = (void *)buf;
679: int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
680: #ifdef PCNET_DEBUG_MATCH
681: printf("padr_bcast result=%d\n", result);
682: #endif
683: return result;
684: }
685:
686: static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
687: {
688: struct qemu_ether_header *hdr = (void *)buf;
1.1.1.3 ! root 689: if ((*(hdr->ether_dhost)&0x01) &&
1.1 root 690: ((uint64_t *)&s->csr[8])[0] != 0LL) {
1.1.1.3 ! root 691: uint8_t ladr[8] = {
1.1 root 692: s->csr[8] & 0xff, s->csr[8] >> 8,
693: s->csr[9] & 0xff, s->csr[9] >> 8,
1.1.1.3 ! root 694: s->csr[10] & 0xff, s->csr[10] >> 8,
! 695: s->csr[11] & 0xff, s->csr[11] >> 8
1.1 root 696: };
697: int index = lnc_mchash(hdr->ether_dhost) >> 26;
698: return !!(ladr[index >> 3] & (1 << (index & 7)));
699: }
700: return 0;
701: }
702:
1.1.1.3 ! root 703: static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx)
1.1 root 704: {
705: while (idx < 1) idx += CSR_RCVRL(s);
706: return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
707: }
708:
709: static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
710: {
1.1.1.3 ! root 711: int64_t next_time = current_time +
! 712: muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
1.1 root 713: ticks_per_sec, 33000000L);
714: if (next_time <= current_time)
715: next_time = current_time + 1;
716: return next_time;
717: }
718:
719: static void pcnet_poll(PCNetState *s);
720: static void pcnet_poll_timer(void *opaque);
721:
722: static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
723: static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
724: static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
725: static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
726:
727: static void pcnet_s_reset(PCNetState *s)
728: {
729: #ifdef PCNET_DEBUG
730: printf("pcnet_s_reset\n");
731: #endif
732:
733: s->lnkst = 0x40;
734: s->rdra = 0;
735: s->tdra = 0;
736: s->rap = 0;
1.1.1.3 ! root 737:
1.1 root 738: s->bcr[BCR_BSBC] &= ~0x0080;
739:
740: s->csr[0] = 0x0004;
741: s->csr[3] = 0x0000;
742: s->csr[4] = 0x0115;
743: s->csr[5] = 0x0000;
744: s->csr[6] = 0x0000;
745: s->csr[8] = 0;
746: s->csr[9] = 0;
747: s->csr[10] = 0;
748: s->csr[11] = 0;
749: s->csr[12] = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
750: s->csr[13] = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
751: s->csr[14] = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
752: s->csr[15] &= 0x21c4;
753: s->csr[72] = 1;
754: s->csr[74] = 1;
755: s->csr[76] = 1;
756: s->csr[78] = 1;
757: s->csr[80] = 0x1410;
758: s->csr[88] = 0x1003;
759: s->csr[89] = 0x0262;
760: s->csr[94] = 0x0000;
761: s->csr[100] = 0x0200;
762: s->csr[103] = 0x0105;
763: s->csr[103] = 0x0105;
764: s->csr[112] = 0x0000;
765: s->csr[114] = 0x0000;
766: s->csr[122] = 0x0000;
767: s->csr[124] = 0x0000;
768:
769: s->tx_busy = 0;
770: }
771:
772: static void pcnet_update_irq(PCNetState *s)
773: {
774: int isr = 0;
775: s->csr[0] &= ~0x0080;
1.1.1.3 ! root 776:
1.1 root 777: #if 1
778: if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
779: (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
780: (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
781: #else
782: if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
783: (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
784: (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
785: (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
786: (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
787: (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
788: (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
789: (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
790: (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
791: (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
792: (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
793: (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
794: #endif
795: {
1.1.1.3 ! root 796:
1.1 root 797: isr = CSR_INEA(s);
798: s->csr[0] |= 0x0080;
799: }
1.1.1.3 ! root 800:
1.1 root 801: if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
802: s->csr[4] &= ~0x0080;
803: s->csr[4] |= 0x0040;
804: s->csr[0] |= 0x0080;
805: isr = 1;
806: #ifdef PCNET_DEBUG
807: printf("pcnet user int\n");
808: #endif
809: }
810:
811: #if 1
1.1.1.3 ! root 812: if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
1.1 root 813: #else
814: if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
815: (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
816: #endif
817: {
818: isr = 1;
819: s->csr[0] |= 0x0080;
820: }
821:
822: if (isr != s->isr) {
823: #ifdef PCNET_DEBUG
824: printf("pcnet: INTA=%d\n", isr);
825: #endif
826: }
1.1.1.3 ! root 827: qemu_set_irq(s->irq, isr);
1.1.1.2 root 828: s->isr = isr;
1.1 root 829: }
830:
831: static void pcnet_init(PCNetState *s)
832: {
1.1.1.2 root 833: int rlen, tlen;
1.1.1.3 ! root 834: uint16_t padr[3], ladrf[4], mode;
1.1.1.2 root 835: uint32_t rdra, tdra;
836:
1.1 root 837: #ifdef PCNET_DEBUG
838: printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
839: #endif
1.1.1.3 ! root 840:
1.1 root 841: if (BCR_SSIZE32(s)) {
842: struct pcnet_initblk32 initblk;
1.1.1.2 root 843: s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
844: (uint8_t *)&initblk, sizeof(initblk), 0);
1.1.1.3 ! root 845: mode = le16_to_cpu(initblk.mode);
1.1.1.2 root 846: rlen = initblk.rlen >> 4;
847: tlen = initblk.tlen >> 4;
1.1.1.3 ! root 848: ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
! 849: ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
! 850: ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
! 851: ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
! 852: padr[0] = le16_to_cpu(initblk.padr[0]);
! 853: padr[1] = le16_to_cpu(initblk.padr[1]);
! 854: padr[2] = le16_to_cpu(initblk.padr[2]);
1.1.1.2 root 855: rdra = le32_to_cpu(initblk.rdra);
856: tdra = le32_to_cpu(initblk.tdra);
1.1 root 857: } else {
858: struct pcnet_initblk16 initblk;
1.1.1.2 root 859: s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
860: (uint8_t *)&initblk, sizeof(initblk), 0);
1.1.1.3 ! root 861: mode = le16_to_cpu(initblk.mode);
! 862: ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
! 863: ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
! 864: ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
! 865: ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
! 866: padr[0] = le16_to_cpu(initblk.padr[0]);
! 867: padr[1] = le16_to_cpu(initblk.padr[1]);
! 868: padr[2] = le16_to_cpu(initblk.padr[2]);
1.1.1.2 root 869: rdra = le32_to_cpu(initblk.rdra);
870: tdra = le32_to_cpu(initblk.tdra);
871: rlen = rdra >> 29;
872: tlen = tdra >> 29;
873: rdra &= 0x00ffffff;
874: tdra &= 0x00ffffff;
1.1 root 875: }
1.1.1.3 ! root 876:
1.1.1.2 root 877: #if defined(PCNET_DEBUG)
1.1.1.3 ! root 878: printf("rlen=%d tlen=%d\n", rlen, tlen);
1.1.1.2 root 879: #endif
1.1.1.3 ! root 880:
1.1.1.2 root 881: CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
882: CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
883: s->csr[ 6] = (tlen << 12) | (rlen << 8);
1.1.1.3 ! root 884: s->csr[15] = mode;
! 885: s->csr[ 8] = ladrf[0];
! 886: s->csr[ 9] = ladrf[1];
! 887: s->csr[10] = ladrf[2];
! 888: s->csr[11] = ladrf[3];
! 889: s->csr[12] = padr[0];
! 890: s->csr[13] = padr[1];
! 891: s->csr[14] = padr[2];
1.1.1.2 root 892: s->rdra = PHYSADDR(s, rdra);
893: s->tdra = PHYSADDR(s, tdra);
1.1 root 894:
895: CSR_RCVRC(s) = CSR_RCVRL(s);
896: CSR_XMTRC(s) = CSR_XMTRL(s);
897:
898: #ifdef PCNET_DEBUG
1.1.1.3 ! root 899: printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
1.1 root 900: BCR_SSIZE32(s),
901: s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
902: #endif
903:
1.1.1.3 ! root 904: s->csr[0] |= 0x0101;
1.1 root 905: s->csr[0] &= ~0x0004; /* clear STOP bit */
906: }
907:
908: static void pcnet_start(PCNetState *s)
909: {
910: #ifdef PCNET_DEBUG
911: printf("pcnet_start\n");
912: #endif
913:
914: if (!CSR_DTX(s))
915: s->csr[0] |= 0x0010; /* set TXON */
1.1.1.3 ! root 916:
1.1 root 917: if (!CSR_DRX(s))
918: s->csr[0] |= 0x0020; /* set RXON */
919:
920: s->csr[0] &= ~0x0004; /* clear STOP bit */
921: s->csr[0] |= 0x0002;
922: }
923:
924: static void pcnet_stop(PCNetState *s)
925: {
926: #ifdef PCNET_DEBUG
927: printf("pcnet_stop\n");
928: #endif
929: s->csr[0] &= ~0x7feb;
930: s->csr[0] |= 0x0014;
931: s->csr[4] &= ~0x02c2;
932: s->csr[5] &= ~0x0011;
933: pcnet_poll_timer(s);
934: }
935:
936: static void pcnet_rdte_poll(PCNetState *s)
937: {
938: s->csr[28] = s->csr[29] = 0;
939: if (s->rdra) {
940: int bad = 0;
941: #if 1
942: target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
943: target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
944: target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
945: #else
1.1.1.3 ! root 946: target_phys_addr_t crda = s->rdra +
1.1 root 947: (CSR_RCVRL(s) - CSR_RCVRC(s)) *
948: (BCR_SWSTYLE(s) ? 16 : 8 );
949: int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
1.1.1.3 ! root 950: target_phys_addr_t nrda = s->rdra +
1.1 root 951: (CSR_RCVRL(s) - nrdc) *
952: (BCR_SWSTYLE(s) ? 16 : 8 );
953: int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
1.1.1.3 ! root 954: target_phys_addr_t nnrd = s->rdra +
1.1 root 955: (CSR_RCVRL(s) - nnrc) *
956: (BCR_SWSTYLE(s) ? 16 : 8 );
957: #endif
958:
959: CHECK_RMD(PHYSADDR(s,crda), bad);
960: if (!bad) {
961: CHECK_RMD(PHYSADDR(s,nrda), bad);
962: if (bad || (nrda == crda)) nrda = 0;
963: CHECK_RMD(PHYSADDR(s,nnrd), bad);
964: if (bad || (nnrd == crda)) nnrd = 0;
965:
966: s->csr[28] = crda & 0xffff;
967: s->csr[29] = crda >> 16;
968: s->csr[26] = nrda & 0xffff;
969: s->csr[27] = nrda >> 16;
970: s->csr[36] = nnrd & 0xffff;
971: s->csr[37] = nnrd >> 16;
972: #ifdef PCNET_DEBUG
973: if (bad) {
974: printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
975: PHYSADDR(s,crda));
976: }
977: } else {
978: printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
979: #endif
980: }
981: }
1.1.1.3 ! root 982:
1.1 root 983: if (CSR_CRDA(s)) {
984: struct pcnet_RMD rmd;
985: RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
1.1.1.3 ! root 986: CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
! 987: CSR_CRST(s) = rmd.status;
1.1 root 988: #ifdef PCNET_DEBUG_RMD_X
1.1.1.3 ! root 989: printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
1.1 root 990: PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
1.1.1.3 ! root 991: rmd.buf_length, rmd.status, rmd.msg_length);
1.1 root 992: PRINT_RMD(&rmd);
993: #endif
994: } else {
995: CSR_CRBC(s) = CSR_CRST(s) = 0;
996: }
1.1.1.3 ! root 997:
1.1 root 998: if (CSR_NRDA(s)) {
999: struct pcnet_RMD rmd;
1000: RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
1.1.1.3 ! root 1001: CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
! 1002: CSR_NRST(s) = rmd.status;
1.1 root 1003: } else {
1004: CSR_NRBC(s) = CSR_NRST(s) = 0;
1005: }
1006:
1007: }
1008:
1009: static int pcnet_tdte_poll(PCNetState *s)
1010: {
1011: s->csr[34] = s->csr[35] = 0;
1012: if (s->tdra) {
1.1.1.3 ! root 1013: target_phys_addr_t cxda = s->tdra +
1.1 root 1014: (CSR_XMTRL(s) - CSR_XMTRC(s)) *
1.1.1.3 ! root 1015: (BCR_SWSTYLE(s) ? 16 : 8);
1.1 root 1016: int bad = 0;
1017: CHECK_TMD(PHYSADDR(s, cxda),bad);
1018: if (!bad) {
1019: if (CSR_CXDA(s) != cxda) {
1020: s->csr[60] = s->csr[34];
1021: s->csr[61] = s->csr[35];
1022: s->csr[62] = CSR_CXBC(s);
1023: s->csr[63] = CSR_CXST(s);
1024: }
1025: s->csr[34] = cxda & 0xffff;
1026: s->csr[35] = cxda >> 16;
1.1.1.3 ! root 1027: #ifdef PCNET_DEBUG_X
1.1 root 1028: printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
1029: #endif
1030: }
1031: }
1032:
1033: if (CSR_CXDA(s)) {
1034: struct pcnet_TMD tmd;
1035:
1.1.1.3 ! root 1036: TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1.1 root 1037:
1.1.1.3 ! root 1038: CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
! 1039: CSR_CXST(s) = tmd.status;
1.1 root 1040: } else {
1041: CSR_CXBC(s) = CSR_CXST(s) = 0;
1042: }
1.1.1.3 ! root 1043:
1.1 root 1044: return !!(CSR_CXST(s) & 0x8000);
1045: }
1046:
1047: static int pcnet_can_receive(void *opaque)
1048: {
1049: PCNetState *s = opaque;
1050: if (CSR_STOP(s) || CSR_SPND(s))
1051: return 0;
1.1.1.3 ! root 1052:
1.1 root 1053: if (s->recv_pos > 0)
1054: return 0;
1055:
1056: return sizeof(s->buffer)-16;
1057: }
1058:
1059: #define MIN_BUF_SIZE 60
1060:
1061: static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
1062: {
1063: PCNetState *s = opaque;
1064: int is_padr = 0, is_bcast = 0, is_ladr = 0;
1065: uint8_t buf1[60];
1066:
1067: if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
1068: return;
1069:
1070: #ifdef PCNET_DEBUG
1071: printf("pcnet_receive size=%d\n", size);
1072: #endif
1073:
1074: /* if too small buffer, then expand it */
1075: if (size < MIN_BUF_SIZE) {
1076: memcpy(buf1, buf, size);
1077: memset(buf1 + size, 0, MIN_BUF_SIZE - size);
1078: buf = buf1;
1079: size = MIN_BUF_SIZE;
1080: }
1081:
1.1.1.3 ! root 1082: if (CSR_PROM(s)
! 1083: || (is_padr=padr_match(s, buf, size))
1.1 root 1084: || (is_bcast=padr_bcast(s, buf, size))
1085: || (is_ladr=ladr_match(s, buf, size))) {
1086:
1087: pcnet_rdte_poll(s);
1088:
1089: if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1090: struct pcnet_RMD rmd;
1091: int rcvrc = CSR_RCVRC(s)-1,i;
1092: target_phys_addr_t nrda;
1093: for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1094: if (rcvrc <= 1)
1095: rcvrc = CSR_RCVRL(s);
1096: nrda = s->rdra +
1097: (CSR_RCVRL(s) - rcvrc) *
1098: (BCR_SWSTYLE(s) ? 16 : 8 );
1.1.1.3 ! root 1099: RMDLOAD(&rmd, PHYSADDR(s,nrda));
! 1100: if (GET_FIELD(rmd.status, RMDS, OWN)) {
1.1 root 1101: #ifdef PCNET_DEBUG_RMD
1.1.1.3 ! root 1102: printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1.1 root 1103: rcvrc, CSR_RCVRC(s));
1104: #endif
1105: CSR_RCVRC(s) = rcvrc;
1106: pcnet_rdte_poll(s);
1107: break;
1108: }
1109: }
1110: }
1111:
1112: if (!(CSR_CRST(s) & 0x8000)) {
1113: #ifdef PCNET_DEBUG_RMD
1114: printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1115: #endif
1116: s->csr[0] |= 0x1000; /* Set MISS flag */
1117: CSR_MISSC(s)++;
1118: } else {
1119: uint8_t *src = &s->buffer[8];
1120: target_phys_addr_t crda = CSR_CRDA(s);
1121: struct pcnet_RMD rmd;
1122: int pktcount = 0;
1123:
1124: memcpy(src, buf, size);
1.1.1.3 ! root 1125:
1.1 root 1126: #if 1
1127: /* no need to compute the CRC */
1128: src[size] = 0;
1129: src[size + 1] = 0;
1130: src[size + 2] = 0;
1131: src[size + 3] = 0;
1132: size += 4;
1133: #else
1134: /* XXX: avoid CRC generation */
1135: if (!CSR_ASTRP_RCV(s)) {
1136: uint32_t fcs = ~0;
1137: uint8_t *p = src;
1138:
1139: while (size < 46) {
1140: src[size++] = 0;
1141: }
1.1.1.3 ! root 1142:
1.1 root 1143: while (p != &src[size]) {
1144: CRC(fcs, *p++);
1145: }
1146: ((uint32_t *)&src[size])[0] = htonl(fcs);
1147: size += 4; /* FCS at end of packet */
1148: } else size += 4;
1149: #endif
1150:
1151: #ifdef PCNET_DEBUG_MATCH
1152: PRINT_PKTHDR(buf);
1153: #endif
1154:
1155: RMDLOAD(&rmd, PHYSADDR(s,crda));
1156: /*if (!CSR_LAPPEN(s))*/
1.1.1.3 ! root 1157: SET_FIELD(&rmd.status, RMDS, STP, 1);
1.1 root 1158:
1159: #define PCNET_RECV_STORE() do { \
1.1.1.3 ! root 1160: int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),size); \
! 1161: target_phys_addr_t rbadr = PHYSADDR(s, rmd.rbadr); \
! 1162: s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
1.1 root 1163: src += count; size -= count; \
1.1.1.3 ! root 1164: SET_FIELD(&rmd.msg_length, RMDM, MCNT, count); \
! 1165: SET_FIELD(&rmd.status, RMDS, OWN, 0); \
1.1 root 1166: RMDSTORE(&rmd, PHYSADDR(s,crda)); \
1167: pktcount++; \
1168: } while (0)
1169:
1170: PCNET_RECV_STORE();
1171: if ((size > 0) && CSR_NRDA(s)) {
1172: target_phys_addr_t nrda = CSR_NRDA(s);
1173: RMDLOAD(&rmd, PHYSADDR(s,nrda));
1.1.1.3 ! root 1174: if (GET_FIELD(rmd.status, RMDS, OWN)) {
1.1 root 1175: crda = nrda;
1176: PCNET_RECV_STORE();
1177: if ((size > 0) && (nrda=CSR_NNRD(s))) {
1178: RMDLOAD(&rmd, PHYSADDR(s,nrda));
1.1.1.3 ! root 1179: if (GET_FIELD(rmd.status, RMDS, OWN)) {
1.1 root 1180: crda = nrda;
1181: PCNET_RECV_STORE();
1182: }
1183: }
1.1.1.3 ! root 1184: }
1.1 root 1185: }
1186:
1187: #undef PCNET_RECV_STORE
1188:
1189: RMDLOAD(&rmd, PHYSADDR(s,crda));
1190: if (size == 0) {
1.1.1.3 ! root 1191: SET_FIELD(&rmd.status, RMDS, ENP, 1);
! 1192: SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
! 1193: SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
! 1194: SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
1.1 root 1195: } else {
1.1.1.3 ! root 1196: SET_FIELD(&rmd.status, RMDS, OFLO, 1);
! 1197: SET_FIELD(&rmd.status, RMDS, BUFF, 1);
! 1198: SET_FIELD(&rmd.status, RMDS, ERR, 1);
1.1 root 1199: }
1200: RMDSTORE(&rmd, PHYSADDR(s,crda));
1201: s->csr[0] |= 0x0400;
1202:
1203: #ifdef PCNET_DEBUG
1.1.1.3 ! root 1204: printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1.1 root 1205: CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1206: #endif
1207: #ifdef PCNET_DEBUG_RMD
1208: PRINT_RMD(&rmd);
1.1.1.3 ! root 1209: #endif
1.1 root 1210:
1211: while (pktcount--) {
1212: if (CSR_RCVRC(s) <= 1)
1213: CSR_RCVRC(s) = CSR_RCVRL(s);
1214: else
1.1.1.3 ! root 1215: CSR_RCVRC(s)--;
1.1 root 1216: }
1.1.1.3 ! root 1217:
1.1 root 1218: pcnet_rdte_poll(s);
1219:
1.1.1.3 ! root 1220: }
1.1 root 1221: }
1222:
1223: pcnet_poll(s);
1.1.1.3 ! root 1224: pcnet_update_irq(s);
1.1 root 1225: }
1226:
1227: static void pcnet_transmit(PCNetState *s)
1228: {
1229: target_phys_addr_t xmit_cxda = 0;
1230: int count = CSR_XMTRL(s)-1;
1231: s->xmit_pos = -1;
1.1.1.3 ! root 1232:
1.1 root 1233: if (!CSR_TXON(s)) {
1234: s->csr[0] &= ~0x0008;
1235: return;
1236: }
1237:
1238: s->tx_busy = 1;
1239:
1240: txagain:
1241: if (pcnet_tdte_poll(s)) {
1242: struct pcnet_TMD tmd;
1243:
1.1.1.3 ! root 1244: TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1.1 root 1245:
1246: #ifdef PCNET_DEBUG_TMD
1247: printf(" TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1248: PRINT_TMD(&tmd);
1249: #endif
1.1.1.3 ! root 1250: if (GET_FIELD(tmd.status, TMDS, STP)) {
! 1251: s->xmit_pos = 0;
! 1252: if (!GET_FIELD(tmd.status, TMDS, ENP)) {
! 1253: int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
! 1254: s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
! 1255: s->buffer, bcnt, CSR_BSWP(s));
! 1256: s->xmit_pos += bcnt;
! 1257: }
1.1 root 1258: xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1259: }
1.1.1.3 ! root 1260: if (GET_FIELD(tmd.status, TMDS, ENP) && (s->xmit_pos >= 0)) {
! 1261: int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
! 1262: s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
! 1263: s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
! 1264: s->xmit_pos += bcnt;
1.1 root 1265: #ifdef PCNET_DEBUG
1266: printf("pcnet_transmit size=%d\n", s->xmit_pos);
1.1.1.3 ! root 1267: #endif
1.1 root 1268: if (CSR_LOOP(s))
1269: pcnet_receive(s, s->buffer, s->xmit_pos);
1270: else
1.1.1.3 ! root 1271: if (s->vc)
! 1272: qemu_send_packet(s->vc, s->buffer, s->xmit_pos);
1.1 root 1273:
1274: s->csr[0] &= ~0x0008; /* clear TDMD */
1275: s->csr[4] |= 0x0004; /* set TXSTRT */
1276: s->xmit_pos = -1;
1277: }
1278:
1.1.1.3 ! root 1279: SET_FIELD(&tmd.status, TMDS, OWN, 0);
1.1 root 1280: TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1.1.1.3 ! root 1281: if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
1.1 root 1282: s->csr[0] |= 0x0200; /* set TINT */
1283:
1284: if (CSR_XMTRC(s)<=1)
1285: CSR_XMTRC(s) = CSR_XMTRL(s);
1286: else
1287: CSR_XMTRC(s)--;
1288: if (count--)
1289: goto txagain;
1290:
1.1.1.3 ! root 1291: } else
1.1 root 1292: if (s->xmit_pos >= 0) {
1293: struct pcnet_TMD tmd;
1.1.1.3 ! root 1294: TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));
! 1295: SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
! 1296: SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
! 1297: SET_FIELD(&tmd.status, TMDS, ERR, 1);
! 1298: SET_FIELD(&tmd.status, TMDS, OWN, 0);
1.1 root 1299: TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
1300: s->csr[0] |= 0x0200; /* set TINT */
1301: if (!CSR_DXSUFLO(s)) {
1302: s->csr[0] &= ~0x0010;
1303: } else
1304: if (count--)
1305: goto txagain;
1306: }
1307:
1308: s->tx_busy = 0;
1309: }
1310:
1311: static void pcnet_poll(PCNetState *s)
1312: {
1313: if (CSR_RXON(s)) {
1314: pcnet_rdte_poll(s);
1315: }
1316:
1.1.1.3 ! root 1317: if (CSR_TDMD(s) ||
1.1 root 1318: (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1319: {
1320: /* prevent recursion */
1321: if (s->tx_busy)
1322: return;
1323:
1324: pcnet_transmit(s);
1325: }
1326: }
1327:
1328: static void pcnet_poll_timer(void *opaque)
1329: {
1330: PCNetState *s = opaque;
1331:
1332: qemu_del_timer(s->poll_timer);
1333:
1334: if (CSR_TDMD(s)) {
1335: pcnet_transmit(s);
1336: }
1337:
1.1.1.3 ! root 1338: pcnet_update_irq(s);
1.1 root 1339:
1340: if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1341: uint64_t now = qemu_get_clock(vm_clock) * 33;
1342: if (!s->timer || !now)
1343: s->timer = now;
1344: else {
1345: uint64_t t = now - s->timer + CSR_POLL(s);
1346: if (t > 0xffffLL) {
1347: pcnet_poll(s);
1348: CSR_POLL(s) = CSR_PINT(s);
1349: } else
1350: CSR_POLL(s) = t;
1351: }
1.1.1.3 ! root 1352: qemu_mod_timer(s->poll_timer,
1.1 root 1353: pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
1354: }
1355: }
1356:
1357:
1358: static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1359: {
1360: uint16_t val = new_value;
1361: #ifdef PCNET_DEBUG_CSR
1362: printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1363: #endif
1364: switch (rap) {
1365: case 0:
1366: s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1367:
1368: s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1369:
1370: val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1371:
1372: /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1373: if ((val&7) == 7)
1374: val &= ~3;
1375:
1376: if (!CSR_STOP(s) && (val & 4))
1377: pcnet_stop(s);
1378:
1379: if (!CSR_INIT(s) && (val & 1))
1380: pcnet_init(s);
1381:
1382: if (!CSR_STRT(s) && (val & 2))
1383: pcnet_start(s);
1384:
1.1.1.3 ! root 1385: if (CSR_TDMD(s))
1.1 root 1386: pcnet_transmit(s);
1387:
1388: return;
1389: case 1:
1390: case 2:
1391: case 8:
1392: case 9:
1393: case 10:
1394: case 11:
1395: case 12:
1396: case 13:
1397: case 14:
1398: case 15:
1399: case 18: /* CRBAL */
1400: case 19: /* CRBAU */
1401: case 20: /* CXBAL */
1402: case 21: /* CXBAU */
1403: case 22: /* NRBAU */
1404: case 23: /* NRBAU */
1405: case 24:
1406: case 25:
1407: case 26:
1408: case 27:
1409: case 28:
1410: case 29:
1411: case 30:
1412: case 31:
1413: case 32:
1414: case 33:
1415: case 34:
1416: case 35:
1417: case 36:
1418: case 37:
1419: case 38:
1420: case 39:
1421: case 40: /* CRBC */
1422: case 41:
1423: case 42: /* CXBC */
1424: case 43:
1425: case 44:
1426: case 45:
1427: case 46: /* POLL */
1428: case 47: /* POLLINT */
1429: case 72:
1430: case 74:
1431: case 76: /* RCVRL */
1432: case 78: /* XMTRL */
1433: case 112:
1434: if (CSR_STOP(s) || CSR_SPND(s))
1435: break;
1436: return;
1437: case 3:
1438: break;
1439: case 4:
1.1.1.3 ! root 1440: s->csr[4] &= ~(val & 0x026a);
1.1 root 1441: val &= ~0x026a; val |= s->csr[4] & 0x026a;
1442: break;
1443: case 5:
1.1.1.3 ! root 1444: s->csr[5] &= ~(val & 0x0a90);
1.1 root 1445: val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1446: break;
1447: case 16:
1448: pcnet_csr_writew(s,1,val);
1449: return;
1450: case 17:
1451: pcnet_csr_writew(s,2,val);
1452: return;
1453: case 58:
1454: pcnet_bcr_writew(s,BCR_SWS,val);
1455: break;
1456: default:
1457: return;
1458: }
1459: s->csr[rap] = val;
1460: }
1461:
1462: static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1463: {
1464: uint32_t val;
1465: switch (rap) {
1466: case 0:
1467: pcnet_update_irq(s);
1468: val = s->csr[0];
1469: val |= (val & 0x7800) ? 0x8000 : 0;
1470: break;
1471: case 16:
1472: return pcnet_csr_readw(s,1);
1473: case 17:
1474: return pcnet_csr_readw(s,2);
1475: case 58:
1476: return pcnet_bcr_readw(s,BCR_SWS);
1477: case 88:
1478: val = s->csr[89];
1479: val <<= 16;
1480: val |= s->csr[88];
1481: break;
1482: default:
1483: val = s->csr[rap];
1484: }
1485: #ifdef PCNET_DEBUG_CSR
1486: printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1487: #endif
1488: return val;
1489: }
1490:
1491: static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1492: {
1493: rap &= 127;
1494: #ifdef PCNET_DEBUG_BCR
1495: printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1496: #endif
1497: switch (rap) {
1498: case BCR_SWS:
1499: if (!(CSR_STOP(s) || CSR_SPND(s)))
1500: return;
1501: val &= ~0x0300;
1502: switch (val & 0x00ff) {
1503: case 0:
1504: val |= 0x0200;
1505: break;
1506: case 1:
1507: val |= 0x0100;
1508: break;
1509: case 2:
1510: case 3:
1511: val |= 0x0300;
1512: break;
1513: default:
1514: printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1515: val = 0x0200;
1516: break;
1517: }
1518: #ifdef PCNET_DEBUG
1519: printf("BCR_SWS=0x%04x\n", val);
1520: #endif
1521: case BCR_LNKST:
1522: case BCR_LED1:
1523: case BCR_LED2:
1524: case BCR_LED3:
1525: case BCR_MC:
1526: case BCR_FDC:
1527: case BCR_BSBC:
1528: case BCR_EECAS:
1529: case BCR_PLAT:
1530: s->bcr[rap] = val;
1531: break;
1532: default:
1533: break;
1534: }
1535: }
1536:
1537: static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1538: {
1539: uint32_t val;
1540: rap &= 127;
1541: switch (rap) {
1542: case BCR_LNKST:
1543: case BCR_LED1:
1544: case BCR_LED2:
1545: case BCR_LED3:
1546: val = s->bcr[rap] & ~0x8000;
1547: val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1548: break;
1549: default:
1550: val = rap < 32 ? s->bcr[rap] : 0;
1551: break;
1552: }
1553: #ifdef PCNET_DEBUG_BCR
1554: printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1555: #endif
1556: return val;
1557: }
1558:
1.1.1.3 ! root 1559: static void pcnet_h_reset(void *opaque)
1.1 root 1560: {
1.1.1.2 root 1561: PCNetState *s = opaque;
1.1 root 1562: int i;
1563: uint16_t checksum;
1564:
1565: /* Initialize the PROM */
1566:
1.1.1.3 ! root 1567: if (s->nd)
! 1568: memcpy(s->prom, s->nd->macaddr, 6);
1.1 root 1569: s->prom[12] = s->prom[13] = 0x00;
1570: s->prom[14] = s->prom[15] = 0x57;
1571:
1572: for (i = 0,checksum = 0; i < 16; i++)
1573: checksum += s->prom[i];
1574: *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1575:
1576:
1577: s->bcr[BCR_MSRDA] = 0x0005;
1578: s->bcr[BCR_MSWRA] = 0x0005;
1579: s->bcr[BCR_MC ] = 0x0002;
1580: s->bcr[BCR_LNKST] = 0x00c0;
1581: s->bcr[BCR_LED1 ] = 0x0084;
1582: s->bcr[BCR_LED2 ] = 0x0088;
1583: s->bcr[BCR_LED3 ] = 0x0090;
1584: s->bcr[BCR_FDC ] = 0x0000;
1585: s->bcr[BCR_BSBC ] = 0x9001;
1586: s->bcr[BCR_EECAS] = 0x0002;
1587: s->bcr[BCR_SWS ] = 0x0200;
1588: s->bcr[BCR_PLAT ] = 0xff06;
1589:
1590: pcnet_s_reset(s);
1591: }
1592:
1593: static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
1594: {
1595: PCNetState *s = opaque;
1596: #ifdef PCNET_DEBUG
1597: printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
1.1.1.3 ! root 1598: #endif
1.1 root 1599: /* Check APROMWE bit to enable write access */
1600: if (pcnet_bcr_readw(s,2) & 0x80)
1601: s->prom[addr & 15] = val;
1.1.1.3 ! root 1602: }
1.1 root 1603:
1604: static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
1605: {
1606: PCNetState *s = opaque;
1607: uint32_t val = s->prom[addr &= 15];
1608: #ifdef PCNET_DEBUG
1609: printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
1610: #endif
1611: return val;
1612: }
1613:
1614: static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1615: {
1616: PCNetState *s = opaque;
1617: pcnet_poll_timer(s);
1618: #ifdef PCNET_DEBUG_IO
1619: printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1620: #endif
1621: if (!BCR_DWIO(s)) {
1622: switch (addr & 0x0f) {
1623: case 0x00: /* RDP */
1624: pcnet_csr_writew(s, s->rap, val);
1625: break;
1626: case 0x02:
1627: s->rap = val & 0x7f;
1628: break;
1629: case 0x06:
1630: pcnet_bcr_writew(s, s->rap, val);
1631: break;
1632: }
1633: }
1634: pcnet_update_irq(s);
1635: }
1636:
1637: static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1638: {
1639: PCNetState *s = opaque;
1640: uint32_t val = -1;
1641: pcnet_poll_timer(s);
1642: if (!BCR_DWIO(s)) {
1643: switch (addr & 0x0f) {
1644: case 0x00: /* RDP */
1645: val = pcnet_csr_readw(s, s->rap);
1646: break;
1647: case 0x02:
1648: val = s->rap;
1649: break;
1650: case 0x04:
1651: pcnet_s_reset(s);
1652: val = 0;
1653: break;
1654: case 0x06:
1655: val = pcnet_bcr_readw(s, s->rap);
1656: break;
1657: }
1658: }
1659: pcnet_update_irq(s);
1660: #ifdef PCNET_DEBUG_IO
1661: printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1662: #endif
1663: return val;
1664: }
1665:
1666: static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1667: {
1668: PCNetState *s = opaque;
1669: pcnet_poll_timer(s);
1670: #ifdef PCNET_DEBUG_IO
1671: printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1672: #endif
1673: if (BCR_DWIO(s)) {
1674: switch (addr & 0x0f) {
1675: case 0x00: /* RDP */
1676: pcnet_csr_writew(s, s->rap, val & 0xffff);
1677: break;
1678: case 0x04:
1679: s->rap = val & 0x7f;
1680: break;
1681: case 0x0c:
1682: pcnet_bcr_writew(s, s->rap, val & 0xffff);
1683: break;
1684: }
1685: } else
1686: if ((addr & 0x0f) == 0) {
1687: /* switch device to dword i/o mode */
1688: pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1689: #ifdef PCNET_DEBUG_IO
1690: printf("device switched into dword i/o mode\n");
1.1.1.3 ! root 1691: #endif
1.1 root 1692: }
1693: pcnet_update_irq(s);
1694: }
1695:
1696: static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1697: {
1698: PCNetState *s = opaque;
1699: uint32_t val = -1;
1700: pcnet_poll_timer(s);
1.1.1.3 ! root 1701: if (BCR_DWIO(s)) {
1.1 root 1702: switch (addr & 0x0f) {
1703: case 0x00: /* RDP */
1704: val = pcnet_csr_readw(s, s->rap);
1705: break;
1706: case 0x04:
1707: val = s->rap;
1708: break;
1709: case 0x08:
1710: pcnet_s_reset(s);
1711: val = 0;
1712: break;
1713: case 0x0c:
1714: val = pcnet_bcr_readw(s, s->rap);
1715: break;
1716: }
1717: }
1718: pcnet_update_irq(s);
1719: #ifdef PCNET_DEBUG_IO
1720: printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1721: #endif
1722: return val;
1723: }
1724:
1.1.1.3 ! root 1725: static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
1.1 root 1726: uint32_t addr, uint32_t size, int type)
1727: {
1728: PCNetState *d = (PCNetState *)pci_dev;
1729:
1730: #ifdef PCNET_DEBUG_IO
1731: printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
1732: #endif
1733:
1734: register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
1735: register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
1.1.1.3 ! root 1736:
1.1 root 1737: register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
1738: register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
1739: register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
1740: register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
1741: }
1742:
1743: static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1744: {
1745: PCNetState *d = opaque;
1746: #ifdef PCNET_DEBUG_IO
1747: printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
1748: #endif
1749: if (!(addr & 0x10))
1750: pcnet_aprom_writeb(d, addr & 0x0f, val);
1751: }
1752:
1.1.1.3 ! root 1753: static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
1.1 root 1754: {
1755: PCNetState *d = opaque;
1756: uint32_t val = -1;
1757: if (!(addr & 0x10))
1758: val = pcnet_aprom_readb(d, addr & 0x0f);
1759: #ifdef PCNET_DEBUG_IO
1760: printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
1761: #endif
1762: return val;
1763: }
1764:
1765: static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1766: {
1767: PCNetState *d = opaque;
1768: #ifdef PCNET_DEBUG_IO
1769: printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
1770: #endif
1771: if (addr & 0x10)
1772: pcnet_ioport_writew(d, addr & 0x0f, val);
1773: else {
1774: addr &= 0x0f;
1775: pcnet_aprom_writeb(d, addr, val & 0xff);
1776: pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1777: }
1778: }
1779:
1.1.1.3 ! root 1780: static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
1.1 root 1781: {
1782: PCNetState *d = opaque;
1783: uint32_t val = -1;
1784: if (addr & 0x10)
1785: val = pcnet_ioport_readw(d, addr & 0x0f);
1786: else {
1787: addr &= 0x0f;
1788: val = pcnet_aprom_readb(d, addr+1);
1789: val <<= 8;
1790: val |= pcnet_aprom_readb(d, addr);
1791: }
1792: #ifdef PCNET_DEBUG_IO
1793: printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
1794: #endif
1795: return val;
1796: }
1797:
1798: static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1799: {
1800: PCNetState *d = opaque;
1801: #ifdef PCNET_DEBUG_IO
1802: printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
1803: #endif
1804: if (addr & 0x10)
1805: pcnet_ioport_writel(d, addr & 0x0f, val);
1806: else {
1807: addr &= 0x0f;
1808: pcnet_aprom_writeb(d, addr, val & 0xff);
1809: pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1810: pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
1811: pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
1812: }
1813: }
1814:
1.1.1.3 ! root 1815: static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
1.1 root 1816: {
1817: PCNetState *d = opaque;
1818: uint32_t val;
1819: if (addr & 0x10)
1820: val = pcnet_ioport_readl(d, addr & 0x0f);
1821: else {
1822: addr &= 0x0f;
1823: val = pcnet_aprom_readb(d, addr+3);
1824: val <<= 8;
1825: val |= pcnet_aprom_readb(d, addr+2);
1826: val <<= 8;
1827: val |= pcnet_aprom_readb(d, addr+1);
1828: val <<= 8;
1829: val |= pcnet_aprom_readb(d, addr);
1830: }
1831: #ifdef PCNET_DEBUG_IO
1832: printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
1833: #endif
1834: return val;
1835: }
1836:
1837:
1.1.1.2 root 1838: static void pcnet_save(QEMUFile *f, void *opaque)
1839: {
1840: PCNetState *s = opaque;
1841: unsigned int i;
1842:
1843: if (s->pci_dev)
1844: pci_device_save(s->pci_dev, f);
1845:
1.1.1.3 ! root 1846: qemu_put_be32(f, s->rap);
! 1847: qemu_put_be32(f, s->isr);
! 1848: qemu_put_be32(f, s->lnkst);
1.1.1.2 root 1849: qemu_put_be32s(f, &s->rdra);
1850: qemu_put_be32s(f, &s->tdra);
1851: qemu_put_buffer(f, s->prom, 16);
1852: for (i = 0; i < 128; i++)
1853: qemu_put_be16s(f, &s->csr[i]);
1854: for (i = 0; i < 32; i++)
1855: qemu_put_be16s(f, &s->bcr[i]);
1856: qemu_put_be64s(f, &s->timer);
1.1.1.3 ! root 1857: qemu_put_be32(f, s->xmit_pos);
! 1858: qemu_put_be32(f, s->recv_pos);
1.1.1.2 root 1859: qemu_put_buffer(f, s->buffer, 4096);
1.1.1.3 ! root 1860: qemu_put_be32(f, s->tx_busy);
1.1.1.2 root 1861: qemu_put_timer(f, s->poll_timer);
1862: }
1863:
1864: static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
1865: {
1866: PCNetState *s = opaque;
1867: int i, ret;
1868:
1869: if (version_id != 2)
1870: return -EINVAL;
1871:
1872: if (s->pci_dev) {
1873: ret = pci_device_load(s->pci_dev, f);
1874: if (ret < 0)
1875: return ret;
1876: }
1877:
1.1.1.3 ! root 1878: qemu_get_be32s(f, (uint32_t*)&s->rap);
! 1879: qemu_get_be32s(f, (uint32_t*)&s->isr);
! 1880: qemu_get_be32s(f, (uint32_t*)&s->lnkst);
1.1.1.2 root 1881: qemu_get_be32s(f, &s->rdra);
1882: qemu_get_be32s(f, &s->tdra);
1883: qemu_get_buffer(f, s->prom, 16);
1884: for (i = 0; i < 128; i++)
1885: qemu_get_be16s(f, &s->csr[i]);
1886: for (i = 0; i < 32; i++)
1887: qemu_get_be16s(f, &s->bcr[i]);
1888: qemu_get_be64s(f, &s->timer);
1.1.1.3 ! root 1889: qemu_get_be32s(f, (uint32_t*)&s->xmit_pos);
! 1890: qemu_get_be32s(f, (uint32_t*)&s->recv_pos);
1.1.1.2 root 1891: qemu_get_buffer(f, s->buffer, 4096);
1.1.1.3 ! root 1892: qemu_get_be32s(f, (uint32_t*)&s->tx_busy);
1.1.1.2 root 1893: qemu_get_timer(f, s->poll_timer);
1894:
1895: return 0;
1896: }
1897:
1898: static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str)
1899: {
1900: d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
1901:
1902: d->nd = nd;
1903:
1.1.1.3 ! root 1904: if (nd && nd->vlan) {
! 1905: d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
! 1906: pcnet_can_receive, d);
! 1907:
! 1908: snprintf(d->vc->info_str, sizeof(d->vc->info_str),
! 1909: "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
! 1910: d->nd->macaddr[0],
! 1911: d->nd->macaddr[1],
! 1912: d->nd->macaddr[2],
! 1913: d->nd->macaddr[3],
! 1914: d->nd->macaddr[4],
! 1915: d->nd->macaddr[5]);
! 1916: } else {
! 1917: d->vc = NULL;
! 1918: }
1.1.1.2 root 1919: pcnet_h_reset(d);
1920: register_savevm("pcnet", 0, 2, pcnet_save, pcnet_load, d);
1921: }
1922:
1923: /* PCI interface */
1924:
1.1 root 1925: static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
1926: (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
1927: (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
1928: (CPUWriteMemoryFunc *)&pcnet_mmio_writel
1929: };
1930:
1931: static CPUReadMemoryFunc *pcnet_mmio_read[] = {
1932: (CPUReadMemoryFunc *)&pcnet_mmio_readb,
1933: (CPUReadMemoryFunc *)&pcnet_mmio_readw,
1934: (CPUReadMemoryFunc *)&pcnet_mmio_readl
1935: };
1936:
1.1.1.3 ! root 1937: static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
1.1 root 1938: uint32_t addr, uint32_t size, int type)
1939: {
1940: PCNetState *d = (PCNetState *)pci_dev;
1941:
1942: #ifdef PCNET_DEBUG_IO
1943: printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
1944: #endif
1945:
1.1.1.2 root 1946: cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index);
1.1 root 1947: }
1948:
1.1.1.2 root 1949: static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
1950: uint8_t *buf, int len, int do_bswap)
1951: {
1952: cpu_physical_memory_write(addr, buf, len);
1953: }
1954:
1955: static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
1956: uint8_t *buf, int len, int do_bswap)
1957: {
1958: cpu_physical_memory_read(addr, buf, len);
1959: }
1960:
1961: void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
1.1 root 1962: {
1963: PCNetState *d;
1964: uint8_t *pci_conf;
1965:
1966: #if 0
1.1.1.3 ! root 1967: printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
1.1 root 1968: sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
1969: #endif
1970:
1971: d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
1.1.1.2 root 1972: devfn, NULL, NULL);
1.1.1.3 ! root 1973:
1.1 root 1974: pci_conf = d->dev.config;
1.1.1.3 ! root 1975:
1.1 root 1976: *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
1.1.1.3 ! root 1977: *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);
! 1978: *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007);
1.1 root 1979: *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
1980: pci_conf[0x08] = 0x10;
1981: pci_conf[0x09] = 0x00;
1.1.1.3 ! root 1982: pci_conf[0x0a] = 0x00; // ethernet network controller
1.1 root 1983: pci_conf[0x0b] = 0x02;
1984: pci_conf[0x0e] = 0x00; // header_type
1.1.1.3 ! root 1985:
1.1 root 1986: *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
1987: *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
1.1.1.3 ! root 1988:
1.1 root 1989: pci_conf[0x3d] = 1; // interrupt pin 0
1990: pci_conf[0x3e] = 0x06;
1991: pci_conf[0x3f] = 0xff;
1992:
1993: /* Handler for memory-mapped I/O */
1.1.1.2 root 1994: d->mmio_index =
1.1 root 1995: cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
1996:
1.1.1.3 ! root 1997: pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
1.1 root 1998: PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
1.1.1.3 ! root 1999:
! 2000: pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
1.1 root 2001: PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
1.1.1.3 ! root 2002:
! 2003: d->irq = d->dev.irq[0];
1.1.1.2 root 2004: d->phys_mem_read = pci_physical_memory_read;
2005: d->phys_mem_write = pci_physical_memory_write;
2006: d->pci_dev = &d->dev;
1.1 root 2007:
1.1.1.2 root 2008: pcnet_common_init(d, nd, "pcnet");
2009: }
1.1 root 2010:
1.1.1.2 root 2011: /* SPARC32 interface */
1.1 root 2012:
1.1.1.2 root 2013: #if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure
1.1.1.3 ! root 2014: #include "sun4m.h"
1.1.1.2 root 2015:
1.1.1.3 ! root 2016: static void parent_lance_reset(void *opaque, int irq, int level)
! 2017: {
! 2018: if (level)
! 2019: pcnet_h_reset(opaque);
! 2020: }
1.1.1.2 root 2021:
1.1.1.3 ! root 2022: static void lance_mem_writew(void *opaque, target_phys_addr_t addr,
! 2023: uint32_t val)
! 2024: {
! 2025: #ifdef PCNET_DEBUG_IO
! 2026: printf("lance_mem_writew addr=" TARGET_FMT_plx " val=0x%04x\n", addr,
! 2027: val & 0xffff);
! 2028: #endif
! 2029: pcnet_ioport_writew(opaque, addr & 7, val & 0xffff);
! 2030: }
1.1.1.2 root 2031:
1.1.1.3 ! root 2032: static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
1.1.1.2 root 2033: {
1.1.1.3 ! root 2034: uint32_t val;
! 2035:
! 2036: val = pcnet_ioport_readw(opaque, addr & 7);
! 2037: #ifdef PCNET_DEBUG_IO
! 2038: printf("pcnet_mmio_readw addr=" TARGET_FMT_plx " val = 0x%04x\n", addr,
! 2039: val & 0xffff);
! 2040: #endif
1.1.1.2 root 2041:
1.1.1.3 ! root 2042: return val & 0xffff;
1.1.1.2 root 2043: }
2044:
1.1.1.3 ! root 2045: static CPUReadMemoryFunc *lance_mem_read[3] = {
! 2046: NULL,
! 2047: lance_mem_readw,
! 2048: NULL,
! 2049: };
! 2050:
! 2051: static CPUWriteMemoryFunc *lance_mem_write[3] = {
! 2052: NULL,
! 2053: lance_mem_writew,
! 2054: NULL,
! 2055: };
! 2056:
! 2057: void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
! 2058: qemu_irq irq, qemu_irq *reset)
1.1.1.2 root 2059: {
2060: PCNetState *d;
2061: int lance_io_memory;
2062:
2063: d = qemu_mallocz(sizeof(PCNetState));
2064: if (!d)
1.1.1.3 ! root 2065: return;
1.1.1.2 root 2066:
2067: lance_io_memory =
2068: cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d);
2069:
2070: d->dma_opaque = dma_opaque;
1.1.1.3 ! root 2071:
! 2072: *reset = *qemu_allocate_irqs(parent_lance_reset, d, 1);
! 2073:
1.1.1.2 root 2074: cpu_register_physical_memory(leaddr, 4, lance_io_memory);
2075:
1.1.1.3 ! root 2076: d->irq = irq;
1.1.1.2 root 2077: d->phys_mem_read = ledma_memory_read;
2078: d->phys_mem_write = ledma_memory_write;
2079:
2080: pcnet_common_init(d, nd, "lance");
1.1 root 2081: }
1.1.1.2 root 2082: #endif /* TARGET_SPARC */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.