2
0

slavio_misc.c 13 KB

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