openpic.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721
  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, args...) do { printf(fmt , ##args); } while (0)
  42. #else
  43. #define DPRINTF(fmt, args...) do { } while (0)
  44. #endif
  45. #define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
  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 0
  56. #define VID (0x00000000)
  57. #elif defined(USE_MPCxxx)
  58. #define MAX_CPU 2
  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
  118. enum mpic_ide_bits {
  119. IDR_EP = 0,
  120. IDR_CI0 = 1,
  121. IDR_CI1 = 2,
  122. IDR_P1 = 30,
  123. IDR_P0 = 31,
  124. };
  125. #else
  126. #error "Please select which OpenPic implementation is to be emulated"
  127. #endif
  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. int need_swap;
  219. void (*reset) (void *);
  220. void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
  221. } openpic_t;
  222. static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val)
  223. {
  224. if (opp->need_swap)
  225. return bswap32(val);
  226. return val;
  227. }
  228. static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
  229. {
  230. set_bit(q->queue, n_IRQ);
  231. }
  232. static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
  233. {
  234. reset_bit(q->queue, n_IRQ);
  235. }
  236. static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
  237. {
  238. return test_bit(q->queue, n_IRQ);
  239. }
  240. static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
  241. {
  242. int next, i;
  243. int priority;
  244. next = -1;
  245. priority = -1;
  246. for (i = 0; i < opp->max_irq; i++) {
  247. if (IRQ_testbit(q, i)) {
  248. DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
  249. i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
  250. if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
  251. next = i;
  252. priority = IPVP_PRIORITY(opp->src[i].ipvp);
  253. }
  254. }
  255. }
  256. q->next = next;
  257. q->priority = priority;
  258. }
  259. static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
  260. {
  261. if (q->next == -1) {
  262. /* XXX: optimize */
  263. IRQ_check(opp, q);
  264. }
  265. return q->next;
  266. }
  267. static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
  268. {
  269. IRQ_dst_t *dst;
  270. IRQ_src_t *src;
  271. int priority;
  272. dst = &opp->dst[n_CPU];
  273. src = &opp->src[n_IRQ];
  274. priority = IPVP_PRIORITY(src->ipvp);
  275. if (priority <= dst->pctp) {
  276. /* Too low priority */
  277. DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
  278. __func__, n_IRQ, n_CPU);
  279. return;
  280. }
  281. if (IRQ_testbit(&dst->raised, n_IRQ)) {
  282. /* Interrupt miss */
  283. DPRINTF("%s: IRQ %d was missed on CPU %d\n",
  284. __func__, n_IRQ, n_CPU);
  285. return;
  286. }
  287. set_bit(&src->ipvp, IPVP_ACTIVITY);
  288. IRQ_setbit(&dst->raised, n_IRQ);
  289. if (priority < dst->raised.priority) {
  290. /* An higher priority IRQ is already raised */
  291. DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
  292. __func__, n_IRQ, dst->raised.next, n_CPU);
  293. return;
  294. }
  295. IRQ_get_next(opp, &dst->raised);
  296. if (IRQ_get_next(opp, &dst->servicing) != -1 &&
  297. priority <= dst->servicing.priority) {
  298. DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
  299. __func__, n_IRQ, dst->servicing.next, n_CPU);
  300. /* Already servicing a higher priority IRQ */
  301. return;
  302. }
  303. DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
  304. opp->irq_raise(opp, n_CPU, src);
  305. }
  306. /* update pic state because registers for n_IRQ have changed value */
  307. static void openpic_update_irq(openpic_t *opp, int n_IRQ)
  308. {
  309. IRQ_src_t *src;
  310. int i;
  311. src = &opp->src[n_IRQ];
  312. if (!src->pending) {
  313. /* no irq pending */
  314. DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
  315. return;
  316. }
  317. if (test_bit(&src->ipvp, IPVP_MASK)) {
  318. /* Interrupt source is disabled */
  319. DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
  320. return;
  321. }
  322. if (IPVP_PRIORITY(src->ipvp) == 0) {
  323. /* Priority set to zero */
  324. DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
  325. return;
  326. }
  327. if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
  328. /* IRQ already active */
  329. DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
  330. return;
  331. }
  332. if (src->ide == 0x00000000) {
  333. /* No target */
  334. DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
  335. return;
  336. }
  337. if (src->ide == (1 << src->last_cpu)) {
  338. /* Only one CPU is allowed to receive this IRQ */
  339. IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
  340. } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
  341. /* Directed delivery mode */
  342. for (i = 0; i < opp->nb_cpus; i++) {
  343. if (test_bit(&src->ide, i))
  344. IRQ_local_pipe(opp, i, n_IRQ);
  345. }
  346. } else {
  347. /* Distributed delivery mode */
  348. for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
  349. if (i == opp->nb_cpus)
  350. i = 0;
  351. if (test_bit(&src->ide, i)) {
  352. IRQ_local_pipe(opp, i, n_IRQ);
  353. src->last_cpu = i;
  354. break;
  355. }
  356. }
  357. }
  358. }
  359. static void openpic_set_irq(void *opaque, int n_IRQ, int level)
  360. {
  361. openpic_t *opp = opaque;
  362. IRQ_src_t *src;
  363. src = &opp->src[n_IRQ];
  364. DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
  365. n_IRQ, level, src->ipvp);
  366. if (test_bit(&src->ipvp, IPVP_SENSE)) {
  367. /* level-sensitive irq */
  368. src->pending = level;
  369. if (!level)
  370. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  371. } else {
  372. /* edge-sensitive irq */
  373. if (level)
  374. src->pending = 1;
  375. }
  376. openpic_update_irq(opp, n_IRQ);
  377. }
  378. static void openpic_reset (void *opaque)
  379. {
  380. openpic_t *opp = (openpic_t *)opaque;
  381. int i;
  382. opp->glbc = 0x80000000;
  383. /* Initialise controller registers */
  384. opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
  385. opp->veni = VENI;
  386. opp->pint = 0x00000000;
  387. opp->spve = 0x000000FF;
  388. opp->tifr = 0x003F7A00;
  389. /* ? */
  390. opp->micr = 0x00000000;
  391. /* Initialise IRQ sources */
  392. for (i = 0; i < opp->max_irq; i++) {
  393. opp->src[i].ipvp = 0xA0000000;
  394. opp->src[i].ide = 0x00000000;
  395. }
  396. /* Initialise IRQ destinations */
  397. for (i = 0; i < MAX_CPU; i++) {
  398. opp->dst[i].pctp = 0x0000000F;
  399. opp->dst[i].pcsr = 0x00000000;
  400. memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
  401. memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
  402. }
  403. /* Initialise timers */
  404. for (i = 0; i < MAX_TMR; i++) {
  405. opp->timers[i].ticc = 0x00000000;
  406. opp->timers[i].tibc = 0x80000000;
  407. }
  408. /* Initialise doorbells */
  409. #if MAX_DBL > 0
  410. opp->dar = 0x00000000;
  411. for (i = 0; i < MAX_DBL; i++) {
  412. opp->doorbells[i].dmr = 0x00000000;
  413. }
  414. #endif
  415. /* Initialise mailboxes */
  416. #if MAX_MBX > 0
  417. for (i = 0; i < MAX_MBX; i++) { /* ? */
  418. opp->mailboxes[i].mbr = 0x00000000;
  419. }
  420. #endif
  421. /* Go out of RESET state */
  422. opp->glbc = 0x00000000;
  423. }
  424. static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
  425. {
  426. uint32_t retval;
  427. switch (reg) {
  428. case IRQ_IPVP:
  429. retval = opp->src[n_IRQ].ipvp;
  430. break;
  431. case IRQ_IDE:
  432. retval = opp->src[n_IRQ].ide;
  433. break;
  434. }
  435. return retval;
  436. }
  437. static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
  438. uint32_t reg, uint32_t val)
  439. {
  440. uint32_t tmp;
  441. switch (reg) {
  442. case IRQ_IPVP:
  443. /* NOTE: not fully accurate for special IRQs, but simple and
  444. sufficient */
  445. /* ACTIVITY bit is read-only */
  446. opp->src[n_IRQ].ipvp =
  447. (opp->src[n_IRQ].ipvp & 0x40000000) |
  448. (val & 0x800F00FF);
  449. openpic_update_irq(opp, n_IRQ);
  450. DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
  451. n_IRQ, val, opp->src[n_IRQ].ipvp);
  452. break;
  453. case IRQ_IDE:
  454. tmp = val & 0xC0000000;
  455. tmp |= val & ((1 << MAX_CPU) - 1);
  456. opp->src[n_IRQ].ide = tmp;
  457. DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
  458. break;
  459. }
  460. }
  461. #if 0 // Code provision for Intel model
  462. #if MAX_DBL > 0
  463. static uint32_t read_doorbell_register (openpic_t *opp,
  464. int n_dbl, uint32_t offset)
  465. {
  466. uint32_t retval;
  467. switch (offset) {
  468. case DBL_IPVP_OFFSET:
  469. retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
  470. break;
  471. case DBL_IDE_OFFSET:
  472. retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
  473. break;
  474. case DBL_DMR_OFFSET:
  475. retval = opp->doorbells[n_dbl].dmr;
  476. break;
  477. }
  478. return retval;
  479. }
  480. static void write_doorbell_register (penpic_t *opp, int n_dbl,
  481. uint32_t offset, uint32_t value)
  482. {
  483. switch (offset) {
  484. case DBL_IVPR_OFFSET:
  485. write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
  486. break;
  487. case DBL_IDE_OFFSET:
  488. write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
  489. break;
  490. case DBL_DMR_OFFSET:
  491. opp->doorbells[n_dbl].dmr = value;
  492. break;
  493. }
  494. }
  495. #endif
  496. #if MAX_MBX > 0
  497. static uint32_t read_mailbox_register (openpic_t *opp,
  498. int n_mbx, uint32_t offset)
  499. {
  500. uint32_t retval;
  501. switch (offset) {
  502. case MBX_MBR_OFFSET:
  503. retval = opp->mailboxes[n_mbx].mbr;
  504. break;
  505. case MBX_IVPR_OFFSET:
  506. retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
  507. break;
  508. case MBX_DMR_OFFSET:
  509. retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
  510. break;
  511. }
  512. return retval;
  513. }
  514. static void write_mailbox_register (openpic_t *opp, int n_mbx,
  515. uint32_t address, uint32_t value)
  516. {
  517. switch (offset) {
  518. case MBX_MBR_OFFSET:
  519. opp->mailboxes[n_mbx].mbr = value;
  520. break;
  521. case MBX_IVPR_OFFSET:
  522. write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
  523. break;
  524. case MBX_DMR_OFFSET:
  525. write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
  526. break;
  527. }
  528. }
  529. #endif
  530. #endif /* 0 : Code provision for Intel model */
  531. static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val)
  532. {
  533. openpic_t *opp = opaque;
  534. IRQ_dst_t *dst;
  535. int idx;
  536. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  537. if (addr & 0xF)
  538. return;
  539. #if defined TARGET_WORDS_BIGENDIAN
  540. val = openpic_swap32(opp, val);
  541. #endif
  542. addr &= 0xFF;
  543. switch (addr) {
  544. case 0x00: /* FREP */
  545. break;
  546. case 0x20: /* GLBC */
  547. if (val & 0x80000000 && opp->reset)
  548. opp->reset(opp);
  549. opp->glbc = val & ~0x80000000;
  550. break;
  551. case 0x80: /* VENI */
  552. break;
  553. case 0x90: /* PINT */
  554. for (idx = 0; idx < opp->nb_cpus; idx++) {
  555. if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
  556. DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
  557. dst = &opp->dst[idx];
  558. qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
  559. } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
  560. DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
  561. dst = &opp->dst[idx];
  562. qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
  563. }
  564. }
  565. opp->pint = val;
  566. break;
  567. #if MAX_IPI > 0
  568. case 0xA0: /* IPI_IPVP */
  569. case 0xB0:
  570. case 0xC0:
  571. case 0xD0:
  572. {
  573. int idx;
  574. idx = (addr - 0xA0) >> 4;
  575. write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP, val);
  576. }
  577. break;
  578. #endif
  579. case 0xE0: /* SPVE */
  580. opp->spve = val & 0x000000FF;
  581. break;
  582. case 0xF0: /* TIFR */
  583. opp->tifr = val;
  584. break;
  585. default:
  586. break;
  587. }
  588. }
  589. static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
  590. {
  591. openpic_t *opp = opaque;
  592. uint32_t retval;
  593. DPRINTF("%s: addr %08x\n", __func__, addr);
  594. retval = 0xFFFFFFFF;
  595. if (addr & 0xF)
  596. return retval;
  597. addr &= 0xFF;
  598. switch (addr) {
  599. case 0x00: /* FREP */
  600. retval = opp->frep;
  601. break;
  602. case 0x20: /* GLBC */
  603. retval = opp->glbc;
  604. break;
  605. case 0x80: /* VENI */
  606. retval = opp->veni;
  607. break;
  608. case 0x90: /* PINT */
  609. retval = 0x00000000;
  610. break;
  611. #if MAX_IPI > 0
  612. case 0xA0: /* IPI_IPVP */
  613. case 0xB0:
  614. case 0xC0:
  615. case 0xD0:
  616. {
  617. int idx;
  618. idx = (addr - 0xA0) >> 4;
  619. retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IPVP);
  620. }
  621. break;
  622. #endif
  623. case 0xE0: /* SPVE */
  624. retval = opp->spve;
  625. break;
  626. case 0xF0: /* TIFR */
  627. retval = opp->tifr;
  628. break;
  629. default:
  630. break;
  631. }
  632. DPRINTF("%s: => %08x\n", __func__, retval);
  633. #if defined TARGET_WORDS_BIGENDIAN
  634. retval = openpic_swap32(opp, retval);
  635. #endif
  636. return retval;
  637. }
  638. static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
  639. {
  640. openpic_t *opp = opaque;
  641. int idx;
  642. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  643. if (addr & 0xF)
  644. return;
  645. #if defined TARGET_WORDS_BIGENDIAN
  646. val = openpic_swap32(opp, val);
  647. #endif
  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(opp, opp->irq_tim0 + idx, IRQ_IPVP, val);
  664. break;
  665. case 0x30: /* TIDE */
  666. write_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE, 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(opp, opp->irq_tim0 + idx, IRQ_IPVP);
  692. break;
  693. case 0x30: /* TIDE */
  694. retval = read_IRQreg(opp, opp->irq_tim0 + idx, IRQ_IDE);
  695. break;
  696. }
  697. DPRINTF("%s: => %08x\n", __func__, retval);
  698. #if defined TARGET_WORDS_BIGENDIAN
  699. retval = openpic_swap32(opp, retval);
  700. #endif
  701. return retval;
  702. }
  703. static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
  704. {
  705. openpic_t *opp = opaque;
  706. int idx;
  707. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  708. if (addr & 0xF)
  709. return;
  710. #if defined TARGET_WORDS_BIGENDIAN
  711. val = openpic_swap32(opp, val);
  712. #endif
  713. addr = addr & 0xFFF0;
  714. idx = addr >> 5;
  715. if (addr & 0x10) {
  716. /* EXDE / IFEDE / IEEDE */
  717. write_IRQreg(opp, idx, IRQ_IDE, val);
  718. } else {
  719. /* EXVP / IFEVP / IEEVP */
  720. write_IRQreg(opp, idx, IRQ_IPVP, val);
  721. }
  722. }
  723. static uint32_t openpic_src_read (void *opaque, uint32_t addr)
  724. {
  725. openpic_t *opp = opaque;
  726. uint32_t retval;
  727. int idx;
  728. DPRINTF("%s: addr %08x\n", __func__, addr);
  729. retval = 0xFFFFFFFF;
  730. if (addr & 0xF)
  731. return retval;
  732. addr = addr & 0xFFF0;
  733. idx = addr >> 5;
  734. if (addr & 0x10) {
  735. /* EXDE / IFEDE / IEEDE */
  736. retval = read_IRQreg(opp, idx, IRQ_IDE);
  737. } else {
  738. /* EXVP / IFEVP / IEEVP */
  739. retval = read_IRQreg(opp, idx, IRQ_IPVP);
  740. }
  741. DPRINTF("%s: => %08x\n", __func__, retval);
  742. #if defined TARGET_WORDS_BIGENDIAN
  743. retval = openpic_swap32(opp, retval);
  744. #endif
  745. return retval;
  746. }
  747. static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t val)
  748. {
  749. openpic_t *opp = opaque;
  750. IRQ_src_t *src;
  751. IRQ_dst_t *dst;
  752. int idx, s_IRQ, n_IRQ;
  753. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  754. if (addr & 0xF)
  755. return;
  756. #if defined TARGET_WORDS_BIGENDIAN
  757. val = openpic_swap32(opp, val);
  758. #endif
  759. addr &= 0x1FFF0;
  760. idx = addr / 0x1000;
  761. dst = &opp->dst[idx];
  762. addr &= 0xFF0;
  763. switch (addr) {
  764. #if MAX_IPI > 0
  765. case 0x40: /* PIPD */
  766. case 0x50:
  767. case 0x60:
  768. case 0x70:
  769. idx = (addr - 0x40) >> 4;
  770. write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
  771. openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
  772. openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
  773. break;
  774. #endif
  775. case 0x80: /* PCTP */
  776. dst->pctp = val & 0x0000000F;
  777. break;
  778. case 0x90: /* WHOAMI */
  779. /* Read-only register */
  780. break;
  781. case 0xA0: /* PIAC */
  782. /* Read-only register */
  783. break;
  784. case 0xB0: /* PEOI */
  785. DPRINTF("PEOI\n");
  786. s_IRQ = IRQ_get_next(opp, &dst->servicing);
  787. IRQ_resetbit(&dst->servicing, s_IRQ);
  788. dst->servicing.next = -1;
  789. /* Set up next servicing IRQ */
  790. s_IRQ = IRQ_get_next(opp, &dst->servicing);
  791. /* Check queued interrupts. */
  792. n_IRQ = IRQ_get_next(opp, &dst->raised);
  793. src = &opp->src[n_IRQ];
  794. if (n_IRQ != -1 &&
  795. (s_IRQ == -1 ||
  796. IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
  797. DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
  798. idx, n_IRQ);
  799. opp->irq_raise(opp, idx, src);
  800. }
  801. break;
  802. default:
  803. break;
  804. }
  805. }
  806. static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
  807. {
  808. openpic_t *opp = opaque;
  809. IRQ_src_t *src;
  810. IRQ_dst_t *dst;
  811. uint32_t retval;
  812. int idx, n_IRQ;
  813. DPRINTF("%s: addr %08x\n", __func__, addr);
  814. retval = 0xFFFFFFFF;
  815. if (addr & 0xF)
  816. return retval;
  817. addr &= 0x1FFF0;
  818. idx = addr / 0x1000;
  819. dst = &opp->dst[idx];
  820. addr &= 0xFF0;
  821. switch (addr) {
  822. case 0x80: /* PCTP */
  823. retval = dst->pctp;
  824. break;
  825. case 0x90: /* WHOAMI */
  826. retval = idx;
  827. break;
  828. case 0xA0: /* PIAC */
  829. DPRINTF("Lower OpenPIC INT output\n");
  830. qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
  831. n_IRQ = IRQ_get_next(opp, &dst->raised);
  832. DPRINTF("PIAC: irq=%d\n", n_IRQ);
  833. if (n_IRQ == -1) {
  834. /* No more interrupt pending */
  835. retval = IPVP_VECTOR(opp->spve);
  836. } else {
  837. src = &opp->src[n_IRQ];
  838. if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
  839. !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
  840. /* - Spurious level-sensitive IRQ
  841. * - Priorities has been changed
  842. * and the pending IRQ isn't allowed anymore
  843. */
  844. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  845. retval = IPVP_VECTOR(opp->spve);
  846. } else {
  847. /* IRQ enter servicing state */
  848. IRQ_setbit(&dst->servicing, n_IRQ);
  849. retval = IPVP_VECTOR(src->ipvp);
  850. }
  851. IRQ_resetbit(&dst->raised, n_IRQ);
  852. dst->raised.next = -1;
  853. if (!test_bit(&src->ipvp, IPVP_SENSE)) {
  854. /* edge-sensitive IRQ */
  855. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  856. src->pending = 0;
  857. }
  858. }
  859. break;
  860. case 0xB0: /* PEOI */
  861. retval = 0;
  862. break;
  863. #if MAX_IPI > 0
  864. case 0x40: /* IDE */
  865. case 0x50:
  866. idx = (addr - 0x40) >> 4;
  867. retval = read_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE);
  868. break;
  869. #endif
  870. default:
  871. break;
  872. }
  873. DPRINTF("%s: => %08x\n", __func__, retval);
  874. #if defined TARGET_WORDS_BIGENDIAN
  875. retval = openpic_swap32(opp, retval);
  876. #endif
  877. return retval;
  878. }
  879. static void openpic_buggy_write (void *opaque,
  880. target_phys_addr_t addr, uint32_t val)
  881. {
  882. printf("Invalid OPENPIC write access !\n");
  883. }
  884. static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
  885. {
  886. printf("Invalid OPENPIC read access !\n");
  887. return -1;
  888. }
  889. static void openpic_writel (void *opaque,
  890. target_phys_addr_t addr, uint32_t val)
  891. {
  892. openpic_t *opp = opaque;
  893. addr &= 0x3FFFF;
  894. DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
  895. if (addr < 0x1100) {
  896. /* Global registers */
  897. openpic_gbl_write(opp, addr, val);
  898. } else if (addr < 0x10000) {
  899. /* Timers registers */
  900. openpic_timer_write(opp, addr, val);
  901. } else if (addr < 0x20000) {
  902. /* Source registers */
  903. openpic_src_write(opp, addr, val);
  904. } else {
  905. /* CPU registers */
  906. openpic_cpu_write(opp, addr, val);
  907. }
  908. }
  909. static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
  910. {
  911. openpic_t *opp = opaque;
  912. uint32_t retval;
  913. addr &= 0x3FFFF;
  914. DPRINTF("%s: offset %08x\n", __func__, (int)addr);
  915. if (addr < 0x1100) {
  916. /* Global registers */
  917. retval = openpic_gbl_read(opp, addr);
  918. } else if (addr < 0x10000) {
  919. /* Timers registers */
  920. retval = openpic_timer_read(opp, addr);
  921. } else if (addr < 0x20000) {
  922. /* Source registers */
  923. retval = openpic_src_read(opp, addr);
  924. } else {
  925. /* CPU registers */
  926. retval = openpic_cpu_read(opp, addr);
  927. }
  928. return retval;
  929. }
  930. static CPUWriteMemoryFunc *openpic_write[] = {
  931. &openpic_buggy_write,
  932. &openpic_buggy_write,
  933. &openpic_writel,
  934. };
  935. static CPUReadMemoryFunc *openpic_read[] = {
  936. &openpic_buggy_read,
  937. &openpic_buggy_read,
  938. &openpic_readl,
  939. };
  940. static void openpic_map(PCIDevice *pci_dev, int region_num,
  941. uint32_t addr, uint32_t size, int type)
  942. {
  943. openpic_t *opp;
  944. DPRINTF("Map OpenPIC\n");
  945. opp = (openpic_t *)pci_dev;
  946. /* Global registers */
  947. DPRINTF("Register OPENPIC gbl %08x => %08x\n",
  948. addr + 0x1000, addr + 0x1000 + 0x100);
  949. /* Timer registers */
  950. DPRINTF("Register OPENPIC timer %08x => %08x\n",
  951. addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
  952. /* Interrupt source registers */
  953. DPRINTF("Register OPENPIC src %08x => %08x\n",
  954. addr + 0x10000, addr + 0x10000 + 0x20 * (OPENPIC_EXT_IRQ + 2));
  955. /* Per CPU registers */
  956. DPRINTF("Register OPENPIC dst %08x => %08x\n",
  957. addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
  958. cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
  959. #if 0 // Don't implement ISU for now
  960. opp_io_memory = cpu_register_io_memory(0, openpic_src_read,
  961. openpic_src_write);
  962. cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
  963. opp_io_memory);
  964. #endif
  965. }
  966. static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
  967. {
  968. unsigned int i;
  969. for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
  970. qemu_put_be32s(f, &q->queue[i]);
  971. qemu_put_sbe32s(f, &q->next);
  972. qemu_put_sbe32s(f, &q->priority);
  973. }
  974. static void openpic_save(QEMUFile* f, void *opaque)
  975. {
  976. openpic_t *opp = (openpic_t *)opaque;
  977. unsigned int i;
  978. qemu_put_be32s(f, &opp->frep);
  979. qemu_put_be32s(f, &opp->glbc);
  980. qemu_put_be32s(f, &opp->micr);
  981. qemu_put_be32s(f, &opp->veni);
  982. qemu_put_be32s(f, &opp->pint);
  983. qemu_put_be32s(f, &opp->spve);
  984. qemu_put_be32s(f, &opp->tifr);
  985. for (i = 0; i < opp->max_irq; i++) {
  986. qemu_put_be32s(f, &opp->src[i].ipvp);
  987. qemu_put_be32s(f, &opp->src[i].ide);
  988. qemu_put_sbe32s(f, &opp->src[i].type);
  989. qemu_put_sbe32s(f, &opp->src[i].last_cpu);
  990. qemu_put_sbe32s(f, &opp->src[i].pending);
  991. }
  992. qemu_put_sbe32s(f, &opp->nb_cpus);
  993. for (i = 0; i < opp->nb_cpus; i++) {
  994. qemu_put_be32s(f, &opp->dst[i].tfrr);
  995. qemu_put_be32s(f, &opp->dst[i].pctp);
  996. qemu_put_be32s(f, &opp->dst[i].pcsr);
  997. openpic_save_IRQ_queue(f, &opp->dst[i].raised);
  998. openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
  999. }
  1000. for (i = 0; i < MAX_TMR; i++) {
  1001. qemu_put_be32s(f, &opp->timers[i].ticc);
  1002. qemu_put_be32s(f, &opp->timers[i].tibc);
  1003. }
  1004. #if MAX_DBL > 0
  1005. qemu_put_be32s(f, &opp->dar);
  1006. for (i = 0; i < MAX_DBL; i++) {
  1007. qemu_put_be32s(f, &opp->doorbells[i].dmr);
  1008. }
  1009. #endif
  1010. #if MAX_MBX > 0
  1011. for (i = 0; i < MAX_MAILBOXES; i++) {
  1012. qemu_put_be32s(f, &opp->mailboxes[i].mbr);
  1013. }
  1014. #endif
  1015. pci_device_save(&opp->pci_dev, f);
  1016. }
  1017. static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
  1018. {
  1019. unsigned int i;
  1020. for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
  1021. qemu_get_be32s(f, &q->queue[i]);
  1022. qemu_get_sbe32s(f, &q->next);
  1023. qemu_get_sbe32s(f, &q->priority);
  1024. }
  1025. static int openpic_load(QEMUFile* f, void *opaque, int version_id)
  1026. {
  1027. openpic_t *opp = (openpic_t *)opaque;
  1028. unsigned int i;
  1029. if (version_id != 1)
  1030. return -EINVAL;
  1031. qemu_get_be32s(f, &opp->frep);
  1032. qemu_get_be32s(f, &opp->glbc);
  1033. qemu_get_be32s(f, &opp->micr);
  1034. qemu_get_be32s(f, &opp->veni);
  1035. qemu_get_be32s(f, &opp->pint);
  1036. qemu_get_be32s(f, &opp->spve);
  1037. qemu_get_be32s(f, &opp->tifr);
  1038. for (i = 0; i < opp->max_irq; i++) {
  1039. qemu_get_be32s(f, &opp->src[i].ipvp);
  1040. qemu_get_be32s(f, &opp->src[i].ide);
  1041. qemu_get_sbe32s(f, &opp->src[i].type);
  1042. qemu_get_sbe32s(f, &opp->src[i].last_cpu);
  1043. qemu_get_sbe32s(f, &opp->src[i].pending);
  1044. }
  1045. qemu_get_sbe32s(f, &opp->nb_cpus);
  1046. for (i = 0; i < opp->nb_cpus; i++) {
  1047. qemu_get_be32s(f, &opp->dst[i].tfrr);
  1048. qemu_get_be32s(f, &opp->dst[i].pctp);
  1049. qemu_get_be32s(f, &opp->dst[i].pcsr);
  1050. openpic_load_IRQ_queue(f, &opp->dst[i].raised);
  1051. openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
  1052. }
  1053. for (i = 0; i < MAX_TMR; i++) {
  1054. qemu_get_be32s(f, &opp->timers[i].ticc);
  1055. qemu_get_be32s(f, &opp->timers[i].tibc);
  1056. }
  1057. #if MAX_DBL > 0
  1058. qemu_get_be32s(f, &opp->dar);
  1059. for (i = 0; i < MAX_DBL; i++) {
  1060. qemu_get_be32s(f, &opp->doorbells[i].dmr);
  1061. }
  1062. #endif
  1063. #if MAX_MBX > 0
  1064. for (i = 0; i < MAX_MAILBOXES; i++) {
  1065. qemu_get_be32s(f, &opp->mailboxes[i].mbr);
  1066. }
  1067. #endif
  1068. return pci_device_load(&opp->pci_dev, f);
  1069. }
  1070. static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
  1071. {
  1072. qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
  1073. }
  1074. qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
  1075. qemu_irq **irqs, qemu_irq irq_out)
  1076. {
  1077. openpic_t *opp;
  1078. uint8_t *pci_conf;
  1079. int i, m;
  1080. /* XXX: for now, only one CPU is supported */
  1081. if (nb_cpus != 1)
  1082. return NULL;
  1083. if (bus) {
  1084. opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
  1085. -1, NULL, NULL);
  1086. if (opp == NULL)
  1087. return NULL;
  1088. pci_conf = opp->pci_dev.config;
  1089. pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_IBM);
  1090. pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_IBM_OPENPIC2);
  1091. pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); // FIXME?
  1092. pci_conf[0x0e] = 0x00; // header_type
  1093. pci_conf[0x3d] = 0x00; // no interrupt pin
  1094. /* Register I/O spaces */
  1095. pci_register_io_region((PCIDevice *)opp, 0, 0x40000,
  1096. PCI_ADDRESS_SPACE_MEM, &openpic_map);
  1097. } else {
  1098. opp = qemu_mallocz(sizeof(openpic_t));
  1099. }
  1100. opp->mem_index = cpu_register_io_memory(0, openpic_read,
  1101. openpic_write, opp);
  1102. // isu_base &= 0xFFFC0000;
  1103. opp->nb_cpus = nb_cpus;
  1104. opp->max_irq = OPENPIC_MAX_IRQ;
  1105. opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
  1106. opp->irq_tim0 = OPENPIC_IRQ_TIM0;
  1107. /* Set IRQ types */
  1108. for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
  1109. opp->src[i].type = IRQ_EXTERNAL;
  1110. }
  1111. for (; i < OPENPIC_IRQ_TIM0; i++) {
  1112. opp->src[i].type = IRQ_SPECIAL;
  1113. }
  1114. #if MAX_IPI > 0
  1115. m = OPENPIC_IRQ_IPI0;
  1116. #else
  1117. m = OPENPIC_IRQ_DBL0;
  1118. #endif
  1119. for (; i < m; i++) {
  1120. opp->src[i].type = IRQ_TIMER;
  1121. }
  1122. for (; i < OPENPIC_MAX_IRQ; i++) {
  1123. opp->src[i].type = IRQ_INTERNAL;
  1124. }
  1125. for (i = 0; i < nb_cpus; i++)
  1126. opp->dst[i].irqs = irqs[i];
  1127. opp->irq_out = irq_out;
  1128. opp->need_swap = 1;
  1129. register_savevm("openpic", 0, 2, openpic_save, openpic_load, opp);
  1130. qemu_register_reset(openpic_reset, opp);
  1131. opp->irq_raise = openpic_irq_raise;
  1132. opp->reset = openpic_reset;
  1133. opp->reset(opp);
  1134. if (pmem_index)
  1135. *pmem_index = opp->mem_index;
  1136. return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
  1137. }
  1138. static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
  1139. {
  1140. int n_ci = IDR_CI0 - n_CPU;
  1141. DPRINTF("%s: cpu:%d irq:%d (testbit idr:%x ci:%d)\n", __func__,
  1142. n_CPU, n_IRQ, mpp->src[n_IRQ].ide, n_ci);
  1143. if(test_bit(&src->ide, n_ci)) {
  1144. qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
  1145. }
  1146. else {
  1147. qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
  1148. }
  1149. }
  1150. static void mpic_reset (void *opaque)
  1151. {
  1152. openpic_t *mpp = (openpic_t *)opaque;
  1153. int i;
  1154. mpp->glbc = 0x80000000;
  1155. /* Initialise controller registers */
  1156. mpp->frep = 0x004f0002;
  1157. mpp->veni = VENI;
  1158. mpp->pint = 0x00000000;
  1159. mpp->spve = 0x0000FFFF;
  1160. /* Initialise IRQ sources */
  1161. for (i = 0; i < mpp->max_irq; i++) {
  1162. mpp->src[i].ipvp = 0x80800000;
  1163. mpp->src[i].ide = 0x00000001;
  1164. }
  1165. /* Initialise IRQ destinations */
  1166. for (i = 0; i < MAX_CPU; i++) {
  1167. mpp->dst[i].pctp = 0x0000000F;
  1168. mpp->dst[i].tfrr = 0x00000000;
  1169. memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
  1170. mpp->dst[i].raised.next = -1;
  1171. memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
  1172. mpp->dst[i].servicing.next = -1;
  1173. }
  1174. /* Initialise timers */
  1175. for (i = 0; i < MAX_TMR; i++) {
  1176. mpp->timers[i].ticc = 0x00000000;
  1177. mpp->timers[i].tibc = 0x80000000;
  1178. }
  1179. /* Go out of RESET state */
  1180. mpp->glbc = 0x00000000;
  1181. }
  1182. static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val)
  1183. {
  1184. openpic_t *mpp = opaque;
  1185. int idx, cpu;
  1186. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  1187. if (addr & 0xF)
  1188. return;
  1189. addr &= 0xFFFF;
  1190. cpu = addr >> 12;
  1191. idx = (addr >> 6) & 0x3;
  1192. switch (addr & 0x30) {
  1193. case 0x00: /* gtccr */
  1194. break;
  1195. case 0x10: /* gtbcr */
  1196. if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
  1197. (val & 0x80000000) == 0 &&
  1198. (mpp->timers[idx].tibc & 0x80000000) != 0)
  1199. mpp->timers[idx].ticc &= ~0x80000000;
  1200. mpp->timers[idx].tibc = val;
  1201. break;
  1202. case 0x20: /* GTIVPR */
  1203. write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP, val);
  1204. break;
  1205. case 0x30: /* GTIDR & TFRR */
  1206. if ((addr & 0xF0) == 0xF0)
  1207. mpp->dst[cpu].tfrr = val;
  1208. else
  1209. write_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE, val);
  1210. break;
  1211. }
  1212. }
  1213. static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
  1214. {
  1215. openpic_t *mpp = opaque;
  1216. uint32_t retval;
  1217. int idx, cpu;
  1218. DPRINTF("%s: addr %08x\n", __func__, addr);
  1219. retval = 0xFFFFFFFF;
  1220. if (addr & 0xF)
  1221. return retval;
  1222. addr &= 0xFFFF;
  1223. cpu = addr >> 12;
  1224. idx = (addr >> 6) & 0x3;
  1225. switch (addr & 0x30) {
  1226. case 0x00: /* gtccr */
  1227. retval = mpp->timers[idx].ticc;
  1228. break;
  1229. case 0x10: /* gtbcr */
  1230. retval = mpp->timers[idx].tibc;
  1231. break;
  1232. case 0x20: /* TIPV */
  1233. retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IPVP);
  1234. break;
  1235. case 0x30: /* TIDR */
  1236. if ((addr &0xF0) == 0XF0)
  1237. retval = mpp->dst[cpu].tfrr;
  1238. else
  1239. retval = read_IRQreg(mpp, MPIC_TMR_IRQ + idx, IRQ_IDE);
  1240. break;
  1241. }
  1242. DPRINTF("%s: => %08x\n", __func__, retval);
  1243. return retval;
  1244. }
  1245. static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
  1246. uint32_t val)
  1247. {
  1248. openpic_t *mpp = opaque;
  1249. int idx = MPIC_EXT_IRQ;
  1250. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  1251. if (addr & 0xF)
  1252. return;
  1253. addr -= MPIC_EXT_REG_START & (TARGET_PAGE_SIZE - 1);
  1254. if (addr < MPIC_EXT_REG_SIZE) {
  1255. idx += (addr & 0xFFF0) >> 5;
  1256. if (addr & 0x10) {
  1257. /* EXDE / IFEDE / IEEDE */
  1258. write_IRQreg(mpp, idx, IRQ_IDE, val);
  1259. } else {
  1260. /* EXVP / IFEVP / IEEVP */
  1261. write_IRQreg(mpp, idx, IRQ_IPVP, val);
  1262. }
  1263. }
  1264. }
  1265. static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
  1266. {
  1267. openpic_t *mpp = opaque;
  1268. uint32_t retval;
  1269. int idx = MPIC_EXT_IRQ;
  1270. DPRINTF("%s: addr %08x\n", __func__, addr);
  1271. retval = 0xFFFFFFFF;
  1272. if (addr & 0xF)
  1273. return retval;
  1274. addr -= MPIC_EXT_REG_START & (TARGET_PAGE_SIZE - 1);
  1275. if (addr < MPIC_EXT_REG_SIZE) {
  1276. idx += (addr & 0xFFF0) >> 5;
  1277. if (addr & 0x10) {
  1278. /* EXDE / IFEDE / IEEDE */
  1279. retval = read_IRQreg(mpp, idx, IRQ_IDE);
  1280. } else {
  1281. /* EXVP / IFEVP / IEEVP */
  1282. retval = read_IRQreg(mpp, idx, IRQ_IPVP);
  1283. }
  1284. DPRINTF("%s: => %08x\n", __func__, retval);
  1285. }
  1286. return retval;
  1287. }
  1288. static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
  1289. uint32_t val)
  1290. {
  1291. openpic_t *mpp = opaque;
  1292. int idx = MPIC_INT_IRQ;
  1293. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  1294. if (addr & 0xF)
  1295. return;
  1296. addr -= MPIC_INT_REG_START & (TARGET_PAGE_SIZE - 1);
  1297. if (addr < MPIC_INT_REG_SIZE) {
  1298. idx += (addr & 0xFFF0) >> 5;
  1299. if (addr & 0x10) {
  1300. /* EXDE / IFEDE / IEEDE */
  1301. write_IRQreg(mpp, idx, IRQ_IDE, val);
  1302. } else {
  1303. /* EXVP / IFEVP / IEEVP */
  1304. write_IRQreg(mpp, idx, IRQ_IPVP, val);
  1305. }
  1306. }
  1307. }
  1308. static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
  1309. {
  1310. openpic_t *mpp = opaque;
  1311. uint32_t retval;
  1312. int idx = MPIC_INT_IRQ;
  1313. DPRINTF("%s: addr %08x\n", __func__, addr);
  1314. retval = 0xFFFFFFFF;
  1315. if (addr & 0xF)
  1316. return retval;
  1317. addr -= MPIC_INT_REG_START & (TARGET_PAGE_SIZE - 1);
  1318. if (addr < MPIC_INT_REG_SIZE) {
  1319. idx += (addr & 0xFFF0) >> 5;
  1320. if (addr & 0x10) {
  1321. /* EXDE / IFEDE / IEEDE */
  1322. retval = read_IRQreg(mpp, idx, IRQ_IDE);
  1323. } else {
  1324. /* EXVP / IFEVP / IEEVP */
  1325. retval = read_IRQreg(mpp, idx, IRQ_IPVP);
  1326. }
  1327. DPRINTF("%s: => %08x\n", __func__, retval);
  1328. }
  1329. return retval;
  1330. }
  1331. static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
  1332. uint32_t val)
  1333. {
  1334. openpic_t *mpp = opaque;
  1335. int idx = MPIC_MSG_IRQ;
  1336. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  1337. if (addr & 0xF)
  1338. return;
  1339. addr -= MPIC_MSG_REG_START & (TARGET_PAGE_SIZE - 1);
  1340. if (addr < MPIC_MSG_REG_SIZE) {
  1341. idx += (addr & 0xFFF0) >> 5;
  1342. if (addr & 0x10) {
  1343. /* EXDE / IFEDE / IEEDE */
  1344. write_IRQreg(mpp, idx, IRQ_IDE, val);
  1345. } else {
  1346. /* EXVP / IFEVP / IEEVP */
  1347. write_IRQreg(mpp, idx, IRQ_IPVP, val);
  1348. }
  1349. }
  1350. }
  1351. static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
  1352. {
  1353. openpic_t *mpp = opaque;
  1354. uint32_t retval;
  1355. int idx = MPIC_MSG_IRQ;
  1356. DPRINTF("%s: addr %08x\n", __func__, addr);
  1357. retval = 0xFFFFFFFF;
  1358. if (addr & 0xF)
  1359. return retval;
  1360. addr -= MPIC_MSG_REG_START & (TARGET_PAGE_SIZE - 1);
  1361. if (addr < MPIC_MSG_REG_SIZE) {
  1362. idx += (addr & 0xFFF0) >> 5;
  1363. if (addr & 0x10) {
  1364. /* EXDE / IFEDE / IEEDE */
  1365. retval = read_IRQreg(mpp, idx, IRQ_IDE);
  1366. } else {
  1367. /* EXVP / IFEVP / IEEVP */
  1368. retval = read_IRQreg(mpp, idx, IRQ_IPVP);
  1369. }
  1370. DPRINTF("%s: => %08x\n", __func__, retval);
  1371. }
  1372. return retval;
  1373. }
  1374. static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
  1375. uint32_t val)
  1376. {
  1377. openpic_t *mpp = opaque;
  1378. int idx = MPIC_MSI_IRQ;
  1379. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  1380. if (addr & 0xF)
  1381. return;
  1382. addr -= MPIC_MSI_REG_START & (TARGET_PAGE_SIZE - 1);
  1383. if (addr < MPIC_MSI_REG_SIZE) {
  1384. idx += (addr & 0xFFF0) >> 5;
  1385. if (addr & 0x10) {
  1386. /* EXDE / IFEDE / IEEDE */
  1387. write_IRQreg(mpp, idx, IRQ_IDE, val);
  1388. } else {
  1389. /* EXVP / IFEVP / IEEVP */
  1390. write_IRQreg(mpp, idx, IRQ_IPVP, val);
  1391. }
  1392. }
  1393. }
  1394. static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
  1395. {
  1396. openpic_t *mpp = opaque;
  1397. uint32_t retval;
  1398. int idx = MPIC_MSI_IRQ;
  1399. DPRINTF("%s: addr %08x\n", __func__, addr);
  1400. retval = 0xFFFFFFFF;
  1401. if (addr & 0xF)
  1402. return retval;
  1403. addr -= MPIC_MSI_REG_START & (TARGET_PAGE_SIZE - 1);
  1404. if (addr < MPIC_MSI_REG_SIZE) {
  1405. idx += (addr & 0xFFF0) >> 5;
  1406. if (addr & 0x10) {
  1407. /* EXDE / IFEDE / IEEDE */
  1408. retval = read_IRQreg(mpp, idx, IRQ_IDE);
  1409. } else {
  1410. /* EXVP / IFEVP / IEEVP */
  1411. retval = read_IRQreg(mpp, idx, IRQ_IPVP);
  1412. }
  1413. DPRINTF("%s: => %08x\n", __func__, retval);
  1414. }
  1415. return retval;
  1416. }
  1417. static CPUWriteMemoryFunc *mpic_glb_write[] = {
  1418. &openpic_buggy_write,
  1419. &openpic_buggy_write,
  1420. &openpic_gbl_write,
  1421. };
  1422. static CPUReadMemoryFunc *mpic_glb_read[] = {
  1423. &openpic_buggy_read,
  1424. &openpic_buggy_read,
  1425. &openpic_gbl_read,
  1426. };
  1427. static CPUWriteMemoryFunc *mpic_tmr_write[] = {
  1428. &openpic_buggy_write,
  1429. &openpic_buggy_write,
  1430. &mpic_timer_write,
  1431. };
  1432. static CPUReadMemoryFunc *mpic_tmr_read[] = {
  1433. &openpic_buggy_read,
  1434. &openpic_buggy_read,
  1435. &mpic_timer_read,
  1436. };
  1437. static CPUWriteMemoryFunc *mpic_cpu_write[] = {
  1438. &openpic_buggy_write,
  1439. &openpic_buggy_write,
  1440. &openpic_cpu_write,
  1441. };
  1442. static CPUReadMemoryFunc *mpic_cpu_read[] = {
  1443. &openpic_buggy_read,
  1444. &openpic_buggy_read,
  1445. &openpic_cpu_read,
  1446. };
  1447. static CPUWriteMemoryFunc *mpic_ext_write[] = {
  1448. &openpic_buggy_write,
  1449. &openpic_buggy_write,
  1450. &mpic_src_ext_write,
  1451. };
  1452. static CPUReadMemoryFunc *mpic_ext_read[] = {
  1453. &openpic_buggy_read,
  1454. &openpic_buggy_read,
  1455. &mpic_src_ext_read,
  1456. };
  1457. static CPUWriteMemoryFunc *mpic_int_write[] = {
  1458. &openpic_buggy_write,
  1459. &openpic_buggy_write,
  1460. &mpic_src_int_write,
  1461. };
  1462. static CPUReadMemoryFunc *mpic_int_read[] = {
  1463. &openpic_buggy_read,
  1464. &openpic_buggy_read,
  1465. &mpic_src_int_read,
  1466. };
  1467. static CPUWriteMemoryFunc *mpic_msg_write[] = {
  1468. &openpic_buggy_write,
  1469. &openpic_buggy_write,
  1470. &mpic_src_msg_write,
  1471. };
  1472. static CPUReadMemoryFunc *mpic_msg_read[] = {
  1473. &openpic_buggy_read,
  1474. &openpic_buggy_read,
  1475. &mpic_src_msg_read,
  1476. };
  1477. static CPUWriteMemoryFunc *mpic_msi_write[] = {
  1478. &openpic_buggy_write,
  1479. &openpic_buggy_write,
  1480. &mpic_src_msi_write,
  1481. };
  1482. static CPUReadMemoryFunc *mpic_msi_read[] = {
  1483. &openpic_buggy_read,
  1484. &openpic_buggy_read,
  1485. &mpic_src_msi_read,
  1486. };
  1487. qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
  1488. qemu_irq **irqs, qemu_irq irq_out)
  1489. {
  1490. openpic_t *mpp;
  1491. int i;
  1492. struct {
  1493. CPUReadMemoryFunc **read;
  1494. CPUWriteMemoryFunc **write;
  1495. target_phys_addr_t start_addr;
  1496. ram_addr_t size;
  1497. } const list[] = {
  1498. {mpic_glb_read, mpic_glb_write, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
  1499. {mpic_tmr_read, mpic_tmr_write, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
  1500. {mpic_ext_read, mpic_ext_write, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
  1501. {mpic_int_read, mpic_int_write, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
  1502. {mpic_msg_read, mpic_msg_write, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
  1503. {mpic_msi_read, mpic_msi_write, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
  1504. {mpic_cpu_read, mpic_cpu_write, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
  1505. };
  1506. /* XXX: for now, only one CPU is supported */
  1507. if (nb_cpus != 1)
  1508. return NULL;
  1509. mpp = qemu_mallocz(sizeof(openpic_t));
  1510. for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
  1511. int mem_index;
  1512. mem_index = cpu_register_io_memory(0, list[i].read, list[i].write, mpp);
  1513. if (mem_index < 0) {
  1514. goto free;
  1515. }
  1516. cpu_register_physical_memory(base + list[i].start_addr,
  1517. list[i].size, mem_index);
  1518. }
  1519. mpp->nb_cpus = nb_cpus;
  1520. mpp->max_irq = MPIC_MAX_IRQ;
  1521. mpp->irq_ipi0 = MPIC_IPI_IRQ;
  1522. mpp->irq_tim0 = MPIC_TMR_IRQ;
  1523. for (i = 0; i < nb_cpus; i++)
  1524. mpp->dst[i].irqs = irqs[i];
  1525. mpp->irq_out = irq_out;
  1526. mpp->need_swap = 0; /* MPIC has the same endian as target */
  1527. mpp->irq_raise = mpic_irq_raise;
  1528. mpp->reset = mpic_reset;
  1529. register_savevm("mpic", 0, 2, openpic_save, openpic_load, mpp);
  1530. qemu_register_reset(mpic_reset, mpp);
  1531. mpp->reset(mpp);
  1532. return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
  1533. free:
  1534. qemu_free(mpp);
  1535. return NULL;
  1536. }