/* * ======== tskMkPort ======== * Creates a DIO object and binds the controller. */ static DIO_Handle tskMkPort(DEV_Handle device, String name) { DIO_Params *params = (DIO_Params *)device->params; DIO_Handle dio; DEV_Device *entry; Uns mode; Int status; /* params should contain name of mini-driver */ if (params == NULL) { return (NULL); } /* * check to see that name of mini-driver matches one in the device table * and its type is of DEV_IOMTYPE. */ (void)DEV_match(params->name, &entry); if (entry == NULL || entry->type != DEV_IOMTYPE) { return (NULL); } /* allocate 0-initialized dio object */ if ((dio = MEM_calloc(0, sizeof(DIO_Obj), 0)) == MEM_ILLEGAL) { return (NULL); } /* * Tasks will pend on dio->complete if there are no available frames on * the fromdevice queue. */ dio->context.sems.complete = SEM_create(0, NULL); /* make sure SEM_create() succeeded ... */ if (dio->context.sems.complete == NULL) { MEM_free(0, dio, sizeof(DIO_Obj)); /* free dio object */ return (NULL); } dio->fxns = (IOM_Fxns *)entry->fxns; mode = (device->mode == DEV_INPUT) ? IOM_INPUT : IOM_OUTPUT; /* create a channel from the mini-driver */ status = dio->fxns->mdCreateChan(&dio->chanp, entry->devp, name, mode, params->chanParams, DIO_tskCallback, device); if (status != IOM_COMPLETED) { tskRmPort(dio); return (NULL); } return (dio); }
/* * ======== cbMkPort ======== * Creates a DIO object and binds the controller. */ static DIO_Handle cbMkPort(DEV_Handle device, String name) { DIO_Params *params = (DIO_Params *)device->params; DEV_Callback *callback = (DEV_Callback *)device->callback; DIO_Handle dio; DEV_Device *entry; Uns mode; Int status; /* callback must not be NULL if using this version of DIO */ if (callback == NULL) { return (NULL); } /* params must contain name of mini-driver */ if (params == NULL) { return (NULL); } /* * check to see that name of mini-driver matches one in the device table * and its type is of DEV_IOMTYPE. */ (void)DEV_match(params->name, &entry); if (entry == NULL || entry->type != DEV_IOMTYPE) { return (NULL); } /* allocate 0-initialized dio object */ if ((dio = MEM_calloc(0, sizeof(DIO_Obj), 0)) == MEM_ILLEGAL) { return (NULL); } /* initialize the DIO callback values */ dio->context.cb = *callback; dio->fxns = (IOM_Fxns *)entry->fxns; mode = (device->mode == DEV_INPUT) ? IOM_INPUT : IOM_OUTPUT; /* create a channel from the mini-driver */ status = dio->fxns->mdCreateChan(&dio->chanp, entry->devp, name, mode, params->chanParams, DIO_cbCallback, device); if (status != IOM_COMPLETED) { cbRmPort(dio); return (NULL); } return (dio); }
/* * ======== GIO_removeDevice ======== */ Int GIO_removeDevice(String name) { DEV_Handle device; DEV_match(name, &device); if (device != NULL) { DEV_delete(&device); return (IOM_COMPLETED); } else { return (IOM_EBADIO); } }
/* * ======== GIO_Instance_init ======== */ Int GIO_Instance_init(GIO_Object *obj, String name, UInt mode, const GIO_Params *params, Error_Block *eb) { Int i, status; Queue_Handle doneList; Queue_Handle freeList; DEV_Handle device; IOM_Packet *packets; IOM_Fxns *iomFxns; Ptr devp; obj->name = name; obj->numPackets = params->numPackets; obj->doneCount = 0; obj->freeCount = 0; obj->submitCount = 0; obj->mode = mode; obj->model = params->model; obj->timeout = params->timeout; if (params->sync == NULL) { obj->userSync = FALSE; obj->sync = SyncSemThread_Handle_upCast(SyncSemThread_create(NULL, eb)); if (obj->sync == NULL) { return (1); } } else { obj->sync = params->sync; obj->userSync = TRUE; } doneList = GIO_Instance_State_doneList(obj); Queue_construct(Queue_struct(doneList), NULL); freeList = GIO_Instance_State_freeList(obj); Queue_construct(Queue_struct(freeList), NULL); /* allocate packets */ packets = Memory_alloc(NULL, sizeof(IOM_Packet) * (obj->numPackets), 0, eb); if (packets == NULL) { return (2); } obj->packets = packets; obj->freeCount = obj->numPackets; /* * Split the buffer into packets and add to freeList */ for (i = 0; i < obj->numPackets; i++) { Queue_enqueue(freeList, (Queue_Elem *)&packets[i]); } name = DEV_match(name, &device); if (device == NULL) { /* The name was not found */ Error_raise(eb, GIO_E_notFound, obj->name, 0); return (3); } obj->fxns = DEV_getFxns(device); iomFxns = (IOM_Fxns *)obj->fxns; devp = DEV_getDevp(device); status = iomFxns->mdCreateChan(&obj->mdChan, devp, name, mode, params->chanParams, callback, obj); if (status != IOM_COMPLETED) { Error_raise(eb, GIO_E_createFailed, status, 0); return (4); } return (0); }
/* * ======== GIO_new ======== */ GIO_Handle GIO_new(GIO_Handle gioChan, String name, Int mode, Int *status, Ptr optArgs, IOM_Packet packetBuf[], Ptr syncObject, GIO_Attrs *attrs) { DEV_Device *entry; Int i; Int tmpStat; if (attrs == NULL) { attrs = &GIO_ATTRS; } /* * status param is used to pass additional device status back to caller. */ if (status == NULL) { status = &tmpStat; /* no longer need to check if status valid ptr */ } *status = IOM_COMPLETED; /* * Find device structure in device table for device with name 'name'. * DEV_match() returns the remaining name string for use by the * mini-driver's create() function. */ name = DEV_match(name, &entry); if (entry == NULL) { SYS_error(name, SYS_ENODEV); /* sys error - no device found */ return (NULL); } if (entry->type != DEV_IOMTYPE) { SYS_error("IOM", SYS_EINVAL); /* sys error - invalid device parameter */ return (NULL); } /* initialize queue structures */ QUE_new(&gioChan->freeList); /* zero out the packet buffers */ memset(packetBuf, 0, attrs->nPackets * sizeof(IOM_Packet)); /* Put packets into freeList. */ for (i=0; i < attrs->nPackets; i++) { QUE_put(&gioChan->freeList, &packetBuf[i]); } /* * Plug semaphore or other synchronization object. 'gioChan->syncObj' is * used to wait for I/O to complete when GIO_submit() is called with * NULL *appCallback parameter. */ gioChan->syncObj = syncObject; gioChan->fxns = (IOM_Fxns *)entry->fxns; gioChan->mode = mode; gioChan->timeout = attrs->timeout; *status = gioChan->fxns->mdCreateChan(&gioChan->mdChan, entry->devp, name, mode, optArgs, _GIO_iomCallback, gioChan); if (gioChan->mdChan == NULL) { return (NULL); } return (gioChan); }
/* * ======== GIO_create ======== */ GIO_Handle GIO_create(String name, Int mode, Int *status, Ptr optArgs, \ GIO_Attrs *attrs) { GIO_Handle gioChan; IOM_Packet *packet; DEV_Device *entry; Int i; Int tmpStat; if (attrs == NULL) { attrs = &GIO_ATTRS; } /* * status param is used to pass additional device status back to caller. */ if (status == NULL) { status = &tmpStat; /* no longer need to check if status valid ptr */ } *status = IOM_COMPLETED; /* * Find device structure in device table for device with name 'name'. * DEV_match() returns the remaining name string for use by the * mini-driver's create() function. */ name = DEV_match(name, &entry); if (entry == NULL) { SYS_error(name, SYS_ENODEV); /* sys error - no device found */ return (NULL); } if (entry->type != DEV_IOMTYPE) { SYS_error("IOM", SYS_EINVAL); /* sys error - invalid device parameter */ return (NULL); } /* allocate and 0-fill IOM object */ gioChan = MEM_calloc(0, sizeof(GIO_Obj), 0); if (gioChan == NULL) { *status = IOM_EALLOC; return (NULL); } /* initialize queue structures */ QUE_new(&gioChan->freeList); /* * Allocate packets for asynch I/O. */ for (i=0; i < attrs->nPackets; i++) { packet = _GIO_mkPacket(); if (packet == NULL) { *status = IOM_EALLOC; GIO_delete(gioChan); return (NULL); } QUE_put(&gioChan->freeList, packet); } /* * Create semaphore or other synchronization object. 'gioChan->syncObj' is * used to wait for I/O to complete when GIO_submit() is called with * NULL *appCallback parameter. */ gioChan->syncObj = GIO->SEMCREATE(0, NULL); if (gioChan->syncObj == NULL) { *status = IOM_EALLOC; GIO_delete(gioChan); return (NULL); } gioChan->fxns = (IOM_Fxns *)entry->fxns; gioChan->mode = mode; gioChan->timeout = attrs->timeout; *status = gioChan->fxns->mdCreateChan(&gioChan->mdChan, entry->devp, name, mode, optArgs, _GIO_iomCallback, gioChan); if (gioChan->mdChan == NULL) { GIO_delete(gioChan); return (NULL); } return (gioChan); }
/* * ======== DOV_open ======== */ static Int DOV_open(DEV_Handle device, String name) { DOV_CopyObj *copy; DEV_Device *entry; Int status = SYS_EALLOC; DEV_Frame *frame; size_t size; if (device->mode != DEV_INPUT) { return (SYS_EINVAL); } /* * If devid is nonzero, it holds the 'size' of the overlap buffer. */ if (device->devid > 0) { size = device->devid; } else { size = atoi(name); /* * Skip the numeric characters to get to the underlying * device's name. */ while (isdigit(*name)) { name++; } } if (size <= 0 || size >= device->bufsize) { return (SYS_EINVAL); } /* * find underlying device in device table */ name = DEV_match(name, &entry); if (entry == NULL) { return (SYS_ENODEV); } /* allocate copy object */ if ((copy = MEM_alloc(0, sizeof(DOV_CopyObj), 0)) == MEM_ILLEGAL) { return (SYS_EALLOC); } copy->size = size; /* allocate and initialize overlap buffer */ if ((copy->overlap = MEM_valloc(0, size, 0, DOV->INITIAL)) == MEM_ILLEGAL) { goto e1; } copy->dobj = *device; /* copy descriptor fields */ copy->dobj.fxns = *(DEV_Fxns *)(entry->fxns); copy->dobj.devid = entry->devid; copy->dobj.params = entry->params; /* size of underlying buffers */ copy->dobj.bufsize = device->bufsize - size; /* * create queues and frames for underlying device. */ if ((copy->dobj.todevice = QUE_create(NULL)) == NULL) { goto e2; } if ((copy->dobj.fromdevice = QUE_create(NULL)) == NULL) { goto e3; } /* * adjust frame size and address according to the overlap size before * copying frames to underlying device's 'todevice' queue */ while (!QUE_empty(device->todevice)) { frame = QUE_get(device->todevice); frame->size = frame->size - size; frame->addr = (Char *)frame->addr + size; QUE_put(copy->dobj.todevice, frame); } /* open underlying device */ if ((status = DEV_open((©->dobj), name)) != SYS_OK) { goto e4; } device->object = (Ptr)copy; return (SYS_OK); /* all is well */ /* free memory and return error code */ e4: QUE_delete(copy->dobj.fromdevice); e3: QUE_delete(copy->dobj.todevice); e2: MEM_free(0, copy->overlap, copy->size); e1: MEM_free(0, copy, sizeof(DOV_CopyObj)); return (status); }