openpic.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725
  1. /*
  2. * OpenPIC emulation
  3. *
  4. * Copyright (c) 2004 Jocelyn Mayer
  5. * 2011 Alexander Graf
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. /*
  26. *
  27. * Based on OpenPic implementations:
  28. * - Intel GW80314 I/O companion chip developer's manual
  29. * - Motorola MPC8245 & MPC8540 user manuals.
  30. * - Motorola MCP750 (aka Raven) programmer manual.
  31. * - Motorola Harrier programmer manuel
  32. *
  33. * Serial interrupts, as implemented in Raven chipset are not supported yet.
  34. *
  35. */
  36. #include "hw.h"
  37. #include "ppc_mac.h"
  38. #include "pci.h"
  39. #include "openpic.h"
  40. //#define DEBUG_OPENPIC
  41. #ifdef DEBUG_OPENPIC
  42. #define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
  43. #else
  44. #define DPRINTF(fmt, ...) do { } while (0)
  45. #endif
  46. #define USE_MPCxxx /* Intel model is broken, for now */
  47. #if defined (USE_INTEL_GW80314)
  48. /* Intel GW80314 I/O Companion chip */
  49. #define MAX_CPU 4
  50. #define MAX_IRQ 32
  51. #define MAX_DBL 4
  52. #define MAX_MBX 4
  53. #define MAX_TMR 4
  54. #define VECTOR_BITS 8
  55. #define MAX_IPI 4
  56. #define VID (0x00000000)
  57. #elif defined(USE_MPCxxx)
  58. #define MAX_CPU 15
  59. #define MAX_IRQ 128
  60. #define MAX_DBL 0
  61. #define MAX_MBX 0
  62. #define MAX_TMR 4
  63. #define VECTOR_BITS 8
  64. #define MAX_IPI 4
  65. #define VID 0x03 /* MPIC version ID */
  66. #define VENI 0x00000000 /* Vendor ID */
  67. enum {
  68. IRQ_IPVP = 0,
  69. IRQ_IDE,
  70. };
  71. /* OpenPIC */
  72. #define OPENPIC_MAX_CPU 2
  73. #define OPENPIC_MAX_IRQ 64
  74. #define OPENPIC_EXT_IRQ 48
  75. #define OPENPIC_MAX_TMR MAX_TMR
  76. #define OPENPIC_MAX_IPI MAX_IPI
  77. /* Interrupt definitions */
  78. #define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */
  79. #define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
  80. #define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
  81. #if OPENPIC_MAX_IPI > 0
  82. #define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
  83. #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
  84. #else
  85. #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
  86. #define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
  87. #endif
  88. /* MPIC */
  89. #define MPIC_MAX_CPU 1
  90. #define MPIC_MAX_EXT 12
  91. #define MPIC_MAX_INT 64
  92. #define MPIC_MAX_MSG 4
  93. #define MPIC_MAX_MSI 8
  94. #define MPIC_MAX_TMR MAX_TMR
  95. #define MPIC_MAX_IPI MAX_IPI
  96. #define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU))
  97. /* Interrupt definitions */
  98. #define MPIC_EXT_IRQ 0
  99. #define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT)
  100. #define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT)
  101. #define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR)
  102. #define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG)
  103. #define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI)
  104. #define MPIC_GLB_REG_START 0x0
  105. #define MPIC_GLB_REG_SIZE 0x10F0
  106. #define MPIC_TMR_REG_START 0x10F0
  107. #define MPIC_TMR_REG_SIZE 0x220
  108. #define MPIC_EXT_REG_START 0x10000
  109. #define MPIC_EXT_REG_SIZE 0x180
  110. #define MPIC_INT_REG_START 0x10200
  111. #define MPIC_INT_REG_SIZE 0x800
  112. #define MPIC_MSG_REG_START 0x11600
  113. #define MPIC_MSG_REG_SIZE 0x100
  114. #define MPIC_MSI_REG_START 0x11C00
  115. #define MPIC_MSI_REG_SIZE 0x100
  116. #define MPIC_CPU_REG_START 0x20000
  117. #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
  118. enum mpic_ide_bits {
  119. IDR_EP = 31,
  120. IDR_CI0 = 30,
  121. IDR_CI1 = 29,
  122. IDR_P1 = 1,
  123. IDR_P0 = 0,
  124. };
  125. #else
  126. #error "Please select which OpenPic implementation is to be emulated"
  127. #endif
  128. #define OPENPIC_PAGE_SIZE 4096
  129. #define BF_WIDTH(_bits_) \
  130. (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
  131. static inline void set_bit (uint32_t *field, int bit)
  132. {
  133. field[bit >> 5] |= 1 << (bit & 0x1F);
  134. }
  135. static inline void reset_bit (uint32_t *field, int bit)
  136. {
  137. field[bit >> 5] &= ~(1 << (bit & 0x1F));
  138. }
  139. static inline int test_bit (uint32_t *field, int bit)
  140. {
  141. return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
  142. }
  143. static int get_current_cpu(void)
  144. {
  145. return cpu_single_env->cpu_index;
  146. }
  147. static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
  148. int idx);
  149. static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
  150. uint32_t val, int idx);
  151. enum {
  152. IRQ_EXTERNAL = 0x01,
  153. IRQ_INTERNAL = 0x02,
  154. IRQ_TIMER = 0x04,
  155. IRQ_SPECIAL = 0x08,
  156. };
  157. typedef struct IRQ_queue_t {
  158. uint32_t queue[BF_WIDTH(MAX_IRQ)];
  159. int next;
  160. int priority;
  161. } IRQ_queue_t;
  162. typedef struct IRQ_src_t {
  163. uint32_t ipvp; /* IRQ vector/priority register */
  164. uint32_t ide; /* IRQ destination register */
  165. int type;
  166. int last_cpu;
  167. int pending; /* TRUE if IRQ is pending */
  168. } IRQ_src_t;
  169. enum IPVP_bits {
  170. IPVP_MASK = 31,
  171. IPVP_ACTIVITY = 30,
  172. IPVP_MODE = 29,
  173. IPVP_POLARITY = 23,
  174. IPVP_SENSE = 22,
  175. };
  176. #define IPVP_PRIORITY_MASK (0x1F << 16)
  177. #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
  178. #define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
  179. #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
  180. typedef struct IRQ_dst_t {
  181. uint32_t tfrr;
  182. uint32_t pctp; /* CPU current task priority */
  183. uint32_t pcsr; /* CPU sensitivity register */
  184. IRQ_queue_t raised;
  185. IRQ_queue_t servicing;
  186. qemu_irq *irqs;
  187. } IRQ_dst_t;
  188. typedef struct openpic_t {
  189. PCIDevice pci_dev;
  190. MemoryRegion mem;
  191. /* Sub-regions */
  192. MemoryRegion sub_io_mem[7];
  193. /* Global registers */
  194. uint32_t frep; /* Feature reporting register */
  195. uint32_t glbc; /* Global configuration register */
  196. uint32_t micr; /* MPIC interrupt configuration register */
  197. uint32_t veni; /* Vendor identification register */
  198. uint32_t pint; /* Processor initialization register */
  199. uint32_t spve; /* Spurious vector register */
  200. uint32_t tifr; /* Timer frequency reporting register */
  201. /* Source registers */
  202. IRQ_src_t src[MAX_IRQ];
  203. /* Local registers per output pin */
  204. IRQ_dst_t dst[MAX_CPU];
  205. int nb_cpus;
  206. /* Timer registers */
  207. struct {
  208. uint32_t ticc; /* Global timer current count register */
  209. uint32_t tibc; /* Global timer base count register */
  210. } timers[MAX_TMR];
  211. #if MAX_DBL > 0
  212. /* Doorbell registers */
  213. uint32_t dar; /* Doorbell activate register */
  214. struct {
  215. uint32_t dmr; /* Doorbell messaging register */
  216. } doorbells[MAX_DBL];
  217. #endif
  218. #if MAX_MBX > 0
  219. /* Mailbox registers */
  220. struct {
  221. uint32_t mbr; /* Mailbox register */
  222. } mailboxes[MAX_MAILBOXES];
  223. #endif
  224. /* IRQ out is used when in bypass mode (not implemented) */
  225. qemu_irq irq_out;
  226. int max_irq;
  227. int irq_ipi0;
  228. int irq_tim0;
  229. void (*reset) (void *);
  230. void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
  231. } openpic_t;
  232. static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
  233. {
  234. set_bit(q->queue, n_IRQ);
  235. }
  236. static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
  237. {
  238. reset_bit(q->queue, n_IRQ);
  239. }
  240. static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
  241. {
  242. return test_bit(q->queue, n_IRQ);
  243. }
  244. static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
  245. {
  246. int next, i;
  247. int priority;
  248. next = -1;
  249. priority = -1;
  250. for (i = 0; i < opp->max_irq; i++) {
  251. if (IRQ_testbit(q, i)) {
  252. DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
  253. i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
  254. if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
  255. next = i;
  256. priority = IPVP_PRIORITY(opp->src[i].ipvp);
  257. }
  258. }
  259. }
  260. q->next = next;
  261. q->priority = priority;
  262. }
  263. static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
  264. {
  265. if (q->next == -1) {
  266. /* XXX: optimize */
  267. IRQ_check(opp, q);
  268. }
  269. return q->next;
  270. }
  271. static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
  272. {
  273. IRQ_dst_t *dst;
  274. IRQ_src_t *src;
  275. int priority;
  276. dst = &opp->dst[n_CPU];
  277. src = &opp->src[n_IRQ];
  278. priority = IPVP_PRIORITY(src->ipvp);
  279. if (priority <= dst->pctp) {
  280. /* Too low priority */
  281. DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
  282. __func__, n_IRQ, n_CPU);
  283. return;
  284. }
  285. if (IRQ_testbit(&dst->raised, n_IRQ)) {
  286. /* Interrupt miss */
  287. DPRINTF("%s: IRQ %d was missed on CPU %d\n",
  288. __func__, n_IRQ, n_CPU);
  289. return;
  290. }
  291. set_bit(&src->ipvp, IPVP_ACTIVITY);
  292. IRQ_setbit(&dst->raised, n_IRQ);
  293. if (priority < dst->raised.priority) {
  294. /* An higher priority IRQ is already raised */
  295. DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
  296. __func__, n_IRQ, dst->raised.next, n_CPU);
  297. return;
  298. }
  299. IRQ_get_next(opp, &dst->raised);
  300. if (IRQ_get_next(opp, &dst->servicing) != -1 &&
  301. priority <= dst->servicing.priority) {
  302. DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
  303. __func__, n_IRQ, dst->servicing.next, n_CPU);
  304. /* Already servicing a higher priority IRQ */
  305. return;
  306. }
  307. DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
  308. opp->irq_raise(opp, n_CPU, src);
  309. }
  310. /* update pic state because registers for n_IRQ have changed value */
  311. static void openpic_update_irq(openpic_t *opp, int n_IRQ)
  312. {
  313. IRQ_src_t *src;
  314. int i;
  315. src = &opp->src[n_IRQ];
  316. if (!src->pending) {
  317. /* no irq pending */
  318. DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
  319. return;
  320. }
  321. if (test_bit(&src->ipvp, IPVP_MASK)) {
  322. /* Interrupt source is disabled */
  323. DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
  324. return;
  325. }
  326. if (IPVP_PRIORITY(src->ipvp) == 0) {
  327. /* Priority set to zero */
  328. DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
  329. return;
  330. }
  331. if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
  332. /* IRQ already active */
  333. DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
  334. return;
  335. }
  336. if (src->ide == 0x00000000) {
  337. /* No target */
  338. DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
  339. return;
  340. }
  341. if (src->ide == (1 << src->last_cpu)) {
  342. /* Only one CPU is allowed to receive this IRQ */
  343. IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
  344. } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
  345. /* Directed delivery mode */
  346. for (i = 0; i < opp->nb_cpus; i++) {
  347. if (test_bit(&src->ide, i))
  348. IRQ_local_pipe(opp, i, n_IRQ);
  349. }
  350. } else {
  351. /* Distributed delivery mode */
  352. for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
  353. if (i == opp->nb_cpus)
  354. i = 0;
  355. if (test_bit(&src->ide, i)) {
  356. IRQ_local_pipe(opp, i, n_IRQ);
  357. src->last_cpu = i;
  358. break;
  359. }
  360. }
  361. }
  362. }
  363. static void openpic_set_irq(void *opaque, int n_IRQ, int level)
  364. {
  365. openpic_t *opp = opaque;
  366. IRQ_src_t *src;
  367. src = &opp->src[n_IRQ];
  368. DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
  369. n_IRQ, level, src->ipvp);
  370. if (test_bit(&src->ipvp, IPVP_SENSE)) {
  371. /* level-sensitive irq */
  372. src->pending = level;
  373. if (!level)
  374. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  375. } else {
  376. /* edge-sensitive irq */
  377. if (level)
  378. src->pending = 1;
  379. }
  380. openpic_update_irq(opp, n_IRQ);
  381. }
  382. static void openpic_reset (void *opaque)
  383. {
  384. openpic_t *opp = (openpic_t *)opaque;
  385. int i;
  386. opp->glbc = 0x80000000;
  387. /* Initialise controller registers */
  388. opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
  389. opp->veni = VENI;
  390. opp->pint = 0x00000000;
  391. opp->spve = 0x000000FF;
  392. opp->tifr = 0x003F7A00;
  393. /* ? */
  394. opp->micr = 0x00000000;
  395. /* Initialise IRQ sources */
  396. for (i = 0; i < opp->max_irq; i++) {
  397. opp->src[i].ipvp = 0xA0000000;
  398. opp->src[i].ide = 0x00000000;
  399. }
  400. /* Initialise IRQ destinations */
  401. for (i = 0; i < MAX_CPU; i++) {
  402. opp->dst[i].pctp = 0x0000000F;
  403. opp->dst[i].pcsr = 0x00000000;
  404. memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
  405. opp->dst[i].raised.next = -1;
  406. memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
  407. opp->dst[i].servicing.next = -1;
  408. }
  409. /* Initialise timers */
  410. for (i = 0; i < MAX_TMR; i++) {
  411. opp->timers[i].ticc = 0x00000000;
  412. opp->timers[i].tibc = 0x80000000;
  413. }
  414. /* Initialise doorbells */
  415. #if MAX_DBL > 0
  416. opp->dar = 0x00000000;
  417. for (i = 0; i < MAX_DBL; i++) {
  418. opp->doorbells[i].dmr = 0x00000000;
  419. }
  420. #endif
  421. /* Initialise mailboxes */
  422. #if MAX_MBX > 0
  423. for (i = 0; i < MAX_MBX; i++) { /* ? */
  424. opp->mailboxes[i].mbr = 0x00000000;
  425. }
  426. #endif
  427. /* Go out of RESET state */
  428. opp->glbc = 0x00000000;
  429. }
  430. static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
  431. {
  432. return opp->src[n_IRQ].ide;
  433. }
  434. static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
  435. {
  436. return opp->src[n_IRQ].ipvp;
  437. }
  438. static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
  439. {
  440. uint32_t tmp;
  441. tmp = val & 0xC0000000;
  442. tmp |= val & ((1ULL << MAX_CPU) - 1);
  443. opp->src[n_IRQ].ide = tmp;
  444. DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
  445. }
  446. static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
  447. {
  448. /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
  449. /* ACTIVITY bit is read-only */
  450. opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
  451. | (val & 0x800F00FF);
  452. openpic_update_irq(opp, n_IRQ);
  453. DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
  454. opp->src[n_IRQ].ipvp);
  455. }
  456. #if 0 // Code provision for Intel model
  457. #if MAX_DBL > 0
  458. static uint32_t read_doorbell_register (openpic_t *opp,
  459. int n_dbl, uint32_t offset)
  460. {
  461. uint32_t retval;
  462. switch (offset) {
  463. case DBL_IPVP_OFFSET:
  464. retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
  465. break;
  466. case DBL_IDE_OFFSET:
  467. retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
  468. break;
  469. case DBL_DMR_OFFSET:
  470. retval = opp->doorbells[n_dbl].dmr;
  471. break;
  472. }
  473. return retval;
  474. }
  475. static void write_doorbell_register (penpic_t *opp, int n_dbl,
  476. uint32_t offset, uint32_t value)
  477. {
  478. switch (offset) {
  479. case DBL_IVPR_OFFSET:
  480. write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
  481. break;
  482. case DBL_IDE_OFFSET:
  483. write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
  484. break;
  485. case DBL_DMR_OFFSET:
  486. opp->doorbells[n_dbl].dmr = value;
  487. break;
  488. }
  489. }
  490. #endif
  491. #if MAX_MBX > 0
  492. static uint32_t read_mailbox_register (openpic_t *opp,
  493. int n_mbx, uint32_t offset)
  494. {
  495. uint32_t retval;
  496. switch (offset) {
  497. case MBX_MBR_OFFSET:
  498. retval = opp->mailboxes[n_mbx].mbr;
  499. break;
  500. case MBX_IVPR_OFFSET:
  501. retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
  502. break;
  503. case MBX_DMR_OFFSET:
  504. retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
  505. break;
  506. }
  507. return retval;
  508. }
  509. static void write_mailbox_register (openpic_t *opp, int n_mbx,
  510. uint32_t address, uint32_t value)
  511. {
  512. switch (offset) {
  513. case MBX_MBR_OFFSET:
  514. opp->mailboxes[n_mbx].mbr = value;
  515. break;
  516. case MBX_IVPR_OFFSET:
  517. write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
  518. break;
  519. case MBX_DMR_OFFSET:
  520. write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
  521. break;
  522. }
  523. }
  524. #endif
  525. #endif /* 0 : Code provision for Intel model */
  526. static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val)
  527. {
  528. openpic_t *opp = opaque;
  529. IRQ_dst_t *dst;
  530. int idx;
  531. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  532. if (addr & 0xF)
  533. return;
  534. switch (addr) {
  535. case 0x40:
  536. case 0x50:
  537. case 0x60:
  538. case 0x70:
  539. case 0x80:
  540. case 0x90:
  541. case 0xA0:
  542. case 0xB0:
  543. openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
  544. break;
  545. case 0x1000: /* FREP */
  546. break;
  547. case 0x1020: /* GLBC */
  548. if (val & 0x80000000 && opp->reset)
  549. opp->reset(opp);
  550. opp->glbc = val & ~0x80000000;
  551. break;
  552. case 0x1080: /* VENI */
  553. break;
  554. case 0x1090: /* PINT */
  555. for (idx = 0; idx < opp->nb_cpus; idx++) {
  556. if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
  557. DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
  558. dst = &opp->dst[idx];
  559. qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
  560. } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
  561. DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
  562. dst = &opp->dst[idx];
  563. qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
  564. }
  565. }
  566. opp->pint = val;
  567. break;
  568. case 0x10A0: /* IPI_IPVP */
  569. case 0x10B0:
  570. case 0x10C0:
  571. case 0x10D0:
  572. {
  573. int idx;
  574. idx = (addr - 0x10A0) >> 4;
  575. write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
  576. }
  577. break;
  578. case 0x10E0: /* SPVE */
  579. opp->spve = val & 0x000000FF;
  580. break;
  581. case 0x10F0: /* TIFR */
  582. opp->tifr = val;
  583. break;
  584. default:
  585. break;
  586. }
  587. }
  588. static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
  589. {
  590. openpic_t *opp = opaque;
  591. uint32_t retval;
  592. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  593. retval = 0xFFFFFFFF;
  594. if (addr & 0xF)
  595. return retval;
  596. switch (addr) {
  597. case 0x1000: /* FREP */
  598. retval = opp->frep;
  599. break;
  600. case 0x1020: /* GLBC */
  601. retval = opp->glbc;
  602. break;
  603. case 0x1080: /* VENI */
  604. retval = opp->veni;
  605. break;
  606. case 0x1090: /* PINT */
  607. retval = 0x00000000;
  608. break;
  609. case 0x40:
  610. case 0x50:
  611. case 0x60:
  612. case 0x70:
  613. case 0x80:
  614. case 0x90:
  615. case 0xA0:
  616. case 0xB0:
  617. retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
  618. break;
  619. case 0x10A0: /* IPI_IPVP */
  620. case 0x10B0:
  621. case 0x10C0:
  622. case 0x10D0:
  623. {
  624. int idx;
  625. idx = (addr - 0x10A0) >> 4;
  626. retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
  627. }
  628. break;
  629. case 0x10E0: /* SPVE */
  630. retval = opp->spve;
  631. break;
  632. case 0x10F0: /* TIFR */
  633. retval = opp->tifr;
  634. break;
  635. default:
  636. break;
  637. }
  638. DPRINTF("%s: => %08x\n", __func__, retval);
  639. return retval;
  640. }
  641. static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
  642. {
  643. openpic_t *opp = opaque;
  644. int idx;
  645. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  646. if (addr & 0xF)
  647. return;
  648. addr -= 0x1100;
  649. addr &= 0xFFFF;
  650. idx = (addr & 0xFFF0) >> 6;
  651. addr = addr & 0x30;
  652. switch (addr) {
  653. case 0x00: /* TICC */
  654. break;
  655. case 0x10: /* TIBC */
  656. if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
  657. (val & 0x80000000) == 0 &&
  658. (opp->timers[idx].tibc & 0x80000000) != 0)
  659. opp->timers[idx].ticc &= ~0x80000000;
  660. opp->timers[idx].tibc = val;
  661. break;
  662. case 0x20: /* TIVP */
  663. write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
  664. break;
  665. case 0x30: /* TIDE */
  666. write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
  667. break;
  668. }
  669. }
  670. static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
  671. {
  672. openpic_t *opp = opaque;
  673. uint32_t retval;
  674. int idx;
  675. DPRINTF("%s: addr %08x\n", __func__, addr);
  676. retval = 0xFFFFFFFF;
  677. if (addr & 0xF)
  678. return retval;
  679. addr -= 0x1100;
  680. addr &= 0xFFFF;
  681. idx = (addr & 0xFFF0) >> 6;
  682. addr = addr & 0x30;
  683. switch (addr) {
  684. case 0x00: /* TICC */
  685. retval = opp->timers[idx].ticc;
  686. break;
  687. case 0x10: /* TIBC */
  688. retval = opp->timers[idx].tibc;
  689. break;
  690. case 0x20: /* TIPV */
  691. retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
  692. break;
  693. case 0x30: /* TIDE */
  694. retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
  695. break;
  696. }
  697. DPRINTF("%s: => %08x\n", __func__, retval);
  698. return retval;
  699. }
  700. static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
  701. {
  702. openpic_t *opp = opaque;
  703. int idx;
  704. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  705. if (addr & 0xF)
  706. return;
  707. addr = addr & 0xFFF0;
  708. idx = addr >> 5;
  709. if (addr & 0x10) {
  710. /* EXDE / IFEDE / IEEDE */
  711. write_IRQreg_ide(opp, idx, val);
  712. } else {
  713. /* EXVP / IFEVP / IEEVP */
  714. write_IRQreg_ipvp(opp, idx, val);
  715. }
  716. }
  717. static uint32_t openpic_src_read (void *opaque, uint32_t addr)
  718. {
  719. openpic_t *opp = opaque;
  720. uint32_t retval;
  721. int idx;
  722. DPRINTF("%s: addr %08x\n", __func__, addr);
  723. retval = 0xFFFFFFFF;
  724. if (addr & 0xF)
  725. return retval;
  726. addr = addr & 0xFFF0;
  727. idx = addr >> 5;
  728. if (addr & 0x10) {
  729. /* EXDE / IFEDE / IEEDE */
  730. retval = read_IRQreg_ide(opp, idx);
  731. } else {
  732. /* EXVP / IFEVP / IEEVP */
  733. retval = read_IRQreg_ipvp(opp, idx);
  734. }
  735. DPRINTF("%s: => %08x\n", __func__, retval);
  736. return retval;
  737. }
  738. static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
  739. uint32_t val, int idx)
  740. {
  741. openpic_t *opp = opaque;
  742. IRQ_src_t *src;
  743. IRQ_dst_t *dst;
  744. int s_IRQ, n_IRQ;
  745. DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
  746. addr, val);
  747. if (addr & 0xF)
  748. return;
  749. dst = &opp->dst[idx];
  750. addr &= 0xFF0;
  751. switch (addr) {
  752. #if MAX_IPI > 0
  753. case 0x40: /* IPIDR */
  754. case 0x50:
  755. case 0x60:
  756. case 0x70:
  757. idx = (addr - 0x40) >> 4;
  758. /* we use IDE as mask which CPUs to deliver the IPI to still. */
  759. write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
  760. opp->src[opp->irq_ipi0 + idx].ide | val);
  761. openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
  762. openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
  763. break;
  764. #endif
  765. case 0x80: /* PCTP */
  766. dst->pctp = val & 0x0000000F;
  767. break;
  768. case 0x90: /* WHOAMI */
  769. /* Read-only register */
  770. break;
  771. case 0xA0: /* PIAC */
  772. /* Read-only register */
  773. break;
  774. case 0xB0: /* PEOI */
  775. DPRINTF("PEOI\n");
  776. s_IRQ = IRQ_get_next(opp, &dst->servicing);
  777. IRQ_resetbit(&dst->servicing, s_IRQ);
  778. dst->servicing.next = -1;
  779. /* Set up next servicing IRQ */
  780. s_IRQ = IRQ_get_next(opp, &dst->servicing);
  781. /* Check queued interrupts. */
  782. n_IRQ = IRQ_get_next(opp, &dst->raised);
  783. src = &opp->src[n_IRQ];
  784. if (n_IRQ != -1 &&
  785. (s_IRQ == -1 ||
  786. IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
  787. DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
  788. idx, n_IRQ);
  789. opp->irq_raise(opp, idx, src);
  790. }
  791. break;
  792. default:
  793. break;
  794. }
  795. }
  796. static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val)
  797. {
  798. openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
  799. }
  800. static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
  801. int idx)
  802. {
  803. openpic_t *opp = opaque;
  804. IRQ_src_t *src;
  805. IRQ_dst_t *dst;
  806. uint32_t retval;
  807. int n_IRQ;
  808. DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
  809. retval = 0xFFFFFFFF;
  810. if (addr & 0xF)
  811. return retval;
  812. dst = &opp->dst[idx];
  813. addr &= 0xFF0;
  814. switch (addr) {
  815. case 0x80: /* PCTP */
  816. retval = dst->pctp;
  817. break;
  818. case 0x90: /* WHOAMI */
  819. retval = idx;
  820. break;
  821. case 0xA0: /* PIAC */
  822. DPRINTF("Lower OpenPIC INT output\n");
  823. qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
  824. n_IRQ = IRQ_get_next(opp, &dst->raised);
  825. DPRINTF("PIAC: irq=%d\n", n_IRQ);
  826. if (n_IRQ == -1) {
  827. /* No more interrupt pending */
  828. retval = IPVP_VECTOR(opp->spve);
  829. } else {
  830. src = &opp->src[n_IRQ];
  831. if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
  832. !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
  833. /* - Spurious level-sensitive IRQ
  834. * - Priorities has been changed
  835. * and the pending IRQ isn't allowed anymore
  836. */
  837. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  838. retval = IPVP_VECTOR(opp->spve);
  839. } else {
  840. /* IRQ enter servicing state */
  841. IRQ_setbit(&dst->servicing, n_IRQ);
  842. retval = IPVP_VECTOR(src->ipvp);
  843. }
  844. IRQ_resetbit(&dst->raised, n_IRQ);
  845. dst->raised.next = -1;
  846. if (!test_bit(&src->ipvp, IPVP_SENSE)) {
  847. /* edge-sensitive IRQ */
  848. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  849. src->pending = 0;
  850. }
  851. if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
  852. src->ide &= ~(1 << idx);
  853. if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
  854. /* trigger on CPUs that didn't know about it yet */
  855. openpic_set_irq(opp, n_IRQ, 1);
  856. openpic_set_irq(opp, n_IRQ, 0);
  857. /* if all CPUs knew about it, set active bit again */
  858. set_bit(&src->ipvp, IPVP_ACTIVITY);
  859. }
  860. }
  861. }
  862. break;
  863. case 0xB0: /* PEOI */
  864. retval = 0;
  865. break;
  866. default:
  867. break;
  868. }
  869. DPRINTF("%s: => %08x\n", __func__, retval);
  870. return retval;
  871. }
  872. static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr)
  873. {
  874. return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
  875. }
  876. static void openpic_buggy_write (void *opaque,
  877. target_phys_addr_t addr, uint32_t val)
  878. {
  879. printf("Invalid OPENPIC write access !\n");
  880. }
  881. static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
  882. {
  883. printf("Invalid OPENPIC read access !\n");
  884. return -1;
  885. }
  886. static void openpic_writel (void *opaque,
  887. target_phys_addr_t addr, uint32_t val)
  888. {
  889. openpic_t *opp = opaque;
  890. addr &= 0x3FFFF;
  891. DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
  892. if (addr < 0x1100) {
  893. /* Global registers */
  894. openpic_gbl_write(opp, addr, val);
  895. } else if (addr < 0x10000) {
  896. /* Timers registers */
  897. openpic_timer_write(opp, addr, val);
  898. } else if (addr < 0x20000) {
  899. /* Source registers */
  900. openpic_src_write(opp, addr, val);
  901. } else {
  902. /* CPU registers */
  903. openpic_cpu_write(opp, addr, val);
  904. }
  905. }
  906. static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
  907. {
  908. openpic_t *opp = opaque;
  909. uint32_t retval;
  910. addr &= 0x3FFFF;
  911. DPRINTF("%s: offset %08x\n", __func__, (int)addr);
  912. if (addr < 0x1100) {
  913. /* Global registers */
  914. retval = openpic_gbl_read(opp, addr);
  915. } else if (addr < 0x10000) {
  916. /* Timers registers */
  917. retval = openpic_timer_read(opp, addr);
  918. } else if (addr < 0x20000) {
  919. /* Source registers */
  920. retval = openpic_src_read(opp, addr);
  921. } else {
  922. /* CPU registers */
  923. retval = openpic_cpu_read(opp, addr);
  924. }
  925. return retval;
  926. }
  927. static uint64_t openpic_read(void *opaque, target_phys_addr_t addr,
  928. unsigned size)
  929. {
  930. openpic_t *opp = opaque;
  931. switch (size) {
  932. case 4: return openpic_readl(opp, addr);
  933. default: return openpic_buggy_read(opp, addr);
  934. }
  935. }
  936. static void openpic_write(void *opaque, target_phys_addr_t addr,
  937. uint64_t data, unsigned size)
  938. {
  939. openpic_t *opp = opaque;
  940. switch (size) {
  941. case 4: return openpic_writel(opp, addr, data);
  942. default: return openpic_buggy_write(opp, addr, data);
  943. }
  944. }
  945. static const MemoryRegionOps openpic_ops = {
  946. .read = openpic_read,
  947. .write = openpic_write,
  948. .endianness = DEVICE_LITTLE_ENDIAN,
  949. };
  950. static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
  951. {
  952. unsigned int i;
  953. for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
  954. qemu_put_be32s(f, &q->queue[i]);
  955. qemu_put_sbe32s(f, &q->next);
  956. qemu_put_sbe32s(f, &q->priority);
  957. }
  958. static void openpic_save(QEMUFile* f, void *opaque)
  959. {
  960. openpic_t *opp = (openpic_t *)opaque;
  961. unsigned int i;
  962. qemu_put_be32s(f, &opp->frep);
  963. qemu_put_be32s(f, &opp->glbc);
  964. qemu_put_be32s(f, &opp->micr);
  965. qemu_put_be32s(f, &opp->veni);
  966. qemu_put_be32s(f, &opp->pint);
  967. qemu_put_be32s(f, &opp->spve);
  968. qemu_put_be32s(f, &opp->tifr);
  969. for (i = 0; i < opp->max_irq; i++) {
  970. qemu_put_be32s(f, &opp->src[i].ipvp);
  971. qemu_put_be32s(f, &opp->src[i].ide);
  972. qemu_put_sbe32s(f, &opp->src[i].type);
  973. qemu_put_sbe32s(f, &opp->src[i].last_cpu);
  974. qemu_put_sbe32s(f, &opp->src[i].pending);
  975. }
  976. qemu_put_sbe32s(f, &opp->nb_cpus);
  977. for (i = 0; i < opp->nb_cpus; i++) {
  978. qemu_put_be32s(f, &opp->dst[i].tfrr);
  979. qemu_put_be32s(f, &opp->dst[i].pctp);
  980. qemu_put_be32s(f, &opp->dst[i].pcsr);
  981. openpic_save_IRQ_queue(f, &opp->dst[i].raised);
  982. openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
  983. }
  984. for (i = 0; i < MAX_TMR; i++) {
  985. qemu_put_be32s(f, &opp->timers[i].ticc);
  986. qemu_put_be32s(f, &opp->timers[i].tibc);
  987. }
  988. #if MAX_DBL > 0
  989. qemu_put_be32s(f, &opp->dar);
  990. for (i = 0; i < MAX_DBL; i++) {
  991. qemu_put_be32s(f, &opp->doorbells[i].dmr);
  992. }
  993. #endif
  994. #if MAX_MBX > 0
  995. for (i = 0; i < MAX_MAILBOXES; i++) {
  996. qemu_put_be32s(f, &opp->mailboxes[i].mbr);
  997. }
  998. #endif
  999. pci_device_save(&opp->pci_dev, f);
  1000. }
  1001. static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
  1002. {
  1003. unsigned int i;
  1004. for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
  1005. qemu_get_be32s(f, &q->queue[i]);
  1006. qemu_get_sbe32s(f, &q->next);
  1007. qemu_get_sbe32s(f, &q->priority);
  1008. }
  1009. static int openpic_load(QEMUFile* f, void *opaque, int version_id)
  1010. {
  1011. openpic_t *opp = (openpic_t *)opaque;
  1012. unsigned int i;
  1013. if (version_id != 1)
  1014. return -EINVAL;
  1015. qemu_get_be32s(f, &opp->frep);
  1016. qemu_get_be32s(f, &opp->glbc);
  1017. qemu_get_be32s(f, &opp->micr);
  1018. qemu_get_be32s(f, &opp->veni);
  1019. qemu_get_be32s(f, &opp->pint);
  1020. qemu_get_be32s(f, &opp->spve);
  1021. qemu_get_be32s(f, &opp->tifr);
  1022. for (i = 0; i < opp->max_irq; i++) {
  1023. qemu_get_be32s(f, &opp->src[i].ipvp);
  1024. qemu_get_be32s(f, &opp->src[i].ide);
  1025. qemu_get_sbe32s(f, &opp->src[i].type);
  1026. qemu_get_sbe32s(f, &opp->src[i].last_cpu);
  1027. qemu_get_sbe32s(f, &opp->src[i].pending);
  1028. }
  1029. qemu_get_sbe32s(f, &opp->nb_cpus);
  1030. for (i = 0; i < opp->nb_cpus; i++) {
  1031. qemu_get_be32s(f, &opp->dst[i].tfrr);
  1032. qemu_get_be32s(f, &opp->dst[i].pctp);
  1033. qemu_get_be32s(f, &opp->dst[i].pcsr);
  1034. openpic_load_IRQ_queue(f, &opp->dst[i].raised);
  1035. openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
  1036. }
  1037. for (i = 0; i < MAX_TMR; i++) {
  1038. qemu_get_be32s(f, &opp->timers[i].ticc);
  1039. qemu_get_be32s(f, &opp->timers[i].tibc);
  1040. }
  1041. #if MAX_DBL > 0
  1042. qemu_get_be32s(f, &opp->dar);
  1043. for (i = 0; i < MAX_DBL; i++) {
  1044. qemu_get_be32s(f, &opp->doorbells[i].dmr);
  1045. }
  1046. #endif
  1047. #if MAX_MBX > 0
  1048. for (i = 0; i < MAX_MAILBOXES; i++) {
  1049. qemu_get_be32s(f, &opp->mailboxes[i].mbr);
  1050. }
  1051. #endif
  1052. return pci_device_load(&opp->pci_dev, f);
  1053. }
  1054. static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
  1055. {
  1056. qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
  1057. }
  1058. qemu_irq *openpic_init (PCIBus *bus, MemoryRegion **pmem, int nb_cpus,
  1059. qemu_irq **irqs, qemu_irq irq_out)
  1060. {
  1061. openpic_t *opp;
  1062. uint8_t *pci_conf;
  1063. int i, m;
  1064. /* XXX: for now, only one CPU is supported */
  1065. if (nb_cpus != 1)
  1066. return NULL;
  1067. if (bus) {
  1068. opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
  1069. -1, NULL, NULL);
  1070. pci_conf = opp->pci_dev.config;
  1071. pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
  1072. pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
  1073. pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
  1074. pci_conf[0x3d] = 0x00; // no interrupt pin
  1075. memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
  1076. #if 0 // Don't implement ISU for now
  1077. opp_io_memory = cpu_register_io_memory(openpic_src_read,
  1078. openpic_src_write, NULL
  1079. DEVICE_NATIVE_ENDIAN);
  1080. cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
  1081. opp_io_memory);
  1082. #endif
  1083. /* Register I/O spaces */
  1084. pci_register_bar(&opp->pci_dev, 0,
  1085. PCI_BASE_ADDRESS_SPACE_MEMORY, &opp->mem);
  1086. } else {
  1087. opp = g_malloc0(sizeof(openpic_t));
  1088. memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
  1089. }
  1090. // isu_base &= 0xFFFC0000;
  1091. opp->nb_cpus = nb_cpus;
  1092. opp->max_irq = OPENPIC_MAX_IRQ;
  1093. opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
  1094. opp->irq_tim0 = OPENPIC_IRQ_TIM0;
  1095. /* Set IRQ types */
  1096. for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
  1097. opp->src[i].type = IRQ_EXTERNAL;
  1098. }
  1099. for (; i < OPENPIC_IRQ_TIM0; i++) {
  1100. opp->src[i].type = IRQ_SPECIAL;
  1101. }
  1102. #if MAX_IPI > 0
  1103. m = OPENPIC_IRQ_IPI0;
  1104. #else
  1105. m = OPENPIC_IRQ_DBL0;
  1106. #endif
  1107. for (; i < m; i++) {
  1108. opp->src[i].type = IRQ_TIMER;
  1109. }
  1110. for (; i < OPENPIC_MAX_IRQ; i++) {
  1111. opp->src[i].type = IRQ_INTERNAL;
  1112. }
  1113. for (i = 0; i < nb_cpus; i++)
  1114. opp->dst[i].irqs = irqs[i];
  1115. opp->irq_out = irq_out;
  1116. register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
  1117. openpic_save, openpic_load, opp);
  1118. qemu_register_reset(openpic_reset, opp);
  1119. opp->irq_raise = openpic_irq_raise;
  1120. opp->reset = openpic_reset;
  1121. if (pmem)
  1122. *pmem = &opp->mem;
  1123. return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
  1124. }
  1125. static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
  1126. {
  1127. int n_ci = IDR_CI0 - n_CPU;
  1128. if(test_bit(&src->ide, n_ci)) {
  1129. qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
  1130. }
  1131. else {
  1132. qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
  1133. }
  1134. }
  1135. static void mpic_reset (void *opaque)
  1136. {
  1137. openpic_t *mpp = (openpic_t *)opaque;
  1138. int i;
  1139. mpp->glbc = 0x80000000;
  1140. /* Initialise controller registers */
  1141. mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
  1142. mpp->veni = VENI;
  1143. mpp->pint = 0x00000000;
  1144. mpp->spve = 0x0000FFFF;
  1145. /* Initialise IRQ sources */
  1146. for (i = 0; i < mpp->max_irq; i++) {
  1147. mpp->src[i].ipvp = 0x80800000;
  1148. mpp->src[i].ide = 0x00000001;
  1149. }
  1150. /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
  1151. for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
  1152. mpp->src[i].ide = 0;
  1153. }
  1154. /* Initialise IRQ destinations */
  1155. for (i = 0; i < MAX_CPU; i++) {
  1156. mpp->dst[i].pctp = 0x0000000F;
  1157. mpp->dst[i].tfrr = 0x00000000;
  1158. memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
  1159. mpp->dst[i].raised.next = -1;
  1160. memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
  1161. mpp->dst[i].servicing.next = -1;
  1162. }
  1163. /* Initialise timers */
  1164. for (i = 0; i < MAX_TMR; i++) {
  1165. mpp->timers[i].ticc = 0x00000000;
  1166. mpp->timers[i].tibc = 0x80000000;
  1167. }
  1168. /* Go out of RESET state */
  1169. mpp->glbc = 0x00000000;
  1170. }
  1171. static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val)
  1172. {
  1173. openpic_t *mpp = opaque;
  1174. int idx, cpu;
  1175. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1176. if (addr & 0xF)
  1177. return;
  1178. addr &= 0xFFFF;
  1179. cpu = addr >> 12;
  1180. idx = (addr >> 6) & 0x3;
  1181. switch (addr & 0x30) {
  1182. case 0x00: /* gtccr */
  1183. break;
  1184. case 0x10: /* gtbcr */
  1185. if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
  1186. (val & 0x80000000) == 0 &&
  1187. (mpp->timers[idx].tibc & 0x80000000) != 0)
  1188. mpp->timers[idx].ticc &= ~0x80000000;
  1189. mpp->timers[idx].tibc = val;
  1190. break;
  1191. case 0x20: /* GTIVPR */
  1192. write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
  1193. break;
  1194. case 0x30: /* GTIDR & TFRR */
  1195. if ((addr & 0xF0) == 0xF0)
  1196. mpp->dst[cpu].tfrr = val;
  1197. else
  1198. write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
  1199. break;
  1200. }
  1201. }
  1202. static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
  1203. {
  1204. openpic_t *mpp = opaque;
  1205. uint32_t retval;
  1206. int idx, cpu;
  1207. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1208. retval = 0xFFFFFFFF;
  1209. if (addr & 0xF)
  1210. return retval;
  1211. addr &= 0xFFFF;
  1212. cpu = addr >> 12;
  1213. idx = (addr >> 6) & 0x3;
  1214. switch (addr & 0x30) {
  1215. case 0x00: /* gtccr */
  1216. retval = mpp->timers[idx].ticc;
  1217. break;
  1218. case 0x10: /* gtbcr */
  1219. retval = mpp->timers[idx].tibc;
  1220. break;
  1221. case 0x20: /* TIPV */
  1222. retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
  1223. break;
  1224. case 0x30: /* TIDR */
  1225. if ((addr &0xF0) == 0XF0)
  1226. retval = mpp->dst[cpu].tfrr;
  1227. else
  1228. retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
  1229. break;
  1230. }
  1231. DPRINTF("%s: => %08x\n", __func__, retval);
  1232. return retval;
  1233. }
  1234. static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
  1235. uint32_t val)
  1236. {
  1237. openpic_t *mpp = opaque;
  1238. int idx = MPIC_EXT_IRQ;
  1239. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1240. if (addr & 0xF)
  1241. return;
  1242. addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1243. if (addr < MPIC_EXT_REG_SIZE) {
  1244. idx += (addr & 0xFFF0) >> 5;
  1245. if (addr & 0x10) {
  1246. /* EXDE / IFEDE / IEEDE */
  1247. write_IRQreg_ide(mpp, idx, val);
  1248. } else {
  1249. /* EXVP / IFEVP / IEEVP */
  1250. write_IRQreg_ipvp(mpp, idx, val);
  1251. }
  1252. }
  1253. }
  1254. static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
  1255. {
  1256. openpic_t *mpp = opaque;
  1257. uint32_t retval;
  1258. int idx = MPIC_EXT_IRQ;
  1259. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1260. retval = 0xFFFFFFFF;
  1261. if (addr & 0xF)
  1262. return retval;
  1263. addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1264. if (addr < MPIC_EXT_REG_SIZE) {
  1265. idx += (addr & 0xFFF0) >> 5;
  1266. if (addr & 0x10) {
  1267. /* EXDE / IFEDE / IEEDE */
  1268. retval = read_IRQreg_ide(mpp, idx);
  1269. } else {
  1270. /* EXVP / IFEVP / IEEVP */
  1271. retval = read_IRQreg_ipvp(mpp, idx);
  1272. }
  1273. DPRINTF("%s: => %08x\n", __func__, retval);
  1274. }
  1275. return retval;
  1276. }
  1277. static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
  1278. uint32_t val)
  1279. {
  1280. openpic_t *mpp = opaque;
  1281. int idx = MPIC_INT_IRQ;
  1282. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1283. if (addr & 0xF)
  1284. return;
  1285. addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1286. if (addr < MPIC_INT_REG_SIZE) {
  1287. idx += (addr & 0xFFF0) >> 5;
  1288. if (addr & 0x10) {
  1289. /* EXDE / IFEDE / IEEDE */
  1290. write_IRQreg_ide(mpp, idx, val);
  1291. } else {
  1292. /* EXVP / IFEVP / IEEVP */
  1293. write_IRQreg_ipvp(mpp, idx, val);
  1294. }
  1295. }
  1296. }
  1297. static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
  1298. {
  1299. openpic_t *mpp = opaque;
  1300. uint32_t retval;
  1301. int idx = MPIC_INT_IRQ;
  1302. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1303. retval = 0xFFFFFFFF;
  1304. if (addr & 0xF)
  1305. return retval;
  1306. addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1307. if (addr < MPIC_INT_REG_SIZE) {
  1308. idx += (addr & 0xFFF0) >> 5;
  1309. if (addr & 0x10) {
  1310. /* EXDE / IFEDE / IEEDE */
  1311. retval = read_IRQreg_ide(mpp, idx);
  1312. } else {
  1313. /* EXVP / IFEVP / IEEVP */
  1314. retval = read_IRQreg_ipvp(mpp, idx);
  1315. }
  1316. DPRINTF("%s: => %08x\n", __func__, retval);
  1317. }
  1318. return retval;
  1319. }
  1320. static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
  1321. uint32_t val)
  1322. {
  1323. openpic_t *mpp = opaque;
  1324. int idx = MPIC_MSG_IRQ;
  1325. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1326. if (addr & 0xF)
  1327. return;
  1328. addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1329. if (addr < MPIC_MSG_REG_SIZE) {
  1330. idx += (addr & 0xFFF0) >> 5;
  1331. if (addr & 0x10) {
  1332. /* EXDE / IFEDE / IEEDE */
  1333. write_IRQreg_ide(mpp, idx, val);
  1334. } else {
  1335. /* EXVP / IFEVP / IEEVP */
  1336. write_IRQreg_ipvp(mpp, idx, val);
  1337. }
  1338. }
  1339. }
  1340. static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
  1341. {
  1342. openpic_t *mpp = opaque;
  1343. uint32_t retval;
  1344. int idx = MPIC_MSG_IRQ;
  1345. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1346. retval = 0xFFFFFFFF;
  1347. if (addr & 0xF)
  1348. return retval;
  1349. addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1350. if (addr < MPIC_MSG_REG_SIZE) {
  1351. idx += (addr & 0xFFF0) >> 5;
  1352. if (addr & 0x10) {
  1353. /* EXDE / IFEDE / IEEDE */
  1354. retval = read_IRQreg_ide(mpp, idx);
  1355. } else {
  1356. /* EXVP / IFEVP / IEEVP */
  1357. retval = read_IRQreg_ipvp(mpp, idx);
  1358. }
  1359. DPRINTF("%s: => %08x\n", __func__, retval);
  1360. }
  1361. return retval;
  1362. }
  1363. static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
  1364. uint32_t val)
  1365. {
  1366. openpic_t *mpp = opaque;
  1367. int idx = MPIC_MSI_IRQ;
  1368. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1369. if (addr & 0xF)
  1370. return;
  1371. addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1372. if (addr < MPIC_MSI_REG_SIZE) {
  1373. idx += (addr & 0xFFF0) >> 5;
  1374. if (addr & 0x10) {
  1375. /* EXDE / IFEDE / IEEDE */
  1376. write_IRQreg_ide(mpp, idx, val);
  1377. } else {
  1378. /* EXVP / IFEVP / IEEVP */
  1379. write_IRQreg_ipvp(mpp, idx, val);
  1380. }
  1381. }
  1382. }
  1383. static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
  1384. {
  1385. openpic_t *mpp = opaque;
  1386. uint32_t retval;
  1387. int idx = MPIC_MSI_IRQ;
  1388. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1389. retval = 0xFFFFFFFF;
  1390. if (addr & 0xF)
  1391. return retval;
  1392. addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
  1393. if (addr < MPIC_MSI_REG_SIZE) {
  1394. idx += (addr & 0xFFF0) >> 5;
  1395. if (addr & 0x10) {
  1396. /* EXDE / IFEDE / IEEDE */
  1397. retval = read_IRQreg_ide(mpp, idx);
  1398. } else {
  1399. /* EXVP / IFEVP / IEEVP */
  1400. retval = read_IRQreg_ipvp(mpp, idx);
  1401. }
  1402. DPRINTF("%s: => %08x\n", __func__, retval);
  1403. }
  1404. return retval;
  1405. }
  1406. static const MemoryRegionOps mpic_glb_ops = {
  1407. .old_mmio = {
  1408. .write = { openpic_buggy_write,
  1409. openpic_buggy_write,
  1410. openpic_gbl_write,
  1411. },
  1412. .read = { openpic_buggy_read,
  1413. openpic_buggy_read,
  1414. openpic_gbl_read,
  1415. },
  1416. },
  1417. .endianness = DEVICE_BIG_ENDIAN,
  1418. };
  1419. static const MemoryRegionOps mpic_tmr_ops = {
  1420. .old_mmio = {
  1421. .write = { openpic_buggy_write,
  1422. openpic_buggy_write,
  1423. mpic_timer_write,
  1424. },
  1425. .read = { openpic_buggy_read,
  1426. openpic_buggy_read,
  1427. mpic_timer_read,
  1428. },
  1429. },
  1430. .endianness = DEVICE_BIG_ENDIAN,
  1431. };
  1432. static const MemoryRegionOps mpic_cpu_ops = {
  1433. .old_mmio = {
  1434. .write = { openpic_buggy_write,
  1435. openpic_buggy_write,
  1436. openpic_cpu_write,
  1437. },
  1438. .read = { openpic_buggy_read,
  1439. openpic_buggy_read,
  1440. openpic_cpu_read,
  1441. },
  1442. },
  1443. .endianness = DEVICE_BIG_ENDIAN,
  1444. };
  1445. static const MemoryRegionOps mpic_ext_ops = {
  1446. .old_mmio = {
  1447. .write = { openpic_buggy_write,
  1448. openpic_buggy_write,
  1449. mpic_src_ext_write,
  1450. },
  1451. .read = { openpic_buggy_read,
  1452. openpic_buggy_read,
  1453. mpic_src_ext_read,
  1454. },
  1455. },
  1456. .endianness = DEVICE_BIG_ENDIAN,
  1457. };
  1458. static const MemoryRegionOps mpic_int_ops = {
  1459. .old_mmio = {
  1460. .write = { openpic_buggy_write,
  1461. openpic_buggy_write,
  1462. mpic_src_int_write,
  1463. },
  1464. .read = { openpic_buggy_read,
  1465. openpic_buggy_read,
  1466. mpic_src_int_read,
  1467. },
  1468. },
  1469. .endianness = DEVICE_BIG_ENDIAN,
  1470. };
  1471. static const MemoryRegionOps mpic_msg_ops = {
  1472. .old_mmio = {
  1473. .write = { openpic_buggy_write,
  1474. openpic_buggy_write,
  1475. mpic_src_msg_write,
  1476. },
  1477. .read = { openpic_buggy_read,
  1478. openpic_buggy_read,
  1479. mpic_src_msg_read,
  1480. },
  1481. },
  1482. .endianness = DEVICE_BIG_ENDIAN,
  1483. };
  1484. static const MemoryRegionOps mpic_msi_ops = {
  1485. .old_mmio = {
  1486. .write = { openpic_buggy_write,
  1487. openpic_buggy_write,
  1488. mpic_src_msi_write,
  1489. },
  1490. .read = { openpic_buggy_read,
  1491. openpic_buggy_read,
  1492. mpic_src_msi_read,
  1493. },
  1494. },
  1495. .endianness = DEVICE_BIG_ENDIAN,
  1496. };
  1497. qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
  1498. int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
  1499. {
  1500. openpic_t *mpp;
  1501. int i;
  1502. struct {
  1503. const char *name;
  1504. MemoryRegionOps const *ops;
  1505. target_phys_addr_t start_addr;
  1506. ram_addr_t size;
  1507. } const list[] = {
  1508. {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
  1509. {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
  1510. {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
  1511. {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
  1512. {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
  1513. {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
  1514. {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
  1515. };
  1516. mpp = g_malloc0(sizeof(openpic_t));
  1517. memory_region_init(&mpp->mem, "mpic", 0x40000);
  1518. memory_region_add_subregion(address_space, base, &mpp->mem);
  1519. for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
  1520. memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
  1521. list[i].name, list[i].size);
  1522. memory_region_add_subregion(&mpp->mem, list[i].start_addr,
  1523. &mpp->sub_io_mem[i]);
  1524. }
  1525. mpp->nb_cpus = nb_cpus;
  1526. mpp->max_irq = MPIC_MAX_IRQ;
  1527. mpp->irq_ipi0 = MPIC_IPI_IRQ;
  1528. mpp->irq_tim0 = MPIC_TMR_IRQ;
  1529. for (i = 0; i < nb_cpus; i++)
  1530. mpp->dst[i].irqs = irqs[i];
  1531. mpp->irq_out = irq_out;
  1532. mpp->irq_raise = mpic_irq_raise;
  1533. mpp->reset = mpic_reset;
  1534. register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
  1535. qemu_register_reset(mpic_reset, mpp);
  1536. return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
  1537. }