openpic.c 46 KB

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