unit sys_conf; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface uses mqueue, time, kern_param, vmount, vfile, vuio, vnode, sys_event, vm, sys_vm_object, kern_mtx; const //modeventtype MOD_LOAD =0; MOD_UNLOAD =1; MOD_SHUTDOWN=2; MOD_QUIESCE =3; MAKEDEV_ETERNAL_KLD=0; SI_ETERNAL =$0001; { never destroyed } SI_ALIAS =$0002; { carrier of alias name } SI_NAMED =$0004; { make_dev _alias has been called } SI_CHEAPCLONE=$0008; { can be removed_dev'ed when vnode reclaims } SI_CHILD =$0010; { child of another struct cdev *} SI_DEVOPEN =$0020; { opened by device } SI_CONSOPEN =$0040; { opened by console } SI_DUMPDEV =$0080; { is kernel dumpdev } SI_CANDELETE =$0100; { can do BIO_DELETE } SI_CLONELIST =$0200; { on a clone list } SI_UNMAPPED =$0400; { can handle unmapped I/O } type pp_cdev=^p_cdev; p_cdev=^t_cdev; t_cdev=packed record si_mountpt :p_mount; si_flags :DWORD; _align1 :Integer; si_atime :timespec; si_ctime :timespec; si_mtime :timespec; si_uid :uid_t; si_gid :gid_t; si_mode :mode_t; si_drv0 :Integer; si_refcount :Integer; _align2 :Integer; si_list :LIST_ENTRY; //(cdev) si_clone :LIST_ENTRY; //(cdev) si_children :LIST_HEAD ; //(cdev) si_siblings :LIST_ENTRY; //(cdev) si_parent :p_cdev; si_name :PChar; si_drv1 :Pointer; si_drv2 :Pointer; si_devsw :Pointer; //cdevsw si_iosize_max :Integer; { maximum I/O size (for physio &al) } _align3 :Integer; si_usecount :QWORD; si_threadcount:QWORD; si_snapdata :Pointer; //snapdata __si_namebuf :array[0..SPECNAMELEN] of AnsiChar; end; d_open_t =Function (dev:p_cdev;oflags,devtype:Integer):Integer; d_fdopen_t =Function (dev:p_cdev;oflags:Integer;fp:p_file):Integer; d_close_t =Function (dev:p_cdev;fflag,devtype:Integer):Integer; d_strategy_t =Procedure(bp:Pointer);//bio d_ioctl_t =Function (dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer; d_read_t =Function (dev:p_cdev;uio:p_uio;ioflag:Integer):Integer; d_write_t =Function (dev:p_cdev;uio:p_uio;ioflag:Integer):Integer; d_poll_t =Function (dev:p_cdev;events:Integer):Integer; d_kqfilter_t =Function (dev:p_cdev;kn:p_knote):Integer; d_mmap_t =Function (dev:p_cdev;offset:vm_ooffset_t;paddr:p_vm_paddr_t;nprot:Integer;memattr:p_vm_memattr_t):Integer; d_mmap_single_t =Function (dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer):Integer; d_mmap_single2_t=Function (dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer;maxprotp:p_vm_prot_t;flagsp:PInteger):Integer; d_purge_t =Procedure(dev:p_cdev); dumper_t=Function( _priv:Pointer ; { Private to the driver. } _virtual:Pointer ; { Virtual (mapped) address. } _physical:vm_offset_t; { Physical address of virtual. } _offset:Int64 ; { Byte-offset to write at. } _length:QWORD):Integer; { Number of bytes to dump. } const { * Types for d_flags. } D_TAPE=$0001; D_DISK=$0002; D_TTY =$0004; D_MEM =$0008; D_TYPEMASK=$ffff; { * Flags for d_flags which the drivers can set. } D_TRACKCLOSE =$00080000; { track all closes } D_MMAP_ANON =$00100000; { special treatment in vm_mmap.c } D_PSEUDO =$00200000; { make_dev() can return NULL } D_NEEDGIANT =$00400000; { driver want Giant } D_NEEDMINOR =$00800000; { driver uses clone_create() } D_UNMAPPED_IO=$01000000; { d_strategy can accept unmapped IO } { * Version numbers. } D_VERSION_00=$20011966; D_VERSION_01=$17032005; { Add d_uid,gid,mode & kind } D_VERSION_02=$28042009; { Add d_mmap_single } D_VERSION_03=$17122009; { d_mmap takes memattr,vm_ooffset_t } D_VERSION=D_VERSION_03; { * Flags used for internal housekeeping } D_INIT =$80000000; { cdevsw initialized } { * Character device switch table } type pp_cdevsw=^p_cdevsw; p_cdevsw=^t_cdevsw; t_cdevsw=packed object //declaration as "object" allows to skip fields when declaring a constant d_version :Integer; d_flags :DWORD; d_name :PChar; d_open :d_open_t; d_fdopen :d_fdopen_t; d_close :d_close_t; d_read :d_read_t; d_write :d_write_t; d_ioctl :d_ioctl_t; d_poll :d_poll_t; d_mmap :d_mmap_t; d_strategy :d_strategy_t; d_dump :dumper_t; d_kqfilter :d_kqfilter_t; d_purge :d_purge_t; d_mmap_single :d_mmap_single_t; d_mmap_single2:d_mmap_single2_t; d_spare0:array[0..1] of Integer; d_spare1:array[0..2] of Pointer; { These fields should not be messed with by drivers } d_devs:Pointer; //cdev d_spare2:array[0..1] of Integer; d_gianttrick:p_cdevsw; d_postfree_list:SLIST_ENTRY; //cdevsw end; const MAKEDEV_REF =$01; MAKEDEV_WHTOUT =$02; MAKEDEV_NOWAIT =$04; MAKEDEV_WAITOK =$08; MAKEDEV_ETERNAL =$10; MAKEDEV_CHECKNAME=$20; UID_ROOT =0; UID_BIN =3; UID_UUCP =66; UID_NOBODY =65534; GID_WHEEL =0; GID_KMEM =2; GID_TTY =4; GID_OPERATOR=5; GID_BIN =7; GID_GAMES =13; GID_DIALER =68; GID_NOBODY =65534; var devmtx:mtx; cdevp_free_list:TAILQ_HEAD=(tqh_first:nil;tqh_last:@cdevp_free_list.tqh_first); cdevsw_gt_post_list:SLIST_HEAD=(slh_first:nil); type cdevpriv_dtr_t=Procedure(data:Pointer); function devfs_get_cdevpriv(datap:PPointer):Integer; external; function devfs_set_cdevpriv(priv:Pointer;priv_dtr:cdevpriv_dtr_t):Integer; external; procedure devfs_clear_cdevpriv(); external; procedure devfs_fpdrop(fp:p_file); external; type ino_t=Integer; function devfs_alloc_cdp_inode():ino_t; external; procedure devfs_free_cdp_inode(ino:ino_t); external; procedure dev_lock(); external; procedure dev_unlock(); external; procedure dev_ref(dev:p_cdev); external; procedure dev_refl(dev:p_cdev); external; procedure dev_rel(dev:p_cdev); external; function dev_refthread(dev:p_cdev;ref:PInteger):p_cdevsw; external; function devvn_refthread(vp:p_vnode;devp:pp_cdev;ref:PInteger):p_cdevsw; external; procedure dev_relthread(dev:p_cdev;ref:Integer); external; procedure destroy_dev(dev:p_cdev); external; function dev2unit(d:p_cdev):Integer; function devtoname(dev:p_cdev):PChar; function make_dev_credv(flags:Integer; dres:pp_cdev; devsw:p_cdevsw; _unit:Integer; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):Integer; register; external; function make_dev(devsw:p_cdevsw; _unit:Integer; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):p_cdev; register; function make_dev_cred(devsw:p_cdevsw; _unit:Integer; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):p_cdev; register; function make_dev_credf(flags:Integer; devsw:p_cdevsw; _unit:Integer; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):p_cdev; register; function make_dev_p(flags:Integer; cdev:pp_cdev; devsw:p_cdevsw; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):Integer; register; function make_dev_alias_v(flags:Integer; cdev:pp_cdev; pdev:p_cdev; fmt:PChar; const Args:Array of const):Integer; register; external; function make_dev_alias(pdev:p_cdev; fmt:PChar; const Args:Array of const):p_cdev; register; function make_dev_alias_p(flags:Integer; cdev:pp_cdev; pdev:p_cdev; fmt:PChar; const Args:Array of const):Integer; register; function make_dev_physpath_alias(flags:Integer; cdev:pp_cdev; pdev,old_alias:p_cdev; physpath:PChar):Integer; external; function _nullop():Integer; function _eopnotsupp():Integer; function _enxio():Integer; function _enodev():Integer; function _einval():Integer; implementation uses errno; function dev2unit(d:p_cdev):Integer; inline; begin Result:=d^.si_drv0; end; function devtoname(dev:p_cdev):PChar; inline; begin Result:=dev^.si_name; end; function _nullop():Integer; begin Exit(0); end; function _eopnotsupp():Integer; begin Exit(EOPNOTSUPP); end; function _enxio():Integer; begin Exit(ENXIO); end; function _enodev():Integer; begin Exit(ENODEV); end; function _einval():Integer; begin Exit(EINVAL); end; function make_dev(devsw:p_cdevsw; _unit:Integer; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):p_cdev; register; public; var dev:p_cdev; res:Integer; begin res:=make_dev_credv(0, @dev, devsw, _unit, uid, gid, mode, fmt, Args); Assert((res=0) and (dev<>nil),'make_dev: failed make_dev_credv (error=%d)'); if (res=0) then Exit(dev) else Exit(nil); end; function make_dev_cred(devsw:p_cdevsw; _unit:Integer; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):p_cdev; register; public; var dev:p_cdev; res:Integer; begin res:=make_dev_credv(0, @dev, devsw, _unit, uid, gid, mode, fmt, Args); Assert((res=0) and (dev<>nil),'make_dev_cred: failed make_dev_credv (error=%d)'); if (res=0) then Exit(dev) else Exit(nil); end; function make_dev_credf(flags:Integer; devsw:p_cdevsw; _unit:Integer; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):p_cdev; register; public; var dev:p_cdev; res:Integer; begin res:=make_dev_credv(flags, @dev, devsw, _unit, uid, gid, mode, fmt, Args); Assert((((flags and MAKEDEV_NOWAIT)<>0) and (res=ENOMEM)) or (((flags and MAKEDEV_CHECKNAME)<>0) and (res<>ENOMEM)) or (res=0),'make_dev_credf: failed make_dev_credv (error=%d)'); if (res=0) then Exit(dev) else Exit(nil); end; function make_dev_p(flags:Integer; cdev:pp_cdev; devsw:p_cdevsw; uid:uid_t; gid:gid_t; mode:Integer; fmt:PChar; const Args:Array of const):Integer; register; public; var res:Integer; begin res:=make_dev_credv(flags, cdev, devsw, 0, uid, gid, mode, fmt, Args); Assert((((flags and MAKEDEV_NOWAIT)<>0) and (res=ENOMEM)) or (((flags and MAKEDEV_CHECKNAME)<>0) and (res<>ENOMEM)) or (res=0),'make_dev_p: failed make_dev_credv (error=%d)'); Exit(res); end; function make_dev_alias(pdev:p_cdev; fmt:PChar; const Args:Array of const):p_cdev; register; public; var dev:p_cdev; res:Integer; begin res:=make_dev_alias_v(MAKEDEV_WAITOK, @dev, pdev, fmt, Args); Assert((res=0) and (dev<>nil),'make_dev_alias: failed make_dev_alias_v (error=%d)'); if (res=0) then Exit(dev) else Exit(nil); end; function make_dev_alias_p(flags:Integer; cdev:pp_cdev; pdev:p_cdev; fmt:PChar; const Args:Array of const):Integer; register; public; var res:Integer; begin res:=make_dev_alias_v(flags, cdev, pdev, fmt, Args); Exit(res); end; end.