1e8b8b948671ccbefc4f31661ffa1998f06e1bc7
[nvidia.git] / src / nvidia_dev.c
1 /* _NVRM_COPYRIGHT_BEGIN_
2  *
3  * Copyright 2001-2002 by NVIDIA Corporation.  All rights reserved.  All
4  * information contained herein is proprietary and confidential to NVIDIA
5  * Corporation.  Any use, reproduction, or disclosure without the written
6  * permission of NVIDIA Corporation is prohibited.
7  *
8  * _NVRM_COPYRIGHT_END_
9  */
10
11 #include "nv-misc.h"
12 #include "os-interface.h"
13 #include "nv.h"
14 #include "nv-freebsd.h"
15
16 static d_open_t  nvidia_dev_open;
17 static d_close_t nvidia_dev_close;
18 static d_ioctl_t nvidia_dev_ioctl;
19 static d_poll_t  nvidia_dev_poll;
20 static d_mmap_t  nvidia_dev_mmap;
21
22 static struct dev_ops nvidia_dev_ops = {
23     { "nvidia", CDEV_MAJOR, D_MEM|D_TRACKCLOSE },
24     .d_open =      nvidia_dev_open,
25     .d_close =     nvidia_dev_close,
26     .d_ioctl =     nvidia_dev_ioctl,
27     .d_poll =      nvidia_dev_poll,
28     .d_mmap =      nvidia_dev_mmap,
29 };
30
31 int nvidia_dev_open(
32     struct dev_open_args *ap
33 )
34 {
35     struct cdev *dev = ap->a_head.a_dev;
36     d_thread_t *td = curthread;
37     int status;
38     struct nvidia_softc *sc;
39     nv_state_t *nv;
40     int unit = minor(dev);
41
42     sc = devclass_get_softc(nvidia_devclass, unit);
43     if (!sc)
44         return ENXIO;
45
46     nv = sc->nv_state;
47
48     nv_lock_api(nv);
49     status = nvidia_open_dev(sc, dev, td);
50     nv_unlock_api(nv);
51
52     return status;
53 }
54
55 int nvidia_dev_close(
56     struct dev_close_args *ap
57 )
58 {
59     struct cdev *dev = ap->a_head.a_dev;
60     d_thread_t *td = curthread;
61     int status;
62     struct nvidia_softc *sc;
63     nv_state_t *nv;
64     int unit = minor(dev);
65
66     sc = devclass_get_softc(nvidia_devclass, unit);
67     nv = sc->nv_state;
68
69     nv_lock_api(nv);
70     status = nvidia_close_dev(sc, dev, td);
71     nv_unlock_api(nv);
72
73     return status;
74 }
75
76 int nvidia_dev_ioctl(
77     struct dev_ioctl_args *ap
78 )
79 {
80     struct cdev *dev = ap->a_head.a_dev;
81     u_long cmd = ap->a_cmd;
82     caddr_t data = ap->a_data;
83     int fflag = ap->a_fflag;
84     d_thread_t *td = curthread;
85     int status;
86     struct nvidia_softc *sc;
87     nv_state_t *nv;
88     int unit = minor(dev);
89
90     if (__NV_IOC_TYPE(cmd) != NV_IOCTL_MAGIC)
91         return ENOTTY;
92
93     sc = devclass_get_softc(nvidia_devclass, unit);
94     nv = sc->nv_state;
95
96     nv_lock_api(nv);
97     status = nvidia_handle_ioctl(dev, cmd, data, fflag, td);
98     nv_unlock_api(nv);
99
100     return status;
101 }
102
103 int nvidia_dev_poll(
104     struct dev_poll_args *ap
105 )
106 {
107     struct cdev *dev = ap->a_head.a_dev;
108     int events = ap->a_events;
109     d_thread_t *td = curthread;
110     struct nvidia_softc *sc;
111     nv_state_t *nv;
112     struct nvidia_event *et;
113     int unit = minor(dev);
114
115     sc = devclass_get_softc(nvidia_devclass, unit);
116     nv = sc->nv_state;
117
118     nv_lock_rm(nv);
119
120     STAILQ_FOREACH(et, &sc->event_queue, queue) {
121         if (et->event.file == __TD_FDT(td))
122             break;
123     }
124
125     if (et == NULL) {
126         nv_unlock_rm(nv);
127         selrecord(td, &sc->rsel);
128         ap->a_events = 0;
129     } else {
130         nv_unlock_rm(nv);
131         ap->a_events = (events & (POLLIN | POLLPRI | POLLRDNORM));
132     }
133
134     return 0;
135 }
136
137 int nvidia_dev_mmap(
138     struct dev_mmap_args *ap
139 )
140 {
141     struct cdev *dev = ap->a_head.a_dev;
142     vm_offset_t offset = ap->a_offset;
143     int status;
144     struct nvidia_softc *sc;
145     vm_offset_t physical;
146     nv_state_t *nv;
147     int unit = minor(dev);
148
149     sc = devclass_get_softc(nvidia_devclass, unit);
150     nv = sc->nv_state;
151
152     nv_lock_api(nv);
153     status = nvidia_mmap_dev(sc, offset, &physical);
154     nv_unlock_api(nv);
155
156     if (status != -1)
157         ap->a_result = atop(physical);
158
159     return status;
160 }
161
162 int nvidia_dev_attach(struct nvidia_softc *sc)
163 {
164     dev_ops_add(&nvidia_dev_ops, -1, device_get_unit(sc->dev));
165     sc->cdev = make_dev(&nvidia_dev_ops,
166             device_get_unit(sc->dev),
167             UID_ROOT, GID_WHEEL, 0666,
168             "%s%d", nvidia_dev_ops.head.name,
169             device_get_unit(sc->dev));
170     reference_dev(sc->cdev);
171
172     return 0;
173 }
174
175 int nvidia_dev_detach(struct nvidia_softc *sc)
176 {
177     dev_ops_remove(&nvidia_dev_ops, -1, device_get_unit(sc->dev));
178     destroy_dev(sc->cdev);
179     return 0;
180 }