Add support for /very/ experimental -e (exposure) option.

Add support for LKM operation.

Change M_NOWAIT on buffer memory allocation to M_WAIT in hopes we'll be
able to get ourselves a nice fat buffer from the kernel if we suspend.

Note: The LKM support looks kinda screwy in two areas, where I found
      problems with the kernel proper.  First, calling dev_attach()
      at module load time will cause a panic.  I haven't investigated.
      Secondly, I had to manually call qcam_drvinit() to register the
      device softc structure by hand at module load time.  This seems
      bogus,  it should be called as a core part of the module load
      process for character/block device drivers.
This commit is contained in:
Paul Traina 1996-03-21 08:22:59 +00:00
parent 4374dd874b
commit f3a4ca94cd
3 changed files with 101 additions and 14 deletions

View File

@ -118,7 +118,10 @@ qcam_registerdev (struct isa_device *id)
kdc->kdc_unit = id->id_unit;
kdc->kdc_parentdata = id;
#ifndef ACTUALLY_LKM_NOT_KERNEL /* there's a bug in dev_attach
when running from an LKM */
dev_attach(kdc);
#endif
}
static int
@ -186,7 +189,7 @@ qcam_attach (struct isa_device *devp)
static int
qcam_open (dev_t dev, int flags, int fmt, struct proc *p)
{
struct qcam_softc *qs = (struct qcam_softc *)&qcam_softc[UNIT(dev)];
struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
if (!(qs->flags & QC_ALIVE))
return ENXIO;
@ -195,7 +198,7 @@ qcam_open (dev_t dev, int flags, int fmt, struct proc *p)
return EBUSY;
qs->buffer_end = qs->buffer = malloc(QC_MAXFRAMEBUFSIZE, M_DEVBUF,
M_NOWAIT);
M_WAITOK);
if (!qs->buffer)
return ENOMEM;
@ -212,7 +215,7 @@ qcam_open (dev_t dev, int flags, int fmt, struct proc *p)
static int
qcam_close (dev_t dev, int flags, int fmt, struct proc *p)
{
struct qcam_softc *qs = (struct qcam_softc *)&qcam_softc[UNIT(dev)];
struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
if (qs->buffer) {
free(qs->buffer, M_DEVBUF);
@ -228,7 +231,7 @@ qcam_close (dev_t dev, int flags, int fmt, struct proc *p)
static int
qcam_read (dev_t dev, struct uio *uio, int ioflag)
{
struct qcam_softc *qs = (struct qcam_softc *)&qcam_softc[UNIT(dev)];
struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
int bytes, bufsize;
int error;
@ -252,7 +255,7 @@ qcam_read (dev_t dev, struct uio *uio, int ioflag)
static int
qcam_ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
{
struct qcam_softc *qs = (struct qcam_softc *)&qcam_softc[UNIT(dev)];
struct qcam_softc *qs = &qcam_softc[UNIT(dev)];
struct qcam *info = (struct qcam *)data;
if (!data)
@ -268,6 +271,7 @@ qcam_ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
info->qc_yorigin = qs->y_origin;
info->qc_bpp = qs->bpp;
info->qc_zoom = qs->zoom;
info->qc_exposure = qs->exposure;
info->qc_brightness = qs->brightness;
info->qc_whitebalance = qs->whitebalance;
info->qc_contrast = qs->contrast;
@ -300,6 +304,7 @@ qcam_ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
qs->y_origin = info->qc_yorigin;
qs->bpp = info->qc_bpp;
qs->zoom = info->qc_zoom;
qs->exposure = info->qc_exposure;
qs->brightness = info->qc_brightness;
qs->whitebalance = info->qc_whitebalance;
qs->contrast = info->qc_contrast;
@ -333,4 +338,68 @@ qcam_drvinit (void *unused)
SYSINIT(qcamdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,qcam_drvinit,NULL)
#ifdef QCAM_MODULE
#include <sys/exec.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/lkm.h>
static struct isa_device qcam_mod_dev =
{0, &qcamdriver, IO_LPT1, 0, -1, (caddr_t) 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0};
MOD_DEV(qcam, LM_DT_CHAR, CDEV_MAJOR, &qcam_cdevsw);
static int
qcam_load (struct lkm_table *lkmtp, int cmd)
{
if (qcam_probe(&qcam_mod_dev)) {
qcam_attach(&qcam_mod_dev);
qcam_drvinit(NULL); /* XXX this shouldn't NEED to be here
* the LKM code should be doing this
* for us! */
uprintf("qcam: driver loaded\n");
return 0;
} else {
uprintf("qcam: probe failed\n");
return 1;
}
}
static int
qcam_unload (struct lkm_table *lkmtp, int cmd)
{
struct qcam_softc *qs;
int i;
for (i = 0; i < NQCAM; i++) {
qs = &qcam_softc[i];
if (qs->flags & QC_OPEN) {
uprintf("qcam%d: cannot unload, device busy", qs->unit);
return 1;
}
}
uprintf("qcam: driver unloaded\n");
return 0;
}
static int
qcam_stat (struct lkm_table *lkmtp, int cmd)
{
return 0;
}
int
qcam_mod (struct lkm_table *lkmtp, int cmd, int ver)
{
#define _module qcam_module
DISPATCH(lkmtp, cmd, ver,
qcam_load, qcam_unload, qcam_stat);
}
#endif /* QCAM_MODULE */
#endif /* NQCAM */

View File

@ -56,6 +56,7 @@ struct qcam_softc {
int y_origin; /* ?? units */
int zoom; /* 0=none, 1=1.5x, 2=2x */
int bpp; /* 4 or 6 */
int exposure; /* time to open shutter */
u_char xferparms; /* calcualted transfer params */
u_char contrast;
u_char brightness;
@ -104,6 +105,10 @@ struct qcam_softc {
#define QC_TIMEOUT_CMD 5000 /* timeout for control cmds */
#define QC_TIMEOUT 400 /* timeout on scan reads */
/* This value could be OS
dependant */
#define QC_DEF_EXPOSURE 200 /* default exposure */
extern int qcam_detect __P((u_int port));
extern void qcam_reset __P((struct qcam_softc *qs));
extern int qcam_scan __P((struct qcam_softc *qs));

View File

@ -115,16 +115,16 @@ static u_short *qcam_rsblow_end = &qcam_rsblow[STATBUFSIZE];
} while (((V) & 0x01) && --timeout); STATLOW(T) \
}
static int
sendbyte (u_int port, int value)
inline static int
sendbyte (u_int port, int value, int delay)
{
u_char s1, s2;
write_data(port, value);
DELAY(100);
write_data(port, value);
DELAY(100);
write_data(port, value);
if (delay) {
DELAY(delay);
write_data(port, value);
}
write_control(port, QC_CTL_HIGHNIB);
READ_STATUS_BYTE_HIGH(port, s1, QC_TIMEOUT_CMD);
@ -138,15 +138,27 @@ sendbyte (u_int port, int value)
static int
send_command (struct qcam_softc *qs, int cmd, int value)
{
if (sendbyte(qs->iobase, cmd) != cmd)
if (sendbyte(qs->iobase, cmd, qs->exposure) != cmd)
return 1;
if (sendbyte(qs->iobase, value) != value)
if (sendbyte(qs->iobase, value, qs->exposure) != value)
return 1;
return 0; /* success */
}
static int
send_xfermode (struct qcam_softc *qs, int value)
{
if (sendbyte(qs->iobase, QC_XFERMODE, qs->exposure) != QC_XFERMODE)
return 1;
if (sendbyte(qs->iobase, value, qs->exposure) != value)
return 1;
return 0;
}
void
qcam_reset (struct qcam_softc *qs)
{
@ -447,7 +459,7 @@ qcam_scan (struct qcam_softc *qs)
if (qs->init_req)
qcam_init(qs);
if (send_command(qs, QC_XFERMODE, qs->xferparms))
if (send_xfermode(qs, qs->xferparms))
return 1;
if (qcam_debug && (timeouts != qcam_timeouts))
@ -481,6 +493,7 @@ qcam_default (struct qcam_softc *qs) {
qs->y_origin = QC_DEF_YORG;
qs->bpp = QC_DEF_BPP;
qs->zoom = QC_DEF_ZOOM;
qs->exposure = QC_DEF_EXPOSURE;
}
int