Bug Summary

File:dev/midi.c
Warning:line 508, column 2
Value stored to 'error' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name midi.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/midi.c
1/* $OpenBSD: midi.c,v 1.52 2021/10/30 12:48:11 ratchov Exp $ */
2
3/*
4 * Copyright (c) 2003, 2004 Alexandre Ratchov
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/fcntl.h>
21#include <sys/systm.h>
22#include <sys/ioctl.h>
23#include <sys/conf.h>
24#include <sys/poll.h>
25#include <sys/kernel.h>
26#include <sys/timeout.h>
27#include <sys/vnode.h>
28#include <sys/signalvar.h>
29#include <sys/device.h>
30
31#include <dev/midi_if.h>
32#include <dev/audio_if.h>
33#include <dev/midivar.h>
34
35#define IPL_SOFTMIDI0x5 IPL_SOFTNET0x5
36#define DEVNAME(sc)((sc)->dev.dv_xname) ((sc)->dev.dv_xname)
37
38int midiopen(dev_t, int, int, struct proc *);
39int midiclose(dev_t, int, int, struct proc *);
40int midiread(dev_t, struct uio *, int);
41int midiwrite(dev_t, struct uio *, int);
42int midipoll(dev_t, int, struct proc *);
43int midikqfilter(dev_t, struct knote *);
44int midiioctl(dev_t, u_long, caddr_t, int, struct proc *);
45int midiprobe(struct device *, void *, void *);
46void midiattach(struct device *, struct device *, void *);
47int mididetach(struct device *, int);
48int midiprint(void *, const char *);
49
50void midi_iintr(void *, int);
51void midi_ointr(void *);
52void midi_timeout(void *);
53void midi_out_start(struct midi_softc *);
54void midi_out_stop(struct midi_softc *);
55void midi_out_do(struct midi_softc *);
56void midi_attach(struct midi_softc *, struct device *);
57
58
59struct cfattach midi_ca = {
60 sizeof(struct midi_softc), midiprobe, midiattach, mididetach
61};
62
63struct cfdriver midi_cd = {
64 NULL((void *)0), "midi", DV_DULL
65};
66
67
68void filt_midiwdetach(struct knote *);
69int filt_midiwrite(struct knote *, long);
70
71const struct filterops midiwrite_filtops = {
72 .f_flags = FILTEROP_ISFD0x00000001,
73 .f_attach = NULL((void *)0),
74 .f_detach = filt_midiwdetach,
75 .f_event = filt_midiwrite,
76};
77
78void filt_midirdetach(struct knote *);
79int filt_midiread(struct knote *, long);
80
81const struct filterops midiread_filtops = {
82 .f_flags = FILTEROP_ISFD0x00000001,
83 .f_attach = NULL((void *)0),
84 .f_detach = filt_midirdetach,
85 .f_event = filt_midiread,
86};
87
88void
89midi_buf_wakeup(void *addr)
90{
91 struct midi_buffer *buf = addr;
92
93 if (buf->blocking) {
94 wakeup(&buf->blocking);
95 buf->blocking = 0;
96 }
97 /*
98 * As long as selwakeup() grabs the KERNEL_LOCK() make sure it is
99 * already held here to avoid lock ordering problems with `audio_lock'
100 */
101 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/midi.c"
, 101, "_kernel_lock_held()"))
;
102 mtx_enter(&audio_lock);
103 selwakeup(&buf->sel);
104 mtx_leave(&audio_lock);
105}
106
107void
108midi_iintr(void *addr, int data)
109{
110 struct midi_softc *sc = (struct midi_softc *)addr;
111 struct midi_buffer *mb = &sc->inbuf;
112
113 MUTEX_ASSERT_LOCKED(&audio_lock)do { if (((&audio_lock)->mtx_owner != ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})) && !(panicstr ||
db_active)) panic("mutex %p not held in %s", (&audio_lock
), __func__); } while (0)
;
114 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001) || !(sc->flags & FREAD0x0001))
115 return;
116
117 if (MIDIBUF_ISFULL(mb)((mb)->used >= (1 << 10)))
118 return; /* discard data */
119
120 MIDIBUF_WRITE(mb, data)do { (mb)->data[(((mb)->start + (mb)->used) & ((
1 << 10) - 1))] = (data); (mb)->used++; } while(0)
;
121
122 /*
123 * As long as selwakeup() needs to be protected by the
124 * KERNEL_LOCK() we have to delay the wakeup to another
125 * context to keep the interrupt context KERNEL_LOCK()
126 * free.
127 */
128 softintr_schedule(sc->inbuf.softintr)do { struct x86_soft_intrhand *__sih = (sc->inbuf.softintr
); struct x86_soft_intr *__si = __sih->sih_intrhead; mtx_enter
(&__si->softintr_lock); if (__sih->sih_pending == 0
) { do { (__sih)->sih_q.tqe_next = ((void *)0); (__sih)->
sih_q.tqe_prev = (&__si->softintr_q)->tqh_last; *(&
__si->softintr_q)->tqh_last = (__sih); (&__si->softintr_q
)->tqh_last = &(__sih)->sih_q.tqe_next; } while (0)
; __sih->sih_pending = 1; softintr(__si->softintr_ssir)
; } mtx_leave(&__si->softintr_lock); } while ( 0)
;
129}
130
131int
132midiread(dev_t dev, struct uio *uio, int ioflag)
133{
134 struct midi_softc *sc;
135 struct midi_buffer *mb;
136 size_t count;
137 int error;
138
139 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
140 if (sc == NULL((void *)0))
141 return ENXIO6;
142 if (!(sc->flags & FREAD0x0001)) {
143 error = ENXIO6;
144 goto done;
145 }
146 mb = &sc->inbuf;
147
148 /* if there is no data then sleep (unless IO_NDELAY flag is set) */
149 error = 0;
150 mtx_enter(&audio_lock);
151 while (MIDIBUF_ISEMPTY(mb)((mb)->used == 0)) {
152 if (ioflag & IO_NDELAY0x10) {
153 error = EWOULDBLOCK35;
154 goto done_mtx;
155 }
156 sc->inbuf.blocking = 1;
157 error = msleep_nsec(&sc->inbuf.blocking, &audio_lock,
158 PWAIT32 | PCATCH0x100, "mid_rd", INFSLP0xffffffffffffffffULL);
159 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
160 error = EIO5;
161 if (error)
162 goto done_mtx;
163 }
164
165 /* at this stage, there is at least 1 byte */
166
167 while (uio->uio_resid > 0 && mb->used > 0) {
168 count = MIDIBUF_SIZE(1 << 10) - mb->start;
169 if (count > mb->used)
170 count = mb->used;
171 if (count > uio->uio_resid)
172 count = uio->uio_resid;
173 mtx_leave(&audio_lock);
174 error = uiomove(mb->data + mb->start, count, uio);
175 if (error)
176 goto done;
177 mtx_enter(&audio_lock);
178 MIDIBUF_REMOVE(mb, count)do { (mb)->start += (count); (mb)->start &= ((1 <<
10) - 1); (mb)->used -= (count); } while(0)
;
179 }
180
181done_mtx:
182 mtx_leave(&audio_lock);
183done:
184 device_unref(&sc->dev);
185 return error;
186}
187
188void
189midi_ointr(void *addr)
190{
191 struct midi_softc *sc = (struct midi_softc *)addr;
192 struct midi_buffer *mb;
193
194 MUTEX_ASSERT_LOCKED(&audio_lock)do { if (((&audio_lock)->mtx_owner != ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})) && !(panicstr ||
db_active)) panic("mutex %p not held in %s", (&audio_lock
), __func__); } while (0)
;
195 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001) || !(sc->flags & FWRITE0x0002))
196 return;
197
198 mb = &sc->outbuf;
199 if (mb->used > 0) {
200#ifdef MIDI_DEBUG
201 if (!sc->isbusy) {
202 printf("midi_ointr: output must be busy\n");
203 }
204#endif
205 midi_out_do(sc);
206 } else if (sc->isbusy)
207 midi_out_stop(sc);
208}
209
210void
211midi_timeout(void *addr)
212{
213 mtx_enter(&audio_lock);
214 midi_ointr(addr);
215 mtx_leave(&audio_lock);
216}
217
218void
219midi_out_start(struct midi_softc *sc)
220{
221 if (!sc->isbusy) {
222 sc->isbusy = 1;
223 midi_out_do(sc);
224 }
225}
226
227void
228midi_out_stop(struct midi_softc *sc)
229{
230 sc->isbusy = 0;
231
232 /*
233 * As long as selwakeup() needs to be protected by the
234 * KERNEL_LOCK() we have to delay the wakeup to another
235 * context to keep the interrupt context KERNEL_LOCK()
236 * free.
237 */
238 softintr_schedule(sc->outbuf.softintr)do { struct x86_soft_intrhand *__sih = (sc->outbuf.softintr
); struct x86_soft_intr *__si = __sih->sih_intrhead; mtx_enter
(&__si->softintr_lock); if (__sih->sih_pending == 0
) { do { (__sih)->sih_q.tqe_next = ((void *)0); (__sih)->
sih_q.tqe_prev = (&__si->softintr_q)->tqh_last; *(&
__si->softintr_q)->tqh_last = (__sih); (&__si->softintr_q
)->tqh_last = &(__sih)->sih_q.tqe_next; } while (0)
; __sih->sih_pending = 1; softintr(__si->softintr_ssir)
; } mtx_leave(&__si->softintr_lock); } while ( 0)
;
239}
240
241void
242midi_out_do(struct midi_softc *sc)
243{
244 struct midi_buffer *mb = &sc->outbuf;
245
246 while (mb->used > 0) {
247 if (!sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]))
248 break;
249 MIDIBUF_REMOVE(mb, 1)do { (mb)->start += (1); (mb)->start &= ((1 <<
10) - 1); (mb)->used -= (1); } while(0)
;
250 if (MIDIBUF_ISEMPTY(mb)((mb)->used == 0)) {
251 if (sc->hw_if->flush != NULL((void *)0))
252 sc->hw_if->flush(sc->hw_hdl);
253 midi_out_stop(sc);
254 return;
255 }
256 }
257
258 if (!(sc->props & MIDI_PROP_OUT_INTR1)) {
259 if (MIDIBUF_ISEMPTY(mb)((mb)->used == 0))
260 midi_out_stop(sc);
261 else
262 timeout_add(&sc->timeo, 1);
263 }
264}
265
266int
267midiwrite(dev_t dev, struct uio *uio, int ioflag)
268{
269 struct midi_softc *sc;
270 struct midi_buffer *mb;
271 size_t count;
272 int error;
273
274 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
275 if (sc == NULL((void *)0))
276 return ENXIO6;
277 if (!(sc->flags & FWRITE0x0002)) {
278 error = ENXIO6;
279 goto done;
280 }
281 mb = &sc->outbuf;
282
283 /*
284 * If IO_NDELAY flag is set then check if there is enough room
285 * in the buffer to store at least one byte. If not then dont
286 * start the write process.
287 */
288 error = 0;
289 mtx_enter(&audio_lock);
290 if ((ioflag & IO_NDELAY0x10) && MIDIBUF_ISFULL(mb)((mb)->used >= (1 << 10)) && (uio->uio_resid > 0)) {
291 error = EWOULDBLOCK35;
292 goto done_mtx;
293 }
294
295 while (uio->uio_resid > 0) {
296 while (MIDIBUF_ISFULL(mb)((mb)->used >= (1 << 10))) {
297 if (ioflag & IO_NDELAY0x10) {
298 /*
299 * At this stage at least one byte is already
300 * moved so we do not return EWOULDBLOCK
301 */
302 goto done_mtx;
303 }
304 sc->outbuf.blocking = 1;
305 error = msleep_nsec(&sc->outbuf.blocking, &audio_lock,
306 PWAIT32 | PCATCH0x100, "mid_wr", INFSLP0xffffffffffffffffULL);
307 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
308 error = EIO5;
309 if (error)
310 goto done_mtx;
311 }
312
313 count = MIDIBUF_SIZE(1 << 10) - MIDIBUF_END(mb)(((mb)->start + (mb)->used) & ((1 << 10) - 1)
)
;
314 if (count > MIDIBUF_AVAIL(mb)((1 << 10) - (mb)->used))
315 count = MIDIBUF_AVAIL(mb)((1 << 10) - (mb)->used);
316 if (count > uio->uio_resid)
317 count = uio->uio_resid;
318 mtx_leave(&audio_lock);
319 error = uiomove(mb->data + MIDIBUF_END(mb)(((mb)->start + (mb)->used) & ((1 << 10) - 1)
)
, count, uio);
320 if (error)
321 goto done;
322 mtx_enter(&audio_lock);
323 mb->used += count;
324 midi_out_start(sc);
325 }
326
327done_mtx:
328 mtx_leave(&audio_lock);
329done:
330 device_unref(&sc->dev);
331 return error;
332}
333
334int
335midipoll(dev_t dev, int events, struct proc *p)
336{
337 struct midi_softc *sc;
338 int revents;
339
340 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
341 if (sc == NULL((void *)0))
342 return POLLERR0x0008;
343 revents = 0;
344 mtx_enter(&audio_lock);
345 if (events & (POLLIN0x0001 | POLLRDNORM0x0040)) {
346 if (!MIDIBUF_ISEMPTY(&sc->inbuf)((&sc->inbuf)->used == 0))
347 revents |= events & (POLLIN0x0001 | POLLRDNORM0x0040);
348 }
349 if (events & (POLLOUT0x0004 | POLLWRNORM0x0004)) {
350 if (!MIDIBUF_ISFULL(&sc->outbuf)((&sc->outbuf)->used >= (1 << 10)))
351 revents |= events & (POLLOUT0x0004 | POLLWRNORM0x0004);
352 }
353 if (revents == 0) {
354 if (events & (POLLIN0x0001 | POLLRDNORM0x0040))
355 selrecord(p, &sc->inbuf.sel);
356 if (events & (POLLOUT0x0004 | POLLWRNORM0x0004))
357 selrecord(p, &sc->outbuf.sel);
358 }
359 mtx_leave(&audio_lock);
360 device_unref(&sc->dev);
361 return (revents);
362}
363
364int
365midikqfilter(dev_t dev, struct knote *kn)
366{
367 struct midi_softc *sc;
368 struct klist *klist;
369 int error;
370
371 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
372 if (sc == NULL((void *)0))
373 return ENXIO6;
374 error = 0;
375 switch (kn->kn_filterkn_kevent.filter) {
376 case EVFILT_READ(-1):
377 klist = &sc->inbuf.sel.si_note;
378 kn->kn_fop = &midiread_filtops;
379 break;
380 case EVFILT_WRITE(-2):
381 klist = &sc->outbuf.sel.si_note;
382 kn->kn_fop = &midiwrite_filtops;
383 break;
384 default:
385 error = EINVAL22;
386 goto done;
387 }
388 kn->kn_hook = (void *)sc;
389
390 mtx_enter(&audio_lock);
391 klist_insert_locked(klist, kn);
392 mtx_leave(&audio_lock);
393done:
394 device_unref(&sc->dev);
395 return error;
396}
397
398void
399filt_midirdetach(struct knote *kn)
400{
401 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
402
403 mtx_enter(&audio_lock);
404 klist_remove_locked(&sc->inbuf.sel.si_note, kn);
405 mtx_leave(&audio_lock);
406}
407
408int
409filt_midiread(struct knote *kn, long hint)
410{
411 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
412 int retval;
413
414 if ((hint & NOTE_SUBMIT0x01000000) == 0)
415 mtx_enter(&audio_lock);
416 retval = !MIDIBUF_ISEMPTY(&sc->inbuf)((&sc->inbuf)->used == 0);
417 if ((hint & NOTE_SUBMIT0x01000000) == 0)
418 mtx_leave(&audio_lock);
419
420 return (retval);
421}
422
423void
424filt_midiwdetach(struct knote *kn)
425{
426 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
427
428 mtx_enter(&audio_lock);
429 klist_remove_locked(&sc->outbuf.sel.si_note, kn);
430 mtx_leave(&audio_lock);
431}
432
433int
434filt_midiwrite(struct knote *kn, long hint)
435{
436 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
437 int retval;
438
439 if ((hint & NOTE_SUBMIT0x01000000) == 0)
440 mtx_enter(&audio_lock);
441 retval = !MIDIBUF_ISFULL(&sc->outbuf)((&sc->outbuf)->used >= (1 << 10));
442 if ((hint & NOTE_SUBMIT0x01000000) == 0)
443 mtx_leave(&audio_lock);
444
445 return (retval);
446}
447
448int
449midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
450{
451 struct midi_softc *sc;
452 int error;
453
454 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
455 if (sc == NULL((void *)0))
456 return ENXIO6;
457 error = 0;
458 switch(cmd) {
459 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
460 /* All handled in the upper FS layer */
461 break;
462 default:
463 error = ENOTTY25;
464 }
465 device_unref(&sc->dev);
466 return error;
467}
468
469int
470midiopen(dev_t dev, int flags, int mode, struct proc *p)
471{
472 struct midi_softc *sc;
473 int error;
474
475 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
476 if (sc == NULL((void *)0))
477 return ENXIO6;
478 error = 0;
479 if (sc->flags) {
480 error = EBUSY16;
481 goto done;
482 }
483 MIDIBUF_INIT(&sc->inbuf)do { (&sc->inbuf)->start = (&sc->inbuf)->
used = 0; } while(0)
;
484 MIDIBUF_INIT(&sc->outbuf)do { (&sc->outbuf)->start = (&sc->outbuf)->
used = 0; } while(0)
;
485 sc->isbusy = 0;
486 sc->inbuf.blocking = sc->outbuf.blocking = 0;
487 sc->flags = flags;
488 error = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc);
489 if (error)
490 sc->flags = 0;
491done:
492 device_unref(&sc->dev);
493 return error;
494}
495
496int
497midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
498{
499 struct midi_softc *sc;
500 struct midi_buffer *mb;
501 int error;
502
503 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
504 if (sc == NULL((void *)0))
505 return ENXIO6;
506
507 /* start draining output buffer */
508 error = 0;
Value stored to 'error' is never read
509 mb = &sc->outbuf;
510 mtx_enter(&audio_lock);
511 if (!MIDIBUF_ISEMPTY(mb)((mb)->used == 0))
512 midi_out_start(sc);
513 while (sc->isbusy) {
514 sc->outbuf.blocking = 1;
515 error = msleep_nsec(&sc->outbuf.blocking, &audio_lock,
516 PWAIT32, "mid_dr", SEC_TO_NSEC(5));
517 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
518 error = EIO5;
519 if (error)
520 break;
521 }
522 mtx_leave(&audio_lock);
523
524 /*
525 * some hw_if->close() reset immediately the midi uart
526 * which flushes the internal buffer of the uart device,
527 * so we may lose some (important) data. To avoid this,
528 * sleep 20ms (around 64 bytes) to give the time to the
529 * uart to drain its internal buffers.
530 */
531 tsleep_nsec(&sc->outbuf.blocking, PWAIT32, "mid_cl", MSEC_TO_NSEC(20));
532 sc->hw_if->close(sc->hw_hdl);
533 sc->flags = 0;
534 device_unref(&sc->dev);
535 return 0;
536}
537
538int
539midiprobe(struct device *parent, void *match, void *aux)
540{
541 struct audio_attach_args *sa = aux;
542
543 return (sa != NULL((void *)0) && (sa->type == AUDIODEV_TYPE_MIDI1) ? 1 : 0);
544}
545
546void
547midiattach(struct device *parent, struct device *self, void *aux)
548{
549 struct midi_info mi;
550 struct midi_softc *sc = (struct midi_softc *)self;
551 struct audio_attach_args *sa = (struct audio_attach_args *)aux;
552 struct midi_hw_if *hwif = sa->hwif;
553 void *hdl = sa->hdl;
554
555#ifdef DIAGNOSTIC1
556 if (hwif == 0 ||
557 hwif->open == 0 ||
558 hwif->close == 0 ||
559 hwif->output == 0 ||
560 hwif->getinfo == 0) {
561 printf("%s: missing method\n", DEVNAME(sc)((sc)->dev.dv_xname));
562 return;
563 }
564#endif
565
566 sc->inbuf.softintr = softintr_establish(IPL_SOFTMIDI0x5,
567 midi_buf_wakeup, &sc->inbuf);
568 if (sc->inbuf.softintr == NULL((void *)0)) {
569 printf("%s: can't establish input softintr\n", DEVNAME(sc)((sc)->dev.dv_xname));
570 return;
571 }
572
573 sc->outbuf.softintr = softintr_establish(IPL_SOFTMIDI0x5,
574 midi_buf_wakeup, &sc->outbuf);
575 if (sc->outbuf.softintr == NULL((void *)0)) {
576 printf("%s: can't establish output softintr\n", DEVNAME(sc)((sc)->dev.dv_xname));
577 softintr_disestablish(sc->inbuf.softintr);
578 return;
579 }
580
581 sc->hw_if = hwif;
582 sc->hw_hdl = hdl;
583 sc->hw_if->getinfo(sc->hw_hdl, &mi);
584 sc->props = mi.props;
585 sc->flags = 0;
586 timeout_set(&sc->timeo, midi_timeout, sc);
587 printf(": <%s>\n", mi.name);
588}
589
590int
591mididetach(struct device *self, int flags)
592{
593 struct midi_softc *sc = (struct midi_softc *)self;
594 int maj, mn;
595
596 /* locate the major number */
597 for (maj = 0; maj < nchrdev; maj++) {
598 if (cdevsw[maj].d_open == midiopen) {
599 /* Nuke the vnodes for any open instances (calls close). */
600 mn = self->dv_unit;
601 vdevgone(maj, mn, mn, VCHR);
602 }
603 }
604
605 /*
606 * The close() method did nothing (device_lookup() returns
607 * NULL), so quickly halt transfers (normally parent is already
608 * gone, and code below is no-op), and wake-up user-land blocked
609 * in read/write/ioctl, which return EIO.
610 */
611 if (sc->flags) {
612 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/midi.c"
, 612, "_kernel_lock_held()"))
;
613 if (sc->flags & FREAD0x0001) {
614 wakeup(&sc->inbuf.blocking);
615 mtx_enter(&audio_lock);
616 selwakeup(&sc->inbuf.sel);
617 mtx_leave(&audio_lock);
618 }
619 if (sc->flags & FWRITE0x0002) {
620 wakeup(&sc->outbuf.blocking);
621 mtx_enter(&audio_lock);
622 selwakeup(&sc->outbuf.sel);
623 mtx_leave(&audio_lock);
624 }
625 sc->hw_if->close(sc->hw_hdl);
626 sc->flags = 0;
627 }
628
629 klist_invalidate(&sc->inbuf.sel.si_note);
630 klist_invalidate(&sc->outbuf.sel.si_note);
631
632 if (sc->inbuf.softintr)
633 softintr_disestablish(sc->inbuf.softintr);
634 if (sc->outbuf.softintr)
635 softintr_disestablish(sc->outbuf.softintr);
636 return 0;
637}
638
639int
640midiprint(void *aux, const char *pnp)
641{
642 if (pnp)
643 printf("midi at %s", pnp);
644 return (UNCONF1);
645}
646
647struct device *
648midi_attach_mi(struct midi_hw_if *hwif, void *hdl, struct device *dev)
649{
650 struct audio_attach_args arg;
651
652 arg.type = AUDIODEV_TYPE_MIDI1;
653 arg.hwif = hwif;
654 arg.hdl = hdl;
655 return config_found(dev, &arg, midiprint)config_found_sm((dev), (&arg), (midiprint), ((void *)0));
656}