Change the kernel dev_t, representing a pointer to a specinfo structure,
[dragonfly.git] / sys / dev / misc / xrpu / xrpu.c
CommitLineData
984263bc
MD
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 $
b13267a5 10 * $DragonFly: src/sys/dev/misc/xrpu/Attic/xrpu.c,v 1.11 2006/09/10 01:26:35 dillon Exp $
984263bc
MD
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>
fef8985e 24#include <sys/device.h>
984263bc
MD
25#include <sys/kernel.h>
26#include <sys/malloc.h>
27#include <sys/timepps.h>
28#include <sys/xrpuio.h>
29#include <sys/bus.h>
30#include <machine/bus.h>
31#include <sys/rman.h>
32#include <machine/resource.h>
1f2de5d4
MD
33#include <bus/pci/pcireg.h>
34#include <bus/pci/pcivar.h>
984263bc
MD
35#include "pci_if.h"
36
37/*
38 * Device driver initialization stuff
39 */
40
41static d_open_t xrpu_open;
42static d_close_t xrpu_close;
43static d_ioctl_t xrpu_ioctl;
44static d_mmap_t xrpu_mmap;
45
46#define CDEV_MAJOR 100
fef8985e
MD
47static struct dev_ops xrpu_ops = {
48 { "xrpu", CDEV_MAJOR, 0 },
49 .d_open = xrpu_open,
50 .d_close = xrpu_close,
51 .d_ioctl = xrpu_ioctl,
52 .d_mmap = xrpu_mmap,
984263bc
MD
53};
54
55static MALLOC_DEFINE(M_XRPU, "xrpu", "XRPU related");
56
57static devclass_t xrpu_devclass;
58
59#define dev2unit(devt) (minor(devt) & 0xff)
60#define dev2pps(devt) ((minor(devt) >> 16)-1)
61
62struct softc {
63 enum { NORMAL, TIMECOUNTER } mode;
64 vm_offset_t virbase, physbase;
65 u_int *virbase62;
88c4d2f6 66#if 0
984263bc 67 struct timecounter tc;
88c4d2f6 68#endif
984263bc
MD
69 u_int *trigger, *latch, dummy;
70 struct pps_state pps[XRPU_MAX_PPS];
71 u_int *assert[XRPU_MAX_PPS], *clear[XRPU_MAX_PPS];
72};
73
88c4d2f6
MD
74#if 0
75
984263bc
MD
76static unsigned
77xrpu_get_timecount(struct timecounter *tc)
78{
79 struct softc *sc = tc->tc_priv;
80
81 sc->dummy += *sc->trigger;
82 return (*sc->latch & tc->tc_counter_mask);
83}
84
85static void
86xrpu_poll_pps(struct timecounter *tc)
87{
88 struct softc *sc = tc->tc_priv;
89 int i, j;
90 unsigned count1, ppscount;
91
92 for (i = 0; i < XRPU_MAX_PPS; i++) {
93 if (sc->assert[i]) {
94 ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
95 j = 0;
96 do {
97 count1 = ppscount;
98 ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
99 } while (ppscount != count1 && ++j < 5);
100 pps_event(&sc->pps[i], tc, ppscount, PPS_CAPTUREASSERT);
101 }
102 if (sc->clear[i]) {
103 j = 0;
104 ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
105 do {
106 count1 = ppscount;
107 ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
108 } while (ppscount != count1 && ++j < 5);
109 pps_event(&sc->pps[i], tc, ppscount, PPS_CAPTURECLEAR);
110 }
111 }
112}
113
88c4d2f6
MD
114#endif
115
984263bc 116static int
fef8985e 117xrpu_open(struct dev_open_args *ap)
984263bc 118{
b13267a5 119 cdev_t dev = ap->a_head.a_dev;
984263bc
MD
120 struct softc *sc = devclass_get_softc(xrpu_devclass, dev2unit(dev));
121
122 if (!sc)
123 return (ENXIO);
124 dev->si_drv1 = sc;
125 return (0);
126}
127
128static int
fef8985e
MD
129xrpu_close(struct dev_close_args *ap)
130{
984263bc
MD
131 return (0);
132}
133
134static int
fef8985e 135xrpu_mmap(struct dev_mmap_args *ap)
984263bc 136{
b13267a5 137 cdev_t dev = ap->a_head.a_dev;
984263bc 138 struct softc *sc = dev->si_drv1;
fef8985e
MD
139
140 if (ap->a_offset >= 0x1000000)
984263bc 141 return (-1);
fef8985e 142 return (i386_btop(sc->physbase + ap->a_offset));
984263bc
MD
143}
144
145static int
fef8985e 146xrpu_ioctl(struct dev_ioctl_args *ap)
984263bc 147{
b13267a5 148 cdev_t dev = ap->a_head.a_dev;
984263bc
MD
149 struct softc *sc = dev->si_drv1;
150 int i, error;
151
152 if (sc->mode == TIMECOUNTER) {
153 i = dev2pps(dev);
154 if (i < 0 || i >= XRPU_MAX_PPS)
155 return ENODEV;
fef8985e 156 error = pps_ioctl(ap->a_cmd, ap->a_data, &sc->pps[i]);
984263bc
MD
157 return (error);
158 }
159
88c4d2f6 160#if 0
fef8985e
MD
161 if (ap->a_cmd == XRPU_IOC_TIMECOUNTING) {
162 struct xrpu_timecounting *xt = (struct xrpu_timecounting *)ap->a_data;
984263bc
MD
163
164 /* Name SHALL be zero terminated */
165 xt->xt_name[sizeof xt->xt_name - 1] = '\0';
166 i = strlen(xt->xt_name);
efda3bd0 167 sc->tc.tc_name = (char *)kmalloc(i + 1, M_XRPU, M_WAITOK);
984263bc
MD
168 strcpy(sc->tc.tc_name, xt->xt_name);
169 sc->tc.tc_frequency = xt->xt_frequency;
170 sc->tc.tc_get_timecount = xrpu_get_timecount;
171 sc->tc.tc_poll_pps = xrpu_poll_pps;
172 sc->tc.tc_priv = sc;
173 sc->tc.tc_counter_mask = xt->xt_mask;
174 sc->trigger = sc->virbase62 + xt->xt_addr_trigger;
175 sc->latch = sc->virbase62 + xt->xt_addr_latch;
176
177 for (i = 0; i < XRPU_MAX_PPS; i++) {
178 if (xt->xt_pps[i].xt_addr_assert == 0
179 && xt->xt_pps[i].xt_addr_clear == 0)
180 continue;
fef8985e 181 make_dev(&xrpu_ops, (i+1)<<16,
984263bc
MD
182 UID_ROOT, GID_WHEEL, 0600, "xpps%d", i);
183 sc->pps[i].ppscap = 0;
184 if (xt->xt_pps[i].xt_addr_assert) {
185 sc->assert[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_assert;
186 sc->pps[i].ppscap |= PPS_CAPTUREASSERT;
187 }
188 if (xt->xt_pps[i].xt_addr_clear) {
189 sc->clear[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_clear;
190 sc->pps[i].ppscap |= PPS_CAPTURECLEAR;
191 }
192 pps_init(&sc->pps[i]);
193 }
194 sc->mode = TIMECOUNTER;
195 init_timecounter(&sc->tc);
196 return (0);
197 }
88c4d2f6 198#endif
984263bc
MD
199 error = ENOTTY;
200 return (error);
201}
202
203/*
204 * PCI initialization stuff
205 */
206
207static int
208xrpu_probe(device_t self)
209{
210 char *desc;
211
212 desc = NULL;
213 switch (pci_get_devid(self)) {
214 case 0x6216133e:
215 desc = "VCC Hotworks-I xc6216";
216 break;
217 }
218 if (desc == NULL)
219 return ENXIO;
220
221 device_set_desc(self, desc);
222 return 0;
223}
224
225static int
226xrpu_attach(device_t self)
227{
228 struct softc *sc;
229 struct resource *res;
230 int rid, unit;
231
232 unit = device_get_unit(self);
233 sc = device_get_softc(self);
234 sc->mode = NORMAL;
235 rid = PCIR_MAPS;
236 res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid,
237 0, ~0, 1, RF_ACTIVE);
238 if (res == NULL) {
239 device_printf(self, "Could not map memory\n");
240 return ENXIO;
241 }
242 sc->virbase = (vm_offset_t)rman_get_virtual(res);
243 sc->physbase = rman_get_start(res);
244 sc->virbase62 = (u_int *)(sc->virbase + 0x800000);
245
246 if (bootverbose)
247 printf("Mapped physbase %#lx to virbase %#lx\n",
248 (u_long)sc->physbase, (u_long)sc->virbase);
249
fef8985e
MD
250 dev_ops_add(&xrpu_ops, -1, unit);
251 make_dev(&xrpu_ops, unit, UID_ROOT, GID_WHEEL, 0600, "xrpu%d", unit);
984263bc
MD
252 return 0;
253}
254
255static device_method_t xrpu_methods[] = {
256 /* Device interface */
257 DEVMETHOD(device_probe, xrpu_probe),
258 DEVMETHOD(device_attach, xrpu_attach),
259 DEVMETHOD(device_suspend, bus_generic_suspend),
260 DEVMETHOD(device_resume, bus_generic_resume),
261 DEVMETHOD(device_shutdown, bus_generic_shutdown),
262
263 {0, 0}
264};
265
266static driver_t xrpu_driver = {
267 "xrpu",
268 xrpu_methods,
269 sizeof(struct softc)
270};
271
272
273DRIVER_MODULE(xrpu, pci, xrpu_driver, xrpu_devclass, 0, 0);