/* Copyright 1992 by Holger Veit
* May be freely used with Bill Jolitz's port of
* 386bsd and may be included in a 386bsd collection
* as long as binary and source are available and reproduce the above
* copyright. This includes special software collections which
* are derived from 386bsd, such as the so-called NetBSD.
* You may freely modify this code and contribute improvements based
* on this code as long as you don't claim to be the original author.
* Commercial use of this source requires permittance of the copyright
* holder. A general license for 386bsd will override this restriction.
* Use at your own risk. The copyright holder or any person who makes
* this code available for the public (administrators of public archives
* for instance) are not responsible for any harm to hardware or software
* that might happen due to wrong application or program faults.
* @(#) $RCSfile: co_codrv1.c,v $ $Revision: 1.6 $ (Contributed to 386bsd) $Date: 93/01/23 23:14:27 $
* This file processes the vga/kbdioctls
* History: see CO_HISTORY
static char *rcsid
= "$Header: /usr/src/sys.386bsd/i386/isa/codrv/RCS/co_codrv1.c,v 1.6 93/01/23 23:14:27 root Exp Locker: root $";
/**************************************************************************
* This file serves as a plug-in interface for IOCTL processing.
* This file has been modified to understand most of the CODRV1 and
* CODRV2 ioctls which have been tested long in codrv-0.1.2-ALPHA.
* For some reasons, the CODRV2 font interface will be revised
* again. It is not integrated here. The other ioctls are available.
* This file has four public entry points:
* coioctl_init() (called by coattach, initialization)
* consioctl(dev,cmd,addr,flag) (serves /dev/console specific things)
* kbdioctl(dev,cmd,addr,flags) (serves /dev/kbd specific things)
* vgaioctl(dev,cmd,addr,flags) (serves /dev/vga specific things)
* In CODRV1 these functions were available with any console device,
* be it /dev/console, /dev/kbd, /dev/vga
* This ioctl package contains its own set of service functions, that
* were in co_kbd.c and co_vga.c before, with the exception of the
* keyboard overload subsystem, which is still in co_kbd.c.
* Programmers are invited to provide different interfaces, such as
* SVR3/SVR4/SUN-OS. There will be hopefully fully runtime-replacable
* kernel modules, which can make use of this.
***********************************************************************/
* initialize ioctl system
cons_capabilities
.info1
|= (CONS_CODRV1
|CONS_CODRV2
);
* process /dev/console ioctls
int consioctl(dev_t dev
, int cmd
, caddr_t data
, int flag
)
register struct tty
*tp
= dev2tty(dev
);
*((struct consinfo
*)data
) = cons_capabilities
;
} else if (cmd
==OLDCONSGINFO
) {
((struct oldconsinfo
*)data
)->info1
= cons_capabilities
.info1
;
error
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, cmd
, data
, flag
);
error
= ttioctl(tp
, cmd
, data
, flag
);
/* must be executed for backward compatibility
* must be executed *after* the tty ioctls,
* because it shares an essential ioctl with them.
error
= kbdioctl(dev
, cmd
, data
, flag
);
return error
==0 ? 0 : ENOTTY
;
/**********************************************************************
* utility functions for kbdioctl
*********************************************************************/
static struct vty
*n2vty(int n
)
if (n
== KBD_ACTVTY
) return actvty
;
if (n
>= 0 && n
< nvty
) return &vtys
[n
];
static void kioc_setlockkeys(dev_t dev
,int snc
)
register struct vty
*vp
= dev2vty(dev
);
vp
->num
= (snc
& 2) ? 1 : 0;
vp
->caps
= (snc
& 4) ? 1 : 0;
vp
->num
= (snc
& 2) ? 1 : 0;
vp
->caps
= (snc
& 4) ? 1 : 0;
static int kioc_assignleds(dev_t dev
,int param
)
/* used for initialization */
vp
->altgrled
= (param
&3)==2;
vp
->shiftled
= (param
&3)==1;
ostate
= vp
->altgrled
? 2 : vp
->shiftled
? 1 : 0;
static int kioc_dobeep(struct kbd_bell
*data
)
kbd_cvtsound(data
->pitch
, &p
, data
->duration
, &d
);
sysbeep (kbs
.pitch
, kbs
.duration
);
static int kioc_getbeep2(struct kbd_bell
*data
)
if (data
->nr
== KBD_DEFLT
) {
data
->pitch
= 1193180 / kbs
.pitch
;
data
->duration
= kbs
.duration
/ hz
* 1000;
data
->pitch
= 1193180 / vp
->pitch
;
data
->duration
= vp
->duration
/ hz
* 1000;
static int kioc_setbeep2(struct kbd_bell
*data
)
if (data
->nr
== KBD_DEFLT
) {
kbd_cvtsound(data
->pitch
, &kbs
.pitch
,
data
->duration
, &kbs
.duration
);
kbd_cvtsound(data
->pitch
, &vp
->pitch
, data
->duration
, &vp
->duration
);
* process keyboard ioctls
int kbdioctl(dev_t dev
, int cmd
, caddr_t data
, int flag
)
struct vty
*vp
= dev2vty(dev
);
/* CONSGINFO is mandatory ! */
*((struct consinfo
*)data
) = cons_capabilities
;
((struct oldconsinfo
*)data
)->info1
= cons_capabilities
.info1
;
/* this is a relic from my youth mistakes */
kbd_settpmrate(KBD_TPD500
|KBD_TPM100
);
*(int *)data
= kbs
.tpmrate
;
kbd_settpmrate(*(int *)data
);
*(int *)data
= kbs
.repeat
;
kbs
.repeat
= (*(int *)data
) & 1;
*(int *)data
= kbs
.ledstate
;
kbd_setleds(*(int *)data
);
*(int *)data
= vp
->scroll
| (vp
->num
<<1) |
(vp
->caps
<<2) | (vp
->altgrlock
<<3) |
kioc_setlockkeys (dev
,*(int *) data
);
case KBDSCAPSLED
: /* assign CapsLock LED to AltgrLock or ShiftLock */
*(int *) data
= kioc_assignleds (dev
, *(int *)data
);
*(int *) data
= vp
->altgrled
? 2 :
return kbd_cvtsound(((struct kbd_sound
*)data
)->pitch
, &kbs
.pitch
,
((struct kbd_sound
*)data
)->duration
, &kbs
.duration
);
return kioc_getbeep2((struct kbd_bell
*)data
);
return kioc_setbeep2((struct kbd_bell
*)data
);
case KBDSETBELL
: /* compatibility */
return kioc_dobeep((struct kbd_bell
*)data
);
return kbd_getckeydef (((Ovl_tbl
*)data
)->keynum
, (Ovl_tbl
*) data
);
stat
= kbd_getckeydef (ok
.keynum
, &ok
);
bcopy(&ok
,data
,sizeof(struct oldkbd_ovlkey
));
return kbd_setkeydef((Ovl_tbl
*)data
);
return kbd_getokeydef (((Ovl_tbl
*)data
)->keynum
, (Ovl_tbl
*) data
);
return kbd_rmkeydef (*(int *) data
);
kbs
.a0flag
= (*(int*)data
& 1) != 0;
kbs
.c0flag
= (*(int*)data
& 2) != 0;
kbs
.m0flag
= (*(int*)data
& 4) != 0; /*not used yet*/
return kbd_gethotkey((struct kbd_hotkey
*)data
);
return kbd_sethotkey((struct kbd_hotkey
*)data
);
/* and now some special features which are cheap */
consoftc
.cs_pgid
= *(int*)data
;
*(int*)data
= consoftc
.cs_pgid
;
/* backward compatibility */
error
= vgaioctl(dev
, cmd
, data
, flag
);
/**********************************************************************
* utility functions for vgaioctl
*********************************************************************/
static int chklim(struct vty
*vp
,int x0
,int x1
, int y0
, int y1
)
if (x0
< 0 || x0
>= vp
->ncol
||
y0
< 0 || y0
>= vp
->nrow
||
x1
< 0 || x1
>= vp
->ncol
||
y1
< 0 || y1
>= vp
->nrow
||
static int cpyblk(u_char
*from
, u_char
*to
, int mode
,
int x0
, int x1
, int y0
, int y1
, int ncol
)
/* copy the requested data, could be optimized */
for (n
=0, y
=y0
; y
<=y1
; y
++, ofs
+= (ncol
*2) ) {
for (ofs2
=ofs
,x
=x0
; x
<=x1
; x
++,n
++,ofs2
+=2)
ofs1
= ((u_short
*)from
) + x0
;
for (y
=y0
; y
<=y1
; y
++, ofs1
+= ncol
)
bcopy(ofs1
, to
, (x1
-x0
+1)*2);
static int getsz(struct vty
*vp
,struct vga_block
*p
)
if ((p
->mode
& 0x03) == VGA_SCREEN
) {
if (chklim(vp
,p
->x0
,p
->x1
,p
->y0
,p
->y1
))
sz
= (p
->x1
-p
->x0
+1) * (p
->y1
-p
->y0
+1);
if ((p
->mode
& 0x30) == VGA_BOTH
)
static int vioc_vgagetblock(struct vga_block
*p
)
if (!(sz
=getsz(vp
, p
))) return EINVAL
;
data
= (u_char
*)malloc(sz
, M_IOCTLOPS
, M_WAITOK
);
/* copy the data into buffer */
error
= cpyblk( (u_char
*)vp
->Crtat
, data
, p
->mode
&0x30,
x0
, x1
, y0
, y1
, vp
->ncol
);
if (!error
) error
= copyout(data
, p
->map
, sz
);
static int vioc_vgasetblock(struct vga_block
*p
)
if (!(sz
=getsz(vp
, p
))) return EINVAL
;
data
= (u_char
*)malloc(sz
, M_IOCTLOPS
, M_WAITOK
);
error
= copyin(p
->map
,data
,sz
);
/* copy the requested data */
error
= cpyblk (data
, (u_char
*)vp
->Crtat
, p
->mode
&0x30,
x0
, x1
, y0
, y1
, vp
->ncol
);
static int vioc_gettextpage(struct textpage
*tp
)
u_char
*p
= ((u_char
*)Crtat
) + tp
->ad
;
if (tp
->ad
> 1 || tp
->pagenum
> 7) return EINVAL
;
for (i
=0; i
<actvty
->size
; i
++, p
+=2)
static int vioc_settextpage(struct textpage
*tp
)
u_char
*p
= ((u_char
*)Crtat
) + tp
->ad
;
if (tp
->ad
> 1 || tp
->pagenum
> 7) return EINVAL
;
for (i
=0; i
<actvty
->size
; i
++,p
+=2)
static int vioc_oldgetfontchar(struct fontchar
*fc
)
u_char
*ofs
= (u_char
*)Crtat
+ pg
*0x4000;
if (vds
.cardtype
< VG_EGA
|| pg
< 0 || pg
> 7) return EINVAL
;
bcopy(ofs
+(fc
->idx
<<5),fc
->cmap
,VGA_FNTCSIZE
);
static int vioc_oldsetfontchar(struct fontchar
*fc
)
u_char
*ofs
= (u_char
*)Crtat
+ pg
*0x4000;
if (vds
.cardtype
< VG_EGA
|| pg
< 0 || pg
> 7) return EINVAL
;
bcopy(fc
->cmap
,ofs
+(fc
->idx
<<5),VGA_FNTCSIZE
);
static int vioc_miscfunctions(struct miscfcns
*f
)
vds
.encoding
[1] = NOFONT
;
outw(0x3c4,0x0003); /* SA=0,SB=0 */
f
->u
.enc
[0] = vds
.encoding
[0];
f
->u
.enc
[1] = vds
.encoding
[1];
vds
.scrtimeout
= f
->u
.timeout
; /* seconds */
vga_doblanking(BLANKSTART
);
f
->u
.timeout
= (vds
.scrtimeout
&0x3FFFFFFF) |
((u_long
)(vds
.blanking
&3)<<30);
static int vioc_oldsetfontmap(struct fontmap
*data
)
u_char
*ofs
= (u_char
*)Crtat
+pg
*0x4000;
if (vds
.cardtype
< VG_EGA
|| pg
< 0 || pg
> 7) return EINVAL
;
vds
.encoding
[pg
] = data
->encoding
;
for(i
=k
=0; i
<(VGA_FNTCSIZE
*VGA_FNTNCHARS
); k
+=32,i
+=VGA_FNTCSIZE
) {
bcopy(&data
->map
[i
],ofs
+k
,VGA_FNTCSIZE
);
/* enable SB/SBH when font 1 is loaded */
if (pg
==1 && data
->encoding
!= NOFONT
) outw(0x3c4,0x0403); /* SA=1,SB=0 */
static int vioc_oldgetfontmap(struct fontmap
*data
)
u_char
*ofs
= (u_char
*)Crtat
+ pg
*0x4000;
if (vds
.cardtype
< VG_EGA
|| pg
< 0 || pg
> 7) return EINVAL
;
data
->encoding
= vds
.encoding
[pg
];
for(i
=k
=0; i
<(VGA_FNTCSIZE
*VGA_FNTNCHARS
); k
+=32,i
+=VGA_FNTCSIZE
)
bcopy(ofs
+k
,&data
->map
[i
],VGA_FNTCSIZE
);
static int vioc_setfontmap(struct fmap
*f
)
u_char
*ofs
= (u_char
*)Crtat
+ f
->page
*0x4000;
struct fchar
*cibuf
,fc
[FCHUNKS
];
if (vds
.cardtype
< VG_EGA
|| f
->page
< 0 || f
->page
> 1 ||
f
->x
> 9 || f
->y
> 16 || f
->nr
> 256) return EINVAL
;
vds
.f89bit
= vds
.cardtype
>= VG_EGA
? 9 : 8;
buf
= (u_char
*)malloc(FSPACE
, M_IOCTLOPS
, M_WAITOK
);
for (i
= f
->nr
; i
> 0; i
-= FCHUNKS
, cibuf
+=FCHUNKS
) {
j
= i
>= FCHUNKS
? FCHUNKS
: i
;
error
= copyin(cibuf
, fc
, j
*sizeof(struct fchar
));
ec
= fc
[k
].encoding
& 0xFF;
bcopy(fc
[k
].map
,buf
+(ec
<<5),f
->y
);
/* set the extension bit (this is really switched in
/* move the data into CG space */
/* this is a hack, as long as XCHAR == u_char */
vds
.encoding
[f
->page
] = (u_short
)i
;
/* enable SB/SBH when font 1 is loaded */
if (f
->nr
> 0) outw(0x3c4,0x0403); /* SA=1,SB=0 */
static int vioc_getfontmap(struct fmap
*f
)
u_char
*ofs
= (u_char
*)Crtat
+ f
->page
*0x4000;
struct fchar
*cobuf
,fc
[FCHUNKS
];
if (vds
.cardtype
< VG_EGA
|| f
->page
< 0 || f
->page
> 1 ||
f
->nr
> 0 && (f
->x
> 9 || f
->y
> 16) || (f
->nr
+f
->start
) > 256) return EINVAL
;
buf
= (u_char
*)malloc(FSPACE
, M_IOCTLOPS
, M_WAITOK
);
/* move the data from CG space */
for (k
= i
= 0; i
<f
->nr
; i
++,k
++) {
error
= copyout(fc
,cobuf
,FCHUNKS
*sizeof(struct fchar
));
fc
[k
].encoding
= i
+f
->start
;
bzero(fc
[k
].map
,VGA_MAXX
/8*VGA_MAXY
);
bcopy(buf
+32*(i
+f
->start
),fc
[k
].map
,f
->y
);
error
= copyout(fc
,cobuf
,k
*sizeof(struct fchar
));
f
->start
= vds
.encoding
[f
->page
];
* execute my own vga ioctls
int vgaioctl(dev_t dev
, int cmd
, caddr_t data
, int flag
)
/* CONSGINFO is mandatory ! */
*((struct consinfo
*)data
) = cons_capabilities
;
((struct oldconsinfo
*)data
)->info1
= cons_capabilities
.info1
;
return kbd_setxserveriopl(*(int*)data
);
return vga_setcshape((struct cursorshape
*)data
);
return vga_getcshape((struct cursorshape
*)data
);
return vga_getvideoinfo((struct videoinfo
*)data
);
*(int*)data
= (vds
.scrtimeout
&0x3FFFFFFF) |
((u_long
)(vds
.blanking
&3)<<30);
vds
.scrtimeout
= *(int*)data
; /* seconds */
vga_doblanking(BLANKSTART
);
return vioc_vgagetblock((struct vga_block
*)data
);
return vioc_vgasetblock((struct vga_block
*)data
);
return vioc_oldsetfontmap((struct fontmap
*)data
);
return vioc_oldgetfontmap((struct fontmap
*)data
);
return vioc_setfontmap((struct fmap
*)data
);
return vioc_getfontmap((struct fmap
*)data
);
return vioc_oldgetfontchar((struct fontchar
*)data
);
return vioc_oldsetfontchar((struct fontchar
*)data
);
return vioc_gettextpage((struct textpage
*)data
);
return vioc_settextpage((struct textpage
*)data
);
return vioc_miscfunctions((struct miscfcns
*)data
);