device.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998
  1. /* This file is part of the program psim.
  2. Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #ifndef _DEVICE_C_
  15. #define _DEVICE_C_
  16. #include <stdio.h>
  17. #include "device_table.h"
  18. #include "cap.h"
  19. #include "events.h"
  20. #include "psim.h"
  21. #ifdef HAVE_STDLIB_H
  22. #include <stdlib.h>
  23. #endif
  24. #ifdef HAVE_STRING_H
  25. #include <string.h>
  26. #else
  27. #ifdef HAVE_STRINGS_H
  28. #include <strings.h>
  29. #endif
  30. #endif
  31. #include <ctype.h>
  32. STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
  33. /* property entries */
  34. typedef struct _device_property_entry device_property_entry;
  35. struct _device_property_entry {
  36. device_property_entry *next;
  37. device_property *value;
  38. const void *init_array;
  39. unsigned sizeof_init_array;
  40. };
  41. /* Interrupt edges */
  42. typedef struct _device_interrupt_edge device_interrupt_edge;
  43. struct _device_interrupt_edge {
  44. int my_port;
  45. device *dest;
  46. int dest_port;
  47. device_interrupt_edge *next;
  48. object_disposition disposition;
  49. };
  50. STATIC_INLINE_DEVICE\
  51. (void)
  52. attach_device_interrupt_edge(device_interrupt_edge **list,
  53. int my_port,
  54. device *dest,
  55. int dest_port,
  56. object_disposition disposition)
  57. {
  58. device_interrupt_edge *new_edge = ZALLOC(device_interrupt_edge);
  59. new_edge->my_port = my_port;
  60. new_edge->dest = dest;
  61. new_edge->dest_port = dest_port;
  62. new_edge->next = *list;
  63. new_edge->disposition = disposition;
  64. *list = new_edge;
  65. }
  66. STATIC_INLINE_DEVICE\
  67. (void)
  68. detach_device_interrupt_edge(device *me,
  69. device_interrupt_edge **list,
  70. int my_port,
  71. device *dest,
  72. int dest_port)
  73. {
  74. while (*list != NULL) {
  75. device_interrupt_edge *old_edge = *list;
  76. if (old_edge->dest == dest
  77. && old_edge->dest_port == dest_port
  78. && old_edge->my_port == my_port) {
  79. if (old_edge->disposition == permenant_object)
  80. device_error(me, "attempt to delete permenant interrupt");
  81. *list = old_edge->next;
  82. free(old_edge);
  83. return;
  84. }
  85. }
  86. device_error(me, "attempt to delete unattached interrupt");
  87. }
  88. STATIC_INLINE_DEVICE\
  89. (void)
  90. clean_device_interrupt_edges(device_interrupt_edge **list)
  91. {
  92. while (*list != NULL) {
  93. device_interrupt_edge *old_edge = *list;
  94. switch (old_edge->disposition) {
  95. case permenant_object:
  96. list = &old_edge->next;
  97. break;
  98. case tempoary_object:
  99. *list = old_edge->next;
  100. free(old_edge);
  101. break;
  102. }
  103. }
  104. }
  105. /* A device */
  106. struct _device {
  107. /* my name is ... */
  108. const char *name;
  109. device_unit unit_address;
  110. const char *path;
  111. int nr_address_cells;
  112. int nr_size_cells;
  113. /* device tree */
  114. device *parent;
  115. device *children;
  116. device *sibling;
  117. /* its template methods */
  118. void *data; /* device specific data */
  119. const device_callbacks *callback;
  120. /* device properties */
  121. device_property_entry *properties;
  122. /* interrupts */
  123. device_interrupt_edge *interrupt_destinations;
  124. /* any open instances of this device */
  125. device_instance *instances;
  126. /* the internal/external mappings and other global requirements */
  127. cap *ihandles;
  128. cap *phandles;
  129. psim *system;
  130. /* debugging */
  131. int trace;
  132. };
  133. /* an instance of a device */
  134. struct _device_instance {
  135. void *data;
  136. char *args;
  137. char *path;
  138. const device_instance_callbacks *callback;
  139. /* the root instance */
  140. device *owner;
  141. device_instance *next;
  142. /* interposed instance */
  143. device_instance *parent;
  144. device_instance *child;
  145. };
  146. /* creation */
  147. STATIC_INLINE_DEVICE\
  148. (const char *)
  149. device_full_name(device *leaf,
  150. char *buf,
  151. unsigned sizeof_buf)
  152. {
  153. /* get a buffer */
  154. char full_name[1024];
  155. if (buf == (char*)0) {
  156. buf = full_name;
  157. sizeof_buf = sizeof(full_name);
  158. }
  159. /* construct a name */
  160. if (leaf->parent == NULL) {
  161. if (sizeof_buf < 1)
  162. error("device_full_name: buffer overflow");
  163. *buf = '\0';
  164. }
  165. else {
  166. char unit[1024];
  167. device_full_name(leaf->parent, buf, sizeof_buf);
  168. if (leaf->parent != NULL
  169. && device_encode_unit(leaf->parent,
  170. &leaf->unit_address,
  171. unit+1,
  172. sizeof(unit)-1) > 0)
  173. unit[0] = '@';
  174. else
  175. unit[0] = '\0';
  176. if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit)
  177. >= sizeof_buf)
  178. error("device_full_name: buffer overflow");
  179. strcat(buf, "/");
  180. strcat(buf, leaf->name);
  181. strcat (buf, unit);
  182. }
  183. /* return it usefully */
  184. if (buf == full_name)
  185. buf = (char *) strdup(full_name);
  186. return buf;
  187. }
  188. STATIC_INLINE_DEVICE\
  189. (device *)
  190. device_create_from(const char *name,
  191. const device_unit *unit_address,
  192. void *data,
  193. const device_callbacks *callbacks,
  194. device *parent)
  195. {
  196. device *new_device = ZALLOC(device);
  197. /* insert it into the device tree */
  198. new_device->parent = parent;
  199. new_device->children = NULL;
  200. if (parent != NULL) {
  201. device **sibling = &parent->children;
  202. while ((*sibling) != NULL)
  203. sibling = &(*sibling)->sibling;
  204. *sibling = new_device;
  205. }
  206. /* give it a name */
  207. new_device->name = (char *) strdup(name);
  208. new_device->unit_address = *unit_address;
  209. new_device->path = device_full_name(new_device, NULL, 0);
  210. /* its template */
  211. new_device->data = data;
  212. new_device->callback = callbacks;
  213. /* its properties - already null */
  214. /* interrupts - already null */
  215. /* mappings - if needed */
  216. if (parent == NULL) {
  217. new_device->ihandles = cap_create(name);
  218. new_device->phandles = cap_create(name);
  219. }
  220. else {
  221. new_device->ihandles = device_root(parent)->ihandles;
  222. new_device->phandles = device_root(parent)->phandles;
  223. }
  224. cap_add(new_device->phandles, new_device);
  225. return new_device;
  226. }
  227. INLINE_DEVICE\
  228. (device *)
  229. device_create(device *parent,
  230. const char *base,
  231. const char *name,
  232. const char *unit_address,
  233. const char *args)
  234. {
  235. const device_descriptor *const *table;
  236. for (table = device_table; *table != NULL; table++) {
  237. const device_descriptor *descr;
  238. for (descr = *table; descr->name != NULL; descr++) {
  239. if (strcmp(base, descr->name) == 0) {
  240. device_unit address = { 0 };
  241. void *data = NULL;
  242. if (parent != NULL)
  243. if (device_decode_unit(parent, unit_address, &address) < 0)
  244. device_error(parent, "invalid address %s for device %s",
  245. unit_address, name);
  246. if (descr->creator != NULL)
  247. data = descr->creator(name, &address, args);
  248. return device_create_from(name, &address, data,
  249. descr->callbacks, parent);
  250. }
  251. }
  252. }
  253. device_error(parent, "attempt to attach unknown device %s", name);
  254. return NULL;
  255. }
  256. INLINE_DEVICE\
  257. (void)
  258. device_usage(int verbose)
  259. {
  260. const device_descriptor *const *table;
  261. if (verbose == 1) {
  262. int pos = 0;
  263. for (table = device_table; *table != NULL; table++) {
  264. const device_descriptor *descr;
  265. for (descr = *table; descr->name != NULL; descr++) {
  266. pos += strlen(descr->name) + 2;
  267. if (pos > 75) {
  268. pos = strlen(descr->name) + 2;
  269. printf_filtered("\n");
  270. }
  271. printf_filtered(" %s", descr->name);
  272. }
  273. printf_filtered("\n");
  274. }
  275. }
  276. if (verbose > 1) {
  277. for (table = device_table; *table != NULL; table++) {
  278. const device_descriptor *descr;
  279. for (descr = *table; descr->name != NULL; descr++) {
  280. printf_filtered(" %s:\n", descr->name);
  281. /* interrupt ports */
  282. if (descr->callbacks->interrupt.ports != NULL) {
  283. const device_interrupt_port_descriptor *ports =
  284. descr->callbacks->interrupt.ports;
  285. printf_filtered(" interrupt ports:");
  286. while (ports->name != NULL) {
  287. printf_filtered(" %s", ports->name);
  288. ports++;
  289. }
  290. printf_filtered("\n");
  291. }
  292. /* general info */
  293. if (descr->callbacks->usage != NULL)
  294. descr->callbacks->usage(verbose);
  295. }
  296. }
  297. }
  298. }
  299. /* Device node: */
  300. INLINE_DEVICE\
  301. (device *)
  302. device_parent(device *me)
  303. {
  304. return me->parent;
  305. }
  306. INLINE_DEVICE\
  307. (device *)
  308. device_root(device *me)
  309. {
  310. ASSERT(me != NULL);
  311. while (me->parent != NULL)
  312. me = me->parent;
  313. return me;
  314. }
  315. INLINE_DEVICE\
  316. (device *)
  317. device_sibling(device *me)
  318. {
  319. return me->sibling;
  320. }
  321. INLINE_DEVICE\
  322. (device *)
  323. device_child(device *me)
  324. {
  325. return me->children;
  326. }
  327. INLINE_DEVICE\
  328. (const char *)
  329. device_name(device *me)
  330. {
  331. return me->name;
  332. }
  333. INLINE_DEVICE\
  334. (const char *)
  335. device_path(device *me)
  336. {
  337. return me->path;
  338. }
  339. INLINE_DEVICE\
  340. (void *)
  341. device_data(device *me)
  342. {
  343. return me->data;
  344. }
  345. INLINE_DEVICE\
  346. (psim *)
  347. device_system(device *me)
  348. {
  349. return me->system;
  350. }
  351. INLINE_DEVICE\
  352. (const device_unit *)
  353. device_unit_address(device *me)
  354. {
  355. return &me->unit_address;
  356. }
  357. INLINE_DEVICE\
  358. (int)
  359. device_address_to_attach_address(device *me,
  360. const device_unit *address,
  361. int *attach_space,
  362. unsigned_word *attach_address,
  363. device *client)
  364. {
  365. if (me->callback->convert.address_to_attach_address == NULL)
  366. device_error(me, "no convert.address_to_attach_address method");
  367. return me->callback->convert.address_to_attach_address(me, address, attach_space, attach_address, client);
  368. }
  369. INLINE_DEVICE\
  370. (int)
  371. device_size_to_attach_size(device *me,
  372. const device_unit *size,
  373. unsigned *nr_bytes,
  374. device *client)
  375. {
  376. if (me->callback->convert.size_to_attach_size == NULL)
  377. device_error(me, "no convert.size_to_attach_size method");
  378. return me->callback->convert.size_to_attach_size(me, size, nr_bytes, client);
  379. }
  380. INLINE_DEVICE\
  381. (int)
  382. device_decode_unit(device *bus,
  383. const char *unit,
  384. device_unit *address)
  385. {
  386. if (bus->callback->convert.decode_unit == NULL)
  387. device_error(bus, "no convert.decode_unit method");
  388. return bus->callback->convert.decode_unit(bus, unit, address);
  389. }
  390. INLINE_DEVICE\
  391. (int)
  392. device_encode_unit(device *bus,
  393. const device_unit *unit_address,
  394. char *buf,
  395. int sizeof_buf)
  396. {
  397. if (bus->callback->convert.encode_unit == NULL)
  398. device_error(bus, "no convert.encode_unit method");
  399. return bus->callback->convert.encode_unit(bus, unit_address, buf, sizeof_buf);
  400. }
  401. INLINE_DEVICE\
  402. (unsigned)
  403. device_nr_address_cells(device *me)
  404. {
  405. if (me->nr_address_cells == 0) {
  406. if (device_find_property(me, "#address-cells") != NULL)
  407. me->nr_address_cells = device_find_integer_property(me, "#address-cells");
  408. else
  409. me->nr_address_cells = 2;
  410. }
  411. return me->nr_address_cells;
  412. }
  413. INLINE_DEVICE\
  414. (unsigned)
  415. device_nr_size_cells(device *me)
  416. {
  417. if (me->nr_size_cells == 0) {
  418. if (device_find_property(me, "#size-cells") != NULL)
  419. me->nr_size_cells = device_find_integer_property(me, "#size-cells");
  420. else
  421. me->nr_size_cells = 1;
  422. }
  423. return me->nr_size_cells;
  424. }
  425. /* device-instance: */
  426. INLINE_DEVICE\
  427. (device_instance *)
  428. device_create_instance_from(device *me,
  429. device_instance *parent,
  430. void *data,
  431. const char *path,
  432. const char *args,
  433. const device_instance_callbacks *callbacks)
  434. {
  435. device_instance *instance = ZALLOC(device_instance);
  436. if ((me == NULL) == (parent == NULL))
  437. device_error(me, "can't have both parent instance and parent device");
  438. /*instance->unit*/
  439. /* link this instance into the devices list */
  440. if (me != NULL) {
  441. ASSERT(parent == NULL);
  442. instance->owner = me;
  443. instance->parent = NULL;
  444. /* link this instance into the front of the devices instance list */
  445. instance->next = me->instances;
  446. me->instances = instance;
  447. }
  448. if (parent != NULL) {
  449. device_instance **previous;
  450. ASSERT(parent->child == NULL);
  451. parent->child = instance;
  452. ASSERT(me == NULL);
  453. instance->owner = parent->owner;
  454. instance->parent = parent;
  455. /* in the devices instance list replace the parent instance with
  456. this one */
  457. instance->next = parent->next;
  458. /* replace parent with this new node */
  459. previous = &instance->owner->instances;
  460. while (*previous != parent) {
  461. ASSERT(*previous != NULL);
  462. previous = &(*previous)->next;
  463. }
  464. *previous = instance;
  465. }
  466. instance->data = data;
  467. instance->args = (args == NULL ? NULL : (char *) strdup(args));
  468. instance->path = (path == NULL ? NULL : (char *) strdup(path));
  469. instance->callback = callbacks;
  470. cap_add(instance->owner->ihandles, instance);
  471. return instance;
  472. }
  473. INLINE_DEVICE\
  474. (device_instance *)
  475. device_create_instance(device *me,
  476. const char *path,
  477. const char *args)
  478. {
  479. /* create the instance */
  480. if (me->callback->instance_create == NULL)
  481. device_error(me, "no instance_create method");
  482. return me->callback->instance_create(me, path, args);
  483. }
  484. STATIC_INLINE_DEVICE\
  485. (void)
  486. clean_device_instances(device *me)
  487. {
  488. device_instance **instance = &me->instances;
  489. while (*instance != NULL) {
  490. device_instance *old_instance = *instance;
  491. device_instance_delete(old_instance);
  492. instance = &me->instances;
  493. }
  494. }
  495. INLINE_DEVICE\
  496. (void)
  497. device_instance_delete(device_instance *instance)
  498. {
  499. device *me = instance->owner;
  500. if (instance->callback->delete == NULL)
  501. device_error(me, "no delete method");
  502. instance->callback->delete(instance);
  503. if (instance->args != NULL)
  504. free(instance->args);
  505. if (instance->path != NULL)
  506. free(instance->path);
  507. if (instance->child == NULL) {
  508. /* only remove leaf nodes */
  509. device_instance **curr = &me->instances;
  510. while (*curr != instance) {
  511. ASSERT(*curr != NULL);
  512. curr = &(*curr)->next;
  513. }
  514. *curr = instance->next;
  515. }
  516. else {
  517. /* check it isn't in the instance list */
  518. device_instance *curr = me->instances;
  519. while (curr != NULL) {
  520. ASSERT(curr != instance);
  521. curr = curr->next;
  522. }
  523. /* unlink the child */
  524. ASSERT(instance->child->parent == instance);
  525. instance->child->parent = NULL;
  526. }
  527. cap_remove(me->ihandles, instance);
  528. free(instance);
  529. }
  530. INLINE_DEVICE\
  531. (int)
  532. device_instance_read(device_instance *instance,
  533. void *addr,
  534. unsigned_word len)
  535. {
  536. device *me = instance->owner;
  537. if (instance->callback->read == NULL)
  538. device_error(me, "no read method");
  539. return instance->callback->read(instance, addr, len);
  540. }
  541. INLINE_DEVICE\
  542. (int)
  543. device_instance_write(device_instance *instance,
  544. const void *addr,
  545. unsigned_word len)
  546. {
  547. device *me = instance->owner;
  548. if (instance->callback->write == NULL)
  549. device_error(me, "no write method");
  550. return instance->callback->write(instance, addr, len);
  551. }
  552. INLINE_DEVICE\
  553. (int)
  554. device_instance_seek(device_instance *instance,
  555. unsigned_word pos_hi,
  556. unsigned_word pos_lo)
  557. {
  558. device *me = instance->owner;
  559. if (instance->callback->seek == NULL)
  560. device_error(me, "no seek method");
  561. return instance->callback->seek(instance, pos_hi, pos_lo);
  562. }
  563. INLINE_DEVICE\
  564. (int)
  565. device_instance_call_method(device_instance *instance,
  566. const char *method_name,
  567. int n_stack_args,
  568. unsigned_cell stack_args[/*n_stack_args*/],
  569. int n_stack_returns,
  570. unsigned_cell stack_returns[/*n_stack_args*/])
  571. {
  572. device *me = instance->owner;
  573. const device_instance_methods *method = instance->callback->methods;
  574. if (method == NULL) {
  575. device_error(me, "no methods (want %s)", method_name);
  576. }
  577. while (method->name != NULL) {
  578. if (strcmp(method->name, method_name) == 0) {
  579. return method->method(instance,
  580. n_stack_args, stack_args,
  581. n_stack_returns, stack_returns);
  582. }
  583. method++;
  584. }
  585. device_error(me, "no %s method", method_name);
  586. return 0;
  587. }
  588. INLINE_DEVICE\
  589. (device *)
  590. device_instance_device(device_instance *instance)
  591. {
  592. return instance->owner;
  593. }
  594. INLINE_DEVICE\
  595. (const char *)
  596. device_instance_path(device_instance *instance)
  597. {
  598. return instance->path;
  599. }
  600. INLINE_DEVICE\
  601. (void *)
  602. device_instance_data(device_instance *instance)
  603. {
  604. return instance->data;
  605. }
  606. /* Device Properties: */
  607. STATIC_INLINE_DEVICE\
  608. (device_property_entry *)
  609. find_property_entry(device *me,
  610. const char *property)
  611. {
  612. device_property_entry *entry;
  613. ASSERT(property != NULL);
  614. entry = me->properties;
  615. while (entry != NULL) {
  616. if (strcmp(entry->value->name, property) == 0)
  617. return entry;
  618. entry = entry->next;
  619. }
  620. return NULL;
  621. }
  622. STATIC_INLINE_DEVICE\
  623. (void)
  624. device_add_property(device *me,
  625. const char *property,
  626. device_property_type type,
  627. const void *init_array,
  628. unsigned sizeof_init_array,
  629. const void *array,
  630. unsigned sizeof_array,
  631. const device_property *original,
  632. object_disposition disposition)
  633. {
  634. device_property_entry *new_entry = NULL;
  635. device_property *new_value = NULL;
  636. /* find the list end */
  637. device_property_entry **insertion_point = &me->properties;
  638. while (*insertion_point != NULL) {
  639. if (strcmp((*insertion_point)->value->name, property) == 0)
  640. return;
  641. insertion_point = &(*insertion_point)->next;
  642. }
  643. /* create a new value */
  644. new_value = ZALLOC(device_property);
  645. new_value->name = (char *) strdup(property);
  646. new_value->type = type;
  647. if (sizeof_array > 0) {
  648. void *new_array = zalloc(sizeof_array);
  649. memcpy(new_array, array, sizeof_array);
  650. new_value->array = new_array;
  651. new_value->sizeof_array = sizeof_array;
  652. }
  653. new_value->owner = me;
  654. new_value->original = original;
  655. new_value->disposition = disposition;
  656. /* insert the value into the list */
  657. new_entry = ZALLOC(device_property_entry);
  658. *insertion_point = new_entry;
  659. if (sizeof_init_array > 0) {
  660. void *new_init_array = zalloc(sizeof_init_array);
  661. memcpy(new_init_array, init_array, sizeof_init_array);
  662. new_entry->init_array = new_init_array;
  663. new_entry->sizeof_init_array = sizeof_init_array;
  664. }
  665. new_entry->value = new_value;
  666. }
  667. /* local - not available externally */
  668. STATIC_INLINE_DEVICE\
  669. (void)
  670. device_set_property(device *me,
  671. const char *property,
  672. device_property_type type,
  673. const void *array,
  674. int sizeof_array)
  675. {
  676. /* find the property */
  677. device_property_entry *entry = find_property_entry(me, property);
  678. if (entry != NULL) {
  679. /* existing property - update it */
  680. void *new_array = 0;
  681. device_property *value = entry->value;
  682. /* check the type matches */
  683. if (value->type != type)
  684. device_error(me, "conflict between type of new and old value for property %s", property);
  685. /* replace its value */
  686. if (value->array != NULL)
  687. free((void*)value->array);
  688. new_array = (sizeof_array > 0
  689. ? zalloc(sizeof_array)
  690. : (void*)0);
  691. value->array = new_array;
  692. value->sizeof_array = sizeof_array;
  693. if (sizeof_array > 0)
  694. memcpy(new_array, array, sizeof_array);
  695. return;
  696. }
  697. else {
  698. /* new property - create it */
  699. device_add_property(me, property, type,
  700. NULL, 0, array, sizeof_array,
  701. NULL, tempoary_object);
  702. }
  703. }
  704. STATIC_INLINE_DEVICE\
  705. (void)
  706. clean_device_properties(device *me)
  707. {
  708. device_property_entry **delete_point = &me->properties;
  709. while (*delete_point != NULL) {
  710. device_property_entry *current = *delete_point;
  711. switch (current->value->disposition) {
  712. case permenant_object:
  713. /* zap the current value, will be initialized later */
  714. ASSERT(current->init_array != NULL);
  715. if (current->value->array != NULL) {
  716. free((void*)current->value->array);
  717. current->value->array = NULL;
  718. }
  719. delete_point = &(*delete_point)->next;
  720. break;
  721. case tempoary_object:
  722. /* zap the actual property, was created during simulation run */
  723. ASSERT(current->init_array == NULL);
  724. *delete_point = current->next;
  725. if (current->value->array != NULL)
  726. free((void*)current->value->array);
  727. free(current->value);
  728. free(current);
  729. break;
  730. }
  731. }
  732. }
  733. INLINE_DEVICE\
  734. (void)
  735. device_init_static_properties(device *me,
  736. void *data)
  737. {
  738. device_property_entry *property;
  739. for (property = me->properties;
  740. property != NULL;
  741. property = property->next) {
  742. ASSERT(property->init_array != NULL);
  743. ASSERT(property->value->array == NULL);
  744. ASSERT(property->value->disposition == permenant_object);
  745. switch (property->value->type) {
  746. case array_property:
  747. case boolean_property:
  748. case range_array_property:
  749. case reg_array_property:
  750. case string_property:
  751. case string_array_property:
  752. case integer_property:
  753. /* delete the property, and replace it with the original */
  754. device_set_property(me, property->value->name,
  755. property->value->type,
  756. property->init_array,
  757. property->sizeof_init_array);
  758. break;
  759. case ihandle_property:
  760. break;
  761. }
  762. }
  763. }
  764. INLINE_DEVICE\
  765. (void)
  766. device_init_runtime_properties(device *me,
  767. void *data)
  768. {
  769. device_property_entry *property;
  770. for (property = me->properties;
  771. property != NULL;
  772. property = property->next) {
  773. switch (property->value->disposition) {
  774. case permenant_object:
  775. switch (property->value->type) {
  776. case ihandle_property:
  777. {
  778. device_instance *ihandle;
  779. ihandle_runtime_property_spec spec;
  780. ASSERT(property->init_array != NULL);
  781. ASSERT(property->value->array == NULL);
  782. device_find_ihandle_runtime_property(me, property->value->name, &spec);
  783. ihandle = tree_instance(me, spec.full_path);
  784. device_set_ihandle_property(me, property->value->name, ihandle);
  785. break;
  786. }
  787. case array_property:
  788. case boolean_property:
  789. case range_array_property:
  790. case integer_property:
  791. case reg_array_property:
  792. case string_property:
  793. case string_array_property:
  794. ASSERT(property->init_array != NULL);
  795. ASSERT(property->value->array != NULL);
  796. break;
  797. }
  798. break;
  799. case tempoary_object:
  800. ASSERT(property->init_array == NULL);
  801. ASSERT(property->value->array != NULL);
  802. break;
  803. }
  804. }
  805. }
  806. INLINE_DEVICE\
  807. (const device_property *)
  808. device_next_property(const device_property *property)
  809. {
  810. /* find the property in the list */
  811. device *owner = property->owner;
  812. device_property_entry *entry = owner->properties;
  813. while (entry != NULL && entry->value != property)
  814. entry = entry->next;
  815. /* now return the following property */
  816. ASSERT(entry != NULL); /* must be a member! */
  817. if (entry->next != NULL)
  818. return entry->next->value;
  819. else
  820. return NULL;
  821. }
  822. INLINE_DEVICE\
  823. (const device_property *)
  824. device_find_property(device *me,
  825. const char *property)
  826. {
  827. if (me == NULL) {
  828. return NULL;
  829. }
  830. else if (property == NULL || strcmp(property, "") == 0) {
  831. if (me->properties == NULL)
  832. return NULL;
  833. else
  834. return me->properties->value;
  835. }
  836. else {
  837. device_property_entry *entry = find_property_entry(me, property);
  838. if (entry != NULL)
  839. return entry->value;
  840. }
  841. return NULL;
  842. }
  843. INLINE_DEVICE\
  844. (void)
  845. device_add_array_property(device *me,
  846. const char *property,
  847. const void *array,
  848. int sizeof_array)
  849. {
  850. device_add_property(me, property, array_property,
  851. array, sizeof_array, array, sizeof_array,
  852. NULL, permenant_object);
  853. }
  854. INLINE_DEVICE\
  855. (void)
  856. device_set_array_property(device *me,
  857. const char *property,
  858. const void *array,
  859. int sizeof_array)
  860. {
  861. device_set_property(me, property, array_property, array, sizeof_array);
  862. }
  863. INLINE_DEVICE\
  864. (const device_property *)
  865. device_find_array_property(device *me,
  866. const char *property)
  867. {
  868. const device_property *node;
  869. node = device_find_property(me, property);
  870. if (node == (device_property*)0
  871. || node->type != array_property)
  872. device_error(me, "property %s not found or of wrong type", property);
  873. return node;
  874. }
  875. INLINE_DEVICE\
  876. (void)
  877. device_add_boolean_property(device *me,
  878. const char *property,
  879. int boolean)
  880. {
  881. signed32 new_boolean = (boolean ? -1 : 0);
  882. device_add_property(me, property, boolean_property,
  883. &new_boolean, sizeof(new_boolean),
  884. &new_boolean, sizeof(new_boolean),
  885. NULL, permenant_object);
  886. }
  887. INLINE_DEVICE\
  888. (int)
  889. device_find_boolean_property(device *me,
  890. const char *property)
  891. {
  892. const device_property *node;
  893. unsigned_cell boolean;
  894. node = device_find_property(me, property);
  895. if (node == (device_property*)0
  896. || node->type != boolean_property)
  897. device_error(me, "property %s not found or of wrong type", property);
  898. ASSERT(sizeof(boolean) == node->sizeof_array);
  899. memcpy(&boolean, node->array, sizeof(boolean));
  900. return boolean;
  901. }
  902. INLINE_DEVICE\
  903. (void)
  904. device_add_ihandle_runtime_property(device *me,
  905. const char *property,
  906. const ihandle_runtime_property_spec *ihandle)
  907. {
  908. /* enter the full path as the init array */
  909. device_add_property(me, property, ihandle_property,
  910. ihandle->full_path, strlen(ihandle->full_path) + 1,
  911. NULL, 0,
  912. NULL, permenant_object);
  913. }
  914. INLINE_DEVICE\
  915. (void)
  916. device_find_ihandle_runtime_property(device *me,
  917. const char *property,
  918. ihandle_runtime_property_spec *ihandle)
  919. {
  920. device_property_entry *entry = find_property_entry(me, property);
  921. TRACE(trace_devices,
  922. ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
  923. (long)me, property));
  924. if (entry == NULL
  925. || entry->value->type != ihandle_property
  926. || entry->value->disposition != permenant_object)
  927. device_error(me, "property %s not found or of wrong type", property);
  928. ASSERT(entry->init_array != NULL);
  929. /* the full path */
  930. ihandle->full_path = entry->init_array;
  931. }
  932. INLINE_DEVICE\
  933. (void)
  934. device_set_ihandle_property(device *me,
  935. const char *property,
  936. device_instance *ihandle)
  937. {
  938. unsigned_cell cells;
  939. cells = H2BE_cell(device_instance_to_external(ihandle));
  940. device_set_property(me, property, ihandle_property,
  941. &cells, sizeof(cells));
  942. }
  943. INLINE_DEVICE\
  944. (device_instance *)
  945. device_find_ihandle_property(device *me,
  946. const char *property)
  947. {
  948. const device_property *node;
  949. unsigned_cell ihandle;
  950. device_instance *instance;
  951. node = device_find_property(me, property);
  952. if (node == NULL || node->type != ihandle_property)
  953. device_error(me, "property %s not found or of wrong type", property);
  954. if (node->array == NULL)
  955. device_error(me, "runtime property %s not yet initialized", property);
  956. ASSERT(sizeof(ihandle) == node->sizeof_array);
  957. memcpy(&ihandle, node->array, sizeof(ihandle));
  958. instance = external_to_device_instance(me, BE2H_cell(ihandle));
  959. ASSERT(instance != NULL);
  960. return instance;
  961. }
  962. INLINE_DEVICE\
  963. (void)
  964. device_add_integer_property(device *me,
  965. const char *property,
  966. signed_cell integer)
  967. {
  968. H2BE(integer);
  969. device_add_property(me, property, integer_property,
  970. &integer, sizeof(integer),
  971. &integer, sizeof(integer),
  972. NULL, permenant_object);
  973. }
  974. INLINE_DEVICE\
  975. (signed_cell)
  976. device_find_integer_property(device *me,
  977. const char *property)
  978. {
  979. const device_property *node;
  980. signed_cell integer;
  981. TRACE(trace_devices,
  982. ("device_find_integer(me=0x%lx, property=%s)\n",
  983. (long)me, property));
  984. node = device_find_property(me, property);
  985. if (node == (device_property*)0
  986. || node->type != integer_property)
  987. device_error(me, "property %s not found or of wrong type", property);
  988. ASSERT(sizeof(integer) == node->sizeof_array);
  989. memcpy(&integer, node->array, sizeof(integer));
  990. return BE2H_cell(integer);
  991. }
  992. INLINE_DEVICE\
  993. (int)
  994. device_find_integer_array_property(device *me,
  995. const char *property,
  996. unsigned index,
  997. signed_cell *integer)
  998. {
  999. const device_property *node;
  1000. int sizeof_integer = sizeof(*integer);
  1001. signed_cell *cell;
  1002. TRACE(trace_devices,
  1003. ("device_find_integer(me=0x%lx, property=%s)\n",
  1004. (long)me, property));
  1005. /* check things sane */
  1006. node = device_find_property(me, property);
  1007. if (node == (device_property*)0
  1008. || (node->type != integer_property
  1009. && node->type != array_property))
  1010. device_error(me, "property %s not found or of wrong type", property);
  1011. if ((node->sizeof_array % sizeof_integer) != 0)
  1012. device_error(me, "property %s contains an incomplete number of cells", property);
  1013. if (node->sizeof_array <= sizeof_integer * index)
  1014. return 0;
  1015. /* Find and convert the value */
  1016. cell = ((signed_cell*)node->array) + index;
  1017. *integer = BE2H_cell(*cell);
  1018. return node->sizeof_array / sizeof_integer;
  1019. }
  1020. STATIC_INLINE_DEVICE\
  1021. (unsigned_cell *)
  1022. unit_address_to_cells(const device_unit *unit,
  1023. unsigned_cell *cell,
  1024. int nr_cells)
  1025. {
  1026. int i;
  1027. ASSERT(nr_cells == unit->nr_cells);
  1028. for (i = 0; i < unit->nr_cells; i++) {
  1029. *cell = H2BE_cell(unit->cells[i]);
  1030. cell += 1;
  1031. }
  1032. return cell;
  1033. }
  1034. STATIC_INLINE_DEVICE\
  1035. (const unsigned_cell *)
  1036. cells_to_unit_address(const unsigned_cell *cell,
  1037. device_unit *unit,
  1038. int nr_cells)
  1039. {
  1040. int i;
  1041. memset(unit, 0, sizeof(*unit));
  1042. unit->nr_cells = nr_cells;
  1043. for (i = 0; i < unit->nr_cells; i++) {
  1044. unit->cells[i] = BE2H_cell(*cell);
  1045. cell += 1;
  1046. }
  1047. return cell;
  1048. }
  1049. STATIC_INLINE_DEVICE\
  1050. (unsigned)
  1051. nr_range_property_cells(device *me,
  1052. int nr_ranges)
  1053. {
  1054. return ((device_nr_address_cells(me)
  1055. + device_nr_address_cells(device_parent(me))
  1056. + device_nr_size_cells(me))
  1057. ) * nr_ranges;
  1058. }
  1059. INLINE_DEVICE\
  1060. (void)
  1061. device_add_range_array_property(device *me,
  1062. const char *property,
  1063. const range_property_spec *ranges,
  1064. unsigned nr_ranges)
  1065. {
  1066. unsigned sizeof_cells = (nr_range_property_cells(me, nr_ranges)
  1067. * sizeof(unsigned_cell));
  1068. unsigned_cell *cells = zalloc(sizeof_cells);
  1069. unsigned_cell *cell;
  1070. int i;
  1071. /* copy the property elements over */
  1072. cell = cells;
  1073. for (i = 0; i < nr_ranges; i++) {
  1074. const range_property_spec *range = &ranges[i];
  1075. /* copy the child address */
  1076. cell = unit_address_to_cells(&range->child_address, cell,
  1077. device_nr_address_cells(me));
  1078. /* copy the parent address */
  1079. cell = unit_address_to_cells(&range->parent_address, cell,
  1080. device_nr_address_cells(device_parent(me)));
  1081. /* copy the size */
  1082. cell = unit_address_to_cells(&range->size, cell,
  1083. device_nr_size_cells(me));
  1084. }
  1085. ASSERT(cell == &cells[nr_range_property_cells(me, nr_ranges)]);
  1086. /* add it */
  1087. device_add_property(me, property, range_array_property,
  1088. cells, sizeof_cells,
  1089. cells, sizeof_cells,
  1090. NULL, permenant_object);
  1091. free(cells);
  1092. }
  1093. INLINE_DEVICE\
  1094. (int)
  1095. device_find_range_array_property(device *me,
  1096. const char *property,
  1097. unsigned index,
  1098. range_property_spec *range)
  1099. {
  1100. const device_property *node;
  1101. unsigned sizeof_entry = (nr_range_property_cells(me, 1)
  1102. * sizeof(unsigned_cell));
  1103. const unsigned_cell *cells;
  1104. /* locate the property */
  1105. node = device_find_property(me, property);
  1106. if (node == (device_property*)0
  1107. || node->type != range_array_property)
  1108. device_error(me, "property %s not found or of wrong type", property);
  1109. /* aligned ? */
  1110. if ((node->sizeof_array % sizeof_entry) != 0)
  1111. device_error(me, "property %s contains an incomplete number of entries",
  1112. property);
  1113. /* within bounds? */
  1114. if (node->sizeof_array < sizeof_entry * (index + 1))
  1115. return 0;
  1116. /* find the range of interest */
  1117. cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
  1118. /* copy the child address out - converting as we go */
  1119. cells = cells_to_unit_address(cells, &range->child_address,
  1120. device_nr_address_cells(me));
  1121. /* copy the parent address out - converting as we go */
  1122. cells = cells_to_unit_address(cells, &range->parent_address,
  1123. device_nr_address_cells(device_parent(me)));
  1124. /* copy the size - converting as we go */
  1125. cells = cells_to_unit_address(cells, &range->size,
  1126. device_nr_size_cells(me));
  1127. return node->sizeof_array / sizeof_entry;
  1128. }
  1129. STATIC_INLINE_DEVICE\
  1130. (unsigned)
  1131. nr_reg_property_cells(device *me,
  1132. int nr_regs)
  1133. {
  1134. return (device_nr_address_cells(device_parent(me))
  1135. + device_nr_size_cells(device_parent(me))
  1136. ) * nr_regs;
  1137. }
  1138. INLINE_DEVICE\
  1139. (void)
  1140. device_add_reg_array_property(device *me,
  1141. const char *property,
  1142. const reg_property_spec *regs,
  1143. unsigned nr_regs)
  1144. {
  1145. unsigned sizeof_cells = (nr_reg_property_cells(me, nr_regs)
  1146. * sizeof(unsigned_cell));
  1147. unsigned_cell *cells = zalloc(sizeof_cells);
  1148. unsigned_cell *cell;
  1149. int i;
  1150. /* copy the property elements over */
  1151. cell = cells;
  1152. for (i = 0; i < nr_regs; i++) {
  1153. const reg_property_spec *reg = &regs[i];
  1154. /* copy the address */
  1155. cell = unit_address_to_cells(&reg->address, cell,
  1156. device_nr_address_cells(device_parent(me)));
  1157. /* copy the size */
  1158. cell = unit_address_to_cells(&reg->size, cell,
  1159. device_nr_size_cells(device_parent(me)));
  1160. }
  1161. ASSERT(cell == &cells[nr_reg_property_cells(me, nr_regs)]);
  1162. /* add it */
  1163. device_add_property(me, property, reg_array_property,
  1164. cells, sizeof_cells,
  1165. cells, sizeof_cells,
  1166. NULL, permenant_object);
  1167. free(cells);
  1168. }
  1169. INLINE_DEVICE\
  1170. (int)
  1171. device_find_reg_array_property(device *me,
  1172. const char *property,
  1173. unsigned index,
  1174. reg_property_spec *reg)
  1175. {
  1176. const device_property *node;
  1177. unsigned sizeof_entry = (nr_reg_property_cells(me, 1)
  1178. * sizeof(unsigned_cell));
  1179. const unsigned_cell *cells;
  1180. /* locate the property */
  1181. node = device_find_property(me, property);
  1182. if (node == (device_property*)0
  1183. || node->type != reg_array_property)
  1184. device_error(me, "property %s not found or of wrong type", property);
  1185. /* aligned ? */
  1186. if ((node->sizeof_array % sizeof_entry) != 0)
  1187. device_error(me, "property %s contains an incomplete number of entries",
  1188. property);
  1189. /* within bounds? */
  1190. if (node->sizeof_array < sizeof_entry * (index + 1))
  1191. return 0;
  1192. /* find the range of interest */
  1193. cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
  1194. /* copy the address out - converting as we go */
  1195. cells = cells_to_unit_address(cells, &reg->address,
  1196. device_nr_address_cells(device_parent(me)));
  1197. /* copy the size out - converting as we go */
  1198. cells = cells_to_unit_address(cells, &reg->size,
  1199. device_nr_size_cells(device_parent(me)));
  1200. return node->sizeof_array / sizeof_entry;
  1201. }
  1202. INLINE_DEVICE\
  1203. (void)
  1204. device_add_string_property(device *me,
  1205. const char *property,
  1206. const char *string)
  1207. {
  1208. device_add_property(me, property, string_property,
  1209. string, strlen(string) + 1,
  1210. string, strlen(string) + 1,
  1211. NULL, permenant_object);
  1212. }
  1213. INLINE_DEVICE\
  1214. (const char *)
  1215. device_find_string_property(device *me,
  1216. const char *property)
  1217. {
  1218. const device_property *node;
  1219. const char *string;
  1220. node = device_find_property(me, property);
  1221. if (node == (device_property*)0
  1222. || node->type != string_property)
  1223. device_error(me, "property %s not found or of wrong type", property);
  1224. string = node->array;
  1225. ASSERT(strlen(string) + 1 == node->sizeof_array);
  1226. return string;
  1227. }
  1228. INLINE_DEVICE\
  1229. (void)
  1230. device_add_string_array_property(device *me,
  1231. const char *property,
  1232. const string_property_spec *strings,
  1233. unsigned nr_strings)
  1234. {
  1235. int sizeof_array;
  1236. int string_nr;
  1237. char *array;
  1238. char *chp;
  1239. if (nr_strings == 0)
  1240. device_error(me, "property %s must be non-null", property);
  1241. /* total up the size of the needed array */
  1242. for (sizeof_array = 0, string_nr = 0;
  1243. string_nr < nr_strings;
  1244. string_nr ++) {
  1245. sizeof_array += strlen(strings[string_nr]) + 1;
  1246. }
  1247. /* create the array */
  1248. array = (char*)zalloc(sizeof_array);
  1249. chp = array;
  1250. for (string_nr = 0;
  1251. string_nr < nr_strings;
  1252. string_nr++) {
  1253. strcpy(chp, strings[string_nr]);
  1254. chp += strlen(chp) + 1;
  1255. }
  1256. ASSERT(chp == array + sizeof_array);
  1257. /* now enter it */
  1258. device_add_property(me, property, string_array_property,
  1259. array, sizeof_array,
  1260. array, sizeof_array,
  1261. NULL, permenant_object);
  1262. }
  1263. INLINE_DEVICE\
  1264. (int)
  1265. device_find_string_array_property(device *me,
  1266. const char *property,
  1267. unsigned index,
  1268. string_property_spec *string)
  1269. {
  1270. const device_property *node;
  1271. node = device_find_property(me, property);
  1272. if (node == (device_property*)0)
  1273. device_error(me, "property %s not found", property);
  1274. switch (node->type) {
  1275. default:
  1276. device_error(me, "property %s of wrong type", property);
  1277. break;
  1278. case string_property:
  1279. if (index == 0) {
  1280. *string = node->array;
  1281. ASSERT(strlen(*string) + 1 == node->sizeof_array);
  1282. return 1;
  1283. }
  1284. break;
  1285. case array_property:
  1286. if (node->sizeof_array == 0
  1287. || ((char*)node->array)[node->sizeof_array - 1] != '\0')
  1288. device_error(me, "property %s invalid for string array", property);
  1289. /* FALL THROUGH */
  1290. case string_array_property:
  1291. ASSERT(node->sizeof_array > 0);
  1292. ASSERT(((char*)node->array)[node->sizeof_array - 1] == '\0');
  1293. {
  1294. const char *chp = node->array;
  1295. int nr_entries = 0;
  1296. /* count the number of strings, keeping an eye out for the one
  1297. we're looking for */
  1298. *string = chp;
  1299. do {
  1300. if (*chp == '\0') {
  1301. /* next string */
  1302. nr_entries++;
  1303. chp++;
  1304. if (nr_entries == index)
  1305. *string = chp;
  1306. }
  1307. else {
  1308. chp++;
  1309. }
  1310. } while (chp < (char*)node->array + node->sizeof_array);
  1311. if (index < nr_entries)
  1312. return nr_entries;
  1313. else {
  1314. *string = NULL;
  1315. return 0;
  1316. }
  1317. }
  1318. break;
  1319. }
  1320. return 0;
  1321. }
  1322. INLINE_DEVICE\
  1323. (void)
  1324. device_add_duplicate_property(device *me,
  1325. const char *property,
  1326. const device_property *original)
  1327. {
  1328. device_property_entry *master;
  1329. TRACE(trace_devices,
  1330. ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
  1331. (long)me, property));
  1332. if (original->disposition != permenant_object)
  1333. device_error(me, "Can only duplicate permenant objects");
  1334. /* find the original's master */
  1335. master = original->owner->properties;
  1336. while (master->value != original) {
  1337. master = master->next;
  1338. ASSERT(master != NULL);
  1339. }
  1340. /* now duplicate it */
  1341. device_add_property(me, property,
  1342. original->type,
  1343. master->init_array, master->sizeof_init_array,
  1344. original->array, original->sizeof_array,
  1345. original, permenant_object);
  1346. }
  1347. /* Device Hardware: */
  1348. INLINE_DEVICE\
  1349. (unsigned)
  1350. device_io_read_buffer(device *me,
  1351. void *dest,
  1352. int space,
  1353. unsigned_word addr,
  1354. unsigned nr_bytes,
  1355. cpu *processor,
  1356. unsigned_word cia)
  1357. {
  1358. if (me->callback->io.read_buffer == NULL)
  1359. device_error(me, "no io.read_buffer method");
  1360. return me->callback->io.read_buffer(me, dest, space,
  1361. addr, nr_bytes,
  1362. processor, cia);
  1363. }
  1364. INLINE_DEVICE\
  1365. (unsigned)
  1366. device_io_write_buffer(device *me,
  1367. const void *source,
  1368. int space,
  1369. unsigned_word addr,
  1370. unsigned nr_bytes,
  1371. cpu *processor,
  1372. unsigned_word cia)
  1373. {
  1374. if (me->callback->io.write_buffer == NULL)
  1375. device_error(me, "no io.write_buffer method");
  1376. return me->callback->io.write_buffer(me, source, space,
  1377. addr, nr_bytes,
  1378. processor, cia);
  1379. }
  1380. INLINE_DEVICE\
  1381. (unsigned)
  1382. device_dma_read_buffer(device *me,
  1383. void *dest,
  1384. int space,
  1385. unsigned_word addr,
  1386. unsigned nr_bytes)
  1387. {
  1388. if (me->callback->dma.read_buffer == NULL)
  1389. device_error(me, "no dma.read_buffer method");
  1390. return me->callback->dma.read_buffer(me, dest, space,
  1391. addr, nr_bytes);
  1392. }
  1393. INLINE_DEVICE\
  1394. (unsigned)
  1395. device_dma_write_buffer(device *me,
  1396. const void *source,
  1397. int space,
  1398. unsigned_word addr,
  1399. unsigned nr_bytes,
  1400. int violate_read_only_section)
  1401. {
  1402. if (me->callback->dma.write_buffer == NULL)
  1403. device_error(me, "no dma.write_buffer method");
  1404. return me->callback->dma.write_buffer(me, source, space,
  1405. addr, nr_bytes,
  1406. violate_read_only_section);
  1407. }
  1408. INLINE_DEVICE\
  1409. (void)
  1410. device_attach_address(device *me,
  1411. attach_type attach,
  1412. int space,
  1413. unsigned_word addr,
  1414. unsigned nr_bytes,
  1415. access_type access,
  1416. device *client) /*callback/default*/
  1417. {
  1418. if (me->callback->address.attach == NULL)
  1419. device_error(me, "no address.attach method");
  1420. me->callback->address.attach(me, attach, space,
  1421. addr, nr_bytes, access, client);
  1422. }
  1423. INLINE_DEVICE\
  1424. (void)
  1425. device_detach_address(device *me,
  1426. attach_type attach,
  1427. int space,
  1428. unsigned_word addr,
  1429. unsigned nr_bytes,
  1430. access_type access,
  1431. device *client) /*callback/default*/
  1432. {
  1433. if (me->callback->address.detach == NULL)
  1434. device_error(me, "no address.detach method");
  1435. me->callback->address.detach(me, attach, space,
  1436. addr, nr_bytes, access, client);
  1437. }
  1438. /* Interrupts: */
  1439. INLINE_DEVICE(void)
  1440. device_interrupt_event(device *me,
  1441. int my_port,
  1442. int level,
  1443. cpu *processor,
  1444. unsigned_word cia)
  1445. {
  1446. int found_an_edge = 0;
  1447. device_interrupt_edge *edge;
  1448. /* device's interrupt lines directly connected */
  1449. for (edge = me->interrupt_destinations;
  1450. edge != NULL;
  1451. edge = edge->next) {
  1452. if (edge->my_port == my_port) {
  1453. if (edge->dest->callback->interrupt.event == NULL)
  1454. device_error(me, "no interrupt method");
  1455. edge->dest->callback->interrupt.event(edge->dest,
  1456. edge->dest_port,
  1457. me,
  1458. my_port,
  1459. level,
  1460. processor, cia);
  1461. found_an_edge = 1;
  1462. }
  1463. }
  1464. if (!found_an_edge) {
  1465. device_error(me, "No interrupt edge for port %d", my_port);
  1466. }
  1467. }
  1468. INLINE_DEVICE\
  1469. (void)
  1470. device_interrupt_attach(device *me,
  1471. int my_port,
  1472. device *dest,
  1473. int dest_port,
  1474. object_disposition disposition)
  1475. {
  1476. attach_device_interrupt_edge(&me->interrupt_destinations,
  1477. my_port,
  1478. dest,
  1479. dest_port,
  1480. disposition);
  1481. }
  1482. INLINE_DEVICE\
  1483. (void)
  1484. device_interrupt_detach(device *me,
  1485. int my_port,
  1486. device *dest,
  1487. int dest_port)
  1488. {
  1489. detach_device_interrupt_edge(me,
  1490. &me->interrupt_destinations,
  1491. my_port,
  1492. dest,
  1493. dest_port);
  1494. }
  1495. INLINE_DEVICE\
  1496. (void)
  1497. device_interrupt_traverse(device *me,
  1498. device_interrupt_traverse_function *handler,
  1499. void *data)
  1500. {
  1501. device_interrupt_edge *interrupt_edge;
  1502. for (interrupt_edge = me->interrupt_destinations;
  1503. interrupt_edge != NULL;
  1504. interrupt_edge = interrupt_edge->next) {
  1505. handler(me, interrupt_edge->my_port,
  1506. interrupt_edge->dest, interrupt_edge->dest_port,
  1507. data);
  1508. }
  1509. }
  1510. INLINE_DEVICE\
  1511. (int)
  1512. device_interrupt_decode(device *me,
  1513. const char *port_name,
  1514. port_direction direction)
  1515. {
  1516. if (port_name == NULL || port_name[0] == '\0')
  1517. return 0;
  1518. if (isdigit(port_name[0])) {
  1519. return strtoul(port_name, NULL, 0);
  1520. }
  1521. else {
  1522. const device_interrupt_port_descriptor *ports =
  1523. me->callback->interrupt.ports;
  1524. if (ports != NULL) {
  1525. while (ports->name != NULL) {
  1526. if (ports->direction == bidirect_port
  1527. || ports->direction == direction) {
  1528. if (ports->nr_ports > 0) {
  1529. int len = strlen(ports->name);
  1530. if (strncmp(port_name, ports->name, len) == 0) {
  1531. if (port_name[len] == '\0')
  1532. return ports->number;
  1533. else if(isdigit(port_name[len])) {
  1534. int port = ports->number + strtoul(&port_name[len], NULL, 0);
  1535. if (port >= ports->number + ports->nr_ports)
  1536. device_error(me, "Interrupt port %s out of range",
  1537. port_name);
  1538. return port;
  1539. }
  1540. }
  1541. }
  1542. else if (strcmp(port_name, ports->name) == 0)
  1543. return ports->number;
  1544. }
  1545. ports++;
  1546. }
  1547. }
  1548. }
  1549. device_error(me, "Unreconized interrupt port %s", port_name);
  1550. return 0;
  1551. }
  1552. INLINE_DEVICE\
  1553. (int)
  1554. device_interrupt_encode(device *me,
  1555. int port_number,
  1556. char *buf,
  1557. int sizeof_buf,
  1558. port_direction direction)
  1559. {
  1560. const device_interrupt_port_descriptor *ports = NULL;
  1561. ports = me->callback->interrupt.ports;
  1562. if (ports != NULL) {
  1563. while (ports->name != NULL) {
  1564. if (ports->direction == bidirect_port
  1565. || ports->direction == direction) {
  1566. if (ports->nr_ports > 0) {
  1567. if (port_number >= ports->number
  1568. && port_number < ports->number + ports->nr_ports) {
  1569. strcpy(buf, ports->name);
  1570. sprintf(buf + strlen(buf), "%d", port_number - ports->number);
  1571. if (strlen(buf) >= sizeof_buf)
  1572. error("device_interrupt_encode: buffer overflow");
  1573. return strlen(buf);
  1574. }
  1575. }
  1576. else {
  1577. if (ports->number == port_number) {
  1578. if (strlen(ports->name) >= sizeof_buf)
  1579. error("device_interrupt_encode: buffer overflow");
  1580. strcpy(buf, ports->name);
  1581. return strlen(buf);
  1582. }
  1583. }
  1584. }
  1585. ports++;
  1586. }
  1587. }
  1588. sprintf(buf, "%d", port_number);
  1589. if (strlen(buf) >= sizeof_buf)
  1590. error("device_interrupt_encode: buffer overflow");
  1591. return strlen(buf);
  1592. }
  1593. /* IOCTL: */
  1594. EXTERN_DEVICE\
  1595. (int)
  1596. device_ioctl(device *me,
  1597. cpu *processor,
  1598. unsigned_word cia,
  1599. device_ioctl_request request,
  1600. ...)
  1601. {
  1602. int status;
  1603. va_list ap;
  1604. va_start(ap, request);
  1605. if (me->callback->ioctl == NULL)
  1606. device_error(me, "no ioctl method");
  1607. status = me->callback->ioctl(me, processor, cia, request, ap);
  1608. va_end(ap);
  1609. return status;
  1610. }
  1611. /* I/O */
  1612. EXTERN_DEVICE\
  1613. (void)
  1614. device_error(device *me,
  1615. const char *fmt,
  1616. ...)
  1617. {
  1618. char message[1024];
  1619. va_list ap;
  1620. /* format the message */
  1621. va_start(ap, fmt);
  1622. vsprintf(message, fmt, ap);
  1623. va_end(ap);
  1624. /* sanity check */
  1625. if (strlen(message) >= sizeof(message))
  1626. error("device_error: buffer overflow");
  1627. if (me == NULL)
  1628. error("device: %s", message);
  1629. else if (me->path != NULL && me->path[0] != '\0')
  1630. error("%s: %s", me->path, message);
  1631. else if (me->name != NULL && me->name[0] != '\0')
  1632. error("%s: %s", me->name, message);
  1633. else
  1634. error("device: %s", message);
  1635. while(1);
  1636. }
  1637. INLINE_DEVICE\
  1638. (int)
  1639. device_trace(device *me)
  1640. {
  1641. return me->trace;
  1642. }
  1643. /* External representation */
  1644. INLINE_DEVICE\
  1645. (device *)
  1646. external_to_device(device *tree_member,
  1647. unsigned_cell phandle)
  1648. {
  1649. device *me = cap_internal(tree_member->phandles, phandle);
  1650. return me;
  1651. }
  1652. INLINE_DEVICE\
  1653. (unsigned_cell)
  1654. device_to_external(device *me)
  1655. {
  1656. unsigned_cell phandle = cap_external(me->phandles, me);
  1657. return phandle;
  1658. }
  1659. INLINE_DEVICE\
  1660. (device_instance *)
  1661. external_to_device_instance(device *tree_member,
  1662. unsigned_cell ihandle)
  1663. {
  1664. device_instance *instance = cap_internal(tree_member->ihandles, ihandle);
  1665. return instance;
  1666. }
  1667. INLINE_DEVICE\
  1668. (unsigned_cell)
  1669. device_instance_to_external(device_instance *instance)
  1670. {
  1671. unsigned_cell ihandle = cap_external(instance->owner->ihandles, instance);
  1672. return ihandle;
  1673. }
  1674. /* Map onto the event functions */
  1675. INLINE_DEVICE\
  1676. (event_entry_tag)
  1677. device_event_queue_schedule(device *me,
  1678. signed64 delta_time,
  1679. device_event_handler *handler,
  1680. void *data)
  1681. {
  1682. return event_queue_schedule(psim_event_queue(me->system),
  1683. delta_time,
  1684. handler,
  1685. data);
  1686. }
  1687. INLINE_DEVICE\
  1688. (void)
  1689. device_event_queue_deschedule(device *me,
  1690. event_entry_tag event_to_remove)
  1691. {
  1692. event_queue_deschedule(psim_event_queue(me->system),
  1693. event_to_remove);
  1694. }
  1695. INLINE_DEVICE\
  1696. (signed64)
  1697. device_event_queue_time(device *me)
  1698. {
  1699. return event_queue_time(psim_event_queue(me->system));
  1700. }
  1701. /* Initialization: */
  1702. INLINE_DEVICE\
  1703. (void)
  1704. device_clean(device *me,
  1705. void *data)
  1706. {
  1707. psim *system;
  1708. system = (psim*)data;
  1709. TRACE(trace_device_init, ("device_clean - initializing %s", me->path));
  1710. clean_device_interrupt_edges(&me->interrupt_destinations);
  1711. clean_device_instances(me);
  1712. clean_device_properties(me);
  1713. }
  1714. /* Device initialization: */
  1715. INLINE_DEVICE\
  1716. (void)
  1717. device_init_address(device *me,
  1718. void *data)
  1719. {
  1720. psim *system = (psim*)data;
  1721. int nr_address_cells;
  1722. int nr_size_cells;
  1723. TRACE(trace_device_init, ("device_init_address - initializing %s", me->path));
  1724. /* ensure the cap database is valid */
  1725. if (me->parent == NULL) {
  1726. cap_init(me->ihandles);
  1727. cap_init(me->phandles);
  1728. }
  1729. /* some basics */
  1730. me->system = system; /* misc things not known until now */
  1731. me->trace = (device_find_property(me, "trace")
  1732. ? device_find_integer_property(me, "trace")
  1733. : 0);
  1734. /* Ensure that the first address found in the reg property matches
  1735. anything that was specified as part of the devices name */
  1736. if (device_find_property(me, "reg") != NULL) {
  1737. reg_property_spec unit;
  1738. device_find_reg_array_property(me, "reg", 0, &unit);
  1739. if (memcmp(device_unit_address(me), &unit.address, sizeof(unit.address))
  1740. != 0)
  1741. device_error(me, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
  1742. }
  1743. /* ensure that the devices #address/size-cells is consistent */
  1744. nr_address_cells = device_nr_address_cells(me);
  1745. if (device_find_property(me, "#address-cells") != NULL
  1746. && (nr_address_cells
  1747. != device_find_integer_property(me, "#address-cells")))
  1748. device_error(me, "#address-cells property used before defined");
  1749. nr_size_cells = device_nr_size_cells(me);
  1750. if (device_find_property(me, "#size-cells") != NULL
  1751. && (nr_size_cells
  1752. != device_find_integer_property(me, "#size-cells")))
  1753. device_error(me, "#size-cells property used before defined");
  1754. /* now init it */
  1755. if (me->callback->init.address != NULL)
  1756. me->callback->init.address(me);
  1757. }
  1758. INLINE_DEVICE\
  1759. (void)
  1760. device_init_data(device *me,
  1761. void *data)
  1762. {
  1763. TRACE(trace_device_init, ("device_init_data - initializing %s", me->path));
  1764. if (me->callback->init.data != NULL)
  1765. me->callback->init.data(me);
  1766. }
  1767. #endif /* _DEVICE_C_ */