File:  [DragonFly] / src / sys / bus / isa / i386 / isa_compat.c
Revision 1.6: download - view: text, annotated - select for diffs
Sat Nov 22 19:43:25 2003 UTC (10 years, 4 months ago) by asmodai
Branches: MAIN
CVS tags: HEAD
Use malloc() + M_ZERO instead of malloc() + bzero().

Synchs with FreeBSD's 1.23.

    1: /*-
    2:  * Copyright (c) 1998 Doug Rabson
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  *
   14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24:  * SUCH DAMAGE.
   25:  *
   26:  * $FreeBSD: src/sys/i386/isa/isa_compat.c,v 1.18.2.1 2001/05/17 23:05:06 imp Exp $
   27:  * $DragonFly: src/sys/bus/isa/i386/isa_compat.c,v 1.6 2003/11/22 19:43:25 asmodai Exp $
   28:  */
   29: 
   30: #include <sys/param.h>
   31: #include <sys/systm.h>
   32: #include <sys/kernel.h>
   33: #include <sys/bus.h>
   34: #include <sys/malloc.h>
   35: #include <sys/module.h>
   36: #include <machine/bus.h>
   37: #include <sys/rman.h>
   38: 
   39: #include <machine/vmparam.h>
   40: #include <vm/vm.h>
   41: #include <vm/pmap.h>
   42: #include <machine/pmap.h>
   43: #include <machine/md_var.h>
   44: 
   45: #include <machine/resource.h>
   46: #include "../isavar.h"
   47: #include "isa_compat.h"
   48: #include "isa_device.h"
   49: 
   50: struct isa_compat_resources {
   51:     struct resource *ports;
   52:     struct resource *memory;
   53:     struct resource *drq;
   54:     struct resource *irq;
   55: };
   56: 
   57: int
   58: isa_compat_nextid(void)
   59: {
   60: 	static int id = 2;	/* id_id of -1, 0 and 1 are "used" */
   61: 
   62: 	return id++;
   63: }
   64: 
   65: static void
   66: isa_compat_alloc_resources(device_t dev, struct isa_compat_resources *res)
   67: {
   68: 	int rid;
   69: 	u_long start, count;
   70: 
   71: 	if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
   72: 			     &start, &count) == 0) {
   73: 		rid = 0;
   74: 		res->ports = bus_alloc_resource(dev, SYS_RES_IOPORT,
   75: 						&rid, 0ul, ~0ul, 1,
   76: 						RF_ACTIVE);
   77: 		if (res->ports == NULL && bootverbose)
   78: 			printf("isa_compat: didn't get ports for %s\n",
   79: 			       device_get_name(dev));
   80: 	} else
   81: 		res->ports = 0;
   82: 
   83: 	if (bus_get_resource(dev, SYS_RES_MEMORY, 0,
   84: 			     &start, &count) == 0
   85: 	    && start != 0) {
   86: 		rid = 0;
   87: 		res->memory = bus_alloc_resource(dev, SYS_RES_MEMORY,
   88: 						 &rid, 0ul, ~0ul, 1,
   89: 						 RF_ACTIVE);
   90: 		if (res->memory == NULL && bootverbose)
   91: 			printf("isa_compat: didn't get memory for %s\n",
   92: 			       device_get_name(dev));
   93: 	} else
   94: 		res->memory = 0;
   95: 
   96: 	if (bus_get_resource(dev, SYS_RES_DRQ, 0,
   97: 			     &start, &count) == 0) {
   98: 		rid = 0;
   99: 		res->drq = bus_alloc_resource(dev, SYS_RES_DRQ,
  100: 					      &rid, 0ul, ~0ul, 1,
  101: 					      RF_ACTIVE);
  102: 		if (res->drq == NULL && bootverbose)
  103: 			printf("isa_compat: didn't get drq for %s\n",
  104: 			       device_get_name(dev));
  105: 	} else
  106: 		res->drq = 0;
  107: 
  108: 	if (bus_get_resource(dev, SYS_RES_IRQ, 0,
  109: 			     &start, &count) == 0) {
  110: 		rid = 0;
  111: 		res->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
  112: 					      &rid, 0ul, ~0ul, 1,
  113: 					      RF_SHAREABLE | RF_ACTIVE);
  114: 		if (res->irq == NULL && bootverbose)
  115: 			printf("isa_compat: didn't get irq for %s\n",
  116: 			       device_get_name(dev));
  117: 	} else
  118: 		res->irq = 0;
  119: }
  120: 
  121: static void
  122: isa_compat_release_resources(device_t dev, struct isa_compat_resources *res)
  123: {
  124: 	if (res->ports) {
  125: 		bus_release_resource(dev, SYS_RES_IOPORT, 0, res->ports);
  126: 		res->ports = 0;
  127: 	}
  128: 	if (res->memory) {
  129: 		bus_release_resource(dev, SYS_RES_MEMORY, 0, res->memory);
  130: 		res->memory = 0;
  131: 	}
  132: 	if (res->drq) {
  133: 		bus_release_resource(dev, SYS_RES_DRQ, 0, res->drq);
  134: 		res->drq = 0;
  135: 	}
  136: 	if (res->irq) {
  137: 		bus_release_resource(dev, SYS_RES_IRQ, 0, res->irq);
  138: 		res->irq = 0;
  139: 	}
  140: }
  141: 
  142: #define	irqmask(x)	((x) < 0 ? 0 : (1 << (x)))
  143: 
  144: static int
  145: isa_compat_probe(device_t dev)
  146: {
  147: 	struct isa_device *dvp = device_get_softc(dev);
  148: 	struct isa_compat_resources res;
  149: 	struct old_isa_driver *op;
  150: 	u_long start, count;
  151: 
  152: 	/* No pnp support */
  153: 	if (isa_get_vendorid(dev))
  154: 		return (ENXIO);
  155: 
  156: 	bzero(&res, sizeof(res));
  157: 	/*
  158: 	 * Fill in the isa_device fields.
  159: 	 */
  160: 	op = device_get_driver(dev)->priv;
  161: 	dvp->id_id = isa_compat_nextid();
  162: 	dvp->id_driver = op->driver;
  163: 	if (bus_get_resource(dev, SYS_RES_IOPORT, 0,
  164: 			     &start, &count) == 0)
  165: 		dvp->id_iobase = start;
  166: 	else
  167: 		dvp->id_iobase = -1;
  168: 	if (bus_get_resource(dev, SYS_RES_IRQ, 0,
  169: 			     &start, &count) == 0)
  170: 		dvp->id_irq = irqmask(start);
  171: 	else
  172: 		dvp->id_irq = 0;
  173: 	if (bus_get_resource(dev, SYS_RES_DRQ, 0,
  174: 			     &start, &count) == 0)
  175: 		dvp->id_drq = start;
  176: 	else
  177: 		dvp->id_drq = -1;
  178: 	if (bus_get_resource(dev, SYS_RES_MEMORY,
  179: 			     0, &start, &count) == 0) {
  180: 		dvp->id_maddr = (void *)(uintptr_t)start;
  181: 		dvp->id_msize = count;
  182: 	} else {
  183: 		dvp->id_maddr = NULL;
  184: 		dvp->id_msize = 0;
  185: 	}
  186: 	dvp->id_unit = device_get_unit(dev);
  187: 	dvp->id_flags = device_get_flags(dev);
  188: 	dvp->id_enabled = device_is_enabled(dev);	/* XXX unused */
  189: 	dvp->id_device = dev;
  190: 
  191: 	/*
  192: 	 * Do the wrapped probe.
  193: 	 */
  194: 	if (dvp->id_driver->probe) {
  195: 		int portsize;
  196: 		void *maddr;
  197: 		struct isa_device old;
  198: 
  199: 		isa_compat_alloc_resources(dev, &res);
  200: 		if (res.memory)
  201: 			maddr = rman_get_virtual(res.memory);
  202: 		else
  203: 			maddr = 0;
  204: 		dvp->id_maddr = maddr;
  205: 		old = *dvp;
  206: 		portsize = dvp->id_driver->probe(dvp);
  207: 		isa_compat_release_resources(dev, &res);
  208: 		if (portsize != 0) {
  209: 			if (portsize > 0 || dvp->id_iobase != old.id_iobase)
  210: 				bus_set_resource(dev, SYS_RES_IOPORT,
  211: 						 0, dvp->id_iobase, portsize);
  212: 			if (dvp->id_irq != old.id_irq)
  213: 				bus_set_resource(dev, SYS_RES_IRQ, 0,
  214: 						 ffs(dvp->id_irq) - 1, 1);
  215: 			if (dvp->id_drq != old.id_drq)
  216: 				bus_set_resource(dev, SYS_RES_DRQ, 0,
  217: 						 dvp->id_drq, 1);
  218: 			if (dvp->id_maddr != old.id_maddr
  219: 			    || dvp->id_msize != old.id_msize) {
  220: 				maddr = dvp->id_maddr;
  221: 				if (maddr != NULL)
  222: 					bus_set_resource(dev,
  223: 							 SYS_RES_MEMORY,
  224: 							 0,
  225: 							 kvtop(maddr),
  226: 							 dvp->id_msize);
  227: 				else
  228: 					bus_delete_resource(dev,
  229: 							    SYS_RES_MEMORY,
  230: 							    0);
  231: 			}
  232: 			return 0;
  233: 		}
  234: 	}
  235: 	return ENXIO;
  236: }
  237: 
  238: static int
  239: isa_compat_attach(device_t dev)
  240: {
  241: 	struct isa_device *dvp = device_get_softc(dev);
  242: 	struct isa_compat_resources res;
  243: 	int error;
  244: 
  245: 	bzero(&res, sizeof(res));
  246: 	isa_compat_alloc_resources(dev, &res);
  247: 	if (dvp->id_driver->attach)
  248: 		dvp->id_driver->attach(dvp);
  249: 	if (res.irq && dvp->id_irq && dvp->id_intr) {
  250: 		struct old_isa_driver *op;
  251: 		void *ih;
  252: 
  253: 		op = device_get_driver(dev)->priv;
  254: 		error = BUS_SETUP_INTR(device_get_parent(dev), dev,
  255: 				       res.irq, op->type,
  256: 				       dvp->id_intr,
  257: 				       (void *)(uintptr_t)dvp->id_unit,
  258: 				       &ih);
  259: 		if (error)
  260: 			printf("isa_compat_attach: failed to setup intr: %d\n",
  261: 			       error);
  262: 	}
  263: 	device_printf(dev, "driver is using old-style compatibility shims\n");
  264: 	return 0;
  265: }
  266: 
  267: static device_method_t isa_compat_methods[] = {
  268: 	/* Device interface */
  269: 	DEVMETHOD(device_probe,		isa_compat_probe),
  270: 	DEVMETHOD(device_attach,	isa_compat_attach),
  271: 
  272: 	{ 0, 0 }
  273: };
  274: 
  275: /*
  276:  * Create a new style driver around each old isa driver.
  277:  */
  278: void
  279: isa_wrap_old_drivers(void)
  280: {
  281: 	int i;
  282: 	struct old_isa_driver *op;
  283: 	devclass_t isa_devclass = devclass_find("isa");
  284: 
  285: 	for (i = 0, op = &old_drivers[0]; i < old_drivers_count; i++, op++) {
  286: 		driver_t *driver;
  287: 		driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT | M_ZERO);
  288: 		if (!driver)
  289: 			continue;
  290: 		driver->name = op->driver->name;
  291: 		driver->methods = isa_compat_methods;
  292: 		driver->size = sizeof(struct isa_device);
  293: 		driver->priv = op;
  294: 		if (op->driver->sensitive_hw)
  295: 			resource_set_int(op->driver->name, -1, "sensitive", 1);
  296: 		devclass_add_driver(isa_devclass, driver);
  297: 	}
  298: }
  299: 
  300: int
  301: haveseen_iobase(struct isa_device *dvp, int size)
  302: {
  303: 	int rid;
  304: 	struct resource *res;
  305: 	device_t dev = dvp->id_device;
  306: 	int base = dvp->id_iobase;
  307: 
  308: 	/*
  309: 	 * Ask for resource 1 so that we don't hurt our hints.  In theory
  310: 	 * this should work, but....
  311: 	 */
  312: 	rid = 1;
  313: 	res = bus_alloc_resource(dev, SYS_RES_IOPORT,
  314: 				 &rid, base, base + size, size, RF_ACTIVE);
  315: 	if (res)
  316: 		bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
  317: 	return res ? 0 : 1;
  318: }