📄 device.c
字号:
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 volatile)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_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -