usb: Fix compilation for Windows
[qemu/ar7.git] / hw / net / tnetw1130.c
bloba35874050aa08f6e17aa568765b19f9792d6768e
1 /*
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.
21 * TODO:
22 * - Add save, load support.
23 * - Much more emulation is needed.
26 #include "qemu/osdep.h"
27 #include "hw.h"
28 #include "net/net.h"
29 #include "pci/pci.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)
42 #define KiB 1024
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__)
55 #else
56 # define logout(fmt, ...) ((void)0)
57 #endif
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. */
65 #define LOG_PHY 1
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)
71 #else
72 # define TRACE(condition, command) ((void)0)
73 #endif
75 //~ static int tnetw1130_instance = 0;
77 typedef struct {
78 PCIDevice dev;
79 MemoryRegion mmio_bar0;
80 MemoryRegion mmio_bar1;
81 tnetw1130_t tnetw1130;
82 } TNETW1130State;
84 typedef enum {
85 CMD_MAILBOX = 0x0001e108, /* ECPU_CTRL? */
86 INFO_MAILBOX = 0x0001e0f0, /* HINT_STS_ND? */
87 } tnetw1130_memory_offset_t;
89 typedef enum {
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 */
105 #else
106 ACX1xx_CMD_MEM_READ = 0x0d,
107 ACX1xx_CMD_MEM_WRITE = 0x0e,
108 #endif
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;
127 /* IRQ Constants */
128 typedef enum {
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 /*****************************************************************************
149 * Helper functions.
151 ****************************************************************************/
153 #if defined(DEBUG_TNETW1130)
154 static uint32_t traceflags = 1;
156 #define TNETW traceflags
158 #define SET_TRACEFLAG(name) \
159 do { \
160 char *substring = strstr(envvalue, #name); \
161 if (substring) { \
162 name = ((substring > envvalue && substring[-1] == '-') ? 0 : 1); \
164 TRACE(name, logout("Logging enabled for " #name "\n")); \
165 } while(0)
167 static void set_traceflags(const char *envname)
169 const char *envvalue = getenv(envname);
170 if (envvalue != 0) {
171 unsigned long ul = strtoul(envvalue, 0, 0);
172 if ((ul == 0) && strstr(envvalue, "ALL")) ul = 0xffffffff;
173 traceflags = ul;
174 SET_TRACEFLAG(TNETW);
177 #endif /* DEBUG_TNETW1130 */
179 static uint16_t reg_read16(const uint8_t * reg, uint32_t addr)
181 assert(!(addr & 1));
182 return le16_to_cpu(*(uint16_t *) (&reg[addr]));
185 static void reg_write16(uint8_t * reg, uint32_t addr, uint16_t value)
187 assert(!(addr & 1));
188 *(uint16_t *) (&reg[addr]) = cpu_to_le16(value);
191 static uint32_t reg_read32(const uint8_t * reg, uint32_t addr)
193 assert(!(addr & 3));
194 return le32_to_cpu(*(uint32_t *) (&reg[addr]));
197 static void reg_write32(uint8_t * reg, uint32_t addr, uint32_t value)
199 assert(!(addr & 3));
200 *(uint32_t *) (&reg[addr]) = cpu_to_le32(value);
203 #if defined(DEBUG_TNETW1130)
205 typedef struct {
206 unsigned offset;
207 const char *name;
208 } offset_name_t;
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) {
217 name = o2n->name;
218 break;
221 return name;
224 #define ENTRY(entry) { TNETW1130_##entry, #entry }
225 static const offset_name_t addr2reg[] = {
226 ENTRY(SOFT_RESET),
227 ENTRY(SLV_MEM_ADDR),
228 ENTRY(SLV_MEM_DATA),
229 ENTRY(SLV_MEM_CTL),
230 ENTRY(IRQ_MASK),
231 ENTRY(IRQ_STATUS_CLEAR),
232 ENTRY(IRQ_ACK),
233 ENTRY(HINT_TRIG),
234 ENTRY(IRQ_STATUS_NON_DES),
235 ENTRY(EE_START),
236 ENTRY(ECPU_CTRL),
237 ENTRY(ENABLE),
238 ENTRY(EEPROM_CTL),
239 ENTRY(EEPROM_ADDR),
240 ENTRY(EEPROM_DATA),
241 ENTRY(EEPROM_CFG),
242 ENTRY(PHY_ADDR),
243 ENTRY(PHY_DATA),
244 ENTRY(PHY_CTL),
245 ENTRY(GPIO_OE),
246 ENTRY(GPIO_OUT),
247 ENTRY(CMD_MAILBOX_OFFS),
248 ENTRY(INFO_MAILBOX_OFFS),
249 ENTRY(EEPROM_INFORMATION),
250 { 0 }
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);
263 switch (addr) {
264 case CMD_MAILBOX:
265 name = "CMD_MAILBOX";
266 break;
267 case INFO_MAILBOX:
268 name = "INFO_MAILBOX";
269 break;
271 return name;
274 #undef ENTRY
275 #define ENTRY(entry) { ACX1xx_CMD_##entry, #entry }
276 static const offset_name_t cmd2name[] = {
277 ENTRY(RESET),
278 ENTRY(INTERROGATE),
279 ENTRY(CONFIGURE),
280 ENTRY(ENABLE_RX),
281 ENTRY(ENABLE_TX),
282 ENTRY(DISABLE_RX),
283 ENTRY(DISABLE_TX),
284 ENTRY(FLUSH_QUEUE),
285 ENTRY(SCAN),
286 ENTRY(STOP_SCAN),
287 ENTRY(CONFIG_TIM),
288 ENTRY(JOIN),
289 ENTRY(WEP_MGMT),
290 ENTRY(MEM_READ),
291 ENTRY(MEM_WRITE),
292 ENTRY(SLEEP),
293 ENTRY(WAKE),
294 ENTRY(UNKNOWN_11),
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),
301 { 0 }
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);
324 switch (cmd) {
325 case ACX1xx_CMD_RESET: /* 0x00 */
326 tnetw1130_cmd_reset(s);
327 break;
328 case ACX1xx_CMD_INTERROGATE: /* 0x01 */
329 tnetw1130_cmd_interrogate(s);
330 break;
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 */
337 break;
341 static void tnetw1130_reset(tnetw1130_t *s)
343 MISSING();
346 static uint8_t tnetw1130_read0b(tnetw1130_t *s, hwaddr addr)
348 uint8_t value = 0;
349 if (addr < TNETW1130_MEM0_SIZE) {
350 value = s->mem0[addr];
351 } else {
352 UNEXPECTED();
354 //~ } else if (addr -= 0x20000, addr == TNETW1130_SOFT_RESET) {
355 TRACE(TNETW, logout("addr %s = 0x%02x\n", tnetw1130_regname(addr), value));
356 return value;
359 /* Radio type names. */
360 typedef enum {
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,
366 } radio_t;
368 static uint16_t tnetw1130_read0w(tnetw1130_t *s, hwaddr addr)
370 uint16_t value = 0;
371 if (addr < TNETW1130_MEM0_SIZE) {
372 value = reg_read16(s->mem0, addr);
374 if (0) {
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) {
382 value = 0;
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));
387 return value;
390 static uint32_t tnetw1130_read0l(tnetw1130_t *s, hwaddr addr)
392 uint32_t value = 0;
393 assert(addr < TNETW1130_MEM0_SIZE);
394 value = reg_read32(s->mem0, addr);
395 if (0) {
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) {
399 value = CMD_MAILBOX;
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));
404 return value;
407 static void tnetw1130_write0b(tnetw1130_t *s, hwaddr addr,
408 uint8_t value)
410 if (addr < TNETW1130_MEM0_SIZE) {
411 s->mem0[addr] = value;
412 } else {
413 UNEXPECTED();
415 TRACE(TNETW, logout("addr %s = 0x%02x\n", tnetw1130_regname(addr), value));
418 static void tnetw1130_write0w(tnetw1130_t *s, hwaddr addr,
419 uint16_t value)
421 if (addr < TNETW1130_MEM0_SIZE) {
422 reg_write16(s->mem0, addr, value);
423 } else {
424 UNEXPECTED();
426 if (addr == TNETW1130_SOFT_RESET) {
427 if (value & 1) {
428 TRACE(TNETW, logout("soft reset\n"));
430 } else if (addr == TNETW1130_INT_TRIG) {
431 if (value == 1) {
432 TRACE(TNETW, logout("trigger interrupt, status, cmd = %s\n",
433 tnetw1130_cmdname(reg_read16(s->mem1, CMD_MAILBOX))));
434 tnetw1130_cmd(s);
435 } else {
436 UNEXPECTED();
438 } else if (addr == TNETW1130_IRQ_ACK) {
439 /* !!! must reset irq */
440 s->irq_status &= ~value;
441 } else if (addr == TNETW1130_EE_START) {
442 if (value & 1) {
443 TRACE(TNETW, logout("start burst read from EEPROM\n"));
445 } else if (addr == TNETW1130_ECPU_CTRL) {
446 if (value & 1) {
447 TRACE(TNETW, logout("halt eCPU\n"));
448 //~ reg_write16(s->mem0, addr, value & ~1);
449 } else {
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,
458 uint32_t value)
460 if (addr < TNETW1130_MEM0_SIZE) {
461 reg_write32(s->mem0, addr, value);
463 if (addr == TNETW1130_SLV_MEM_ADDR) {
464 s->fw_addr = value;
465 if (value >= TNETW1130_FW_SIZE) {
466 UNEXPECTED();
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) {
471 if (value == 0) {
472 TRACE(TNETW, logout("basic mode\n"));
473 } else if (value == 1) {
474 TRACE(TNETW, logout("autoincrement mode\n"));
475 MISSING();
476 } else {
477 UNEXPECTED();
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)
486 uint8_t value = 0;
487 assert(addr < TNETW1130_MEM1_SIZE);
488 value = s->mem1[addr];
489 TRACE(TNETW, logout("addr %s = 0x%02x\n", tnetw1130_regname1(addr), value));
490 return value;
493 static uint16_t tnetw1130_read1w(tnetw1130_t *s, hwaddr addr)
495 uint16_t value = 0;
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));
499 return 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));
507 return value;
510 static void tnetw1130_write1b(tnetw1130_t *s, hwaddr addr,
511 uint8_t value)
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,
519 uint16_t value)
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,
527 uint32_t value)
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 /*****************************************************************************
536 * Memory mapped I/O.
538 ****************************************************************************/
540 static uint64_t tnetw1130_read0(void *opaque, hwaddr addr,
541 unsigned size)
543 TNETW1130State *d = opaque;
544 tnetw1130_t *s = &d->tnetw1130;
545 uint64_t val = 0;
546 switch (size) {
547 case 1:
548 val = tnetw1130_read0b(s, addr);
549 break;
550 case 2:
551 val = tnetw1130_read0w(s, addr);
552 break;
553 case 4:
554 val = tnetw1130_read0l(s, addr);
555 break;
556 default:
557 assert(!"bad size");
559 return val;
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;
567 switch (size) {
568 case 1:
569 tnetw1130_write0b(s, addr, val);
570 break;
571 case 2:
572 tnetw1130_write0w(s, addr, val);
573 break;
574 case 4:
575 tnetw1130_write0l(s, addr, val);
576 break;
577 default:
578 assert(!"bad size");
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,
589 unsigned size)
591 TNETW1130State *d = opaque;
592 tnetw1130_t *s = &d->tnetw1130;
593 uint64_t val = 0;
594 switch (size) {
595 case 1:
596 val = tnetw1130_read1b(s, addr);
597 break;
598 case 2:
599 val = tnetw1130_read1w(s, addr);
600 break;
601 case 4:
602 val = tnetw1130_read1l(s, addr);
603 break;
604 default:
605 assert(!"bad size");
607 return val;
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;
615 switch (size) {
616 case 1:
617 tnetw1130_write1b(s, addr, val);
618 break;
619 case 2:
620 tnetw1130_write1w(s, addr, val);
621 break;
622 case 4:
623 tnetw1130_write1l(s, addr, val);
624 break;
625 default:
626 assert(!"bad size");
630 static const MemoryRegionOps tnetw1130_ops1 = {
631 .read = tnetw1130_read1,
632 .write = tnetw1130_write1,
633 .endianness = DEVICE_LITTLE_ENDIAN,
636 /*****************************************************************************
638 * Other functions.
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. */
655 return 0;
658 static ssize_t nic_receive(NetClientState *ncs,
659 const uint8_t * buf, size_t size)
661 TRACE(TNETW, logout("\n"));
662 return size;
665 static void nic_cleanup(NetClientState *ncs)
667 #if 0
668 tnetw1130_t *s = qemu_get_nic_opaque(ncs);
669 timer_del(d->poll_timer);
670 timer_free(d->poll_timer);
671 #endif
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;
705 /* TI 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);
717 #if 0
718 static const char macaddr[6] = {
719 0x00, 0x60, 0x65, 0x02, 0x4a, 0x8e
721 memcpy(s->conf.macaddr.a, macaddr, 6);
722 #endif
723 qemu_macaddr_default_if_unset(&s->conf.macaddr);
724 tnetw1130_reset(s);
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);
734 return 0;
737 static int pci_tnetw1130_init(PCIDevice* pci_dev)
739 #if defined(DEBUG_TNETW1130)
740 set_traceflags("DEBUG_TNETW1130");
741 #endif
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 = {
755 .name = "tnetw1130",
756 .version_id = 1,
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 = {
858 .name = "tnetw1130",
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);
929 write_flush(adev);
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
961 vlynq.c
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)
968 B1 vertauscht
969 B2 nicht vertauscht
971 config_read
972 C1 vertauscht
973 C2 nicht vertauscht
975 config_write
976 D1 vertauscht
977 D2 nicht vertauscht
980 A1 B2 C2 D2:
984 /* eof */