1 /* $NetBSD: ucbsnd.c,v 1.18 2008/04/28 20:23:21 martin Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end
36 * /dev/ucbsnd0 : sampling rate 22.154kHz monoral 16bit straight PCM device.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: ucbsnd.c,v 1.18 2008/04/28 20:23:21 martin Exp $");
42 #include "opt_use_poll.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
47 #include <sys/malloc.h>
48 #include <sys/device.h>
50 #include <sys/endian.h>
52 #include <mips/cache.h>
54 #include <machine/bus.h>
55 #include <machine/intr.h>
57 #include <hpcmips/tx/tx39var.h>
58 #include <hpcmips/tx/tx39sibvar.h>
59 #include <hpcmips/tx/tx39sibreg.h>
60 #include <hpcmips/tx/tx39icureg.h>
61 #include <hpcmips/tx/txsnd.h>
63 #include <hpcmips/dev/ucb1200var.h>
64 #include <hpcmips/dev/ucb1200reg.h>
66 #define AUDIOUNIT(x) (minor(x)&0x0f)
67 #define AUDIODEV(x) (minor(x)&0xf0)
71 #define DPRINTF(arg) if (ucbsnd_debug) printf arg;
72 #define DPRINTFN(n, arg) if (ucbsnd_debug > (n)) printf arg;
75 #define DPRINTFN(n, arg)
78 #define UCBSND_BUFBLOCK 5
80 * XXX temporary DMA buffer
82 static u_int8_t dmabuf_static
[TX39_SIBDMA_SIZE
* UCBSND_BUFBLOCK
] __attribute__((__aligned__(16))); /* XXX */
83 static size_t dmabufcnt_static
[UCBSND_BUFBLOCK
]; /* XXX */
88 /* 2 */ UCBSND_ENABLE_SAMPLERATE
,
89 /* 3 */ UCBSND_ENABLE_OUTPUTPATH
,
90 /* 4 */ UCBSND_ENABLE_SETVOLUME
,
91 /* 5 */ UCBSND_ENABLE_SPEAKER0
,
92 /* 6 */ UCBSND_ENABLE_SPEAKER1
,
93 /* 7 */ UCBSND_TRANSITION_PIO
,
95 /* 9 */ UCBSND_TRANSITION_DISABLE
,
96 /*10 */ UCBSND_DISABLE_OUTPUTPATH
,
97 /*11 */ UCBSND_DISABLE_SPEAKER0
,
98 /*12 */ UCBSND_DISABLE_SPEAKER1
,
99 /*13 */ UCBSND_DISABLE_SIB
,
100 /*14 */ UCBSND_DMASTART
,
101 /*15 */ UCBSND_DMAEND
,
105 u_int32_t rb_buf
; /* buffer start address */
106 size_t *rb_bufcnt
; /* effective data count (max rb_blksize)*/
108 size_t rb_bufsize
; /* total amount of buffer */
109 int rb_blksize
; /* DMA block size */
110 int rb_maxblks
; /* # of blocks in ring */
112 int rb_inp
; /* start of input (to buffer) */
113 int rb_outp
; /* output pointer */
116 struct ucbsnd_softc
{
117 struct device sc_dev
;
118 struct device
*sc_sib
; /* parent (TX39 SIB module) */
119 struct device
*sc_ucb
; /* parent (UCB1200 module) */
120 tx_chipset_tag_t sc_tc
;
122 struct tx_sound_tag sc_tag
;
126 * audio codec state machine
128 int sa_transfer_mode
;
129 #define UCBSND_TRANSFERMODE_DMA 0
130 #define UCBSND_TRANSFERMODE_PIO 1
131 enum ucbsnd_state sa_state
;
132 int sa_snd_attenuation
;
133 #define UCBSND_DEFAULT_ATTENUATION 0 /* Full volume */
134 int sa_snd_rate
; /* passed down from SIB module */
139 int sa_cnt
; /* misc counter */
145 struct ring_buf sc_rb
;
148 int ucbsnd_match(struct device
*, struct cfdata
*, void*);
149 void ucbsnd_attach(struct device
*, struct device
*, void*);
151 int ucbsnd_exec_output(void*);
152 int ucbsnd_busy(void*);
154 void ucbsnd_sound_init(struct ucbsnd_softc
*);
155 void __ucbsnd_sound_click(tx_sound_tag_t
);
156 void __ucbsnd_sound_mute(tx_sound_tag_t
, int);
158 int ucbsndwrite_subr(struct ucbsnd_softc
*, u_int32_t
*, size_t,
161 int ringbuf_allocate(struct ring_buf
*, size_t, int);
162 void ringbuf_deallocate(struct ring_buf
*);
163 void ringbuf_reset(struct ring_buf
*);
164 int ringbuf_full(struct ring_buf
*);
165 void *ringbuf_producer_get(struct ring_buf
*);
166 void ringbuf_producer_return(struct ring_buf
*, size_t);
167 void *ringbuf_consumer_get(struct ring_buf
*, size_t*);
168 void ringbuf_consumer_return(struct ring_buf
*);
170 CFATTACH_DECL(ucbsnd
, sizeof(struct ucbsnd_softc
),
171 ucbsnd_match
, ucbsnd_attach
, NULL
, NULL
);
173 dev_type_open(ucbsndopen
);
174 dev_type_close(ucbsndclose
);
175 dev_type_read(ucbsndread
);
176 dev_type_write(ucbsndwrite
);
178 const struct cdevsw ucbsnd_cdevsw
= {
179 ucbsndopen
, ucbsndclose
, ucbsndread
, ucbsndwrite
, nullioctl
,
180 nostop
, notty
, nopoll
, nullmmap
, nokqfilter
,
184 ucbsnd_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
191 ucbsnd_attach(struct device
*parent
, struct device
*self
, void *aux
)
193 struct ucb1200_attach_args
*ucba
= aux
;
194 struct ucbsnd_softc
*sc
= (void*)self
;
197 tc
= sc
->sc_tc
= ucba
->ucba_tc
;
198 sc
->sc_sib
= ucba
->ucba_sib
;
199 sc
->sc_ucb
= ucba
->ucba_ucb
;
201 /* register sound functions */
202 ucbsnd_sound_init(sc
);
204 sc
->sa_snd_rate
= ucba
->ucba_snd_rate
;
205 sc
->sa_tel_rate
= ucba
->ucba_tel_rate
;
207 sc
->sa_snd_attenuation
= UCBSND_DEFAULT_ATTENUATION
;
208 #define KHZ(a) ((a) / 1000), (((a) % 1000))
209 printf(": audio %d.%03d kHz telecom %d.%03d kHz",
210 KHZ((tx39sib_clock(sc
->sc_sib
) * 2) /
211 (sc
->sa_snd_rate
* 64)),
212 KHZ((tx39sib_clock(sc
->sc_sib
) * 2) /
213 (sc
->sa_tel_rate
* 64)));
215 ucb1200_state_install(parent
, ucbsnd_busy
, self
,
218 ringbuf_allocate(&sc
->sc_rb
, TX39_SIBDMA_SIZE
, UCBSND_BUFBLOCK
);
224 ucbsnd_busy(void *arg
)
226 struct ucbsnd_softc
*sc
= arg
;
228 return (sc
->sa_state
!= UCBSND_IDLE
);
232 ucbsnd_exec_output(void *arg
)
234 struct ucbsnd_softc
*sc
= arg
;
235 tx_chipset_tag_t tc
= sc
->sc_tc
;
240 switch (sc
->sa_state
) {
242 panic("ucbsnd_exec_output: invalid state %d", sc
->sa_state
);
251 sc
->sa_sf0ih
= tx_intr_establish(
252 tc
, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT
),
253 IST_EDGE
, IPL_TTY
, ucbsnd_exec_output
, sc
);
255 sc
->sa_state
= UCBSND_ENABLE_SAMPLERATE
;
258 case UCBSND_ENABLE_SAMPLERATE
:
259 /* Enable UCB1200 side sample rate */
260 reg
= TX39_SIBSF0_WRITE
;
261 reg
= TX39_SIBSF0_REGADDR_SET(reg
, UCB1200_AUDIOCTRLA_REG
);
262 reg
= TX39_SIBSF0_REGDATA_SET(reg
, sc
->sa_snd_rate
);
263 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, reg
);
265 sc
->sa_state
= UCBSND_ENABLE_OUTPUTPATH
;
268 case UCBSND_ENABLE_OUTPUTPATH
:
269 /* Enable UCB1200 side */
270 reg
= TX39_SIBSF0_WRITE
;
271 reg
= TX39_SIBSF0_REGADDR_SET(reg
, UCB1200_AUDIOCTRLB_REG
);
272 reg
= TX39_SIBSF0_REGDATA_SET(reg
, sc
->sa_snd_attenuation
|
273 UCB1200_AUDIOCTRLB_OUTEN
);
274 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, reg
);
276 /* Enable SIB side */
277 reg
= tx_conf_read(tc
, TX39_SIBCTRL_REG
);
278 tx_conf_write(tc
, TX39_SIBCTRL_REG
,
279 reg
| TX39_SIBCTRL_ENSND
);
281 sc
->sa_state
= UCBSND_ENABLE_SPEAKER0
;
284 case UCBSND_ENABLE_SPEAKER0
:
287 reg
= TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG
);
288 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, reg
);
290 sc
->sa_state
= UCBSND_ENABLE_SPEAKER1
;
293 case UCBSND_ENABLE_SPEAKER1
:
294 reg
= tx_conf_read(tc
, TX39_SIBSF0STAT_REG
);
295 if ((TX39_SIBSF0_REGADDR(reg
) != UCB1200_IO_DATA_REG
) &&
296 --sc
->sa_retry
> 0) {
298 sc
->sa_state
= UCBSND_ENABLE_SPEAKER0
;
302 if (sc
->sa_retry
<= 0) {
303 printf("ucbsnd_exec_output: subframe0 busy\n");
305 sc
->sa_state
= UCBSND_IDLE
;
309 reg
|= TX39_SIBSF0_WRITE
;
310 reg
|= UCB1200_IO_DATA_SPEAKER
;
311 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, reg
);
316 switch (sc
->sa_transfer_mode
) {
317 case UCBSND_TRANSFERMODE_DMA
:
318 sc
->sa_state
= UCBSND_DMASTART
;
321 case UCBSND_TRANSFERMODE_PIO
:
322 sc
->sa_state
= UCBSND_TRANSITION_PIO
;
327 case UCBSND_DMASTART
:
329 if (sc
->sa_dmacnt
) /* return previous buffer */
330 ringbuf_consumer_return(&sc
->sc_rb
);
331 buf
= ringbuf_consumer_get(&sc
->sc_rb
, &bufcnt
);
333 sc
->sa_state
= UCBSND_DMAEND
;
337 if (sc
->sa_dmacnt
== 0) {
338 /* change interrupt source */
340 tx_intr_disestablish(tc
, sc
->sa_sf0ih
);
343 sc
->sa_sndih
= tx_intr_establish(
344 tc
, MAKEINTR(1, TX39_INTRSTATUS1_SND1_0INT
),
345 IST_EDGE
, IPL_TTY
, ucbsnd_exec_output
, sc
);
350 /* set DMA buffer address */
351 tx_conf_write(tc
, TX39_SIBSNDTXSTART_REG
,
352 MIPS_KSEG0_TO_PHYS(buf
));
354 /* set DMA buffer size */
355 tx_conf_write(tc
, TX39_SIBSIZE_REG
,
356 TX39_SIBSIZE_SNDSIZE_SET(0, bufcnt
));
358 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, TX39_SIBSF0_SNDVALID
);
361 reg
= tx_conf_read(tc
, TX39_SIBDMACTRL_REG
);
362 reg
|= TX39_SIBDMACTRL_ENDMATXSND
;
363 tx_conf_write(tc
, TX39_SIBDMACTRL_REG
, reg
);
366 sc
->sa_dmacnt
+= bufcnt
;
371 sc
->sa_state
= UCBSND_TRANSITION_DISABLE
;
373 case UCBSND_TRANSITION_PIO
:
374 /* change interrupt source */
376 tx_intr_disestablish(tc
, sc
->sa_sf0ih
);
379 sc
->sa_sndih
= tx_intr_establish(
380 tc
, MAKEINTR(1, TX39_INTRSTATUS1_SNDININT
),
381 IST_EDGE
, IPL_TTY
, ucbsnd_exec_output
, sc
);
383 sc
->sa_state
= UCBSND_PIO
;
389 /* PIO test routine */
390 int dummy_data
= sc
->sa_cnt
* 3;
391 tx_conf_write(tc
, TX39_SIBSNDHOLD_REG
,
392 dummy_data
<< 16 | dummy_data
);
393 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, TX39_SIBSF0_SNDVALID
);
394 if (sc
->sa_cnt
++ > 50) {
395 sc
->sa_state
= UCBSND_TRANSITION_DISABLE
;
399 case UCBSND_TRANSITION_DISABLE
:
400 /* change interrupt source */
402 tx_intr_disestablish(tc
, sc
->sa_sndih
);
405 sc
->sa_sf0ih
= tx_intr_establish(
406 tc
, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT
),
407 IST_EDGE
, IPL_TTY
, ucbsnd_exec_output
, sc
);
409 sc
->sa_state
= UCBSND_DISABLE_OUTPUTPATH
;
412 case UCBSND_DISABLE_OUTPUTPATH
:
413 /* disable codec output path and mute */
414 reg
= TX39_SIBSF0_WRITE
;
415 reg
= TX39_SIBSF0_REGADDR_SET(reg
, UCB1200_AUDIOCTRLB_REG
);
416 reg
= TX39_SIBSF0_REGDATA_SET(reg
, UCB1200_AUDIOCTRLB_MUTE
);
417 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, reg
);
419 sc
->sa_state
= UCBSND_DISABLE_SPEAKER0
;
423 case UCBSND_DISABLE_SPEAKER0
:
425 reg
= TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG
);
426 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, reg
);
428 sc
->sa_state
= UCBSND_DISABLE_SPEAKER1
;
431 case UCBSND_DISABLE_SPEAKER1
:
432 reg
= tx_conf_read(tc
, TX39_SIBSF0STAT_REG
);
433 if ((TX39_SIBSF0_REGADDR(reg
) != UCB1200_IO_DATA_REG
) &&
434 --sc
->sa_retry
> 0) {
436 sc
->sa_state
= UCBSND_DISABLE_SPEAKER0
;
440 if (sc
->sa_retry
<= 0) {
441 printf("ucbsnd_exec_output: subframe0 busy\n");
443 sc
->sa_state
= UCBSND_IDLE
;
447 reg
|= TX39_SIBSF0_WRITE
;
448 reg
&= ~UCB1200_IO_DATA_SPEAKER
;
449 tx_conf_write(tc
, TX39_SIBSF0CTRL_REG
, reg
);
451 sc
->sa_state
= UCBSND_DISABLE_SIB
;
454 case UCBSND_DISABLE_SIB
:
455 /* Disable SIB side */
456 reg
= tx_conf_read(tc
, TX39_SIBCTRL_REG
);
457 reg
&= ~TX39_SIBCTRL_ENSND
;
458 tx_conf_write(tc
, TX39_SIBCTRL_REG
, reg
);
460 /* end audio disable sequence */
462 tx_intr_disestablish(tc
, sc
->sa_sf0ih
);
465 sc
->sa_state
= UCBSND_IDLE
;
474 * global sound interface.
477 ucbsnd_sound_init(struct ucbsnd_softc
*sc
)
479 tx_sound_tag_t ts
= &sc
->sc_tag
;
480 tx_chipset_tag_t tc
= sc
->sc_tc
;
483 ts
->ts_click
= __ucbsnd_sound_click
;
484 ts
->ts_mute
= __ucbsnd_sound_mute
;
486 tx_conf_register_sound(tc
, ts
);
490 __ucbsnd_sound_click(tx_sound_tag_t arg
)
492 struct ucbsnd_softc
*sc
= (void*)arg
;
494 if (!sc
->sc_mute
&& sc
->sa_state
== UCBSND_IDLE
) {
495 sc
->sa_transfer_mode
= UCBSND_TRANSFERMODE_PIO
;
496 sc
->sa_state
= UCBSND_INIT
;
497 ucbsnd_exec_output((void*)sc
);
502 __ucbsnd_sound_mute(tx_sound_tag_t arg
, int onoff
)
504 struct ucbsnd_softc
*sc
= (void*)arg
;
512 extern struct cfdriver ucbsnd_cd
;
515 ucbsndopen(dev_t dev
, int flags
, int ifmt
, struct lwp
*l
)
517 int unit
= AUDIOUNIT(dev
);
518 struct ucbsnd_softc
*sc
;
521 sc
= device_lookup_private(&ucbsnd_cd
, unit
);
526 ringbuf_reset(&sc
->sc_rb
);
533 ucbsndclose(dev_t dev
, int flags
, int ifmt
, struct lwp
*l
)
535 int unit
= AUDIOUNIT(dev
);
536 struct ucbsnd_softc
*sc
;
538 sc
= device_lookup_private(&ucbsnd_cd
, unit
);
546 ucbsndread(dev_t dev
, struct uio
*uio
, int ioflag
)
548 int unit
= AUDIOUNIT(dev
);
549 struct ucbsnd_softc
*sc
;
552 sc
= device_lookup_private(&ucbsnd_cd
, unit
);
555 /* not supported yet */
561 ucbsndwrite_subr(struct ucbsnd_softc
*sc
, u_int32_t
*buf
, size_t bufsize
,
566 error
= uiomove(buf
, bufsize
, uio
);
568 * inverse endian for UCB1200
570 for (i
= 0; i
< bufsize
/ sizeof(int); i
++)
571 buf
[i
] = htobe32(buf
[i
]);
572 mips_dcache_wbinv_range((vaddr_t
)buf
, bufsize
);
574 ringbuf_producer_return(&sc
->sc_rb
, bufsize
);
577 if (sc
->sa_state
== UCBSND_IDLE
&& ringbuf_full(&sc
->sc_rb
)) {
578 sc
->sa_transfer_mode
= UCBSND_TRANSFERMODE_DMA
;
579 sc
->sa_state
= UCBSND_INIT
;
580 ucbsnd_exec_output((void*)sc
);
588 ucbsndwrite(dev_t dev
, struct uio
*uio
, int ioflag
)
590 int unit
= AUDIOUNIT(dev
);
591 struct ucbsnd_softc
*sc
;
596 sc
= device_lookup_private(&ucbsnd_cd
, unit
);
600 len
= uio
->uio_resid
;
601 n
= (len
+ TX39_SIBDMA_SIZE
- 1) / TX39_SIBDMA_SIZE
;
602 rest
= len
% TX39_SIBDMA_SIZE
;
607 for (i
= 0; i
< n
; i
++) {
608 while (!(buf
= ringbuf_producer_get(&sc
->sc_rb
))) {
609 error
= tsleep(&sc
->sc_rb
, PRIBIO
, "ucbsnd", 1000);
614 error
= ucbsndwrite_subr(sc
, buf
, TX39_SIBDMA_SIZE
, uio
);
620 while (!(buf
= ringbuf_producer_get(&sc
->sc_rb
))) {
621 error
= tsleep(&sc
->sc_rb
, PRIBIO
, "ucbsnd", 1000);
626 error
= ucbsndwrite_subr(sc
, buf
, rest
, uio
);
632 printf("%s: timeout. reset ring-buffer.\n", sc
->sc_dev
.dv_xname
);
634 ringbuf_reset(&sc
->sc_rb
);
644 ringbuf_allocate(struct ring_buf
*rb
, size_t blksize
, int maxblk
)
646 rb
->rb_bufsize
= blksize
* maxblk
;
647 rb
->rb_blksize
= blksize
;
648 rb
->rb_maxblks
= maxblk
;
650 rb
->rb_buf
= (u_int32_t
)malloc(rb
->rb_bufsize
, M_DEVBUF
, M_WAITOK
);
652 rb
->rb_buf
= (u_int32_t
)dmabuf_static
;
654 if (rb
->rb_buf
== 0) {
655 printf("ringbuf_allocate: can't allocate buffer\n");
658 memset((char*)rb
->rb_buf
, 0, rb
->rb_bufsize
);
660 rb
->rb_bufcnt
= malloc(rb
->rb_maxblks
* sizeof(size_t), M_DEVBUF
,
663 rb
->rb_bufcnt
= dmabufcnt_static
;
665 if (rb
->rb_bufcnt
== 0) {
666 printf("ringbuf_allocate: can't allocate buffer\n");
669 memset((char*)rb
->rb_bufcnt
, 0, rb
->rb_maxblks
* sizeof(size_t));
677 ringbuf_deallocate(struct ring_buf
*rb
)
680 free((void*)rb
->rb_buf
, M_DEVBUF
);
681 free(rb
->rb_bufcnt
, M_DEVBUF
);
686 ringbuf_reset(struct ring_buf
*rb
)
693 ringbuf_full(struct ring_buf
*rb
)
697 ret
= rb
->rb_outp
== rb
->rb_maxblks
;
703 ringbuf_producer_get(struct ring_buf
*rb
)
709 ret
= ringbuf_full(rb
) ? 0 :
710 rb
->rb_buf
+ rb
->rb_inp
* rb
->rb_blksize
;
717 ringbuf_producer_return(struct ring_buf
*rb
, size_t cnt
)
721 assert(cnt
<= rb
->rb_blksize
);
726 rb
->rb_bufcnt
[rb
->rb_inp
] = cnt
;
727 rb
->rb_inp
= (rb
->rb_inp
+ 1) % rb
->rb_maxblks
;
732 ringbuf_consumer_get(struct ring_buf
*rb
, size_t *cntp
)
737 if (rb
->rb_outp
== 0)
740 idx
= (rb
->rb_inp
- rb
->rb_outp
+ rb
->rb_maxblks
) % rb
->rb_maxblks
;
742 p
= rb
->rb_buf
+ idx
* rb
->rb_blksize
;
743 *cntp
= rb
->rb_bufcnt
[idx
];
749 ringbuf_consumer_return(struct ring_buf
*rb
)