dp8393x.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. /*
  2. * QEMU NS SONIC DP8393x netcard
  3. *
  4. * Copyright (c) 2008-2009 Herve Poussineau
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or (at your option) any later version.
  10. *
  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.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "hw.h"
  20. #include "qemu/timer.h"
  21. #include "net/net.h"
  22. #include "mips.h"
  23. //#define DEBUG_SONIC
  24. /* Calculate CRCs properly on Rx packets */
  25. #define SONIC_CALCULATE_RXCRC
  26. #if defined(SONIC_CALCULATE_RXCRC)
  27. /* For crc32 */
  28. #include <zlib.h>
  29. #endif
  30. #ifdef DEBUG_SONIC
  31. #define DPRINTF(fmt, ...) \
  32. do { printf("sonic: " fmt , ## __VA_ARGS__); } while (0)
  33. static const char* reg_names[] = {
  34. "CR", "DCR", "RCR", "TCR", "IMR", "ISR", "UTDA", "CTDA",
  35. "TPS", "TFC", "TSA0", "TSA1", "TFS", "URDA", "CRDA", "CRBA0",
  36. "CRBA1", "RBWC0", "RBWC1", "EOBC", "URRA", "RSA", "REA", "RRP",
  37. "RWP", "TRBA0", "TRBA1", "0x1b", "0x1c", "0x1d", "0x1e", "LLFA",
  38. "TTDA", "CEP", "CAP2", "CAP1", "CAP0", "CE", "CDP", "CDC",
  39. "SR", "WT0", "WT1", "RSC", "CRCT", "FAET", "MPT", "MDT",
  40. "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37",
  41. "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "DCR2" };
  42. #else
  43. #define DPRINTF(fmt, ...) do {} while (0)
  44. #endif
  45. #define SONIC_ERROR(fmt, ...) \
  46. do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
  47. #define SONIC_CR 0x00
  48. #define SONIC_DCR 0x01
  49. #define SONIC_RCR 0x02
  50. #define SONIC_TCR 0x03
  51. #define SONIC_IMR 0x04
  52. #define SONIC_ISR 0x05
  53. #define SONIC_UTDA 0x06
  54. #define SONIC_CTDA 0x07
  55. #define SONIC_TPS 0x08
  56. #define SONIC_TFC 0x09
  57. #define SONIC_TSA0 0x0a
  58. #define SONIC_TSA1 0x0b
  59. #define SONIC_TFS 0x0c
  60. #define SONIC_URDA 0x0d
  61. #define SONIC_CRDA 0x0e
  62. #define SONIC_CRBA0 0x0f
  63. #define SONIC_CRBA1 0x10
  64. #define SONIC_RBWC0 0x11
  65. #define SONIC_RBWC1 0x12
  66. #define SONIC_EOBC 0x13
  67. #define SONIC_URRA 0x14
  68. #define SONIC_RSA 0x15
  69. #define SONIC_REA 0x16
  70. #define SONIC_RRP 0x17
  71. #define SONIC_RWP 0x18
  72. #define SONIC_TRBA0 0x19
  73. #define SONIC_TRBA1 0x1a
  74. #define SONIC_LLFA 0x1f
  75. #define SONIC_TTDA 0x20
  76. #define SONIC_CEP 0x21
  77. #define SONIC_CAP2 0x22
  78. #define SONIC_CAP1 0x23
  79. #define SONIC_CAP0 0x24
  80. #define SONIC_CE 0x25
  81. #define SONIC_CDP 0x26
  82. #define SONIC_CDC 0x27
  83. #define SONIC_SR 0x28
  84. #define SONIC_WT0 0x29
  85. #define SONIC_WT1 0x2a
  86. #define SONIC_RSC 0x2b
  87. #define SONIC_CRCT 0x2c
  88. #define SONIC_FAET 0x2d
  89. #define SONIC_MPT 0x2e
  90. #define SONIC_MDT 0x2f
  91. #define SONIC_DCR2 0x3f
  92. #define SONIC_CR_HTX 0x0001
  93. #define SONIC_CR_TXP 0x0002
  94. #define SONIC_CR_RXDIS 0x0004
  95. #define SONIC_CR_RXEN 0x0008
  96. #define SONIC_CR_STP 0x0010
  97. #define SONIC_CR_ST 0x0020
  98. #define SONIC_CR_RST 0x0080
  99. #define SONIC_CR_RRRA 0x0100
  100. #define SONIC_CR_LCAM 0x0200
  101. #define SONIC_CR_MASK 0x03bf
  102. #define SONIC_DCR_DW 0x0020
  103. #define SONIC_DCR_LBR 0x2000
  104. #define SONIC_DCR_EXBUS 0x8000
  105. #define SONIC_RCR_PRX 0x0001
  106. #define SONIC_RCR_LBK 0x0002
  107. #define SONIC_RCR_FAER 0x0004
  108. #define SONIC_RCR_CRCR 0x0008
  109. #define SONIC_RCR_CRS 0x0020
  110. #define SONIC_RCR_LPKT 0x0040
  111. #define SONIC_RCR_BC 0x0080
  112. #define SONIC_RCR_MC 0x0100
  113. #define SONIC_RCR_LB0 0x0200
  114. #define SONIC_RCR_LB1 0x0400
  115. #define SONIC_RCR_AMC 0x0800
  116. #define SONIC_RCR_PRO 0x1000
  117. #define SONIC_RCR_BRD 0x2000
  118. #define SONIC_RCR_RNT 0x4000
  119. #define SONIC_TCR_PTX 0x0001
  120. #define SONIC_TCR_BCM 0x0002
  121. #define SONIC_TCR_FU 0x0004
  122. #define SONIC_TCR_EXC 0x0040
  123. #define SONIC_TCR_CRSL 0x0080
  124. #define SONIC_TCR_NCRS 0x0100
  125. #define SONIC_TCR_EXD 0x0400
  126. #define SONIC_TCR_CRCI 0x2000
  127. #define SONIC_TCR_PINT 0x8000
  128. #define SONIC_ISR_RBE 0x0020
  129. #define SONIC_ISR_RDE 0x0040
  130. #define SONIC_ISR_TC 0x0080
  131. #define SONIC_ISR_TXDN 0x0200
  132. #define SONIC_ISR_PKTRX 0x0400
  133. #define SONIC_ISR_PINT 0x0800
  134. #define SONIC_ISR_LCD 0x1000
  135. typedef struct dp8393xState {
  136. /* Hardware */
  137. int it_shift;
  138. qemu_irq irq;
  139. #ifdef DEBUG_SONIC
  140. int irq_level;
  141. #endif
  142. QEMUTimer *watchdog;
  143. int64_t wt_last_update;
  144. NICConf conf;
  145. NICState *nic;
  146. MemoryRegion *address_space;
  147. MemoryRegion mmio;
  148. /* Registers */
  149. uint8_t cam[16][6];
  150. uint16_t regs[0x40];
  151. /* Temporaries */
  152. uint8_t tx_buffer[0x10000];
  153. int loopback_packet;
  154. /* Memory access */
  155. void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write);
  156. void* mem_opaque;
  157. } dp8393xState;
  158. static void dp8393x_update_irq(dp8393xState *s)
  159. {
  160. int level = (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0;
  161. #ifdef DEBUG_SONIC
  162. if (level != s->irq_level) {
  163. s->irq_level = level;
  164. if (level) {
  165. DPRINTF("raise irq, isr is 0x%04x\n", s->regs[SONIC_ISR]);
  166. } else {
  167. DPRINTF("lower irq\n");
  168. }
  169. }
  170. #endif
  171. qemu_set_irq(s->irq, level);
  172. }
  173. static void do_load_cam(dp8393xState *s)
  174. {
  175. uint16_t data[8];
  176. int width, size;
  177. uint16_t index = 0;
  178. width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
  179. size = sizeof(uint16_t) * 4 * width;
  180. while (s->regs[SONIC_CDC] & 0x1f) {
  181. /* Fill current entry */
  182. s->memory_rw(s->mem_opaque,
  183. (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP],
  184. (uint8_t *)data, size, 0);
  185. s->cam[index][0] = data[1 * width] & 0xff;
  186. s->cam[index][1] = data[1 * width] >> 8;
  187. s->cam[index][2] = data[2 * width] & 0xff;
  188. s->cam[index][3] = data[2 * width] >> 8;
  189. s->cam[index][4] = data[3 * width] & 0xff;
  190. s->cam[index][5] = data[3 * width] >> 8;
  191. DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index,
  192. s->cam[index][0], s->cam[index][1], s->cam[index][2],
  193. s->cam[index][3], s->cam[index][4], s->cam[index][5]);
  194. /* Move to next entry */
  195. s->regs[SONIC_CDC]--;
  196. s->regs[SONIC_CDP] += size;
  197. index++;
  198. }
  199. /* Read CAM enable */
  200. s->memory_rw(s->mem_opaque,
  201. (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP],
  202. (uint8_t *)data, size, 0);
  203. s->regs[SONIC_CE] = data[0 * width];
  204. DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
  205. /* Done */
  206. s->regs[SONIC_CR] &= ~SONIC_CR_LCAM;
  207. s->regs[SONIC_ISR] |= SONIC_ISR_LCD;
  208. dp8393x_update_irq(s);
  209. }
  210. static void do_read_rra(dp8393xState *s)
  211. {
  212. uint16_t data[8];
  213. int width, size;
  214. /* Read memory */
  215. width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
  216. size = sizeof(uint16_t) * 4 * width;
  217. s->memory_rw(s->mem_opaque,
  218. (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_RRP],
  219. (uint8_t *)data, size, 0);
  220. /* Update SONIC registers */
  221. s->regs[SONIC_CRBA0] = data[0 * width];
  222. s->regs[SONIC_CRBA1] = data[1 * width];
  223. s->regs[SONIC_RBWC0] = data[2 * width];
  224. s->regs[SONIC_RBWC1] = data[3 * width];
  225. DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n",
  226. s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1],
  227. s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]);
  228. /* Go to next entry */
  229. s->regs[SONIC_RRP] += size;
  230. /* Handle wrap */
  231. if (s->regs[SONIC_RRP] == s->regs[SONIC_REA]) {
  232. s->regs[SONIC_RRP] = s->regs[SONIC_RSA];
  233. }
  234. /* Check resource exhaustion */
  235. if (s->regs[SONIC_RRP] == s->regs[SONIC_RWP])
  236. {
  237. s->regs[SONIC_ISR] |= SONIC_ISR_RBE;
  238. dp8393x_update_irq(s);
  239. }
  240. /* Done */
  241. s->regs[SONIC_CR] &= ~SONIC_CR_RRRA;
  242. }
  243. static void do_software_reset(dp8393xState *s)
  244. {
  245. qemu_del_timer(s->watchdog);
  246. s->regs[SONIC_CR] &= ~(SONIC_CR_LCAM | SONIC_CR_RRRA | SONIC_CR_TXP | SONIC_CR_HTX);
  247. s->regs[SONIC_CR] |= SONIC_CR_RST | SONIC_CR_RXDIS;
  248. }
  249. static void set_next_tick(dp8393xState *s)
  250. {
  251. uint32_t ticks;
  252. int64_t delay;
  253. if (s->regs[SONIC_CR] & SONIC_CR_STP) {
  254. qemu_del_timer(s->watchdog);
  255. return;
  256. }
  257. ticks = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
  258. s->wt_last_update = qemu_get_clock_ns(vm_clock);
  259. delay = get_ticks_per_sec() * ticks / 5000000;
  260. qemu_mod_timer(s->watchdog, s->wt_last_update + delay);
  261. }
  262. static void update_wt_regs(dp8393xState *s)
  263. {
  264. int64_t elapsed;
  265. uint32_t val;
  266. if (s->regs[SONIC_CR] & SONIC_CR_STP) {
  267. qemu_del_timer(s->watchdog);
  268. return;
  269. }
  270. elapsed = s->wt_last_update - qemu_get_clock_ns(vm_clock);
  271. val = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
  272. val -= elapsed / 5000000;
  273. s->regs[SONIC_WT1] = (val >> 16) & 0xffff;
  274. s->regs[SONIC_WT0] = (val >> 0) & 0xffff;
  275. set_next_tick(s);
  276. }
  277. static void do_start_timer(dp8393xState *s)
  278. {
  279. s->regs[SONIC_CR] &= ~SONIC_CR_STP;
  280. set_next_tick(s);
  281. }
  282. static void do_stop_timer(dp8393xState *s)
  283. {
  284. s->regs[SONIC_CR] &= ~SONIC_CR_ST;
  285. update_wt_regs(s);
  286. }
  287. static void do_receiver_enable(dp8393xState *s)
  288. {
  289. s->regs[SONIC_CR] &= ~SONIC_CR_RXDIS;
  290. }
  291. static void do_receiver_disable(dp8393xState *s)
  292. {
  293. s->regs[SONIC_CR] &= ~SONIC_CR_RXEN;
  294. }
  295. static void do_transmit_packets(dp8393xState *s)
  296. {
  297. NetClientState *nc = qemu_get_queue(s->nic);
  298. uint16_t data[12];
  299. int width, size;
  300. int tx_len, len;
  301. uint16_t i;
  302. width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
  303. while (1) {
  304. /* Read memory */
  305. DPRINTF("Transmit packet at %08x\n",
  306. (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_CTDA]);
  307. size = sizeof(uint16_t) * 6 * width;
  308. s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA];
  309. s->memory_rw(s->mem_opaque,
  310. ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * width,
  311. (uint8_t *)data, size, 0);
  312. tx_len = 0;
  313. /* Update registers */
  314. s->regs[SONIC_TCR] = data[0 * width] & 0xf000;
  315. s->regs[SONIC_TPS] = data[1 * width];
  316. s->regs[SONIC_TFC] = data[2 * width];
  317. s->regs[SONIC_TSA0] = data[3 * width];
  318. s->regs[SONIC_TSA1] = data[4 * width];
  319. s->regs[SONIC_TFS] = data[5 * width];
  320. /* Handle programmable interrupt */
  321. if (s->regs[SONIC_TCR] & SONIC_TCR_PINT) {
  322. s->regs[SONIC_ISR] |= SONIC_ISR_PINT;
  323. } else {
  324. s->regs[SONIC_ISR] &= ~SONIC_ISR_PINT;
  325. }
  326. for (i = 0; i < s->regs[SONIC_TFC]; ) {
  327. /* Append fragment */
  328. len = s->regs[SONIC_TFS];
  329. if (tx_len + len > sizeof(s->tx_buffer)) {
  330. len = sizeof(s->tx_buffer) - tx_len;
  331. }
  332. s->memory_rw(s->mem_opaque,
  333. (s->regs[SONIC_TSA1] << 16) | s->regs[SONIC_TSA0],
  334. &s->tx_buffer[tx_len], len, 0);
  335. tx_len += len;
  336. i++;
  337. if (i != s->regs[SONIC_TFC]) {
  338. /* Read next fragment details */
  339. size = sizeof(uint16_t) * 3 * width;
  340. s->memory_rw(s->mem_opaque,
  341. ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * i) * width,
  342. (uint8_t *)data, size, 0);
  343. s->regs[SONIC_TSA0] = data[0 * width];
  344. s->regs[SONIC_TSA1] = data[1 * width];
  345. s->regs[SONIC_TFS] = data[2 * width];
  346. }
  347. }
  348. /* Handle Ethernet checksum */
  349. if (!(s->regs[SONIC_TCR] & SONIC_TCR_CRCI)) {
  350. /* Don't append FCS there, to look like slirp packets
  351. * which don't have one */
  352. } else {
  353. /* Remove existing FCS */
  354. tx_len -= 4;
  355. }
  356. if (s->regs[SONIC_RCR] & (SONIC_RCR_LB1 | SONIC_RCR_LB0)) {
  357. /* Loopback */
  358. s->regs[SONIC_TCR] |= SONIC_TCR_CRSL;
  359. if (nc->info->can_receive(nc)) {
  360. s->loopback_packet = 1;
  361. nc->info->receive(nc, s->tx_buffer, tx_len);
  362. }
  363. } else {
  364. /* Transmit packet */
  365. qemu_send_packet(nc, s->tx_buffer, tx_len);
  366. }
  367. s->regs[SONIC_TCR] |= SONIC_TCR_PTX;
  368. /* Write status */
  369. data[0 * width] = s->regs[SONIC_TCR] & 0x0fff; /* status */
  370. size = sizeof(uint16_t) * width;
  371. s->memory_rw(s->mem_opaque,
  372. (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA],
  373. (uint8_t *)data, size, 1);
  374. if (!(s->regs[SONIC_CR] & SONIC_CR_HTX)) {
  375. /* Read footer of packet */
  376. size = sizeof(uint16_t) * width;
  377. s->memory_rw(s->mem_opaque,
  378. ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * s->regs[SONIC_TFC]) * width,
  379. (uint8_t *)data, size, 0);
  380. s->regs[SONIC_CTDA] = data[0 * width] & ~0x1;
  381. if (data[0 * width] & 0x1) {
  382. /* EOL detected */
  383. break;
  384. }
  385. }
  386. }
  387. /* Done */
  388. s->regs[SONIC_CR] &= ~SONIC_CR_TXP;
  389. s->regs[SONIC_ISR] |= SONIC_ISR_TXDN;
  390. dp8393x_update_irq(s);
  391. }
  392. static void do_halt_transmission(dp8393xState *s)
  393. {
  394. /* Nothing to do */
  395. }
  396. static void do_command(dp8393xState *s, uint16_t command)
  397. {
  398. if ((s->regs[SONIC_CR] & SONIC_CR_RST) && !(command & SONIC_CR_RST)) {
  399. s->regs[SONIC_CR] &= ~SONIC_CR_RST;
  400. return;
  401. }
  402. s->regs[SONIC_CR] |= (command & SONIC_CR_MASK);
  403. if (command & SONIC_CR_HTX)
  404. do_halt_transmission(s);
  405. if (command & SONIC_CR_TXP)
  406. do_transmit_packets(s);
  407. if (command & SONIC_CR_RXDIS)
  408. do_receiver_disable(s);
  409. if (command & SONIC_CR_RXEN)
  410. do_receiver_enable(s);
  411. if (command & SONIC_CR_STP)
  412. do_stop_timer(s);
  413. if (command & SONIC_CR_ST)
  414. do_start_timer(s);
  415. if (command & SONIC_CR_RST)
  416. do_software_reset(s);
  417. if (command & SONIC_CR_RRRA)
  418. do_read_rra(s);
  419. if (command & SONIC_CR_LCAM)
  420. do_load_cam(s);
  421. }
  422. static uint16_t read_register(dp8393xState *s, int reg)
  423. {
  424. uint16_t val = 0;
  425. switch (reg) {
  426. /* Update data before reading it */
  427. case SONIC_WT0:
  428. case SONIC_WT1:
  429. update_wt_regs(s);
  430. val = s->regs[reg];
  431. break;
  432. /* Accept read to some registers only when in reset mode */
  433. case SONIC_CAP2:
  434. case SONIC_CAP1:
  435. case SONIC_CAP0:
  436. if (s->regs[SONIC_CR] & SONIC_CR_RST) {
  437. val = s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 - reg) + 1] << 8;
  438. val |= s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 - reg)];
  439. }
  440. break;
  441. /* All other registers have no special contrainst */
  442. default:
  443. val = s->regs[reg];
  444. }
  445. DPRINTF("read 0x%04x from reg %s\n", val, reg_names[reg]);
  446. return val;
  447. }
  448. static void write_register(dp8393xState *s, int reg, uint16_t val)
  449. {
  450. DPRINTF("write 0x%04x to reg %s\n", val, reg_names[reg]);
  451. switch (reg) {
  452. /* Command register */
  453. case SONIC_CR:
  454. do_command(s, val);
  455. break;
  456. /* Prevent write to read-only registers */
  457. case SONIC_CAP2:
  458. case SONIC_CAP1:
  459. case SONIC_CAP0:
  460. case SONIC_SR:
  461. case SONIC_MDT:
  462. DPRINTF("writing to reg %d invalid\n", reg);
  463. break;
  464. /* Accept write to some registers only when in reset mode */
  465. case SONIC_DCR:
  466. if (s->regs[SONIC_CR] & SONIC_CR_RST) {
  467. s->regs[reg] = val & 0xbfff;
  468. } else {
  469. DPRINTF("writing to DCR invalid\n");
  470. }
  471. break;
  472. case SONIC_DCR2:
  473. if (s->regs[SONIC_CR] & SONIC_CR_RST) {
  474. s->regs[reg] = val & 0xf017;
  475. } else {
  476. DPRINTF("writing to DCR2 invalid\n");
  477. }
  478. break;
  479. /* 12 lower bytes are Read Only */
  480. case SONIC_TCR:
  481. s->regs[reg] = val & 0xf000;
  482. break;
  483. /* 9 lower bytes are Read Only */
  484. case SONIC_RCR:
  485. s->regs[reg] = val & 0xffe0;
  486. break;
  487. /* Ignore most significant bit */
  488. case SONIC_IMR:
  489. s->regs[reg] = val & 0x7fff;
  490. dp8393x_update_irq(s);
  491. break;
  492. /* Clear bits by writing 1 to them */
  493. case SONIC_ISR:
  494. val &= s->regs[reg];
  495. s->regs[reg] &= ~val;
  496. if (val & SONIC_ISR_RBE) {
  497. do_read_rra(s);
  498. }
  499. dp8393x_update_irq(s);
  500. break;
  501. /* Ignore least significant bit */
  502. case SONIC_RSA:
  503. case SONIC_REA:
  504. case SONIC_RRP:
  505. case SONIC_RWP:
  506. s->regs[reg] = val & 0xfffe;
  507. break;
  508. /* Invert written value for some registers */
  509. case SONIC_CRCT:
  510. case SONIC_FAET:
  511. case SONIC_MPT:
  512. s->regs[reg] = val ^ 0xffff;
  513. break;
  514. /* All other registers have no special contrainst */
  515. default:
  516. s->regs[reg] = val;
  517. }
  518. if (reg == SONIC_WT0 || reg == SONIC_WT1) {
  519. set_next_tick(s);
  520. }
  521. }
  522. static void dp8393x_watchdog(void *opaque)
  523. {
  524. dp8393xState *s = opaque;
  525. if (s->regs[SONIC_CR] & SONIC_CR_STP) {
  526. return;
  527. }
  528. s->regs[SONIC_WT1] = 0xffff;
  529. s->regs[SONIC_WT0] = 0xffff;
  530. set_next_tick(s);
  531. /* Signal underflow */
  532. s->regs[SONIC_ISR] |= SONIC_ISR_TC;
  533. dp8393x_update_irq(s);
  534. }
  535. static uint32_t dp8393x_readw(void *opaque, hwaddr addr)
  536. {
  537. dp8393xState *s = opaque;
  538. int reg;
  539. if ((addr & ((1 << s->it_shift) - 1)) != 0) {
  540. return 0;
  541. }
  542. reg = addr >> s->it_shift;
  543. return read_register(s, reg);
  544. }
  545. static uint32_t dp8393x_readb(void *opaque, hwaddr addr)
  546. {
  547. uint16_t v = dp8393x_readw(opaque, addr & ~0x1);
  548. return (v >> (8 * (addr & 0x1))) & 0xff;
  549. }
  550. static uint32_t dp8393x_readl(void *opaque, hwaddr addr)
  551. {
  552. uint32_t v;
  553. v = dp8393x_readw(opaque, addr);
  554. v |= dp8393x_readw(opaque, addr + 2) << 16;
  555. return v;
  556. }
  557. static void dp8393x_writew(void *opaque, hwaddr addr, uint32_t val)
  558. {
  559. dp8393xState *s = opaque;
  560. int reg;
  561. if ((addr & ((1 << s->it_shift) - 1)) != 0) {
  562. return;
  563. }
  564. reg = addr >> s->it_shift;
  565. write_register(s, reg, (uint16_t)val);
  566. }
  567. static void dp8393x_writeb(void *opaque, hwaddr addr, uint32_t val)
  568. {
  569. uint16_t old_val = dp8393x_readw(opaque, addr & ~0x1);
  570. switch (addr & 3) {
  571. case 0:
  572. val = val | (old_val & 0xff00);
  573. break;
  574. case 1:
  575. val = (val << 8) | (old_val & 0x00ff);
  576. break;
  577. }
  578. dp8393x_writew(opaque, addr & ~0x1, val);
  579. }
  580. static void dp8393x_writel(void *opaque, hwaddr addr, uint32_t val)
  581. {
  582. dp8393x_writew(opaque, addr, val & 0xffff);
  583. dp8393x_writew(opaque, addr + 2, (val >> 16) & 0xffff);
  584. }
  585. static const MemoryRegionOps dp8393x_ops = {
  586. .old_mmio = {
  587. .read = { dp8393x_readb, dp8393x_readw, dp8393x_readl, },
  588. .write = { dp8393x_writeb, dp8393x_writew, dp8393x_writel, },
  589. },
  590. .endianness = DEVICE_NATIVE_ENDIAN,
  591. };
  592. static int nic_can_receive(NetClientState *nc)
  593. {
  594. dp8393xState *s = qemu_get_nic_opaque(nc);
  595. if (!(s->regs[SONIC_CR] & SONIC_CR_RXEN))
  596. return 0;
  597. if (s->regs[SONIC_ISR] & SONIC_ISR_RBE)
  598. return 0;
  599. return 1;
  600. }
  601. static int receive_filter(dp8393xState *s, const uint8_t * buf, int size)
  602. {
  603. static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  604. int i;
  605. /* Check for runt packet (remember that checksum is not there) */
  606. if (size < 64 - 4) {
  607. return (s->regs[SONIC_RCR] & SONIC_RCR_RNT) ? 0 : -1;
  608. }
  609. /* Check promiscuous mode */
  610. if ((s->regs[SONIC_RCR] & SONIC_RCR_PRO) && (buf[0] & 1) == 0) {
  611. return 0;
  612. }
  613. /* Check multicast packets */
  614. if ((s->regs[SONIC_RCR] & SONIC_RCR_AMC) && (buf[0] & 1) == 1) {
  615. return SONIC_RCR_MC;
  616. }
  617. /* Check broadcast */
  618. if ((s->regs[SONIC_RCR] & SONIC_RCR_BRD) && !memcmp(buf, bcast, sizeof(bcast))) {
  619. return SONIC_RCR_BC;
  620. }
  621. /* Check CAM */
  622. for (i = 0; i < 16; i++) {
  623. if (s->regs[SONIC_CE] & (1 << i)) {
  624. /* Entry enabled */
  625. if (!memcmp(buf, s->cam[i], sizeof(s->cam[i]))) {
  626. return 0;
  627. }
  628. }
  629. }
  630. return -1;
  631. }
  632. static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
  633. {
  634. dp8393xState *s = qemu_get_nic_opaque(nc);
  635. uint16_t data[10];
  636. int packet_type;
  637. uint32_t available, address;
  638. int width, rx_len = size;
  639. uint32_t checksum;
  640. width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
  641. s->regs[SONIC_RCR] &= ~(SONIC_RCR_PRX | SONIC_RCR_LBK | SONIC_RCR_FAER |
  642. SONIC_RCR_CRCR | SONIC_RCR_LPKT | SONIC_RCR_BC | SONIC_RCR_MC);
  643. packet_type = receive_filter(s, buf, size);
  644. if (packet_type < 0) {
  645. DPRINTF("packet not for netcard\n");
  646. return -1;
  647. }
  648. /* XXX: Check byte ordering */
  649. /* Check for EOL */
  650. if (s->regs[SONIC_LLFA] & 0x1) {
  651. /* Are we still in resource exhaustion? */
  652. size = sizeof(uint16_t) * 1 * width;
  653. address = ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width;
  654. s->memory_rw(s->mem_opaque, address, (uint8_t*)data, size, 0);
  655. if (data[0 * width] & 0x1) {
  656. /* Still EOL ; stop reception */
  657. return -1;
  658. } else {
  659. s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
  660. }
  661. }
  662. /* Save current position */
  663. s->regs[SONIC_TRBA1] = s->regs[SONIC_CRBA1];
  664. s->regs[SONIC_TRBA0] = s->regs[SONIC_CRBA0];
  665. /* Calculate the ethernet checksum */
  666. #ifdef SONIC_CALCULATE_RXCRC
  667. checksum = cpu_to_le32(crc32(0, buf, rx_len));
  668. #else
  669. checksum = 0;
  670. #endif
  671. /* Put packet into RBA */
  672. DPRINTF("Receive packet at %08x\n", (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0]);
  673. address = (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0];
  674. s->memory_rw(s->mem_opaque, address, (uint8_t*)buf, rx_len, 1);
  675. address += rx_len;
  676. s->memory_rw(s->mem_opaque, address, (uint8_t*)&checksum, 4, 1);
  677. rx_len += 4;
  678. s->regs[SONIC_CRBA1] = address >> 16;
  679. s->regs[SONIC_CRBA0] = address & 0xffff;
  680. available = (s->regs[SONIC_RBWC1] << 16) | s->regs[SONIC_RBWC0];
  681. available -= rx_len / 2;
  682. s->regs[SONIC_RBWC1] = available >> 16;
  683. s->regs[SONIC_RBWC0] = available & 0xffff;
  684. /* Update status */
  685. if (((s->regs[SONIC_RBWC1] << 16) | s->regs[SONIC_RBWC0]) < s->regs[SONIC_EOBC]) {
  686. s->regs[SONIC_RCR] |= SONIC_RCR_LPKT;
  687. }
  688. s->regs[SONIC_RCR] |= packet_type;
  689. s->regs[SONIC_RCR] |= SONIC_RCR_PRX;
  690. if (s->loopback_packet) {
  691. s->regs[SONIC_RCR] |= SONIC_RCR_LBK;
  692. s->loopback_packet = 0;
  693. }
  694. /* Write status to memory */
  695. DPRINTF("Write status at %08x\n", (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]);
  696. data[0 * width] = s->regs[SONIC_RCR]; /* status */
  697. data[1 * width] = rx_len; /* byte count */
  698. data[2 * width] = s->regs[SONIC_TRBA0]; /* pkt_ptr0 */
  699. data[3 * width] = s->regs[SONIC_TRBA1]; /* pkt_ptr1 */
  700. data[4 * width] = s->regs[SONIC_RSC]; /* seq_no */
  701. size = sizeof(uint16_t) * 5 * width;
  702. s->memory_rw(s->mem_opaque, (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA], (uint8_t *)data, size, 1);
  703. /* Move to next descriptor */
  704. size = sizeof(uint16_t) * width;
  705. s->memory_rw(s->mem_opaque,
  706. ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width,
  707. (uint8_t *)data, size, 0);
  708. s->regs[SONIC_LLFA] = data[0 * width];
  709. if (s->regs[SONIC_LLFA] & 0x1) {
  710. /* EOL detected */
  711. s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
  712. } else {
  713. data[0 * width] = 0; /* in_use */
  714. s->memory_rw(s->mem_opaque,
  715. ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 6 * width,
  716. (uint8_t *)data, size, 1);
  717. s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
  718. s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
  719. s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
  720. if (s->regs[SONIC_RCR] & SONIC_RCR_LPKT) {
  721. /* Read next RRA */
  722. do_read_rra(s);
  723. }
  724. }
  725. /* Done */
  726. dp8393x_update_irq(s);
  727. return size;
  728. }
  729. static void nic_reset(void *opaque)
  730. {
  731. dp8393xState *s = opaque;
  732. qemu_del_timer(s->watchdog);
  733. s->regs[SONIC_CR] = SONIC_CR_RST | SONIC_CR_STP | SONIC_CR_RXDIS;
  734. s->regs[SONIC_DCR] &= ~(SONIC_DCR_EXBUS | SONIC_DCR_LBR);
  735. s->regs[SONIC_RCR] &= ~(SONIC_RCR_LB0 | SONIC_RCR_LB1 | SONIC_RCR_BRD | SONIC_RCR_RNT);
  736. s->regs[SONIC_TCR] |= SONIC_TCR_NCRS | SONIC_TCR_PTX;
  737. s->regs[SONIC_TCR] &= ~SONIC_TCR_BCM;
  738. s->regs[SONIC_IMR] = 0;
  739. s->regs[SONIC_ISR] = 0;
  740. s->regs[SONIC_DCR2] = 0;
  741. s->regs[SONIC_EOBC] = 0x02F8;
  742. s->regs[SONIC_RSC] = 0;
  743. s->regs[SONIC_CE] = 0;
  744. s->regs[SONIC_RSC] = 0;
  745. /* Network cable is connected */
  746. s->regs[SONIC_RCR] |= SONIC_RCR_CRS;
  747. dp8393x_update_irq(s);
  748. }
  749. static void nic_cleanup(NetClientState *nc)
  750. {
  751. dp8393xState *s = qemu_get_nic_opaque(nc);
  752. memory_region_del_subregion(s->address_space, &s->mmio);
  753. memory_region_destroy(&s->mmio);
  754. qemu_del_timer(s->watchdog);
  755. qemu_free_timer(s->watchdog);
  756. g_free(s);
  757. }
  758. static NetClientInfo net_dp83932_info = {
  759. .type = NET_CLIENT_OPTIONS_KIND_NIC,
  760. .size = sizeof(NICState),
  761. .can_receive = nic_can_receive,
  762. .receive = nic_receive,
  763. .cleanup = nic_cleanup,
  764. };
  765. void dp83932_init(NICInfo *nd, hwaddr base, int it_shift,
  766. MemoryRegion *address_space,
  767. qemu_irq irq, void* mem_opaque,
  768. void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write))
  769. {
  770. dp8393xState *s;
  771. qemu_check_nic_model(nd, "dp83932");
  772. s = g_malloc0(sizeof(dp8393xState));
  773. s->address_space = address_space;
  774. s->mem_opaque = mem_opaque;
  775. s->memory_rw = memory_rw;
  776. s->it_shift = it_shift;
  777. s->irq = irq;
  778. s->watchdog = qemu_new_timer_ns(vm_clock, dp8393x_watchdog, s);
  779. s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
  780. s->conf.macaddr = nd->macaddr;
  781. s->conf.peers.ncs[0] = nd->netdev;
  782. s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s);
  783. qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
  784. qemu_register_reset(nic_reset, s);
  785. nic_reset(s);
  786. memory_region_init_io(&s->mmio, &dp8393x_ops, s,
  787. "dp8393x", 0x40 << it_shift);
  788. memory_region_add_subregion(address_space, base, &s->mmio);
  789. }