Revision 5fafdf24 hw/pcnet.c
b/hw/pcnet.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* QEMU AMD PC-Net II (Am79C970A) emulation |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2004 Antony T Curtis |
5 |
*
|
|
5 |
* |
|
6 | 6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 |
* of this software and associated documentation files (the "Software"), to deal |
8 | 8 |
* in the Software without restriction, including without limitation the rights |
... | ... | |
21 | 21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 |
|
|
24 |
|
|
25 | 25 |
/* This software was written to be compatible with the specification: |
26 | 26 |
* AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet |
27 | 27 |
* AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 |
28 | 28 |
*/ |
29 |
|
|
29 |
|
|
30 | 30 |
/* |
31 | 31 |
* On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also |
32 | 32 |
* produced as NCR89C100. See |
... | ... | |
652 | 652 |
static inline int padr_match(PCNetState *s, const uint8_t *buf, int size) |
653 | 653 |
{ |
654 | 654 |
struct qemu_ether_header *hdr = (void *)buf; |
655 |
uint8_t padr[6] = {
|
|
655 |
uint8_t padr[6] = { |
|
656 | 656 |
s->csr[12] & 0xff, s->csr[12] >> 8, |
657 | 657 |
s->csr[13] & 0xff, s->csr[13] >> 8, |
658 |
s->csr[14] & 0xff, s->csr[14] >> 8
|
|
658 |
s->csr[14] & 0xff, s->csr[14] >> 8 |
|
659 | 659 |
}; |
660 | 660 |
int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6); |
661 | 661 |
#ifdef PCNET_DEBUG_MATCH |
... | ... | |
683 | 683 |
static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size) |
684 | 684 |
{ |
685 | 685 |
struct qemu_ether_header *hdr = (void *)buf; |
686 |
if ((*(hdr->ether_dhost)&0x01) &&
|
|
686 |
if ((*(hdr->ether_dhost)&0x01) && |
|
687 | 687 |
((uint64_t *)&s->csr[8])[0] != 0LL) { |
688 |
uint8_t ladr[8] = {
|
|
688 |
uint8_t ladr[8] = { |
|
689 | 689 |
s->csr[8] & 0xff, s->csr[8] >> 8, |
690 | 690 |
s->csr[9] & 0xff, s->csr[9] >> 8, |
691 |
s->csr[10] & 0xff, s->csr[10] >> 8,
|
|
692 |
s->csr[11] & 0xff, s->csr[11] >> 8
|
|
691 |
s->csr[10] & 0xff, s->csr[10] >> 8, |
|
692 |
s->csr[11] & 0xff, s->csr[11] >> 8 |
|
693 | 693 |
}; |
694 | 694 |
int index = lnc_mchash(hdr->ether_dhost) >> 26; |
695 | 695 |
return !!(ladr[index >> 3] & (1 << (index & 7))); |
... | ... | |
697 | 697 |
return 0; |
698 | 698 |
} |
699 | 699 |
|
700 |
static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx)
|
|
700 |
static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx) |
|
701 | 701 |
{ |
702 | 702 |
while (idx < 1) idx += CSR_RCVRL(s); |
703 | 703 |
return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8)); |
... | ... | |
705 | 705 |
|
706 | 706 |
static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time) |
707 | 707 |
{ |
708 |
int64_t next_time = current_time +
|
|
709 |
muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
|
|
708 |
int64_t next_time = current_time + |
|
709 |
muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)), |
|
710 | 710 |
ticks_per_sec, 33000000L); |
711 | 711 |
if (next_time <= current_time) |
712 | 712 |
next_time = current_time + 1; |
... | ... | |
731 | 731 |
s->rdra = 0; |
732 | 732 |
s->tdra = 0; |
733 | 733 |
s->rap = 0; |
734 |
|
|
734 |
|
|
735 | 735 |
s->bcr[BCR_BSBC] &= ~0x0080; |
736 | 736 |
|
737 | 737 |
s->csr[0] = 0x0004; |
... | ... | |
770 | 770 |
{ |
771 | 771 |
int isr = 0; |
772 | 772 |
s->csr[0] &= ~0x0080; |
773 |
|
|
773 |
|
|
774 | 774 |
#if 1 |
775 | 775 |
if (((s->csr[0] & ~s->csr[3]) & 0x5f00) || |
776 | 776 |
(((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) || |
... | ... | |
790 | 790 |
(!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */) |
791 | 791 |
#endif |
792 | 792 |
{ |
793 |
|
|
793 |
|
|
794 | 794 |
isr = CSR_INEA(s); |
795 | 795 |
s->csr[0] |= 0x0080; |
796 | 796 |
} |
797 |
|
|
797 |
|
|
798 | 798 |
if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */ |
799 | 799 |
s->csr[4] &= ~0x0080; |
800 | 800 |
s->csr[4] |= 0x0040; |
... | ... | |
806 | 806 |
} |
807 | 807 |
|
808 | 808 |
#if 1 |
809 |
if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
|
|
809 |
if (((s->csr[5]>>1) & s->csr[5]) & 0x0500) |
|
810 | 810 |
#else |
811 | 811 |
if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ || |
812 | 812 |
(!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ ) |
... | ... | |
834 | 834 |
#ifdef PCNET_DEBUG |
835 | 835 |
printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s))); |
836 | 836 |
#endif |
837 |
|
|
837 |
|
|
838 | 838 |
if (BCR_SSIZE32(s)) { |
839 | 839 |
struct pcnet_initblk32 initblk; |
840 | 840 |
s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)), |
... | ... | |
893 | 893 |
CSR_XMTRC(s) = CSR_XMTRL(s); |
894 | 894 |
|
895 | 895 |
#ifdef PCNET_DEBUG |
896 |
printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
|
|
896 |
printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n", |
|
897 | 897 |
BCR_SSIZE32(s), |
898 | 898 |
s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s)); |
899 | 899 |
#endif |
900 | 900 |
|
901 |
s->csr[0] |= 0x0101;
|
|
901 |
s->csr[0] |= 0x0101; |
|
902 | 902 |
s->csr[0] &= ~0x0004; /* clear STOP bit */ |
903 | 903 |
} |
904 | 904 |
|
... | ... | |
910 | 910 |
|
911 | 911 |
if (!CSR_DTX(s)) |
912 | 912 |
s->csr[0] |= 0x0010; /* set TXON */ |
913 |
|
|
913 |
|
|
914 | 914 |
if (!CSR_DRX(s)) |
915 | 915 |
s->csr[0] |= 0x0020; /* set RXON */ |
916 | 916 |
|
... | ... | |
940 | 940 |
target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s)); |
941 | 941 |
target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s)); |
942 | 942 |
#else |
943 |
target_phys_addr_t crda = s->rdra +
|
|
943 |
target_phys_addr_t crda = s->rdra + |
|
944 | 944 |
(CSR_RCVRL(s) - CSR_RCVRC(s)) * |
945 | 945 |
(BCR_SWSTYLE(s) ? 16 : 8 ); |
946 | 946 |
int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1; |
947 |
target_phys_addr_t nrda = s->rdra +
|
|
947 |
target_phys_addr_t nrda = s->rdra + |
|
948 | 948 |
(CSR_RCVRL(s) - nrdc) * |
949 | 949 |
(BCR_SWSTYLE(s) ? 16 : 8 ); |
950 | 950 |
int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1; |
951 |
target_phys_addr_t nnrd = s->rdra +
|
|
951 |
target_phys_addr_t nnrd = s->rdra + |
|
952 | 952 |
(CSR_RCVRL(s) - nnrc) * |
953 | 953 |
(BCR_SWSTYLE(s) ? 16 : 8 ); |
954 | 954 |
#endif |
... | ... | |
976 | 976 |
#endif |
977 | 977 |
} |
978 | 978 |
} |
979 |
|
|
979 |
|
|
980 | 980 |
if (CSR_CRDA(s)) { |
981 | 981 |
struct pcnet_RMD rmd; |
982 | 982 |
RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s))); |
... | ... | |
991 | 991 |
} else { |
992 | 992 |
CSR_CRBC(s) = CSR_CRST(s) = 0; |
993 | 993 |
} |
994 |
|
|
994 |
|
|
995 | 995 |
if (CSR_NRDA(s)) { |
996 | 996 |
struct pcnet_RMD rmd; |
997 | 997 |
RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s))); |
... | ... | |
1007 | 1007 |
{ |
1008 | 1008 |
s->csr[34] = s->csr[35] = 0; |
1009 | 1009 |
if (s->tdra) { |
1010 |
target_phys_addr_t cxda = s->tdra +
|
|
1010 |
target_phys_addr_t cxda = s->tdra + |
|
1011 | 1011 |
(CSR_XMTRL(s) - CSR_XMTRC(s)) * |
1012 | 1012 |
(BCR_SWSTYLE(s) ? 16 : 8); |
1013 | 1013 |
int bad = 0; |
... | ... | |
1030 | 1030 |
if (CSR_CXDA(s)) { |
1031 | 1031 |
struct pcnet_TMD tmd; |
1032 | 1032 |
|
1033 |
TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
|
|
1033 |
TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s))); |
|
1034 | 1034 |
|
1035 | 1035 |
CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT); |
1036 | 1036 |
CSR_CXST(s) = tmd.status; |
1037 | 1037 |
} else { |
1038 | 1038 |
CSR_CXBC(s) = CSR_CXST(s) = 0; |
1039 | 1039 |
} |
1040 |
|
|
1040 |
|
|
1041 | 1041 |
return !!(CSR_CXST(s) & 0x8000); |
1042 | 1042 |
} |
1043 | 1043 |
|
... | ... | |
1046 | 1046 |
PCNetState *s = opaque; |
1047 | 1047 |
if (CSR_STOP(s) || CSR_SPND(s)) |
1048 | 1048 |
return 0; |
1049 |
|
|
1049 |
|
|
1050 | 1050 |
if (s->recv_pos > 0) |
1051 | 1051 |
return 0; |
1052 | 1052 |
|
... | ... | |
1076 | 1076 |
size = MIN_BUF_SIZE; |
1077 | 1077 |
} |
1078 | 1078 |
|
1079 |
if (CSR_PROM(s)
|
|
1080 |
|| (is_padr=padr_match(s, buf, size))
|
|
1079 |
if (CSR_PROM(s) |
|
1080 |
|| (is_padr=padr_match(s, buf, size)) |
|
1081 | 1081 |
|| (is_bcast=padr_bcast(s, buf, size)) |
1082 | 1082 |
|| (is_ladr=ladr_match(s, buf, size))) { |
1083 | 1083 |
|
... | ... | |
1093 | 1093 |
nrda = s->rdra + |
1094 | 1094 |
(CSR_RCVRL(s) - rcvrc) * |
1095 | 1095 |
(BCR_SWSTYLE(s) ? 16 : 8 ); |
1096 |
RMDLOAD(&rmd, PHYSADDR(s,nrda));
|
|
1096 |
RMDLOAD(&rmd, PHYSADDR(s,nrda)); |
|
1097 | 1097 |
if (GET_FIELD(rmd.status, RMDS, OWN)) { |
1098 | 1098 |
#ifdef PCNET_DEBUG_RMD |
1099 |
printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
|
|
1099 |
printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", |
|
1100 | 1100 |
rcvrc, CSR_RCVRC(s)); |
1101 | 1101 |
#endif |
1102 | 1102 |
CSR_RCVRC(s) = rcvrc; |
... | ... | |
1119 | 1119 |
int pktcount = 0; |
1120 | 1120 |
|
1121 | 1121 |
memcpy(src, buf, size); |
1122 |
|
|
1122 |
|
|
1123 | 1123 |
#if 1 |
1124 | 1124 |
/* no need to compute the CRC */ |
1125 | 1125 |
src[size] = 0; |
... | ... | |
1136 | 1136 |
while (size < 46) { |
1137 | 1137 |
src[size++] = 0; |
1138 | 1138 |
} |
1139 |
|
|
1139 |
|
|
1140 | 1140 |
while (p != &src[size]) { |
1141 | 1141 |
CRC(fcs, *p++); |
1142 | 1142 |
} |
... | ... | |
1178 | 1178 |
PCNET_RECV_STORE(); |
1179 | 1179 |
} |
1180 | 1180 |
} |
1181 |
}
|
|
1181 |
} |
|
1182 | 1182 |
} |
1183 | 1183 |
|
1184 | 1184 |
#undef PCNET_RECV_STORE |
... | ... | |
1198 | 1198 |
s->csr[0] |= 0x0400; |
1199 | 1199 |
|
1200 | 1200 |
#ifdef PCNET_DEBUG |
1201 |
printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
|
|
1201 |
printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n", |
|
1202 | 1202 |
CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount); |
1203 | 1203 |
#endif |
1204 | 1204 |
#ifdef PCNET_DEBUG_RMD |
1205 | 1205 |
PRINT_RMD(&rmd); |
1206 |
#endif
|
|
1206 |
#endif |
|
1207 | 1207 |
|
1208 | 1208 |
while (pktcount--) { |
1209 | 1209 |
if (CSR_RCVRC(s) <= 1) |
1210 | 1210 |
CSR_RCVRC(s) = CSR_RCVRL(s); |
1211 | 1211 |
else |
1212 |
CSR_RCVRC(s)--;
|
|
1212 |
CSR_RCVRC(s)--; |
|
1213 | 1213 |
} |
1214 |
|
|
1214 |
|
|
1215 | 1215 |
pcnet_rdte_poll(s); |
1216 | 1216 |
|
1217 |
}
|
|
1217 |
} |
|
1218 | 1218 |
} |
1219 | 1219 |
|
1220 | 1220 |
pcnet_poll(s); |
1221 |
pcnet_update_irq(s);
|
|
1221 |
pcnet_update_irq(s); |
|
1222 | 1222 |
} |
1223 | 1223 |
|
1224 | 1224 |
static void pcnet_transmit(PCNetState *s) |
... | ... | |
1226 | 1226 |
target_phys_addr_t xmit_cxda = 0; |
1227 | 1227 |
int count = CSR_XMTRL(s)-1; |
1228 | 1228 |
s->xmit_pos = -1; |
1229 |
|
|
1229 |
|
|
1230 | 1230 |
if (!CSR_TXON(s)) { |
1231 | 1231 |
s->csr[0] &= ~0x0008; |
1232 | 1232 |
return; |
... | ... | |
1285 | 1285 |
if (count--) |
1286 | 1286 |
goto txagain; |
1287 | 1287 |
|
1288 |
} else
|
|
1288 |
} else |
|
1289 | 1289 |
if (s->xmit_pos >= 0) { |
1290 | 1290 |
struct pcnet_TMD tmd; |
1291 | 1291 |
TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda)); |
... | ... | |
1311 | 1311 |
pcnet_rdte_poll(s); |
1312 | 1312 |
} |
1313 | 1313 |
|
1314 |
if (CSR_TDMD(s) ||
|
|
1314 |
if (CSR_TDMD(s) || |
|
1315 | 1315 |
(CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s))) |
1316 | 1316 |
{ |
1317 | 1317 |
/* prevent recursion */ |
... | ... | |
1332 | 1332 |
pcnet_transmit(s); |
1333 | 1333 |
} |
1334 | 1334 |
|
1335 |
pcnet_update_irq(s);
|
|
1335 |
pcnet_update_irq(s); |
|
1336 | 1336 |
|
1337 | 1337 |
if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) { |
1338 | 1338 |
uint64_t now = qemu_get_clock(vm_clock) * 33; |
... | ... | |
1346 | 1346 |
} else |
1347 | 1347 |
CSR_POLL(s) = t; |
1348 | 1348 |
} |
1349 |
qemu_mod_timer(s->poll_timer,
|
|
1349 |
qemu_mod_timer(s->poll_timer, |
|
1350 | 1350 |
pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock))); |
1351 | 1351 |
} |
1352 | 1352 |
} |
... | ... | |
1379 | 1379 |
if (!CSR_STRT(s) && (val & 2)) |
1380 | 1380 |
pcnet_start(s); |
1381 | 1381 |
|
1382 |
if (CSR_TDMD(s))
|
|
1382 |
if (CSR_TDMD(s)) |
|
1383 | 1383 |
pcnet_transmit(s); |
1384 | 1384 |
|
1385 | 1385 |
return; |
... | ... | |
1434 | 1434 |
case 3: |
1435 | 1435 |
break; |
1436 | 1436 |
case 4: |
1437 |
s->csr[4] &= ~(val & 0x026a);
|
|
1437 |
s->csr[4] &= ~(val & 0x026a); |
|
1438 | 1438 |
val &= ~0x026a; val |= s->csr[4] & 0x026a; |
1439 | 1439 |
break; |
1440 | 1440 |
case 5: |
1441 |
s->csr[5] &= ~(val & 0x0a90);
|
|
1441 |
s->csr[5] &= ~(val & 0x0a90); |
|
1442 | 1442 |
val &= ~0x0a90; val |= s->csr[5] & 0x0a90; |
1443 | 1443 |
break; |
1444 | 1444 |
case 16: |
... | ... | |
1592 | 1592 |
PCNetState *s = opaque; |
1593 | 1593 |
#ifdef PCNET_DEBUG |
1594 | 1594 |
printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val); |
1595 |
#endif
|
|
1595 |
#endif |
|
1596 | 1596 |
/* Check APROMWE bit to enable write access */ |
1597 | 1597 |
if (pcnet_bcr_readw(s,2) & 0x80) |
1598 | 1598 |
s->prom[addr & 15] = val; |
1599 |
}
|
|
1599 |
} |
|
1600 | 1600 |
|
1601 | 1601 |
static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr) |
1602 | 1602 |
{ |
... | ... | |
1685 | 1685 |
pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080); |
1686 | 1686 |
#ifdef PCNET_DEBUG_IO |
1687 | 1687 |
printf("device switched into dword i/o mode\n"); |
1688 |
#endif
|
|
1688 |
#endif |
|
1689 | 1689 |
} |
1690 | 1690 |
pcnet_update_irq(s); |
1691 | 1691 |
} |
... | ... | |
1695 | 1695 |
PCNetState *s = opaque; |
1696 | 1696 |
uint32_t val = -1; |
1697 | 1697 |
pcnet_poll_timer(s); |
1698 |
if (BCR_DWIO(s)) {
|
|
1698 |
if (BCR_DWIO(s)) { |
|
1699 | 1699 |
switch (addr & 0x0f) { |
1700 | 1700 |
case 0x00: /* RDP */ |
1701 | 1701 |
val = pcnet_csr_readw(s, s->rap); |
... | ... | |
1719 | 1719 |
return val; |
1720 | 1720 |
} |
1721 | 1721 |
|
1722 |
static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
|
|
1722 |
static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, |
|
1723 | 1723 |
uint32_t addr, uint32_t size, int type) |
1724 | 1724 |
{ |
1725 | 1725 |
PCNetState *d = (PCNetState *)pci_dev; |
... | ... | |
1730 | 1730 |
|
1731 | 1731 |
register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d); |
1732 | 1732 |
register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d); |
1733 |
|
|
1733 |
|
|
1734 | 1734 |
register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d); |
1735 | 1735 |
register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d); |
1736 | 1736 |
register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d); |
... | ... | |
1747 | 1747 |
pcnet_aprom_writeb(d, addr & 0x0f, val); |
1748 | 1748 |
} |
1749 | 1749 |
|
1750 |
static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
|
|
1750 |
static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) |
|
1751 | 1751 |
{ |
1752 | 1752 |
PCNetState *d = opaque; |
1753 | 1753 |
uint32_t val = -1; |
... | ... | |
1774 | 1774 |
} |
1775 | 1775 |
} |
1776 | 1776 |
|
1777 |
static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
|
|
1777 |
static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) |
|
1778 | 1778 |
{ |
1779 | 1779 |
PCNetState *d = opaque; |
1780 | 1780 |
uint32_t val = -1; |
... | ... | |
1809 | 1809 |
} |
1810 | 1810 |
} |
1811 | 1811 |
|
1812 |
static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
|
|
1812 |
static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) |
|
1813 | 1813 |
{ |
1814 | 1814 |
PCNetState *d = opaque; |
1815 | 1815 |
uint32_t val; |
... | ... | |
1931 | 1931 |
(CPUReadMemoryFunc *)&pcnet_mmio_readl |
1932 | 1932 |
}; |
1933 | 1933 |
|
1934 |
static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
|
|
1934 |
static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, |
|
1935 | 1935 |
uint32_t addr, uint32_t size, int type) |
1936 | 1936 |
{ |
1937 | 1937 |
PCNetState *d = (PCNetState *)pci_dev; |
... | ... | |
1961 | 1961 |
uint8_t *pci_conf; |
1962 | 1962 |
|
1963 | 1963 |
#if 0 |
1964 |
printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
|
|
1964 |
printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", |
|
1965 | 1965 |
sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD)); |
1966 | 1966 |
#endif |
1967 | 1967 |
|
1968 | 1968 |
d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState), |
1969 | 1969 |
devfn, NULL, NULL); |
1970 |
|
|
1970 |
|
|
1971 | 1971 |
pci_conf = d->dev.config; |
1972 |
|
|
1972 |
|
|
1973 | 1973 |
*(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022); |
1974 |
*(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);
|
|
1975 |
*(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007);
|
|
1974 |
*(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000); |
|
1975 |
*(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007); |
|
1976 | 1976 |
*(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280); |
1977 | 1977 |
pci_conf[0x08] = 0x10; |
1978 | 1978 |
pci_conf[0x09] = 0x00; |
1979 |
pci_conf[0x0a] = 0x00; // ethernet network controller
|
|
1979 |
pci_conf[0x0a] = 0x00; // ethernet network controller |
|
1980 | 1980 |
pci_conf[0x0b] = 0x02; |
1981 | 1981 |
pci_conf[0x0e] = 0x00; // header_type |
1982 |
|
|
1982 |
|
|
1983 | 1983 |
*(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001); |
1984 | 1984 |
*(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000); |
1985 |
|
|
1985 |
|
|
1986 | 1986 |
pci_conf[0x3d] = 1; // interrupt pin 0 |
1987 | 1987 |
pci_conf[0x3e] = 0x06; |
1988 | 1988 |
pci_conf[0x3f] = 0xff; |
... | ... | |
1991 | 1991 |
d->mmio_index = |
1992 | 1992 |
cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d); |
1993 | 1993 |
|
1994 |
pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
|
|
1994 |
pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, |
|
1995 | 1995 |
PCI_ADDRESS_SPACE_IO, pcnet_ioport_map); |
1996 |
|
|
1997 |
pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
|
|
1996 |
|
|
1997 |
pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, |
|
1998 | 1998 |
PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map); |
1999 |
|
|
1999 |
|
|
2000 | 2000 |
d->irq = d->dev.irq[0]; |
2001 | 2001 |
d->phys_mem_read = pci_physical_memory_read; |
2002 | 2002 |
d->phys_mem_write = pci_physical_memory_write; |
Also available in: Unified diff