2 * QEMU emulation for Texas Instruments TNETW1130 (ACX111) wireless.
4 * Copyright (C) 2007-2012 Stefan Weil
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * Texas Instruments does not provide any datasheets.
22 * - Add save, load support.
23 * - Much more emulation is needed.
26 #include "qemu/osdep.h"
31 #include "tnetw1130.h"
33 /*****************************************************************************
35 * Common declarations.
37 ****************************************************************************/
39 #define BIT(n) (1 << (n))
40 #define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
44 /*****************************************************************************
46 * Declarations for emulation options and debugging.
48 ****************************************************************************/
50 /* Debug TNETW1130 card. */
51 #define DEBUG_TNETW1130
53 #if defined(DEBUG_TNETW1130)
54 # define logout(fmt, ...) fprintf(stderr, "ACX111\t%-24s" fmt, __func__, ##__VA_ARGS__)
56 # define logout(fmt, ...) ((void)0)
59 #define missing(text) assert(!"feature is missing in this emulation: " text)
60 #define MISSING() logout("%s:%u missing, %s!!!\n", __FILE__, __LINE__, backtrace())
61 #define UNEXPECTED() logout("%s:%u unexpected, %s!!!\n", __FILE__, __LINE__, backtrace())
62 #define backtrace() ""
64 /* Enable or disable logging categories. */
66 #define LOG_RX 1 /* receive messages */
67 #define LOG_TX 1 /* transmit messages */
69 #if defined(DEBUG_TNETW1130)
70 # define TRACE(condition, command) ((condition) ? (command) : (void)0)
72 # define TRACE(condition, command) ((void)0)
75 //~ static int tnetw1130_instance = 0;
79 MemoryRegion mmio_bar0
;
80 MemoryRegion mmio_bar1
;
81 tnetw1130_t tnetw1130
;
85 CMD_MAILBOX
= 0x0001e108, /* ECPU_CTRL? */
86 INFO_MAILBOX
= 0x0001e0f0, /* HINT_STS_ND? */
87 } tnetw1130_memory_offset_t
;
90 ACX1xx_CMD_RESET
= 0x00,
91 ACX1xx_CMD_INTERROGATE
= 0x01,
92 ACX1xx_CMD_CONFIGURE
= 0x02,
93 ACX1xx_CMD_ENABLE_RX
= 0x03,
94 ACX1xx_CMD_ENABLE_TX
= 0x04,
95 ACX1xx_CMD_DISABLE_RX
= 0x05,
96 ACX1xx_CMD_DISABLE_TX
= 0x06,
97 ACX1xx_CMD_FLUSH_QUEUE
= 0x07,
98 ACX1xx_CMD_SCAN
= 0x08,
99 ACX1xx_CMD_STOP_SCAN
= 0x09,
100 ACX1xx_CMD_CONFIG_TIM
= 0x0a,
101 ACX1xx_CMD_JOIN
= 0x0b,
102 ACX1xx_CMD_WEP_MGMT
= 0x0c,
103 #ifdef OLD_FIRMWARE_VERSIONS
104 ACX100_CMD_HALT
= 0x0e, /* mapped to unknownCMD in FW150 */
106 ACX1xx_CMD_MEM_READ
= 0x0d,
107 ACX1xx_CMD_MEM_WRITE
= 0x0e,
109 ACX1xx_CMD_SLEEP
= 0x0f,
110 ACX1xx_CMD_WAKE
= 0x10,
111 ACX1xx_CMD_UNKNOWN_11
= 0x11, /* mapped to unknownCMD in FW150 */
112 ACX100_CMD_INIT_MEMORY
= 0x12,
113 ACX1xx_CMD_DISABLE_RADIO
= 0x12, /* new firmware? TNETW1450? */
114 ACX1xx_CMD_CONFIG_BEACON
= 0x13,
115 ACX1xx_CMD_CONFIG_PROBE_RESPONSE
= 0x14,
116 ACX1xx_CMD_CONFIG_NULL_DATA
= 0x15,
117 ACX1xx_CMD_CONFIG_PROBE_REQUEST
= 0x16,
118 ACX1xx_CMD_FCC_TEST
= 0x17,
119 ACX1xx_CMD_RADIOINIT
= 0x18,
120 ACX111_CMD_RADIOCALIB
= 0x19,
121 ACX1FF_CMD_NOISE_HISTOGRAM
= 0x1c, /* new firmware? TNETW1450? */
122 ACX1FF_CMD_RX_RESET
= 0x1d, /* new firmware? TNETW1450? */
123 ACX1FF_CMD_LNA_CONTROL
= 0x20, /* new firmware? TNETW1450? */
124 ACX1FF_CMD_CONTROL_DBG_TRACE
= 0x21, /* new firmware? TNETW1450? */
125 } tnetw1130_command_t
;
129 HOST_INT_RX_DATA
= BIT(0),
130 #define HOST_INT_TX_COMPLETE 0x0002
131 #define HOST_INT_TX_XFER 0x0004
132 #define HOST_INT_RX_COMPLETE 0x0008
133 #define HOST_INT_DTIM 0x0010
134 #define HOST_INT_BEACON 0x0020
135 #define HOST_INT_TIMER 0x0040
136 #define HOST_INT_KEY_NOT_FOUND 0x0080
137 #define HOST_INT_IV_ICV_FAILURE 0x0100
138 #define HOST_INT_CMD_COMPLETE 0x0200
139 #define HOST_INT_INFO 0x0400
140 #define HOST_INT_OVERFLOW 0x0800
141 #define HOST_INT_PROCESS_ERROR 0x1000
142 #define HOST_INT_SCAN_COMPLETE 0x2000
143 #define HOST_INT_FCS_THRESHOLD 0x4000
144 #define HOST_INT_UNKNOWN 0x8000
145 } tnetw10030_irq_bit_t
;
147 /*****************************************************************************
151 ****************************************************************************/
153 #if defined(DEBUG_TNETW1130)
154 static uint32_t traceflags
= 1;
156 #define TNETW traceflags
158 #define SET_TRACEFLAG(name) \
160 char *substring = strstr(envvalue, #name); \
162 name = ((substring > envvalue && substring[-1] == '-') ? 0 : 1); \
164 TRACE(name, logout("Logging enabled for " #name "\n")); \
167 static void set_traceflags(const char *envname
)
169 const char *envvalue
= getenv(envname
);
171 unsigned long ul
= strtoul(envvalue
, 0, 0);
172 if ((ul
== 0) && strstr(envvalue
, "ALL")) ul
= 0xffffffff;
174 SET_TRACEFLAG(TNETW
);
177 #endif /* DEBUG_TNETW1130 */
179 static uint16_t reg_read16(const uint8_t * reg
, uint32_t addr
)
182 return le16_to_cpu(*(uint16_t *) (®
[addr
]));
185 static void reg_write16(uint8_t * reg
, uint32_t addr
, uint16_t value
)
188 *(uint16_t *) (®
[addr
]) = cpu_to_le16(value
);
191 static uint32_t reg_read32(const uint8_t * reg
, uint32_t addr
)
194 return le32_to_cpu(*(uint32_t *) (®
[addr
]));
197 static void reg_write32(uint8_t * reg
, uint32_t addr
, uint32_t value
)
200 *(uint32_t *) (®
[addr
]) = cpu_to_le32(value
);
203 #if defined(DEBUG_TNETW1130)
210 static const char *offset2name(const offset_name_t
*o2n
, unsigned offset
)
212 static char buffer
[32];
213 const char *name
= buffer
;
214 sprintf(buffer
, "0x%08x", offset
);
215 for (; o2n
->name
!= 0; o2n
++) {
216 if (offset
== o2n
->offset
) {
224 #define ENTRY(entry) { TNETW1130_##entry, #entry }
225 static const offset_name_t addr2reg
[] = {
231 ENTRY(IRQ_STATUS_CLEAR
),
234 ENTRY(IRQ_STATUS_NON_DES
),
247 ENTRY(CMD_MAILBOX_OFFS
),
248 ENTRY(INFO_MAILBOX_OFFS
),
249 ENTRY(EEPROM_INFORMATION
),
253 static const char *tnetw1130_regname(unsigned addr
)
255 return offset2name(addr2reg
, addr
);
258 static const char *tnetw1130_regname1(unsigned addr
)
260 static char buffer
[32];
261 const char *name
= buffer
;
262 sprintf(buffer
, "0x%08x", addr
);
265 name
= "CMD_MAILBOX";
268 name
= "INFO_MAILBOX";
275 #define ENTRY(entry) { ACX1xx_CMD_##entry, #entry }
276 static const offset_name_t cmd2name
[] = {
295 //~ ENTRY(INIT_MEMORY),
296 ENTRY(DISABLE_RADIO
),
297 ENTRY(CONFIG_BEACON
),
298 ENTRY(CONFIG_PROBE_RESPONSE
),
299 ENTRY(CONFIG_NULL_DATA
),
300 ENTRY(CONFIG_PROBE_REQUEST
),
304 static const char *tnetw1130_cmdname(uint16_t cmd
)
306 return offset2name(cmd2name
, cmd
);
309 #endif /* DEBUG_TNETW1130 */
311 static void tnetw1130_cmd_reset(tnetw1130_t
*s
)
315 static void tnetw1130_cmd_interrogate(tnetw1130_t
*s
)
319 static void tnetw1130_cmd(tnetw1130_t
*s
)
321 uint16_t cmd
= reg_read16(s
->mem1
, CMD_MAILBOX
);
322 s
->irq_status
|= HOST_INT_CMD_COMPLETE
;
323 reg_write16(s
->mem1
, CMD_MAILBOX
+ 2, 0x0001);
325 case ACX1xx_CMD_RESET
: /* 0x00 */
326 tnetw1130_cmd_reset(s
);
328 case ACX1xx_CMD_INTERROGATE
: /* 0x01 */
329 tnetw1130_cmd_interrogate(s
);
331 case ACX1xx_CMD_CONFIGURE
: /* 0x02 */
332 case ACX1xx_CMD_CONFIG_TIM
: /* 0x0a */
333 case ACX1xx_CMD_CONFIG_BEACON
: /* 0x13 */
334 case ACX1xx_CMD_CONFIG_PROBE_RESPONSE
: /* 0x14 */
335 case ACX1xx_CMD_CONFIG_NULL_DATA
: /* 0x15 */
336 case ACX1xx_CMD_CONFIG_PROBE_REQUEST
: /* 0x16 */
341 static void tnetw1130_reset(tnetw1130_t
*s
)
346 static uint8_t tnetw1130_read0b(tnetw1130_t
*s
, hwaddr addr
)
349 if (addr
< TNETW1130_MEM0_SIZE
) {
350 value
= s
->mem0
[addr
];
354 //~ } else if (addr -= 0x20000, addr == TNETW1130_SOFT_RESET) {
355 TRACE(TNETW
, logout("addr %s = 0x%02x\n", tnetw1130_regname(addr
), value
));
359 /* Radio type names. */
361 RADIO_MAXIM_0D
= 0x0d,
362 RADIO_RFMD_11
= 0x11,
363 RADIO_RALINK_15
= 0x15,
364 /* used in ACX111 cards (WG311v2, WL-121, ...): */
365 RADIO_RADIA_16
= 0x16,
368 static uint16_t tnetw1130_read0w(tnetw1130_t
*s
, hwaddr addr
)
371 if (addr
< TNETW1130_MEM0_SIZE
) {
372 value
= reg_read16(s
->mem0
, addr
);
375 } else if (addr
== TNETW1130_SOFT_RESET
) {
376 } else if (addr
== TNETW1130_IRQ_STATUS_NON_DES
) {
377 /* !!! set after eCPU start */
378 value
= s
->irq_status
;
379 } else if (addr
== TNETW1130_EE_START
) {
380 } else if (addr
== TNETW1130_ECPU_CTRL
) {
381 } else if (addr
== TNETW1130_EEPROM_CTL
) {
383 } else if (addr
== TNETW1130_EEPROM_INFORMATION
) {
384 value
= (RADIO_RADIA_16
<< 8) + 0x01;
386 TRACE(TNETW
, logout("addr %s = 0x%04x\n", tnetw1130_regname(addr
), value
));
390 static uint32_t tnetw1130_read0l(tnetw1130_t
*s
, hwaddr addr
)
393 assert(addr
< TNETW1130_MEM0_SIZE
);
394 value
= reg_read32(s
->mem0
, addr
);
396 } else if (addr
== TNETW1130_SLV_MEM_DATA
) {
397 value
= reg_read32(s
->fw
, s
->fw_addr
);
398 } else if (addr
== TNETW1130_CMD_MAILBOX_OFFS
) {
400 } else if (addr
== TNETW1130_INFO_MAILBOX_OFFS
) {
401 value
= INFO_MAILBOX
;
403 TRACE(TNETW
, logout("addr %s = 0x%08x\n", tnetw1130_regname(addr
), value
));
407 static void tnetw1130_write0b(tnetw1130_t
*s
, hwaddr addr
,
410 if (addr
< TNETW1130_MEM0_SIZE
) {
411 s
->mem0
[addr
] = value
;
415 TRACE(TNETW
, logout("addr %s = 0x%02x\n", tnetw1130_regname(addr
), value
));
418 static void tnetw1130_write0w(tnetw1130_t
*s
, hwaddr addr
,
421 if (addr
< TNETW1130_MEM0_SIZE
) {
422 reg_write16(s
->mem0
, addr
, value
);
426 if (addr
== TNETW1130_SOFT_RESET
) {
428 TRACE(TNETW
, logout("soft reset\n"));
430 } else if (addr
== TNETW1130_INT_TRIG
) {
432 TRACE(TNETW
, logout("trigger interrupt, status, cmd = %s\n",
433 tnetw1130_cmdname(reg_read16(s
->mem1
, CMD_MAILBOX
))));
438 } else if (addr
== TNETW1130_IRQ_ACK
) {
439 /* !!! must reset irq */
440 s
->irq_status
&= ~value
;
441 } else if (addr
== TNETW1130_EE_START
) {
443 TRACE(TNETW
, logout("start burst read from EEPROM\n"));
445 } else if (addr
== TNETW1130_ECPU_CTRL
) {
447 TRACE(TNETW
, logout("halt eCPU\n"));
448 //~ reg_write16(s->mem0, addr, value & ~1);
450 TRACE(TNETW
, logout("start eCPU\n"));
451 s
->irq_status
|= HOST_INT_FCS_THRESHOLD
;
454 TRACE(TNETW
, logout("addr %s = 0x%04x\n", tnetw1130_regname(addr
), value
));
457 static void tnetw1130_write0l(tnetw1130_t
*s
, hwaddr addr
,
460 if (addr
< TNETW1130_MEM0_SIZE
) {
461 reg_write32(s
->mem0
, addr
, value
);
463 if (addr
== TNETW1130_SLV_MEM_ADDR
) {
465 if (value
>= TNETW1130_FW_SIZE
) {
468 } else if (addr
== TNETW1130_SLV_MEM_DATA
) {
469 reg_write32(s
->fw
, s
->fw_addr
, value
);
470 } else if (addr
== TNETW1130_SLV_MEM_CTL
) {
472 TRACE(TNETW
, logout("basic mode\n"));
473 } else if (value
== 1) {
474 TRACE(TNETW
, logout("autoincrement mode\n"));
479 } else if (addr
== TNETW1130_SLV_END_CTL
) {
481 TRACE(TNETW
, logout("addr %s = 0x%08x\n", tnetw1130_regname(addr
), value
));
484 static uint8_t tnetw1130_read1b(tnetw1130_t
*s
, hwaddr addr
)
487 assert(addr
< TNETW1130_MEM1_SIZE
);
488 value
= s
->mem1
[addr
];
489 TRACE(TNETW
, logout("addr %s = 0x%02x\n", tnetw1130_regname1(addr
), value
));
493 static uint16_t tnetw1130_read1w(tnetw1130_t
*s
, hwaddr addr
)
496 assert(addr
< TNETW1130_MEM1_SIZE
);
497 value
= reg_read16(s
->mem1
, addr
);
498 TRACE(TNETW
, logout("addr %s = 0x%04x\n", tnetw1130_regname1(addr
), value
));
502 static uint32_t tnetw1130_read1l(tnetw1130_t
*s
, hwaddr addr
)
504 assert(addr
< TNETW1130_MEM1_SIZE
);
505 uint32_t value
= reg_read32(s
->mem1
, addr
);
506 TRACE(TNETW
, logout("addr %s = 0x%08x\n", tnetw1130_regname1(addr
), value
));
510 static void tnetw1130_write1b(tnetw1130_t
*s
, hwaddr addr
,
513 assert(addr
< TNETW1130_MEM1_SIZE
);
514 s
->mem1
[addr
] = value
;
515 TRACE(TNETW
, logout("addr %s = 0x%02x\n", tnetw1130_regname1(addr
), value
));
518 static void tnetw1130_write1w(tnetw1130_t
*s
, hwaddr addr
,
521 assert(addr
< TNETW1130_MEM1_SIZE
);
522 reg_write16(s
->mem1
, addr
, value
);
523 TRACE(TNETW
, logout("addr %s = 0x%04x\n", tnetw1130_regname1(addr
), value
));
526 static void tnetw1130_write1l(tnetw1130_t
*s
, hwaddr addr
,
529 assert(addr
< TNETW1130_MEM1_SIZE
);
530 reg_write32(s
->mem1
, addr
, value
);
531 TRACE(TNETW
, logout("addr %s = 0x%08x\n", tnetw1130_regname1(addr
), value
));
534 /*****************************************************************************
538 ****************************************************************************/
540 static uint64_t tnetw1130_read0(void *opaque
, hwaddr addr
,
543 TNETW1130State
*d
= opaque
;
544 tnetw1130_t
*s
= &d
->tnetw1130
;
548 val
= tnetw1130_read0b(s
, addr
);
551 val
= tnetw1130_read0w(s
, addr
);
554 val
= tnetw1130_read0l(s
, addr
);
562 static void tnetw1130_write0(void *opaque
, hwaddr addr
,
563 uint64_t val
, unsigned size
)
565 TNETW1130State
*d
= opaque
;
566 tnetw1130_t
*s
= &d
->tnetw1130
;
569 tnetw1130_write0b(s
, addr
, val
);
572 tnetw1130_write0w(s
, addr
, val
);
575 tnetw1130_write0l(s
, addr
, val
);
582 static const MemoryRegionOps tnetw1130_ops0
= {
583 .read
= tnetw1130_read0
,
584 .write
= tnetw1130_write0
,
585 .endianness
= DEVICE_LITTLE_ENDIAN
,
588 static uint64_t tnetw1130_read1(void *opaque
, hwaddr addr
,
591 TNETW1130State
*d
= opaque
;
592 tnetw1130_t
*s
= &d
->tnetw1130
;
596 val
= tnetw1130_read1b(s
, addr
);
599 val
= tnetw1130_read1w(s
, addr
);
602 val
= tnetw1130_read1l(s
, addr
);
610 static void tnetw1130_write1(void *opaque
, hwaddr addr
,
611 uint64_t val
, unsigned size
)
613 TNETW1130State
*d
= opaque
;
614 tnetw1130_t
*s
= &d
->tnetw1130
;
617 tnetw1130_write1b(s
, addr
, val
);
620 tnetw1130_write1w(s
, addr
, val
);
623 tnetw1130_write1l(s
, addr
, val
);
630 static const MemoryRegionOps tnetw1130_ops1
= {
631 .read
= tnetw1130_read1
,
632 .write
= tnetw1130_write1
,
633 .endianness
= DEVICE_LITTLE_ENDIAN
,
636 /*****************************************************************************
640 ****************************************************************************/
642 static void nic_reset(void *opaque
)
644 //~ TNETW1130State *d = (TNETW1130State *) opaque;
645 TRACE(TNETW
, logout("%p\n", opaque
));
648 static int nic_can_receive(NetClientState
*ncs
)
650 //~ tnetw1130_t *s = qemu_get_nic_opaque(ncs);
652 TRACE(TNETW
, logout("\n"));
654 /* TODO: handle queued receive data. */
658 static ssize_t
nic_receive(NetClientState
*ncs
,
659 const uint8_t * buf
, size_t size
)
661 TRACE(TNETW
, logout("\n"));
665 static void nic_cleanup(NetClientState
*ncs
)
668 tnetw1130_t
*s
= qemu_get_nic_opaque(ncs
);
669 timer_del(d
->poll_timer
);
670 timer_free(d
->poll_timer
);
674 static void tnetw1130_pci_config(uint8_t *pci_conf
)
676 pci_set_word(pci_conf
+ PCI_STATUS
, 0x0210);
677 pci_set_long(pci_conf
+ PCI_CARDBUS_CIS
, 0x00001c02);
678 /* Address registers are set by pci_register_bar. */
679 /* Capabilities Pointer, CLOFS */
680 pci_set_long(pci_conf
+ PCI_CAPABILITY_LIST
, 0x00000040);
681 /* 0x38 reserved, returns 0 */
682 /* MNGNT = 11, MXLAT = 52, IPIN = 0 */
683 /* TODO: Split next command using pci_set_byte. */
684 pci_set_long(pci_conf
+ PCI_INTERRUPT_LINE
, 0x00000100);
685 /* Power Management Capabilities */
686 pci_set_long(pci_conf
+ 0x40, 0x7e020001);
687 /* Power Management Control and Status */
688 //~ pci_set_long(pci_conf + 0x44, 0x00000000);
689 /* 0x48...0xff reserved, returns 0 */
692 static NetClientInfo net_info
= {
693 .type
= NET_CLIENT_OPTIONS_KIND_NIC
,
694 .size
= sizeof(NICState
),
695 .can_receive
= nic_can_receive
,
696 .receive
= nic_receive
,
697 .cleanup
= nic_cleanup
,
700 static int tnetw1130_init(PCIDevice
*pci_dev
)
702 TNETW1130State
*d
= DO_UPCAST(TNETW1130State
, dev
, pci_dev
);
703 tnetw1130_t
*s
= &d
->tnetw1130
;
706 tnetw1130_pci_config(d
->dev
.config
);
708 /* Handler for memory-mapped I/O */
709 memory_region_init_io(&d
->mmio_bar0
, &tnetw1130_ops0
, s
, "tnetw1130_mmio0",
710 TNETW1130_MEM0_SIZE
);
711 memory_region_init_io(&d
->mmio_bar1
, &tnetw1130_ops1
, s
, "tnetw1130_mmio1",
712 TNETW1130_MEM1_SIZE
);
714 pci_register_bar(&d
->dev
, 0, PCI_BASE_ADDRESS_SPACE_MEMORY
, &d
->mmio_bar0
);
715 pci_register_bar(&d
->dev
, 1, PCI_BASE_ADDRESS_SPACE_MEMORY
, &d
->mmio_bar1
);
718 static const char macaddr
[6] = {
719 0x00, 0x60, 0x65, 0x02, 0x4a, 0x8e
721 memcpy(s
->conf
.macaddr
.a
, macaddr
, 6);
723 qemu_macaddr_default_if_unset(&s
->conf
.macaddr
);
726 s
->nic
= qemu_new_nic(&net_info
, &s
->conf
,
727 object_get_typename(OBJECT(pci_dev
)),
728 pci_dev
->qdev
.id
, s
);
730 qemu_format_nic_info_str(qemu_get_queue(s
->nic
), s
->conf
.macaddr
.a
);
732 qemu_register_reset(nic_reset
, d
);
737 static int pci_tnetw1130_init(PCIDevice
* pci_dev
)
739 #if defined(DEBUG_TNETW1130)
740 set_traceflags("DEBUG_TNETW1130");
742 TRACE(TNETW
, logout("\n"));
743 return tnetw1130_init(pci_dev
);
746 static void pci_tnetw1130_uninit(PCIDevice
*pci_dev
)
748 TNETW1130State
*s
= DO_UPCAST(TNETW1130State
, dev
, pci_dev
);
749 memory_region_destroy(&s
->mmio_bar0
);
750 memory_region_destroy(&s
->mmio_bar1
);
751 qemu_del_nic(s
->tnetw1130
.nic
);
754 static const VMStateDescription vmstate_pci_tnetw1130
= {
757 .minimum_version_id
= 1,
758 .minimum_version_id_old
= 1,
759 .fields
= (VMStateField
[]) {
760 VMSTATE_PCI_DEVICE(dev
, TNETW1130State
),
761 // TODO: entries for tnetw1130 are missing here.
762 //~ VMSTATE_UINT32(rxbuf_size, E1000State),
763 //~ VMSTATE_UINT32(rxbuf_min_shift, E1000State),
764 //~ VMSTATE_UINT32(eecd_state.val_in, E1000State),
765 //~ VMSTATE_UINT16(eecd_state.bitnum_in, E1000State),
766 //~ VMSTATE_UINT16(eecd_state.bitnum_out, E1000State),
767 //~ VMSTATE_UINT16(eecd_state.reading, E1000State),
768 //~ VMSTATE_UINT32(eecd_state.old_eecd, E1000State),
769 //~ VMSTATE_UINT8(tx.ipcss, E1000State),
770 //~ VMSTATE_UINT8(tx.ipcso, E1000State),
771 //~ VMSTATE_UINT16(tx.ipcse, E1000State),
772 //~ VMSTATE_UINT8(tx.tucss, E1000State),
773 //~ VMSTATE_UINT8(tx.tucso, E1000State),
774 //~ VMSTATE_UINT16(tx.tucse, E1000State),
775 //~ VMSTATE_UINT32(tx.paylen, E1000State),
776 //~ VMSTATE_UINT8(tx.hdr_len, E1000State),
777 //~ VMSTATE_UINT16(tx.mss, E1000State),
778 //~ VMSTATE_UINT16(tx.size, E1000State),
779 //~ VMSTATE_UINT16(tx.tso_frames, E1000State),
780 //~ VMSTATE_UINT8(tx.sum_needed, E1000State),
781 //~ VMSTATE_INT8(tx.ip, E1000State),
782 //~ VMSTATE_INT8(tx.tcp, E1000State),
783 //~ VMSTATE_BUFFER(tx.header, E1000State),
784 //~ VMSTATE_BUFFER(tx.data, E1000State),
785 //~ VMSTATE_UINT16_ARRAY(eeprom_data, E1000State, 64),
786 //~ VMSTATE_UINT16_ARRAY(phy_reg, E1000State, 0x20),
787 //~ VMSTATE_UINT32(mac_reg[CTRL], E1000State),
788 //~ VMSTATE_UINT32(mac_reg[EECD], E1000State),
789 //~ VMSTATE_UINT32(mac_reg[EERD], E1000State),
790 //~ VMSTATE_UINT32(mac_reg[GPRC], E1000State),
791 //~ VMSTATE_UINT32(mac_reg[GPTC], E1000State),
792 //~ VMSTATE_UINT32(mac_reg[ICR], E1000State),
793 //~ VMSTATE_UINT32(mac_reg[ICS], E1000State),
794 //~ VMSTATE_UINT32(mac_reg[IMC], E1000State),
795 //~ VMSTATE_UINT32(mac_reg[IMS], E1000State),
796 //~ VMSTATE_UINT32(mac_reg[LEDCTL], E1000State),
797 //~ VMSTATE_UINT32(mac_reg[MANC], E1000State),
798 //~ VMSTATE_UINT32(mac_reg[MDIC], E1000State),
799 //~ VMSTATE_UINT32(mac_reg[MPC], E1000State),
800 //~ VMSTATE_UINT32(mac_reg[PBA], E1000State),
801 //~ VMSTATE_UINT32(mac_reg[RCTL], E1000State),
802 //~ VMSTATE_UINT32(mac_reg[RDBAH], E1000State),
803 //~ VMSTATE_UINT32(mac_reg[RDBAL], E1000State),
804 //~ VMSTATE_UINT32(mac_reg[RDH], E1000State),
805 //~ VMSTATE_UINT32(mac_reg[RDLEN], E1000State),
806 //~ VMSTATE_UINT32(mac_reg[RDT], E1000State),
807 //~ VMSTATE_UINT32(mac_reg[STATUS], E1000State),
808 //~ VMSTATE_UINT32(mac_reg[SWSM], E1000State),
809 //~ VMSTATE_UINT32(mac_reg[TCTL], E1000State),
810 //~ VMSTATE_UINT32(mac_reg[TDBAH], E1000State),
811 //~ VMSTATE_UINT32(mac_reg[TDBAL], E1000State),
812 //~ VMSTATE_UINT32(mac_reg[TDH], E1000State),
813 //~ VMSTATE_UINT32(mac_reg[TDLEN], E1000State),
814 //~ VMSTATE_UINT32(mac_reg[TDT], E1000State),
815 //~ VMSTATE_UINT32(mac_reg[TORH], E1000State),
816 //~ VMSTATE_UINT32(mac_reg[TORL], E1000State),
817 //~ VMSTATE_UINT32(mac_reg[TOTH], E1000State),
818 //~ VMSTATE_UINT32(mac_reg[TOTL], E1000State),
819 //~ VMSTATE_UINT32(mac_reg[TPR], E1000State),
820 //~ VMSTATE_UINT32(mac_reg[TPT], E1000State),
821 //~ VMSTATE_UINT32(mac_reg[TXDCTL], E1000State),
822 //~ VMSTATE_UINT32(mac_reg[WUFC], E1000State),
823 //~ VMSTATE_UINT32(mac_reg[VET], E1000State),
824 //~ VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, RA, 32),
825 //~ VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128),
826 //~ VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
827 VMSTATE_END_OF_LIST()
831 static Property tnetw1130_properties
[] = {
832 DEFINE_NIC_PROPERTIES(TNETW1130State
, tnetw1130
.conf
),
833 DEFINE_PROP_END_OF_LIST(),
836 static void tnetw1130_class_init(ObjectClass
*klass
, void *data
)
838 DeviceClass
*dc
= DEVICE_CLASS(klass
);
839 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
841 dc
->desc
= "Texas Instruments TNETW1130";
842 dc
->props
= tnetw1130_properties
;
843 //~ dc->reset = qdev_tnetw1130_reset;
844 dc
->vmsd
= &vmstate_pci_tnetw1130
;
845 //~ k->romfile = "pxe-tnetw1130.rom";
846 k
->init
= pci_tnetw1130_init
;
847 k
->exit
= pci_tnetw1130_uninit
;
848 k
->vendor_id
= PCI_VENDOR_ID_TI
;
849 /* wireless network controller */
850 k
->class_id
= PCI_CLASS_NETWORK_OTHER
;
851 k
->device_id
= 0x9066;
852 //~ k->revision = 0x01;
853 k
->subsystem_vendor_id
= PCI_VENDOR_ID_TI
;
854 k
->subsystem_id
= 0x9067;
857 static const TypeInfo pci_tnetw1130_info
= {
859 .parent
= TYPE_PCI_DEVICE
,
860 .instance_size
= sizeof(TNETW1130State
),
861 .class_init
= tnetw1130_class_init
,
864 static void tnetw1130_register_types(void)
866 type_register_static(&pci_tnetw1130_info
);
869 type_init(tnetw1130_register_types
)
873 00:0a.0 Network controller: Texas Instruments ACX 111 54Mbps Wireless Interface
874 Subsystem: Abocom Systems Inc: Unknown device ab90
875 Flags: bus master, medium devsel, latency 32, IRQ 10
876 Memory at dffdc000 (32-bit, non-prefetchable) [size=8K]
877 Memory at dffa0000 (32-bit, non-prefetchable) [size=128K]
878 Capabilities: [40] Power Management version 2
880 04:08.0 Network controller: Texas Instruments ACX 111 54Mbps Wireless Interface
881 Subsystem: Texas Instruments Unknown device 9067
882 Flags: medium devsel, IRQ 50
883 Memory at faafe000 (32-bit, non-prefetchable) [size=8K]
884 Memory at faac0000 (32-bit, non-prefetchable) [size=128K]
885 Capabilities: [40] Power Management version 2
887 01:08.0 Network controller: Texas Instruments ACX 111 54Mbps Wireless Interface
888 Subsystem: Netgear Unknown device 4c00
889 Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
890 Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
891 Latency: 32, Cache Line Size: 32 bytes
892 Interrupt: pin A routed to IRQ 201
893 Region 0: Memory at eb020000 (32-bit, non-prefetchable) [size=8K]
894 Region 1: Memory at eb000000 (32-bit, non-prefetchable) [size=128K]
895 Capabilities: [40] Power Management version 2
896 Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
897 Status: D0 PME-Enable- DSel=0 DScale=0 PME-
899 00:09.0 Network controller: Texas Instruments ACX 111 54Mbps Wireless Interface
900 Subsystem: D-Link System Inc: Unknown device 3b04
901 Flags: medium devsel, IRQ 11
902 Memory at de020000 (32-bit, non-prefetchable) [size=8K]
903 Memory at de000000 (32-bit, non-prefetchable) [size=128K]
904 Capabilities: [40] Power Management version 2
906 0000:02:08.0 Network controller: Texas Instruments ACX 111 54Mbps Wireless Interface
907 Subsystem: Abocom Systems Inc: Unknown device ab90
908 Flags: bus master, medium devsel, latency 32, IRQ 10
909 Memory at f8140000 (32-bit, non-prefetchable) [size=8K]
910 Memory at f8100000 (32-bit, non-prefetchable) [size=128K]
911 Capabilities: [40] Power Management version 2
913 02:0d.0 Network controller: Texas Instruments ACX 111 54Mbps Wireless Interface
914 Subsystem: D-Link System Inc Unknown device 3b04
915 Flags: bus master, medium devsel, latency 64, IRQ 10
916 Memory at feafc000 (32-bit, non-prefetchable) [size=8K]
917 Memory at feac0000 (32-bit, non-prefetchable) [size=128K]
918 Capabilities: [40] Power Management version 2
920 #define AVALANCHE_VLYNQ0_MEM1_BASE 0x04000000 VLYNQ 0 memory mapped
921 #define AVALANCHE_VLYNQ0_MEM2_BASE 0x04022000 VLYNQ 0 memory mapped
922 uint32_t vlynq0mem1[8 * KiB / 4]; // 0x04000000
923 uint32_t vlynq0mem2[128 * KiB / 4]; // 0x04022000
924 vlynq0mem2 + 0x0001e0f0 Mailbox (from ACX111)?
925 vlynq0mem2 + 0x0001e108 Command (to ACX111)?
927 write_reg32(adev, IO_ACX_EEPROM_CFG, 0);
928 write_reg32(adev, IO_ACX_EEPROM_ADDR, addr);
930 write_reg32(adev, IO_ACX_EEPROM_CTL, 2);
931 while (read_reg16(adev, IO_ACX_EEPROM_CTL)) {
934 *charbuf = read_reg8(adev, IO_ACX_EEPROM_DATA);
936 ACX111 PCI control block
938 0xa4041000 / 0x00: 0x9066104c
939 0xa4041004 / 0x04: 0x02100000
940 0xa4041008 / 0x08: 0x02800000
941 0xa404100c / 0x0c: 0x00000000
942 0xa4041010 / 0x10: 0x00000000
943 0xa4041014 / 0x14: 0x00000000
944 0xa4041018 / 0x18: 0x00000000
945 0xa404101c / 0x1c: 0x00000000
946 0xa4041020 / 0x20: 0x00000000
947 0xa4041024 / 0x24: 0x00000000
948 0xa4041028 / 0x28: 0x00001c02
949 0xa404102c / 0x2c: 0x9067104c
950 0xa4041030 / 0x30: 0x00000000
951 0xa4041034 / 0x34: 0x00000040
952 0xa4041038 / 0x38: 0x00000000
953 0xa404103c / 0x3c: 0x00000100
954 0xa4041040 / 0x40: 0x7e020001
956 //~ lspci -x: 00: 4c 10 66 90 07 01 10 02 00 00 80 02 04 40 00 00
957 //~ lspci -x: 10: 00 c0 af fe 00 00 ac fe 00 00 00 00 00 00 00 00
958 //~ lspci -x: 20: 00 00 00 00 00 00 00 00 02 1c 00 00 86 11 04 3b
959 //~ lspci -x: 30: 00 00 00 00 40 00 00 00 00 00 00 00 0a 01 00 00
962 A1 { .size = 0x22000, .offset = 0xf0000000 },
963 { .size = 0x40000, .offset = 0xc0000000 },
964 A2 { .size = 0x40000, .offset = 0xc0000000 },
965 { .size = 0x22000, .offset = 0xf0000000 },
967 u32 vlynq_get_mapped(struct vlynq_device *dev, int res)