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 (9 years 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);