slavio_misc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  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. MemoryRegion cfg_iomem;
  37. MemoryRegion diag_iomem;
  38. MemoryRegion mdm_iomem;
  39. MemoryRegion led_iomem;
  40. MemoryRegion sysctrl_iomem;
  41. MemoryRegion aux1_iomem;
  42. MemoryRegion aux2_iomem;
  43. qemu_irq irq;
  44. qemu_irq fdc_tc;
  45. uint32_t dummy;
  46. uint8_t config;
  47. uint8_t aux1, aux2;
  48. uint8_t diag, mctrl;
  49. uint8_t sysctrl;
  50. uint16_t leds;
  51. } MiscState;
  52. typedef struct APCState {
  53. SysBusDevice busdev;
  54. MemoryRegion iomem;
  55. qemu_irq cpu_halt;
  56. } APCState;
  57. #define MISC_SIZE 1
  58. #define SYSCTRL_SIZE 4
  59. #define AUX1_TC 0x02
  60. #define AUX2_PWROFF 0x01
  61. #define AUX2_PWRINTCLR 0x02
  62. #define AUX2_PWRFAIL 0x20
  63. #define CFG_PWRINTEN 0x08
  64. #define SYS_RESET 0x01
  65. #define SYS_RESETSTAT 0x02
  66. static void slavio_misc_update_irq(void *opaque)
  67. {
  68. MiscState *s = opaque;
  69. if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
  70. trace_slavio_misc_update_irq_raise();
  71. qemu_irq_raise(s->irq);
  72. } else {
  73. trace_slavio_misc_update_irq_lower();
  74. qemu_irq_lower(s->irq);
  75. }
  76. }
  77. static void slavio_misc_reset(DeviceState *d)
  78. {
  79. MiscState *s = container_of(d, MiscState, busdev.qdev);
  80. // Diagnostic and system control registers not cleared in reset
  81. s->config = s->aux1 = s->aux2 = s->mctrl = 0;
  82. }
  83. static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
  84. {
  85. MiscState *s = opaque;
  86. trace_slavio_set_power_fail(power_failing, s->config);
  87. if (power_failing && (s->config & CFG_PWRINTEN)) {
  88. s->aux2 |= AUX2_PWRFAIL;
  89. } else {
  90. s->aux2 &= ~AUX2_PWRFAIL;
  91. }
  92. slavio_misc_update_irq(s);
  93. }
  94. static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
  95. uint64_t val, unsigned size)
  96. {
  97. MiscState *s = opaque;
  98. trace_slavio_cfg_mem_writeb(val & 0xff);
  99. s->config = val & 0xff;
  100. slavio_misc_update_irq(s);
  101. }
  102. static uint64_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr,
  103. unsigned size)
  104. {
  105. MiscState *s = opaque;
  106. uint32_t ret = 0;
  107. ret = s->config;
  108. trace_slavio_cfg_mem_readb(ret);
  109. return ret;
  110. }
  111. static const MemoryRegionOps slavio_cfg_mem_ops = {
  112. .read = slavio_cfg_mem_readb,
  113. .write = slavio_cfg_mem_writeb,
  114. .endianness = DEVICE_NATIVE_ENDIAN,
  115. .valid = {
  116. .min_access_size = 1,
  117. .max_access_size = 1,
  118. },
  119. };
  120. static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
  121. uint64_t val, unsigned size)
  122. {
  123. MiscState *s = opaque;
  124. trace_slavio_diag_mem_writeb(val & 0xff);
  125. s->diag = val & 0xff;
  126. }
  127. static uint64_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr,
  128. unsigned size)
  129. {
  130. MiscState *s = opaque;
  131. uint32_t ret = 0;
  132. ret = s->diag;
  133. trace_slavio_diag_mem_readb(ret);
  134. return ret;
  135. }
  136. static const MemoryRegionOps slavio_diag_mem_ops = {
  137. .read = slavio_diag_mem_readb,
  138. .write = slavio_diag_mem_writeb,
  139. .endianness = DEVICE_NATIVE_ENDIAN,
  140. .valid = {
  141. .min_access_size = 1,
  142. .max_access_size = 1,
  143. },
  144. };
  145. static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
  146. uint64_t val, unsigned size)
  147. {
  148. MiscState *s = opaque;
  149. trace_slavio_mdm_mem_writeb(val & 0xff);
  150. s->mctrl = val & 0xff;
  151. }
  152. static uint64_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr,
  153. unsigned size)
  154. {
  155. MiscState *s = opaque;
  156. uint32_t ret = 0;
  157. ret = s->mctrl;
  158. trace_slavio_mdm_mem_readb(ret);
  159. return ret;
  160. }
  161. static const MemoryRegionOps slavio_mdm_mem_ops = {
  162. .read = slavio_mdm_mem_readb,
  163. .write = slavio_mdm_mem_writeb,
  164. .endianness = DEVICE_NATIVE_ENDIAN,
  165. .valid = {
  166. .min_access_size = 1,
  167. .max_access_size = 1,
  168. },
  169. };
  170. static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
  171. uint64_t val, unsigned size)
  172. {
  173. MiscState *s = opaque;
  174. trace_slavio_aux1_mem_writeb(val & 0xff);
  175. if (val & AUX1_TC) {
  176. // Send a pulse to floppy terminal count line
  177. if (s->fdc_tc) {
  178. qemu_irq_raise(s->fdc_tc);
  179. qemu_irq_lower(s->fdc_tc);
  180. }
  181. val &= ~AUX1_TC;
  182. }
  183. s->aux1 = val & 0xff;
  184. }
  185. static uint64_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr,
  186. unsigned size)
  187. {
  188. MiscState *s = opaque;
  189. uint32_t ret = 0;
  190. ret = s->aux1;
  191. trace_slavio_aux1_mem_readb(ret);
  192. return ret;
  193. }
  194. static const MemoryRegionOps slavio_aux1_mem_ops = {
  195. .read = slavio_aux1_mem_readb,
  196. .write = slavio_aux1_mem_writeb,
  197. .endianness = DEVICE_NATIVE_ENDIAN,
  198. .valid = {
  199. .min_access_size = 1,
  200. .max_access_size = 1,
  201. },
  202. };
  203. static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
  204. uint64_t val, unsigned size)
  205. {
  206. MiscState *s = opaque;
  207. val &= AUX2_PWRINTCLR | AUX2_PWROFF;
  208. trace_slavio_aux2_mem_writeb(val & 0xff);
  209. val |= s->aux2 & AUX2_PWRFAIL;
  210. if (val & AUX2_PWRINTCLR) // Clear Power Fail int
  211. val &= AUX2_PWROFF;
  212. s->aux2 = val;
  213. if (val & AUX2_PWROFF)
  214. qemu_system_shutdown_request();
  215. slavio_misc_update_irq(s);
  216. }
  217. static uint64_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr,
  218. unsigned size)
  219. {
  220. MiscState *s = opaque;
  221. uint32_t ret = 0;
  222. ret = s->aux2;
  223. trace_slavio_aux2_mem_readb(ret);
  224. return ret;
  225. }
  226. static const MemoryRegionOps slavio_aux2_mem_ops = {
  227. .read = slavio_aux2_mem_readb,
  228. .write = slavio_aux2_mem_writeb,
  229. .endianness = DEVICE_NATIVE_ENDIAN,
  230. .valid = {
  231. .min_access_size = 1,
  232. .max_access_size = 1,
  233. },
  234. };
  235. static void apc_mem_writeb(void *opaque, target_phys_addr_t addr,
  236. uint64_t val, unsigned size)
  237. {
  238. APCState *s = opaque;
  239. trace_apc_mem_writeb(val & 0xff);
  240. qemu_irq_raise(s->cpu_halt);
  241. }
  242. static uint64_t apc_mem_readb(void *opaque, target_phys_addr_t addr,
  243. unsigned size)
  244. {
  245. uint32_t ret = 0;
  246. trace_apc_mem_readb(ret);
  247. return ret;
  248. }
  249. static const MemoryRegionOps apc_mem_ops = {
  250. .read = apc_mem_readb,
  251. .write = apc_mem_writeb,
  252. .endianness = DEVICE_NATIVE_ENDIAN,
  253. .valid = {
  254. .min_access_size = 1,
  255. .max_access_size = 1,
  256. }
  257. };
  258. static uint64_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr,
  259. unsigned size)
  260. {
  261. MiscState *s = opaque;
  262. uint32_t ret = 0;
  263. switch (addr) {
  264. case 0:
  265. ret = s->sysctrl;
  266. break;
  267. default:
  268. break;
  269. }
  270. trace_slavio_sysctrl_mem_readl(ret);
  271. return ret;
  272. }
  273. static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
  274. uint64_t val, unsigned size)
  275. {
  276. MiscState *s = opaque;
  277. trace_slavio_sysctrl_mem_writel(val);
  278. switch (addr) {
  279. case 0:
  280. if (val & SYS_RESET) {
  281. s->sysctrl = SYS_RESETSTAT;
  282. qemu_system_reset_request();
  283. }
  284. break;
  285. default:
  286. break;
  287. }
  288. }
  289. static const MemoryRegionOps slavio_sysctrl_mem_ops = {
  290. .read = slavio_sysctrl_mem_readl,
  291. .write = slavio_sysctrl_mem_writel,
  292. .endianness = DEVICE_NATIVE_ENDIAN,
  293. .valid = {
  294. .min_access_size = 4,
  295. .max_access_size = 4,
  296. },
  297. };
  298. static uint64_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr,
  299. unsigned size)
  300. {
  301. MiscState *s = opaque;
  302. uint32_t ret = 0;
  303. switch (addr) {
  304. case 0:
  305. ret = s->leds;
  306. break;
  307. default:
  308. break;
  309. }
  310. trace_slavio_led_mem_readw(ret);
  311. return ret;
  312. }
  313. static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
  314. uint64_t val, unsigned size)
  315. {
  316. MiscState *s = opaque;
  317. trace_slavio_led_mem_readw(val & 0xffff);
  318. switch (addr) {
  319. case 0:
  320. s->leds = val;
  321. break;
  322. default:
  323. break;
  324. }
  325. }
  326. static const MemoryRegionOps slavio_led_mem_ops = {
  327. .read = slavio_led_mem_readw,
  328. .write = slavio_led_mem_writew,
  329. .endianness = DEVICE_NATIVE_ENDIAN,
  330. .valid = {
  331. .min_access_size = 2,
  332. .max_access_size = 2,
  333. },
  334. };
  335. static const VMStateDescription vmstate_misc = {
  336. .name ="slavio_misc",
  337. .version_id = 1,
  338. .minimum_version_id = 1,
  339. .minimum_version_id_old = 1,
  340. .fields = (VMStateField []) {
  341. VMSTATE_UINT32(dummy, MiscState),
  342. VMSTATE_UINT8(config, MiscState),
  343. VMSTATE_UINT8(aux1, MiscState),
  344. VMSTATE_UINT8(aux2, MiscState),
  345. VMSTATE_UINT8(diag, MiscState),
  346. VMSTATE_UINT8(mctrl, MiscState),
  347. VMSTATE_UINT8(sysctrl, MiscState),
  348. VMSTATE_END_OF_LIST()
  349. }
  350. };
  351. static int apc_init1(SysBusDevice *dev)
  352. {
  353. APCState *s = FROM_SYSBUS(APCState, dev);
  354. sysbus_init_irq(dev, &s->cpu_halt);
  355. /* Power management (APC) XXX: not a Slavio device */
  356. memory_region_init_io(&s->iomem, &apc_mem_ops, s,
  357. "apc", MISC_SIZE);
  358. sysbus_init_mmio(dev, &s->iomem);
  359. return 0;
  360. }
  361. static int slavio_misc_init1(SysBusDevice *dev)
  362. {
  363. MiscState *s = FROM_SYSBUS(MiscState, dev);
  364. sysbus_init_irq(dev, &s->irq);
  365. sysbus_init_irq(dev, &s->fdc_tc);
  366. /* 8 bit registers */
  367. /* Slavio control */
  368. memory_region_init_io(&s->cfg_iomem, &slavio_cfg_mem_ops, s,
  369. "configuration", MISC_SIZE);
  370. sysbus_init_mmio(dev, &s->cfg_iomem);
  371. /* Diagnostics */
  372. memory_region_init_io(&s->diag_iomem, &slavio_diag_mem_ops, s,
  373. "diagnostic", MISC_SIZE);
  374. sysbus_init_mmio(dev, &s->diag_iomem);
  375. /* Modem control */
  376. memory_region_init_io(&s->mdm_iomem, &slavio_mdm_mem_ops, s,
  377. "modem", MISC_SIZE);
  378. sysbus_init_mmio(dev, &s->mdm_iomem);
  379. /* 16 bit registers */
  380. /* ss600mp diag LEDs */
  381. memory_region_init_io(&s->led_iomem, &slavio_led_mem_ops, s,
  382. "leds", MISC_SIZE);
  383. sysbus_init_mmio(dev, &s->led_iomem);
  384. /* 32 bit registers */
  385. /* System control */
  386. memory_region_init_io(&s->sysctrl_iomem, &slavio_sysctrl_mem_ops, s,
  387. "system-control", MISC_SIZE);
  388. sysbus_init_mmio(dev, &s->sysctrl_iomem);
  389. /* AUX 1 (Misc System Functions) */
  390. memory_region_init_io(&s->aux1_iomem, &slavio_aux1_mem_ops, s,
  391. "misc-system-functions", MISC_SIZE);
  392. sysbus_init_mmio(dev, &s->aux1_iomem);
  393. /* AUX 2 (Software Powerdown Control) */
  394. memory_region_init_io(&s->aux2_iomem, &slavio_aux2_mem_ops, s,
  395. "software-powerdown-control", MISC_SIZE);
  396. sysbus_init_mmio(dev, &s->aux2_iomem);
  397. qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
  398. return 0;
  399. }
  400. static void slavio_misc_class_init(ObjectClass *klass, void *data)
  401. {
  402. DeviceClass *dc = DEVICE_CLASS(klass);
  403. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  404. k->init = slavio_misc_init1;
  405. dc->reset = slavio_misc_reset;
  406. dc->vmsd = &vmstate_misc;
  407. }
  408. static TypeInfo slavio_misc_info = {
  409. .name = "slavio_misc",
  410. .parent = TYPE_SYS_BUS_DEVICE,
  411. .instance_size = sizeof(MiscState),
  412. .class_init = slavio_misc_class_init,
  413. };
  414. static void apc_class_init(ObjectClass *klass, void *data)
  415. {
  416. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  417. k->init = apc_init1;
  418. }
  419. static TypeInfo apc_info = {
  420. .name = "apc",
  421. .parent = TYPE_SYS_BUS_DEVICE,
  422. .instance_size = sizeof(MiscState),
  423. .class_init = apc_class_init,
  424. };
  425. static void slavio_misc_register_types(void)
  426. {
  427. type_register_static(&slavio_misc_info);
  428. type_register_static(&apc_info);
  429. }
  430. type_init(slavio_misc_register_types)