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