slavio_misc.c 13 KB

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