slavio_misc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * QEMU Sparc SLAVIO aux io port emulation
  3. *
  4. * Copyright (c) 2005 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "sysemu.h"
  25. #include "sysbus.h"
  26. #include "trace.h"
  27. /*
  28. * This is the auxio port, chip control and system control part of
  29. * chip STP2001 (Slave I/O), also produced as NCR89C105. See
  30. * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
  31. *
  32. * This also includes the PMC CPU idle controller.
  33. */
  34. typedef struct MiscState {
  35. SysBusDevice busdev;
  36. qemu_irq irq;
  37. qemu_irq fdc_tc;
  38. uint32_t dummy;
  39. uint8_t config;
  40. uint8_t aux1, aux2;
  41. uint8_t diag, mctrl;
  42. uint8_t sysctrl;
  43. uint16_t leds;
  44. } MiscState;
  45. typedef struct APCState {
  46. SysBusDevice busdev;
  47. qemu_irq cpu_halt;
  48. } APCState;
  49. #define MISC_SIZE 1
  50. #define SYSCTRL_SIZE 4
  51. #define AUX1_TC 0x02
  52. #define AUX2_PWROFF 0x01
  53. #define AUX2_PWRINTCLR 0x02
  54. #define AUX2_PWRFAIL 0x20
  55. #define CFG_PWRINTEN 0x08
  56. #define SYS_RESET 0x01
  57. #define SYS_RESETSTAT 0x02
  58. static void slavio_misc_update_irq(void *opaque)
  59. {
  60. MiscState *s = opaque;
  61. if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
  62. trace_slavio_misc_update_irq_raise();
  63. qemu_irq_raise(s->irq);
  64. } else {
  65. trace_slavio_misc_update_irq_lower();
  66. qemu_irq_lower(s->irq);
  67. }
  68. }
  69. static void slavio_misc_reset(DeviceState *d)
  70. {
  71. MiscState *s = container_of(d, MiscState, busdev.qdev);
  72. // Diagnostic and system control registers not cleared in reset
  73. s->config = s->aux1 = s->aux2 = s->mctrl = 0;
  74. }
  75. static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
  76. {
  77. MiscState *s = opaque;
  78. trace_slavio_set_power_fail(power_failing, s->config);
  79. if (power_failing && (s->config & CFG_PWRINTEN)) {
  80. s->aux2 |= AUX2_PWRFAIL;
  81. } else {
  82. s->aux2 &= ~AUX2_PWRFAIL;
  83. }
  84. slavio_misc_update_irq(s);
  85. }
  86. static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
  87. uint32_t val)
  88. {
  89. MiscState *s = opaque;
  90. trace_slavio_cfg_mem_writeb(val & 0xff);
  91. s->config = val & 0xff;
  92. slavio_misc_update_irq(s);
  93. }
  94. static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
  95. {
  96. MiscState *s = opaque;
  97. uint32_t ret = 0;
  98. ret = s->config;
  99. trace_slavio_cfg_mem_readb(ret);
  100. return ret;
  101. }
  102. static CPUReadMemoryFunc * const slavio_cfg_mem_read[3] = {
  103. slavio_cfg_mem_readb,
  104. NULL,
  105. NULL,
  106. };
  107. static CPUWriteMemoryFunc * const slavio_cfg_mem_write[3] = {
  108. slavio_cfg_mem_writeb,
  109. NULL,
  110. NULL,
  111. };
  112. static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
  113. uint32_t val)
  114. {
  115. MiscState *s = opaque;
  116. trace_slavio_diag_mem_writeb(val & 0xff);
  117. s->diag = val & 0xff;
  118. }
  119. static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
  120. {
  121. MiscState *s = opaque;
  122. uint32_t ret = 0;
  123. ret = s->diag;
  124. trace_slavio_diag_mem_readb(ret);
  125. return ret;
  126. }
  127. static CPUReadMemoryFunc * const slavio_diag_mem_read[3] = {
  128. slavio_diag_mem_readb,
  129. NULL,
  130. NULL,
  131. };
  132. static CPUWriteMemoryFunc * const slavio_diag_mem_write[3] = {
  133. slavio_diag_mem_writeb,
  134. NULL,
  135. NULL,
  136. };
  137. static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
  138. uint32_t val)
  139. {
  140. MiscState *s = opaque;
  141. trace_slavio_mdm_mem_writeb(val & 0xff);
  142. s->mctrl = val & 0xff;
  143. }
  144. static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
  145. {
  146. MiscState *s = opaque;
  147. uint32_t ret = 0;
  148. ret = s->mctrl;
  149. trace_slavio_mdm_mem_readb(ret);
  150. return ret;
  151. }
  152. static CPUReadMemoryFunc * const slavio_mdm_mem_read[3] = {
  153. slavio_mdm_mem_readb,
  154. NULL,
  155. NULL,
  156. };
  157. static CPUWriteMemoryFunc * const slavio_mdm_mem_write[3] = {
  158. slavio_mdm_mem_writeb,
  159. NULL,
  160. NULL,
  161. };
  162. static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
  163. uint32_t val)
  164. {
  165. MiscState *s = opaque;
  166. trace_slavio_aux1_mem_writeb(val & 0xff);
  167. if (val & AUX1_TC) {
  168. // Send a pulse to floppy terminal count line
  169. if (s->fdc_tc) {
  170. qemu_irq_raise(s->fdc_tc);
  171. qemu_irq_lower(s->fdc_tc);
  172. }
  173. val &= ~AUX1_TC;
  174. }
  175. s->aux1 = val & 0xff;
  176. }
  177. static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
  178. {
  179. MiscState *s = opaque;
  180. uint32_t ret = 0;
  181. ret = s->aux1;
  182. trace_slavio_aux1_mem_readb(ret);
  183. return ret;
  184. }
  185. static CPUReadMemoryFunc * const slavio_aux1_mem_read[3] = {
  186. slavio_aux1_mem_readb,
  187. NULL,
  188. NULL,
  189. };
  190. static CPUWriteMemoryFunc * const slavio_aux1_mem_write[3] = {
  191. slavio_aux1_mem_writeb,
  192. NULL,
  193. NULL,
  194. };
  195. static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
  196. uint32_t val)
  197. {
  198. MiscState *s = opaque;
  199. val &= AUX2_PWRINTCLR | AUX2_PWROFF;
  200. trace_slavio_aux2_mem_writeb(val & 0xff);
  201. val |= s->aux2 & AUX2_PWRFAIL;
  202. if (val & AUX2_PWRINTCLR) // Clear Power Fail int
  203. val &= AUX2_PWROFF;
  204. s->aux2 = val;
  205. if (val & AUX2_PWROFF)
  206. qemu_system_shutdown_request();
  207. slavio_misc_update_irq(s);
  208. }
  209. static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
  210. {
  211. MiscState *s = opaque;
  212. uint32_t ret = 0;
  213. ret = s->aux2;
  214. trace_slavio_aux2_mem_readb(ret);
  215. return ret;
  216. }
  217. static CPUReadMemoryFunc * const slavio_aux2_mem_read[3] = {
  218. slavio_aux2_mem_readb,
  219. NULL,
  220. NULL,
  221. };
  222. static CPUWriteMemoryFunc * const slavio_aux2_mem_write[3] = {
  223. slavio_aux2_mem_writeb,
  224. NULL,
  225. NULL,
  226. };
  227. static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  228. {
  229. APCState *s = opaque;
  230. trace_apc_mem_writeb(val & 0xff);
  231. qemu_irq_raise(s->cpu_halt);
  232. }
  233. static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
  234. {
  235. uint32_t ret = 0;
  236. trace_apc_mem_readb(ret);
  237. return ret;
  238. }
  239. static CPUReadMemoryFunc * const apc_mem_read[3] = {
  240. apc_mem_readb,
  241. NULL,
  242. NULL,
  243. };
  244. static CPUWriteMemoryFunc * const apc_mem_write[3] = {
  245. apc_mem_writeb,
  246. NULL,
  247. NULL,
  248. };
  249. static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
  250. {
  251. MiscState *s = opaque;
  252. uint32_t ret = 0;
  253. switch (addr) {
  254. case 0:
  255. ret = s->sysctrl;
  256. break;
  257. default:
  258. break;
  259. }
  260. trace_slavio_sysctrl_mem_readl(ret);
  261. return ret;
  262. }
  263. static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
  264. uint32_t val)
  265. {
  266. MiscState *s = opaque;
  267. trace_slavio_sysctrl_mem_writel(val);
  268. switch (addr) {
  269. case 0:
  270. if (val & SYS_RESET) {
  271. s->sysctrl = SYS_RESETSTAT;
  272. qemu_system_reset_request();
  273. }
  274. break;
  275. default:
  276. break;
  277. }
  278. }
  279. static CPUReadMemoryFunc * const slavio_sysctrl_mem_read[3] = {
  280. NULL,
  281. NULL,
  282. slavio_sysctrl_mem_readl,
  283. };
  284. static CPUWriteMemoryFunc * const slavio_sysctrl_mem_write[3] = {
  285. NULL,
  286. NULL,
  287. slavio_sysctrl_mem_writel,
  288. };
  289. static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
  290. {
  291. MiscState *s = opaque;
  292. uint32_t ret = 0;
  293. switch (addr) {
  294. case 0:
  295. ret = s->leds;
  296. break;
  297. default:
  298. break;
  299. }
  300. trace_slavio_led_mem_readw(ret);
  301. return ret;
  302. }
  303. static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
  304. uint32_t val)
  305. {
  306. MiscState *s = opaque;
  307. trace_slavio_led_mem_readw(val & 0xffff);
  308. switch (addr) {
  309. case 0:
  310. s->leds = val;
  311. break;
  312. default:
  313. break;
  314. }
  315. }
  316. static CPUReadMemoryFunc * const slavio_led_mem_read[3] = {
  317. NULL,
  318. slavio_led_mem_readw,
  319. NULL,
  320. };
  321. static CPUWriteMemoryFunc * const slavio_led_mem_write[3] = {
  322. NULL,
  323. slavio_led_mem_writew,
  324. NULL,
  325. };
  326. static const VMStateDescription vmstate_misc = {
  327. .name ="slavio_misc",
  328. .version_id = 1,
  329. .minimum_version_id = 1,
  330. .minimum_version_id_old = 1,
  331. .fields = (VMStateField []) {
  332. VMSTATE_UINT32(dummy, MiscState),
  333. VMSTATE_UINT8(config, MiscState),
  334. VMSTATE_UINT8(aux1, MiscState),
  335. VMSTATE_UINT8(aux2, MiscState),
  336. VMSTATE_UINT8(diag, MiscState),
  337. VMSTATE_UINT8(mctrl, MiscState),
  338. VMSTATE_UINT8(sysctrl, MiscState),
  339. VMSTATE_END_OF_LIST()
  340. }
  341. };
  342. static int apc_init1(SysBusDevice *dev)
  343. {
  344. APCState *s = FROM_SYSBUS(APCState, dev);
  345. int io;
  346. sysbus_init_irq(dev, &s->cpu_halt);
  347. /* Power management (APC) XXX: not a Slavio device */
  348. io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s,
  349. DEVICE_NATIVE_ENDIAN);
  350. sysbus_init_mmio(dev, MISC_SIZE, io);
  351. return 0;
  352. }
  353. static int slavio_misc_init1(SysBusDevice *dev)
  354. {
  355. MiscState *s = FROM_SYSBUS(MiscState, dev);
  356. int io;
  357. sysbus_init_irq(dev, &s->irq);
  358. sysbus_init_irq(dev, &s->fdc_tc);
  359. /* 8 bit registers */
  360. /* Slavio control */
  361. io = cpu_register_io_memory(slavio_cfg_mem_read,
  362. slavio_cfg_mem_write, s,
  363. DEVICE_NATIVE_ENDIAN);
  364. sysbus_init_mmio(dev, MISC_SIZE, io);
  365. /* Diagnostics */
  366. io = cpu_register_io_memory(slavio_diag_mem_read,
  367. slavio_diag_mem_write, s,
  368. DEVICE_NATIVE_ENDIAN);
  369. sysbus_init_mmio(dev, MISC_SIZE, io);
  370. /* Modem control */
  371. io = cpu_register_io_memory(slavio_mdm_mem_read,
  372. slavio_mdm_mem_write, s,
  373. DEVICE_NATIVE_ENDIAN);
  374. sysbus_init_mmio(dev, MISC_SIZE, io);
  375. /* 16 bit registers */
  376. /* ss600mp diag LEDs */
  377. io = cpu_register_io_memory(slavio_led_mem_read,
  378. slavio_led_mem_write, s,
  379. DEVICE_NATIVE_ENDIAN);
  380. sysbus_init_mmio(dev, MISC_SIZE, io);
  381. /* 32 bit registers */
  382. /* System control */
  383. io = cpu_register_io_memory(slavio_sysctrl_mem_read,
  384. slavio_sysctrl_mem_write, s,
  385. DEVICE_NATIVE_ENDIAN);
  386. sysbus_init_mmio(dev, SYSCTRL_SIZE, io);
  387. /* AUX 1 (Misc System Functions) */
  388. io = cpu_register_io_memory(slavio_aux1_mem_read,
  389. slavio_aux1_mem_write, s,
  390. DEVICE_NATIVE_ENDIAN);
  391. sysbus_init_mmio(dev, MISC_SIZE, io);
  392. /* AUX 2 (Software Powerdown Control) */
  393. io = cpu_register_io_memory(slavio_aux2_mem_read,
  394. slavio_aux2_mem_write, s,
  395. DEVICE_NATIVE_ENDIAN);
  396. sysbus_init_mmio(dev, MISC_SIZE, io);
  397. qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
  398. return 0;
  399. }
  400. static SysBusDeviceInfo slavio_misc_info = {
  401. .init = slavio_misc_init1,
  402. .qdev.name = "slavio_misc",
  403. .qdev.size = sizeof(MiscState),
  404. .qdev.vmsd = &vmstate_misc,
  405. .qdev.reset = slavio_misc_reset,
  406. };
  407. static SysBusDeviceInfo apc_info = {
  408. .init = apc_init1,
  409. .qdev.name = "apc",
  410. .qdev.size = sizeof(MiscState),
  411. };
  412. static void slavio_misc_register_devices(void)
  413. {
  414. sysbus_register_withprop(&slavio_misc_info);
  415. sysbus_register_withprop(&apc_info);
  416. }
  417. device_init(slavio_misc_register_devices)