slavio_misc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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 "hw.h"
  25. #include "sun4m.h"
  26. #include "sysemu.h"
  27. /* debug misc */
  28. //#define DEBUG_MISC
  29. /*
  30. * This is the auxio port, chip control and system control part of
  31. * chip STP2001 (Slave I/O), also produced as NCR89C105. See
  32. * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
  33. *
  34. * This also includes the PMC CPU idle controller.
  35. */
  36. #ifdef DEBUG_MISC
  37. #define MISC_DPRINTF(fmt, args...) \
  38. do { printf("MISC: " fmt , ##args); } while (0)
  39. #else
  40. #define MISC_DPRINTF(fmt, args...)
  41. #endif
  42. typedef struct MiscState {
  43. qemu_irq irq;
  44. uint8_t config;
  45. uint8_t aux1, aux2;
  46. uint8_t diag, mctrl;
  47. uint32_t sysctrl;
  48. uint16_t leds;
  49. qemu_irq cpu_halt;
  50. qemu_irq fdc_tc;
  51. } MiscState;
  52. #define MISC_SIZE 1
  53. #define SYSCTRL_SIZE 4
  54. #define LED_MAXADDR 1
  55. #define LED_SIZE (LED_MAXADDR + 1)
  56. #define MISC_MASK 0x0fff0000
  57. #define MISC_LEDS 0x01600000
  58. #define MISC_CFG 0x01800000
  59. #define MISC_DIAG 0x01a00000
  60. #define MISC_MDM 0x01b00000
  61. #define MISC_SYS 0x01f00000
  62. #define AUX1_TC 0x02
  63. #define AUX2_PWROFF 0x01
  64. #define AUX2_PWRINTCLR 0x02
  65. #define AUX2_PWRFAIL 0x20
  66. #define CFG_PWRINTEN 0x08
  67. #define SYS_RESET 0x01
  68. #define SYS_RESETSTAT 0x02
  69. static void slavio_misc_update_irq(void *opaque)
  70. {
  71. MiscState *s = opaque;
  72. if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
  73. MISC_DPRINTF("Raise IRQ\n");
  74. qemu_irq_raise(s->irq);
  75. } else {
  76. MISC_DPRINTF("Lower IRQ\n");
  77. qemu_irq_lower(s->irq);
  78. }
  79. }
  80. static void slavio_misc_reset(void *opaque)
  81. {
  82. MiscState *s = opaque;
  83. // Diagnostic and system control registers not cleared in reset
  84. s->config = s->aux1 = s->aux2 = s->mctrl = 0;
  85. }
  86. void slavio_set_power_fail(void *opaque, int power_failing)
  87. {
  88. MiscState *s = opaque;
  89. MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
  90. if (power_failing && (s->config & CFG_PWRINTEN)) {
  91. s->aux2 |= AUX2_PWRFAIL;
  92. } else {
  93. s->aux2 &= ~AUX2_PWRFAIL;
  94. }
  95. slavio_misc_update_irq(s);
  96. }
  97. static void slavio_cfg_mem_writeb(void *opaque, target_phys_addr_t addr,
  98. uint32_t val)
  99. {
  100. MiscState *s = opaque;
  101. MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
  102. s->config = val & 0xff;
  103. slavio_misc_update_irq(s);
  104. }
  105. static uint32_t slavio_cfg_mem_readb(void *opaque, target_phys_addr_t addr)
  106. {
  107. MiscState *s = opaque;
  108. uint32_t ret = 0;
  109. ret = s->config;
  110. MISC_DPRINTF("Read config %2.2x\n", ret);
  111. return ret;
  112. }
  113. static CPUReadMemoryFunc *slavio_cfg_mem_read[3] = {
  114. slavio_cfg_mem_readb,
  115. NULL,
  116. NULL,
  117. };
  118. static CPUWriteMemoryFunc *slavio_cfg_mem_write[3] = {
  119. slavio_cfg_mem_writeb,
  120. NULL,
  121. NULL,
  122. };
  123. static void slavio_diag_mem_writeb(void *opaque, target_phys_addr_t addr,
  124. uint32_t val)
  125. {
  126. MiscState *s = opaque;
  127. MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
  128. s->diag = val & 0xff;
  129. }
  130. static uint32_t slavio_diag_mem_readb(void *opaque, target_phys_addr_t addr)
  131. {
  132. MiscState *s = opaque;
  133. uint32_t ret = 0;
  134. ret = s->diag;
  135. MISC_DPRINTF("Read diag %2.2x\n", ret);
  136. return ret;
  137. }
  138. static CPUReadMemoryFunc *slavio_diag_mem_read[3] = {
  139. slavio_diag_mem_readb,
  140. NULL,
  141. NULL,
  142. };
  143. static CPUWriteMemoryFunc *slavio_diag_mem_write[3] = {
  144. slavio_diag_mem_writeb,
  145. NULL,
  146. NULL,
  147. };
  148. static void slavio_mdm_mem_writeb(void *opaque, target_phys_addr_t addr,
  149. uint32_t val)
  150. {
  151. MiscState *s = opaque;
  152. MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
  153. s->mctrl = val & 0xff;
  154. }
  155. static uint32_t slavio_mdm_mem_readb(void *opaque, target_phys_addr_t addr)
  156. {
  157. MiscState *s = opaque;
  158. uint32_t ret = 0;
  159. ret = s->mctrl;
  160. MISC_DPRINTF("Read modem control %2.2x\n", ret);
  161. return ret;
  162. }
  163. static CPUReadMemoryFunc *slavio_mdm_mem_read[3] = {
  164. slavio_mdm_mem_readb,
  165. NULL,
  166. NULL,
  167. };
  168. static CPUWriteMemoryFunc *slavio_mdm_mem_write[3] = {
  169. slavio_mdm_mem_writeb,
  170. NULL,
  171. NULL,
  172. };
  173. static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
  174. uint32_t val)
  175. {
  176. MiscState *s = opaque;
  177. MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
  178. if (val & AUX1_TC) {
  179. // Send a pulse to floppy terminal count line
  180. if (s->fdc_tc) {
  181. qemu_irq_raise(s->fdc_tc);
  182. qemu_irq_lower(s->fdc_tc);
  183. }
  184. val &= ~AUX1_TC;
  185. }
  186. s->aux1 = val & 0xff;
  187. }
  188. static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
  189. {
  190. MiscState *s = opaque;
  191. uint32_t ret = 0;
  192. ret = s->aux1;
  193. MISC_DPRINTF("Read aux1 %2.2x\n", ret);
  194. return ret;
  195. }
  196. static CPUReadMemoryFunc *slavio_aux1_mem_read[3] = {
  197. slavio_aux1_mem_readb,
  198. NULL,
  199. NULL,
  200. };
  201. static CPUWriteMemoryFunc *slavio_aux1_mem_write[3] = {
  202. slavio_aux1_mem_writeb,
  203. NULL,
  204. NULL,
  205. };
  206. static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
  207. uint32_t val)
  208. {
  209. MiscState *s = opaque;
  210. val &= AUX2_PWRINTCLR | AUX2_PWROFF;
  211. MISC_DPRINTF("Write aux2 %2.2x\n", val);
  212. val |= s->aux2 & AUX2_PWRFAIL;
  213. if (val & AUX2_PWRINTCLR) // Clear Power Fail int
  214. val &= AUX2_PWROFF;
  215. s->aux2 = val;
  216. if (val & AUX2_PWROFF)
  217. qemu_system_shutdown_request();
  218. slavio_misc_update_irq(s);
  219. }
  220. static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
  221. {
  222. MiscState *s = opaque;
  223. uint32_t ret = 0;
  224. ret = s->aux2;
  225. MISC_DPRINTF("Read aux2 %2.2x\n", ret);
  226. return ret;
  227. }
  228. static CPUReadMemoryFunc *slavio_aux2_mem_read[3] = {
  229. slavio_aux2_mem_readb,
  230. NULL,
  231. NULL,
  232. };
  233. static CPUWriteMemoryFunc *slavio_aux2_mem_write[3] = {
  234. slavio_aux2_mem_writeb,
  235. NULL,
  236. NULL,
  237. };
  238. static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  239. {
  240. MiscState *s = opaque;
  241. MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
  242. qemu_irq_raise(s->cpu_halt);
  243. }
  244. static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
  245. {
  246. uint32_t ret = 0;
  247. MISC_DPRINTF("Read power management %2.2x\n", ret);
  248. return ret;
  249. }
  250. static CPUReadMemoryFunc *apc_mem_read[3] = {
  251. apc_mem_readb,
  252. NULL,
  253. NULL,
  254. };
  255. static CPUWriteMemoryFunc *apc_mem_write[3] = {
  256. apc_mem_writeb,
  257. NULL,
  258. NULL,
  259. };
  260. static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
  261. {
  262. MiscState *s = opaque;
  263. uint32_t ret = 0;
  264. switch (addr) {
  265. case 0:
  266. ret = s->sysctrl;
  267. break;
  268. default:
  269. break;
  270. }
  271. MISC_DPRINTF("Read system control %08x\n", ret);
  272. return ret;
  273. }
  274. static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
  275. uint32_t val)
  276. {
  277. MiscState *s = opaque;
  278. MISC_DPRINTF("Write system control %08x\n", val);
  279. switch (addr) {
  280. case 0:
  281. if (val & SYS_RESET) {
  282. s->sysctrl = SYS_RESETSTAT;
  283. qemu_system_reset_request();
  284. }
  285. break;
  286. default:
  287. break;
  288. }
  289. }
  290. static CPUReadMemoryFunc *slavio_sysctrl_mem_read[3] = {
  291. NULL,
  292. NULL,
  293. slavio_sysctrl_mem_readl,
  294. };
  295. static CPUWriteMemoryFunc *slavio_sysctrl_mem_write[3] = {
  296. NULL,
  297. NULL,
  298. slavio_sysctrl_mem_writel,
  299. };
  300. static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
  301. {
  302. MiscState *s = opaque;
  303. uint32_t ret = 0;
  304. switch (addr) {
  305. case 0:
  306. ret = s->leds;
  307. break;
  308. default:
  309. break;
  310. }
  311. MISC_DPRINTF("Read diagnostic LED %04x\n", ret);
  312. return ret;
  313. }
  314. static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
  315. uint32_t val)
  316. {
  317. MiscState *s = opaque;
  318. MISC_DPRINTF("Write diagnostic LED %04x\n", val & 0xffff);
  319. switch (addr) {
  320. case 0:
  321. s->leds = val;
  322. break;
  323. default:
  324. break;
  325. }
  326. }
  327. static CPUReadMemoryFunc *slavio_led_mem_read[3] = {
  328. NULL,
  329. slavio_led_mem_readw,
  330. NULL,
  331. };
  332. static CPUWriteMemoryFunc *slavio_led_mem_write[3] = {
  333. NULL,
  334. slavio_led_mem_writew,
  335. NULL,
  336. };
  337. static void slavio_misc_save(QEMUFile *f, void *opaque)
  338. {
  339. MiscState *s = opaque;
  340. uint32_t tmp = 0;
  341. uint8_t tmp8;
  342. qemu_put_be32s(f, &tmp); /* ignored, was IRQ. */
  343. qemu_put_8s(f, &s->config);
  344. qemu_put_8s(f, &s->aux1);
  345. qemu_put_8s(f, &s->aux2);
  346. qemu_put_8s(f, &s->diag);
  347. qemu_put_8s(f, &s->mctrl);
  348. tmp8 = s->sysctrl & 0xff;
  349. qemu_put_8s(f, &tmp8);
  350. }
  351. static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
  352. {
  353. MiscState *s = opaque;
  354. uint32_t tmp;
  355. uint8_t tmp8;
  356. if (version_id != 1)
  357. return -EINVAL;
  358. qemu_get_be32s(f, &tmp);
  359. qemu_get_8s(f, &s->config);
  360. qemu_get_8s(f, &s->aux1);
  361. qemu_get_8s(f, &s->aux2);
  362. qemu_get_8s(f, &s->diag);
  363. qemu_get_8s(f, &s->mctrl);
  364. qemu_get_8s(f, &tmp8);
  365. s->sysctrl = (uint32_t)tmp8;
  366. return 0;
  367. }
  368. void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base,
  369. target_phys_addr_t aux1_base,
  370. target_phys_addr_t aux2_base, qemu_irq irq,
  371. qemu_irq cpu_halt, qemu_irq **fdc_tc)
  372. {
  373. int io;
  374. MiscState *s;
  375. s = qemu_mallocz(sizeof(MiscState));
  376. if (base) {
  377. /* 8 bit registers */
  378. // Slavio control
  379. io = cpu_register_io_memory(0, slavio_cfg_mem_read,
  380. slavio_cfg_mem_write, s);
  381. cpu_register_physical_memory(base + MISC_CFG, MISC_SIZE, io);
  382. // Diagnostics
  383. io = cpu_register_io_memory(0, slavio_diag_mem_read,
  384. slavio_diag_mem_write, s);
  385. cpu_register_physical_memory(base + MISC_DIAG, MISC_SIZE, io);
  386. // Modem control
  387. io = cpu_register_io_memory(0, slavio_mdm_mem_read,
  388. slavio_mdm_mem_write, s);
  389. cpu_register_physical_memory(base + MISC_MDM, MISC_SIZE, io);
  390. /* 16 bit registers */
  391. io = cpu_register_io_memory(0, slavio_led_mem_read,
  392. slavio_led_mem_write, s);
  393. /* ss600mp diag LEDs */
  394. cpu_register_physical_memory(base + MISC_LEDS, MISC_SIZE, io);
  395. /* 32 bit registers */
  396. io = cpu_register_io_memory(0, slavio_sysctrl_mem_read,
  397. slavio_sysctrl_mem_write, s);
  398. // System control
  399. cpu_register_physical_memory(base + MISC_SYS, SYSCTRL_SIZE, io);
  400. }
  401. // AUX 1 (Misc System Functions)
  402. if (aux1_base) {
  403. io = cpu_register_io_memory(0, slavio_aux1_mem_read,
  404. slavio_aux1_mem_write, s);
  405. cpu_register_physical_memory(aux1_base, MISC_SIZE, io);
  406. }
  407. // AUX 2 (Software Powerdown Control)
  408. if (aux2_base) {
  409. io = cpu_register_io_memory(0, slavio_aux2_mem_read,
  410. slavio_aux2_mem_write, s);
  411. cpu_register_physical_memory(aux2_base, MISC_SIZE, io);
  412. }
  413. // Power management (APC) XXX: not a Slavio device
  414. if (power_base) {
  415. io = cpu_register_io_memory(0, apc_mem_read, apc_mem_write, s);
  416. cpu_register_physical_memory(power_base, MISC_SIZE, io);
  417. }
  418. s->irq = irq;
  419. s->cpu_halt = cpu_halt;
  420. *fdc_tc = &s->fdc_tc;
  421. register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load,
  422. s);
  423. qemu_register_reset(slavio_misc_reset, s);
  424. slavio_misc_reset(s);
  425. return s;
  426. }