slavio_misc.c 13 KB

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