FPPS4/sys/dev/dev_tty.pas

404 lines
8.1 KiB
Plaintext

unit dev_tty;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
sysutils,
vselinfo,
kern_thr,
sys_conf,
sys_tty;
var
dev_console:p_cdev;
procedure ttyconsdev_init(); //SYSINIT(tty, SI_SUB_DRIVERS, SI_ORDER_FIRST, ttyconsdev_init, nil);
implementation
uses
errno,
vfile,
vstat,
vuio,
vttycom,
vpoll,
vm,
md_tty,
vsys_generic,
sys_event;
{
* Operations that are exposed through the character device in /dev.
}
Function ttydev_open(dev:p_cdev;oflags,devtype:Integer):Integer;
var
tp:p_tty;
begin
Writeln('ttydev_open("',dev^.si_name,'",',oflags,',',devtype,')');
tp:=dev^.si_drv1;
if (tp=nil) then Exit(EWOULDBLOCK);
Result:=0;
end;
Function ttydev_close(dev:p_cdev;fflag,devtype:Integer):Integer;
begin
Result:=0;
end;
Function ttydev_read(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
var
tp:p_tty;
error:Integer;
begin
tp:=dev^.si_drv1;
error:=ttydisc_read(tp, uio, ioflag);
if (error=ENXIO) then error:=0;
Exit(error);
end;
Function ttydev_write(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
var
tp:p_tty;
error:Integer;
begin
tp:=dev^.si_drv1;
error:=ttydisc_write(tp, uio, ioflag);
Exit(error);
end;
Function ttydev_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
var
error:Integer;
begin
error:=0;
case (cmd) of
TIOCCBRK,
TIOCCONS,
TIOCDRAIN,
TIOCEXCL,
TIOCFLUSH,
TIOCNXCL,
TIOCSBRK,
TIOCSCTTY,
TIOCSETA,
TIOCSETAF,
TIOCSETAW,
TIOCSPGRP,
TIOCSTART,
TIOCSTAT,
TIOCSTI,
TIOCSTOP,
TIOCSWINSZ:
begin
//error:=tty_wait_background(tp, curthread, SIGTTOU);
//if (error) then goto done;
end;
else;
end;
Writeln('ttydev_ioctl("',dev^.si_name,'",0x',HexStr(cmd,8),',0x',HexStr(data),',0x',HexStr(fflag,8),')');
//error:=tty_ioctl(tp, cmd, data, fflag, td);
//done:
Exit(error);
end;
Function ttydev_poll(dev:p_cdev;events:Integer):Integer;
var
tp:p_tty;
error:Integer;
revents:Integer;
begin
error:=0;
revents:=0;
tp:=dev^.si_drv1;
tty_lock(tp);
if (error<>0) then
begin
Exit((events and (POLLIN or POLLRDNORM)) or POLLHUP);
end;
if ((events and (POLLIN or POLLRDNORM))<>0) then
begin
{ See if we can read something. }
if (ttydisc_read_poll(tp) > 0) then
begin
revents:=revents or events and (POLLIN or POLLRDNORM);
end;
end;
//if (tp^.t_flags and TF_ZOMBIE) then
//begin
// { Hangup flag on zombie state. }
// revents:=revents or POLLHUP;
//end else
if ((events and (POLLOUT or POLLWRNORM))<>0) then
begin
{ See if we can write something. }
if (ttydisc_write_poll(tp) > 0) then
begin
revents:=revents or events and (POLLOUT or POLLWRNORM);
end;
end;
if (revents=0) then
begin
if ((events and (POLLIN or POLLRDNORM))<>0) then
begin
selrecord(curkthread, @tp^.t_inpoll);
end;
if ((events and (POLLOUT or POLLWRNORM))<>0) then
begin
selrecord(curkthread, @tp^.t_outpoll);
end;
end;
tty_unlock(tp);
Exit(revents);
end;
Function ttydev_mmap(dev:p_cdev;offset:vm_ooffset_t;paddr:p_vm_paddr_t;nprot:Integer;memattr:p_vm_memattr_t):Integer;
var
error:Integer;
begin
{ Handle mmap() through the driver. }
error:=EPERM;
//error:=ttydevsw_mmap(tp, offset, paddr, nprot, memattr);
Exit(error);
end;
{
* kqueue support.
}
procedure tty_kqops_read_detach(kn:p_knote);
var
tp:p_tty;
begin
tp:=kn^.kn_hook;
knlist_remove(@tp^.t_inpoll.si_note, kn, 0);
end;
function tty_kqops_read_event(kn:p_knote;hint:QWORD):Integer;
var
tp:p_tty;
begin
Result:=0;
tp:=kn^.kn_hook;
//tty_lock_assert(tp, MA_OWNED);
//if (tty_gone(tp) or tp^.t_flags and TF_ZOMBIE) then
//begin
// kn^.kn_flags:=kn^.kn_flags or EV_EOF;
// Exit(1);
//end else
begin
kn^.kn_data:=ttydisc_read_poll(tp);
Exit(ord(kn^.kn_data > 0));
end;
end;
procedure tty_kqops_write_detach(kn:p_knote);
var
tp:p_tty;
begin
tp:=kn^.kn_hook;
knlist_remove(@tp^.t_outpoll.si_note, kn, 0);
end;
function tty_kqops_write_event(kn:p_knote;hint:QWORD):Integer;
var
tp:p_tty;
begin
Result:=0;
tp:=kn^.kn_hook;
//tty_lock_assert(tp, MA_OWNED);
//if (tty_gone(tp)) then
//begin
// kn^.kn_flags:=kn^.kn_flags or EV_EOF;
// Exit(1);
//end else
begin
kn^.kn_data:=ttydisc_write_poll(tp);
Exit(ord(kn^.kn_data > 0));
end;
end;
const
tty_kqops_read:t_filterops=(
f_isfd :1;
f_detach:@tty_kqops_read_detach;
f_event :@tty_kqops_read_event;
);
tty_kqops_write:t_filterops=(
f_isfd :1;
f_detach:@tty_kqops_write_detach;
f_event :@tty_kqops_write_event;
);
Function ttydev_kqfilter(dev:p_cdev;kn:p_knote):Integer;
var
tp:p_tty;
error:Integer;
begin
error:=0;
tp:=dev^.si_drv1;
case (kn^.kn_filter) of
EVFILT_READ:
begin
kn^.kn_hook:=tp;
kn^.kn_fop:=@tty_kqops_read;
knlist_add(@tp^.t_inpoll.si_note, kn, 0);
end;
EVFILT_WRITE:
begin
kn^.kn_hook:=tp;
kn^.kn_fop:=@tty_kqops_write;
knlist_add(@tp^.t_outpoll.si_note, kn, 0);
end;
else
error:=EINVAL;
end;
Exit(error);
end;
const
ttydev_cdevsw:t_cdevsw=(
d_version :D_VERSION;
d_flags :D_TTY;
d_name :'ttydev';
d_open :@ttydev_open;
d_close :@ttydev_close;
d_read :@ttydev_read;
d_write :@ttydev_write;
d_ioctl :@ttydev_ioctl;
d_poll :@ttydev_poll;
d_mmap :@ttydev_mmap;
d_kqfilter :@ttydev_kqfilter;
);
{
* /dev/console handling.
}
Function ttyconsdev_open(dev:p_cdev;oflags,devtype:Integer):Integer;
begin
//
Result:=ttydev_open(dev, oflags, devtype);
end;
Function ttyconsdev_write(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
begin
Result:=ttydev_write(dev,uio,ioflag);
end;
const
ttyconsdev_cdevsw:t_cdevsw=(
d_version :D_VERSION;
d_flags :D_TTY;
d_name :'ttyconsdev';
d_open :@ttyconsdev_open;
d_close :@ttydev_close;
d_read :@ttydev_read;
d_write :@ttyconsdev_write;
d_ioctl :@ttydev_ioctl;
d_poll :@ttydev_poll;
d_mmap :@ttydev_mmap;
d_kqfilter :@ttydev_kqfilter;
);
{
* /dev/console is a little different than normal TTY's. When opened,
* it determines which TTY to use. When data gets written to it, it
* will be logged in the kernel message buffer.
}
function tty_makedev(tp:p_tty;fmt:PChar;const Args:Array of const):p_cdev; register;
var
dev:p_cdev;
uid:uid_t;
gid:gid_t;
mode:mode_t;
begin
// User device.
uid :=0;
gid :=GID_TTY;
mode:=S_IRUSR or S_IWUSR or S_IWGRP;
dev:=make_dev_cred(@ttydev_cdevsw, 0, uid, gid, mode, fmt, Args);
dev^.si_drv1:=tp;
Result:=dev;
end;
procedure ttyconsdev_init();
begin
tty_init( @std_tty[ 0],'[Input ]:',nil,TF_THD_NAME_PREFIX);
tty_init( @std_tty[ 1],'[Output]:',nil,TF_THD_NAME_PREFIX);
tty_init( @std_tty[ 2],'[Error ]:',nil,TF_THD_NAME_PREFIX);
//
tty_init(@deci_tty[ 0],'[stdin ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 1],'[stdout]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 2],'[stderr]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 3],'[tty2 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 4],'[tty3 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 5],'[tty4 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 6],'[tty5 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 7],'[tty6 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 8],'[tty7 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[ 9],'[ttya0 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[10],'[ttyb0 ]:',nil,TF_THD_NAME_PREFIX);
tty_init(@deci_tty[11],'[ttyc0 ]:',nil,TF_THD_NAME_PREFIX);
//
tty_init(@debug_tty ,'[Debug ]:',nil,TF_THD_NAME_PREFIX);
//
dev_console:=make_dev_credf(MAKEDEV_ETERNAL, @ttyconsdev_cdevsw, 0, UID_ROOT, GID_WHEEL, &600, 'console',[]);
dev_console^.si_drv1:=@debug_tty;
//
tty_makedev(@deci_tty[ 0],'deci_stdin' ,[]);
tty_makedev(@deci_tty[ 1],'deci_stdout',[]);
tty_makedev(@deci_tty[ 2],'deci_stderr',[]);
tty_makedev(@deci_tty[ 3],'deci_tty2' ,[]);
tty_makedev(@deci_tty[ 4],'deci_tty3' ,[]);
tty_makedev(@deci_tty[ 5],'deci_tty4' ,[]);
tty_makedev(@deci_tty[ 6],'deci_tty5' ,[]);
tty_makedev(@deci_tty[ 7],'deci_tty6' ,[]);
tty_makedev(@deci_tty[ 8],'deci_tty7' ,[]);
tty_makedev(@deci_tty[ 9],'deci_ttya0' ,[]);
tty_makedev(@deci_tty[10],'deci_ttyb0' ,[]);
tty_makedev(@deci_tty[11],'deci_ttyc0' ,[]);
//
if (init_tty<>nil) then
begin
init_tty();
end;
end;
end.