123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998 |
- /* This file is part of the program psim.
- Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- */
- #ifndef _DEVICE_C_
- #define _DEVICE_C_
- #include <stdio.h>
- #include "device_table.h"
- #include "cap.h"
- #include "events.h"
- #include "psim.h"
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #ifdef HAVE_STRING_H
- #include <string.h>
- #else
- #ifdef HAVE_STRINGS_H
- #include <strings.h>
- #endif
- #endif
- #include <ctype.h>
- STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
- /* property entries */
- typedef struct _device_property_entry device_property_entry;
- struct _device_property_entry {
- device_property_entry *next;
- device_property *value;
- const void *init_array;
- unsigned sizeof_init_array;
- };
- /* Interrupt edges */
- typedef struct _device_interrupt_edge device_interrupt_edge;
- struct _device_interrupt_edge {
- int my_port;
- device *dest;
- int dest_port;
- device_interrupt_edge *next;
- object_disposition disposition;
- };
- STATIC_INLINE_DEVICE\
- (void)
- attach_device_interrupt_edge(device_interrupt_edge **list,
- int my_port,
- device *dest,
- int dest_port,
- object_disposition disposition)
- {
- device_interrupt_edge *new_edge = ZALLOC(device_interrupt_edge);
- new_edge->my_port = my_port;
- new_edge->dest = dest;
- new_edge->dest_port = dest_port;
- new_edge->next = *list;
- new_edge->disposition = disposition;
- *list = new_edge;
- }
- STATIC_INLINE_DEVICE\
- (void)
- detach_device_interrupt_edge(device *me,
- device_interrupt_edge **list,
- int my_port,
- device *dest,
- int dest_port)
- {
- while (*list != NULL) {
- device_interrupt_edge *old_edge = *list;
- if (old_edge->dest == dest
- && old_edge->dest_port == dest_port
- && old_edge->my_port == my_port) {
- if (old_edge->disposition == permenant_object)
- device_error(me, "attempt to delete permenant interrupt");
- *list = old_edge->next;
- free(old_edge);
- return;
- }
- }
- device_error(me, "attempt to delete unattached interrupt");
- }
- STATIC_INLINE_DEVICE\
- (void)
- clean_device_interrupt_edges(device_interrupt_edge **list)
- {
- while (*list != NULL) {
- device_interrupt_edge *old_edge = *list;
- switch (old_edge->disposition) {
- case permenant_object:
- list = &old_edge->next;
- break;
- case tempoary_object:
- *list = old_edge->next;
- free(old_edge);
- break;
- }
- }
- }
- /* A device */
- struct _device {
- /* my name is ... */
- const char *name;
- device_unit unit_address;
- const char *path;
- int nr_address_cells;
- int nr_size_cells;
- /* device tree */
- device *parent;
- device *children;
- device *sibling;
- /* its template methods */
- void *data; /* device specific data */
- const device_callbacks *callback;
- /* device properties */
- device_property_entry *properties;
- /* interrupts */
- device_interrupt_edge *interrupt_destinations;
- /* any open instances of this device */
- device_instance *instances;
- /* the internal/external mappings and other global requirements */
- cap *ihandles;
- cap *phandles;
- psim *system;
- /* debugging */
- int trace;
- };
- /* an instance of a device */
- struct _device_instance {
- void *data;
- char *args;
- char *path;
- const device_instance_callbacks *callback;
- /* the root instance */
- device *owner;
- device_instance *next;
- /* interposed instance */
- device_instance *parent;
- device_instance *child;
- };
- /* creation */
- STATIC_INLINE_DEVICE\
- (const char *)
- device_full_name(device *leaf,
- char *buf,
- unsigned sizeof_buf)
- {
- /* get a buffer */
- char full_name[1024];
- if (buf == (char*)0) {
- buf = full_name;
- sizeof_buf = sizeof(full_name);
- }
- /* construct a name */
- if (leaf->parent == NULL) {
- if (sizeof_buf < 1)
- error("device_full_name: buffer overflow");
- *buf = '\0';
- }
- else {
- char unit[1024];
- device_full_name(leaf->parent, buf, sizeof_buf);
- if (leaf->parent != NULL
- && device_encode_unit(leaf->parent,
- &leaf->unit_address,
- unit+1,
- sizeof(unit)-1) > 0)
- unit[0] = '@';
- else
- unit[0] = '\0';
- if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit)
- >= sizeof_buf)
- error("device_full_name: buffer overflow");
- strcat(buf, "/");
- strcat(buf, leaf->name);
- strcat (buf, unit);
- }
-
- /* return it usefully */
- if (buf == full_name)
- buf = (char *) strdup(full_name);
- return buf;
- }
- STATIC_INLINE_DEVICE\
- (device *)
- device_create_from(const char *name,
- const device_unit *unit_address,
- void *data,
- const device_callbacks *callbacks,
- device *parent)
- {
- device *new_device = ZALLOC(device);
- /* insert it into the device tree */
- new_device->parent = parent;
- new_device->children = NULL;
- if (parent != NULL) {
- device **sibling = &parent->children;
- while ((*sibling) != NULL)
- sibling = &(*sibling)->sibling;
- *sibling = new_device;
- }
- /* give it a name */
- new_device->name = (char *) strdup(name);
- new_device->unit_address = *unit_address;
- new_device->path = device_full_name(new_device, NULL, 0);
- /* its template */
- new_device->data = data;
- new_device->callback = callbacks;
- /* its properties - already null */
- /* interrupts - already null */
- /* mappings - if needed */
- if (parent == NULL) {
- new_device->ihandles = cap_create(name);
- new_device->phandles = cap_create(name);
- }
- else {
- new_device->ihandles = device_root(parent)->ihandles;
- new_device->phandles = device_root(parent)->phandles;
- }
- cap_add(new_device->phandles, new_device);
- return new_device;
- }
- INLINE_DEVICE\
- (device *)
- device_create(device *parent,
- const char *base,
- const char *name,
- const char *unit_address,
- const char *args)
- {
- const device_descriptor *const *table;
- for (table = device_table; *table != NULL; table++) {
- const device_descriptor *descr;
- for (descr = *table; descr->name != NULL; descr++) {
- if (strcmp(base, descr->name) == 0) {
- device_unit address = { 0 };
- void *data = NULL;
- if (parent != NULL)
- if (device_decode_unit(parent, unit_address, &address) < 0)
- device_error(parent, "invalid address %s for device %s",
- unit_address, name);
- if (descr->creator != NULL)
- data = descr->creator(name, &address, args);
- return device_create_from(name, &address, data,
- descr->callbacks, parent);
- }
- }
- }
- device_error(parent, "attempt to attach unknown device %s", name);
- return NULL;
- }
- INLINE_DEVICE\
- (void)
- device_usage(int verbose)
- {
- const device_descriptor *const *table;
- if (verbose == 1) {
- int pos = 0;
- for (table = device_table; *table != NULL; table++) {
- const device_descriptor *descr;
- for (descr = *table; descr->name != NULL; descr++) {
- pos += strlen(descr->name) + 2;
- if (pos > 75) {
- pos = strlen(descr->name) + 2;
- printf_filtered("\n");
- }
- printf_filtered(" %s", descr->name);
- }
- printf_filtered("\n");
- }
- }
- if (verbose > 1) {
- for (table = device_table; *table != NULL; table++) {
- const device_descriptor *descr;
- for (descr = *table; descr->name != NULL; descr++) {
- printf_filtered(" %s:\n", descr->name);
- /* interrupt ports */
- if (descr->callbacks->interrupt.ports != NULL) {
- const device_interrupt_port_descriptor *ports =
- descr->callbacks->interrupt.ports;
- printf_filtered(" interrupt ports:");
- while (ports->name != NULL) {
- printf_filtered(" %s", ports->name);
- ports++;
- }
- printf_filtered("\n");
- }
- /* general info */
- if (descr->callbacks->usage != NULL)
- descr->callbacks->usage(verbose);
- }
- }
- }
- }
-
- /* Device node: */
- INLINE_DEVICE\
- (device *)
- device_parent(device *me)
- {
- return me->parent;
- }
- INLINE_DEVICE\
- (device *)
- device_root(device *me)
- {
- ASSERT(me != NULL);
- while (me->parent != NULL)
- me = me->parent;
- return me;
- }
- INLINE_DEVICE\
- (device *)
- device_sibling(device *me)
- {
- return me->sibling;
- }
- INLINE_DEVICE\
- (device *)
- device_child(device *me)
- {
- return me->children;
- }
- INLINE_DEVICE\
- (const char *)
- device_name(device *me)
- {
- return me->name;
- }
- INLINE_DEVICE\
- (const char *)
- device_path(device *me)
- {
- return me->path;
- }
- INLINE_DEVICE\
- (void *)
- device_data(device *me)
- {
- return me->data;
- }
- INLINE_DEVICE\
- (psim *)
- device_system(device *me)
- {
- return me->system;
- }
- INLINE_DEVICE\
- (const device_unit *)
- device_unit_address(device *me)
- {
- return &me->unit_address;
- }
- INLINE_DEVICE\
- (int)
- device_address_to_attach_address(device *me,
- const device_unit *address,
- int *attach_space,
- unsigned_word *attach_address,
- device *client)
- {
- if (me->callback->convert.address_to_attach_address == NULL)
- device_error(me, "no convert.address_to_attach_address method");
- return me->callback->convert.address_to_attach_address(me, address, attach_space, attach_address, client);
- }
- INLINE_DEVICE\
- (int)
- device_size_to_attach_size(device *me,
- const device_unit *size,
- unsigned *nr_bytes,
- device *client)
- {
- if (me->callback->convert.size_to_attach_size == NULL)
- device_error(me, "no convert.size_to_attach_size method");
- return me->callback->convert.size_to_attach_size(me, size, nr_bytes, client);
- }
- INLINE_DEVICE\
- (int)
- device_decode_unit(device *bus,
- const char *unit,
- device_unit *address)
- {
- if (bus->callback->convert.decode_unit == NULL)
- device_error(bus, "no convert.decode_unit method");
- return bus->callback->convert.decode_unit(bus, unit, address);
- }
- INLINE_DEVICE\
- (int)
- device_encode_unit(device *bus,
- const device_unit *unit_address,
- char *buf,
- int sizeof_buf)
- {
- if (bus->callback->convert.encode_unit == NULL)
- device_error(bus, "no convert.encode_unit method");
- return bus->callback->convert.encode_unit(bus, unit_address, buf, sizeof_buf);
- }
- INLINE_DEVICE\
- (unsigned)
- device_nr_address_cells(device *me)
- {
- if (me->nr_address_cells == 0) {
- if (device_find_property(me, "#address-cells") != NULL)
- me->nr_address_cells = device_find_integer_property(me, "#address-cells");
- else
- me->nr_address_cells = 2;
- }
- return me->nr_address_cells;
- }
- INLINE_DEVICE\
- (unsigned)
- device_nr_size_cells(device *me)
- {
- if (me->nr_size_cells == 0) {
- if (device_find_property(me, "#size-cells") != NULL)
- me->nr_size_cells = device_find_integer_property(me, "#size-cells");
- else
- me->nr_size_cells = 1;
- }
- return me->nr_size_cells;
- }
- /* device-instance: */
- INLINE_DEVICE\
- (device_instance *)
- device_create_instance_from(device *me,
- device_instance *parent,
- void *data,
- const char *path,
- const char *args,
- const device_instance_callbacks *callbacks)
- {
- device_instance *instance = ZALLOC(device_instance);
- if ((me == NULL) == (parent == NULL))
- device_error(me, "can't have both parent instance and parent device");
- /*instance->unit*/
- /* link this instance into the devices list */
- if (me != NULL) {
- ASSERT(parent == NULL);
- instance->owner = me;
- instance->parent = NULL;
- /* link this instance into the front of the devices instance list */
- instance->next = me->instances;
- me->instances = instance;
- }
- if (parent != NULL) {
- device_instance **previous;
- ASSERT(parent->child == NULL);
- parent->child = instance;
- ASSERT(me == NULL);
- instance->owner = parent->owner;
- instance->parent = parent;
- /* in the devices instance list replace the parent instance with
- this one */
- instance->next = parent->next;
- /* replace parent with this new node */
- previous = &instance->owner->instances;
- while (*previous != parent) {
- ASSERT(*previous != NULL);
- previous = &(*previous)->next;
- }
- *previous = instance;
- }
- instance->data = data;
- instance->args = (args == NULL ? NULL : (char *) strdup(args));
- instance->path = (path == NULL ? NULL : (char *) strdup(path));
- instance->callback = callbacks;
- cap_add(instance->owner->ihandles, instance);
- return instance;
- }
- INLINE_DEVICE\
- (device_instance *)
- device_create_instance(device *me,
- const char *path,
- const char *args)
- {
- /* create the instance */
- if (me->callback->instance_create == NULL)
- device_error(me, "no instance_create method");
- return me->callback->instance_create(me, path, args);
- }
- STATIC_INLINE_DEVICE\
- (void)
- clean_device_instances(device *me)
- {
- device_instance **instance = &me->instances;
- while (*instance != NULL) {
- device_instance *old_instance = *instance;
- device_instance_delete(old_instance);
- instance = &me->instances;
- }
- }
- INLINE_DEVICE\
- (void)
- device_instance_delete(device_instance *instance)
- {
- device *me = instance->owner;
- if (instance->callback->delete == NULL)
- device_error(me, "no delete method");
- instance->callback->delete(instance);
- if (instance->args != NULL)
- free(instance->args);
- if (instance->path != NULL)
- free(instance->path);
- if (instance->child == NULL) {
- /* only remove leaf nodes */
- device_instance **curr = &me->instances;
- while (*curr != instance) {
- ASSERT(*curr != NULL);
- curr = &(*curr)->next;
- }
- *curr = instance->next;
- }
- else {
- /* check it isn't in the instance list */
- device_instance *curr = me->instances;
- while (curr != NULL) {
- ASSERT(curr != instance);
- curr = curr->next;
- }
- /* unlink the child */
- ASSERT(instance->child->parent == instance);
- instance->child->parent = NULL;
- }
- cap_remove(me->ihandles, instance);
- free(instance);
- }
- INLINE_DEVICE\
- (int)
- device_instance_read(device_instance *instance,
- void *addr,
- unsigned_word len)
- {
- device *me = instance->owner;
- if (instance->callback->read == NULL)
- device_error(me, "no read method");
- return instance->callback->read(instance, addr, len);
- }
- INLINE_DEVICE\
- (int)
- device_instance_write(device_instance *instance,
- const void *addr,
- unsigned_word len)
- {
- device *me = instance->owner;
- if (instance->callback->write == NULL)
- device_error(me, "no write method");
- return instance->callback->write(instance, addr, len);
- }
- INLINE_DEVICE\
- (int)
- device_instance_seek(device_instance *instance,
- unsigned_word pos_hi,
- unsigned_word pos_lo)
- {
- device *me = instance->owner;
- if (instance->callback->seek == NULL)
- device_error(me, "no seek method");
- return instance->callback->seek(instance, pos_hi, pos_lo);
- }
- INLINE_DEVICE\
- (int)
- device_instance_call_method(device_instance *instance,
- const char *method_name,
- int n_stack_args,
- unsigned_cell stack_args[/*n_stack_args*/],
- int n_stack_returns,
- unsigned_cell stack_returns[/*n_stack_args*/])
- {
- device *me = instance->owner;
- const device_instance_methods *method = instance->callback->methods;
- if (method == NULL) {
- device_error(me, "no methods (want %s)", method_name);
- }
- while (method->name != NULL) {
- if (strcmp(method->name, method_name) == 0) {
- return method->method(instance,
- n_stack_args, stack_args,
- n_stack_returns, stack_returns);
- }
- method++;
- }
- device_error(me, "no %s method", method_name);
- return 0;
- }
- INLINE_DEVICE\
- (device *)
- device_instance_device(device_instance *instance)
- {
- return instance->owner;
- }
- INLINE_DEVICE\
- (const char *)
- device_instance_path(device_instance *instance)
- {
- return instance->path;
- }
- INLINE_DEVICE\
- (void *)
- device_instance_data(device_instance *instance)
- {
- return instance->data;
- }
- /* Device Properties: */
- STATIC_INLINE_DEVICE\
- (device_property_entry *)
- find_property_entry(device *me,
- const char *property)
- {
- device_property_entry *entry;
- ASSERT(property != NULL);
- entry = me->properties;
- while (entry != NULL) {
- if (strcmp(entry->value->name, property) == 0)
- return entry;
- entry = entry->next;
- }
- return NULL;
- }
- STATIC_INLINE_DEVICE\
- (void)
- device_add_property(device *me,
- const char *property,
- device_property_type type,
- const void *init_array,
- unsigned sizeof_init_array,
- const void *array,
- unsigned sizeof_array,
- const device_property *original,
- object_disposition disposition)
- {
- device_property_entry *new_entry = NULL;
- device_property *new_value = NULL;
- /* find the list end */
- device_property_entry **insertion_point = &me->properties;
- while (*insertion_point != NULL) {
- if (strcmp((*insertion_point)->value->name, property) == 0)
- return;
- insertion_point = &(*insertion_point)->next;
- }
- /* create a new value */
- new_value = ZALLOC(device_property);
- new_value->name = (char *) strdup(property);
- new_value->type = type;
- if (sizeof_array > 0) {
- void *new_array = zalloc(sizeof_array);
- memcpy(new_array, array, sizeof_array);
- new_value->array = new_array;
- new_value->sizeof_array = sizeof_array;
- }
- new_value->owner = me;
- new_value->original = original;
- new_value->disposition = disposition;
- /* insert the value into the list */
- new_entry = ZALLOC(device_property_entry);
- *insertion_point = new_entry;
- if (sizeof_init_array > 0) {
- void *new_init_array = zalloc(sizeof_init_array);
- memcpy(new_init_array, init_array, sizeof_init_array);
- new_entry->init_array = new_init_array;
- new_entry->sizeof_init_array = sizeof_init_array;
- }
- new_entry->value = new_value;
- }
- /* local - not available externally */
- STATIC_INLINE_DEVICE\
- (void)
- device_set_property(device *me,
- const char *property,
- device_property_type type,
- const void *array,
- int sizeof_array)
- {
- /* find the property */
- device_property_entry *entry = find_property_entry(me, property);
- if (entry != NULL) {
- /* existing property - update it */
- void *new_array = 0;
- device_property *value = entry->value;
- /* check the type matches */
- if (value->type != type)
- device_error(me, "conflict between type of new and old value for property %s", property);
- /* replace its value */
- if (value->array != NULL)
- free((void*)value->array);
- new_array = (sizeof_array > 0
- ? zalloc(sizeof_array)
- : (void*)0);
- value->array = new_array;
- value->sizeof_array = sizeof_array;
- if (sizeof_array > 0)
- memcpy(new_array, array, sizeof_array);
- return;
- }
- else {
- /* new property - create it */
- device_add_property(me, property, type,
- NULL, 0, array, sizeof_array,
- NULL, tempoary_object);
- }
- }
- STATIC_INLINE_DEVICE\
- (void)
- clean_device_properties(device *me)
- {
- device_property_entry **delete_point = &me->properties;
- while (*delete_point != NULL) {
- device_property_entry *current = *delete_point;
- switch (current->value->disposition) {
- case permenant_object:
- /* zap the current value, will be initialized later */
- ASSERT(current->init_array != NULL);
- if (current->value->array != NULL) {
- free((void*)current->value->array);
- current->value->array = NULL;
- }
- delete_point = &(*delete_point)->next;
- break;
- case tempoary_object:
- /* zap the actual property, was created during simulation run */
- ASSERT(current->init_array == NULL);
- *delete_point = current->next;
- if (current->value->array != NULL)
- free((void*)current->value->array);
- free(current->value);
- free(current);
- break;
- }
- }
- }
- INLINE_DEVICE\
- (void)
- device_init_static_properties(device *me,
- void *data)
- {
- device_property_entry *property;
- for (property = me->properties;
- property != NULL;
- property = property->next) {
- ASSERT(property->init_array != NULL);
- ASSERT(property->value->array == NULL);
- ASSERT(property->value->disposition == permenant_object);
- switch (property->value->type) {
- case array_property:
- case boolean_property:
- case range_array_property:
- case reg_array_property:
- case string_property:
- case string_array_property:
- case integer_property:
- /* delete the property, and replace it with the original */
- device_set_property(me, property->value->name,
- property->value->type,
- property->init_array,
- property->sizeof_init_array);
- break;
- case ihandle_property:
- break;
- }
- }
- }
- INLINE_DEVICE\
- (void)
- device_init_runtime_properties(device *me,
- void *data)
- {
- device_property_entry *property;
- for (property = me->properties;
- property != NULL;
- property = property->next) {
- switch (property->value->disposition) {
- case permenant_object:
- switch (property->value->type) {
- case ihandle_property:
- {
- device_instance *ihandle;
- ihandle_runtime_property_spec spec;
- ASSERT(property->init_array != NULL);
- ASSERT(property->value->array == NULL);
- device_find_ihandle_runtime_property(me, property->value->name, &spec);
- ihandle = tree_instance(me, spec.full_path);
- device_set_ihandle_property(me, property->value->name, ihandle);
- break;
- }
- case array_property:
- case boolean_property:
- case range_array_property:
- case integer_property:
- case reg_array_property:
- case string_property:
- case string_array_property:
- ASSERT(property->init_array != NULL);
- ASSERT(property->value->array != NULL);
- break;
- }
- break;
- case tempoary_object:
- ASSERT(property->init_array == NULL);
- ASSERT(property->value->array != NULL);
- break;
- }
- }
- }
- INLINE_DEVICE\
- (const device_property *)
- device_next_property(const device_property *property)
- {
- /* find the property in the list */
- device *owner = property->owner;
- device_property_entry *entry = owner->properties;
- while (entry != NULL && entry->value != property)
- entry = entry->next;
- /* now return the following property */
- ASSERT(entry != NULL); /* must be a member! */
- if (entry->next != NULL)
- return entry->next->value;
- else
- return NULL;
- }
- INLINE_DEVICE\
- (const device_property *)
- device_find_property(device *me,
- const char *property)
- {
- if (me == NULL) {
- return NULL;
- }
- else if (property == NULL || strcmp(property, "") == 0) {
- if (me->properties == NULL)
- return NULL;
- else
- return me->properties->value;
- }
- else {
- device_property_entry *entry = find_property_entry(me, property);
- if (entry != NULL)
- return entry->value;
- }
- return NULL;
- }
- INLINE_DEVICE\
- (void)
- device_add_array_property(device *me,
- const char *property,
- const void *array,
- int sizeof_array)
- {
- device_add_property(me, property, array_property,
- array, sizeof_array, array, sizeof_array,
- NULL, permenant_object);
- }
- INLINE_DEVICE\
- (void)
- device_set_array_property(device *me,
- const char *property,
- const void *array,
- int sizeof_array)
- {
- device_set_property(me, property, array_property, array, sizeof_array);
- }
- INLINE_DEVICE\
- (const device_property *)
- device_find_array_property(device *me,
- const char *property)
- {
- const device_property *node;
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != array_property)
- device_error(me, "property %s not found or of wrong type", property);
- return node;
- }
- INLINE_DEVICE\
- (void)
- device_add_boolean_property(device *me,
- const char *property,
- int boolean)
- {
- signed32 new_boolean = (boolean ? -1 : 0);
- device_add_property(me, property, boolean_property,
- &new_boolean, sizeof(new_boolean),
- &new_boolean, sizeof(new_boolean),
- NULL, permenant_object);
- }
- INLINE_DEVICE\
- (int)
- device_find_boolean_property(device *me,
- const char *property)
- {
- const device_property *node;
- unsigned_cell boolean;
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != boolean_property)
- device_error(me, "property %s not found or of wrong type", property);
- ASSERT(sizeof(boolean) == node->sizeof_array);
- memcpy(&boolean, node->array, sizeof(boolean));
- return boolean;
- }
- INLINE_DEVICE\
- (void)
- device_add_ihandle_runtime_property(device *me,
- const char *property,
- const ihandle_runtime_property_spec *ihandle)
- {
- /* enter the full path as the init array */
- device_add_property(me, property, ihandle_property,
- ihandle->full_path, strlen(ihandle->full_path) + 1,
- NULL, 0,
- NULL, permenant_object);
- }
- INLINE_DEVICE\
- (void)
- device_find_ihandle_runtime_property(device *me,
- const char *property,
- ihandle_runtime_property_spec *ihandle)
- {
- device_property_entry *entry = find_property_entry(me, property);
- TRACE(trace_devices,
- ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
- (long)me, property));
- if (entry == NULL
- || entry->value->type != ihandle_property
- || entry->value->disposition != permenant_object)
- device_error(me, "property %s not found or of wrong type", property);
- ASSERT(entry->init_array != NULL);
- /* the full path */
- ihandle->full_path = entry->init_array;
- }
- INLINE_DEVICE\
- (void)
- device_set_ihandle_property(device *me,
- const char *property,
- device_instance *ihandle)
- {
- unsigned_cell cells;
- cells = H2BE_cell(device_instance_to_external(ihandle));
- device_set_property(me, property, ihandle_property,
- &cells, sizeof(cells));
-
- }
- INLINE_DEVICE\
- (device_instance *)
- device_find_ihandle_property(device *me,
- const char *property)
- {
- const device_property *node;
- unsigned_cell ihandle;
- device_instance *instance;
- node = device_find_property(me, property);
- if (node == NULL || node->type != ihandle_property)
- device_error(me, "property %s not found or of wrong type", property);
- if (node->array == NULL)
- device_error(me, "runtime property %s not yet initialized", property);
- ASSERT(sizeof(ihandle) == node->sizeof_array);
- memcpy(&ihandle, node->array, sizeof(ihandle));
- instance = external_to_device_instance(me, BE2H_cell(ihandle));
- ASSERT(instance != NULL);
- return instance;
- }
- INLINE_DEVICE\
- (void)
- device_add_integer_property(device *me,
- const char *property,
- signed_cell integer)
- {
- H2BE(integer);
- device_add_property(me, property, integer_property,
- &integer, sizeof(integer),
- &integer, sizeof(integer),
- NULL, permenant_object);
- }
- INLINE_DEVICE\
- (signed_cell)
- device_find_integer_property(device *me,
- const char *property)
- {
- const device_property *node;
- signed_cell integer;
- TRACE(trace_devices,
- ("device_find_integer(me=0x%lx, property=%s)\n",
- (long)me, property));
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != integer_property)
- device_error(me, "property %s not found or of wrong type", property);
- ASSERT(sizeof(integer) == node->sizeof_array);
- memcpy(&integer, node->array, sizeof(integer));
- return BE2H_cell(integer);
- }
- INLINE_DEVICE\
- (int)
- device_find_integer_array_property(device *me,
- const char *property,
- unsigned index,
- signed_cell *integer)
- {
- const device_property *node;
- int sizeof_integer = sizeof(*integer);
- signed_cell *cell;
- TRACE(trace_devices,
- ("device_find_integer(me=0x%lx, property=%s)\n",
- (long)me, property));
- /* check things sane */
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || (node->type != integer_property
- && node->type != array_property))
- device_error(me, "property %s not found or of wrong type", property);
- if ((node->sizeof_array % sizeof_integer) != 0)
- device_error(me, "property %s contains an incomplete number of cells", property);
- if (node->sizeof_array <= sizeof_integer * index)
- return 0;
- /* Find and convert the value */
- cell = ((signed_cell*)node->array) + index;
- *integer = BE2H_cell(*cell);
- return node->sizeof_array / sizeof_integer;
- }
- STATIC_INLINE_DEVICE\
- (unsigned_cell *)
- unit_address_to_cells(const device_unit *unit,
- unsigned_cell *cell,
- int nr_cells)
- {
- int i;
- ASSERT(nr_cells == unit->nr_cells);
- for (i = 0; i < unit->nr_cells; i++) {
- *cell = H2BE_cell(unit->cells[i]);
- cell += 1;
- }
- return cell;
- }
- STATIC_INLINE_DEVICE\
- (const unsigned_cell *)
- cells_to_unit_address(const unsigned_cell *cell,
- device_unit *unit,
- int nr_cells)
- {
- int i;
- memset(unit, 0, sizeof(*unit));
- unit->nr_cells = nr_cells;
- for (i = 0; i < unit->nr_cells; i++) {
- unit->cells[i] = BE2H_cell(*cell);
- cell += 1;
- }
- return cell;
- }
- STATIC_INLINE_DEVICE\
- (unsigned)
- nr_range_property_cells(device *me,
- int nr_ranges)
- {
- return ((device_nr_address_cells(me)
- + device_nr_address_cells(device_parent(me))
- + device_nr_size_cells(me))
- ) * nr_ranges;
- }
- INLINE_DEVICE\
- (void)
- device_add_range_array_property(device *me,
- const char *property,
- const range_property_spec *ranges,
- unsigned nr_ranges)
- {
- unsigned sizeof_cells = (nr_range_property_cells(me, nr_ranges)
- * sizeof(unsigned_cell));
- unsigned_cell *cells = zalloc(sizeof_cells);
- unsigned_cell *cell;
- int i;
- /* copy the property elements over */
- cell = cells;
- for (i = 0; i < nr_ranges; i++) {
- const range_property_spec *range = &ranges[i];
- /* copy the child address */
- cell = unit_address_to_cells(&range->child_address, cell,
- device_nr_address_cells(me));
- /* copy the parent address */
- cell = unit_address_to_cells(&range->parent_address, cell,
- device_nr_address_cells(device_parent(me)));
- /* copy the size */
- cell = unit_address_to_cells(&range->size, cell,
- device_nr_size_cells(me));
- }
- ASSERT(cell == &cells[nr_range_property_cells(me, nr_ranges)]);
- /* add it */
- device_add_property(me, property, range_array_property,
- cells, sizeof_cells,
- cells, sizeof_cells,
- NULL, permenant_object);
- free(cells);
- }
- INLINE_DEVICE\
- (int)
- device_find_range_array_property(device *me,
- const char *property,
- unsigned index,
- range_property_spec *range)
- {
- const device_property *node;
- unsigned sizeof_entry = (nr_range_property_cells(me, 1)
- * sizeof(unsigned_cell));
- const unsigned_cell *cells;
- /* locate the property */
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != range_array_property)
- device_error(me, "property %s not found or of wrong type", property);
- /* aligned ? */
- if ((node->sizeof_array % sizeof_entry) != 0)
- device_error(me, "property %s contains an incomplete number of entries",
- property);
- /* within bounds? */
- if (node->sizeof_array < sizeof_entry * (index + 1))
- return 0;
- /* find the range of interest */
- cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
- /* copy the child address out - converting as we go */
- cells = cells_to_unit_address(cells, &range->child_address,
- device_nr_address_cells(me));
- /* copy the parent address out - converting as we go */
- cells = cells_to_unit_address(cells, &range->parent_address,
- device_nr_address_cells(device_parent(me)));
- /* copy the size - converting as we go */
- cells = cells_to_unit_address(cells, &range->size,
- device_nr_size_cells(me));
- return node->sizeof_array / sizeof_entry;
- }
- STATIC_INLINE_DEVICE\
- (unsigned)
- nr_reg_property_cells(device *me,
- int nr_regs)
- {
- return (device_nr_address_cells(device_parent(me))
- + device_nr_size_cells(device_parent(me))
- ) * nr_regs;
- }
- INLINE_DEVICE\
- (void)
- device_add_reg_array_property(device *me,
- const char *property,
- const reg_property_spec *regs,
- unsigned nr_regs)
- {
- unsigned sizeof_cells = (nr_reg_property_cells(me, nr_regs)
- * sizeof(unsigned_cell));
- unsigned_cell *cells = zalloc(sizeof_cells);
- unsigned_cell *cell;
- int i;
- /* copy the property elements over */
- cell = cells;
- for (i = 0; i < nr_regs; i++) {
- const reg_property_spec *reg = ®s[i];
- /* copy the address */
- cell = unit_address_to_cells(®->address, cell,
- device_nr_address_cells(device_parent(me)));
- /* copy the size */
- cell = unit_address_to_cells(®->size, cell,
- device_nr_size_cells(device_parent(me)));
- }
- ASSERT(cell == &cells[nr_reg_property_cells(me, nr_regs)]);
- /* add it */
- device_add_property(me, property, reg_array_property,
- cells, sizeof_cells,
- cells, sizeof_cells,
- NULL, permenant_object);
- free(cells);
- }
- INLINE_DEVICE\
- (int)
- device_find_reg_array_property(device *me,
- const char *property,
- unsigned index,
- reg_property_spec *reg)
- {
- const device_property *node;
- unsigned sizeof_entry = (nr_reg_property_cells(me, 1)
- * sizeof(unsigned_cell));
- const unsigned_cell *cells;
- /* locate the property */
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != reg_array_property)
- device_error(me, "property %s not found or of wrong type", property);
- /* aligned ? */
- if ((node->sizeof_array % sizeof_entry) != 0)
- device_error(me, "property %s contains an incomplete number of entries",
- property);
- /* within bounds? */
- if (node->sizeof_array < sizeof_entry * (index + 1))
- return 0;
- /* find the range of interest */
- cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
- /* copy the address out - converting as we go */
- cells = cells_to_unit_address(cells, ®->address,
- device_nr_address_cells(device_parent(me)));
- /* copy the size out - converting as we go */
- cells = cells_to_unit_address(cells, ®->size,
- device_nr_size_cells(device_parent(me)));
- return node->sizeof_array / sizeof_entry;
- }
- INLINE_DEVICE\
- (void)
- device_add_string_property(device *me,
- const char *property,
- const char *string)
- {
- device_add_property(me, property, string_property,
- string, strlen(string) + 1,
- string, strlen(string) + 1,
- NULL, permenant_object);
- }
- INLINE_DEVICE\
- (const char *)
- device_find_string_property(device *me,
- const char *property)
- {
- const device_property *node;
- const char *string;
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != string_property)
- device_error(me, "property %s not found or of wrong type", property);
- string = node->array;
- ASSERT(strlen(string) + 1 == node->sizeof_array);
- return string;
- }
- INLINE_DEVICE\
- (void)
- device_add_string_array_property(device *me,
- const char *property,
- const string_property_spec *strings,
- unsigned nr_strings)
- {
- int sizeof_array;
- int string_nr;
- char *array;
- char *chp;
- if (nr_strings == 0)
- device_error(me, "property %s must be non-null", property);
- /* total up the size of the needed array */
- for (sizeof_array = 0, string_nr = 0;
- string_nr < nr_strings;
- string_nr ++) {
- sizeof_array += strlen(strings[string_nr]) + 1;
- }
- /* create the array */
- array = (char*)zalloc(sizeof_array);
- chp = array;
- for (string_nr = 0;
- string_nr < nr_strings;
- string_nr++) {
- strcpy(chp, strings[string_nr]);
- chp += strlen(chp) + 1;
- }
- ASSERT(chp == array + sizeof_array);
- /* now enter it */
- device_add_property(me, property, string_array_property,
- array, sizeof_array,
- array, sizeof_array,
- NULL, permenant_object);
- }
- INLINE_DEVICE\
- (int)
- device_find_string_array_property(device *me,
- const char *property,
- unsigned index,
- string_property_spec *string)
- {
- const device_property *node;
- node = device_find_property(me, property);
- if (node == (device_property*)0)
- device_error(me, "property %s not found", property);
- switch (node->type) {
- default:
- device_error(me, "property %s of wrong type", property);
- break;
- case string_property:
- if (index == 0) {
- *string = node->array;
- ASSERT(strlen(*string) + 1 == node->sizeof_array);
- return 1;
- }
- break;
- case array_property:
- if (node->sizeof_array == 0
- || ((char*)node->array)[node->sizeof_array - 1] != '\0')
- device_error(me, "property %s invalid for string array", property);
- /* FALL THROUGH */
- case string_array_property:
- ASSERT(node->sizeof_array > 0);
- ASSERT(((char*)node->array)[node->sizeof_array - 1] == '\0');
- {
- const char *chp = node->array;
- int nr_entries = 0;
- /* count the number of strings, keeping an eye out for the one
- we're looking for */
- *string = chp;
- do {
- if (*chp == '\0') {
- /* next string */
- nr_entries++;
- chp++;
- if (nr_entries == index)
- *string = chp;
- }
- else {
- chp++;
- }
- } while (chp < (char*)node->array + node->sizeof_array);
- if (index < nr_entries)
- return nr_entries;
- else {
- *string = NULL;
- return 0;
- }
- }
- break;
- }
- return 0;
- }
- INLINE_DEVICE\
- (void)
- device_add_duplicate_property(device *me,
- const char *property,
- const device_property *original)
- {
- device_property_entry *master;
- TRACE(trace_devices,
- ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
- (long)me, property));
- if (original->disposition != permenant_object)
- device_error(me, "Can only duplicate permenant objects");
- /* find the original's master */
- master = original->owner->properties;
- while (master->value != original) {
- master = master->next;
- ASSERT(master != NULL);
- }
- /* now duplicate it */
- device_add_property(me, property,
- original->type,
- master->init_array, master->sizeof_init_array,
- original->array, original->sizeof_array,
- original, permenant_object);
- }
- /* Device Hardware: */
- INLINE_DEVICE\
- (unsigned)
- device_io_read_buffer(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
- {
- if (me->callback->io.read_buffer == NULL)
- device_error(me, "no io.read_buffer method");
- return me->callback->io.read_buffer(me, dest, space,
- addr, nr_bytes,
- processor, cia);
- }
- INLINE_DEVICE\
- (unsigned)
- device_io_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
- {
- if (me->callback->io.write_buffer == NULL)
- device_error(me, "no io.write_buffer method");
- return me->callback->io.write_buffer(me, source, space,
- addr, nr_bytes,
- processor, cia);
- }
- INLINE_DEVICE\
- (unsigned)
- device_dma_read_buffer(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
- {
- if (me->callback->dma.read_buffer == NULL)
- device_error(me, "no dma.read_buffer method");
- return me->callback->dma.read_buffer(me, dest, space,
- addr, nr_bytes);
- }
- INLINE_DEVICE\
- (unsigned)
- device_dma_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section)
- {
- if (me->callback->dma.write_buffer == NULL)
- device_error(me, "no dma.write_buffer method");
- return me->callback->dma.write_buffer(me, source, space,
- addr, nr_bytes,
- violate_read_only_section);
- }
- INLINE_DEVICE\
- (void)
- device_attach_address(device *me,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *client) /*callback/default*/
- {
- if (me->callback->address.attach == NULL)
- device_error(me, "no address.attach method");
- me->callback->address.attach(me, attach, space,
- addr, nr_bytes, access, client);
- }
- INLINE_DEVICE\
- (void)
- device_detach_address(device *me,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *client) /*callback/default*/
- {
- if (me->callback->address.detach == NULL)
- device_error(me, "no address.detach method");
- me->callback->address.detach(me, attach, space,
- addr, nr_bytes, access, client);
- }
- /* Interrupts: */
- INLINE_DEVICE(void)
- device_interrupt_event(device *me,
- int my_port,
- int level,
- cpu *processor,
- unsigned_word cia)
- {
- int found_an_edge = 0;
- device_interrupt_edge *edge;
- /* device's interrupt lines directly connected */
- for (edge = me->interrupt_destinations;
- edge != NULL;
- edge = edge->next) {
- if (edge->my_port == my_port) {
- if (edge->dest->callback->interrupt.event == NULL)
- device_error(me, "no interrupt method");
- edge->dest->callback->interrupt.event(edge->dest,
- edge->dest_port,
- me,
- my_port,
- level,
- processor, cia);
- found_an_edge = 1;
- }
- }
- if (!found_an_edge) {
- device_error(me, "No interrupt edge for port %d", my_port);
- }
- }
- INLINE_DEVICE\
- (void)
- device_interrupt_attach(device *me,
- int my_port,
- device *dest,
- int dest_port,
- object_disposition disposition)
- {
- attach_device_interrupt_edge(&me->interrupt_destinations,
- my_port,
- dest,
- dest_port,
- disposition);
- }
- INLINE_DEVICE\
- (void)
- device_interrupt_detach(device *me,
- int my_port,
- device *dest,
- int dest_port)
- {
- detach_device_interrupt_edge(me,
- &me->interrupt_destinations,
- my_port,
- dest,
- dest_port);
- }
- INLINE_DEVICE\
- (void)
- device_interrupt_traverse(device *me,
- device_interrupt_traverse_function *handler,
- void *data)
- {
- device_interrupt_edge *interrupt_edge;
- for (interrupt_edge = me->interrupt_destinations;
- interrupt_edge != NULL;
- interrupt_edge = interrupt_edge->next) {
- handler(me, interrupt_edge->my_port,
- interrupt_edge->dest, interrupt_edge->dest_port,
- data);
- }
- }
- INLINE_DEVICE\
- (int)
- device_interrupt_decode(device *me,
- const char *port_name,
- port_direction direction)
- {
- if (port_name == NULL || port_name[0] == '\0')
- return 0;
- if (isdigit(port_name[0])) {
- return strtoul(port_name, NULL, 0);
- }
- else {
- const device_interrupt_port_descriptor *ports =
- me->callback->interrupt.ports;
- if (ports != NULL) {
- while (ports->name != NULL) {
- if (ports->direction == bidirect_port
- || ports->direction == direction) {
- if (ports->nr_ports > 0) {
- int len = strlen(ports->name);
- if (strncmp(port_name, ports->name, len) == 0) {
- if (port_name[len] == '\0')
- return ports->number;
- else if(isdigit(port_name[len])) {
- int port = ports->number + strtoul(&port_name[len], NULL, 0);
- if (port >= ports->number + ports->nr_ports)
- device_error(me, "Interrupt port %s out of range",
- port_name);
- return port;
- }
- }
- }
- else if (strcmp(port_name, ports->name) == 0)
- return ports->number;
- }
- ports++;
- }
- }
- }
- device_error(me, "Unreconized interrupt port %s", port_name);
- return 0;
- }
- INLINE_DEVICE\
- (int)
- device_interrupt_encode(device *me,
- int port_number,
- char *buf,
- int sizeof_buf,
- port_direction direction)
- {
- const device_interrupt_port_descriptor *ports = NULL;
- ports = me->callback->interrupt.ports;
- if (ports != NULL) {
- while (ports->name != NULL) {
- if (ports->direction == bidirect_port
- || ports->direction == direction) {
- if (ports->nr_ports > 0) {
- if (port_number >= ports->number
- && port_number < ports->number + ports->nr_ports) {
- strcpy(buf, ports->name);
- sprintf(buf + strlen(buf), "%d", port_number - ports->number);
- if (strlen(buf) >= sizeof_buf)
- error("device_interrupt_encode: buffer overflow");
- return strlen(buf);
- }
- }
- else {
- if (ports->number == port_number) {
- if (strlen(ports->name) >= sizeof_buf)
- error("device_interrupt_encode: buffer overflow");
- strcpy(buf, ports->name);
- return strlen(buf);
- }
- }
- }
- ports++;
- }
- }
- sprintf(buf, "%d", port_number);
- if (strlen(buf) >= sizeof_buf)
- error("device_interrupt_encode: buffer overflow");
- return strlen(buf);
- }
- /* IOCTL: */
- EXTERN_DEVICE\
- (int)
- device_ioctl(device *me,
- cpu *processor,
- unsigned_word cia,
- device_ioctl_request request,
- ...)
- {
- int status;
- va_list ap;
- va_start(ap, request);
- if (me->callback->ioctl == NULL)
- device_error(me, "no ioctl method");
- status = me->callback->ioctl(me, processor, cia, request, ap);
- va_end(ap);
- return status;
- }
-
- /* I/O */
- EXTERN_DEVICE\
- (void)
- device_error(device *me,
- const char *fmt,
- ...)
- {
- char message[1024];
- va_list ap;
- /* format the message */
- va_start(ap, fmt);
- vsprintf(message, fmt, ap);
- va_end(ap);
- /* sanity check */
- if (strlen(message) >= sizeof(message))
- error("device_error: buffer overflow");
- if (me == NULL)
- error("device: %s", message);
- else if (me->path != NULL && me->path[0] != '\0')
- error("%s: %s", me->path, message);
- else if (me->name != NULL && me->name[0] != '\0')
- error("%s: %s", me->name, message);
- else
- error("device: %s", message);
- while(1);
- }
- INLINE_DEVICE\
- (int)
- device_trace(device *me)
- {
- return me->trace;
- }
- /* External representation */
- INLINE_DEVICE\
- (device *)
- external_to_device(device *tree_member,
- unsigned_cell phandle)
- {
- device *me = cap_internal(tree_member->phandles, phandle);
- return me;
- }
- INLINE_DEVICE\
- (unsigned_cell)
- device_to_external(device *me)
- {
- unsigned_cell phandle = cap_external(me->phandles, me);
- return phandle;
- }
- INLINE_DEVICE\
- (device_instance *)
- external_to_device_instance(device *tree_member,
- unsigned_cell ihandle)
- {
- device_instance *instance = cap_internal(tree_member->ihandles, ihandle);
- return instance;
- }
- INLINE_DEVICE\
- (unsigned_cell)
- device_instance_to_external(device_instance *instance)
- {
- unsigned_cell ihandle = cap_external(instance->owner->ihandles, instance);
- return ihandle;
- }
- /* Map onto the event functions */
- INLINE_DEVICE\
- (event_entry_tag)
- device_event_queue_schedule(device *me,
- signed64 delta_time,
- device_event_handler *handler,
- void *data)
- {
- return event_queue_schedule(psim_event_queue(me->system),
- delta_time,
- handler,
- data);
- }
- INLINE_DEVICE\
- (void)
- device_event_queue_deschedule(device *me,
- event_entry_tag event_to_remove)
- {
- event_queue_deschedule(psim_event_queue(me->system),
- event_to_remove);
- }
- INLINE_DEVICE\
- (signed64)
- device_event_queue_time(device *me)
- {
- return event_queue_time(psim_event_queue(me->system));
- }
- /* Initialization: */
- INLINE_DEVICE\
- (void)
- device_clean(device *me,
- void *data)
- {
- psim *system;
- system = (psim*)data;
- TRACE(trace_device_init, ("device_clean - initializing %s", me->path));
- clean_device_interrupt_edges(&me->interrupt_destinations);
- clean_device_instances(me);
- clean_device_properties(me);
- }
- /* Device initialization: */
- INLINE_DEVICE\
- (void)
- device_init_address(device *me,
- void *data)
- {
- psim *system = (psim*)data;
- int nr_address_cells;
- int nr_size_cells;
- TRACE(trace_device_init, ("device_init_address - initializing %s", me->path));
- /* ensure the cap database is valid */
- if (me->parent == NULL) {
- cap_init(me->ihandles);
- cap_init(me->phandles);
- }
- /* some basics */
- me->system = system; /* misc things not known until now */
- me->trace = (device_find_property(me, "trace")
- ? device_find_integer_property(me, "trace")
- : 0);
- /* Ensure that the first address found in the reg property matches
- anything that was specified as part of the devices name */
- if (device_find_property(me, "reg") != NULL) {
- reg_property_spec unit;
- device_find_reg_array_property(me, "reg", 0, &unit);
- if (memcmp(device_unit_address(me), &unit.address, sizeof(unit.address))
- != 0)
- device_error(me, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
- }
- /* ensure that the devices #address/size-cells is consistent */
- nr_address_cells = device_nr_address_cells(me);
- if (device_find_property(me, "#address-cells") != NULL
- && (nr_address_cells
- != device_find_integer_property(me, "#address-cells")))
- device_error(me, "#address-cells property used before defined");
- nr_size_cells = device_nr_size_cells(me);
- if (device_find_property(me, "#size-cells") != NULL
- && (nr_size_cells
- != device_find_integer_property(me, "#size-cells")))
- device_error(me, "#size-cells property used before defined");
- /* now init it */
- if (me->callback->init.address != NULL)
- me->callback->init.address(me);
- }
- INLINE_DEVICE\
- (void)
- device_init_data(device *me,
- void *data)
- {
- TRACE(trace_device_init, ("device_init_data - initializing %s", me->path));
- if (me->callback->init.data != NULL)
- me->callback->init.data(me);
- }
- #endif /* _DEVICE_C_ */
|