Annotation of funnyos/kern/kern_devctl.c, Revision 1.1
1.1 ! nbrk 1: /*
! 2: * $id$
! 3: */
! 4: #include <sys/types.h>
! 5: #include <sys/device.h>
! 6: #include <sys/devctl.h>
! 7: #include <sys/mem.h>
! 8:
! 9: #include <libkern/printf.h>
! 10: #include <libkern/string.h>
! 11:
! 12: /*
! 13: * devctl, Device control mechanism.
! 14: * devctl is used when driver or task want to talk to a specified attached device,
! 15: * Device driver (if it wishes to) implements devctl stub and registers it with devctl_register();
! 16: * Device driver also defines (for himself) a set of meanings of 32bit 'ctlcmd' field which will be
! 17: * passed to his devctl stub among with 'ctldata' (which is a void *).
! 18: * In summary, picture look like this:
! 19: * - device driver (foodev) implements and registers its devctl handler (foo_devctl()).
! 20: * - another driver (bardev) or task wants to talk to foodev/0 and calls: devctl("foodev", 0, READ_DATA, buffer);
! 21: * - program flow gets in foo_devctl(struct device *self, ctlcmd, ctldata);
! 22: * - foo driver deciphers ctlcmd ("READ_DATA"), performs requested action and passes results back to 'bar' in ctldata ("buffer").
! 23: */
! 24:
! 25: struct devctl_vector {
! 26: struct device *dcv_devp;
! 27: char *dcv_dvname;
! 28: uint8_t dcv_dvminor;
! 29: int (*dcv_ctlfunc)(struct device *self, uint32_t ctlcmd, void *ctldata);
! 30:
! 31: struct devctl_vector *dcv_next;
! 32: };
! 33:
! 34: /* system devctl table */
! 35: struct devctl_vector *devctltable = NULL;
! 36:
! 37:
! 38: void
! 39: devctl_register(struct device *self, int (*ctlfunc)(struct device *self, uint32_t ctlcmd, void *ctldata))
! 40: {
! 41: struct devctl_vector *dcvp, *prevdcvp;
! 42:
! 43: /*
! 44: * Register given function as devctl stub for given device.
! 45: */
! 46:
! 47: dcvp = devctltable;
! 48:
! 49: if (dcvp == NULL) {
! 50: /*
! 51: * First entry.
! 52: */
! 53: dcvp = kmalloc(sizeof(struct devctl_vector));
! 54: if (dcvp == NULL) {
! 55: panic("devctl_register: failed to allocate memory\n");
! 56: /* NOTREACHED */
! 57: }
! 58:
! 59: /* update list head */
! 60: devctltable = dcvp;
! 61: } else {
! 62: /*
! 63: * Append to list.
! 64: */
! 65: while(dcvp->dcv_next != NULL)
! 66: dcvp = dcvp->dcv_next;
! 67:
! 68: /* found last entry, allocate space for next (new) */
! 69: prevdcvp = dcvp;
! 70: dcvp->dcv_next = kmalloc(sizeof(struct devctl_vector));
! 71: if (dcvp->dcv_next == NULL)
! 72: panic("devctl_register: failed to allocate memory\n");
! 73:
! 74: /* ok, jump forward */
! 75: dcvp = dcvp->dcv_next;
! 76:
! 77: prevdcvp->dcv_next = dcvp;
! 78: }
! 79:
! 80: /* write entry; set dcv_next to NULL indicating end of list */
! 81: dcvp->dcv_devp = self;
! 82: dcvp->dcv_dvname = self->dv_name;
! 83: dcvp->dcv_dvminor = self->dv_minor;
! 84: dcvp->dcv_ctlfunc = ctlfunc;
! 85: dcvp->dcv_next = NULL;
! 86: }
! 87:
! 88:
! 89: int
! 90: devctl(const char *dv_name, uint8_t dv_minor, uint32_t ctlcmd, void *ctldata)
! 91: {
! 92: struct devctl_vector *dcvp;
! 93:
! 94: dcvp = devctltable;
! 95:
! 96: if (dcvp == NULL) {
! 97: /* devctl table is empty */
! 98: /* XXX panic here? */
! 99: panic("devctl: can't find devctl for %s/%d: devctltable is not configured yet\n", dv_name, dv_minor);
! 100: /* NOTREACHED */
! 101: }
! 102:
! 103: /* look through the list */
! 104: while(dcvp != NULL) {
! 105:
! 106: if (strncmp(dcvp->dcv_dvname, dv_name, DVNAMELEN - 1) == 0 && dcvp->dcv_dvminor == dv_minor)
! 107: /* got it */
! 108: return(dcvp->dcv_ctlfunc(dcvp->dcv_devp, ctlcmd, ctldata));
! 109:
! 110: dcvp = dcvp->dcv_next;
! 111: }
! 112:
! 113: /* requested devctl not found */
! 114: panic("devctl: can't find devctl for %s/%d: devctltable record not found\n", dv_name, dv_minor);
! 115: }
! 116:
! 117:
CVSweb