#include #include #include #include "fddi.h" #define MAX_IO_INTERFACES 16 #define MAX_IO_INTERFACE_INSTS 64 /* managment of io-interfaces */ static int num_of_interfaces = 0; static IO_INTERFACE io_interfaces[MAX_IO_INTERFACES]; static int num_of_interface_instances = 0; static IO_INTERFACE_INST io_interface_instances[MAX_IO_INTERFACE_INSTS]; int register_io_interface(IO_INTERFACE ioitf) { if (num_of_interfaces >= MAX_IO_INTERFACES) return RESERR_OUT_OF_MEM; io_interfaces[num_of_interfaces++] = ioitf; return RESOK; } int bind_io_interface(IO_INTERFACE ioitf, char* name, LL_INTERFACE llitf, IO_INTERFACE_INST* res) { int ret; if (num_of_interface_instances >= MAX_IO_INTERFACE_INSTS) return RESERR_OUT_OF_MEM; /* call to function pointer from registered io-interface */ ret = (*ioitf->_fptr_bind_io_interface)(name, llitf, res); if (ret == RESOK) io_interface_instances[num_of_interface_instances++] = *res; return ret; } int enum_io_interfaces(IO_INTERFACE** ioitfs) { *ioitfs = io_interfaces; return num_of_interfaces; } int enum_io_interface_instances(IO_INTERFACE_INST** ioitfinsts) { *ioitfinsts = io_interface_instances; return num_of_interface_instances; } IO_INTERFACE get_io_interface(char* name) { int i; for (i = 0; i < num_of_interfaces; i++) if (strcmp(name, io_interfaces[i]->name) == 0) return io_interfaces[i]; return NULL; } IO_INTERFACE_INST get_io_interface_inst(char* name) { int i; for (i = 0; i < num_of_interface_instances; i++) if (strcmp(name, io_interface_instances[i]->name) == 0) return io_interface_instances[i]; return NULL; } int enum_io_transport_units(IO_INTERFACE_INST ioitfinst, IO_TRANSPORT_UNIT** iotpus) { *iotpus = ioitfinst->tpus; return ioitfinst->num_tpus; } int enum_io_devices(IO_INTERFACE_INST ioitfinst, IO_DEVICE** iodevices) { *iodevices = ioitfinst->devlist; return ioitfinst->num_dev; } int enum_io_variables(IO_INTERFACE_INST ioitfinst, IO_VARIABLE** iovars) { *iovars = ioitfinst->varlist; return ioitfinst->num_var; } static int count_devices(IO_DEVICE io_device) { int n_dev; IO_DEVICE dev_child; if (io_device == NULL) return 0; n_dev = 1; // the device itself dev_child = io_device->first_child; while (dev_child != NULL) { n_dev += count_devices(dev_child); dev_child = dev_child->next_child; } return n_dev; } static IO_DEVICE* fill_devices(IO_DEVICE dev, IO_DEVICE* devlist) /* return adress to continue. devlist must be large enough */ { IO_DEVICE* list = devlist; IO_DEVICE dev_child; *list = dev; list++; dev_child = dev->first_child; while (dev_child != NULL) { list = fill_devices(dev_child, list); dev_child = dev_child->next_child; } return list; } int configure_io_interface_inst(IO_INTERFACE_INST ioitfinst, IO_DEVICE root) { int ret; /* call to function pointer from registered io-interface */ ret = (*ioitfinst->ioitf->_fptr_configure_io_interface_inst)(ioitfinst, root); if (ret == RESOK) { int i; IO_VARIABLE* list; /* the configure method fills the tpu-list */ /* the other lists are filled by the fddi interface in this function */ /* fill device list */ ioitfinst->num_dev = count_devices(root); ioitfinst->devlist = malloc(ioitfinst->num_dev * sizeof(IO_DEVICE)); fill_devices(root, ioitfinst->devlist); /* fill variable list */ ioitfinst->num_var = 0; for (i = 0; i < ioitfinst->num_tpus; i++) ioitfinst->num_var += ioitfinst->tpus[i]->num_var; ioitfinst->varlist = malloc(ioitfinst->num_var * sizeof(IO_VARIABLE)); list = ioitfinst->varlist; for (i = 0; i < ioitfinst->num_tpus; i++) { memcpy(list, ioitfinst->tpus[i]->varlist, ioitfinst->tpus[i]->num_var * sizeof(IO_VARIABLE)); list += ioitfinst->tpus[i]->num_var; } } return ret; } int scan_io_interface_inst(IO_INTERFACE_INST ioitfinst, IO_DEVICE *root) { int ret; /* call to function pointer from registered io-interface */ ret = (*ioitfinst->ioitf->_fptr_scan_io_interface_inst)(ioitfinst, root); return ret; } int read_iodevice_async(IO_DEVICE iodev, unsigned long address, unsigned char* buf, unsigned long buf_size, unsigned long* read_size) { int ret; /* call to function pointer from registered io-interface */ ret = (*iodev->itfinst->ioitf->_fptr_read_device_async)(iodev, address, buf, buf_size, read_size); return ret; } int write_iodevice_async(IO_DEVICE iodev, unsigned long address, unsigned char* buf, unsigned long size) { int ret; /* call to function pointer from registered io-interface */ ret = (*iodev->itfinst->ioitf->_fptr_write_device_async)(iodev, address, buf, size); return ret; } int cmd_iodevice(IO_DEVICE iodev, IO_DEVICE_COMMAND cmd) { int ret; /* call to function pointer from registered io-interface */ ret = (*iodev->itfinst->ioitf->_fptr_cmd_device)(iodev, cmd); return ret; } int enum_io_variables_of_iodevice(IO_DEVICE iodev, IO_VARIABLE** iovars) { // todo return 0; } /* A very simple implementation of transport units with a lot of improvement possibilities */ /* While anyone is reading the buffer all write operations are done in a extra buffer to keep the read buffer consistent */ unsigned char* address_to_read(IO_TRANSPORT_UNIT iotpu) { iotpu->read_count++; return iotpu->buf_read; } unsigned char* address_to_write(IO_TRANSPORT_UNIT iotpu) { if (iotpu->write_count != 0) return NULL; iotpu->write_count++; if (iotpu->buf_read == iotpu->buf_write) { iotpu->buf_write = malloc(iotpu->size); memcpy(iotpu->buf_write, iotpu->buf_read, iotpu->size); } return iotpu->buf_write; } unsigned char* address_to_replace(IO_TRANSPORT_UNIT iotpu) { if (iotpu->write_count != 0) return NULL; iotpu->write_count++; if (iotpu->buf_read == iotpu->buf_write) iotpu->buf_write = malloc(iotpu->size); return iotpu->buf_write; } int release_adress(IO_TRANSPORT_UNIT iotpu, unsigned char* address) { if (address == iotpu->buf_read) { iotpu->read_count--; /* assert iotpu->read_count >= 0 */ if (iotpu->read_count == 0 && iotpu->write_count == 0 && iotpu->buf_read != iotpu->buf_write) { free(iotpu->buf_read); iotpu->buf_read = iotpu->buf_write; } return RESOK; } else if (address == iotpu->buf_write) { int i; iotpu->write_count--; /* assert iotpu->write_count >= 0 */ if (iotpu->read_count == 0 && iotpu->write_count == 0 && iotpu->buf_read != iotpu->buf_write) { free(iotpu->buf_read); iotpu->buf_read = iotpu->buf_write; } /* trigger callbacks */ for (i = 0; i < iotpu->num_callbacks; i++) (*iotpu->callback[i])(iotpu); return RESOK; } return RESERR_UNKOWNADDRESS; } int send_iotransport_unit(IO_TRANSPORT_UNIT iotpu) { int res = 0; /* pseudo code, because low level interface is not ready */ /* may be redirected trough stack */ /* res = iotpu->itfinst->llitf->Send(iotpu->id, iotpu->buf_write, iotpu->size); */ return 0; } int register_callback_to_iotransport_unit(IO_TRANSPORT_UNIT iotpu, void (*callback)(IO_TRANSPORT_UNIT iotpu)) { if (iotpu->num_callbacks >= MAXCALLBACKS) return RESERR_OUT_OF_MEM; iotpu->callback[iotpu->num_callbacks] = callback; iotpu->num_callbacks++; return RESOK; } int enum_io_variables_of_iotransport_unit(IO_TRANSPORT_UNIT iotpu, IO_VARIABLE** iovars) { *iovars = iotpu->varlist; return iotpu->num_var; }