File:  [DragonFly] / src / sys / dev / misc / xrpu / Attic / xrpu.c
Revision 1.7: download - view: text, annotated - select for diffs
Thu May 13 23:49:18 2004 UTC (10 years, 4 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:  * ----------------------------------------------------------------------------
    3:  * "THE BEER-WARE LICENSE" (Revision 42):
    4:  * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
    5:  * can do whatever you want with this stuff. If we meet some day, and you think
    6:  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
    7:  * ----------------------------------------------------------------------------
    8:  *
    9:  * $FreeBSD: src/sys/pci/xrpu.c,v 1.19.2.1 2000/08/02 22:19:57 peter Exp $
   10:  * $DragonFly: src/sys/dev/misc/xrpu/xrpu.c,v 1.7 2004/05/13 23:49:18 dillon Exp $
   11:  *
   12:  * A very simple device driver for PCI cards based on Xilinx 6200 series
   13:  * FPGA/RPU devices.  Current Functionality is to allow you to open and
   14:  * mmap the entire thing into your program.
   15:  *
   16:  * Hardware currently supported:
   17:  *	www.vcc.com HotWorks 1 6216 based card.
   18:  *
   19:  */
   20: 
   21: #include <sys/param.h>
   22: #include <sys/systm.h>
   23: #include <sys/conf.h>
   24: #include <sys/kernel.h>
   25: #include <sys/malloc.h>
   26: #include <sys/timepps.h>
   27: #include <sys/xrpuio.h>
   28: #include <sys/bus.h>
   29: #include <machine/bus.h>
   30: #include <sys/rman.h>
   31: #include <machine/resource.h>
   32: #include <bus/pci/pcireg.h>
   33: #include <bus/pci/pcivar.h>
   34: #include "pci_if.h"
   35: 
   36: /*
   37:  * Device driver initialization stuff
   38:  */
   39: 
   40: static d_open_t	xrpu_open;
   41: static d_close_t xrpu_close;
   42: static d_ioctl_t xrpu_ioctl;
   43: static d_mmap_t xrpu_mmap;
   44: 
   45: #define CDEV_MAJOR 100
   46: static struct cdevsw xrpu_cdevsw = {
   47: 	/* name */	"xrpu",
   48: 	/* maj */	CDEV_MAJOR,
   49: 	/* flags */	0,
   50: 	/* port */	NULL,
   51: 	/* clone */	NULL,
   52: 
   53: 	/* open */	xrpu_open,
   54: 	/* close */	xrpu_close,
   55: 	/* read */	noread,
   56: 	/* write */	nowrite,
   57: 	/* ioctl */	xrpu_ioctl,
   58: 	/* poll */	nopoll,
   59: 	/* mmap */	xrpu_mmap,
   60: 	/* strategy */	nostrategy,
   61: 	/* dump */	nodump,
   62: 	/* psize */	nopsize
   63: };
   64: 
   65: static MALLOC_DEFINE(M_XRPU, "xrpu", "XRPU related");
   66: 
   67: static devclass_t xrpu_devclass;
   68: 
   69: #define dev2unit(devt) (minor(devt) & 0xff)
   70: #define dev2pps(devt) ((minor(devt) >> 16)-1)
   71: 
   72: struct softc {
   73: 	enum { NORMAL, TIMECOUNTER } mode;
   74: 	vm_offset_t virbase, physbase;
   75: 	u_int	*virbase62;
   76: #if 0
   77: 	struct timecounter tc;
   78: #endif
   79: 	u_int *trigger, *latch, dummy;
   80: 	struct pps_state pps[XRPU_MAX_PPS];
   81: 	u_int *assert[XRPU_MAX_PPS], *clear[XRPU_MAX_PPS];
   82: };
   83: 
   84: #if 0
   85: 
   86: static unsigned         
   87: xrpu_get_timecount(struct timecounter *tc)
   88: {               
   89: 	struct softc *sc = tc->tc_priv;
   90: 
   91: 	sc->dummy += *sc->trigger;
   92: 	return (*sc->latch & tc->tc_counter_mask);
   93: }        
   94: 
   95: static void            
   96: xrpu_poll_pps(struct timecounter *tc)
   97: {               
   98:         struct softc *sc = tc->tc_priv;
   99: 	int i, j;
  100:         unsigned count1, ppscount; 
  101:                 
  102: 	for (i = 0; i < XRPU_MAX_PPS; i++) {
  103: 		if (sc->assert[i]) {
  104: 			ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
  105: 			j = 0;
  106: 			do {
  107: 				count1 = ppscount;
  108: 				ppscount =  *(sc->assert[i]) & tc->tc_counter_mask;
  109: 			} while (ppscount != count1 && ++j < 5);
  110: 			pps_event(&sc->pps[i], tc, ppscount, PPS_CAPTUREASSERT);
  111: 		}
  112: 		if (sc->clear[i]) {
  113: 			j = 0;
  114: 			ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
  115: 			do {
  116: 				count1 = ppscount;
  117: 				ppscount =  *(sc->clear[i]) & tc->tc_counter_mask;
  118: 			} while (ppscount != count1 && ++j < 5);
  119: 			pps_event(&sc->pps[i], tc, ppscount, PPS_CAPTURECLEAR);
  120: 		}
  121: 	}
  122: }
  123: 
  124: #endif
  125: 
  126: static int
  127: xrpu_open(dev_t dev, int flag, int mode, struct thread *td)
  128: {
  129: 	struct softc *sc = devclass_get_softc(xrpu_devclass, dev2unit(dev));
  130: 
  131: 	if (!sc)
  132: 		return (ENXIO);
  133: 	dev->si_drv1 = sc;
  134: 	return (0);
  135: }
  136: 
  137: static int
  138: xrpu_close(dev_t dev, int flag, int mode, struct thread *td)
  139: { 
  140: 	return (0);
  141: }
  142: 
  143: static int
  144: xrpu_mmap(dev_t dev, vm_offset_t offset, int nprot)
  145: {
  146: 	struct softc *sc = dev->si_drv1;
  147: 	if (offset >= 0x1000000) 
  148: 		return (-1);
  149: 	return (i386_btop(sc->physbase + offset));
  150: }
  151: 
  152: static int
  153: xrpu_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
  154: {
  155: 	struct softc *sc = dev->si_drv1;
  156: 	int i, error;
  157: 
  158: 	if (sc->mode == TIMECOUNTER) {
  159: 		i = dev2pps(dev);
  160: 		if (i < 0 || i >= XRPU_MAX_PPS)
  161: 			return ENODEV;
  162: 		error =  pps_ioctl(cmd, arg, &sc->pps[i]);
  163: 		return (error);
  164: 	}
  165: 		
  166: #if 0
  167: 	if (cmd == XRPU_IOC_TIMECOUNTING) {
  168: 		struct xrpu_timecounting *xt = (struct xrpu_timecounting *)arg;
  169: 
  170: 		/* Name SHALL be zero terminated */
  171: 		xt->xt_name[sizeof xt->xt_name - 1] = '\0';
  172: 		i = strlen(xt->xt_name);
  173: 		sc->tc.tc_name = (char *)malloc(i + 1, M_XRPU, M_WAITOK);
  174: 		strcpy(sc->tc.tc_name, xt->xt_name);
  175: 		sc->tc.tc_frequency = xt->xt_frequency;
  176: 		sc->tc.tc_get_timecount = xrpu_get_timecount;
  177: 		sc->tc.tc_poll_pps = xrpu_poll_pps;
  178: 		sc->tc.tc_priv = sc;
  179: 		sc->tc.tc_counter_mask = xt->xt_mask;
  180: 		sc->trigger = sc->virbase62 + xt->xt_addr_trigger;
  181: 		sc->latch = sc->virbase62 + xt->xt_addr_latch;
  182: 
  183: 		for (i = 0; i < XRPU_MAX_PPS; i++) {
  184: 			if (xt->xt_pps[i].xt_addr_assert == 0
  185: 			    && xt->xt_pps[i].xt_addr_clear == 0)
  186: 				continue;
  187: 			make_dev(&xrpu_cdevsw, (i+1)<<16, 
  188: 			    UID_ROOT, GID_WHEEL, 0600, "xpps%d", i);
  189: 			sc->pps[i].ppscap = 0;
  190: 			if (xt->xt_pps[i].xt_addr_assert) {
  191: 				sc->assert[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_assert;
  192: 				sc->pps[i].ppscap |= PPS_CAPTUREASSERT;
  193: 			}
  194: 			if (xt->xt_pps[i].xt_addr_clear) {
  195: 				sc->clear[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_clear;
  196: 				sc->pps[i].ppscap |= PPS_CAPTURECLEAR;
  197: 			}
  198: 			pps_init(&sc->pps[i]);
  199: 		}
  200: 		sc->mode = TIMECOUNTER;
  201: 		init_timecounter(&sc->tc);
  202: 		return (0);
  203: 	}
  204: #endif
  205: 	error = ENOTTY;
  206: 	return (error);
  207: }
  208: 
  209: /*
  210:  * PCI initialization stuff
  211:  */
  212: 
  213: static int
  214: xrpu_probe(device_t self)
  215: {
  216: 	char *desc;
  217: 
  218: 	desc = NULL;
  219: 	switch (pci_get_devid(self)) {
  220: 	case 0x6216133e:
  221: 		desc = "VCC Hotworks-I xc6216";
  222: 		break;
  223: 	}
  224: 	if (desc == NULL)
  225: 		return ENXIO;
  226: 
  227: 	device_set_desc(self, desc);
  228: 	return 0;
  229: }
  230: 
  231: static int
  232: xrpu_attach(device_t self)
  233: {
  234: 	struct softc *sc;
  235: 	struct resource *res;
  236: 	int rid, unit;
  237: 
  238: 	unit = device_get_unit(self);
  239: 	sc = device_get_softc(self);
  240: 	sc->mode = NORMAL;
  241: 	rid = PCIR_MAPS;
  242: 	res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid,
  243: 				 0, ~0, 1, RF_ACTIVE);
  244: 	if (res == NULL) {
  245: 		device_printf(self, "Could not map memory\n");
  246: 		return ENXIO;
  247: 	}
  248: 	sc->virbase = (vm_offset_t)rman_get_virtual(res);
  249: 	sc->physbase = rman_get_start(res);
  250: 	sc->virbase62 = (u_int *)(sc->virbase + 0x800000);
  251: 
  252: 	if (bootverbose)
  253: 		printf("Mapped physbase %#lx to virbase %#lx\n",
  254: 		    (u_long)sc->physbase, (u_long)sc->virbase);
  255: 
  256: 	make_dev(&xrpu_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "xrpu%d", unit);
  257: 	return 0;
  258: }
  259: 
  260: static device_method_t xrpu_methods[] = {
  261: 	/* Device interface */
  262: 	DEVMETHOD(device_probe,		xrpu_probe),
  263: 	DEVMETHOD(device_attach,	xrpu_attach),
  264: 	DEVMETHOD(device_suspend,	bus_generic_suspend),
  265: 	DEVMETHOD(device_resume,	bus_generic_resume),
  266: 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
  267: 
  268: 	{0, 0}
  269: };
  270:  
  271: static driver_t xrpu_driver = {
  272: 	"xrpu",
  273: 	xrpu_methods,
  274: 	sizeof(struct softc)
  275: };
  276:  
  277:  
  278: DRIVER_MODULE(xrpu, pci, xrpu_driver, xrpu_devclass, 0, 0);