Files
Arquivotheca.SunOS-4.1.4/sys/old/sg.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

177 lines
3.0 KiB
C

#ifndef lint
static char sccsid[] = "@(#)sg.c 1.1 94/10/31 Copyr 1983 Sun Micro";
#endif
/*
* Copyright (c) 1983 by Sun Microsystems, Inc.
*/
/*
* Sun-2 Sound Generator Driver (TI SN76489AN)
*/
#include "../h/param.h"
#include "../h/buf.h"
#include "../h/uio.h"
#include "../h/errno.h"
#include "../sun/pte.h"
#include "../sundev/mbvar.h"
#include "../sundev/video.h"
/*
* Driver information for auto-configuration stuff.
*/
int sgprobe(), sgattach();
struct mb_device *sginfo[1]; /* XXX only supports 1 chip */
u_long sgstd[] = { 0 }; /* no standard addresses */
struct mb_driver sgdriver = {
sgprobe, 0, sgattach, 0, 0, 0, sgstd, 0, 1, "sg", sginfo, 0, 0, 0
};
/*
* States driver can be in.
*/
#define S_CLOSED 0
#define S_OPEN 1
#define S_DELAY1 2
#define S_DELAY2 3
#define S_DELAY3 4
#define S_DELAY4 5
int sgstate; /* current state of driver */
u_int sgdelay; /* microseconds to delay */
#define SGBUFSIZ 512
#define SGPRI 29 /* priority to sleep at when delaying */
extern wakeup();
extern int hz;
/*ARGSUSED*/
sgprobe(reg, unit)
caddr_t reg;
int unit;
{
register int c;
if (pokec((char *)reg, 0))
return (0);
return (1);
}
/*ARGSUSED*/
sgattach(md)
register struct mb_device *md;
{
}
/*ARGSUSED*/
sgopen(dev, flag)
dev_t dev;
int flag;
{
struct videoctl *vc = (struct videoctl *)0xee3800;
if (sgstate != S_CLOSED)
return (ENXIO);
sgstate = S_OPEN;
sgdelay = 0;
vc->vc_sg_en = 1;
return (0);
}
/*ARGSUSED*/
sgclose(dev, flag)
dev_t dev;
int flag;
{
struct videoctl *vc = (struct videoctl *)0xee3800;
vc->vc_sg_en = 0;
if (sgdelay) {
untimeout(wakeup, (caddr_t)&sgdelay);
sgdelay = 0;
}
sgstate = S_CLOSED;
return (0);
}
/*ARGSUSED*/
sgwrite(dev, uio)
dev_t dev;
register struct uio *uio;
{
register u_char *sgp = (u_char *)sginfo[0]->md_addr;
register u_char *cp;
register int cc;
int error = 0;
u_char obuf[SGBUFSIZ];
/*
* Process the user's data in at most SGBUFSIZ chunks.
*/
while (uio->uio_resid > 0) {
/*
* Grab a hunk of data from the user.
*/
cc = uio->uio_iov->iov_len;
if (cc == 0) {
uio->uio_iovcnt--;
uio->uio_iov++;
if (uio->uio_iovcnt < 0) {
printf("sg: iovcnt < 0\n");
error = EIO;
break;
}
continue;
}
if (cc > SGBUFSIZ)
cc = SGBUFSIZ;
cp = obuf;
error = uiomove(cp, cc, UIO_WRITE, uio);
if (error)
break;
while (cc > 0) {
switch (sgstate) {
case S_CLOSED:
case S_OPEN:
default:
if ((*cp&0xc0) != 0x40) {
*sgp = *cp;
DELAY(8);
} else
sgstate = S_DELAY1;
break;
case S_DELAY1:
case S_DELAY2:
case S_DELAY3:
sgdelay <<= 8;
sgdelay |= *cp;
sgstate++;
break;
case S_DELAY4:
sgdelay <<= 8;
sgdelay |= *cp;
if (sgdelay < 4*(1000000/hz)) {
DELAY(sgdelay);
} else {
int s = spl6();
timeout(wakeup, (caddr_t)&sgdelay,
sgdelay / (1000000/hz));
sleep((caddr_t)&sgdelay, SGPRI);
(void) splx(s);
}
sgdelay = 0;
sgstate = S_OPEN;
break;
}
cp++;
cc--;
}
}
return (error);
}