File:  [DragonFly] / src / sys / kern / kern_device.c
Revision 1.10: download - view: text, annotated - select for diffs
Thu May 13 23:49:23 2004 UTC (9 years, 11 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*
    2:  * Copyright (c) 2003 Matthew Dillon <dillon@backplane.com> All rights reserved.
    3:  * cdevsw from kern/kern_conf.c Copyright (c) 1995 Terrence R. Lambert
    4:  * cdevsw from kern/kern_conf.c Copyright (c) 1995 Julian R. Elishcer,
    5:  *							All rights reserved.
    6:  *
    7:  * Redistribution and use in source and binary forms, with or without
    8:  * modification, are permitted provided that the following conditions
    9:  * are met:
   10:  * 1. Redistributions of source code must retain the above copyright
   11:  *    notice, this list of conditions and the following disclaimer.
   12:  * 2. Redistributions in binary form must reproduce the above copyright
   13:  *    notice, this list of conditions and the following disclaimer in the
   14:  *    documentation and/or other materials provided with the distribution.
   15:  *
   16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26:  * SUCH DAMAGE.
   27:  *
   28:  * $DragonFly: src/sys/kern/kern_device.c,v 1.10 2004/05/13 23:49:23 dillon Exp $
   29:  */
   30: #include <sys/param.h>
   31: #include <sys/kernel.h>
   32: #include <sys/sysctl.h>
   33: #include <sys/systm.h>
   34: #include <sys/module.h>
   35: #include <sys/malloc.h>
   36: #include <sys/conf.h>
   37: #include <sys/vnode.h>
   38: #include <sys/queue.h>
   39: #include <sys/msgport.h>
   40: #include <sys/device.h>
   41: #include <machine/stdarg.h>
   42: #include <sys/proc.h>
   43: #include <sys/thread2.h>
   44: #include <sys/msgport2.h>
   45: 
   46: static struct cdevsw 	*cdevsw[NUMCDEVSW];
   47: static struct lwkt_port	*cdevport[NUMCDEVSW];
   48: 
   49: static int cdevsw_putport(lwkt_port_t port, lwkt_msg_t msg);
   50: 
   51: /*
   52:  * Initialize a message port to serve as the default message-handling port
   53:  * for device operations.  This message port provides compatibility with
   54:  * traditional cdevsw dispatch functions by running them synchronously.
   55:  *
   56:  * YYY NOTE: ms_cmd can now hold a function pointer, should this code be
   57:  * converted from an integer op to a function pointer with a flag to
   58:  * indicate legacy operation?
   59:  */
   60: static void
   61: init_default_cdevsw_port(lwkt_port_t port)
   62: {
   63:     lwkt_initport(port, NULL);
   64:     port->mp_putport = cdevsw_putport;
   65: }
   66: 
   67: static
   68: int
   69: cdevsw_putport(lwkt_port_t port, lwkt_msg_t lmsg)
   70: {
   71:     cdevallmsg_t msg = (cdevallmsg_t)lmsg;
   72:     struct cdevsw *csw = msg->am_msg.csw;
   73:     int error;
   74: 
   75:     /*
   76:      * Run the device switch function synchronously in the context of the
   77:      * caller and return a synchronous error code (anything not EASYNC).
   78:      */
   79:     switch(msg->am_lmsg.ms_cmd.cm_op) {
   80:     case CDEV_CMD_OPEN:
   81: 	error = csw->old_open(
   82: 		    msg->am_open.msg.dev,
   83: 		    msg->am_open.oflags,
   84: 		    msg->am_open.devtype,
   85: 		    msg->am_open.td);
   86: 	break;
   87:     case CDEV_CMD_CLOSE:
   88: 	error = csw->old_close(
   89: 		    msg->am_close.msg.dev,
   90: 		    msg->am_close.fflag,
   91: 		    msg->am_close.devtype,
   92: 		    msg->am_close.td);
   93: 	break;
   94:     case CDEV_CMD_STRATEGY:
   95: 	csw->old_strategy(msg->am_strategy.bp);
   96: 	error = 0;
   97: 	break;
   98:     case CDEV_CMD_IOCTL:
   99: 	error = csw->old_ioctl(
  100: 		    msg->am_ioctl.msg.dev,
  101: 		    msg->am_ioctl.cmd,
  102: 		    msg->am_ioctl.data,
  103: 		    msg->am_ioctl.fflag,
  104: 		    msg->am_ioctl.td);
  105: 	break;
  106:     case CDEV_CMD_DUMP:
  107: 	error = csw->old_dump(msg->am_ioctl.msg.dev);
  108: 	break;
  109:     case CDEV_CMD_PSIZE:
  110: 	msg->am_psize.result = csw->old_psize(msg->am_psize.msg.dev);
  111: 	error = 0;	/* XXX */
  112: 	break;
  113:     case CDEV_CMD_READ:
  114: 	error = csw->old_read(
  115: 		    msg->am_read.msg.dev,
  116: 		    msg->am_read.uio,
  117: 		    msg->am_read.ioflag);
  118: 	break;
  119:     case CDEV_CMD_WRITE:
  120: 	error = csw->old_write(
  121: 		    msg->am_read.msg.dev,
  122: 		    msg->am_read.uio,
  123: 		    msg->am_read.ioflag);
  124: 	break;
  125:     case CDEV_CMD_POLL:
  126: 	msg->am_poll.events = csw->old_poll(
  127: 				msg->am_poll.msg.dev,
  128: 				msg->am_poll.events,
  129: 				msg->am_poll.td);
  130: 	error = 0;
  131: 	break;
  132:     case CDEV_CMD_KQFILTER:
  133: 	msg->am_kqfilter.result = csw->old_kqfilter(
  134: 				msg->am_kqfilter.msg.dev,
  135: 				msg->am_kqfilter.kn);
  136: 	error = 0;
  137: 	break;
  138:     case CDEV_CMD_MMAP:
  139: 	msg->am_mmap.result = csw->old_mmap(
  140: 		    msg->am_mmap.msg.dev,
  141: 		    msg->am_mmap.offset,
  142: 		    msg->am_mmap.nprot);
  143: 	error = 0;	/* XXX */
  144: 	break;
  145:     default:
  146: 	error = ENOSYS;
  147: 	break;
  148:     }
  149:     KKASSERT(error != EASYNC);
  150:     return(error);
  151: }
  152: 
  153: /*
  154:  * These device dispatch functions provide convenient entry points for
  155:  * any code wishing to make a dev call.
  156:  *
  157:  * YYY we ought to be able to optimize the port lookup by caching it in
  158:  * the dev_t structure itself.
  159:  */
  160: static __inline
  161: struct cdevsw *
  162: _devsw(dev_t dev)
  163: {
  164:     if (dev == NULL)
  165: 	return(NULL);
  166:     if (dev->si_devsw)
  167: 	return (dev->si_devsw);
  168:     return(cdevsw[major(dev)]);
  169: }
  170: 
  171: static __inline
  172: lwkt_port_t
  173: _init_cdevmsg(dev_t dev, cdevmsg_t msg, int cmd)
  174: {
  175:     struct cdevsw *csw;
  176: 
  177:     lwkt_initmsg_simple(&msg->msg, cmd);
  178:     msg->dev = dev;
  179:     msg->csw = csw = _devsw(dev);
  180:     if (csw != NULL) {			/* YYY too hackish */
  181: 	KKASSERT(csw->d_port);		/* YYY too hackish */
  182: 	if (cdevport[major(dev)])	/* YYY too hackish */
  183: 	    return(cdevport[major(dev)]);
  184: 	return(csw->d_port);
  185:     }
  186:     return(NULL);
  187: }
  188: 
  189: int
  190: dev_dopen(dev_t dev, int oflags, int devtype, thread_t td)
  191: {
  192:     struct cdevmsg_open	msg;
  193:     lwkt_port_t port;
  194: 
  195:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_OPEN);
  196:     if (port == NULL)
  197: 	return(ENXIO);
  198:     msg.oflags = oflags;
  199:     msg.devtype = devtype;
  200:     msg.td = td;
  201:     return(lwkt_domsg(port, &msg.msg.msg));
  202: }
  203: 
  204: int
  205: dev_dclose(dev_t dev, int fflag, int devtype, thread_t td)
  206: {
  207:     struct cdevmsg_close msg;
  208:     lwkt_port_t port;
  209: 
  210:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_CLOSE);
  211:     if (port == NULL)
  212: 	return(ENXIO);
  213:     msg.fflag = fflag;
  214:     msg.devtype = devtype;
  215:     msg.td = td;
  216:     return(lwkt_domsg(port, &msg.msg.msg));
  217: }
  218: 
  219: void
  220: dev_dstrategy(dev_t dev, struct buf *bp)
  221: {
  222:     struct cdevmsg_strategy msg;
  223:     lwkt_port_t port;
  224: 
  225:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_STRATEGY);
  226:     KKASSERT(port);	/* 'nostrategy' function is NULL YYY */
  227:     msg.bp = bp;
  228:     lwkt_domsg(port, &msg.msg.msg);
  229: }
  230: 
  231: int
  232: dev_dioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, thread_t td)
  233: {
  234:     struct cdevmsg_ioctl msg;
  235:     lwkt_port_t port;
  236: 
  237:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_IOCTL);
  238:     if (port == NULL)
  239: 	return(ENXIO);
  240:     msg.cmd = cmd;
  241:     msg.data = data;
  242:     msg.fflag = fflag;
  243:     msg.td = td;
  244:     return(lwkt_domsg(port, &msg.msg.msg));
  245: }
  246: 
  247: int
  248: dev_ddump(dev_t dev)
  249: {
  250:     struct cdevmsg_dump	msg;
  251:     lwkt_port_t port;
  252: 
  253:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_DUMP);
  254:     if (port == NULL)
  255: 	return(ENXIO);
  256:     return(lwkt_domsg(port, &msg.msg.msg));
  257: }
  258: 
  259: int
  260: dev_dpsize(dev_t dev)
  261: {
  262:     struct cdevmsg_psize msg;
  263:     lwkt_port_t port;
  264:     int error;
  265: 
  266:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_PSIZE);
  267:     if (port == NULL)
  268: 	return(-1);
  269:     error = lwkt_domsg(port, &msg.msg.msg);
  270:     if (error == 0)
  271: 	return(msg.result);
  272:     return(-1);
  273: }
  274: 
  275: int
  276: dev_dread(dev_t dev, struct uio *uio, int ioflag)
  277: {
  278:     struct cdevmsg_read msg;
  279:     lwkt_port_t port;
  280: 
  281:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_READ);
  282:     if (port == NULL)
  283: 	return(ENXIO);
  284:     msg.uio = uio;
  285:     msg.ioflag = ioflag;
  286:     return(lwkt_domsg(port, &msg.msg.msg));
  287: }
  288: 
  289: int
  290: dev_dwrite(dev_t dev, struct uio *uio, int ioflag)
  291: {
  292:     struct cdevmsg_write msg;
  293:     lwkt_port_t port;
  294: 
  295:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_WRITE);
  296:     if (port == NULL)
  297: 	return(ENXIO);
  298:     msg.uio = uio;
  299:     msg.ioflag = ioflag;
  300:     return(lwkt_domsg(port, &msg.msg.msg));
  301: }
  302: 
  303: int
  304: dev_dpoll(dev_t dev, int events, thread_t td)
  305: {
  306:     struct cdevmsg_poll msg;
  307:     lwkt_port_t port;
  308:     int error;
  309: 
  310:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_POLL);
  311:     if (port == NULL)
  312: 	return(ENXIO);
  313:     msg.events = events;
  314:     msg.td = td;
  315:     error = lwkt_domsg(port, &msg.msg.msg);
  316:     if (error == 0)
  317: 	return(msg.events);
  318:     return(seltrue(dev, msg.events, td));
  319: }
  320: 
  321: int
  322: dev_dkqfilter(dev_t dev, struct knote *kn)
  323: {
  324:     struct cdevmsg_kqfilter msg;
  325:     lwkt_port_t port;
  326:     int error;
  327: 
  328:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_KQFILTER);
  329:     if (port == NULL)
  330: 	return(ENXIO);
  331:     msg.kn = kn;
  332:     error = lwkt_domsg(port, &msg.msg.msg);
  333:     if (error == 0)
  334: 	return(msg.result);
  335:     return(ENODEV);
  336: }
  337: 
  338: int
  339: dev_dmmap(dev_t dev, vm_offset_t offset, int nprot)
  340: {
  341:     struct cdevmsg_mmap msg;
  342:     lwkt_port_t port;
  343:     int error;
  344: 
  345:     port = _init_cdevmsg(dev, &msg.msg, CDEV_CMD_MMAP);
  346:     if (port == NULL)
  347: 	return(-1);
  348:     msg.offset = offset;
  349:     msg.nprot = nprot;
  350:     error = lwkt_domsg(port, &msg.msg.msg);
  351:     if (error == 0)
  352: 	return(msg.result);
  353:     return(-1);
  354: }
  355: 
  356: int
  357: dev_port_dopen(lwkt_port_t port, dev_t dev, int oflags, int devtype, thread_t td)
  358: {
  359:     struct cdevmsg_open	msg;
  360: 
  361:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_OPEN);
  362:     if (port == NULL)
  363: 	return(ENXIO);
  364:     msg.oflags = oflags;
  365:     msg.devtype = devtype;
  366:     msg.td = td;
  367:     return(lwkt_domsg(port, &msg.msg.msg));
  368: }
  369: 
  370: int
  371: dev_port_dclose(lwkt_port_t port, dev_t dev, int fflag, int devtype, thread_t td)
  372: {
  373:     struct cdevmsg_close msg;
  374: 
  375:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_CLOSE);
  376:     if (port == NULL)
  377: 	return(ENXIO);
  378:     msg.fflag = fflag;
  379:     msg.devtype = devtype;
  380:     msg.td = td;
  381:     return(lwkt_domsg(port, &msg.msg.msg));
  382: }
  383: 
  384: void
  385: dev_port_dstrategy(lwkt_port_t port, dev_t dev, struct buf *bp)
  386: {
  387:     struct cdevmsg_strategy msg;
  388: 
  389:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_STRATEGY);
  390:     KKASSERT(port);	/* 'nostrategy' function is NULL YYY */
  391:     msg.bp = bp;
  392:     lwkt_domsg(port, &msg.msg.msg);
  393: }
  394: 
  395: int
  396: dev_port_dioctl(lwkt_port_t port, dev_t dev, u_long cmd, caddr_t data, int fflag, thread_t td)
  397: {
  398:     struct cdevmsg_ioctl msg;
  399: 
  400:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_IOCTL);
  401:     if (port == NULL)
  402: 	return(ENXIO);
  403:     msg.cmd = cmd;
  404:     msg.data = data;
  405:     msg.fflag = fflag;
  406:     msg.td = td;
  407:     return(lwkt_domsg(port, &msg.msg.msg));
  408: }
  409: 
  410: int
  411: dev_port_ddump(lwkt_port_t port, dev_t dev)
  412: {
  413:     struct cdevmsg_dump	msg;
  414: 
  415:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_DUMP);
  416:     if (port == NULL)
  417: 	return(ENXIO);
  418:     return(lwkt_domsg(port, &msg.msg.msg));
  419: }
  420: 
  421: int
  422: dev_port_dpsize(lwkt_port_t port, dev_t dev)
  423: {
  424:     struct cdevmsg_psize msg;
  425:     int error;
  426: 
  427:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_PSIZE);
  428:     if (port == NULL)
  429: 	return(-1);
  430:     error = lwkt_domsg(port, &msg.msg.msg);
  431:     if (error == 0)
  432: 	return(msg.result);
  433:     return(-1);
  434: }
  435: 
  436: int
  437: dev_port_dread(lwkt_port_t port, dev_t dev, struct uio *uio, int ioflag)
  438: {
  439:     struct cdevmsg_read msg;
  440: 
  441:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_READ);
  442:     if (port == NULL)
  443: 	return(ENXIO);
  444:     msg.uio = uio;
  445:     msg.ioflag = ioflag;
  446:     return(lwkt_domsg(port, &msg.msg.msg));
  447: }
  448: 
  449: int
  450: dev_port_dwrite(lwkt_port_t port, dev_t dev, struct uio *uio, int ioflag)
  451: {
  452:     struct cdevmsg_write msg;
  453: 
  454:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_WRITE);
  455:     if (port == NULL)
  456: 	return(ENXIO);
  457:     msg.uio = uio;
  458:     msg.ioflag = ioflag;
  459:     return(lwkt_domsg(port, &msg.msg.msg));
  460: }
  461: 
  462: int
  463: dev_port_dpoll(lwkt_port_t port, dev_t dev, int events, thread_t td)
  464: {
  465:     struct cdevmsg_poll msg;
  466:     int error;
  467: 
  468:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_POLL);
  469:     if (port == NULL)
  470: 	return(ENXIO);
  471:     msg.events = events;
  472:     msg.td = td;
  473:     error = lwkt_domsg(port, &msg.msg.msg);
  474:     if (error == 0)
  475: 	return(msg.events);
  476:     return(seltrue(dev, msg.events, td));
  477: }
  478: 
  479: int
  480: dev_port_dkqfilter(lwkt_port_t port, dev_t dev, struct knote *kn)
  481: {
  482:     struct cdevmsg_kqfilter msg;
  483:     int error;
  484: 
  485:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_KQFILTER);
  486:     if (port == NULL)
  487: 	return(ENXIO);
  488:     msg.kn = kn;
  489:     error = lwkt_domsg(port, &msg.msg.msg);
  490:     if (error == 0)
  491: 	return(msg.result);
  492:     return(ENODEV);
  493: }
  494: 
  495: int
  496: dev_port_dmmap(lwkt_port_t port, dev_t dev, vm_offset_t offset, int nprot)
  497: {
  498:     struct cdevmsg_mmap msg;
  499:     int error;
  500: 
  501:     _init_cdevmsg(dev, &msg.msg, CDEV_CMD_MMAP);
  502:     if (port == NULL)
  503: 	return(-1);
  504:     msg.offset = offset;
  505:     msg.nprot = nprot;
  506:     error = lwkt_domsg(port, &msg.msg.msg);
  507:     if (error == 0)
  508: 	return(msg.result);
  509:     return(-1);
  510: }
  511: 
  512: const char *
  513: dev_dname(dev_t dev)
  514: {
  515:     struct cdevsw *csw;
  516: 
  517:     if ((csw = _devsw(dev)) != NULL)
  518: 	return(csw->d_name);
  519:     return(NULL);
  520: }
  521: 
  522: int
  523: dev_dflags(dev_t dev)
  524: {
  525:     struct cdevsw *csw;
  526: 
  527:     if ((csw = _devsw(dev)) != NULL)
  528: 	return(csw->d_flags);
  529:     return(0);
  530: }
  531: 
  532: int
  533: dev_dmaj(dev_t dev)
  534: {
  535:     struct cdevsw *csw;
  536: 
  537:     if ((csw = _devsw(dev)) != NULL)
  538: 	return(csw->d_maj);
  539:     return(0);
  540: }
  541: 
  542: lwkt_port_t
  543: dev_dport(dev_t dev)
  544: {
  545:     struct cdevsw *csw;
  546: 
  547:     if ((csw = _devsw(dev)) != NULL) {
  548: 	if (cdevport[major(dev)])	/* YYY too hackish */
  549: 	    return(cdevport[major(dev)]);
  550: 	return(csw->d_port);
  551:     }
  552:     return(NULL);
  553: }
  554: 
  555: #if 0
  556: /*
  557:  * cdevsw[] array functions, moved from kern/kern_conf.c
  558:  */
  559: struct cdevsw *
  560: devsw(dev_t dev)
  561: {
  562:     return(_devsw(dev));
  563: }
  564: #endif
  565: 
  566: /*
  567:  * Convert a cdevsw template into the real thing, filling in fields the
  568:  * device left empty with appropriate defaults.
  569:  */
  570: void
  571: compile_devsw(struct cdevsw *devsw)
  572: {
  573:     static lwkt_port devsw_compat_port;
  574: 
  575:     if (devsw_compat_port.mp_putport == NULL)
  576: 	init_default_cdevsw_port(&devsw_compat_port);
  577:     
  578:     if (devsw->old_open == NULL)
  579: 	devsw->old_open = noopen;
  580:     if (devsw->old_close == NULL)
  581: 	devsw->old_close = noclose;
  582:     if (devsw->old_read == NULL)
  583: 	devsw->old_read = noread;
  584:     if (devsw->old_write == NULL)
  585: 	devsw->old_write = nowrite;
  586:     if (devsw->old_ioctl == NULL)
  587: 	devsw->old_ioctl = noioctl;
  588:     if (devsw->old_poll == NULL)
  589: 	devsw->old_poll = nopoll;
  590:     if (devsw->old_mmap == NULL)
  591: 	devsw->old_mmap = nommap;
  592:     if (devsw->old_strategy == NULL)
  593: 	devsw->old_strategy = nostrategy;
  594:     if (devsw->old_dump == NULL)
  595: 	devsw->old_dump = nodump;
  596:     if (devsw->old_psize == NULL)
  597: 	devsw->old_psize = nopsize;
  598:     if (devsw->old_kqfilter == NULL)
  599: 	devsw->old_kqfilter = nokqfilter;
  600: 
  601:     if (devsw->d_port == NULL)
  602: 	devsw->d_port = &devsw_compat_port;
  603: }
  604: 
  605: /*
  606:  * Add a cdevsw entry
  607:  */
  608: int
  609: cdevsw_add(struct cdevsw *newentry)
  610: {
  611:     compile_devsw(newentry);
  612:     if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) {
  613: 	printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
  614: 	    newentry->d_name, newentry->d_maj);
  615: 	return (EINVAL);
  616:     }
  617:     if (cdevsw[newentry->d_maj]) {
  618: 	printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n",
  619: 	    newentry->d_name, cdevsw[newentry->d_maj]->d_name);
  620:     }
  621:     cdevsw[newentry->d_maj] = newentry;
  622:     return (0);
  623: }
  624: 
  625: /*
  626:  * Add a cdevsw entry and override the port.
  627:  */
  628: lwkt_port_t
  629: cdevsw_add_override(struct cdevsw *newentry, lwkt_port_t port)
  630: {
  631:     int error;
  632: 
  633:     if ((error = cdevsw_add(newentry)) == 0)
  634: 	cdevport[newentry->d_maj] = port;
  635:     return(newentry->d_port);
  636: }
  637: 
  638: lwkt_port_t
  639: cdevsw_dev_override(dev_t dev, lwkt_port_t port)
  640: {
  641:     struct cdevsw *csw;
  642: 
  643:     KKASSERT(major(dev) >= 0 && major(dev) < NUMCDEVSW);
  644:     if ((csw = _devsw(dev)) != NULL) {
  645: 	cdevport[major(dev)] = port;
  646: 	return(csw->d_port);
  647:     }
  648:     return(NULL);
  649: }
  650: 
  651: /*
  652:  *  Remove a cdevsw entry
  653:  */
  654: int
  655: cdevsw_remove(struct cdevsw *oldentry)
  656: {
  657:     if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) {
  658: 	printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
  659: 	    oldentry->d_name, oldentry->d_maj);
  660: 	return EINVAL;
  661:     }
  662:     cdevsw[oldentry->d_maj] = NULL;
  663:     cdevport[oldentry->d_maj] = NULL;
  664:     return 0;
  665: }
  666: