File:  [MW Coherent from dump] / coherent / a / usr / src / updateprovbyha
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:34 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

$�$�$�7�0707070064030053621006440000030000030000011777770507310624600004000000000431/newbits/lib/LIBCobjects/path.o��(#VW��F���u�����F���F��t�~�:t
��"s��G������v�}�/t��"s��G�/�F
�F��tD�^��F����F��t
��"s��G����"s��vh��z����|����~�t�w�+��_^�path_access_0%%*%7%C%i%v%�7�%�0�0707070064030053611006440000030000030000011777770507310624600004200000000523/newbits/lib/LIBCobjects/perror.oTxEVWU��v�;}��㋿��T�thV�����hhe�����hW����hhh�����_^�Bad error number: 
errno_fputs__stderr_sys_nerr_sys_errlist_perror_'	'
''$'%7)'/$275';7?'E$H7K0707070064030053601006440000030000030000011777770507310625200004300000000752/newbits/lib/LIBCobjects/pnmatch.obHVW��v�~
�~u$�<u�A�F�FPW��FP������t��'��G���F��u���F���F��F��f�CC.;��t��.�g$*?[\^���,��~t��N몃~u��~�t�됋�G���F��~�u��~�]u��~�\u�=-u	��G���F��F�;F�t�=-u�G�ߊ�;F�|��F�;F�|��=t��G�?]u�~�t�1��T�=u�!�N�vWV������t����F�?u��/��G���F��t"�F�;F�u�����~t����<�D��~t�+��_^�pnmatch_00'040D S0b t v x z | ~0�0�0�0�0�00
00 0B0M0S0707070064030053571006440000030000030000011777770507310625200004200000000705/newbits/lib/LIBCobjects/putenv.o�xAVW��~u������+���^�?=t��^�?u���G��G�6�<tW�4�v�����u�F��}���ߋ�+�.�>�@@����W�������u��+�����ƉF�������^���tG���G��ދF���G�����>�t
�6��4����6�6�+��_^�free_putenv_errno_malloc_environ_strncmp_'0'0'<7J'c i7s'�'�%�%�7�'�%�0707070064030053561006440000030000030000011777770507310625300004100000000704/newbits/lib/LIBCobjects/qsort.oR(VW�F�v�F��F��^��7�F
�G�̓�D�F�;�s�%�^��7�G�F
�n��~
s����F�f
ljF��v�F
���f�PW����V�F)F��F�P�V���|;v�r�~��PV�V���|;~�r�;~�s�v�v���vV�v��V����F�+�+��v�F���+�+��v)F
�F�;F
v�F��^��7�G���Y��F��^��?�F
�G�F��F
�A��F
�N
=w���Ƌ��F��F
�F��F��N��tW�FF��F�P�V���}�~���;�t�vVW������F����_^�qsort__memxchg_0'0?7^7�0�0�07@0707070064030053551006440000030000030000011777770507310625300004000000000321/newbits/lib/LIBCobjects/rand.oN<VWU��F+ңN�P�_^�VWU��jh
f�6P�6N������b��6�N�P�������%�+��_^�rand_lrmulsrand_$$$!$%7($5$90707070064030053541006440000030000030000011777770507310625300004500000000364/newbits/lib/LIBCobjects/shellsort.o�VW��v�F
�.�>��F��~�~\�F��F�;F
}L+F����|>��F��n�P���n�P�V���~!�v��F��n�P���n�P���+~���F�묋F���_^�VW��v�~
�~t���F���F�����G�F���Nu��_^�shellsort_ 0c0707070064030053531006440000030000030000011777770507310625300004100000000474/newbits/lib/LIBCobjects/sleep.o�P0VW��vhjj������F�V��������t0�t$;�vW�����j�2���V�+���;�t�;�s�+�j����v�j����W�����_^�VWU��~u�����>�t�����_^�signal_alarm_sleep_pause_ 
777.060O7Z7a%w7|%�%�0707070064030053521006440000030000030000011777770507310625300004200000002543/newbits/lib/LIBCobjects/strtod.oB�VW��v+ɉN��N�N��N�����F��V�+��F�F�F�F��F���F�F䘋؋���u��=+t
=-u
�N���F������u�v�@��u����0�~�u�t�F�~��ws��~���w��F�tH�v��v��T����N��F�P�v��D����>��;���
�5��2�����F��F��F��F��)�v��v�������F��F��F��F�N��F��Ǚ�"�F��Ǚ�F�V�jj
�v��v������F�V�F��V��F�t�N���F��������.u�F�u�N����F�t0�v��v������|��F�P�v��r����l��i���
�c��`�����v��v��R�����F��F��F��F��et��Et��D��F��F����=+t
=-u
�N���F������u�v��+��F�F���t(�~�u��0t�F�kF�
�ȋ��-0�F���F�����у~�~�F�t� ��	F�N�R�F�t�F�)F���F�F�N�~���N� �/�F�F�H=&|�N���~�t�v��d����^��F�P�W���
�~
t�^
�7�F� t �"�����_�F�t�"�F��}�F�½�F��F��H�F�t�F��F��F��F��6���F��F��F��F��_^�errno_ddrmul_fpac_dlmul_ctype_dpushdvcvt_pow10_vrmuldraddstrtod_'A'a0j'n0t0�0�7�7�7�7�7�7�7�	'�'�'�'�7�'�'�''
750Y7|7�7�7�7�7�7�	7�'�'�'�'�0�'�0'7�7�7�'�'�'�'�'�'�'
'''' ')'/'5';0707070064030053511006440000030000030000011777770507310625300004200000001670/newbits/lib/LIBCobjects/strtol.oz�^VWU��j�v�v
�v�!���_^�VWU��j�v�v
�v����_^�VW��v+ɉN��N��N�����F��V���F���F�F昋؋���u��=+t
=-u
�F���F�����~u��0t�X�<xt�<Xu����F�~u��0u�<xt�<Xu�F�F��F�����F0�F�F7�F�FW�F���t;~�|+��t;~�|��t;~�|�~�t�D���F���	�~t%�F�RPj�j�������F�V�F�RPj�j����%�F�RPh�j������F�V�F�RPh�j������F�V���u�;~�}|��0�F��V�;V�wr$;F�r�F��V�;V�u;;F�u6�Ǚ;V�rw,;F�w'�Ǚ�F�V�F�P�F�RP�6���F�V�F��V���F���F�������t�F
���v�%��t;~�}��7�u���t;~�}��W�c�N�~
t�^
�7�~�t)�"�~t�������0�~�t+����#�������~�t�F��V����؃���F��V��_^�errno_strtol_lrdivlrrem_ctype_vrdivvrremvlmulstrtoul_00+'d0�'�'�'�07)7?7O7f's0y7�'�0�'�0'0'40707070064030053471006440000030000030000011777770507310625400004000000000176/newbits/lib/LIBCobjects/swab.o>VW��v�~
�~r(��F���F���G�F���F���^����G�F���n���_^�swab_0707070064030053441006440000030000030000011777770507310625400004300000001700/newbits/lib/LIBCobjects/sys_err.o�(xRSf�������0BNdv��������%=J`o{������(not the super userno such file or directoryno such processinterrupted system callI/O errorno such device or addressarg list too longexec format errorbad file numberno childrenno more processesnot enough memorypermission deniedbad addressblock device requiredmount device busyfile existscross-device linkno such devicenot a directoryis a directoryinvalid argumentfile table overflowtoo many open filesnot a typewriterfile busyfile too largeno space left on deviceillegal seekread-only file systemtoo many linksbroken pipemath argumentresult too largeout of kernel spacedriver not loadedbad exec formatdevice needs attentiondevice busysys_nerr_Psys_errlist_$$$$$$
$$$$$$$$$$$ $"$$$&$($*$,$.$0$2$4$6$8$:$<$>$@$B$D$F$H$J$L$N0707070064030053411006440000030000030000011777770507310625400004200000000553/newbits/lib/LIBCobjects/system.o�x1VW�����F��}����n�~�uj�vh�h�h������
j�����jj�������jj�����F��F�P������;F�t�}��}�v�Wj�����v�j�����F��_^�/bin/shsh-csystem_fork_wait_exit_signal_execl_7$!$$$'7*727<7H7U7p7{0707070064030053401006440000030000030000011777770507310625400004300000000575/newbits/lib/LIBCobjects/tempnam.o�x/VWU��j@��������t{�~uh�������F�u�F��~
u�F
����vV�����<tF��;�s�|�/t��F�/�v
V�����<tF��h�V����W����jW�z���=��u����_^�TMPDIR/tmptXXXXXXstrcpy_access_tempnam_malloc_getenv_mktemp_7$7$,$77@7b$p7t7{7�0707070064030053371006440000030000030000011777770507310625400004200000000421/newbits/lib/LIBCobjects/tmpnam.oL@d%VW��v�u�\hLV�����hQV�����hSV�����V������F�jP�����=��u��_^�/tmp/tXXXXXXstrcpy_access_tmpnam_mktemp_strcat_%$7$7$%7)707<0707070064030053361006440000030000030000011777770507310625400004300000001113/newbits/lib/LIBCobjects/ttyname.o"�AVWU���v����|��+��_^�VW�"�F�P�v������|h<h2��������u������~�F�F��F��D~�LV�T������*�=
t[�D~�LV�T������*�=
t=�D~�LV�T������*�=
tVjh!�C����tj
h�4����u�F����4j
h��������F�Ph�����|
;~�u�F�;F�t�F��L�V������F��_^�/dev/console/etc/ttysrfstat_fclose_stat_ttyname_fttyslot_index_fopen_fgets_0	$7+$5$87;0J$�7�$�7�$�7�$�7�070707070064030053351006440000030000030000011777770507310625500004300000000163/newbits/lib/LIBCobjects/ttyslot.o(VWU��j��������}F���_^�ttyslot_fttyslot_70707070064030053311006440000030000030000011777770507310625500004200000000502/newbits/lib/LIBCobjects/_ctype.o@@@@@@@@@PPPPP@@@@@@@@@@@@@@@@@@�                      						      





    @_ctype_0707070064030053301006440000030000030000011777770507310625500004400000000120/newbits/lib/LIBCobjects/_tolower.oVWU��F
 �_^�_tolower_0707070064030053271006440000030000030000011777770507310625500004400000000120/newbits/lib/LIBCobjects/_toupper.oVWU��F%���_^�_toupper_0707070064030053261006440000030000030000011777770507310625500004300000000157/newbits/lib/LIBCobjects/isalnum.o(VWU��~��*�%�_^�isalnum__ctype_'
0707070064030053251006440000030000030000011777770507310625500004300000000157/newbits/lib/LIBCobjects/isalpha.o(VWU��~��*�%�_^�isalpha__ctype_'
0707070064030050611006440000030000030000011777770507310625500004300000000130/newbits/lib/LIBCobjects/isascii.oVWU���F�u��+��_^�isascii_0707070064030037561006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/iscntrl.o(VWU��~��*�%@�_^�iscntrl__ctype_'
0707070064030037551006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/isdigit.o(VWU��~��*�%�_^�isdigit__ctype_'
0707070064030037541006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/isgraph.o(VWU��~��*�%'�_^�isgraph__ctype_'
0707070064030037521006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/islower.o(VWU��~��*�%�_^�_ctype_islower_'
0707070064030030331006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/isprint.o(VWU��~��*�%��_^�_ctype_isprint_'
0707070064030027151006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/ispunct.o(VWU��~��*�% �_^�_ctype_ispunct_'
0707070064030027071006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/isspace.o(VWU��~��*�%�_^�isspace__ctype_'
0707070064030021731006440000030000030000011777770507310625600004300000000157/newbits/lib/LIBCobjects/isupper.o(VWU��~��*�%�_^�_ctype_isupper_'
0707070064030010601006440000030000030000011777770507310625700004400000000157/newbits/lib/LIBCobjects/isxdigit.o(VWU��~��*�%�_^�isxdigit__ctype_'
0707070064030010201006440000030000030000011777770507310625700004300000000120/newbits/lib/LIBCobjects/toascii.oVWU��F%�_^�toascii_0707070064030004221006440000030000030000011777770507310626000004300000000167/newbits/lib/LIBCobjects/tolower.o(VWU��~��t�F
 ��F�_^�_ctype_tolower_'
0707070064030004211006440000030000030000011777770507310626000004300000000167/newbits/lib/LIBCobjects/toupper.o(VWU��~��t�F%����F�_^�_ctype_toupper_'
0707070064030004171007550000030000030000011777770507310626000004100000000116/newbits/lib/LIBCobjects/abort.oVWU��̀��]_^�abort_0707070064030003601007550000030000030000011777770507310626000004100000000112/newbits/lib/LIBCobjects/canon.o
�܋W�G�_canl_0707070064030003571007550000030000030000011777770507310626000003700000000253/newbits/lib/LIBCobjects/div.od�܋G�����W���remquotdenom	div_numer	$
0707070064030003561007550000030000030000011777770507310626000004100000000312/newbits/lib/LIBCobjects/inout.o&x�܋W�Ë܋W�*�Ë܋W�G�Ë܋W�G*���port	inb_outb_data	in_out_0707070064030003541006440000030000030000011777770507310626000004100000000244/newbits/lib/LIBCobjects/l3tol.odVW��v�~
�~tM�*䙹�������F��V��E*�	F�	V��E*䙹������	F�	V����ރ��F��V���W�Nu��_^�l3tol_0707070064030111141007550000030000030000011777770507310626100004000000000426/newbits/lib/LIBCobjects/ldiv.obxWVU��F�V
�N�^��3����y���ك���y�����؃������y���߃����t���؃���b�?�w�G�W��]^_�remfquotbldiv_denom	numer	vdiv74$O0707070064030110331006440000030000030000011777770507310626100004100000000216/newbits/lib/LIBCobjects/ltol3.oNVW��v�~
�~t8�߃���W�F��V����������F��D�V���������D���Nu��_^�ltol3_0707070064030110321007550000030000030000011777770507310626100004000000001141/newbits/lib/LIBCobjects/modf.o��EVWU�����v�~�����F���V���*�-��F�+��~�����v������}=8|���r��8�~-|�G���Ȱ��� �N��V�F�v
�~��������������
�u*����
�x���������������n���щ��6�>��t0��t)��V�0�V�~�u�u�u�5����
���������
��]_^��@one�modf__fpac_ip	dlsubd	dzerodpushCLAIM	EXP	��SIGN	��dladd'40;7C0F'�'�'�'�'�'�#�7�7�'�7�0707070064030110311007550000030000030000011777770507310626100004200000000306/newbits/lib/LIBCobjects/setjmp.o6dY�܋�/�g�O+���܋G�_�;Nt�n�u�����]_^�g�glongjmp_l0l1+l20setjmp_0707070064030110301006440000030000030000011777770507310626100004300000000505/newbits/lib/LIBCobjects/signame.o�3"#*49EPXht{������hangupinterruptquitalarm clockterminatedrestartbad system callpipe brokenkilledbreakpointsegmentation violationdivide checkoverflowsignal 14signal 15signal 16signame_$$$$$$
$$$$$$$$$$$ 0707070064030110261006440000030000030000011777770507310626100004200000000236/newbits/lib/LIBCobjects/calloc.o,<
VWU��v
���f��V��������t
VjW��������_^�calloc_malloc_memset_77!0707070064030110251006440000030000030000011777770507310626200004200000001576/newbits/lib/LIBCobjects/malloc.o<�pVW��>t+���F%��F�;Fs�F�F����v��������=��u��~�v}�n��~�s��F��҃>u�
�ƉF����/;6u���F��D�F��
��-���E�F��u�
�F�-
���F��-����F��E��_^�VW��~u+����F%���F�;Fr�+��6�
�F��F��N��t$��N���u>+��~�t
�F�%�����D����;6tjhj��������v������u���t���F�%����F��
�F�;F�s��롋F�)F��F�=s�%���F����F����F����F���F����
�D�_^�VWU��~t@�FHH���<��sjh*j�'����!�������;t
��u�6�_^�Bad pointer in malloc.
Bad pointer in free.
free_�__a_first___a_count_
write_sbrk_malloc_�__a_scanp_abort_$0$*$-73$A$_$f$p$s$y$�$�$�$�0�$�$�$-$4797?0E$e$�$�$�$�$�7�7�$�$�$�0707070064030110241006440000030000030000011777770507310626200004100000000406/newbits/lib/LIBCobjects/memok.olPVW�����u�>uP�>uI��F�F���F��F��N��t#;6u�F��%���F��t��F���D���Ӄ~�u;6t�+��_^�__a_first___a_count___a_scanp_memok_''''('9'b0707070064030110221006440000030000030000011777770507310626200004200000000343/newbits/lib/LIBCobjects/notmem.ol<VW��~tY��F��tO�^KK�^��?tB�>��O�t)�F�;F�u+��.�^��7�t	��%�����^��G�F��ЋF�;t������_^�__a_count_notmem___a_scanp_'
'%'\0707070064030110201006440000030000030000011777770507310626200004300000001002/newbits/lib/LIBCobjects/realloc.o"x<VW��v�t���v
�������F
%���F�;F
s���D��F��^��%����;~�r*+~���=v�F���F�ÉF���
�^��������F��F��^���F��F�t[~��F�;F�vP+F�=v�F��^���F�ÉF��F�+F��^����F�%���F��^���F�ÉF���F�;u��F����v
�����F��t+��HHPV�v�����V������F���~
t��V�����+��_^�free_realloc___a_count_malloc_memcpy___a_scanp_0700.'h0m'�'�'�7�7�7070707070064030110161006440000030000030000011777770507310626200004100000000246/newbits/lib/LIBCobjects/fgetw.ofVW��v�D~�LV�T������*��=��u����3�D~�LV�T������*�F�=��u�L��ԋF����ȋ���_^�fgetw_0707070064030110151006440000030000030000011777770507310626300004100000000220/newbits/lib/LIBCobjects/fputw.oPVWU��v
�L}�DV�v�T
���	�<��F��L}�DV�F��P�T
����<��F����F�_^�fputw_0707070064030110131006440000030000030000011777770507310626300004000000000246/newbits/lib/LIBCobjects/getw.ofVW��v�D~�LV�T������*��=��u����3�D~�LV�T������*�F�=��u�L��ԋF����ȋ���_^�getw_0707070064030110111006440000030000030000011777770507310626300004000000000220/newbits/lib/LIBCobjects/putw.oPVWU��v
�L}�DV�v�T
���	�<��F��L}�DV�F��P�T
����<��F����F�_^�putw_0707070064030110071006440000030000030000011777770507310626300004200000000520/newbits/lib/LIBCobjects/_fgetb.o�x(VWU��vV������t����h�>
u	h�������D+DP�t�D
�P�����؉D=u�>t�L��D밃|u�L@뤋D�D)D�<��*��_^�errno__fgetb__stdout_fflush__fputt_read_7
'''!7$'+7B'S0707070064030110061006440000030000030000011777770507310626300004200000000445/newbits/lib/LIBCobjects/_fgetc.o^x#VW��v�>
u	h������D�j�F�P�D
�P�����=��t�t�F�*���>t
�L���L@����_^�errno__fgetc__stdout_fflush__fputt_read_''
'7'!71'H0707070064030110051006440000030000030000011777770507310626300004400000000124/newbits/lib/LIBCobjects/_fgeteof.oVWU��v�D����_^�_fgeteof_0707070064030110041006440000030000030000011777770507310626300004200000001067/newbits/lib/LIBCobjects/_fopen.o2�9VW��v�~�F��F��F��^
�F
��F��F�r�~�rt���F��F�w�^
���F�
�t�~�bt�~�+t�F��:F�t���F��}�~�u�v��v�������}9�~�u�~�t-h��v�i������|�~�tW�V����v��v�J������|l�~�t
jjjW�1����uj�%������u	W�����>�D+��D��D�D�D�D
�LjD
����~�wu�F����~�au�F���+��_^�_fpinit_open__fopen_malloc_creat_lseek_close__fginit_010_7w7�7�7�7�7�7�''00)0707070064030110031006440000030000030000011777770507310626400004300000000322/newbits/lib/LIBCobjects/_fpseek.o`<
VWU��v�DtV�T���D;w	V������6j�<+|�ǙRP�D
�P������؋ʃ��u
���u������D�D+��_^�fflush_lseek__fpseek_7770707070064030110021006440000030000030000011777770507310626400004200000000221/newbits/lib/LIBCobjects/_fputb.o8(VWU��v�~
W������t�����E+EH�E����*�*��_^�_fputb__fpseek_7
0707070064030110011006440000030000030000011777770507310626400004200000000354/newbits/lib/LIBCobjects/_fputc.o\PVW��v�~
�ƈF��E��E�u2W������u'j�F�P�E
�P�����=u��*���>t�M�����_^�errno_write__fputc__fpseek_'7$79'K0707070064030110001006440000030000030000011777770507310626400004200000000252/newbits/lib/LIBCobjects/_fputt.oL(
VWU��v�~
�E�E;uW������u���ƈ*�=
uW������t������*��_^�fflush__fputt_7760707070064030107771006440000030000030000011777770507310626400004400000000313/newbits/lib/LIBCobjects/_stropen.ol(VWU��v�F��D�D�F
�؉D�|�}�D��D
O��D
;���_^�VWU��v
�D����_^�VWU��v
�D��<��F�*��_^�_stropen__fgeteof_' , 30707070064030107761006440000030000030000011777770507310626400004200000000321/newbits/lib/LIBCobjects/fclose.oFPVWU��v�Du����/V��������D
�P������|t�Du	�t������D���_^�free_fclose_fflush_close_77"770707070064030107751006440000030000030000011777770507310626400004200000000275/newbits/lib/LIBCobjects/fdopen.oF<VWU��~|5�~}/���(s&�<t�<�Eu�v�4�v
j�����������+��_^�_fp__fopen_fdopen_''720707070064030107741006440000030000030000011777770507310626500004200000000341/newbits/lib/LIBCobjects/fflush.oj<VWU��v�D��D�uI�+D���~W�t�D
�P�������;�t�>u�|�D;u�D����D+���L�����_^�errno_write_fflush_'7.';0707070064030107721006440000030000030000011777770507310626500004100000000146/newbits/lib/LIBCobjects/fgetc.o&VWU��v�D~�LV�T����<��*��_^�fgetc_0707070064030107711006440000030000030000011777770507310626500004100000000254/newbits/lib/LIBCobjects/fgets.olVW��v
�F�F�N~<�^�G~�OS�W����^���F��^��*��=��t�^��F��Lj�=
u��^�����u�F�;Fu+���F�_^�fgets_0707070064030107661006440000030000030000011777770507310626500004100000000261/newbits/lib/LIBCobjects/fopen.o:<VWU����(s&�<t�<�Euj��4�v
�v�����������+��_^�_fp__fopen_fopen_''
7&0707070064030107651006440000030000030000011777770507310626500004100000000154/newbits/lib/LIBCobjects/fputc.o,VWU��v
�L}�DV�v�T
����<��F�*��_^�fputc_0707070064030107641006440000030000030000011777770507310626500004100000000224/newbits/lib/LIBCobjects/fputs.oTVW��v�~
�<t<�M}�EW��F��P�U
������F���F���^��*�=��u��E�tĸ�����_^�fputs_0707070064030107621006440000030000030000011777770507310626500004100000000403/newbits/lib/LIBCobjects/fread.o�(VW��v�~�F�f
�F��Et��F�F�W�U���^���N��}u�Eu1�~�tV�E~�MW�U������*�F�=��t5��F��N����v�V�E
�P�����F��~)F���~�u�M@��M��F�f
+F�+��v
�_^�fread_read_7w0707070064030107611006440000030000030000011777770507310626500004300000000226/newbits/lib/LIBCobjects/freopen.o$<
VWU���v�����j��v�v
�v������_^�freopen__fopen_fclose_7	70707070064030107571006440000030000030000011777770507310626600004100000000346/newbits/lib/LIBCobjects/fseek.ot<
VWU��v�~u�Dt�n
�^V�����=��u����B�v�v�v
�D
�P������؋ʉ^
�N���u���tӃ|t�F
%�D��D�d�+��_^�fseek_lseek__fpseek_77<0707070064030107561006440000030000030000011777770507310626600004100000000273/newbits/lib/LIBCobjects/ftell.ob(VW��vjjj�D
�P������؋ʉ^��N����u
���u�������(�|t�<+|�ǙF�V��Dt�n��^��F��V��_^�lseek_ftell_70707070064030107551006440000030000030000011777770507310626600004200000000361/newbits/lib/LIBCobjects/fwrite.o�(VW��v�~�F�f
�F��EtW�U���}u�EuH�~�t8�M}�EW��F�*�P�U
������F���F�*�^��*�=��t�N��ƒ~�t+���v�V�E
�P�~���;F�t�M���F�_^�write_fwrite_7�0707070064030107531006440000030000030000011777770507310626600004000000000153/newbits/lib/LIBCobjects/getc.o(VWU���v������_^�getc_fgetc_7	0707070064030107511006440000030000030000011777770507310626600004300000000236/newbits/lib/LIBCobjects/getchar.o,(VWU���~�h�����>��*��_^�_stdin_getchar_''
''''!0707070064030107471006440000030000030000011777770507310626600004000000000314/newbits/lib/LIBCobjects/gets.oZ(VW��v���~�h�������*�F�=��t
�~�
t��G�����~��u;�u+�����_^�gets__stdin_'
''''#''0707070064030107251006440000030000030000011777770507310626600004100000001634/newbits/lib/LIBCobjects/popen.o�(�VW��F�P������}+����^
�?wu��~��+��~������F�����^�����}�v������v�����뽋��ヿ�ui��u"�v������
�P�����v������v�� �v��q����
�P�f����v��]����v��T���j�vh�h�h��@���
j�8�����u�v��*���h��v���v�����h��v��
����_^�VW�
�^�G
������㋿�����LJ��t�v�����=��u����ojj������F�jj�����F�jj�����F��F�P�����ȉN�;�t�~�}�~�}�F����v�j�{����v�j�p����v�j�e����F��_^�/bin/shsh-cwrpopen_pipe_fork_wait_exit_fclose_fdopen_signal__stdin__stdout_pclose_�dup_execl_close_7076%=7G
7P
%]7k
'q7v
77�
'�	7�
7�7�
$�$�$�7�7�7�
$�7�
$�7�%%7#777D7Q7^7�7�7�0707070064030107221006440000030000030000011777770507310626700004000000000157/newbits/lib/LIBCobjects/putc.o(VWU���v
�v������_^�fputc_putc_70707070064030107211006440000030000030000011777770507310626700004300000000244/newbits/lib/LIBCobjects/putchar.o2(VWU���}�h�v�
����>��F�*��_^�putchar__stdout_''
''' '$0707070064030107201006440000030000030000011777770507310626700004000000000433/newbits/lib/LIBCobjects/puts.o�(AVWU��v�<tE�}�h��F��P�
�������F���*�=��uǠ����ǀt�����/�}�hj
�
����>��
�*�=��tϸ�_^�_stdout_puts_''''#','0'B'T'Z']'c'l'p0707070064030107171006440000030000030000011777770507310626700004200000000177/newbits/lib/LIBCobjects/rewind.o&(VWU��vjjjV��������u�d���_^�rewind_fseek_70707070064030107161006440000030000030000011777770507310626700004100000005361/newbits/lib/LIBCobjects/scanf.o�VWU��FPh�L���_^�VWU��F
P�v�6���_^�VW��F�P�v�����P�v�����F
P�F�P����_^�VW�X�F��^
�F
��F��^��F������CC.;��u5.�g
	
 %������v�v� ����P�J������u����^�G~�OS�W����^���F�^�*�ȋ�;�t��vW������^��F�����=*u��+��F��~�t�^��F������F���0|"��9kF�
�ȋ��-0�F��^��F������ك�lu��+��F���hu��+��F�~�u�~�t�^��F������ƻ��CC.;��uL.�g$%DEFNOX[cdefnorsx���uu
��xx
��hh�����
���F��F�
��F��F���F��F���F��F��F�P�v��v��v����F�V�~�u�l�~�t�+��~�t�^
�F
���W��~��^
�F
��F��F�����F��F�P�v��v������F��F��F��F�~�u��~�t����~�t9�^
�F
��F��F��F��F���G��G��G��|��^
�F
��F��F��F��F���G��O��F��F��^��F�����=^u��+��F��~�t�^��F������t��]t�^��F��ƈ���^���F��F��^�G~�OS�W����^���F��^��*���N�~�u�F��^�G~�OS�W����^���F��^��*���F�!��v�������F�"�F��~�u�^
�F
��F��F����t`W�v�������u��+�;F�uF�F��~�u
�^��F��Lj�N�u����ċ^�G~�OS�W����^���F��^��*��뛃��t
�vW�����~�t2�~�t�����cu����^������^
�F
�7�v����F�����~�u�^�G@t�����F��_^�VW��v
�~�F��F��~�� ~� �^��v�����F��~�-u��+��F��u�~�+u-�^�G~�OS�W����^���F�^�*�F��^��^;?|m�ui�~�0t�
�^�^�G~�OS�W����^���F�^�*�F��^��;�|+�~�xt�� ��^�G��OS�W���F��^��^;?��F�-W�F�=
}!�F�-7�F�=
}�F�-0�F��|�~�	;v���uY�F�F�uQ�F�-x�F��uD�F���F�V�F�P�ƙRP�����+F�V�F��V��^�G~�f��^���F�^�*��\��v�v������~�t�F��V��
�F��V����؃��_^�VW�%+��F߉F݃~
~�~
 ~�F
 �^��^�;F
|�
�^�G~�OS�W����^���Fۋ^ۊ*����CC.;��t��.�g$	
 +-.0123456789Ee444EE[eeeeeeeeeexx�uw�^��^��]��t��uaG�^��F݋ƈ���'����t
��t��u��׃�|2��-��ȃ�����t
��t��u�믃�t��u���vV�J����^���F�P�:����_^�VWU��~�E~�MW�^�W����^�?��*��= t׃�
t҃�	t͋��_^�Bad format in scanf
	
 atof__stropen_fscanf_fputs__stderr__fpac_sscanf_,_stdin_ungetc_llmulscanf_index_abort_strlen_'
0
0#7:
7D0R ~ � � � � �0�7�0�7�0� � � � � � � � � � � � � � � � � � � �'�$�7�7�0�0*0<0E0s0�'�'�'�'�0�0�'�'�'�'�'�'�'�'�0�'�''
'''0$�0�$�77m00�0�0�0�0�0�0�7!	0;0O7X0� �0�           " $ & ( * , . 0 20C7�7�0707070064030107151006440000030000030000011777770507310627200004200000000134/newbits/lib/LIBCobjects/setbuf.oVWU��v�~
�|u�|�L�_^�setbuf_0707070064030107141006440000030000030000011777770507310627200004200000001137/newbits/lib/LIBCobjects/ungetc.o4�KVWU��v
�~�tS�|u"�Dh�D
�D�L�d��F�D�F�-�|u�D��Ձ|u�D��ǁ|u�D�빸���_^�VWU��v�D�D
�D�d��D�_^�VWU��v�D�D
�+D�D�~�D+�D�d��D�_^�VWU��v�D�D
�D�d��D�_^�VWU��v�D�4�����؉D�D�_^�VWU��v�~
W�U���M}
�EWV�U
���
���ƈ*��_^�_fgetb__fgetc__fpinit__fgeteof__fputb__fputc_ungetc_strlen__fginit_'  ': A'H O'V ]'s'x'�'�'�'�'�7�0707070064030107131006440000030000030000011777770507310627200004200000003547/newbits/lib/LIBCobjects/_dtefg.oL>T]VW�L�v�^
�G��G��G�����F���F���F���F��~}�FhL�v��v��v��v�����
�};�F���F���F���F���6���F���F���F���F���F�-�F�P�F�P�F�P�v�v��v��v��v��v������~et�~guT�~�
�F��;F�~D�~guj�jj�vWV�L��
���~�|�v�ht�	�F���Ph{V�����V��������~guj�j�v��vWV���
�_^�VW��v�~
�~}��F�0�%��F�F��=t��G����0�^���F�N�uۃ~tP�~t�=tE��F�.�F�N�~5�~t�=t*�F}��F�0�ދ�F�F��=t��G����0�^�������_^�VW�hL�v�v�v�v
����
�}>�^��F��F��F��F
��6���F��F��F��F
��^�hL�v�v�v�v
����
�u
�^������F�P�v�v�v�v
����
�F�PhT�N��F�P�v����p��m���
�g��d���
�v��v��v��v��R����F���P�F����@��F
P�9���
h\�v�v�v�v
�$���
�|�F�hd�F
P�����F��^��~et�~gu�~�
�F��;F�~�F��FF�@�F��~�7�~�u$hl�v�v�v�v
����
�~�^������^������~�~�F��v�F�F;�vzhL�v�v�v�v
�s���
�ta�v�v�v�v
�]�������F��0�h\W�G����A��v�v�v�v
�2����,��)���
��F��F��F��F
�|��hl�v�v�v�v
�����
�N��;Ft
�<0u���F���N;Ft���=9~����^����_^���Kx�TA B�������>�Ae+%02ue-%02u0101ddlmulfrexp_modf_ddrmul_dtefg_dldivilcmp_fpac_idcvtdicvtdlmuldrsubdpushsprintf__dtoa_�_pow10_strlen_''''!'$'*'0'6$G7V'c'i'o'u'y'}'�'�'�0�0�$$7
705$�7�''	'''''#')'/$>7M$^0a7t$~7�	7�7�7�7�7�7�7�7�$�7�$�7�$37B$Q0T$^0a$|7�7�$�7�	7�7�7�7�
'�'�'�'�0�$�7$E0707070064030107121006440000030000030000011777770507310627300004200000003370/newbits/lib/LIBCobjects/printf.o��|VWU��FPh�d���_^�VWU��F
P�v�N���_^�VW��F�Ph��v������F
P�F�P�&���N�}�F��F�Pj�V����	�~��F���_^�VW�^�F
�F��^���F�F��^��F����=%t/�u���^�O}
�GSW�W
���ԋ^���F��^��Lj���F� �F����F����^��F������-u�F��^��F������F���0u�F�0�^��F������*u'�^��F���F��}
�F��؉F�^��F�����,�F���0|"��9kF�
�ȋ��-0�F�^��F�����ك�.uU�^��F������*u�^��F���F�^��F�����,�F���0|"��9kF�
�ȋ��-0�F�^��F�����ك�lu&�^��F������dt��ot
��ut��xu��%�����F��F����F��ǻ�CC.;��t��.�gDOUXcdefgorsux����CO����^}��^��F���F�~�}�؉F��F�-j
�v�V�������j
�^��F��7��j��j��^���W�F�V�F��~�y���؃��F�V��F�-j
�v��v�V�5���j
�^��w�7V�"�����F��j��j��V�v��v�W�������F��j�F��^���F��u�F���F��F��F�����F�?t�~�|��+F�;F�~�N�-�F���F�F��^��F���^����^��7�v�
����F��F�F�+ƉF��}�F��~�uz�~�tG�~�0uA�^��?-u9�^�O}�GS�^��F���P�^�W
����^���F��^��F����^���F��N��t#�^�O}	�GS�v��ŋ^���F��^��F���;v�v;�^�O}�GS�^��F���P�^�W
���ڋ^���F��^��F����^�����~�u�>��F��N��u�1��^�O}�GS�v��W
���܋^���F��^��F�����_^�VW��v
�F��F��N��^����+��v���t �N��F��F��+��v�ڊ����^������N��^�������^��?t�F�F�F��F����^���F�_^�VW��v�~�n��N�^���ǙRP�v�v
������F�V��t4�N�F�F�ǙRP�v�v
�����؊����^��F�V�F
�V��N�F�F�F
�؊����^��^�?t
��F�F��F�����_^�{NULL}0123456789ABCDEF_dtefg__stropen_fprintf__stdout_sprintf_,vrdivvrremprintf_'
0
0#7=0K0� 0 3 5 7 9 ; = ? A C E G I K M0s0{0�0�0�7�#0g0K0X#�#�7"7F#O#u0707070064030107111006440000030000030000011777770507310627300004300000000364/newbits/lib/LIBCobjects/_fdtefg.oHPVWU��hh�����j������_^�
You must compile with the -f flag to include printf() floating point.
_dtefg__stderr_fprintf_exit_$'	770707070064030107101006440000030000030000011777770507310627300003700000000443/newbits/lib/LIBCobjects/_fp.oXx'(8H_fpinit__stderr_H_fp__stdin_(_stdout_8_fginit_$$$'0'2'@'B'P'R0707070064030107071006440000030000030000011777770507310627300004100000001322/newbits/lib/LIBCobjects/finit.o(,RVWU��v�|u9�Du'�D
�P��������t��uh������D�u�D�D
�A�Du�t��u�D�D
�D��D�D
�D
�P���D��D�D�_^�VW�jjj�v�b����؋ʉ^��N����u	���u+���F�+�.�6&���_^�VWU��vV�+���V�T���_^�VWU��v�~
W����WV�U
���_^�VWU��&��r�<t�4����������_^�_fgetb__fgetc__fpinit_�_fp_malloc_fclose__fputb__fputc__stdout__fputt_lseek_finit_isatty__finish__fginit_�7''7/'>'C'S'Z'_	'i'n0v7�
 �0�0�''70707070064030107061006440000030000030000011777770507310627400004000000000210/newbits/lib/LIBCobjects/exit.o<
VWU������v������_^�exit__exit__finish_770707070064030107051006440000030000030000011777770507310627400004300000000112/newbits/lib/LIBCobjects/_finish.o
VWU���_^�_finish_0707070064030124200407550000030000030000011777770507310627400002000000000000/newbits/kernel0707070064030103620407550000030000030000011777770507310627400002700000000000/newbits/kernel/USRSRC0707070064030103630407550000030000030000011777770507310627400003500000000000/newbits/kernel/USRSRC/i80860707070064030103640407550000030000030000011777770507310627400004100000000000/newbits/kernel/USRSRC/i8086/drv0707070064030110711006440000030000030000011777770507310627400005200000024024/newbits/kernel/USRSRC/i8086/drv/Makefile# Makefile for AT specific Coherent drivers

# System utility directory
USRSYS=/usr/sys

# Source directory
USRSRC=/usr/src/sys

# Loadable driver directory
LDRV=$(USRSYS)/ldrv

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

# Object directory
KOBJ=/usr/kobj

ARCHIVES=\
	$(USRSYS)/lib/al.a \
	$(USRSYS)/lib/at.a \
	$(USRSYS)/lib/ati.a \
	$(USRSYS)/lib/fl.a \
	$(USRSYS)/lib/gr.a \
	$(USRSYS)/lib/hs.a \
	$(USRSYS)/lib/kb.a \
	$(USRSYS)/lib/lp.a \
	$(USRSYS)/lib/mm.a \
	$(USRSYS)/lib/ms.a \
	$(USRSYS)/lib/rm.a \
	$(USRSYS)/lib/rs.a \
	$(USRSYS)/lib/st.a \
	$(USRSYS)/lib/tn.a \

DRVOBJ=\
	$(KOBJ)/alx.o \
	$(KOBJ)/at.o \
	$(KOBJ)/atas.o \
	$(KOBJ)/ms.o \
	$(KOBJ)/ati.o \
	$(KOBJ)/com1.o $(KOBJ)/com2.o \
	$(KOBJ)/fdisk.o \
	$(KOBJ)/fl.o \
	$(KOBJ)/fontw.o \
	$(KOBJ)/gr.o $(KOBJ)/gras.o \
	$(KOBJ)/hs.o \
	$(KOBJ)/kb.o \
	$(KOBJ)/mm.o \
	$(KOBJ)/lp.o \
	$(KOBJ)/mmas.o \
	$(KOBJ)/rm.o \
	$(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o \
	$(KOBJ)/st.o \
	$(KOBJ)/tn.o $(KOBJ)/tnas.o

DRIVERS=\
	$(LDRV)/al0 \
	$(LDRV)/al1 \
	$(LDRV)/at \
	$(LDRV)/fl \
	$(LDRV)/gr \
	$(LDRV)/hs \
	$(LDRV)/lp \
	$(LDRV)/mm \
	$(LDRV)/ms \
	$(LDRV)/rm

install: $(ARCHIVES) $(DRIVERS)
	@exec /bin/sync

all:	$(DRVOBJ)
	@exec /bin/sync

$(USRSYS)/lib/al.a: $(KOBJ)/com1.o $(KOBJ)/com2.o $(KOBJ)/alx.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/at.a: $(KOBJ)/at.o $(KOBJ)/atas.o $(KOBJ)/fdisk.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/ati.a: $(KOBJ)/mm.o $(KOBJ)/ati.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/fl.a: $(KOBJ)/fl.o
	rm -f $(USRSYS)/lib/fl.a
	ar rc $(USRSYS)/lib/fl.a $(KOBJ)/fl.o
$(USRSYS)/lib/gr.a: $(KOBJ)/mm.o $(KOBJ)/gr.o $(KOBJ)/gras.o \
				$(KOBJ)/fontw.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/hs.a: $(KOBJ)/hs.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/kb.a: $(KOBJ)/kb.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/lp.a: $(KOBJ)/lp.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/mm.a: $(KOBJ)/mm.o $(KOBJ)/mmas.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/ms.a: $(KOBJ)/ms.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/rm.a: $(KOBJ)/rm.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/rs.a: $(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/st.a: $(KOBJ)/st.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/tn.a: $(KOBJ)/tn.o $(KOBJ)/tnas.o
	rm -f $@
	ar rc $@ $<

$(KOBJ)/alx.o:				\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		alx.c
	$(CC) $(CFLAGS) -c -o $@ alx.c

$(KOBJ)/at.o: at.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h
	$(CC) $(CFLAGS) -DVERBOSE=1 -c -o $@ at.c

$(KOBJ)/atas.o: atas.s
	$(AS) -go $@ $<

$(KOBJ)/ati.o: ati.m
	$(CC) $(CFLAGS) -DATI_132=1 -c -o $@ ati.m

$(KOBJ)/com1.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM1=1 -c -o $@ al.c

$(KOBJ)/com2.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM2=1 -c -o $@ al.c

$(KOBJ)/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@ fdisk.c

$(KOBJ)/fl.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdioctl.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		fl.c
	$(CC) $(CFLAGS) -c -o $@ fl.c

$(KOBJ)/fontw.o: tools/fontgen.c
	$(CC) -o tools/fontgen tools/fontgen.c
	exec tools/fontgen > fontw.s
	exec /bin/rm tools/fontgen
	$(AS) -gxo $(KOBJ)/fontw.o fontw.s
	exec /bin/rm fontw.s

$(KOBJ)/gr.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		gr.c
	$(CC) $(CFLAGS) -c -o $@ gr.c

$(KOBJ)/gras.o: gras.m
	$(CC) $(CFLAGS) -c -o $@ gras.m

$(KOBJ)/hgas.o: gras.s
	$(CC) $(CFLAGS) -c -o $@ -DHERCULES gras.m

$(KOBJ)/hs.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		hs.c
	$(CC) $(CFLAGS) -c -o $@ hs.c

$(KOBJ)/kb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		kb.c
	$(CC) $(CFLAGS) -c -o $@ kb.c

$(KOBJ)/lp.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		lp.c
	$(CC) $(CFLAGS) -c -o $@ lp.c

$(KOBJ)/mm.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/sched.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/timeout.h	\
		mm.c
	$(CC) $(CFLAGS) -c -o $@ mm.c

$(KOBJ)/mmas.o: mmas.m
	$(CC) $(CFLAGS) -c -o $@ mmas.m

$(KOBJ)/ms.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/ms.h		\
		$(USRINC)/errno.h	\
		ms.c
	$(CC) $(CFLAGS) -c -o $@ ms.c

$(KOBJ)/rm.o: rm.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/buf.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/stat.h
	$(CC) $(CFLAGS) -c -o $@ rm.c

$(KOBJ)/rs0.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS0 -c -o $@ rs.c

$(KOBJ)/rs1.o: 				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS1 -c -o $@ rs.c

$(KOBJ)/rsas.o: rsas.s
	$(AS) -gxo $@ rsas.s

$(KOBJ)/st.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/const.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/mtioctl.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		st.c
	$(CC) $(CFLAGS) -c -o $@ st.c

$(KOBJ)/tn.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		tn.c
	$(CC) $(CFLAGS) -c -o $@ tn.c

$(KOBJ)/tnas.o: tnas.s
	$(AS) -gxo $@ tnas.s

# How to make loadable drivers.

$(LDRV)/al0:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al0 )

$(LDRV)/al1:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al1 )

$(LDRV)/at:	$(USRSYS)/lib/at.a
	( cd $(USRSYS); ldconfig at )

$(LDRV)/fl:	$(USRSYS)/lib/fl.a
	( cd $(USRSYS); ldconfig fl )

$(LDRV)/gr:	$(USRSYS)/lib/gr.a
	( cd $(USRSYS); ldconfig gr )

$(LDRV)/hs:	$(USRSYS)/lib/hs.a
	( cd $(USRSYS); ldconfig hs )

$(LDRV)/lp:	$(USRSYS)/lib/lp.a
	( cd $(USRSYS); ldconfig lp )

$(LDRV)/mm:	$(USRSYS)/lib/mm.a
	( cd $(USRSYS); ldconfig mm )

$(LDRV)/ms:	$(USRSYS)/lib/ms.a
	( cd $(USRSYS); ldconfig ms )

$(LDRV)/rm:	$(USRSYS)/lib/rm.a
	( cd $(USRSYS); ldconfig rm )
0707070064030103651006440000030000030000011777770507310627700004700000036064/newbits/kernel/USRSRC/i8086/drv/aha.c/*
 * This is the host adaptor specific portion of the
 * Adaptec AHA154x driver.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	91/05/01  04:54:43	root
 * Debug code and kalloc arg fixes.
 * 
 * Revision 1.1	91/04/30  11:01:41	root
 * Shipped with COH 3.1.0
 * 
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/sched.h>

#include <sys/scsiwork.h>
#include <sys/aha154x.h>

extern	saddr_t	sds;		/* System Data Selector */
static	paddr_t	sds_physical;	/* as physical address */
static	short	aha_i_o_base;
static	char	aha_loaded;	/* did load() find a host adaptor? */
static	char	dev_bit_map[8];	/* one byte per SCSI-ID; one bit per LUN */
char	drive_info[MAX_SCSI_ID * MAX_LUN]; /* "per drive" info/flags */

void	aha_intr();		/* interrupt service routine */

#define	MIN_MAILBOX	1
int	MAX_MAILBOX = { 8 };	/* tunable value */

static	scsi_work_t	*scsi_work_queue;
static	mailentry	*mailbox_in, *mailbox_out;
static	char		*aha_err_msg = { "no message" };

static	long	aha_timeout[] = { 
#define	TIMEOUT_PRESENT	0
	0x30000L,
#define	TIMEOUT_SENDCMD	1
	0x10000L,
#define	TIMEOUT_POLL	2
	0x100L,
};

#if	0
static
OUTB( port, value )
short port;
{	printf( "<O(%x,%x)>", port, value );
	outb( port, value );	}
INB( port )
short port;
{	register i = inb(port);
	printf( "<I(%x)=%x>", port, i );
	return i;	}
#else
#define	OUTB( port, value )	outb( port, value )
#define	INB(port)	inb(port)
#endif

#if	VERBOSE
#define	SETMSG(msg)	aha_err_msg = msg

static
char	*aha_last_msg()
{
	return aha_err_msg;
}

#else

#define	SETMSG(msg)
static
char	*aha_last_msg()
{
	return "error messages not verbose";
} 
#endif

static
int	no_mem()
{
	printf("aha154x: out of kernel memory\n");
}

int	aha_set_base( base )
{
	register i;

	i = aha_i_o_base;
	aha_i_o_base = base;
	return i;
}

int	aha_get_base()
{
	return aha_i_o_base;
}

aha_process( ccb )
ccb_t *ccb;
{
	register scsi_work_t *sw = ccb->ccb_sw;
	register BUF *bp;

#if	VERBOSE
	printf( "aha_process: ccb %x ", ccb );
	printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
	aha_ccb_print( ccb );
#endif
	if( ccb->ccb_sw == 0 ) {
#if	VERBOSE
		printf( "process: ccb %x with NULL sw\n", ccb );
#endif
		++ccb->opcode;
		wakeup( ccb );
		return;
	}

	bp = sw->sw_bp;
#if	VERBOSE
	printf( "bp = %x\n", bp );
#endif
	if( (ccb->hoststatus != 0) || (ccb->targetstatus != 0) ) {
		if( --sw->sw_retry > 0
		   || (ccb->targetstatus == CHECK_TARGET_STATUS
		   && ccb->cmd_status[12] == SENSE_UNIT_ATTENTION)) {
			int s = sphi();
			if( scsi_work_queue->sw_actf == NULL ) {
				scsi_work_queue->sw_actf = sw;
			} else {
				scsi_work_queue->sw_actl->sw_actf = sw;
			}
			scsi_work_queue->sw_actl = sw;
			spl(s);
			aha_start();
			return;
		}
		bp->b_flag |= BFERR;
	} else
		bp->b_resid = 0;
#if	VERBOSE
	printf( "bp flag = %o\n", bp->b_flag );
#endif
	bdone( bp );
	kfree( sw );
	kfree( ccb );
}

static
int	aha_1out( value )
{
	register i;

	while( (i = INB(aha_i_o_base + AHA_STATUS) & AHA_CDOPFULL) != 0 )
		if( (i & AHA_INVDCMD)
		 || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE) )
			return -1;
	OUTB( aha_i_o_base + AHA_WRITE, value );
	return 0;
}

static
int	aha_1in()
{
	register i;

	while( (i = INB(aha_i_o_base + AHA_STATUS) & AHA_DIPFULL) == 0 )
		if( (i & AHA_INVDCMD)
		 || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE) )
			return -1;
	return INB( aha_i_o_base + AHA_READ ) & 0xFF;
}

static
void	aha_cmd_out( value )
{
	register long l;
	register int i;

	for( l = aha_timeout[TIMEOUT_SENDCMD]; --l > 0; )
		if( ((i=INB(aha_i_o_base + AHA_STATUS))
		    & AHA_SCSIIDLE ) != 0 ) {
			aha_1out( value );
			return;
		}
#if	VERBOSE
		else
			printf( "aha: cmd_out status = %x\r", i );
#endif
	SETMSG( "timeout sending cmd byte" );
	printf( "aha154x: timeout sending cmd byte\n" );
}

static
int	aha_poll()
{
	register i;
	register l = aha_timeout[TIMEOUT_POLL];
	while( (--l > 0 )
	  &&  ((i = INB(aha_i_o_base + AHA_INTERRUPT)) & AHA_CMD_DONE) == 0 )
		;
	if( l == 0 )
		printf( "aha154x: aha_poll timed out\n" );

	i = INB(aha_i_o_base + AHA_STATUS);
	OUTB( aha_i_o_base + AHA_CONTROL, AHA_INTRRESET );
	return i;
}

static
void	aha_get_data( vec, cnt )
char	*vec;
int	cnt;
{
	while( --cnt >= 0 )
		*vec++ = aha_1in();
	aha_poll();
}

static
int	aha_present()
{
	long	l;

	if( INB(aha_i_o_base) == 0xFF ) {
		SETMSG( "no adapter found at io base" );
		return -3;
	}
	for( l = aha_timeout[TIMEOUT_PRESENT];
		(--l > 0) && (INB(aha_i_o_base + AHA_STATUS) & AHA_SELFTEST); )
			;
	if( l == 0 ) {
		SETMSG( "selftest not completed" );
		return -1;
	}
	if( INB(aha_i_o_base + AHA_STATUS) & AHA_DIAGFAIL ) {
		SETMSG( "diagnostics failed" );
		return -2;
	}
	if( INB(aha_i_o_base + AHA_STATUS) & AHA_INITMAIL ) {
		SETMSG( "mailbox initialization needed" );
		return 1;
	}
	if( INB(aha_i_o_base + AHA_STATUS) & AHA_SCSIIDLE ) {
		SETMSG( "adaptor okay, idle" );
		return 0;
	}
	SETMSG( "unknown status at start" );
	return -4;
}

static
void	aha_l_to_p3( value, vec )
paddr_t	value;
unsigned char *vec;
{
	register i;

	for( i = 3; --i >= 0; ) {
		vec[i] = value & 0xFF;
		value >>= 8;
	}
}

static
char	*aha_p3_to_v( vec )
unsigned char *vec;
{
	paddr_t adr;

	adr = vec[0];
	adr <<= 16;
	adr |= (vec[1]<<8) | vec[2];
	adr -= sds_physical;
	return (char *)adr;
}

aha_device_info()
{
	register i;
	static char buf[256];

	aha_cmd_out( AHA_DO_GET_DEVICES );
	aha_get_data( &buf[0], 8 );
	for( i = 0; i < 8; ++i )
		if( buf[i] != 0 )
			printf( "[%d] %x ", i, buf[i] );
	printf( "\n" );
}

int	aha_unload( ireq )
{
#if	VERBOSE
	printf( "aha_unload: %x\n", ireq );
#endif
	/*
	 *	we should really verify that everything
	 *	out there gets flushed.
	 */
	if (!aha_loaded)
		return;
	if( mailbox_out ) {
		kfree( mailbox_out );
		mailbox_out = 0;
	}
	clrivec( ireq );
}

int	aha_load( dma, ireq, base, head )
scsi_work_t *head;
{
	register int	i;
	unsigned char	adr[4];

#if	VERBOSE
	printf( "aha_load( %d, %d, 0x%x );\n", dma, ireq, base );
#endif
	aha_set_base(base);
	if( mailbox_out == 0 ) {
		if( (mailbox_out = 
		     kalloc(2 * MAX_MAILBOX * sizeof(mailentry))) == 0 ) {
			no_mem();
			return -1;
		} else
			mailbox_in = &mailbox_out[MAX_MAILBOX];
	}

	for( i = 0; i < MAX_MAILBOX; ++i )
		mailbox_out[i].cmd = mailbox_in[i].cmd = 0;

	sds_physical = VTOP2( 0, sds );
	aha_l_to_p3( VTOP2( mailbox_out, sds ), &adr[1] );
	adr[0] = MAX_MAILBOX;

	/*
	 * setup HW
	 */
	setivec( ireq, aha_intr );
	outb( 0xD6, 0xC1 );		/* DMA is currently hard coded for */
	outb( 0xD4, 0x01 );		/* DMA channel 5 */


	OUTB( aha_i_o_base+AHA_CONTROL, AHA_HARDRESET );
	if (aha_present() < 0) {
		printf("aha154x: initialization error or host adaptor not ");
		printf("found at 0x%x\n", aha_i_o_base);
		return -1;
	}
	aha_cmd_out( AHA_DO_MAILBOX_INIT );
	for( i = 0; i < 4; ++i )
		aha_1out( adr[i] );
	scsi_work_queue = head;
	++aha_loaded;
	return MAX_MAILBOX;
}

aha_command( sc )
register scsi_cmd_t *sc;
{
	register i;
	register ccb_t *ccb;

	short	count = sc->blklen;
	long	block = sc->block;

	ccb = (ccb_t *) kalloc(sizeof (ccb_t));
	if (ccb == (ccb_t *) 0) {
		no_mem();
		return -1;
	}
#if	VERBOSE
	printf( "aha_command( SCSI ID %d, LUN %d, c %x, b %D",
		sc->unit >> 2, sc->unit & 0x3, sc->cmd, sc->block ); 
	printf( " [%d] @%x:%x )\n",
		sc->buflen, sc->buffer );
#endif
	ccb->ccb_sw = 0;
	ccb->opcode = 0;			/* SCSI_INITIATOR*/
	ccb->target = (sc->unit & 0x1C) << 3;	/* SCSI ID */
	ccb->target |= sc->unit & 0x3;		/* LUN */
	if( (ccb->cmd_status[0] = sc->cmd) == ScmdWRITEXTENDED ) {
		ccb->target |= AHA_CCB_DATA_OUT;
	} else { /* READEXT, READCAP, INQUIRY */
		ccb->target |= AHA_CCB_DATA_IN;
	}
	ccb->cmd_status[1] = 0;
	ccb->cmd_status[2] = block;
	ccb->cmd_status[3] = block >>16;
	ccb->cmd_status[4] = block >> 8;
	ccb->cmd_status[5] = block;
	ccb->cmd_status[6] = 0;
	ccb->cmd_status[7] = count / 512;
	ccb->cmd_status[8] = count;
	ccb->cmd_status[9] = 0;
	ccb->cmdlen = 10;
	ccb->senselen = MAX_SENSEDATA;

	aha_l_to_p3( (long)sc->buflen, ccb->datalen );
	aha_l_to_p3( sc->buffer, ccb->dataptr );
	aha_l_to_p3( VTOP2( ccb, sds ), mailbox_out[0].adr );
#if	VERBOSE
	aha_ccb_print( ccb );
#endif
	mailbox_out[0].cmd = MBO_TO_START;
	aha_1out( AHA_DO_SCSI_START );
	while( ccb->opcode == 0 )
		sleep( ccb, CVBLKIO, IVBLKIO, SVBLKIO );
	
#if	VERBOSE
	printf( "done with status = %d, %d\n",
		ccb->hoststatus, ccb->targetstatus );
#endif
	if( (ccb->targetstatus == CHECK_TARGET_STATUS)
	   && (ccb->cmd_status[12] != SENSE_UNIT_ATTENTION) ) {
		printf( "aha: SCSI ID %d LUN %d. SCSI sense =",
		(sc->unit >> 2), sc->unit & 0x3 );
		for( i = 0; i < ccb->senselen; ++i )
			printf( " %x", ccb->cmd_status[10+i] );
		printf( "\n" );
	}
	i = ccb->hoststatus | ccb->targetstatus;
	kfree( ccb );
	return i;
}

ccb_t	*buildccb( sw )
register scsi_work_t *sw;
{
	register ccb_t *ccb;
	ccb = (ccb_t *)kalloc(sizeof(ccb_t));

#if	VERBOSE
	printf( "build: drv = %x, bno = %D  ",
		sw->sw_drv, sw->sw_bno );
#endif
	ccb->ccb_sw = sw;
	ccb->opcode = 0;			/* SCSI INITIATOR */
	ccb->target = (sw->sw_drv & 0x1C) << 3;	/* SCSI ID */
	ccb->target |= (sw->sw_drv) & 0x3;	/* LUN */
	if( sw->sw_bp->b_req == BREAD ) {
		ccb->target |= AHA_CCB_DATA_IN;
		ccb->cmd_status[0] = ScmdREADEXTENDED;
	} else {
		ccb->target |= AHA_CCB_DATA_OUT;
		ccb->cmd_status[0] = ScmdWRITEXTENDED;
	}
	ccb->cmd_status[2] = 0;
	ccb->cmd_status[3] = sw->sw_bno >>16;
	ccb->cmd_status[4] = sw->sw_bno >> 8;
	ccb->cmd_status[5] = sw->sw_bno;
	ccb->cmd_status[6] = 0;
	ccb->cmd_status[7] = sw->sw_bp->b_count / (512*256L);
	ccb->cmd_status[8] = sw->sw_bp->b_count / 512;
	ccb->cmd_status[9] = 0;
	ccb->cmdlen = 10;
	ccb->senselen = MAX_SENSEDATA;

	aha_l_to_p3( (long)sw->sw_bp->b_count, ccb->datalen );
	aha_l_to_p3( vtop(sw->sw_bp->b_faddr), ccb->dataptr );
	return ccb;
#if	0
/* start of ioctl code */
	if( f == SASI_CMD_IN )
		ccb->target |= AHA_CCB_DATA_IN;
	else if( f == SASI_CMD_OUT )
		ccb->target |= AHA_CCB_DATA_OUT;
	else
		ccb->target |=	 AHA_CCB_DATA_IN
				|AHA_CCB_DATA_OUT;
#endif
}

aha_start()
{
	register i, s, n = 0;
	scsi_work_t *sw;
	static char locked;

	s = sphi();
	if( locked ) {
		spl(s);
		return;
	}
	++locked;
	spl(s);

	while( (sw = scsi_work_queue->sw_actf) != NULL ) {
		for( i = MIN_MAILBOX; i < MAX_MAILBOX; ++i )
			if( mailbox_out[i].cmd == MBO_IS_FREE ) {
				register ccb_t *ccb;
				int s;

				++n;
				ccb = buildccb( sw );
#if	VERBOSE
				aha_ccb_print( ccb );
#endif
				aha_l_to_p3( VTOP2( ccb, sds ),
						mailbox_out[i].adr );
				mailbox_out[i].cmd = MBO_TO_START;
#if	VERBOSE
				printf( "MBO[%d] = %x:%x:%x:%x, ccb = %x ",
					i, mailbox_out[i].cmd,
					mailbox_out[i].adr[0],
					mailbox_out[i].adr[1],
					mailbox_out[i].adr[2], ccb );
	printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
#endif
				aha_1out( AHA_DO_SCSI_START );

				s = sphi();
				sw = scsi_work_queue->sw_actf = sw->sw_actf;
				if( sw == NULL )
					scsi_work_queue->sw_actl = NULL;
				spl(s);

				if( sw == NULL )
					break;
			}
		if( i == MAX_MAILBOX )
			break;
	}
	--locked;
	return n;
}

int	aha_completed()
{
	register i, n;

	for( n = 0, i = 0; i < MAX_MAILBOX; ++i )
		if( mailbox_in[i].cmd != MBI_IS_FREE ) {
#if	VERBOSE
			printf( "aha: mail[%d] = %x:%x:%x:%x\n",
				i, mailbox_in[i].cmd,
				mailbox_in[i].adr[0],
				mailbox_in[i].adr[1],
				mailbox_in[i].adr[2] );
#endif
			defer( aha_process,
				aha_p3_to_v( mailbox_in[i].adr ) );
			mailbox_in[i].cmd = MBI_IS_FREE;
			++n;
		}
	return n;
}

void	aha_intr()
{
	register i;

#if	VERBOSE
	printf( "aha_interrupt routine\n" );
#endif
	if( ((i = INB(aha_i_o_base+AHA_INTERRUPT)) & AHA_ANY_INTER) == 0 )
		printf( "aha: spurious interrupt %x\n", i );
#if	VERBOSE
	printf( "aha_interrupt: %x\n", i );
#endif
	switch( i & AHA_ALL_INTERRUPTS ) {
	case AHA_RESETED:
#if	VERBOSE
		printf( "aha: reseted\n" );
#endif
		break;
	case AHA_CMD_DONE:
#if	VERBOSE
		printf( "aha: adapter command completed\n" );
#endif
		break;
	case AHA_MBO_EMPTY:
#if	VERBOSE
		printf( "aha: MAILBOX emptied\n" );
#endif
		defer( aha_start, (char *)0 );
		break;
	case AHA_MBI_STORED:
#if	VERBOSE
		printf( "aha: MAILBOX in stored\n" );
#endif
		aha_completed();
		break;
	default:
		printf( "aha: multiple interrupts not yet handled\n" );
	}
	outb( aha_i_o_base+AHA_CONTROL, AHA_INTRRESET );
}

aha_ioctl()
{
	printf( "aha_ioctl: Not implemented\n" );
}

#if	VERBOSE
static	unsigned char vec[256];

static	aha_ports_are() {
	printf( "aha_ports_are: %x %x %x\n",
		INB(aha_i_o_base+0),
		INB(aha_i_o_base+1),
		INB(aha_i_o_base+2) );
}

static	aha_inquiry_is() {
	printf( "aha_inquiry:" );
	printf( "... aha_present = %d, ", aha_present() );
	printf( "%s\n", aha_last_msg() );
	aha_cmd_out( AHA_DO_INQUIRY );

	aha_get_data( &vec[0], 4 );
	printf( " board id '%c'", vec[0] );
	printf( ", options '%c'", vec[1] );
	printf( ", HW '%c'", vec[2] );
	printf( ", FW '%c'\n", vec[3] );
}

void	aha_setup_is() {
	register i;

	printf( "Setup and Data:\n" );
	aha_cmd_out( AHA_DO_GET_SETUP );
	aha_cmd_out( 16 );
	aha_get_data( &vec[0], 16 );
	printf( "  Data Xfer %s Sync (J1)\n", (vec[0]&1) ? "is" : "not" );
	printf( "  Parity %s Enabled (J1)\n", (vec[0]&2) ? "is" : "not" );
	switch( vec[1] ) {
	case AHA_SPEED_5_0_MB:
		printf( "  5.0 Mb/sec.\n" );	break;
	case AHA_SPEED_6_7_MB:
		printf( "  6.7 Mb/sec.\n" );	break;
	case AHA_SPEED_8_0_MB:
		printf( "  8.0 Mb/sec.\n" );	break;
	case AHA_SPEED_10_MB:
		printf( "  10 Mb/sec.\n" );	break;
	case AHA_SPEED_5_7_MB:
		printf( "  5.7 Mb/sec.\n" );	break;
	default:
		if( vec[1] & 0x80 )
			printf( "  Pulse Read %d, Write %d, Strobe off %d\n",
				50*(2+(vec[1]>>4)&0x7), 50*(2+(vec[1]&7)),
				vec[1] & 0x80 ? 150 : 100 );
	}
	printf( "  Bus Time ON %d, OFF %d\n", vec[2], vec[3] );
	printf( "  %d Mailboxes at %x|%x|%x\n", vec[4],
		vec[5], vec[6], vec[7] );
	for( i = 0; i < 8; ++i )
		if( vec[i+8] )
			printf( "  Target [%d] = Sync Neg %x\n", i, vec[i+8] );
}

static	aha_mailboxes_are( n, adr )
mailentry *adr;
{
	register i;

	printf( "addresses for mailbox is %x:%x\n", (long)adr );
	for( i = 0; i < n; ++i, ++adr )
		printf( "  mbo[%x] = %x %x|%x|%x\n",
			i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2] );
	for( i = 0; i < n; ++i, ++adr )
		printf( "  mbi[%x] = %x %x|%x|%x\n",
			i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2] );
}

void	aha_status()
{
	aha_ports_are();
	aha_inquiry_is();
	aha_devices_are();
	aha_setup_is();
	aha_mailboxes_are( MAX_MAILBOX, mailbox_out );
}

aha_ccb_print( ccb )
ccb_t	*ccb;
{
	register i;
	register unsigned char *cp;

	printf( "ccb @%x, sw @%x, bp @%x, flag %o\n",
		ccb, ccb->ccb_sw, ccb->ccb_sw->sw_bp,
		ccb->ccb_sw->sw_bp->b_flag );
	printf( "op %d, ", ccb->opcode );
	printf( "target ID=%d, ", (ccb->target>>5) & 0x7 );
	printf( "LUN=%d, ", (ccb->target & 0x7) );
	printf( "dir=%s%s\n",	(ccb->target&AHA_CCB_DATA_IN)?"IN":"",
				(ccb->target&AHA_CCB_DATA_OUT)?"OUT":"" );
	printf( "data len %x|%x|%x, adr %x|%x|%x\n",
		ccb->datalen[0],ccb->datalen[1],ccb->datalen[2],
		ccb->dataptr[0],ccb->dataptr[1],ccb->dataptr[2] );
	printf( "status host=%x, target=%x\n",
		ccb->hoststatus, ccb->targetstatus );
	printf( "cmddata[%d]:", ccb->cmdlen );
	for( i = 0, cp = ccb->cmd_status; i < ccb->cmdlen; ++i )
		printf( " %x", *cp++ );
	printf( "\nrequest sense[%d]:", ccb->senselen );
	for( i = 0; i < ccb->senselen; ++i )
		printf( " %x", *cp++ );
	if( i = cp[-1] ) {
		printf( "\n   + " );
		while( --i >= 0 )
			printf( " %x", *cp++ );
	}
	printf( "\n" );
}

#endif	/* VERBOSE */

0707070064030106201006440000030000030000011777770507310630200004600000015324/newbits/kernel/USRSRC/i8086/drv/al.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.8  91/08/01  13:47:28  bin
 * updated by hal to include rts/cts handshaking.
 * 
 * Revision 1.4  91/07/31  16:06:33  hal
 * Change include usage.  Use AL[01]_MAJOR.
 * 
 * Revision 1.2	91/02/21  11:21:28	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 * 
 * Revision 1.1	91/02/21  11:07:36	hal
 * Used in COH Release 3.0.0 - no COM3/COM4
 * 
 -lgl) */
/*
 * Driver for an IBM PC asyncronous
 * line, using interrupts. The interface
 * uses a Natty/WD 8250 chip.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <sys/clist.h>
#include <sys/ins8250.h>
#include <sys/sched.h>
#include <sys/al.h>
#include <sys/devices.h>

#define	minor_st(dev)	(dev & 0x3f)
#define	DEV_TTY		(alttab[minor_st(dev)])
#define ALPORT		(((COM_DDP *)(DEV_TTY.t_ddp))->port)

/*
 * This driver can be compiled to drive any possible
 * async port by appropriate definitions of:
 *	ALPORT[ab]	the io port address(es)
 *	ALNUM[ab]	com index number (0..3 for com[1..4])
 *	ALINT	the interrupt level
 *	ALNAME	the xxcon name
 *	ALMAJ	the major device number
 *      ALCNT	number of ports sharing the interrupt
 *
 *	NOTE:	if ALCNT is changed, alttab and alintr will need hacking
 * Common code for the different ports is handled by alx.c
 */

#ifdef ALCOM1			/* COM1_3 definitions */
#define ALPORTa	0x3F8		/* Base of com1 port */
#define ALPORTb	0x3E8		/* Base of com3 port */
#define ALNUMa	0		/* com1 has com number of 0 */
#define ALNUMb	2		/* com3 has com number of 2 */
#define ALINT	4		/* Interrupt level of com1_3 ports */
#define	ALNAME	a0con		/* CON name of com1_3 ports */
#define ALMAJ	AL0_MAJOR	/* Major number of com1_3 port */
#define ALCNT	A0CNT		/* Number of ports for this IRQ */
#define ALSPEEDa C1BAUD		/* Name of patchable variable for com1 speed */
#define ALSPEEDb C3BAUD		/* Name of patchable variable for com3 speed */
#endif

#ifdef ALCOM2			/* COM2_4 definitions */
#define ALPORTa	0x2F8		/* Base of com2 port */
#define ALPORTb	0x2E8		/* Base of com4 port */
#define ALNUMa	1		/* com2 has com number of 1 */
#define ALNUMb	3		/* com4 has com number of 3 */
#define ALINT	3		/* Interrupt level of com2_4 ports */
#define ALNAME	a1con		/* CON name of com2_4 ports */
#define ALMAJ	AL1_MAJOR	/* Major number of com2_4 ports */
#define ALCNT	A1CNT		/* Number of ports for this IRQ */
#define ALSPEEDa C2BAUD		/* Name of patchable variable for com2 speed */
#define ALSPEEDb C4BAUD		/* Name of patchable variable for com4 speed */
#endif

/*
 * Functions.
 */
int	alxopen();
int	alxclose();
int	alxioctl();
int	alxtimer();
int	alxparam();
int	alxcycle();
int	alxstart();
int	alxbreak();

int	alintr();
int	alopen();
int	alclose();
int	alread();
int	alwrite();
int	alioctl();
int	alload();
int	alunload();
int	alpoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON ALNAME ={
	DFCHR|DFPOL,			/* Flags */
	ALMAJ,				/* Major index */
	alopen,				/* Open */
	alclose,			/* Close */
	nulldev,			/* Block */
	alread,				/* Read */
	alwrite,			/* Write */
	alioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	alxtimer,			/* Timeout */
	alload,				/* Load */
	alunload,			/* Unload */
	alpoll				/* Poll */
};

/*
 * Terminal structures.
 */
static COM_DDP	* ddp;
static TTY	* alttab;
static TTY	* irqtty;  /* point to alttab entry which is IRQ-enabled */

/*
 * to change default speeds - patch kernel variables C1BAUD..C4BAUD
 *   new value should be one of B0..B9600 in /usr/include/sgtty.h
 */
int ALSPEEDa = B9600;
int ALSPEEDb = B9600;

/*
 * to enable com[34], patch here
 *	A0CNT should be 2 if you want com3, 1 otherwise
 *	A1CNT should be 2 if you want com4, 1 otherwise
 */
int ALCNT = 2;

static
alload()
{
	register int s;
	static int init;
	extern int albaud[];
	int port, i;

	if (init == 0
	  && (alttab = (TTY *)kalloc(ALCNT * sizeof(TTY)))
	  && (ddp = (COM_DDP *)kalloc(ALCNT * sizeof(COM_DDP)))) {
		kclear(alttab, ALCNT*sizeof(TTY));
		kclear(ddp, ALCNT*sizeof(COM_DDP));
		s = sphi();
		++init;

		alttab[0].t_dispeed = alttab[0].t_dospeed = ALSPEEDa;
		alttab[0].t_ddp = (char *)&ddp[0];
		tp_table[ALNUMa] = alttab; /* set TTY pointers for polling */
		ddp[0].port = ALPORTa;
		ddp[0].com_num = ALNUMa;

		if (ALCNT > 1) {
			alttab[1].t_dispeed = alttab[1].t_dospeed = ALSPEEDb;
			alttab[1].t_ddp = (char *)&ddp[1];
			tp_table[ALNUMb] = alttab+1;
			ddp[1].port = ALPORTb;
			ddp[1].com_num = ALNUMb;
		}

		for (i = 0;  i < ALCNT; i++) {
			int speed = alttab[i].t_dospeed;

			/* port = base I/O address */
			port = ((COM_DDP *)(alttab[i].t_ddp))->port;
			outb(port+IER, 0);	/* disable port interrupts */
			if (inb(port+IER) == 0) {
				outb(port+MCR, 0);  /* hangup port */
				outb(port+LCR, LC_DLAB);
				outb(port+DLL, albaud[speed]);
				outb(port+DLH, albaud[speed] >> 8);
				outb(port+LCR, LC_CS8);
			}
			alttab[i].t_start = alxstart;
			alttab[i].t_param = alxparam;
			alttab[i].t_cs_sel= cs_sel();
		}

		setivec(ALINT, alintr);     /* set interrupt vector */
		spl(s);
	}
}

static
alunload()
{
	int port, i;

	for (i = 0;  i < ALCNT; i++) {
		port = ((COM_DDP *)(alttab[i].t_ddp))->port;
		outb(port+IER, 0);	/* disable port interrupts */
		outb(port+MCR, 0);	/* hangup port */
		timeout(alttab[i].t_rawtim, 0, NULL, 0);/* cancel timer */
	}
	clrivec(ALINT);			/* release interrupt vector */
	kfree(alttab);
	kfree(ddp);
}

static
alopen(dev, mode)
dev_t	dev;
int	mode;
{
	if (minor_st(dev) < ALCNT) {
		alload();
		alxcycle(&DEV_TTY);
		alxopen(dev, mode, &DEV_TTY, &irqtty);
	} else
		u.u_error = ENXIO;
}

static
alclose(dev, mode)
dev_t	dev;
int	mode;
{
	register int s;

	if (--DEV_TTY.t_open == 0) {	/* Last open */
		s = sphi();
		alxclose(dev, mode, &DEV_TTY);
		spl(s);
	}
}

static
alread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ttread(&DEV_TTY, iop);
}

static
alwrite(dev, iop)
dev_t	dev;
register IO	*iop;
{
	register int c;

	/*
	 * Treat user writes through tty driver.
	 */
	if (iop->io_seg != IOSYS) {
		ttwrite(&DEV_TTY, iop);
		return;
	}

	/*
	 * Treat kernel writes by blocking on transmit buffer.
	 */
	while ((c = iogetc(iop)) >= 0) {
		/*
		 * Wait until transmit buffer is empty.
		 * Check twice to prevent critical race with interrupt handler.
		 */
		for (;;) {
			if (inb(ALPORT+LSR) & LS_TxRDY)
				if (inb(ALPORT+LSR) & LS_TxRDY)
					break;
		}

		/*
		 * Output the next character.
		 */
		outb(ALPORT+DREG, c);
	}
}

static
alioctl(dev, com, vec)
dev_t	dev;
struct sgttyb *vec;
{
	alxioctl(dev, com, vec, &DEV_TTY);
}

static
alpoll(dev, ev, msec)
dev_t dev;
int ev;
int msec;
{
	return ttpoll(&DEV_TTY, ev, msec);
}

static
alintr()
{
	alxintr(irqtty);
}
0707070064030105311006440000030000030000011777770507310630400004700000044563/newbits/kernel/USRSRC/i8086/drv/alx.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.12  91/08/06  10:32:23  bin
 * 2nd rts/cts version form hal
 * 
 * Revision 1.7  91/08/02  07:59:27  hal
 * Raw input silo uses last slot for byte count.
 * Modem control now gives RTS/CTS flow control:
 * 	CTS is checked 10x/sec (probably not often enough).
 * 	On Rx_INT, check T_ISTOP and rawin silo levels; drop RTS if need to.
 * 
 * Revision 1.6	91/04/03  18:55:07	root
 * alxclose():  do closing state machine BEFORE dropping control lines.
 * alxioctl():  save and restore interrupt enable register.
 * alxopen():   wait for pending last close (fixes SLOW port bug).
 * This version needs al.h 1.3 or later.
 *
 * Revision 1.5	91/04/02  17:53:37	root
 * save MSR delta status; add MS_INTR handling; use al.h 1.2
 *
 * Revision 1.4	91/02/22  09:21:17	root
 * alxintr():  replace repeated use of ALPORT macro by local variable
 *
 * Revision 1.3	91/02/21  14:58:16	root
 * Fix unconditional "hupcl" bug in 3.1.0 version.
 *
 * Revision 1.2	91/02/21  11:21:40	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 *
 * Revision 1.1	91/02/21  11:08:31	hal
 * Used in COH Release 3.0.0 - no COM3/COM4
 *
 -lgl) */
/*
 * Shared parts of IBM async port drivers.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/al.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <sys/timeout.h>
#include <sys/clist.h>
#include <sys/ins8250.h>
#include <sys/sched.h>

#define ALPORT	(((COM_DDP *)(tp->t_ddp))->port)
#define AL_TIM	(((COM_DDP *)(tp->t_ddp))->tim)
#define AL_NUM	(((COM_DDP *)(tp->t_ddp))->com_num)
#define AL_MSR_DELTAS	(((COM_DDP *)(tp->t_ddp))->msr_deltas)
#define AL_H_CLOSE	(((COM_DDP *)(tp->t_ddp))->h_close)

#define DTRTMOUT  3	/* DTR timeout interval in seconds for close */
#define	IENABLE	(IE_RxI+IE_TxI+IE_LSI+IE_MSI)

/*
 * For rawin silo (see ktty.h), use last element of si_buf to count the number
 * of characters in the silo.
 */
#define SILO_CHAR_COUNT	si_buf[SI_BUFSIZ-1]
#define SILO_HIGH_MARK	(SI_BUFSIZ-SI_BUFSIZ/4)
#define MAX_SILO_INDEX	(SI_BUFSIZ-2)
#define MAX_SILO_CHARS	(SI_BUFSIZ-1)

int	al_sg_set = 0;
int	al_sg_clr = 0;
static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */

/*
 * functions herein
 */
int	alxopen();
int	alxclose();
int	alxtimer();
int	alxioctl();
int	alxparam();
int	alxcycle();
int	alxstart();
int	alxbreak();
int	alxintr();
static	int alxclk();
static	set_poll_rate();

/*
 * Baud rate table and polling rate table.
 * Indexed by ioctl bit rates.
 */
int albaud[] ={
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	alp_rate[] is tied to albaud[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int alp_rate[] ={			/* baud/6 or zero */
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	the following is for debug only
 */
#if 0
#define CDUMP(text)	cdump(text);

cdump(message)
char *message;
{
	int i, b;

	for (i = 0; i < NUM_AL_PORTS; i++) {
		b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
		printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
	}
	printf("poll=%d ", poll_rate);
	printf("%s\n", message);
}
#else
#define CDUMP(text)
#endif

/*
 * alxopen()
 */
alxopen(dev, mode, tp, irqtty)
dev_t	dev;
int	mode;
register TTY	*tp, **irqtty;
{
	register int	s;
	register int	b;
	register int	minor_h;  /* minor device number including high bit */
	unsigned char	msr;

	minor_h = minor(dev);     /* complete minor number */

	b = ALPORT;

	if (inb(b+IER) & ~IENABLE) { /* chip not found */
		u.u_error = ENXIO;
		return;
	}

	if ((tp->t_flags & T_EXCL) && !super()) {
		u.u_error = ENODEV;
		return;
	}

	if (drvl[major(dev)].d_time != 0) {	/* Modem settling */
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Can't open a polled port if another driver is using polling.
	 */
	if (dev & CPOLL && poll_owner & ~ POLL_AL) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * exclusion conditions:
	 *	can't have same port polled and IRQ at once
	 *	can't have both com[13] or both com[24] IRQ at once
	 */
	if (dev & CPOLL) {
		if (com_usage[AL_NUM] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	} else {
		if (com_usage[AL_NUM] == COM_POLLED
		   || com_usage[AL_NUM ^ 2] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	}

	if (tp->t_open == 0) {        /* not already open */
		/*
		 * Wait for pending last close (if any) to finish.
		 */
		while (AL_H_CLOSE) {
   	  		sleep((char *)(&AL_H_CLOSE), CVTTOUT, IVTTOUT,
				SVTTOUT);
		}
		s = sphi();
		/*
		 * Raise basic modem control lines even if modem
		 * control hasn't been specified.
		 * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
		 * since we can't have two UART's on same IRQ with MC_OUT2 on
		 */
		if (dev & CPOLL) {
			outb(b+MCR, MC_RTS|MC_DTR);
		} else {
			*irqtty = tp_table[AL_NUM];
			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
		}

		outb(b+IER, IENABLE);        /* enable interrupts */

		if ((minor_h & NMODC) == 0) {	/* want modem control? */
			tp->t_flags |= T_MODC | T_HOPEN | T_STOP;
			while (1) {	/* wait for carrier */
				msr = inb(b+MSR);
				AL_MSR_DELTAS |= msr;
				if (msr & MS_RLSD)
					break;
	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
					SVTTOUT);	/* wait for carrier */
		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
					outb(b+MCR, inb(b+MCR)&MC_OUT2);
	                    		/*
					 * make sure port is hungup
					 * disable all ints except for TxI
					 */
			    		outb(b+IER, IE_TxI);
					u.u_error = EINTR;
					spl(s);
					return;
				}
			}
			tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
			if (msr & MS_CTS)
				tp->t_flags &= ~T_STOP;
		} else {
			tp->t_flags &= ~T_MODC;		/* no modem control */
		}
	        tp->t_flags |= T_CARR;			/* carrier on */
		ttopen(tp);				/* stty inits */

		/*
		 * Allow custom modification of defaults.
		 */
		tp->t_sgttyb.sg_flags |=  al_sg_set;
		tp->t_sgttyb.sg_flags &= ~al_sg_clr;
		alxparam(tp);
		spl(s);
	} else {			        /* already open */
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
	   	    if ((tp->t_flags & T_MODC)==0) { /* already not modem control? */
			u.u_error = ENODEV;     /* yes, don't allow open */
			return;
		    }
		} else {		         /* don't want modem control */
			if (tp->t_flags & T_MODC) { /* already modem control? */
				u.u_error = ENODEV; /* yes, don't allow open */
				return;
			}
		}
	}
	tp->t_open++;
	ttsetgrp(tp, dev);

	/*
	 * now that we've successfully opened, designate port as
	 * polled or interrupt driven to avoid future conflicts
	 */
	if (dev & CPOLL) {
		com_usage[AL_NUM] = COM_POLLED;
		set_poll_rate();
	} else {				/* irq-driven port */
		com_usage[AL_NUM] = COM_IRQ;
	}

	CDUMP((dev&CPOLL)?"open polled":"open irq")
}

/*
 * alxclose()
 *
 *	Called at high priority on last close for the device.
 */
alxclose(dev, mode, tp)
dev_t	dev;
int	mode;
TTY	*tp;
{
	register unsigned holdflags;
	register int b;
	int state, maj;
	int s;

	/*
	 * Called at high priority by alclose after al_buff is drained
	 */
	holdflags = tp->t_flags;	/* save flags */
	AL_H_CLOSE = 1;			/* disallow reopen til done closing */
	ttclose(tp);			/* clear flags */
	b = ALPORT;
	/*
	 * ttclose() only emptied the output queue tp->t_oq;
	 * now wait for the silo tp->rawout to empty
	 * and allow a delay for the UART on-chip xmit buffer to empty
	 * state 2: waiting for silo to empty
	 * state 1: stalling so UART can empty xmit buffer
	 * state 0: done!  ok to shut off IRQ for this chip by clearing MC_OUT2
	 */
	state = 2;
	while (state) {
		timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
		sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
			state--;
	}

	/*
	 * If not hanging in open
	 */
	if ((holdflags & T_HOPEN) == 0) {
		/*
		 * Disable all ints except TxI
		 */
		outb(b+IER, IE_TxI);
	} else {
		/*
		 * Flags for first open
		 */
		tp->t_flags = T_MODC | T_HOPEN;
	}

	/*
	 * If hupcls
	 */
	if (holdflags & T_HPCL) {
		/*
		 * Hangup port
		 */
		s = sphi();
		outb(b+MCR, inb(b+MCR)&MC_OUT2);
		spl(s);

		/*
		 * Hold dtr low for timeout
		 */
		maj = major(dev);
		drvl[maj].d_time = 1;
		sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
		drvl[maj].d_time = 0;
	}
	s = sphi();
	outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
	spl(s);
	com_usage[AL_NUM] = COM_UNUSED;
	set_poll_rate();
	AL_H_CLOSE = 0;		/* allow reopen - done closing */
	wakeup((char *)&AL_H_CLOSE);
	CDUMP("closed")
}

/*
 * Common c_timer routine for async ports.
 */
alxtimer(dev)
dev_t dev;
{
	if (++drvl[major(dev)].d_time > DTRTMOUT)
		wakeup((char *)&drvl[major(dev)].d_time);
}


/*
 * Common c_ioctl routine for async ports.
 */
alxioctl(dev, com, vec, tp)
dev_t	dev;
struct sgttyb *vec;
register TTY 	*tp;
{
	register int	s, b;
	int stat1, stat2;
	unsigned char	msr;
	unsigned char ier_save;

	s = sphi();
	b = ALPORT;
	ier_save=inb(b+IER);
	stat1 = inb(b+MCR);		/* get current MCR register status */
	stat2 = inb(b+LCR);		/* get current LCR register status */

	switch(com) {
	case TIOCSBRK:			/* set BREAK */
		outb(b+LCR, stat2|LC_SBRK);
		break;
	case TIOCCBRK:			/* clear BREAK */
		outb(b+LCR, stat2 & ~LC_SBRK);
		break;
	case TIOCSDTR:			/* set DTR */
		outb(b+MCR, stat1|MC_DTR);
		break;
	case TIOCCDTR:			/* clear DTR */
		outb(b+MCR, stat1 & ~MC_DTR);
		break;
	case TIOCSRTS:			/* set RTS */
		outb(b+MCR, stat1|MC_RTS);
		break;
	case TIOCCRTS:			/* clear RTS */
		outb(b+MCR, stat1 & ~MC_RTS);
		break;
	case TIOCRSPEED:		/* set "raw" I/O speed divisor */
		outb(b+LCR, stat2|LC_DLAB);  /* set speed latch bit */
		outb(b+DLL, (unsigned) vec);
		outb(b+DLH, (unsigned) vec >> 8);
		outb(b+LCR, stat2);       /* reset latch bit */
		break;
	case TIOCWORDL:		/* set word length and stop bits */
		outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
		break;
	case TIOCRMSR:		/* get CTS/DSR/RI/RLSD (MSR) */
		msr = inb(b+MSR);
		AL_MSR_DELTAS |= msr;
		stat1 = msr >> 4;
		kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
		break;
	default:
		ttioctl(tp, com, vec);
	}
	outb(b+IER, ier_save);
	spl(s);
}

alxparam(tp)
TTY	*tp;
{
	register int	b;
	register int	baud;
	int s;

	b = ALPORT;

	/*
	 * error if input speed not the same as output speed
	 */
	if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
		u.u_error = ENODEV;
		return;
 	}

	if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
		if (tp->t_flags & T_MODC) {  /* modem control? */
			tp->t_flags &= ~T_CARR;  /* indicate no carrier */
			s = sphi();
			outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
			spl(s);
		}
	}

	if (baud) {
		unsigned char ier_save;

		s=sphi();
		ier_save=inb(b+IER);	/* some chips need this */
		outb(b+LCR, LC_DLAB);
		outb(b+DLL, baud);
		outb(b+DLH, baud >> 8);
		switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
		case EVENP:
			outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN);
			break;

		case ODDP:
			outb(b+LCR, LC_CS7 + LC_PARENB);
			break;

		default:
			outb(b+LCR, LC_CS8);
			break;
		}
		outb(b+IER, ier_save);
		spl(s);
	}
	set_poll_rate();
}

/*
 * Middle level processor.
 *
 *	Invoked 10 times per second.
 *	Checks modem status for loss of carrier.
 *	Tranfers rawin buffer [from intr level] to canonical input queue.
 *	Transfers output queue to rawout buffer [for intr level].
 */
alxcycle(tp)
register TTY * tp;
{
	register int b;
	register int n;
	unsigned char msr, mcr;
	int s;

	/*
	 * Check modem status every ten clock ticks.
	 *
	 * Modem status interrupts were not enabled due to 8250 hardware bug.
	 * Enabling modem status and receive interrupts may cause lockup
	 * on older parts.
	 *
	 * Also check if input silo is nearly full in case we need RTS
	 * flow control.
	 */
	if (tp->t_flags & T_MODC) {

		/*
		 * Get status
		 */
		msr = inb(ALPORT+MSR);
		AL_MSR_DELTAS |= msr;

		/*
		 * Carrier changed.
		 */
		if (AL_MSR_DELTAS & MS_DRLSD) {
			AL_MSR_DELTAS &= ~MS_DRLSD;
			/*
			 * wakeup open
			 */
			if (tp->t_open == 0) {
				wakeup((char *)(&tp->t_open));
			}

			/*
			 * carrier off?
			 */
			else if ((msr & MS_RLSD) == 0) {
				/*
				 * clear carrier flag; send hangup signal
				 */
				s = sphi();
				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
				tp->t_rawin.SILO_CHAR_COUNT = 0;
				spl(s);
				tthup(tp);
			}
		}

		/*
		 * CTS changed.
		 */
		if (AL_MSR_DELTAS & MS_DCTS) {
			AL_MSR_DELTAS &= ~MS_DCTS;
			if (msr & MS_CTS)
				tp->t_flags &= ~T_STOP;
			else
				tp->t_flags |= T_STOP;
		}

		/*
		 * If input silo not nearly full, assert RTS.
		 */
		if (tp->t_rawin.SILO_CHAR_COUNT <= SILO_HIGH_MARK) {
			mcr = inb(ALPORT+MCR);
			if ((mcr & MC_RTS) == 0) {
printf("%x RTS ON\n", ALPORT);
				outb(ALPORT+MCR, mcr | MC_RTS);
			}
		}
	}

	/*
	 * Empty raw input buffer.
	 * If modem control enabled and tt input queue is at high limit
	 * (e.g., tp->t_iq.cq_cc >= IHILIM), don't copy from rawin silo
	 * to tt input queue.
	 */
	if (!(tp->t_flags & T_MODC) || !(tp->t_flags & T_ISTOP))
		while (tp->t_rawin.SILO_CHAR_COUNT > 0) {
			ttin(tp, tp->t_rawin.si_buf[tp->t_rawin.si_ox]);
			if (tp->t_rawin.si_ox < MAX_SILO_INDEX)
				tp->t_rawin.si_ox++;
			else
				tp->t_rawin.si_ox = 0;
			tp->t_rawin.SILO_CHAR_COUNT--;
		}

	/*
	 * Calculate free output slot count.
	 */
	n  = sizeof(tp->t_rawout.si_buf) - 1;
	n += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	n %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ((--n >= 0) && ((b = ttout(tp)) >= 0)) {
		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = b;
		if (tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1)
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, wake sleeping processes, etc.
	 */
	ttstart(tp);

	/*
	 * Schedule next cycle.
	 */
	timeout(&tp->t_rawtim, HZ/10, alxcycle, tp);
}

/*
 * Serial Transmit Start Routine.
 */
alxstart(tp)
register TTY * tp;
{
	register int b;
	register int s;
	extern alxbreak();

	/*
	 * Read line status register AFTER disabling interrupts.
	 */
	s = sphi();
	b = inb(ALPORT+LSR);

	/*
	 * Process break indication.
	 * NOTE: Break indication cleared when line status register was read.
	 */
	if (b & LS_BREAK)
		defer(alxbreak, tp);

	/*
	 * Transmitter is empty, output data is pending.
	 */
	if ((b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox)) {
		outb(	ALPORT+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
		if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
			tp->t_rawout.si_ox = 0;
	}
	spl(s);
}

/*
 * Serial Received Break Handler.
 */
alxbreak(tp)
TTY * tp;
{
	ttsignal(tp, SIGINT);
}

/*
 * Serial Interrupt Handler.
 */
alxintr(tp)
register TTY * tp;
{
	register int	b;
	int port = ALPORT;
	unsigned char mcr;

rescan:
	switch (inb(port+IIR)) {

	case LS_INTR:
		if (inb(port+LSR) & LS_BREAK)
			defer(alxbreak, tp);
		goto rescan;

	case Rx_INTR:
		b = inb(port+DREG);
		if (tp->t_open == 0)
			goto rescan;
		/*
		 * Must recognize XOFF quickly to avoid transmit overrun.
		 * Recognize XON here as well to avoid race conditions.
		 */
		if ((tp->t_sgttyb.sg_flags & RAWIN) == 0) {
			/*
			 * XOFF.
			 */
			if (tp->t_tchars.t_stopc == (b & 0177)) {
				tp->t_flags |= T_STOP;
				goto rescan;
			}

			/*
			 * XON.
			 */
			if (tp->t_tchars.t_startc == (b & 0177)) {
				tp->t_flags &= ~T_STOP;
				goto rescan;
			}
		}

		/*
		 * Save char in raw input buffer.
		 */
		if (tp->t_rawin.SILO_CHAR_COUNT < MAX_SILO_CHARS) {
			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = b;
			if (tp->t_rawin.si_ix < MAX_SILO_INDEX)
				tp->t_rawin.si_ix++;
			else
				tp->t_rawin.si_ix = 0;
			tp->t_rawin.SILO_CHAR_COUNT++;
		}
		if (tp->t_flags & T_MODC)
			if ((tp->t_flags & T_ISTOP)
			|| (tp->t_rawin.SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
				mcr = inb(port+MCR);
				if (mcr & MC_RTS) {
					outb(port+MCR, mcr & ~MC_RTS);
printf("%x RTS OFF\n", port);
				}
			}
		goto rescan;

	case Tx_INTR:
		/*
		 * Do nothing if no raw output data or output is stopped.
		 */
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox) {
			goto rescan;
		}
		if (tp->t_flags & T_STOP)
			goto rescan;

		/*
		 * Transmit next char in raw output buffer.
		 */
		outb(port+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);

		/*
		 * Adjust raw output buffer output index.
		 */
		if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
			tp->t_rawout.si_ox = 0;

		/*
		 * Try to fill buffer if now empty.
		 */
		if (tp->t_rawout.si_ox == tp->t_rawout.si_ix) {
			defer(alxcycle, tp);
		}
		goto rescan;

	case MS_INTR:
		AL_MSR_DELTAS |= inb(port+MSR);
		defer(alxcycle, tp);
		goto rescan;
	}
}

/*
 * alxclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int alxclk()
{
	static int count;
	int i;

	for (i = 0; i < NUM_AL_PORTS;  i++)
		if (com_usage[i] == COM_POLLED)
			alxintr(tp_table[i]);
	count++;
	if (count >= poll_divisor)
		count = 0;
	return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_AL)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
		if (com_usage[port_num] == COM_POLLED) {
			port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
			if (max_rate < port_rate)
				max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in alxclk() */
		altclk_out();		/* stop previous polling */
		poll_owner &= ~ POLL_AL;
		if (max_rate) {	/* resume polling at new rate if needed */
			poll_owner |= POLL_AL;
			altclk_in(poll_rate, alxclk);
		}
		CDUMP("new rate")
	}
}
0707070064030050431006440000030000030000011777770507310631100004600000053720/newbits/kernel/USRSRC/i8086/drv/at.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.5  91/05/22  15:06:59  hal
 * Don't force 8's bit of control byte.
 * 
 * Revision 1.4	91/03/14  14:22:32	hal
 *
 -lgl) */
/*
 * This is a driver for the
 * hard disk on the AT.
 *
 * Reads drive characteristics from ROM (thru interrupt vector 0x41 and 0x46).
 * Reads partition information from disk.
 */
#include	<sys/coherent.h>
#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/devices.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>

extern	saddr_t	sds;		/* System Data Selector */

/*
 * Configurable parameters
 */
#define	HDIRQ	14			/* Level 14 */
#define	HDBASE	0x01F0			/* Port base */
#define NDRIVE	2			/* only two drives supported */
#define	SOFTLIM	6			/*  (7) num of retrys before diag */
#define	HARDLIM	8			/* number of retrys before fail */
#define	BADLIM	100			/* num to stop recov if flagged bad */

#define	BIT(n)		(1 << (n))

#define	CMOSA	0x70			/* write cmos address to this port */
#define	CMOSD	0x71			/* read cmos data through this port */

#ifndef	ATCACHE
#	if VERBOSE > 0
#		define	ATCACHE	2	/* local cache size in blocks */
#	else
#		define	ATCACHE 0	/* no cache for small code */
#	endif
#endif

/*
 * Driver configuration.
 */
void	atload();
void	atunload();
void	atopen();
void	atread();
void	atwrite();
int	atioctl();
void	atwatch();
void	atblock();
int	nulldev();
int	nonedev();

CON	atcon	= {
	DFBLK|DFCHR,			/* Flags */
	AT_MAJOR,			/* Major index */
	atopen,				/* Open */
	nulldev,			/* Close */
	atblock,			/* Block */
	atread,				/* Read */
	atwrite,			/* Write */
	atioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	atwatch,			/* Timeout */
	atload,				/* Load */
	atunload			/* Unload */
};

/*
 * Forward Referenced Functions.
 */
void	atreset();
int	atdequeue();
void	atstart();
void	atintr();
void	atdefer();
int	aterror();
void	atrecov();
void	atdone();

/*
 * I/O Port Addresses
 */
#define	DATA_REG	(HDBASE+0)	/* data (r/w) */
#define	AUX_REG		(HDBASE+1)	/* error(r), write precomp cyl/4 (w) */
#define	NSEC_REG	(HDBASE+2)	/* sector count (r/w) */
#define	SEC_REG		(HDBASE+3)	/* sector number (r/w) */
#define	LCYL_REG	(HDBASE+4)	/* low cylinder (r/w) */
#define	HCYL_REG	(HDBASE+5)	/* high cylinder (r/w) */
#define	HDRV_REG	(HDBASE+6)	/* drive/head (r/w) (D<<4)+(1<<H) */
#define	CSR_REG		(HDBASE+7)	/* status (r), command (w) */
#define	HF_REG		0x3F6

/*
 * Error from AUX_REG (r)
 */
#define	DAM_ERR		BIT(0)		/* data address mark not found */
#define	TR0_ERR		BIT(1)		/* track 000 not found */
#define	ABT_ERR		BIT(2)		/* aborted command */
#define	ID_ERR		BIT(4)		/* id not found */
#define	ECC_ERR		BIT(6)		/* data ecc error */
#define	BAD_ERR		BIT(7)		/* bad block detect */

/*
 * Status from CSR_REG (r)
 */
#define	ERR_ST		BIT(0)		/* error occurred */
#define	INDEX_ST	BIT(1)		/* index pulse */
#define	SOFT_ST		BIT(2)		/* soft (corrected) ECC error */
#define	DRQ_ST		BIT(3)		/* data request */
#define	SKC_ST		BIT(4)		/* seek complete */
#define	WFLT_ST		BIT(5)		/* improper drive operation */
#define	RDY_ST		BIT(6)		/* drive is ready */
#define	BSY_ST		BIT(7)		/* controller is busy */


/*
 * Commands to CSR_REG (w)
 */
#define	RESTORE(rate)	(0x10+(rate))	/* X */
#define	SEEK(rate)	(0x70+(rate))	/* X */
#define	READ_CMD	(0x20)		/* X */
#define	WRITE_CMD	(0x30)		/* X */
#define	FORMAT_CMD	(0x50)		/* X */
#define	VERIFY_CMD	(0x40)		/* X */
#define	DIAGNOSE_CMD	(0x90)		/* X */
#define	SETPARM_CMD	(0x91)		/* X */

/*
 * Device States.
 */
#define	SIDLE	0			/* controller idle */
#define	SRETRY	1			/* seeking */
#define	SREAD	2			/* reading */
#define	SWRITE	3			/* writing */

/*
 * Drive Parameters - copied from ROM.
 * If patched, use the given values instead of reading from the ROM.
 * NOTE: Exactly duplicates hdparm_s struct.
 */
struct dparm_s {
	unsigned short	d_ncyl;		/* number of cylinders */
	unsigned char	d_nhead;	/* number of heads */
	unsigned short	d_rwcc;		/* reduced write current cyl */
	unsigned short	d_wpcc;		/* write pre-compensation cyl */
	unsigned char	d_eccl;		/* max ecc data length */
	unsigned char	d_ctrl;		/* control byte */
	unsigned char	d_fill2[3];
	unsigned short	d_landc;	/* landing zone cylinder */
	unsigned char	d_nspt;		/* number of sectors per track */
	unsigned char	d_fill3;

}	atparm[ NDRIVE ] = {
	0				/* Initialized to allow patching */
};

/*
 * Partition Parameters - copied from disk.
 *
 *	There are NDRIVE * NPARTN positions for the user partitions,
 *	plus NDRIVE additional partitions to span each drive.
 *
 *	Aligning partitions on cylinder boundaries:
 *	Optimal partition size: 2 * 3 * 4 * 5 * 7 * 17 = 14280 blocks
 *	Acceptable partition size:  3 * 4 * 5 * 7 * 17 =  7140 blocks
 */
static
struct fdisk_s pparm[NDRIVE*NPARTN + NDRIVE];

/*
 * Per disk controller data.
 * Only one controller; no more, no less.
 */
static
struct	at	{
	BUF		*at_actf;	/* Link to first */
	BUF		*at_actl;	/* Link to last */
	faddr_t		at_faddr;	/* Source/Dest virtual address */
	daddr_t		at_bno;		/* Block # on disk */
	unsigned	at_nsec;	/* # of sectors on current transfer */
	unsigned	at_drv;
	unsigned	at_head;
	unsigned	at_cyl;
	unsigned	at_sec;
	unsigned	at_partn;
	unsigned char	at_dtype[ NDRIVE ];	/* drive type, 0 if unused */
	unsigned char	at_tries;
	unsigned char	at_state;
	unsigned char	at_caching;		/* caching in progress */
#if	ATCACHE > 0
	unsigned char	at_cdrv[ ATCACHE ];	/* cached drive */
	daddr_t		at_cbno[ ATCACHE ];	/* cached block number */
	unsigned char *	at_cbuf[ ATCACHE ];	/* cached block */
#endif
	unsigned	at_bad_drv;
	unsigned	at_bad_head;
	unsigned	at_bad_cyl;
}	at;

static BUF	dbuf;			/* For raw I/O */

int	ATBSYW = 50;			/* patchable */
static char timeout_msg[] = "at%d: TO\n";

/**
 *
 * void
 * atload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void
atload()
{
	register int u;
	register struct dparm_s * dp;
	struct { unsigned off, seg; } p;

	/*
	 * Obtain Drive Types.
	 *
	 *	High nibble of CMOS 0x12 is drive 0's type.
	 *	Low  nibble of CMOS 0x12 is drive 1's type.
	 */
	outb( CMOSA, 0x12 );
	/* delay */
	u = inb(CMOSD);
	at.at_dtype[0] = u >> 4;
	at.at_dtype[1] = u & 15;

	/*
	 * Interrupt Vector 0x41 points to Drive 0 Characteristics.
	 */
	pkcopy( (paddr_t) (0x41*4), &p, sizeof p );

	/*
	 * Obtain Drive Characteristics.
	 */
	for ( u = 0, dp = &atparm[0]; u < NDRIVE; ++dp, ++u ) {

		if ( dp->d_ncyl == 0 ) {
			/* Not patched, use the ROM drive table values. */
			pkcopy( (paddr_t) (p.seg << 4L) + p.off,
				dp, sizeof(*dp) );
		}
		else {
			/*
			 * Avoid incomplete patching.
			 */
			if (at.at_dtype[u] == 0)
				at.at_dtype[u] = 1;
			if ( dp->d_nspt == 0 )
				dp->d_nspt = 17;
#if FORCE_CTRL_8
			if ( dp->d_nhead > 8 )
				dp->d_ctrl |= 8;
#endif

#if VERBOSE > 0
			printf(
	"at%d: ncyl=%d nhead=%d wpcc=%d eccl=%d ctrl=%d landc=%d nspt=%d\n",
				u,
				dp->d_ncyl,
				dp->d_nhead,
				dp->d_wpcc,
				dp->d_eccl,
				dp->d_ctrl,
				dp->d_landc,
				dp->d_nspt );
#endif
		}

		/*
		 * Interrupt Vector 0x46 points to Drive 1 Characteristics.
		 */
		pkcopy( (paddr_t) (0x46*4), &p, sizeof p );
	}

	/*
	 * Initialize Drive Size.
	 */
	for ( u = 0, dp = &atparm[0]; u < NDRIVE; ++dp, ++u ) {

		if ( at.at_dtype[u] == 0 )
			continue;

		pparm[NDRIVE*NPARTN + u].p_size =
			(long) dp->d_ncyl * dp->d_nhead * dp->d_nspt;
	}

	/*
	 * Initialize Drive Controller.
	 */
	atreset();

	setivec( HDIRQ, atintr );

#if ATCACHE > 0
	at.at_cdrv[0] = -1;
	at.at_cbuf[0] = kalloc( BSIZE );
#endif

#if ATCACHE > 1
	at.at_cdrv[1] = -1;
	at.at_cbuf[1] = kalloc( BSIZE );
#endif

	at.at_bad_drv = -1;
}

/**
 *
 * void
 * atunload()	- unload routine.
 */
static void
atunload()
{
	clrivec( HDIRQ );
}

/**
 *
 * void
 * atreset()	-- reset hard disk controller, define drive characteristics.
 */
static void
atreset()
{
	register int u;
	register struct dparm_s * dp;

	/*
	 * Reset controller for a minimum of 4.8 microseconds.
	 */
	outb( HF_REG, 4 );
	for ( u = 100; --u != 0; )
		;
	outb( HF_REG, atparm[0].d_ctrl & 0x0F );
	myatbsyw(0);
	if ( inb(AUX_REG) != 0x01 )
		printf("at: AT disk controller not present (reset)\n");

	/*
	 * Initialize drive parameters.
	 */
	for ( u = 0, dp = &atparm[0]; u < NDRIVE; ++dp, ++u ) {

		if ( at.at_dtype[u] == 0 )
			continue;

		myatbsyw(u);

		/*
		 * Set drive characteristics.
		 * 0x1F1 - AUX_REG
		 * 0x1F2 - NSEC_REG
		 * 0x1F3 - SEC_REG
		 * 0x1F4 - LCYL_REG
		 * 0x1F5 - HCYL_REG
		 * 0x1F6 - HDRV_REG
		 * 0x1F7 - CSR_REG
		 */
		outb( HF_REG,	dp->d_ctrl );
		outb( AUX_REG,  dp->d_wpcc / 4 );
		outb( NSEC_REG, dp->d_nspt );
		outb( SEC_REG, 0x01 );
		outb( LCYL_REG, (char)(dp->d_ncyl) );
		outb( HCYL_REG, (char)(dp->d_ncyl >> 8) );
		outb( HDRV_REG, 0xA0 + (u<<4) + dp->d_nhead - 1 );
		outb( CSR_REG,  SETPARM_CMD );
		myatbsyw(u);

		/*
		 * Restore heads.
		 */
		outb( CSR_REG, RESTORE(0) );
		myatbsyw(u);
	}
}

/**
 *
 * void
 * atopen( dev, mode )
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void
atopen( dev, mode )
register dev_t	dev;
{
	register int d;		/* drive */
	register int p;		/* partition */

	p = minor(dev) % (NDRIVE*NPARTN);

	if ( minor(dev) & SDEV ) {
		d = minor(dev) % NDRIVE;
		p += NDRIVE * NPARTN;
	}
	else
		d = minor(dev) / NPARTN;

	if ( (d >= NDRIVE) || (at.at_dtype[d] == 0) ) {
		u.u_error = ENXIO;
		return;
	}

	if ( minor(dev) & SDEV )
		return;

	/*
	 * If partition not defined read partition characteristics.
	 */
	if ( pparm[p].p_size == 0 )
		fdisk( makedev( major(dev), SDEV + d), &pparm[ d * NPARTN ] );

	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	if ((pparm[p].p_base+pparm[p].p_size) > pparm[d+NDRIVE*NPARTN].p_size)
		u.u_error = EBADFMT;
	else if ( pparm[p].p_size == 0 )
		u.u_error = ENODEV;
}

/**
 *
 * void
 * atread( dev, iop )	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
atread( dev, iop )
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
}

/**
 *
 * void
 * atwrite( dev, iop )	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
atwrite( dev, iop )
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
}

/**
 *
 * int
 * atioctl( dev, cmd, arg )
 * dev_t dev;
 * int cmd;
 * char * vec;
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static int
atioctl( dev, cmd, vec )
register dev_t	dev;
int cmd;
char * vec;
{
	int d;

	/*
	 * Identify drive number.
	 */
	if ( minor(dev) & SDEV )
		d = minor(dev) % NDRIVE;
	else
		d = minor(dev) / NPARTN;

	/*
	 * Identify input/output request.
	 */
	switch ( cmd ) {

	case HDGETA:
		/*
		 * Get hard disk attributes.
		 */
		kucopy( &atparm[d], vec, sizeof(atparm[0]) );
		return( 0 );

	case HDSETA:
		/* Set hard disk attributes. */
		ukcopy(vec, &atparm[d], sizeof(atparm[0]));
		at.at_dtype[d] = 1;		/* set drive type nonzero */
		pparm[NDRIVE * NPARTN + d].p_size =
			(long) atparm[d].d_ncyl * atparm[d].d_nhead * atparm[d].d_nspt;
		atreset();
		return 0;

	default:
		u.u_error = EINVAL;
		return( -1 );
	}
}

/**
 *
 * void
 * atwatch()		- guard against lost interrupt
 *
 *	Action:	If drvl[AT_MAJOR] is greater than zero, decrement it.
 *		If it decrements to zero, simulate a hardware interrupt.
 */
static void
atwatch()
{
	register BUF * bp = at.at_actf;
	register int s;

	s = sphi();
	if ( --drvl[AT_MAJOR].d_time > 0 ) {
		spl(s);
		return;
	}
	printf("at%d%c: bno=%U head=%u cyl=%u <Watchdog Timeout>\n",
		at.at_drv,
		(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
		bp->b_bno, at.at_head, at.at_cyl );

	/*
	 * Reset hard disk controller.
	 *
	 * Mark current cylinder as bad so atstart() will fail.
	 * Otherwise would lock up if this track NEVER gives enough IRQ's.
	 */
	at.at_bad_drv	= at.at_drv;
	at.at_bad_head	= at.at_head;
	at.at_bad_cyl	= at.at_cyl;
	atreset();
	atstart();
	spl(s);
}

/**
 *
 * void
 * atblock( bp )	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void
atblock(bp)
register BUF	*bp;
{
	register struct fdisk_s *pp;
	int partn = minor(bp->b_dev) % (NDRIVE*NPARTN);

	bp->b_resid = bp->b_count;

	if ( minor(bp->b_dev) & SDEV )
		partn += NDRIVE * NPARTN;

	pp = &pparm[ partn ];

	/*
	 * Check for read at end of partition.
	 */
	if ( (bp->b_req == BREAD) && (bp->b_bno == pp->p_size) ) {
		bdone(bp);
		return;
	}

	/*
	 * Range check disk region.
	 */
	if ( ((bp->b_bno + (bp->b_count/BSIZE)) > pp->p_size)
	|| (bp->b_count % BSIZE) || bp->b_count == 0) {
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}

	bp->b_actf = NULL;
	if (at.at_actf == NULL)
		at.at_actf = bp;
	else
		at.at_actl->b_actf = bp;
	at.at_actl = bp;

	if ( at.at_state == SIDLE )
		if ( atdequeue() )
			atstart();
}

/**
 *
 * int
 * atdequeue()		- obtain next disk read/write operation
 *
 *	Action:	Pull some work from the disk queue.
 *
 *	Return:	0 = no work.
 *		* = work to do.
 */
static int
atdequeue()
{
	register BUF * bp;
	register struct fdisk_s * pp;
	unsigned int nspt;

	for (;;) {
		at.at_caching = 0;
		at.at_tries   = 0;

		if ( (bp = at.at_actf) == NULL )
			return (0);

		at.at_partn = minor( bp->b_dev ) % (NDRIVE*NPARTN);

		if ( minor(bp->b_dev) & SDEV ) {
			at.at_partn += (NDRIVE*NPARTN);
			at.at_drv  = minor( bp->b_dev ) % NDRIVE;
		}
		else
			at.at_drv = minor( bp->b_dev ) / NPARTN;
		nspt = atparm[at.at_drv].d_nspt;

		pp = &pparm[ at.at_partn ];
		at.at_bno   = pp->p_base + bp->b_bno;
		at.at_nsec  = bp->b_count / BSIZE;
		at.at_faddr = bp->b_faddr;

#if ATCACHE > 0
		if ( bp->b_req == BWRITE ) {

			/*
			 * Invalidate cache if write might overlap.
			 */
			if ( at.at_nsec > 1 ) {
				at.at_cdrv[0] = -1;
#if ATCACHE > 1
				at.at_cdrv[1] = -1;
#endif
			}
			else if ( at.at_bno == at.at_cbno[0] )
				at.at_cdrv[0] = -1;
#if ATCACHE > 1
			else if ( at.at_bno == at.at_cbno[1] )
				at.at_cdrv[1] = -1;
#endif
		}
		else if ( at.at_nsec == 1 ) {

			/*
			 * Test for cache hit on block 0.
			 */
			if ( (at.at_drv == at.at_cdrv[0])
			&&   (at.at_bno == at.at_cbno[0]) ) {

				kpcopy( at.at_cbuf[0],
					bp->b_paddr, BSIZE );
				at.at_actf  = bp->b_actf;
				bp->b_resid = 0;
				bdone(bp);
				continue;
			}

#if ATCACHE > 1
			/*
			 * Test for cache hit on block 1.
			 */
			if ( (at.at_drv == at.at_cdrv[1])
			&&   (at.at_bno == at.at_cbno[1]) ) {

				kpcopy( at.at_cbuf[1],
					bp->b_paddr, BSIZE );
				at.at_actf  = bp->b_actf;
				bp->b_resid = 0;
				bdone(bp);
				continue;
			}
#endif

			/*
			 * Enable caching if no backlog for disk i/o.
			 */
			if ( bp->b_actf == NULL ) {
				/*
				 * Enable caching on single block reads
				 * when at least one block left on same track.
				 */
				at.at_caching = nspt - 1 - (at.at_bno % nspt);
#if ATCACHE > 1
				if ( at.at_caching >= 2 ) {
					at.at_caching   = 2;
					at.at_cdrv[2-1] = -1;
				}
#endif

				if ( at.at_caching ) {
					at.at_nsec  += at.at_caching;
					at.at_cdrv[1-1] = -1;
				}
			}
		}
#endif

		return (1);
	}
}

/**
 *
 * void
 * atstart()	- start or restart next disk read/write operation.
 *
 *	Action:	Initiate disk read/write operation.
 */
static void
atstart()
{
	register struct dparm_s *dp;

	dp = &atparm[ at.at_drv ];

	at.at_cyl  = (at.at_bno / dp->d_nspt) / dp->d_nhead;
	at.at_head = (at.at_bno / dp->d_nspt) % dp->d_nhead;
	at.at_sec  = (at.at_bno % dp->d_nspt) + 1;

	/*
	 * Check for repeated access to most recently identified bad track.
	 */
	if ( (at.at_drv  == at.at_bad_drv )
	  && (at.at_cyl  == at.at_bad_cyl )
	  && (at.at_head == at.at_bad_head) ) {
	  	BUF * bp = at.at_actf;
		printf( "at%d%c: bno=%U head=%u cyl=%u <Track Flagged Bad>\n",
			at.at_drv,
			(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
			bp->b_bno,
			at.at_head,
			at.at_cyl );
		bp->b_flag |= BFERR;
		atdone(bp);
		return;
	}

	myatbsyw(at.at_drv);

	outb( HF_REG,   dp->d_ctrl );
	outb( AUX_REG,  dp->d_wpcc / 4 );
	outb( NSEC_REG, at.at_nsec );
	outb( SEC_REG,  at.at_sec );
	outb( LCYL_REG, at.at_cyl );
	outb( HCYL_REG, at.at_cyl >> 8 );
	outb( HDRV_REG, (at.at_drv << 4) + at.at_head + 0xA0 );

	if ( at.at_actf->b_req == BWRITE ) {

		outb( CSR_REG, WRITE_CMD );

		while ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

		atsend( at.at_faddr );
		at.at_state = SWRITE;
	}
	else {
		outb( CSR_REG, READ_CMD );
		at.at_state = SREAD;
	}
	drvl[AT_MAJOR].d_time = 2;
}

/**
 *
 * void
 * atintr()	- Interrupt routine.
 *
 */
static void
atintr()
{
	defer( atdefer, 0 );
}

/**
 *
 * void
 * atdefer()	- Deferred service of hard disk interrupt.
 *
 *	Action:	Service disk interrupt.
 *		Transfer required data.
 *		Update state.
 */
static void
atdefer()
{
	register BUF * bp = at.at_actf;

	switch ( at.at_state ) {

	case SRETRY:
		atstart();
		break;

	case SREAD:
		/*
		 * Check for I/O error before waiting for data.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

		/*
		 * Wait for data, or forever.
		 */
		if ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

#if ATCACHE > 0
		/*
		 * Cache data block.
		 */
		if ( at.at_caching == at.at_nsec )
			atrecv( at.at_cbuf[ at.at_nsec - 1 ], sds );
		else
#endif

		/*
		 * Read data block.
		 */
			atrecv( at.at_faddr );

		/*
		 * Check for I/O error after reading data.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

#if ATCACHE > 0
		/*
		 * Validate cached blocks.
		 */
		if ( at.at_caching == at.at_nsec ) {
			at.at_cbno[ at.at_nsec - 1 ] = at.at_bno;
			at.at_cdrv[ at.at_nsec - 1 ] = at.at_drv;
			at.at_caching--;
		}
		else
#endif
		{
			FP_OFF(at.at_faddr) += BSIZE;
			bp->b_resid -= BSIZE;
		}

		at.at_tries = 0;
		at.at_bno++;

		/*
		 * Check for end of transfer.
		 */
		if ( --at.at_nsec == 0 )
			atdone( bp );
		break;

	case SWRITE:
		/*
		 * Check for I/O error.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

		FP_OFF(at.at_faddr) += BSIZE;
		bp->b_resid -= BSIZE;
		at.at_tries  = 0;
		at.at_bno++;

		/*
		 * Check for end of transfer.
		 */
		if ( --at.at_nsec == 0 ) {
			atdone( bp );
			break;
		}

		/*
		 * Wait for ability to send data, or forever.
		 */
		while ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

		/*
		 * Send data block.
		 */
		atsend( at.at_faddr );
	}
}

/**
 *
 * int
 * aterror()
 *
 *	Action:	Check for drive error.
 *		If found, increment error count and report it.
 *
 *	Return: 0 = No error found.
 *		1 = Error occurred.
 */
static int
aterror()
{
	register BUF * bp = at.at_actf;
	register int csr;
	register int aux;

	if ( (csr = inb(CSR_REG)) & (ERR_ST|WFLT_ST) ) {

		aux = inb(AUX_REG);

		/*
		 * Don't retry or report failures on cache reads.
		 */
#if ATCACHE > 0
		if ((at.at_state == SREAD) && (at.at_caching == at.at_nsec)) {
			at.at_tries = BADLIM;
			return 1;
		}
#endif

		if ( aux & BAD_ERR ) {
			at.at_tries	= BADLIM;
			at.at_bad_drv	= at.at_drv;
			at.at_bad_head	= at.at_head;
			at.at_bad_cyl	= at.at_cyl;
		}
		else if ( ++at.at_tries < SOFTLIM )
			return 1;

		printf( "at%d%c: bno=%U head=%u cyl=%u",
			at.at_drv,
			(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
			(bp->b_count/BSIZE) + bp->b_bno
				+ at.at_caching - at.at_nsec,
			at.at_head, at.at_cyl );

#if VERBOSE > 0
		if ( (csr & RDY_ST) == 0 )
			printf(" <Drive Not Ready>");
		if ( csr & WFLT_ST )
			printf(" <Write Fault>");

		if ( aux & DAM_ERR )
			printf(" <No Data Addr Mark>");
		if ( aux & TR0_ERR )
			printf(" <Track 0 Not Found>" );
		if ( aux & ID_ERR )
			printf(" <ID Not Found>" );
		if ( aux & ECC_ERR )
			printf(" <Bad Data Checksum>" );
		if ( aux & ABT_ERR )
			printf(" <Command Aborted>" );
#else
		if ( (csr & (RDY_ST|WFLT_ST)) != RDY_ST )
			printf( " csr=%x", csr );
		if ( aux & (DAM_ERR|TR0_ERR|ID_ERR|ECC_ERR|ABT_ERR) )
			printf( " aux=%x", aux );
#endif
		if ( aux & BAD_ERR )
			printf(" <Block Flagged Bad>" );

		if ( at.at_tries < HARDLIM )
			printf(" retrying...");
		printf("\n");
		return 1;
	}
	return 0;
}

/**
 *
 * void
 * atrecov()
 *
 *	Action:	Attempt recovery.
 */
static void
atrecov()
{
	register BUF *bp = at.at_actf;
	register int cmd = SEEK(0);
	register int cyl = at.at_cyl;

	switch ( at.at_tries ) {

	case 1:
	case 2:
		/*
		 * Move in 1 cylinder, then retry operation
		 */
		if ( --cyl < 0 )
			cyl += 2;
		break;

	case 3:
	case 4:
		/*
		 * Move out 1 cylinder, then retry operation
		 */
		if ( ++cyl >= atparm[ at.at_drv ].d_ncyl )
			cyl -= 2;
		break;

	case 5:
	case 6:
		/*
		 * Seek to cylinder 0, then retry operation
		 */
		cyl = 0;
		break;

	default:
		/*
		 * Restore drive, then retry operation
		 */
		cmd = RESTORE(0);
		cyl = 0;
		break;
	}

	/*
	 * Retry operation [after repositioning head]
	 */
	if ( at.at_tries < HARDLIM ) {
		drvl[AT_MAJOR].d_time = (cmd == RESTORE(0)) ? 5 : 2;
		outb( LCYL_REG, cyl );
		outb( HCYL_REG, cyl >> 8 );
		outb( HDRV_REG, (at.at_drv << 4) + 0xA0 );
		outb( CSR_REG, cmd );
		at.at_state = SRETRY;
	}

	/*
	 * Give up on block.
	 */
	else {
		/*
		 * Not a cache-read error.
		 */
#if ATCACHE > 0
		if ( (at.at_state != SREAD) || (at.at_caching != at.at_nsec) )
#endif
			bp->b_flag |= BFERR;

		atdone(bp);
	}
}

/**
 *
 * void
 * atdone( bp )
 * BUF * bp;
 *
 *	Action:	Release current i/o buffer to the O/S.
 */
static void
atdone( bp )
register BUF * bp;
{
	drvl[AT_MAJOR].d_time = 0;
	at.at_state = SIDLE;
	at.at_actf  = bp->b_actf;
	bdone(bp);

	if ( atdequeue() )
		atstart();
}

int
myatbsyw(unit) int unit;
{
	register int n, status;

	for (n = ATBSYW; n > 0; --n)
		if ((status = atbsyw()) != 0)
			return status;
	printf(timeout_msg, unit);
	return 0;
}
0707070064030050451006440000030000030000011777770507310631500005000000004006/newbits/kernel/USRSRC/i8086/drv/atas.s/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ AT Hard Disk Assembler Support
/
/ atsend( off, seg ) - send 512 bytes from seg:off into hard disk buffer
/ atrecv( off, seg ) - receive 512 bytes from hard disk buffer into seg:off.
/ DRQ is not checked.  DRQ must be true before atsend/atrecv are called.
/
/ atbsyw()	     - wait while controller is busy
/ atdrqw()	     - wait for controller to request data transfer
/
////////

	.globl	atsend_
	.globl	atrecv_
	.globl	atbsyw_
	.globl	atdrqw_

	CSR_REG	= 0x01F7
	BSY_ST	= 0x80
	DRQ_ST	= 0x08

////////
/
/ void
/ atsend( fp )	-- send 512 bytes to AT disk controller.
/ faddr_t fp;
/
/	Input:	fp = far pointer [sel:off] to data buffer.
/
/	Action:	Transfer 512 bytes to AT disk controller from buffer.
/
////////

atsend_:
	push	si
	push	ds
	push	bp
	mov	bp, sp
	lds	si, 8(bp)
	mov	cx, $256
	mov	dx, $0x1F0
	cld
	rep
	outs
	pop	bp
	pop	ds
	pop	si
	ret

////////
/
/ void
/ atrecv( fp )	-- receive 512 bytes from AT disk controller.
/ faddr_t fp;
/
/	Input:	fp = far pointer [sel:off] to data buffer.
/
/	Action:	Transfer 512 bytes from AT disk controller to buffer.
/
////////

atrecv_:
	push	di
	push	es
	push	bp
	mov	bp, sp
	les	di, 8(bp)
	mov	cx, $256
	mov	dx, $0x1F0
	cld
	rep
	ins
	pop	bp
	pop	es
	pop	di
	ret

////////
/
/ atbsyw()	-- wait for AT disk controller to become not busy
/
/	Return:	0 = timeout
/		* = not busy
/
////////

atbsyw_:
	mov	dx, $CSR_REG
	mov	bx, $4		/ add another layer of iteration for 486's
0:	mov	cx, $-1
1:	inb	al, dx
	testb	al, $BSY_ST
	loopne	1b
	je	2f		/ not busy - return nonzero value
	dec	bx
	jne	0b
2:	mov	ax, cx
	ret

////////
/
/ atdrqw()	-- wait for AT disk controller to initiate data request
/
/	Return:	0 = timeout
/		* = data requested
/
////////

atdrqw_:
	mov	dx, $CSR_REG
	mov	bx, $4
0:	mov	cx, $-1
1:	inb	al, dx
	testb	al, $DRQ_ST
	loope	1b
	jne	2f		/ not busy - return nonzero value
	dec	bx
	jne	0b
2:	mov	ax, cx
	ret
0707070064030050441006440000030000030000011777770507310631600005000000006453/newbits/kernel/USRSRC/i8086/drv/bufq.c/*
 * File:	bufq.c
 *
 * Purpose:
 *	Queueing routines for SCSI driver.
 *	Should be generalizable for other hard drives.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2  91/05/21  23:23:36  hal
 * Enhanced debug printout.
 * 
 * Revision 1.1  91/05/21  13:54:11  root
 * First running version.
 * 
 */

/*
 * Includes.
 */
#include <sys/coherent.h>
#include <sys/buf.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */
typedef struct {
	BUF	* head;	/* point to first node */
	BUF	* tail;	/* point to last node */
	int	count;	/* number of nodes in the queue */
} bufq_type;

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
static int	num_q;		/* number of queues in use */
static bufq_type  * bufq_q;	/* pointer to allocated queue structs */

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
int bufq_init();
void bufq_rlse();
void bufq_wr_tail();
BUF * bufq_rd_head();
BUF * bufq_rm_head();

/*
 * Debug macros.
 */
#if (DEBUG >= 3)
#define QSIZE	printf("Q%d:%d ", s_id, bqp->count)
#else
#if (DEBUG >= 2)
#define QSIZE	{if (bqp->count>1)printf("Q%d:%d ", s_id, bqp->count);}
#else
#define QSIZE
#endif
#endif

/*
 * bufq_init()
 *
 * Set up the desired number of queues.
 *
 * Return 1 if ok, 0 if kalloc() failed.
 */
int bufq_init(qcount)
int qcount;
{
	int ret;

	if (qcount > 0 && (bufq_q = kalloc(qcount*sizeof(bufq_type)))) {
		ret = 1;
		kclear(bufq_q, qcount*sizeof(bufq_type));
		num_q = qcount;
#if (DEBUG >= 2)
printf("%d queues allocated\n", qcount);
#endif
	} else
		ret = 0;

	return ret;
}

/*
 * bufq_rlse()
 *
 * Deallocate buffer queue structs.
 */
void bufq_rlse()
{
	num_q = 0;
	if (bufq_q)
		kfree(bufq_q);
}

/*
 * bufq_wr_tail()
 *
 * Append a BUF object to the doubly-linked queue.
 * Object to be inserted has been allocated by the caller.
 * Run at high priority.
 */
void bufq_wr_tail(s_id, bp)
int s_id;
BUF * bp;
{
	int s;
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		s = sphi();
		if (bqp->count == 0) {
			bqp->head = bqp->tail = bp;
			bp->b_actf = bp->b_actl = NULL;
		} else {
			bqp->tail->b_actf = bp;
			bp->b_actf = NULL;
			bp->b_actl = bqp->tail;
			bqp->tail = bp;
		}
		bqp->count++;
QSIZE;
		spl(s);
	}
}

/*
 * bufq_rd_head()
 *
 * Nondestructively fetch the head entry in the queue - i.e., this routine
 * does not remove an entry from the queue (see ss_rm_head() for that).
 * Return NULL if queue is empty, else return pointer to head item.
 */
BUF * bufq_rd_head(s_id)
int s_id;
{
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		return bqp->head;
	} else
		return NULL;
}

/*
 * bufq_rm_head()
 *
 * Delete head item from the queue.  Return a pointer to the node deleted,
 * or NULL if the queue was already empty.
 * Run at high priority.
 *
 * This routine does NOT deallocate the node.  That must be done by the
 * calling function after this routine runs.
 */
BUF * bufq_rm_head(s_id)
int s_id;
{
	BUF * ret;
	int s;
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		s = sphi();
		if (bqp->count > 0) {
			ret = bqp->head;
			if (bqp->count == 1) {
				bqp->head = bqp->tail = NULL;
			} else {
				bqp->head = bqp->head->b_actf;
				bqp->head->b_actl = NULL;
			}
			bqp->count--;
QSIZE;
		} else
			ret = NULL;
		spl(s);
	} else
		ret = NULL;

	return ret;
}
0707070064030050501004440000030000030000011777770507310631700005300000005751/newbits/kernel/USRSRC/i8086/drv/clocked.s////////
/
/ Clocked Functions - schedule function 'f' to be periodically invoked.
/		    - invocation is at clock interrupt level
/		    - only one function can be clocked
/
/	clocked( f, hz )
/	void (*f)();
/	int hz;
/
////////

	.globl	clocked_

////////
/
/ Hardware Dependant Constants
/
////////

	EOI	= 0x20		/ Non-specific End of Interrupt command
	PIC	= 0x20		/ 8259 pic   base address
	PIT	= 0x40		/ 8253 timer base address

////////
/
/ Private Data Declarations
/
////////

	.bssd
stack:	.blkb	256		/ Run time stack for the clocked function.
stktop:

	.shri	/ CODE SPACE!
uss:	.word	0		/ User stack segment
usp:	.word	0		/ User stack pointer
kds:	.word	0		/ Kernel data segment
oldclk:	.word	0		/ Previous clock interrupt entry point.
reload:	.word	0		/ Number of polls per logical clock tick.
resid:	.word	0		/ Number of polls left in logical clock tick.
cfunc:	.word	0		/ Clocked function
	.shri

////////
/
/ clocked( f, hz )
/ void (*f)();
/ int hz;
/
/	Input:	f  = function to be clocked.
/		hz = desired clock rate in invocations/second.
/
/	Action:	Calculate the number of polls per logical clock tick.
/		Seize the clock hardware interrupt.
/		Preserve the previous clock interrupt handler.
/		Reprogram the hardware clock to the desired rate.
/
/	Return:	 0 = clock interrupt seized.
/		-1 = clock interrupt previously seized.
/
/	Notes:	The logical clock rate to the OS will be unchanged.
/
////////

clocked_:
	pop	ax		/ Convert IP into PSW,CS,IP so can use iret.
	pushf
	push	cs
	push	ax

	mov	cs:kds, ds	/ Remember the kernel data segment

	cli			/ Disable interrupts

	push	es		/ Seize clock interrupt vector
	sub	ax, ax
	mov	es, ax
	mov 	ax, es:0x0020
	cmp	ax, $clocker
	jne	0f
	mov	ax, $-1
	pop	es
	iret

0:	mov	cs:oldclk, ax
	mov	es:0x0020, $clocker
	pop	es

	mov	bx, sp		/ Remember the function to be clocked.
	mov	ax, ss:6(bx)
	mov	cs:cfunc, ax

	mov	ax, ss:8(bx)	/ Compute polling rate relative to 20 hz.
	sub	dx, dx
	mov	cx, $20
	div	cx
	mov	cs:reload, ax
	mov	cs:resid, ax

	movb	al, $0x36	/ Timer 0, LSB, MSB, mode 3
	outb	PIT+3, al
	mov	ax, $59659
	sub	dx, dx
	div	cs:reload
	outb	PIT, al		/ LSB of 59659/reload
	jmp	0f
0:	movb	al, ah
	outb	PIT, al		/ MSB of 59659/reload

	sub	ax, ax
	iret

////////
/
/	clocker()	- initiate clocked function.
/
/	Action:	Every hardware clock tick, invoke the clocked function.
/		Every 'reload' hardware clock ticks,
/			simulate a logical clock interrupt to the OS.
/
////////

clocker:
	push	ax		/ Save registers.
	push	bx
	push	cx
	push	dx
	push	ds
	push	es

	mov	cs:uss, ss	/ Save current stack.
	mov	cs:usp, sp

	mov	ax, cs:kds	/ Remap Data/Extra/Stack Segments into Kernel.
	mov	ds, ax
	mov	es, ax
	mov	ss, ax
	mov	sp, $stktop	/ Remap stack pointer onto private intr stack.

	icall	cs:cfunc	/ Call the clocked function.

	mov	ss, cs:uss	/ Restore previous stack.
	mov	sp, cs:usp
	
	pop	es		/ Restore registers.
	pop	ds
	pop	dx
	pop	cx
	pop	bx

	dec	cs:resid
	je	0f
	movb	al, $EOI
	outb	PIC, al
	pop	ax
	iret

0:	mov	ax, cs:reload
	mov	cs:resid, ax
	pop	ax
	ijmp	cs:oldclk
0707070064030050471004440000030000030000011777770507310631700005300000001525/newbits/kernel/USRSRC/i8086/drv/console.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 * Tiny console driver.
 * 8086/8088 Coherent, IBM PC.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:03:39	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:04:25	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/i8086/drv/console.c
 * putchar() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <sys/inode.h>
#include <sys/stat.h>
#include <sys/con.h>
#include <sys/io.h>

dev_t condev = makedev(2,0);

putchar(c)
int c;
{
	static coninit;
	IO iob;

	if (coninit == 0) {
		++coninit;
		dopen( condev, IPW, DFCHR );
	}

	if (c == '\n')
		putchar('\r');

	iob.io_seg  = IOSYS;
	iob.io_ioc  = 1;
	iob.io_base = &c;
	iob.io_flag = 0;
	dwrite( condev, &iob );
}
0707070064030050521006440000030000030000011777770507310632000004600000032721/newbits/kernel/USRSRC/i8086/drv/dg.c/*
 * dg - device driver for Digiboard PC/Xe intelligent multiport controller
 *
 * $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.3	91/03/05  12:23:42	root
 * Fix cast on dg_ram_base
 * 
 */
 
/*
 * Various notes:
 *
 *	FEP = front-end-processor (the 80186 on the Digiboard)
 *
 *	At port DG_IOB:
 *		the 2's bit is 1 to enable DPRAM, 0 to disable
 *		the 4's bit is 1 to reset FEP, 0 to clear reset 
 *
 *	There is a bug in the current ldlib.a version of setivec and clrivec:
 *	they only work during xxload() and xxunload() due to use of "ucs"
 *	instead of "getcs()" to determine the CS for the interrupt routine.
 */

/*
 * Definitions.
 *
 */
#define	DG_RAM_LENGTH	0x10000L
#define DG_MEMORY_SEG	0xF000		/* dual-port ram base on FEP side */
#define DG_BIOS_ADDR	0xF800
#define DG_FEPOS_ADDR	0x2000
#define DG_BIOS_LOADER	0x80		/* minor number to write to BIOS */
#define DG_FEPOS_LOADER	0x40		/* minor number to write to FEPOS */
#define DG_BIOS_LENGTH	0x800		/* PC/Xe BIOS is 2k bytes */
#define DG_BIOS_CONFIRM	0x0C00		/* look for "GD" here */
#define DG_FEP_CONFIRM	0x0D20		/* look for "OS" here */
#define DG_BIOS_REQ	0x0C40		/* Start FEP BIOS requests here */
#define BIOS_GOOD	('G' + ('D'<<8))	/* "GD" */
#define FEPOS_GOOD	('O' + ('S'<<8))	/* "OS" */

#define CSTART		0x400		/* start addr of command queue */
#define NPORT		0x0C22		/* addr of # of ports */
#define CIN		0x0D10		/* addr for command in pointer */
#define COUT		0x0D12		/* addr for command out pointer */
#define ISTART		0x800		/* start addr of event queue */
#define EIN		0x0D18		/* addr for event in pointer */
#define EOUT		0x0D1A		/* addr for event out pointer */
#define INTERVAL	0x0E04		/* addr for ticks between irpts */
#define EVENT_LEN	4		/* bytes per FEP event */
#define COMMAND_LEN	4		/* bytes per FEP command */

/*
 * Includes.
 */
#include "coherent.h" 
#include <sys/io.h>		/* IO */
#include <sys/sched.h>		/* [CIS]VPAUSE */
#include <sys/uproc.h>		/* u.u_error */
#include <sys/proc.h>		/* wakeup();
				   includes sys/types.h - faddr_t, paddr_t
				   and sys/timeout.h - TIM
				   needs coherent.h for KERNEL */
#include <sys/con.h>		/* CON */
#include <sys/stat.h>		/* minor(dev) */
#include <devices.h>		/* device major numbers, including PE_MAJOR */
#include <errno.h>

/*
 * Export Functions.
 */

/*
 * Export variables - these may be patched in order to configure the driver.
 */
long	DG_RAM = 0xF0000L;	/* segment for 64k of dual-port RAM */
int	DG_IOB = 0x200;		/* address of i/o byte for controller */
int	DG_INT = 15;		/* IRQ number for board's interrupt */

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Local functions.
 */
static dgload();
static dgunload();
static dgopen();
static dgclose();
static dgread();
static dgwrite();
static void dgdelay();
static dg_start_timing();
static dg_stop_timing();
static int dginit2();
static int dginit3();
static void dgintr();
 
/*
 * Local variables.
 */
static faddr_t	dg_ram_fp;	/* (far *) to access screen */
static paddr_t	dg_ram_base;	/* physical address of screen base */
static TIM	delay_tim;	/* needed for calls to timeout() */
static TIM	timeout_tim;	/* needed for calls to timeout() */
static int	dg_expired;	/* TRUE after local timeout */
static int	bios_loading;	/* TRUE if minor device for BIOS load open */
static int	fepos_loading;	/* TRUE if minor device for FEPOS load open */
static int	load_byte_ct;	/* place-holder for BIOS/FEPOS load */
static int	board_ready;	/* TRUE when all board initialization done */
static int	dg_bios_wait;	/* TRUE if waiting for BIOS to be loaded */
static int	dg_fepos_wait;	/* TRUE if waiting for FEPOS to be loaded */
static int	nport;		/* number of ports on the Digiboard */
static int	test_irq;	/* TRUE during startup */

/*
 * Configuration table - another export variable.
 */
CON dgcon ={
	DFCHR,				/* Flags */
	PE_MAJOR,			/* Major index */
	dgopen,				/* Open */
	dgclose,			/* Close */
	nulldev,			/* Block */
	dgread,				/* Read */
	dgwrite,			/* Write */
	nulldev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	dgload,				/* Load */
	dgunload,			/* Unload */
	nulldev				/* Poll */
};

/*
 * Load Routine.
 */
static dgload()
{
	char v;

	setivec(DG_INT, dgintr);
	/*
	 * Allocate a selector to map onto the dual-port RAM.  ptov() will
	 * return the first available selector of the 8,192 possible.
	 */
	dg_ram_base = (paddr_t)((long)(unsigned)DG_RAM << 4);
	dg_ram_fp = ptov(dg_ram_base, (fsize_t)DG_RAM_LENGTH);
	
	/*
	 * Reset the board and wait.
	 * Actual delay is a tick = 0.01 sec; only need 1msec.
	 */
	outb(DG_IOB, 0x04);
	dgdelay(1);
	
	/*
	 * Read board ID.
	 */
	v = inb(DG_IOB);
	if ((v & 0x01) == 0x01) {
		printf("Error - board type is PC/Xi\n");
		return;
	} else {
		outb(DG_IOB, 0x05);	/* hold FEP reset */
		v = inb(DG_IOB);
		if ((v & 0x01) == 0x01) {
			printf("Error - board type is PC/Xm\n");
			return;
		} else
			printf("PC/Xe ID found\n");
	}
	
	/*
	 * Board Reset.
	 */
	outb(DG_IOB, 0x04);	/* reset board */
	dg_start_timing(100);	/* start 1-second timer */
	while ((inb(DG_IOB) & 0x0E) != 0x04) {
		if (dg_expired) {
			printf("Error - PC/Xe failed to reset\n");
			return;
		}
		dgdelay(10);
	}
	outb(DG_IOB, 0x06);	/* enable memory */
	printf("PC/Xe passed reset\n");

	/*
	 * Minimal test of PC/Xe's 64k of dual-ported RAM.
	 */
	sfword(dg_ram_fp, 0xA55A);		/* store a "far" word */
	sfword(dg_ram_fp + 2, 0x3CC3);
	sfword(dg_ram_fp + 0xFFFC, 0xA55A);
	sfword(dg_ram_fp + 0xFFFE, 0x3CC3);
	if (ffword(dg_ram_fp) != 0xA55A		/* fetch a "far" word */
	||  ffword(dg_ram_fp + 2) != 0x3CC3
	||  ffword(dg_ram_fp + 0xFFFC) != 0xA55A
	||  ffword(dg_ram_fp + 0xFFFE) != 0x3CC3) {
		printf("Error - PC/Xe failed memory test\n");
		return;
	} else
		printf("PC/Xe passed memory test\n");
		
	/*
	 * Load and execute the PC/Xe BIOS
	 */
	outb(DG_IOB, 0x06);	/* enable memory */
	dg_bios_wait = 1;
	printf("PC/Xe waiting for BIOS load\n");
}

static dgunload()
{
	if (board_ready) {
		board_ready = 0;
	}
	
	/*
	 * Turn off and unhook interrupts from FEPOS
	 */
	sfword(dg_ram_fp+INTERVAL, 0);	/* stop host interrupts */
	outb(DG_IOB, 0x04);		/* Disable DPRAM and hold FEP reset */
	clrivec(DG_INT);

	/*
	 * We have to free up the selector now that we're done using it.
	 */
	vrelse(dg_ram_fp);
}

/*
 * Open Routine.
 */
static dgopen( dev, mode )
dev_t dev;
{
	/*
	 * If minor number has 128's bit set to 1, this is an attempt to
	 * transfer the BIOS to the FEP.
	 */
	if (minor(dev) & DG_BIOS_LOADER) {
		if (bios_loading) {
			u.u_error = EDBUSY;
			return;
		} else {
			/*
			 * Only allow BIOS xfer if we are waiting for it.
			 */
			if (dg_bios_wait) {
				bios_loading = 1;
				load_byte_ct = 0;
			} else {
				u.u_error = EIO;
				return;
			}
		}
	/*
	 * If minor number has 64's bit set to 1, this is an attempt to
	 * transfer the FEPOS to the FEP.
	 */
	} else if (minor(dev) & DG_FEPOS_LOADER) {
		if (fepos_loading) {
			u.u_error = EDBUSY;
			return;
		} else {
			/*
			 * Only allow FEPOS xfer if we are waiting for it.
			 */
			if (dg_fepos_wait) {
				fepos_loading = 1;
				load_byte_ct = 0;
			} else {
				u.u_error = EIO;
				return;
			}
		}
	} else {
	}
}

/*
 * Close Routine.
 */
static dgclose( dev )
dev_t dev;
{
	/*
	 * If minor number has 128's bit set to 1, this is an attempt to
	 * transfer the BIOS to the FEP.
	 */
	if (minor(dev) & DG_BIOS_LOADER) {
		bios_loading = 0;
		/*
		 * Only set dg_fepos_wait if enough bytes got written.
		 */
		if (load_byte_ct == DG_BIOS_LENGTH) {
			/*
			 * After BIOS is xferred, try to finish
			 * PC/Xe initialization.
			 */
			if (dginit2()) {
				dg_bios_wait = 0;
				dg_fepos_wait = 1;
				printf("PC/Xe waiting for FEPOS load\n");
			}
		}
	/*
	 * If minor number has 64's bit set to 1, this is an attempt to
	 * transfer the FEPOS to the FEP.
	 */
	} else if (minor(dev) & DG_FEPOS_LOADER) {
		fepos_loading = 0;
		/*
		 * After BIOS is xferred, try to finish
		 * PC/Xe initialization.
		 */
		if (dginit3()) {
			dg_fepos_wait = 0;
			board_ready = 1;
			printf("PC/Xe ready for use\n");
		}
	} else {
	}
}

/*
 * Read Routine.
 */
static dgread( dev, iop )
dev_t dev;
register IO * iop;
{
#if 0
	static int offset;
	int c;
	/*
	 * Read a character code from video RAM
	 * Start reading RAM just after where previous read ended
	 *
	 * Note that "offset" is the value of the displacement into
	 * the screen RAM. Any expression which results in a value
	 * which is less than DG_RAM_LENGTH is OK here.
	 */
	while(iop->io_ioc) {
		c = ffbyte(dg_ram_fp + offset); /* fetch a "far" byte */
		if(ioputc(c, iop) == -1)
			break;
		offset += 2;
		offset %= DG_RAM_LENGTH;
	}
#endif	
}

/*
 * Write Routine.
 */
static dgwrite( dev, iop )
dev_t dev;
register IO * iop;
{
	/*
	 * If minor number has 128's bit set to 1, this is an attempt to
	 * transfer the BIOS to the FEP.
	 */
	if (minor(dev) & DG_BIOS_LOADER) {
		int c;

		while ((c = iogetc(iop)) >= 0 && load_byte_ct < DG_BIOS_LENGTH) {
			sfbyte(dg_ram_fp + DG_BIOS_ADDR + load_byte_ct, c);
			load_byte_ct++;
		}
	/*
	 * If minor number has 64's bit set to 1, this is an attempt to
	 * transfer the FEPOS to the FEP.
	 */
	} else if (minor(dev) & DG_FEPOS_LOADER) {
		int c;

		while ((c = iogetc(iop)) >= 0) {
			sfbyte(dg_ram_fp + DG_FEPOS_ADDR + load_byte_ct, c);
			load_byte_ct++;
		}
	} else {
	}
}

/*
 * Delay for some number of clock ticks.
 * 286/386 kernel ticks are at 100Hz
 * Use kernel function sleep(), which is NOT the system call by that name.
 */
static void dgdelay(ticks)
int ticks;
{
	timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
}

/*
 * Start a timeout for some number of ticks.
 * Caller knows timer has expired when "dg_expired" goes to 1.
 *
 * Sample invocation:
 *	dg_start_timing(n);
 *	while (check for desired event fails) {
 *		if (dg_expired) {
 *			...failure stuff..
 *			break;
 *		}
 *		dgdelay(m); <= needed to allow kernel to update timers
 *	}
 */
static dg_start_timing(ticks)
int ticks;
{
	dg_expired = 0;
	timeout(&timeout_tim, ticks, dg_stop_timing, 1);
}

/*
 * Stub function called only by dg_start_timing()
 */
static dg_stop_timing(flagval)
int flagval;
{
	dg_expired = flagval;
}

/*
 * Second part of PC/Xe initialization - done after the BIOS has been
 * written to dual-ported RAM.
 */
static int dginit2()
{
	/*
	 * Execute FEP BIOS
	 */
	sfword(dg_ram_fp + DG_BIOS_CONFIRM, 0);	/* clear confirm word */
	outb(DG_IOB, 0x02);			/* Release reset */
	dg_start_timing(1000);			/* start 10-second timer */

	while (ffword(dg_ram_fp + DG_BIOS_CONFIRM) != BIOS_GOOD) {
		if (dg_expired) {
			printf("Error - PC/Xe BIOS won't start\n");
			return 0;
		}
		dgdelay(10);
	}
	printf("PC/Xe BIOS started\n");

	return 1;
}

/*
 * Third part of PC/Xe initialization - done after the FEPOS has been
 * written to dual-ported RAM.
 */
static int dginit3()
{
	int cmd;

	/*
	 * Ask FEP BIOS to move FEPOS into host memory.
	 */
	sfword(dg_ram_fp + DG_BIOS_REQ, 0x0002);
	sfword(dg_ram_fp + DG_BIOS_REQ+2, DG_MEMORY_SEG+0x200);
	sfword(dg_ram_fp + DG_BIOS_REQ+4, 0x0000);
	sfword(dg_ram_fp + DG_BIOS_REQ+6, 0x0200);
	sfword(dg_ram_fp + DG_BIOS_REQ+8, 0x0000);
	sfword(dg_ram_fp + DG_BIOS_REQ+0xA, 0x2000);
	outb(DG_IOB, 0x0A);			/* Toggle interrupt */
	outb(DG_IOB, 0x02);
	dg_start_timing(100);			/* start 1-second timer */
	while (ffword(dg_ram_fp + DG_BIOS_REQ) != 0) {
		if (dg_expired) {
			printf("Error - PC/Xe FEPOS move failed\n");
			return;
		}
		dgdelay(10);
	}
	printf("PC/Xe FEPOS relocated to host RAM\n");

	/*
	 * Execute FEPOS
	 */
	sfword(dg_ram_fp + DG_BIOS_REQ, 0x0001);
	sfword(dg_ram_fp + DG_BIOS_REQ+2, 0x0200);
	sfword(dg_ram_fp + DG_BIOS_REQ+4, 0x0004);
	sfword(dg_ram_fp + DG_FEP_CONFIRM, 0);	/* clear confirm word */
	outb(DG_IOB, 0x0A);			/* Toggle interrupt */
	outb(DG_IOB, 0x02);
	dg_start_timing(500);			/* start 5-second timer */
	while (ffword(dg_ram_fp + DG_FEP_CONFIRM) != FEPOS_GOOD) {
		if (dg_expired) {
			printf("Error - PC/Xe FEPOS won't start\n");
			printf("Failure code (%x)\n",
				ffword(dg_ram_fp + DG_BIOS_REQ));
			return 0;
		}
		dgdelay(10);
	}
	printf("PC/Xe FEPOS started\n");
	nport = ffbyte(dg_ram_fp+NPORT);

	/*
	 * Enable and test interrupts from FEP
	 */
	sfword(dg_ram_fp+INTERVAL, 1);		/* request host interrupts */
	cmd = ffword(dg_ram_fp+CIN);		/* get command pointer */
	sfword(dg_ram_fp+CSTART+cmd, 0xA1FF);	/* send an invalid command */
	sfword(dg_ram_fp+CSTART+cmd+2, 0xC3B2);
	sfword(dg_ram_fp+CIN, (cmd+4)&0x3ff);	/* update command pointer */
	dg_start_timing(100);			/* start 1-second timer */
	test_irq = 1;
	while (test_irq) {
		if (dg_expired) {
			printf("Error - PC/Xe no FEPOS interrupts\n");
			return 0;
		}
		dgdelay(10);
	}
	printf("PC/Xe interrupts working\n");
	
	return 1;
}

/*
 * Interrupt handler.
 *
 * No specific action is needed to clear the interrupt
 * as it was a pulse sent from the FEPOS to host's IRQ line.
 */
static void dgintr()
{
	int cin, cout, ein, eout;
	unsigned char event[EVENT_LEN];
	int i;

	cin = ffword(dg_ram_fp+CIN);
	cout = ffword(dg_ram_fp+COUT);
	ein = ffword(dg_ram_fp+EIN);
	eout = ffword(dg_ram_fp+EOUT);

	if (board_ready) {
		/*
		 * Remove all packets from event queue.
		 */
		while (ffword(dg_ram_fp+EIN) != ffword(dg_ram_fp+EOUT)) {
			eout = ffword(dg_ram_fp+EOUT);
			for (i = 0; i < EVENT_LEN; i++)
				event[i] = ffbyte(dg_ram_fp+ISTART+eout+i);
			printf("%x %x %x %x\n", event[0],event[1],event[2],event[3]);	
			sfword(dg_ram_fp+EOUT, (eout+4)&0x3ff);
		}
	} else {	/* e.g., if test_irq is TRUE */
		test_irq = 0;
		/*
		 * Attempt to clear the IRQ condition in the FEP.
		 */
		sfword(dg_ram_fp+EOUT, ffword(dg_ram_fp+EIN));
	}
}
0707070064030050511004440000030000030000011777770507310632300005200000007617/newbits/kernel/USRSRC/i8086/drv/dmareq.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */

/*
 * Like ioreq, but guarantee that no DMA straddle occurs.
 * And assume we are called by fl.c, xt.c, dv.c or someone
 * else who obeys the parameter rules that they do.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:03:47	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:04:28	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/i8086/drv/dmareq.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/i8086/drv/dmareq.c
 * dmareq() now wakes &stimer only if the swap timer is active.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/dmac.h>

dmareq(bp, iop, dev, req)
register BUF *bp;
register IO *iop;
dev_t dev;
{
	register int n;
	register SEG *sp;
	register CON *cp;
	dold_t dold;
	long l;
	BUF *tbp;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	lock(bp->b_gate);
	n = cp->c_flag;
	drest(dold);
	if (blocko(iop->io_seek) != 0) {
		u.u_error = EIO;
		goto out;
	}
	if ((sp=iomapvp(iop, bp)) == NULL) {
		u.u_error = EIO;
		goto out;
	}
	bp->b_dev = dev;
	bp->b_flag = 0;
	sp->s_lrefc++;
	bp->b_faddr = ptov( bp->b_paddr, (fsize_t) bp->b_count );
	/*
	 * The dma address is 20 bits; 16 bit offset counter from a 4 bit
	 * base segment.  Since io_ioc is limited to 32Kb positive, we
	 * have at most two raw transfers separated by a block which
	 * straddles the segment boundary.
	 * Life would be simpler if we assumed io_ioc % BSIZE, but
	 * flioctl comes through here with it's short format buffer.
	 */
	while (iop->io_ioc > 0 && (bp->b_flag&BFERR) == 0) {
		l = dmaseg(bp->b_paddr+iop->io_ioc-1) - bp->b_paddr;
		if (l < 0)
			n = iop->io_ioc;
		else
			n = l & ~((long)BSIZE-1);
		l = blockn(iop->io_seek);
		if (n == 0) {
			/* Straddle block */
			tbp = bp;		/* Save the raw buffer */
			n = BSIZE;
			if (n > iop->io_ioc)
				n = iop->io_ioc;
			bp = bclaim(dev, l);
			bp->b_count = n;
			bp->b_req = req;
			if (req != BREAD)
				ioread(iop, FP_OFF(bp->b_faddr), n);
			dmabuf(bp, dev);
			if ((bp->b_flag&BFERR) == 0) {
				if (req == BREAD)
					iowrite(iop, FP_OFF(bp->b_faddr), n);
			} else {
				tbp->b_flag = bp->b_flag;
				tbp->b_err = bp->b_err;
				if (req != BREAD)
					iop->io_ioc += bp->b_resid;
			}
			bp->b_flag |= BFERR;
			brelease(bp);
			bp = tbp;		/* Reclaim raw buffer */
		} else {
			/* Raw transfer */
			bp->b_count = n;
			bp->b_req = req;
			bp->b_bno = l;
			dmabuf(bp, dev);
			if ((bp->b_flag&BFERR) != 0)
				n -= bp->b_resid;
			iop->io_ioc -= n;	/* cookedio do these */
			iop->io_base += n;	/* for everyone */
		}
		FP_OFF(bp->b_faddr) += n;
		bp->b_paddr  += n;
		iop->io_seek += n;
		/* And continue for the next chunk */
	}
	vrelse( bp->b_faddr );
	sp->s_lrefc--;
	if ( stimer.t_last != 0 )
		wakeup((char *)&stimer);
	if ((bp->b_flag&BFERR) != 0 && (u.u_error = bp->b_err) == 0)
		u.u_error = EIO;
out:
	unlock(bp->b_gate);
}

static
dmabuf(bp, dev)
register BUF *bp;
dev_t dev;
{
	register int s;
	bp->b_flag = BFRAW|BFBLK|BFIOC|BFNTP;
	s = sphi();
	dblock(dev, bp);
	while ((bp->b_flag&BFNTP) != 0)
		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
	spl(s);
}
0707070064030050531006440000030000030000011777770507310632400005100000002600/newbits/kernel/USRSRC/i8086/drv/fdisk.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/**
 *
 * fdisk( dev, fp )	--	Fixed Disk Configuration
 * dev_t dev;
 * struct fdisk_s *fp;
 *
 *	Input:	dev = special device to read partition information from
 * 		fp  = pointer to memory-resident partition info (to update)
 *
 *	Action:	Open special device for reading.
 *		Read first block from the device.
 *		If valid signature present on block,
 *			copy partition information to memory
 *
 *	Return:	1 = partition information successfully updated
 *		0 = failure (could not read block, or bad signature)
 */

#include <sys/coherent.h>
#include <sys/uproc.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/fdisk.h>
#include <sys/buf.h>
#include <sys/con.h>

fdisk( dev, fp )
dev_t dev;
register struct fdisk_s *fp;
{
	register struct hdisk_s *hp;
	BUF *bp;
	int s, i;
	int ret = 0;

	s = sphi( );
	dopen( dev, IPR, DFBLK );

	if ( u.u_error == 0 ) {		/* special device now open */

		if (bp = bread(dev, (daddr_t) 0, 1)) {	/* data read */

			/* buffer cache is in kernel data space */
			hp = FP_OFF(bp->b_faddr);

			if ( hp->hd_sig == HDSIG ) {	/* valid data */

				for (i=0; i < NPARTN; ++i)
					*fp++ = hp->hd_partn[i];

				ret   = 1;
			}
			brelease( bp );
		}
		dclose( dev );
	}
	spl( s );
	return ret;
}
0707070064030050541004440000030000030000011777770507310632400004600000057212/newbits/kernel/USRSRC/i8086/drv/fl.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * This is a driver for the IBM AT or PC/XT
 * floppy, using interrupts and DMA on
 * the NEC 756 floppy chip. Ugh.
 * Handles single, double and quad
 * density drives, 8, 9, 15 or 18 sectors per track.
 * 15 and 18 sectors per track only available on the IBM_AT.
 *
 * Minor device assignments: xxuuhkkk
 *	uu - unit = 0/1/2/3
 *	kkk - kind, struct fdata infra.
 *	h - alternating head rather than side by side
 *
 */

#include	<sys/coherent.h>
#include	<sys/i8086.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<errno.h>
#include	<sys/uproc.h>
#include	<sys/fdioctl.h>
#include	<sys/sched.h>
#include	<sys/dmac.h>
#include	<sys/devices.h>

#define		BIT(n)		(1 << (n))

/*
 * Patchable parameters (default to IBM PC/XT values).
 */

int	fl_srt = 0xC;	/* Floppy seek step rate, in unit 2 millisec */
			/* NOT DIRECTLY ENCODED */
			/* COMPAQ wants 0xD */
int	fl_hlt = 1;	/* Floppy head load time, in unit 4 millisec */
int	fl_hut = 0xF;	/* Floppy head unload time, in unit 32 millisec */

int	flload();
int	flunload();
int	flopen();
int	flblock();
int	flread();
int	flwrite();
int	flioctl();
int	fldelay();
int	flintr();
int	fltimeout();
int	nulldev();
int	nonedev();

CON	flcon	= {
	DFBLK|DFCHR,			/* Flags */
	FL_MAJOR,				/* Major index */
	flopen,				/* Open */
	nulldev,			/* Close */
	flblock,			/* Block */
	flread,				/* Read */
	flwrite,			/* Write */
	flioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	fltimeout,			/* Timeout */
	flload,				/* Load */
	flunload			/* Unload */
};

#define	MTIMER	5			/* Motor timeout */
#define	FDCDOR	0x3F2			/* Digital output */
#define	FDCDAT	0x3F5			/* Data register */
#define	FDCMSR	0x3F4			/* Main status register */
#define	FDCRATE	0x3F7			/* Transfer rate (500,300,250 Kbps) */

#define	DORDS	0x03			/* Drive select bits */
#define	DORNMR	0x04			/* Not master reset */
#define	DORIEN	0x08			/* Interrupt, DMA enable */
#define	DORMS	0xF0			/* Motor enables */

#define	MSRDB	0x0F			/* Drive busy */
#define	MSRCB	0x10			/* Control busy */
#define	MSRNDMA	0x20			/* Not DMA */
#define	MSRDIO	0x40			/* Data direction */
#define	MSRRQM	0x80			/* Request for master */

/*
 * Status Register 0 - Bit Definitions.
 */
#define	ST0_US0	0x01			/* Unit Select 0 */
#define	ST0_US1	0x02			/* Unit Select 1 */
#define	ST0_HD	0x04			/* Head Address */
#define	ST0_NR	0x08			/* Not Ready */
#define	ST0_EC	0x10			/* Equipment Check */
#define	ST0_SE	0x20			/* Seek End */
#define	ST0_IC	0xC0			/* Interrupt code */
#define	ST0_NT	0x00			/* Normal Termination */

/*
 * Status Register 1 - Bit Definitions.
 */
#define	ST1_MA	0x01			/* Missing Address Mark */
#define	ST1_NW	0x02			/* Not writeable */
#define	ST1_ND	0x04			/* No Data */
	/*	0x08 */			/* Not used - always 0 */
#define	ST1_OR	0x10			/* Overrun */
#define	ST1_DE	0x20			/* Data Error */
	/*	0x40 */			/* Not used - always 0 */
#define	ST1_EN	0x80			/* End of Cylinder */

/*
 * Status Register 2 - Bit Definitions.
 */
#define	ST2_MD	0x01			/* Missing Address Mark in Data Field */
#define	ST2_BC	0x02			/* Bad Cylinder */
#define	ST2_SN	0x04			/* Scan Not Satisfied */
#define	ST2_SH	0x08			/* Scan Equal Hit */
#define	ST2_WC	0x10			/* Wrong Cylinder */
#define	ST2_DD	0x20			/* Data Error in Data Field */
#define	ST2_CM	0x40			/* Control Mark */
	/*	0x80 */			/* Not used - always 0 */

/*
 * Status Register 3 - Bit Definitions.
 */
#define	ST3_US0	0x01			/* Unit Select 0 */
#define	ST3_US1	0x02			/* Unit Select 1 */
#define	ST3_HD	0x04			/* Head Address */
#define	ST3_TS	0x08			/* Two Sides */
#define	ST3_T0	0x10			/* Track 0 */
#define	ST3_RDY	0x20			/* Ready */
#define	ST3_WP	0x40			/* Write Protected */
#define	ST3_FT	0x80			/* Fault */

/*
 * Controller Commands.
 */
#define	CMDSPEC	0x03			/* Specify */
#define	CMDRCAL	0x07			/* Recal */
#define	CMDSEEK	0x0F			/* Seek */
#define	CMDRDAT	0x66			/* Read data */
#define	CMDWDAT	0x45			/* Write data */
#define	CMDSINT	0x08			/* Sense status */
#define	CMDFMT	0x4D			/* Format track */

/*
 * Driver States.
 */
#define	SIDLE	0			/* Idle */
#define	SSEEK	1			/* Need seek */
#define	SRDWR	2			/* Need read/write command */
#define	SENDIO	3			/* Need end I/O processing */
#define	SDELAY	4			/* Delay before next disk operation */
#define	SHDLY	5			/* Head settling delay before r/w */
#define SLOCK	6			/* Got DMA controller lock */

#define funit(x)	(minor(x)>>4)	/* Unit/drive number */
#define fkind(x)	(minor(x)&0x7)	/* Kind of format */
#define	fhbyh(x)	(minor(x)&0x8)	/* 0=Side by side, 1=Head by head */

static
struct	fdata {
	int	fd_size;	/* Blocks per diskette */
	int	fd_nhds;	/* Heads per drive */
	int	fd_trks;	/* Tracks per side */
	int	fd_offs;	/* Sector base */
	int	fd_nspt;	/* Sectors per track */
	char	fd_GPL[4];	/* Controller gap param (indexed by rate) */
	char	fd_N;		/* Controller size param */
	char	fd_FGPL;	/* Format gap length */
} fdata[] = {
/* 8 sectors per track, surface by surface seek. */
	{  320,1,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */
	{  640,2,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */
	{ 1280,2,80,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */
/* 9 sectors per track, surface by surface seek. */
	{  360,1,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */
	{  720,2,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */
	{ 1440,2,80,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */
/* 15 sectors per track, surface by surface seek. */
	{ 2400,2,80,0,15, { 0x1B,0x00,0x00 }, 2,0x54 }, /* High capacity */
/* 18 sectors per track, surface by surface seek. */
	{ 2880,2,80,0,18, { 0x1B,0x00,0x00 }, 2,0x54 }	/* 1.44 3.5" */
};


static
struct	fl	{
	BUF	*fl_actf;		/* Queue, forward */
	BUF	*fl_actl;		/* Queue, backward */
	paddr_t	fl_addr;		/* Address */
	int	fl_nsec;		/* # of sectors */
	int	fl_secn;		/* Current sector */
	struct	fdata fl_fd;		/* Disk kind data */
	int	fl_fcyl;		/* Floppy cylinder # */
	char	fl_incal[4];		/* Disk in cal flags */
	char	fl_ndsk;		/* # of 5 1/4" drives */
	char	fl_unit;		/* Unit # */
	char	fl_mask;		/* Handy unit mask */
	char	fl_hbyh;		/* 0/1 = Side by side/Head by head */
	char	fl_nerr;		/* Error count */
	int	fl_ncmdstat;		/* Number of cmd status bytes recvd */
	char	fl_cmdstat[8];		/* Command Status buffer */
	int	fl_nintstat;		/* Number of intr status bytes recvd */
	char	fl_intstat[4];		/* Interrupt Status buffer */
	int	fl_fsec;		/* Floppy sector # */
	int	fl_head;		/* Floppy head */
	char	fl_init;		/* FDC init done flag */
	char	fl_state;		/* Processing state */
	char	fl_mstatus;		/* Motor status */
	char	fl_time[4];		/* Motor timeout */
	char	fl_rate;		/* Data rate: 500,300,250,?? kbps */
	char	fl_type[4];		/* Type of drive: 2 = HiCap */
	int	fl_wflag;		/* Write operation  */
	int	fl_recov;		/* Recovery initiated */
}	fl;

static	BUF	flbuf;
static	TIM	fltim;
static	TIM	fldmalck;	/* DMA lock deferred function structure.     */

/*
 * The load routine asks the
 * switches how many drives are present
 * in the machine, and sets up the field
 * in the floppy database. It also grabs
 * the level 6 interrupt vector.
 */
static
flload()
{
	register int	eflag;
	register int	s;

	/*
	 * Ensure DMA channel 2 is turned off.
	 * The Computerland ROM does not disable DMA channel after autoboot
	 * from hard disk.  The Western Digital controller board appears to
	 * send a dma burst when the floppy controller chip is reset.
	 */
	dmaoff( 2 );

	/*
	 * Read floppy equipment byte from CMOS ram
	 *	drive 0 is in high nibble, drive 1 is in low nibble.
	 */
	outb( 0x70, 0x10 );
	/* delay */
	eflag = inb( 0x71 );

	/*
	 * Flag hardware as an IBM AT if neither equipment byte nibble is
	 * greater than 4 (since 5 through 15 are reserved nibble values - see
	 * IBM AT Technical Reference manual, page 1-50).  Note that this
	 * relies on the fact that in the XT, this byte will "float" high.
	 * NOTE: 1.44 Mbyte 3.5 inch drives are type 4
	 */
	if ( (eflag & 0x88) == 0 ) {

		/*
		 * Reinitialize patchable parameters for IBM AT.
		 */
		fl_srt = 0xD;	/* Floppy seek step rate, in unit 2 ms */
				/* NOT DIRECTLY ENCODED */
		fl_hlt = 25;	/* Floppy head load time, in unit 4 ms */

		/*
		 * Define AT drive information.
		 */
		fl.fl_type[0]	= eflag >> 4;
		fl.fl_type[1]	= eflag & 15;
		fl.fl_rate	= 1; /* Must not be 2 */

		/*
		 * Determine number of AT floppy drives.
		 */
		if ( eflag & 0xF0 ) {
			fl.fl_ndsk++;
			if ( eflag & 0x0F )
				fl.fl_ndsk++;
		}
	} else {
		/*
		 * Define XT drive information.
		 */
		eflag		= int11();
		fl.fl_rate	= 2;
		if ( eflag & 1 )
			fl.fl_ndsk = ((eflag >> 6) & 0x03) + 1;
	}

	if ( fl.fl_ndsk ) {

		s = sphi();
		outb(FDCDOR, 0);
		setivec(6, &flintr);

		outb(FDCDOR, 0);
		outb(FDCDOR, DORNMR);

		if ( fl.fl_rate != 2 )
			outb(FDCRATE, fl.fl_rate );

		flput(CMDSPEC);
		flput((fl_srt<<4)|fl_hut);
		flput(fl_hlt<<1);
		spl( s );
	}
}

/*
 * Release resources.
 */
flunload()
{
	/*
	 * Clear interrupt vector.
	 */
	if ( fl.fl_ndsk )
		clrivec(6);

	/*
	 * Cancel timed function.
	 */
	timeout( &fltim, 0, NULL, NULL );

	/*
	 * Cancel periodic [1 second] invocation.
	 */
	drvl[FL_MAJOR].d_time = 0;

	/*
	 * Turn motors off.
	 */
	outb(FDCDOR, DORNMR | DORIEN );
}

/*
 * The open routine screens out
 * opens of illegal minor devices and
 * performs the NEC specify command if
 * this is the very first floppy disk
 * open call.
 */

static
flopen( dev, mode )

dev_t	dev;
int	mode;

{
	/*
	 * Validate existence and data rate [Gap length != 0].
	 */
	if ( ( funit(dev) >= fl.fl_ndsk )
	  || ( fdata[ fkind(dev) ].fd_GPL[ flrate(dev) ] == 0 ) ) {

		u.u_error = ENXIO;
		return;
	}
}

/*
 * The read routine just calls
 * off to the common raw I/O processing
 * code, using a static buffer header in
 * the driver.
 */

static
flread( dev, iop )

dev_t	dev;
IO	*iop;

{
	dmareq(&flbuf, iop, dev, BREAD);
}

/*
 * The write routine is just like the
 * read routine, except that the function code
 * is write instead of read.
 */

static
flwrite( dev, iop )

dev_t	dev;
IO	*iop;

{
	dmareq(&flbuf, iop, dev, BWRITE);
}

/*
 * The ioctl routine simply queues a format request
 * using flbuf.
 * The only valid command is to format a track.
 * The parameter block contains the header records supplied to the controller.
 */

static
flioctl( dev, com, par )

dev_t	dev;
int	com;
char	*par;

{
	register unsigned s;
	register struct fdata *fdp;
	unsigned hd, cyl;

	if (com != FDFORMAT) {
		u.u_error = EINVAL;
		return;
	}

	fdp = &fdata[ fkind(dev) ];
	cyl = getubd(par);
	hd  = getubd(par+1);

	if (hd > 1 || cyl >= fdp->fd_trks) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * The following may need some explanation.
	 * dmareq will:
	 *	claim the buffer,
	 *	bounds check the parameter buffer,
	 *	lock the parameter buffer in memory,
	 *	convert io_seek to b_bno,
	 *	dispatch the request,
	 *	wait for completion,
	 *	and unlock the parameter buffer.
	 * The b_bno is reconverted to hd, cyl in flfsm.
	 */

	s = fhbyh(dev) ? (cyl * fdp->fd_nhds + hd) : (hd * fdp->fd_trks + cyl);
	s *= fdp->fd_nspt;
	u.u_io.io_seek = ((long)s) * BSIZE;
	u.u_io.io_base = par;
	u.u_io.io_ioc = fdp->fd_nspt * 4;
	dmareq(&flbuf, &u.u_io, dev, FDFORMAT);
}

/*
 * Start up block I/O on a
 * buffer. Check that the block number
 * is not out of range, given the style of
 * the disk. Put the buffer header into the
 * device queue. Start up the disk if the
 * device is idle.
 */

static
flblock( bp )

register BUF	*bp;

{
	register int	s;
	register unsigned bno;

	bno = bp->b_bno + (bp->b_count >> 9) - 1;
	if ((unsigned)bp->b_bno > fdata[ fkind(bp->b_dev) ].fd_size) {
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}
	if (bp->b_req != FDFORMAT && bno >= fdata[ fkind(bp->b_dev) ].fd_size) {
		bp->b_resid = bp->b_count;
		if (bp->b_flag & BFRAW)
			bp->b_flag |= BFERR;
		bdone(bp);		/* return w/ b_resid != 0 */
		return;
	}

	if ((bp->b_count&0x1FF) != 0) {
		if (bp->b_req != FDFORMAT) {
			bp->b_flag |= BFERR;
			bdone(bp);
			return;
		}
	}

	bp->b_actf = NULL;
	s = sphi();	/* s was already == sphi() on at least PC/XT. */

	if (fl.fl_actf == NULL)
		fl.fl_actf = bp;
	else
		fl.fl_actl->b_actf = bp;

	fl.fl_actl = bp;

	if (fl.fl_state == SIDLE)
		flfsm();

	spl( s );
}

/*
 * This finite state machine is
 * responsible for all sequencing on the disk.
 * It builds the commands, does the seeks, spins up
 * the drive motor for 1 second on the first call,
 * and so on.
 * Note that the format command is rather obscurely shoehorned into this.
 */

static
flfsm()
{
	register BUF	*bp;
	register int	flcmd;
	register int	i;

again:
	bp = fl.fl_actf;

	switch (fl.fl_state) {

	case SIDLE:
		drvl[FL_MAJOR].d_time = 1;

		if ( bp == NULL )
			break;

		fl.fl_fd   = fdata[ fkind(bp->b_dev) ];
		fl.fl_unit = funit( bp->b_dev );
		fl.fl_hbyh = fhbyh( bp->b_dev );

		fl.fl_mask = 0x10 << fl.fl_unit;

		fl.fl_addr = bp->b_paddr;
		fl.fl_secn = bp->b_bno;
		fl.fl_time[fl.fl_unit] = 0;

		if ((fl.fl_nsec = bp->b_count>>9) == 0)
			fl.fl_nsec = 1;

		fl.fl_nerr = 0;

		/*
		 * Set data rate if changed.
		 * NOTE: XT never changes data rate.
		 */
		if ( (i = flrate(bp->b_dev)) != fl.fl_rate )
			outb(FDCRATE, fl.fl_rate = i );

		/*
		 * Motor is turned off - turn it on, wait 1 second.
		 */
		if ((fl.fl_mstatus&fl.fl_mask) == 0) {

			fl.fl_mstatus |= fl.fl_mask;
			outb(FDCDOR, DORNMR|DORIEN|fl.fl_mstatus|fl.fl_unit);
			flsense();

			timeout( &fltim, HZ, fldelay, SSEEK );
			fl.fl_time[fl.fl_unit] = 0;
			fl.fl_state = SDELAY;
			break;
		}
		/* no break */

	case SSEEK:
		fl.fl_time[fl.fl_unit] = 0;
		outb(FDCDOR, DORNMR|DORIEN|fl.fl_mstatus|fl.fl_unit);
		flsense();

		/*
		 * Drive is not calibrated - seek to track 0.
		 */
		if (fl.fl_incal[fl.fl_unit] == 0) {
			++fl.fl_incal[fl.fl_unit];
			flput(CMDRCAL);
			flput(fl.fl_unit);
			fl.fl_state = SSEEK;
			break;
		}

		fl.fl_fsec = (fl.fl_secn % fl.fl_fd.fd_nspt) + 1;

		/*
		 * Seek cylinder by cylinder (XENIX/DOS compatible).
		 */
		if (fl.fl_hbyh) {
	                fl.fl_head = fl.fl_secn / fl.fl_fd.fd_nspt;
			fl.fl_fcyl = fl.fl_head / fl.fl_fd.fd_nhds;
			fl.fl_head = fl.fl_head % fl.fl_fd.fd_nhds;
		}
		
		/*
		 * Seek surface by surface.
		 */
		else {
			fl.fl_fcyl = fl.fl_secn / fl.fl_fd.fd_nspt;
			fl.fl_head = fl.fl_fcyl / fl.fl_fd.fd_trks;
			fl.fl_fcyl = fl.fl_fcyl % fl.fl_fd.fd_trks;
		}

		flput(CMDSEEK);
		flput((fl.fl_head<<2) | fl.fl_unit);

		if ( fl.fl_fd.fd_trks == 80 )
			flput(fl.fl_fcyl);
		else if ( fl.fl_type[fl.fl_unit] == 2 )
			flput(fl.fl_fcyl << 1);		/* double step */
		else if ( fl.fl_type[fl.fl_unit] == 4 )
			flput(fl.fl_fcyl << 1);		/* double step */
		else
			flput(fl.fl_fcyl);

		fl.fl_state = SHDLY;
		break;

	case SHDLY:
		/*
		 * Delay for minimum 15 milliseconds after seek before w/fmt.
		 * 2 clock ticks would give 10-20 millisecond [100 Hz clock].
		 * 3 clock ticks gives      20-30 millisecond [100 Hz clock].
		 */
		if ( bp->b_req != BREAD ) {
			timeout( &fltim, 3, fldelay, SRDWR );
			fl.fl_state = SDELAY;
			break;
		}
		/* no break */

	case SRDWR:
		/*
		 * Disable watchdog timer while waiting to lock DMA controller.
		 */
		fl.fl_time[fl.fl_unit] = -1;

		/*
		 * Next state will be DMA locked state.
		 */
		fl.fl_state = SLOCK;

		/*
		 * If DMA controller locked by someone else, exit for now.
		 */
		if ( dmalock( &fldmalck, flfsm, 0 ) != 0 )
			return;

	case SLOCK:
		/*
		 * Reset watchdog timer to restart timeout sequence.
		 */
		fl.fl_time[fl.fl_unit] = 0;

		flcmd = CMDRDAT;
		fl.fl_wflag = 0;

		if (bp->b_req == BREAD)
			;

		else if (bp->b_req == BWRITE) {
			fl.fl_wflag = 1;
			flcmd = CMDWDAT;
		}
		
		else {
			fl.fl_wflag = 1;
			flcmd = CMDFMT;

			if(dmaon(2, fl.fl_addr, bp->b_count, fl.fl_wflag) == 0)
				goto straddle;

			else
				goto command;
		}

		if (dmaon(2, fl.fl_addr, 512, fl.fl_wflag) == 0) {
straddle:
			devmsg(bp->b_dev, "fd: DMA page straddle at %x:%x",
				fl.fl_addr);
			dmaunlock( &fldmalck );
			bp->b_flag |= BFERR;
			fldone( bp );
			goto again;
		}
command:
		dmago(2);
		flput(flcmd);
		flput((fl.fl_head<<2) | fl.fl_unit);

		if (bp->b_req == FDFORMAT) {
			flput(fl.fl_fd.fd_N);		/* N */
			flput(fl.fl_fd.fd_nspt);	/* SC */
			flput(fl.fl_fd.fd_FGPL);	/* GPL */
			flput(0xF6);			/* D */
		}
		
		else {
			flput(fl.fl_fcyl);
			flput(fl.fl_head);
			flput(fl.fl_fsec);
			flput(fl.fl_fd.fd_N);		/* N */
			flput(fl.fl_fd.fd_nspt);	/* EOT */
			flput(fl.fl_fd.fd_GPL[fl.fl_rate]); /* GPL */
			flput(0xFF);			/* DTL */
		}

		fl.fl_state = SENDIO;
		break;

	case SENDIO:
		fl.fl_time[fl.fl_unit] = 0;
		dmaoff(2);
		dmaunlock( &fldmalck );

		if ((fl.fl_cmdstat[0]&ST0_IC) != ST0_NT) {
			if (++fl.fl_nerr < 5) {
				fl.fl_incal[fl.fl_unit] = 0;
				fl.fl_state = SSEEK;
			}
			
			else {
				flstatus();
				bp->b_flag |= BFERR;
				fldone(bp);
			}
		}

		else if (--fl.fl_nsec == 0) {
			bp->b_resid = 0;
			fldone(bp);
		}
		
		else {
			++fl.fl_secn;
			fl.fl_addr += 512;	/* 512 == fl.fl_fd.fd_nbps */
			fl.fl_state = SSEEK;
		}

		/*
		 * Delay for minimum 1.5 msecs after writing before seek.
		 */
		if ( fl.fl_wflag ) {
			timeout( &fltim, 2, fldelay, fl.fl_state );
			fl.fl_state = SDELAY;
			break;
		}

		goto again;

	case SDELAY:
		/*
		 * Ignore interrupts until timeout occurs.
		 */
		break;

	default:
		panic("fds");
	}
}

/*
 * Delay before initiating next operation.
 * This allows the floppy motor to turn on,
 * the head to settle before writing,
 * the erase head to turn off after writing, etc.
 */
static
fldelay( state )
int state;
{
	int s;

	s = sphi();
	if ( fl.fl_state == SDELAY ) {
		fl.fl_state = state;
		flfsm();
	}
	spl( s );
}

/*
 * The flrate function returns the data rate for the flopen and flfsm routines.
 */
static int
flrate( dev )
register dev_t dev;
{
	register int rate;

	/*
	 * Default is 250 Kbps.
	 */
	rate = 2;

	/*
	 * Check for high capacity drive.
	 */
	if ( fl.fl_type[ funit(dev) ] == 2 ) {

		/*
		 * 300 Kbps.
		 */
		rate--;

		/*			       
		 * Check for high capacity media.
		 */
		if ( fdata[ fkind(dev) ].fd_nspt == 15 ) {

			/*
			 * 500 Kbps.
			 */
			rate--;
		}
	} else if (fl.fl_type[funit(dev)] == 4 && fkind(dev) == 7)
		rate = 0;

	return( rate );
}

/*
 * This routine is called by the
 * clock handler every second. If the drive
 * has been idle for a long time it turns off
 * the motor and shuts off the timeouts.
 */

static
fltimeout()
{
	register int	unit;
	register int	mask;
	register int	s;

	s = sphi();

	/*
	 * Scan all drives, looking for motor timeouts.
	 */
	for ( unit=0, mask=0x10; unit < 4; unit++, mask <<= 1 ) {

		/*
		 * Ignore drives which aren't spinning.
		 */
		if ( (fl.fl_mstatus & mask) == 0 )
			continue;

		/*
		 * If timer is disabled (i.e. we are waiting for the DMA
		 * controller), go on to the next drive.
		 */
		if ( fl.fl_time[unit] < 0 )
			continue;

		/*
		 * Leave recently accessed (in last 4 seconds) drives spinning.
		 */
		if ( ++fl.fl_time[unit] < MTIMER )
			continue;

		/*
		 * Timeout drives which have been inactive for 5 seconds.
		 */
		fl.fl_mstatus &= ~mask;

		/*
		 * Not selected drive, or selected drive is idle.
		 */
		if ( (unit != fl.fl_unit) || (fl.fl_state == SIDLE) )
			continue;

		/*
		 * Active drive did not complete operation within 5 seconds.
		 * Attempt recovery.
		 */
		flrecov();

		/*
		 * Initiate next block request.
		 */
		if ( fl.fl_state == SIDLE )
			flfsm();
	}

	/*
	 * Physically turn off drives which timed out.
	 */
	outb(FDCDOR, DORNMR | DORIEN | fl.fl_mstatus | fl.fl_unit);

	/*
	 * Stop checking once all drives have been stopped.
	 */
	if ( fl.fl_mstatus == 0 )
		drvl[FL_MAJOR].d_time = 0;

	spl(s);
}

/*
 * The recovery routine resets and reprograms the floppy controller,
 * and discards any queued requests on the current drive.
 * This is required if the floppy door is open, or diskette is missing.
 */

flrecov()
{
	register BUF * bp;
	register dev_t dev;

	/*
	 * Disable DMA transfer.
	 * Reset floppy controller.
	 */
	dmaoff( 2 );

	/*
	 * Unlock the controller if locked by us.
	 */
	dmaunlock( &fldmalck );

	outb(FDCDOR, 0);
	outb(FDCDOR, DORNMR);

	/*
	 * Program transfer bps.
	 */
	if ( fl.fl_rate != 2 )
		outb( FDCRATE, fl.fl_rate );

	/*
	 * Program floppy controller.
	 */
	flput( CMDSPEC );
	flput( (fl_srt << 4) | fl_hut );
	flput( fl_hlt << 1 );

	/*
	 * Drives are no longer in calibration.
	 */
	fl.fl_incal[0] =
	fl.fl_incal[1] =
	fl.fl_incal[2] =
	fl.fl_incal[3] = 0;

	/*
	 * Abort all block requests on current drive after 1st recov attempt.
	 */
	if ( bp = fl.fl_actf ) {
		printf("fd%d: <Door Open>\n", fl.fl_unit );
		dev = bp->b_dev;
		do {
			bp->b_flag |= BFERR;
			fldone( bp );
		} while ( (bp = fl.fl_actf) && (bp->b_dev == dev) );
	}

	/*
	 * Delay before setting controller state to idle.
	 * This gives time for spurious floppy interrupts to occur.
	 * NOTE: Can't call flfsm(), since it may call us [future revision].
	 */
	timeout( &fltim, HZ/4, fldelay, SIDLE );
	fl.fl_state = SDELAY;
}

/*
 * The interrupt routine gets all
 * the status bytes the controller chip
 * will give it, then issues a sense interrupt
 * status command (which is necessary for a seek
 * to complete!) and throws all of the status
 * bytes away.
 */

static
flintr()
{
	register int s;

	s = sphi();
	flsense();

	if (fl.fl_state != SIDLE)
		flfsm();

	spl(s);
}

/*
 * Fldone() returns current request to operating system.
 */
fldone( bp )
register BUF * bp;
{
	fl.fl_actf  = bp->b_actf;
	fl.fl_state = SIDLE;
	bdone( bp );
}

/*
 * Flsense() issues a sense interrupt status command
 * to restore the controller to a quiescent state.
 */

static
flsense()
{
	register int	b;
	register int	n;
	register int	i = 0;
	register int	s;

	s = sphi();

	/*
	 * Read all the status bytes the controller will give us.
	 */
	n = 0;

	for (;;) {
		while (((b=inb(FDCMSR))&MSRRQM) == 0) {
			if ( --i == 0 ) {
				printf("flintr: timeout\n");
				break;
			}
		}

		if ((b&MSRDIO) == 0)
			break;

		b = inb(FDCDAT);
		if ( n < sizeof(fl.fl_cmdstat) )
			fl.fl_cmdstat[n++] = b;
	}

	fl.fl_ncmdstat = n;

	/*
	 * Issue a sense interrupt command and discard result.
	 */
	outb(FDCDAT, CMDSINT);

	n = 0;
	for (;;) {
		while (((b=inb(FDCMSR))&MSRRQM) == 0) {
			if ( --i == 0 ) {
				printf("flsense: timeout\n");
				break;
			}
		}

		if ((b&MSRDIO) == 0)
			break;

		b = inb(FDCDAT);
		if ( n < sizeof(fl.fl_intstat) )
			fl.fl_intstat[n++] = b;
	}
	fl.fl_nintstat = n;

	spl( s );
}

/*
 * Send a command byte to the
 * NEC chip, first waiting until the chip
 * says that it is ready. No timeout is
 * performed; if the chip dies, we do too!
 */

static
flput( b )

int	b;

{
	register int i = 0;

	while ( (inb(FDCMSR) & (MSRRQM|MSRDIO)) != MSRRQM ) {
		if ( --i == 0 ) {
			printf("flput: timeout\n");
			return;
		}
	}

	outb(FDCDAT, b);
}

/*
 * Dissassemble the floppy error status for user reference.
 */

static
flstatus()
{
	printf("fd%d: head=%u cyl=%u",
		fl.fl_cmdstat[0] & 3,
		fl.fl_head, fl.fl_fcyl );

	/*
	 * Report on ST0 bits.
	 */
	if ( fl.fl_ncmdstat >= 1 ) {
		if ( fl.fl_cmdstat[0] & ST0_NR )
			printf(" <Not Ready>");

		if ( fl.fl_cmdstat[0] & ST0_EC )
			printf(" <Equipment Check>");
	}

	/*
	 * Report on ST1 bits.
	 */
	if ( fl.fl_ncmdstat >= 2 ) {
		if ( fl.fl_cmdstat[1] & ST1_MA )
			printf(" <Missing Address Mark>");

		if ( fl.fl_cmdstat[1] & ST1_NW )
			printf(" <Write Protected>");

		if ( fl.fl_cmdstat[1] & ST1_ND )
			printf(" <No Data>");

		if ( fl.fl_cmdstat[1] & ST1_OR )
			printf(" <Overrun>");

		if ( fl.fl_cmdstat[1] & ST1_DE )
			printf(" <Data Error>");

		if ( fl.fl_cmdstat[1] & ST1_EN )
			printf(" <End of Cyl>");
	}

	/*
	 * Report on ST2 bits.
	 */
	if ( fl.fl_ncmdstat >= 3 ) {
		if ( fl.fl_cmdstat[2] & ST2_MD )
			printf(" <Missing Data Address Mark>");

		if ( fl.fl_cmdstat[2] & ST2_BC )
			printf(" <Bad Cylinder>");

		if ( fl.fl_cmdstat[2] & ST2_WC )
			printf(" <Wrong Cylinder>");

		if ( fl.fl_cmdstat[2] & ST2_DD )
			printf(" <Bad Data CRC>");

		if ( fl.fl_cmdstat[2] & ST2_CM )
			printf(" <Data Deleted>");
	}

	printf("\n");
}
0707070064030050561006440000030000030000011777770507310633100005300000003427/newbits/kernel/USRSRC/i8086/drv/fontgen.c/*
 * fontgen - generate 16x8 font assembler source on stdout.
 */

#define	BIT(n)	(1 << (n))
#define	BITS(n)	(((n) >= 4) ? (3 << (((n) - 4) * 2)) : (3 << (((n) + 4) * 2)))

unsigned char ibuf[1024];
unsigned char odef[] = "\tB________ = 0000000\n";
unsigned char obuf[] = "\t.word\tB________\n";

main()
{
	register unsigned s;
	register unsigned j;
	register unsigned i;
	extern long lseek();

	/*
	 * Read fonts from /dev/mem at offset 0xFFA6E.
	 */
	close(0);
	if (open("/dev/mem", 0) != 0)
		fatal("/dev/mem: can't open\n");
	if (lseek( 0, 0xFFA6EL, 0) != 0xFFA6EL)
		fatal("/dev/mem: can't seek to fonts");
	if (read( 0, ibuf, sizeof ibuf ) != sizeof ibuf)
		fatal("/dev/mem: can't read fonts");

	/*
	 * Define symbolic constants.
	 */
	for (i=0; i < 256; ++i) {
		/* Generate constant's name. */
		s = i;
		for (j=10; --j >= 2; s>>=1)
			odef[j] = (s&1) ? 'X' : '_';

		/* Convert 8 pixel width to 16 pixels */
		s = 0;
		for (j=0; j < 8; ++j)
			if (i & BIT(j))
				s |= BITS(j);

		/* Generate constant's value */
		for (j=19; j >= 14; --j) {
			odef[j] = (s & 7) + '0';
			s >>= 3;
		}

		/* Print constant's name and value */
		send( odef );
	}
	send( "\n\t.globl\tfontw_\nfontw_:" );

	/*
	 * Define fonts for 128 characters.
	 */
	for (i=0; i < sizeof ibuf; ++i) {

		/* Format and print one pixel line */
		j = 16;
		s = ibuf[i];
		while ( --j >= 8 ) {
			obuf[j] = (s&1) ? 'X' : '_' ;
			s >>= 1;
		}
		send( obuf );

		/* Insert blank line between characters for readability */
		if ( (i & 7) == 7 )
			send( "\n" );
	}
	exit( 0 );
}

/*
 * Fatal( msg ) - report error, and abort.
 */

fatal( msg )
register char *msg;
{
	write( 2, msg, strlen(msg) );
	exit( 1 );
}

/*
 * send( s ) - write null-terminated string to standard output.
 */

send( s )
register char *s;
{
	write( 1, s, strlen(s) );
}
0707070064030050571006440000030000030000011777770507310633200004600000022311/newbits/kernel/USRSRC/i8086/drv/gc.c/*
 * Interrupt Driver Multi-Port Device Driver.
 * - supports version 7 compatible ioctl
 */

#include "coherent.h"
#include "ins8250.h"
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/proc.h>
#include <sys/tty.h>		/* indirectly includes sgtty.h */
#include <sys/con.h>
#include <errno.h>
#include <sys/timeout.h>	/* TIM */
#include <sched.h>		/* CVTTOUT, IVTTOUT, SVTTOUT */
#include <poll_clk.h>

/*
 * Definitions.
 *
 * MAX_GCNUM is the maximum number of devices that can be polled
 *   using this driver and can be revised up or down
 * PORT is a convenience macro for the base address of a port
 * port_config is the structure of the initial configuration for each
 *   polled port;  note that "speed" is NOT the actual baud rate, but
 *   the value of the symbol for that baud rate as defined in
 *   /usr/include/sgtty.h
 * GCINT is the IRQ number for the interrupt belonging to the board.
 *   On the AT, IRQ2 is mapped to the same vector as IRQ9.
 */
#define MAX_GCNUM	8
#define	PORT	((int)(tp->t_ddp))
struct port_config {
	int	addr;	/* base address of the 8250-family UART */
	int	speed;	/* B0..B19200 */
};
#define GCINT		2

/*
 * Export Variables - these can be patched without recompiling and linking
 *
 * GCNUM is the actual number of polled serial ports, and should be
 *   less than or equal to MAX_GCNUM
 * GCIRPT is the I/O address of the multiport interrupt register;
 *   a value of 0 in bit 0..3 means a pending interrupt for port 0..3
 * GC_PORTS is an array of address/speed pairs, one for each port
 */
int	GCNUM = 4;
int	GCIRPT = 0x2BF;
/*
 * Defaults are for PC COM4, Enhanced Mode, High Address.
 */
struct port_config GC_PORTS[MAX_GCNUM] = {
	{ 0x2A0, B9600 },
	{ 0x2A8, B9600 },
	{ 0x2B0, B9600 },
	{ 0x2B8, B9600 }
};

/*
 * Export Functions.
 */
int	gcload();
int	gcopen();
int	gcclose();
int	gcread();
int	gcwrite();
int	gcioctl();
int	gcunload();
int	gcpoll();

int	gccycle();
int	gcintr();
int	gcparam();
int	gcstart();

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON gccon ={
	DFCHR|DFPOL,			/* Flags */
	GCINT,				/* Major index */
	gcopen,				/* Open */
	gcclose,			/* Close */
	nulldev,			/* Block */
	gcread,				/* Read */
	gcwrite,			/* Write */
	gcioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	gcload,				/* Load */
	gcunload,			/* Unload */
	gcpoll				/* Poll */
};

/*
 * Local variables.
 */
static TTY *hstty;
static TTY *hslimtty;
static TIM hstim;

/*
 * Time constant table.
 * Indexed by ioctl baud rate.
 */
static
int timeconst[] = {
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	6,				/* EXTA */
	6				/* EXTB */
};

/*
 * Load Routine.
 */
static gcload()
{
	register TTY * tp;
	register int port;
	int i, b, s;

	if ((hstty = (TTY *)kalloc(GCNUM*sizeof(TTY))) == 0) {
		printf("gcload: can't allocate tty's\n");
		return;
	}
	kclear(hstty, GCNUM*sizeof(TTY));

	s = sphi();
	for (i = 0; i < GCNUM; i++) {
		port = GC_PORTS[i].addr;
		tp = hstty + i;

		outb( port+MCR, 0 );
		outb( port+IER, 0 );

		if ( inb( port+IER ) )
			break;

		tp->t_cs_sel  = cs_sel();
		tp->t_start   = gcstart;
		tp->t_param   = gcparam;
		tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
		tp->t_dispeed = tp->t_dospeed = GC_PORTS[i].speed;
		tp->t_ddp     = port;

		b = timeconst[ tp->t_sgttyb.sg_ospeed ];
		outb( port+LCR, LC_DLAB );
		outb( port+DLL, b );
		outb( port+DLH, b >> 8);
		outb( port+LCR, LC_CS8);

		hslimtty = tp;
	}
	setivec(GCINT, gcintr);
	spl(s);
}

static gcunload()
{
	clrivec(GCINT);
	kfree(hstty);
}

/*
 * Open Routine.
 */
gcopen( dev, mode )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];
	register int b;
	int s;

	/*
	 * Verify hardware exists.
	 */
	if ( (PORT == 0) || (inb(PORT+IER) & ~IE_TxI) ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Initialize if not already open.
	 */
	if ( ++tp->t_open == 1 ) {
		ttopen( tp );

		if ( dev & 0x80 ) {
			s = sphi();
			b = inb(PORT+MSR);
			tp->t_flags |= T_MODC + T_STOP;
			if ( b & MS_CTS )
				tp->t_flags &= ~T_STOP;
			if ( b & MS_DSR )
				tp->t_flags |=  T_CARR;
			spl( s );
		} else  {
			tp->t_flags &= ~T_MODC;
			tp->t_flags |=  T_CARR;
		}
		gccycle( tp );
	}
	ttsetgrp( tp, dev );
}

/*
 * Close Routine.
 */
gcclose( dev )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];

	/*
	 * Reset if last close.
	 */
	if ( tp->t_open == 1 ) {
		int state;

		ttclose( tp );
		/*
		 * ttclose() only emptied the output queue tp->t_oq;
		 * now wait 0.1 sec for the silo tp->rawout to empty
		 * and allow a delay for the UART on-chip xmit buffer to empty
		 *
		 * state 2: waiting for silo to empty
		 * state 1: stalling so UART can empty xmit buffer
		 * state 0: done!
		 */
		state = 2;
		while (state) {
			timeout(&hstim, 10, wakeup, (int)&hstim);
			sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
			if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
				state--;
		}
	}

	--tp->t_open;
}

/*
 * Read Routine.
 */
gcread( dev, iop )
dev_t dev;
register IO * iop;
{
	ttread( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Write Routine.
 */
gcwrite( dev, iop )
dev_t dev;
register IO * iop;
{
	ttwrite( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Ioctl Routine.
 */
gcioctl( dev, com, vec )
dev_t dev;
int com;
struct sgttyb * vec;
{
	ttioctl( &hstty[ dev & 15 ], com, vec );
}

/*
 * Polling Routine.
 */
gcpoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	return ttpoll( &hstty[ dev & 15 ], ev, msec );
}

/*
 * Cyclic routine - invoked every clock tick to perform raw input/output.
 *
 *	Notes:	Invoked 10 times per second.
 */
gccycle( tp )
register TTY * tp;
{
	register int resid;
	register int c;

	/*
	 * Process rawin buf.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}

	/*
	 * Calculate free output slot count.
	 */
	resid  = sizeof(tp->t_rawout.si_buf) - 1;
	resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	resid %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--resid >= 0) && ((c = ttout(tp)) >= 0) ) {

		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;

		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, waking processes waiting to output, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	if ( tp->t_open != 0 )
		timeout( &tp->t_rawtim, HZ/10, gccycle, tp );
}

/*
 * Interrupt driven Polling routine.
 */
gcintr()
{
	register TTY * tp = &hstty[0];
	register int b;

	do {
		if ( tp->t_open == 0 )
			continue;

		/*
		 * Check modem status if modem control is enabled.
		 */
		if ( tp->t_flags & T_MODC ) {

			b = inb( PORT+MSR );

			if ( b & (MS_DCTS|MS_DDSR) ) {

				if ( b & MS_DCTS ) {
					if ( b & MS_CTS )
						tp->t_flags &= ~T_STOP;
					else
						tp->t_flags |=  T_STOP;
				}
				if ( b & MS_DDSR ) {
					if ( b & MS_DSR )
						tp->t_flags |=  T_CARR;
					else {
						tp->t_flags &= ~T_CARR;
						tthup( tp );
					}
				}
			}
		}

		b = inb( PORT+LSR );

		if ( (b & LS_BREAK) && (tp->t_flags & T_CARR) )
			ttsignal( tp, SIGINT );

		/*
		 * Receive ready.
		 */
		if ( b & LS_RxRDY ) {

			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(PORT+DREG);

			if ( tp->t_flags & T_CARR ) {

				if ( ++(tp->t_rawin.si_ix) >=
						sizeof(tp->t_rawin.si_buf) )
					tp->t_rawin.si_ix = 0;
			}
		}

		/*
		 * Transmit ready and raw output data exists.
		 */
		if ( (b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
		  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

			outb(	PORT+DREG,
				tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

			if ( ++(tp->t_rawout.si_ox) >=
					sizeof(tp->t_rawout.si_buf) )
				tp->t_rawout.si_ox = 0;
		}

	} while ( ++tp <= hslimtty );
}

/*
 * Set hardware parameters.
 */
gcparam( tp )
register TTY * tp;
{
	register int b;
	int s;

	s = sphi();
	/*
	 * Assert required modem control lines (DTR, RTS).
	 */
	b = 0;
	if ( tp->t_sgttyb.sg_ospeed != B0 )
		b |=  MC_DTR | MC_RTS;
	outb( PORT+MCR, b );

	/*
	 * Program baud rate.
	 */
	if (b = timeconst[ tp->t_sgttyb.sg_ospeed ]) {
		outb( PORT+LCR, LC_DLAB );
		outb( PORT+DLL, b );
		outb( PORT+DLH, b >> 8 );
	}

	/*
	 * Program character size, parity.
	 */
	switch ( tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW) ) {
	case ODDP:		b = LC_CS7|LC_PARENB;		 break;
	case EVENP:		b = LC_CS7|LC_PARENB|LC_PAREVEN; break;
	default:		b = LC_CS8;			 break;
	}
	outb( PORT+LCR, b );

	/*
	 * Enable Transmit Buffer Empty Interrupts.
	 */
	outb( PORT+IER, IE_TxI );

	spl(s);
}

/*
 * Start Routine.
 */
gcstart( tp )
register TTY * tp;
{
	register int s;

	/*
	 * Transmit buffer is empty, and raw output buffer is not.
	 */
	s = sphi();
	if ( (inb( PORT+LSR ) & LS_TxRDY)
	  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

		/*
		 * Send next char from raw output buffer.
		 */
		outb( PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}
0707070064030050551004440000030000030000011777770507310633400004600000001521/newbits/kernel/USRSRC/i8086/drv/gr.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Graphics Display Driver for PC Color Card
 */

#include <sys/coherent.h>
#include <sys/sched.h>
#include <sys/types.h>
#include <sys/uproc.h>
#include <errno.h>
#include <sys/con.h>
#include <sys/devices.h>

int grread();
int grwrite();
int nonedev();
int nulldev();

/*
 * Driver Configuration.
 */
CON
grcon = {
	DFCHR,				/* Flags			  */
	GR_MAJOR,				/* Major Index			  */
	nulldev,			/* Open				  */
	nulldev,			/* Close			  */
	nonedev,			/* Block			  */
	grread,				/* Read				  */
	grwrite,			/* Write			  */
	nonedev,			/* Ioctl			  */
	nulldev,			/* Power fail			  */
	nulldev,			/* Timeout			  */
	nulldev,			/* Load				  */
	nulldev				/* Unload			  */
};
0707070064030034631006440000000000000000011777770507310633400005000000074531/newbits/kernel/USRSRC/i8086/drv/mmas.m/ (lgl-
/ 	COHERENT Driver Kit Version 1.0.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/	Memory mapped video driver assembler assist.
/
////////
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal information
/		CX    - input count
/		BP    - references terminal information
/		AH    - character attributes
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
////////

	NCOL	= 80		/ number of columns
	NCB	= 2		/ number of horizontal bytes per char
	NCR	= 1		/ number of horizontal lines per char
	NHB	= 160		/ number of horizontal bytes per line
	NRB	= NCR*NHB	/ number of bytes per character row

	ATTR	= ah		/ attribute byte
	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	INTENSE	= 0x08		/ high intensity attribute bit
	BLINK	= 0x80		/ blinking attribute bit
	REVERSE	= 0x70		/ reverse video

////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_BASE	= 8

	IOSYS	= 0
	IOUSR	= 1

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_INVIS	= 20		/ cursor invisible mask
MM_SLOW		= 22		/ slow [no flicker] video update
MM_WRAP		= 23		/ wrap to start of next line

/ Characters
AZERO		= 0x30
CLOWER		= 0x63
HLOWER		= 0x68
LLOWER		= 0x6C
SEMIC		= 0x3B
SPACE		= 0x20

	.globl	VIDSLOW_	/ Patchable kernel variable.
	.prvd
mmdata:	.word	mminit
	.word	0x03B4
	.word	0xB000
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, 23, 24, 0, 0, 0, 23
	.word	0
VIDSLOW_:.byte	0
	.byte	1
	.shri

////////
/
/ mmgo( iop )
/ IO *iop;
/
////////

	.globl	mmgo_

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc

	cmp	IO_SEG(bx), $IOSYS	/ user address space
	je	0f
	mov	bx, uds_
	mov	ds, bx
0:
	mov	bp, $mmdata
	mov	dx, MM_PORT(bp)		/ turn video off if color board
	cmp	dx, $0x3B4
	je	3f
	cmpb	MM_SLOW(bp), $0		/ check for slow [flicker-free]
	je	2f

	mov	dx, $0x3DA
1:	inb	al, dx			/ wait for vertical retrace
	testb	al, $8
	je	1b
2:
	mov	dx, $0x3D8		/ disable video
	movb	al, $0x25
	outb	dx, al
3:
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	sub	bx, bx
	movb	ATTR, MM_ATTR(bp)
	ijmp	MM_FUNC(bp)

exit:	pop	bx
	pop	es
	pop	ds
	movb	MM_ATTR(bp), ATTR
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, MM_PORT(bp)		/ adjust cursor location
	mov	bx, POS
	or	bx, MM_INVIS(bp)
	shr	bx, $1

	movb	al, $14
	outb	dx, al
	inc	dx
	movb	al, bh
	outb	dx, al
	dec	dx
	movb	al, $15
	outb	dx, al
	inc	dx
	movb	al, bl
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ turn video on
	add	dx, $4
	movb	al, $0x29
	outb	dx, al
	mov	mmvcnt_, $600		/ 600 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret


////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $CLOWER		/ schedule keyboard initialization
	call	int11_			/ read equipment status
	and	ax, $0x30		/ isolate video bits
	cmp	ax, $0x30		/ if not monochrome
	je	0f
	mov	MM_PORT(bp), $0x3D4	/	set color port
	mov	MM_BASE(bp), $0xB800	/	set color base
	mov	es, MM_BASE(bp)		/
0:					/
	mov	dx, MM_PORT(bp)		/ turn video off
	add	dx, $4
	movb	al, $0x21
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ zero display offset
	movb	al, $12
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al
	dec	dx
	movb	al, $13
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ reset border to black
	add	dx, $5
	subb	al, al
	outb	dx, al

	inc	dx			/ reset TECMAR XMSR register
	outb	dx, al

	mov	MM_INVIS(bp), $0
	movb	ATTR, $0x07
	movb	MM_ATTR(bp), ATTR
	movb	MM_WRAP(bp), $1
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ mmspec - schedule special keyboard function
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	cld
	rep
	movsw
	movb	al, $SPACE
	pop	di
	mov	cx, $NCOL
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, cs:rowtab(bx)
	call	exit
	jmp	eval

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, cs:rowtab(bx)
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	stosw				/ Update display memory.
	incb	COL
	cmpb	COL, $NCOL		/ Past end of line?
	jge	0f
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	cmpb	MM_WRAP(bp), $0		/ Yes past, Wrap around?
	jne	0f
	sub	di, $2			/ No wrap, adjust back to end of line.
	decb	COL
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	subb	COL, COL		/ Wrap to next line.
	incb	ROW
	cmpb	ROW, MM_EROW(bp)	/ Past scrolling region?
	jg	0f
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	movb	ROW, MM_EROW(bp)	/ Yes past, scroll up 1 line.
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	sub	POS, $2
	decb	COL
	jge	0f
	movb	COL, $NCOL-1
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
0:	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $SEMIC
	je	csi_n2
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

0:	cmpb	al, $HLOWER
	je	mm_cgh
	cmpb	al, $LLOWER
	je	mm_cgl
	jmp	eval

////////
/
/ Csi_q state - entered after input sequence ESC [ ?
/	
////////

0:	call	exit
csi_q:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_q

0:	cmpb	al, $HLOWER
	je	mm_cqh
	cmpb	al, $LLOWER
	je	mm_cql
	jmp	eval

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jg	0f
	subb	COL, COL		/ cannot step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process ESC [ > N1 h escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process ESC [ > N1 l escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	decb	COL
	jge	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	push	cx
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl
	movb	al, $SPACE
	rep
	stosw
	pop	cx
	cmpb	COL, $NCOL
	jb	0f
	subb	COL, $NCOL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	eval

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cqh - process ESC [ ? N1 h escape sequence
/
/	Recognized sequences:	ESC [ ? 4 h	-- Set smooth scroll.
/				ESC [ ? 7 h	-- Set wraparound.
/
////////

mm_cqh:	cmpb	MM_N1(bp), $4		/ Smooth scroll.
	jne	0f
	movb	MM_SLOW(bp), $1
0:	cmpb	MM_N1(bp), $7		/ Wraparound.
	jne	0f
	movb	MM_WRAP(bp), $1
0:	jmp	eval

////////
/
/ mm_cql - process ESC [ ? N1 l escape sequence
/
/	Recognized sequences:	ESC [ ? 4 l	-- Set jump scroll.
/				ESC [ ? 7 l	-- Reset wraparound.
/
////////

mm_cql:	cmpb	MM_N1(bp), $4		/ Jump scroll.
	jne	0f
	movb	MM_SLOW(bp), $0
0:	cmpb	MM_N1(bp), $7		/ No wraparound.
	jne	0f
	movb	MM_WRAP(bp), $0
0:	jmp	eval

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, $NCOL
	jb	0f
	subb	COL, $NCOL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, $NCOL-1
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter (mm_n1) specifies the vertical position (MM_ROW(bp)).
/	The second parameter (mm_n2) specifies the horizontal position (MM_COL(bp)).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	rep
	movsw
	mov	di, cs:rowtab(bx)
	mov	cx, $NCOL
	movb	al, $SPACE
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input, and causing cursor to vanish.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2


////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

mm_e2:	push	cx
	movb	al, $SPACE
0:	mov	cx, $NCOL
	rep
	stosw
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

mm_e1:	push	cx
	mov	cx, POS
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

mm_e0:	push	cx
	shlb	bl, $1
	mov	cx, cs:rowtab+2(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, cs:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, cs:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, cs:rowtab(bx)
	jle	0f
	shr	cx, $1
	std
	rep
	movsw
	mov	di, cs:rowtab(bx)
	mov	cx, $NCOL
	movb	al, $SPACE
	cld
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	 MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_INVIS(bp), $0
	jmp	eval

0:	mov	MM_INVIS(bp), $-1
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					5 - slow blink
/					7 - reverse video
/					8 - concealed on
/					30-37 - foreground color
/					40-47 - background color
/					50-57 - border color
/
////////

mm_sgr:	movb	al, MM_N1(bp)

	cmpb	al, $0			/ reset all = 0
	jne	0f
	movb	ATTR, $0x07
1:	jmp	eval

0:	cmpb	al, $1			/ bold = 1
	jne	0f
	orb	ATTR, $INTENSE
	jmp	1b

0:	cmpb	al, $4			/ underline = 4
	jne	0f
	cmp	MM_PORT(bp), $0x03D4	/ color card?
	je	1b			/ yes, ignore underline
	andb	ATTR, $~0x77
	orb	ATTR, $0x01
	jmp	1b

0:	cmpb	al, $5			/ blinking = 5
	jne	0f
	orb	ATTR, $BLINK
	jmp	1b

0:	cmpb	al, $7			/ reverse video = 7
	jne	0f
	movb	al, $0x70
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f
	movb	al, ATTR		/ yes, exchange foreground/background
	andb	al, $0x77
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
2:	andb	ATTR, $~0x77
	orb	ATTR, al
	jmp	1b

0:	cmpb	al, $8			/ concealed on = 8
	jne	0f
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f

	andb	ATTR, $0x70		/ Yes,	Set foreground color
	movb	al, ATTR		/	to background color.
	rorb	al, $1
	rorb	al, $1
	rorb	al, $1
	rorb	al, $1
	orb	ATTR, al
	jmp	1b

2:	andb	ATTR, $0x80		/ No, set attributes to non-display.
	jmp	1b			/	retain blink attribute.

0:	cmp	MM_PORT(bp), $0x03D4	/ color card?
	jne	1b			/ no, ignore remaining options
0:	subb	al, $30			/ foreground color
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x07
	orb	ATTR, cs:fcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x70
	orb	ATTR, cs:bcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	movb	al, cs:fcolor(bx)
	push	dx
	mov	dx, MM_PORT(bp)
	add	dx, $5
	outb	dx, al
	pop	dx
/	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	mmbell	/* EOT  ENQ  ACK  BEL  */
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/* BS   HT   LF   VT   */
	.word	eval,	mm_cr,	eval,	eval	/* FF   CR   SO   SI   */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3  */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	mm_esc	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/*   ! " # \040 - \043 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* $ % & quote \044 - \047 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ( ) * + \050 - \053 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* , - . / \054 - \057 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 0 1 2 3 \060 - \063 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 4 5 6 7 \064 - \067 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 8 9 : ; \070 - \073 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* < = > ? \074 - \077 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* @ A B C \100 - \103 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* D E F G \104 - \107 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* H I J K \110 - \113 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* L M N O \114 - \117 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* P Q R S \120 - \123 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* T U V W \124 - \127 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* X Y Z [ \130 - \133 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* \ ] ^ _ \134 - \137 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ` a b c \140 - \143 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* d e f g \144 - \147 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* h i j k \150 - \153 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* l m n o \154 - \157 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* p q r s \160 - \163 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* t u v w \164 - \167 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* x y z { \170 - \173 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* | } ~ ? \174 - \177 */

////////
/
/ esctab - table of functions indexed by ESC characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/* NUL  SOH  STX  ETX  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* EOT  ENQ  ACK  BEL  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* BS   HT   LF   VT   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FF   CR   SO   SI   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DLE  DC1  DC2  DC3  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DC4  NAK  SYN  ETB  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* CAN  EM   SUB  ESC  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	mm_new	/* 4 5 6 7 \064 - \067 */
	.word	mm_old,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	mmspec,	mmspec,	eval	/* < = > ? \074 - \077 */
	.word	eval,	eval,	eval,	eval	/* @ A B C \100 - \103 */
	.word	mm_ind,	mm_cnl,	eval,	eval	/* D E F G \104 - \107 */
	.word	eval,	eval,	eval,	eval	/* H I J K \110 - \113 */
	.word	eval,	mm_ri,	eval,	eval	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	eval	/* P Q R S \120 - \123 */
	.word	eval,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	eval,	csi_n1	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_dmi,	eval,	mm_emi,	mminit	/* ` a b c \140 - \143 */
	.word	eval,	eval,	eval,	eval	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	eval,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	eval,	eval	/* p q r s \160 - \163 */
	.word	mmspec,	mmspec,	eval,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */


////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	eval	/* EOT  ENQ  ACK  BEL  */
	.word	eval,	eval,	eval,	eval	/* BS   HT   LF   VT   */
	.word	eval,	eval,	eval,	eval	/* FF   CR   SO   SI   */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3  */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	eval	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	eval	/* 4 5 6 7 \064 - \067 */
	.word	eval,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	eval,	csi_gt,	csi_q	/* < = > ? \074 - \077 */
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/* @ A B C \100 - \103 */
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/* D E F G \104 - \107 */
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/* H I J K \110 - \113 */
	.word	mm_il,	mm_dl,	eval,	mm_ea	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	mm_ind	/* P Q R S \120 - \123 */
	.word	mm_ri,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	mm_cbt,	eval	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_hpa,	mm_hpr,	eval,	eval	/* ` a b c \140 - \143 */
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	mm_sgr,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	mm_ssr,	eval	/* p q r s \160 - \163 */
	.word	eval,	eval,	mm_scr,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ coltab - integer array of offsets to each column
/
////////

coltab:	.word	 0*NCB,	 1*NCB,	 2*NCB,	 3*NCB
	.word	 4*NCB,	 5*NCB,	 6*NCB,	 7*NCB
	.word	 8*NCB,	 9*NCB,	10*NCB,	11*NCB
	.word	12*NCB,	13*NCB,	14*NCB,	15*NCB
	.word	16*NCB,	17*NCB,	18*NCB,	19*NCB
	.word	20*NCB,	21*NCB,	22*NCB,	23*NCB
	.word	24*NCB,	25*NCB,	26*NCB,	27*NCB
	.word	28*NCB,	29*NCB,	30*NCB,	31*NCB
	.word	32*NCB,	33*NCB,	34*NCB,	35*NCB
	.word	36*NCB,	37*NCB,	38*NCB,	39*NCB
	.word	40*NCB,	41*NCB,	42*NCB,	43*NCB
	.word	44*NCB,	45*NCB,	46*NCB,	47*NCB
	.word	48*NCB,	49*NCB,	50*NCB,	51*NCB
	.word	52*NCB,	53*NCB,	54*NCB,	55*NCB
	.word	56*NCB,	57*NCB,	58*NCB,	59*NCB
	.word	60*NCB,	61*NCB,	62*NCB,	63*NCB
	.word	64*NCB,	65*NCB,	66*NCB,	67*NCB
	.word	68*NCB,	69*NCB,	70*NCB,	71*NCB
	.word	72*NCB,	73*NCB,	74*NCB,	75*NCB
	.word	76*NCB,	77*NCB,	78*NCB,	79*NCB

////////
/
/ rowtab - array of offsets to each row
/
////////

rowtab:	.word	 0*NRB,	 1*NRB,	 2*NRB,	 3*NRB
	.word	 4*NRB,	 5*NRB,	 6*NRB,	 7*NRB
	.word	 8*NRB,	 9*NRB,	10*NRB,	11*NRB
	.word	12*NRB,	13*NRB,	14*NRB,	15*NRB
	.word	16*NRB,	17*NRB,	18*NRB,	19*NRB
	.word	20*NRB,	21*NRB,	22*NRB,	23*NRB
	.word	24*NRB,	25*NRB,	26*NRB,	27*NRB
	.word	28*NRB,	29*NRB,	30*NRB,	31*NRB

////////
/
/ fcolor - foreground color
/ bcolor - background color
/
/	indexed by ansi color (black,red,green,brown,blue,magenta,cyan,white)
/	yields graphics color (black,blue,green,cyan,red,magenta,brown,white)
/		which is properly shifted for installation in attribute byte.
/
////////

fcolor:	.byte	0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
bcolor:	.byte	0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70

////////
/
/ mm_voff()	-- turn video display off
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, mmdata+MM_PORT
	add	dx, $4
	movb	al, $0x21
	outb	dx, al
	ret

////////
/
/ mm_von()	-- turn video display on
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, mmdata+MM_PORT	/ enable video display
	add	dx, $4
	movb	al, $0x29
	outb	dx, al
	mov	mmvcnt_, $900		/ 900 seconds before video disabled
	ret
0707070064030050601006440000030000030000011777770507310634200004600000026510/newbits/kernel/USRSRC/i8086/drv/hs.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Polled Serial Port Device Driver.
 * - supports version 7 compatible ioctl
 */

#include <sys/coherent.h>
#include <sys/ins8250.h>
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/proc.h>
#include <sys/tty.h>		/* indirectly includes sgtty.h */
#include <sys/con.h>
#include <sys/devices.h>
#include <errno.h>
#include <sys/sched.h>		/* CVTTOUT, IVTTOUT, SVTTOUT */
#include <sys/poll_clk.h>

/*
 * Definitions.
 *
 * HSBAUD is the highest baud rate supported by this driver
 * HS_HZ is the polling rate, i.e. the number of times per second
 *   at which all open ports are checked for input, output, and
 *   line status changes
 * MAX_HSNUM is the maximum number of devices that can be polled
 *   using this driver and can be revised up or down
 * PORT is a convenience macro for the base address of a port
 * port_config is the structure of the initial configuration for each
 *   polled port;  note that "speed" is NOT the actual baud rate, but
 *   the value of the symbol for that baud rate as defined in
 *   /usr/include/sgtty.h
 */
#define	HSBAUD	9600
#define	HS_HZ	(HSBAUD/6)
#define MAX_HSNUM	8
#define	PORT	((int)(tp->t_ddp))
struct port_config {
	int	addr;	/* base address of the 8250-family UART */
	int	speed;	/* B0..B19200 */
};

/*
 * Export Variables - these can be patched without recompiling and linking
 *
 * HSNUM is the actual number of polled serial ports, and should be
 *   less than or equal to MAX_HSNUM
 * HS_PORTS is an array of address/speed pairs, one for each port
 */
int	HSNUM = 4;
struct port_config HS_PORTS[MAX_HSNUM] = {
	{ 0x3F8, B9600 },
	{ 0x2F8, B9600 },
	{ 0x3E8, B9600 },
	{ 0x2E8, B9600 }
};

/*
 * Export Functions.
 */
int	hsload();
int	hsopen();
int	hsclose();
int	hsread();
int	hswrite();
int	hsioctl();
int	hsunload();
int	hspoll();

int	hscycle();
int	hsintr();
int	hsparam();
int	hsstart();
int	hsclk();
int	set_poll_rate();

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON hscon ={
	DFCHR|DFPOL,			/* Flags */
	HS_MAJOR,			/* Major index */
	hsopen,				/* Open */
	hsclose,			/* Close */
	nulldev,			/* Block */
	hsread,				/* Read */
	hswrite,			/* Write */
	hsioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	hsload,				/* Load */
	hsunload,			/* Unload */
	hspoll				/* Poll */
};

/*
 * Local variables.
 */
static TTY *hstty;
static TTY *hslimtty;
static TIM hstim;
static int poll_divisor;	/* used in hsclk() and set_poll_rate() */

/*
 * Time constant table.
 * Indexed by ioctl baud rate.
 */
static
int timeconst[] = {
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	6,				/* EXTA */
	6				/* EXTB */
};

/*
 * poll_hz[] is tied to timeconst[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int poll_hz[] ={
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 * Load Routine.
 */
static hsload()
{
	register TTY * tp;
	register int port;
	int i, b;

	if ((hstty = (TTY *)kalloc(HSNUM*sizeof(TTY))) == 0) {
		printf("hsload: can't allocate tty's\n");
		return;
	}
	kclear(hstty, HSNUM*sizeof(TTY));

	for (i = 0; i < HSNUM; i++) {
		port = HS_PORTS[i].addr;
		tp = hstty + i;

		outb( port+MCR, 0 );
		outb( port+IER, 0 );

		if ( inb( port+IER ) )
			break;

		tp->t_cs_sel  = cs_sel();
		tp->t_start   = hsstart;
		tp->t_param   = hsparam;
		tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
		tp->t_dispeed = tp->t_dospeed = HS_PORTS[i].speed;
		tp->t_ddp     = port;

		b = timeconst[ tp->t_sgttyb.sg_ospeed ];
		outb( port+LCR, LC_DLAB );
		outb( port+DLL, b );
		outb( port+DLH, b >> 8);
		outb( port+LCR, LC_CS8);

		hslimtty = tp;
	}
}

static hsunload()
{
	if (hstty != (TTY *)0)
		kfree(hstty);
}

/*
 * Open Routine.
 */
hsopen( dev, mode )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];
	register int b;
	int s;

	/*
	 * Verify hardware exists.
	 */
	if ( (PORT == 0) || (inb(PORT+IER) & ~IE_TxI) ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Can't open if another driver is using polling
	 */
	if (poll_owner & ~ POLL_HS) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Initialize if not already open.
	 */
	if ( ++tp->t_open == 1 ) {
		ttopen( tp );

		if ( dev & 0x80 ) {
			s = sphi();
			b = inb(PORT+MSR);
			tp->t_flags |= T_MODC + T_STOP;
			if ( b & MS_CTS )
				tp->t_flags &= ~T_STOP;
			if ( b & MS_DSR )
				tp->t_flags |=  T_CARR;
			spl( s );
		} else  {
			tp->t_flags &= ~T_MODC;
			tp->t_flags |=  T_CARR;
		}
		hscycle( tp );
	}
	ttsetgrp( tp, dev );
	set_poll_rate();
}

/*
 * Close Routine.
 */
hsclose( dev )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];

	/*
	 * Reset if last close.
	 */
	if ( tp->t_open == 1 ) {
		int state;

		ttclose( tp );
		/*
		 * ttclose() only emptied the output queue tp->t_oq;
		 * now wait 0.1 sec for the silo tp->rawout to empty
		 * and allow a delay for the UART on-chip xmit buffer to empty
		 *
		 * state 2: waiting for silo to empty
		 * state 1: stalling so UART can empty xmit buffer
		 * state 0: done!
		 */
		state = 2;
		while (state) {
			timeout(&hstim, 10, wakeup, (int)&hstim);
			sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
			if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
				state--;
		}
	}

	--tp->t_open;
	set_poll_rate();
}

/*
 * Read Routine.
 */
hsread( dev, iop )
dev_t dev;
register IO * iop;
{
	ttread( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Write Routine.
 */
hswrite( dev, iop )
dev_t dev;
register IO * iop;
{
	ttwrite( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Ioctl Routine.
 */
hsioctl( dev, com, vec )
dev_t dev;
int com;
struct sgttyb * vec;
{
	ttioctl( &hstty[ dev & 15 ], com, vec );
}

/*
 * Polling Routine.
 */
hspoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	return ttpoll( &hstty[ dev & 15 ], ev, msec );
}

/*
 * Cyclic routine - invoked every clock tick to perform raw input/output.
 *
 *	Notes:	Invoked 10 times per second.
 */
hscycle( tp )
register TTY * tp;
{
	register int resid;
	register int c;

	/*
	 * Process rawin buf.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}

	/*
	 * Calculate free output slot count.
	 */
	resid  = sizeof(tp->t_rawout.si_buf) - 1;
	resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	resid %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--resid >= 0) && ((c = ttout(tp)) >= 0) ) {

		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;

		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, waking processes waiting to output, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	if ( tp->t_open != 0 )
		timeout( &tp->t_rawtim, HZ/10, hscycle, tp );
}

/*
 * Clock Interrupt driven Polling routine.
 */
hsintr()
{
	register TTY * tp = &hstty[0];
	register int b;

	do {
		if ( tp->t_open == 0 )
			continue;

		/*
		 * Check modem status if modem control is enabled.
		 */
		if ( tp->t_flags & T_MODC ) {

			b = inb( PORT+MSR );

			if ( b & (MS_DCTS|MS_DDSR) ) {

				if ( b & MS_DCTS ) {
					if ( b & MS_CTS )
						tp->t_flags &= ~T_STOP;
					else
						tp->t_flags |=  T_STOP;
				}
				if ( b & MS_DDSR ) {
					if ( b & MS_DSR )
						tp->t_flags |=  T_CARR;
					else {
						tp->t_flags &= ~T_CARR;
						tthup( tp );
					}
				}
			}
		}

		b = inb( PORT+LSR );

		if ( (b & LS_BREAK) && (tp->t_flags & T_CARR) )
			ttsignal( tp, SIGINT );

		/*
		 * Receive ready.
		 */
		if ( b & LS_RxRDY ) {

			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(PORT+DREG);

			if ( tp->t_flags & T_CARR ) {

				if ( ++(tp->t_rawin.si_ix) >=
						sizeof(tp->t_rawin.si_buf) )
					tp->t_rawin.si_ix = 0;
			}
		}

		/*
		 * Transmit ready and raw output data exists.
		 */
		if ( (b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
		  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

			outb(	PORT+DREG,
				tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

			if ( ++(tp->t_rawout.si_ox) >=
					sizeof(tp->t_rawout.si_buf) )
				tp->t_rawout.si_ox = 0;
		}

	} while ( ++tp <= hslimtty );
}

/*
 * Set hardware parameters.
 */
hsparam( tp )
register TTY * tp;
{
	register int b;
	int s;

	s = sphi();
	/*
	 * Assert required modem control lines (DTR, RTS).
	 */
	b = 0;
	if ( tp->t_sgttyb.sg_ospeed != B0 )
		b |=  MC_DTR | MC_RTS;
	outb( PORT+MCR, b );

	/*
	 * Program baud rate.
	 */
	if (b = timeconst[ tp->t_sgttyb.sg_ospeed ]) {
		outb( PORT+LCR, LC_DLAB );
		outb( PORT+DLL, b );
		outb( PORT+DLH, b >> 8 );
	}

	/*
	 * Program character size, parity.
	 */
	switch ( tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW) ) {
	case ODDP:		b = LC_CS7|LC_PARENB;		 break;
	case EVENP:		b = LC_CS7|LC_PARENB|LC_PAREVEN; break;
	default:		b = LC_CS8;			 break;
	}
	outb( PORT+LCR, b );

	/*
	 * Enable Transmit Buffer Empty Interrupts.
	 */
	outb( PORT+IER, IE_TxI );

	spl(s);
	set_poll_rate();
}

/*
 * Start Routine.
 */
hsstart( tp )
register TTY * tp;
{
	register int s;

	/*
	 * Transmit buffer is empty, and raw output buffer is not.
	 */
	s = sphi();
	if ( (inb( PORT+LSR ) & LS_TxRDY)
	  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

		/*
		 * Send next char from raw output buffer.
		 */
		outb( PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}

/*
 * hsclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int hsclk()
{
  static int count;

  hsintr();
  count++;
  if (count >= poll_divisor)
    count = 0;
  return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_HS)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < HSNUM; port_num++) {
		if (hstty[port_num].t_open) {
		  port_rate = poll_hz[hstty[port_num].t_sgttyb.sg_ispeed];
		  if (max_rate < port_rate)
			max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in hsclk() */
		altclk_out();		/* stop previous polling */
		poll_owner &= ~POLL_HS;
		if (max_rate) {	/* resume polling at new rate if needed */
			altclk_in(poll_rate, hsclk);
			poll_owner |= POLL_HS;
		}
	}
}
0707070064030050631004440000030000030000011777770507310634500004700000003243/newbits/kernel/USRSRC/i8086/drv/ipc.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Inter-Process Communication.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:06:15	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:05:02	src
 * Initial revision
 * 
 */
#include <coherent.h>
#include <sys/ipc.h>
#include <sys/uproc.h>

/*
 * Determine Inter-Process Communication Access Permissions.
 *
 *	Input:	p = pointer to inter-process communication permission struct.
 *
 *	Action:	If super user, permissions are 0600.
 *		If uid is that of the creator or owner of the message id,
 *			use user permissions.
 *		If gid is that of the creator or owner of the message id,
 *			use group permissions.
 *		Otherwise, use others permissions.
 *
 *	Output:	0600 = Read/Alter permission.
 *		0400 = Read permission.
 *		0200 = Alter permission.
 *		   0 = No permission.
 */

ipcaccess( p )

register struct ipc_perm * p;

{
	if ( u.u_uid == 0 )
		return 0600;

	if ((u.u_uid == p->uid) || (u.u_uid == p->cuid))
		return p->mode & 0600;

	if ((u.u_gid == p->gid) || (u.u_gid == p->cgid))
		return (p->mode << 3) & 0600;

	return (p->mode << 6) & 0600;
}
0707070064030050641004440000030000030000011777770507310634500005100000007742/newbits/kernel/USRSRC/i8086/drv/ipcas.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1985, 1984
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/

////////
/
/ System V Compatible Inter-Process Communication - Assembler Support
/
/ ufcopy( base, off, sel, n ) -- copy n bytes from user base to sel:off.
/ fucopy( off, sel, base, n ) -- copy n bytes from sel:off to user base.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 2.1	88/09/03  13:06:24	src
/ *** empty log message ***
/ 
/ Revision 1.1	88/03/24  17:05:05	src
/ Initial revision
/ 
/
/ 85/07/19	Allan Cornish
/ Inserted code to check user address for validity.
/ Functions ufcopy and fucopy now return 0 if user address is invalid.
/ Replaced 'jnc .+2;movsb' with 'rcl cx,$1;rep movsb' to improve pipelining.
/
/ 85/07/03	Allan Cornish
/ Functions renamed: uoscopy --> ufcopy, osucopy --> fucopy (f = far).
/ Module moved from msgas.s to ipcas.s, to reflect its shared use.
/
////////

	.globl	ufcopy_
	.globl	fucopy_

////////
/
/ ufcopy( base, off, sel, n )	-- copy n bytes from user base to sel:off.
/
/	Input:	base = offset in user memory to copy from
/		off  = offset in the destination segment
/		sel  = selector to access the destination segment
/		n    = number of bytes to copy
/
/	Action:	Copy 'n' bytes of data from offset 'base' in user memory
/		to offset 'off' in the segment accessed by selector 'sel'.
/
/	Return:	Number of bytes copied, or 0 if invalid user address.
/
////////

ufcopy_:			/ ufcopy( base, off, sel, n )
	push	si		/
	push	di		/ unsigned base;
	push	bp		/ unsigned off;
	mov	bp, sp		/ saddr_t sel;
	push	ds		/ unsigned n;
	push	es		/
				/ {
	mov	ax, 8(bp)	/	Validate user address.
	dec	ax		/
	add	ax, 14(bp)	/	Wrap-around error?
	jc	fuerr		/
	cmp	ax, udl_	/	Address out of bounds error?
	ja	fuerr		/
				/
	mov	bx, uds_	/	Map DS:SI into user (source) addr
	mov	ds, bx		/
	mov	si, 8(bp)	/
	les	di, 10(bp)	/	Map ES:DI into segment (dest) addr
	mov	cx, 14(bp)	/	Transfer count
				/
	cld			/	Auto Increment
	clc			/
	rcr	cx, $1		/	Change byte count into word count
	rep			/	Transfer data words
	movsw			/
	rcl	cx, $1		/	If residual byte count
	rep			/		Transfer last data byte.
	movsb			/
				/
	mov	ax, 14(bp)	/	Return transfer count.
	pop	es		/ }
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret

fuerr:	sub	ax, ax
	pop	es
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ fucopy( off, sel, base, n )	-- copy n bytes from sel:off to user base.
/
/	Input:	off  = offset is the source segment
/		sel  = selector to access the source segment
/		base = offset in user memory to copy to
/		n    = number of bytes to copy
/
/	Action:	Copy 'n' bytes of data from offset 'off' in the segment
/		accessed by selector 'sel' to offset 'base' in user memory.
/
/	Return:	Number of bytes copied, or 0 if invalid user address.
/
////////

fucopy_:			/ fucopy( off, sel, base, n )
	push	si		/
	push	di		/ unsigned off;
	push	bp		/ saddr_t  sel;
	mov	bp, sp		/ unsigned base;
	push	ds		/ unsigned n;
	push	es		/
				/ {
	mov	ax, 12(bp)	/	Validate user address.
	dec	ax		/
	add	ax, 14(bp)	/	Wrap-around error?
	jc	fuerr		/
	cmp	ax, udl_	/	Address out of bounds error?
	ja	fuerr		/
				/
	mov	es, uds_	/	Map ES:DI into user (dest) address
	mov	di, 12(bp)	/
	lds	si, 8(bp)	/	Map DS:SI into segment (source) addr
	mov	cx, 14(bp)	/	Transfer count
				/
	cld			/	Auto Increment
	clc			/
	rcr	cx, $1		/	Change byte count into word count
	rep			/
	movsw			/	Transfer data words
	rcl	cx, $1		/	If residual byte count
	rep			/		Transfer last data byte.
	movsb			/
				/
	mov	ax, 14(bp)	/	Return transfer count.
	pop	es		/ }
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret
0707070064030057001006440000030000030000011777770507310634600004600000043104/newbits/kernel/USRSRC/i8086/drv/kb.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Keyboard/display driver.
 * Coherent, IBM PC/XT/AT.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <sys/devices.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <signal.h>
#include <sys/sched.h>

#define	SPC	0376			/* Special encoding */
#define XXX	0377			/* Non-character */
#define	KBDATA	0x60			/* Keyboard data */
#define	KBCTRL	0x61			/* Keyboard control */
#define	KBFLAG	0x80			/* Keyboard reset flag */
#define	LEDCMD	0xED			/* status indicator command */
#define	KBACK	0xFA			/* status indicator acknowledge */
#define	EXTENDED1 0xE1			/* extended key seq initiator */

#define	KEYUP	0x80			/* Key up change */
#define	KEYSC	0x7F			/* Key scan code mask */
#define	LSHIFT	0x2A-1			/* Left shift key */
#define LSHIFTA 0x2B-1			/* Alternate left-shift key */
#define	RSHIFT	0x36-1			/* Right shift key */
#define	CTRL	0x1D-1			/* Control key */
/*-- #define	CAPLOCK	0x1D-1	--*/		/* Control key */
#define	ALT	0x38-1			/* Alt key */
#define	CAPLOCK	0x3A-1			/* Caps lock key */
/*-- #define	CTRL	0x3A-1	--*/		/* Caps lock key */
#define	NUMLOCK	0x45-1			/* Numeric lock key */
#define	DELETE	0x53-1			/* Del, as in CTRL-ALT-DEL */
#define BACKSP	0x0E-1			/* Back space */
#define SCRLOCK	0x46-1			/* Scroll lock */

/* Shift flags */
#define	SRS	0x01			/* Right shift key on */
#define	SLS	0x02			/* Left shift key on */
#define CTS	0x04			/* Ctrl key on */
#define ALS	0x08			/* Alt key on */
#define CPLS	0x10			/* Caps lock on */
#define NMLS	0x20			/* Num lock on */
#define AKPS	0x40			/* Alternate keypad shift */
#define SHFT	0x80			/* Shift key flag */

/* Function key information */
#define	NFKEY	20			/* Number of settable functions */
#define	NFCHAR	150			/* Number of characters settable */
#define	NFBUF	(NFKEY*2+NFCHAR+1)	/* Size of buffer */

/*
 * Functions.
 */
int	isrint();
int	istime();
void	isbatch();
int	mmstart();
int	isopen();
int	isclose();
int	isread();
int	mmwrite();
int	isioctl();
void	mmwatch();
int	isload();
int	isuload();
int	ispoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON iscon ={
	DFCHR|DFPOL,			/* Flags */
	KB_MAJOR,				/* Major index */
	isopen,				/* Open */
	isclose,			/* Close */
	nulldev,			/* Block */
	isread,				/* Read */
	mmwrite,			/* Write */
	isioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	mmwatch,			/* Timeout */
	isload,				/* Load */
	isuload,			/* Unload */
	ispoll				/* Poll */
};

/*
 * Flag indicating turbo machine.
 */
int isturbo = 0;

/*
 * Terminal structure.
 */
TTY	istty = {
	{0}, {0}, 0, mmstart, NULL, 0, 0
};

/*
 * State variables.
 */
int		islock;			/* Keyboard locked flag */
int		isbusy;			/* Raw input conversion busy */
static	char	shift;			/* Overall shift state */
static	char	scroll;			/* Scroll lock state */
static  char	lshift = LSHIFT;	/* Left shift alternate state */
static	char	isfbuf[NFBUF];		/* Function key values */
static	char	*isfval[NFKEY];		/* Function key string pointers */
static	int	ledcmd;			/* LED update command flag */
static	int	extended;		/* extended key scan count */

/*
 * Tables for converting key code to ASCII.
 * lmaptab specifies unshifted conversion,
 * umaptab specifies shifted conversion,
 * smaptab specifies the shift states which are active.
 * An entry of XXX says the key is dead.
 * An entry of SPC requires further processing.
 *
 * Key codes:
 *	ESC .. <- == 1 .. 14
 *	-> .. \n == 15 .. 28
 *	CTRL .. ` == 29 .. 41
 *	^Shift .. PrtSc == 42 .. 55
 * 	ALT .. CapsLock == 56 .. 58
 *	F1 .. F10 == 59 .. 68
 *	NumLock .. Del == 69 .. 83
 */
static unsigned char lmaptab[] ={
	     '\33',  '1',  '2',  '3',  '4',  '5',  '6',		/* 1 - 7 */
	 '7',  '8',  '9',  '0',  '-',  '=', '\b', '\t',		/* 8 - 15 */
	 'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',		/* 16 - 23 */
	 'o',  'p',  '[',  ']', '\r',  XXX,  'a',  's',		/* 24 - 31 */
	 'd',  'f',  'g',  'h',  'j',  'k',  'l',  ';',		/* 32 - 39 */
	 '\'', '`',  XXX,  '\\',  'z',  'x',  'c',  'v',	/* 40 - 47 */
	 'b',  'n',  'm',  ',',  '.',  '/',  XXX,  '*',		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC					/* 80 - 83 */
};

static unsigned char umaptab[] ={
	     '\33',  '!',  '@',  '#',  '$',  '%',  '^',		/* 1 - 7 */
	 '&',  '*',  '(',  ')',  '_',  '+', '\b', SPC,		/* 8 - 15 */
	 'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',		/* 16 - 23 */
	 'O',  'P',  '{',  '}', '\r',  XXX,  'A',  'S',		/* 24 - 31 */
	 'D',  'F',  'G',  'H',  'J',  'K',  'L',  ':',		/* 32 - 39 */
	 '"',  '~',  XXX,  '|',  'Z',  'X',  'C',  'V',		/* 40 - 47 */
	 'B',  'N',  'M',  '<',  '>',  '?',  XXX,  '*',		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC					/* 80 - 83 */
};

#define SS0	0			/* No shift */
#define SS1	(SLS|SRS|CTS)		/* Shift, Ctrl */
#define SES	(SLS|SRS)		/* Shift */
#define LET	(SLS|SRS|CPLS|CTS)	/* Shift, Caps, Ctrl */
#define KEY	(SLS|SRS|NMLS|AKPS)	/* Shift, Num, Alt keypad */

static unsigned char smaptab[] ={
	       SS0,  SES,  SS1,  SES,  SES,  SES,  SS1,		/* 1 - 7 */
	 SES,  SES,  SES,  SES,  SS1,  SES,  CTS,  SES,		/* 8 - 15 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  LET,		/* 16 - 23 */
	 LET,  LET,  SS1,  SS1,  CTS, SHFT,  LET,  LET,		/* 24 - 31 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  SES,		/* 32 - 39 */
	 SES,  SS1, SHFT,  SS1,  LET,  LET,  LET,  LET,		/* 40 - 47 */
	 LET,  LET,  LET,  SES,  SES,  SES, SHFT,  SES,		/* 48 - 55 */
	SHFT,  SS1, SHFT,  SS0,  SS0,  SS0,  SS0,  SS0,		/* 56 - 63 */
	 SS0,  SS0,  SS0,  SS0,  SS0, SHFT,  KEY,  KEY,		/* 64 - 71 */
	 KEY,  KEY,  SS0,  KEY,  KEY,  KEY,  SS0,  KEY,		/* 72 - 79 */
	 KEY,  KEY,  KEY,  KEY					/* 80 - 83 */
};

/*
 * Load entry point.
 *  Do reset the keyboard because it gets terribly munged
 *  if you type during the boot.
 */
isload()
{
	register int i;

	/*
	 * Reset keyboard if NOT an XT turbo.
	 */
	if ( ! isturbo ) {
		outb(KBCTRL, 0x0C);		/* Clock low */
		for (i = 10582; --i >= 0; );	/* For 20ms */
		outb(KBCTRL, 0xCC);		/* Clock high */
		for (i = 0; --i != 0; )
			;
		i = inb(KBDATA);
		outb(KBCTRL, 0xCC);			/* Clear keyboard */
		outb(KBCTRL, 0x4D);			/* Enable keyboard */
	}

	/*
	 * Enable mmwatch() invocation every second.
	 */
	drvl[KB_MAJOR].d_time = 1;

	/*
	 * Seize keyboard interrupt.
	 */
	setivec(1, isrint);

	/*
	 * Initiailize video display.
	 */
	mmstart( &istty );
}

/*
 * Unload entry point.
 */
isuload()
{
	clrivec(1);
}

/*
 * Default function key strings (terminated by -1 [\377])
 */
static char *deffuncs[] = {
	"\33[1x\377",	/* F1 */
	"\33[2x\377",	/* F2 */
	"\33[3x\377",	/* F3 */
	"\33[4x\377", 	/* F4 */
	"\33[5x\377",	/* F5 */
	"\33[6x\377",	/* F6 */
	"\33[7x\377",	/* F7 */
	"\33[8x\377",	/* F8 */
	"\33[9x\377",	/* F9 */
	"\33[0x\377",	/* F10 - historical value */
	"\33[1y\377",	/* F11 */
	"\33[2y\377",	/* F12 */
	"\33[3y\377",	/* F13 */
	"\33[4y\377", 	/* F14 */
	"\33[5y\377",	/* F15 */
	"\33[6y\377",	/* F16 */
	"\33[7y\377",	/* F17 */
	"\33[8y\377",	/* F18 */
	"\33[9y\377",	/* F19 */
	"\33[0y\377"	/* F20 */
};

/*
 * Open routine.
 */
isopen(dev)
dev_t dev;
{
	register int s;

	if (minor(dev) != 0) {
		u.u_error = ENXIO;
		return;
	}
	if ((istty.t_flags&T_EXCL)!=0 && super()==0) {
		u.u_error = ENODEV;
		return;
	}
	ttsetgrp(&istty, dev);

	s = sphi();
	if (istty.t_open++ == 0)
	{  initkeys();	 /* init function keys */
	   istty.t_flags = T_CARR;  /* indicate "carrier" */
	   ttopen(&istty);
	}
	spl(s);
	updleds();			/* update keyboard status LEDS */
}

/* Init function keys */
initkeys()
{	register int i;
	register char *cp1, *cp2;

	for (i=0; i<NFKEY; i++)
	    isfval[i] = 0;	    /* clear function key buffer */
	cp2 = isfbuf;	      	    /* pointer to key buffer */   
	for (i=0; i<NFKEY; i++)
	{  isfval[i] = cp2;	    /* save pointer to key string */
	   cp1 = deffuncs[i];       /* get init string pointer */
	   while ((*cp2++ = *cp1++) != -1)  /* copy key data */
	     if (cp2 >= &isfbuf[NFBUF-3])   /* overflow? */
	        return;
	}
}

/*
 * Close a tty.
 */
isclose(dev)
{
	register int s;

	s = sphi();
	if (--istty.t_open == 0)
	{  	s = sphi();
		ttclose(&istty);
		spl(s);
	}
}

/*
 * Read routine.
 */
isread(dev, iop)
dev_t dev;
IO *iop;
{
	ttread(&istty, iop, 0);
	if (istty.t_oq.cq_cc)
		mmtime(&istty);
}

/*
 * Ioctl routine.
 */
isioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	register int s;

	switch(com) {
	case TIOCSETF:
	case TIOCGETF:
		isfunction(com, (char *)vec);
		return;
	case TIOCSHIFT:   /* switch left-SHIFT and "\" */
		lshift = LSHIFTA;    /* alternate values */
		lmaptab[41] = '\\';
		lmaptab[42] = XXX;
		umaptab[41] = '|';
		umaptab[42] = XXX;
		smaptab[41] = SS1;
		smaptab[42] = SHFT;
		return;
	case TIOCCSHIFT:  /* normal (default) left-SHIFT and "\" */
		lshift = LSHIFT;     /* normal values */
		lmaptab[41] = XXX;
		lmaptab[42] = '\\';
		umaptab[41] = XXX;
		umaptab[42] = '|';
		smaptab[41] = SHFT;
		smaptab[42] = SS1;
		return;
	}
	s = sphi();
	ttioctl(&istty, com, vec);
	spl(s);
}

/*
 * Set and receive the function keys.
 */
isfunction(c, v)
int c;
char *v;
{
	register char *cp;
	register int i;

	if (c == TIOCGETF) {
		for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++)
		    putubd(v++, *cp);
	} else {
		for (i=0; i<NFKEY; i++)		/* zap current settings */
			isfval[i] = 0;
		cp = isfbuf;			/* pointer to key buffer */
		for (i=0; i<NFKEY; i++) {
			isfval[i] = cp;	        /* save pointer to key string */
			while ((*cp++ = getubd(v++)) != -1)  /* copy key data */
				if (cp >= &isfbuf[NFBUF-3])  /* overflow? */
					return;
		}
	}
}


/*
 * Poll routine.
 */
ispoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll failure.
	 */
	if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) {

		if ( msec != 0 )
			pollopen( &istty.t_ipolls );

		/*
		 * Second look AFTER enabling monitor, avoiding interrupt race.
		 */
		if ( istty.t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}

	return ev;
}

/*
 * Receive interrupt.
 */
isrint()
{
	register int	c;
	register int	s;
	register int	r;
	int	savests;
	int	update_leds = 0;

	/*
	 * Schedule raw input handler if not already active.
	 */
	if ( isbusy == 0 ) {
		defer( isbatch, &istty );
		isbusy = 1;
	}

	/*
	 * Pull character from the data
	 * port. Pulse the KBFLAG in the control
	 * port to reset the data buffer.
	 */
	r = inb(KBDATA) & 0xFF;
	c = inb(KBCTRL);
	outb(KBCTRL, c|KBFLAG);
	outb(KBCTRL, c);
#if	KBDEBUG
	printf("kbd: %d\n", r);			/* print scan code/direction */
#endif
	if (ledcmd) {
		ledcmd = 0;
		if (r == KBACK) {		/* output to status LEDS */
			c = scroll & 1;
			if (shift & NMLS)
				c |= 2;
			if (shift & CPLS)
				c |= 4;
			outb(KBDATA, c);
		}
		return;
	}
	if (extended > 0) {			/* if multi-character seq, */
		--extended;			/* ... ignore this char */
		return;
	}
	if (r == EXTENDED1) {			/* ignore extended sequences */
		extended = 5;
		return;
	}
	if (r == 0xFF)
		return;	/* Overrun */
	c = (r & KEYSC) - 1;
	/*
	 * Check for reset.
	 */
	if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS))
		boot();

	/*
	 * Track "shift" keys.
	 */
	s = smaptab[c];
	if (s&SHFT) {
		if (r&KEYUP) {			/* "shift" released */
			if (c == RSHIFT)
				shift &= ~SRS;
			else if (c == lshift)
				shift &= ~SLS;
			else if (c == CTRL)
				shift &= ~CTS;
			else if (c == ALT)
				shift &= ~ALS;
		} else {			/* "shift" pressed */
			if (c == lshift)
				shift |= SLS;
			else if (c == RSHIFT)
				shift |= SRS;
			else if (c == CTRL)
				shift |= CTS;
			else if (c == ALT)
				shift |= ALS;
			else if (c == CAPLOCK) {
				shift ^= CPLS;	/* toggle cap lock */
				updleds();
			} else if (c == NUMLOCK) {
				shift ^= NMLS;	/* toggle num lock */
				updleds();
			}
		}
		return;
	}

	/*
	 * No other key up codes of interest.
	 */
	if (r&KEYUP)
		return;

	/*
	 * If the tty is not open the character is
	 * just tossed away.
	 */
	if (istty.t_open == 0)
		return;

	/*
	 * Map character, based on the
	 * current state of the shift, control,
	 * meta and lock flags.
	 */
	if (shift & CTS) {
		if (s == CTS)			/* Map Ctrl (BS | NL) */
			c = (c == BACKSP) ? 0x7F : 0x0A;  
		else if (s==SS1 || s==LET)	/* Normal Ctrl map */
			c = umaptab[c]&0x1F;	/* Clear bits 5-6 */
		else				
			return;			/* Ignore this char */
	} else if (s &= shift) {
		if (shift & SES) {		 /* if shift on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = lmaptab[c];  /* use unshifted */
			else
				c = umaptab[c];	 /* use shifted */
		} else {			 /* if shift not on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = umaptab[c];	 /* use shifted */
			else
				c = lmaptab[c];	 /* use unshifted */
		}
	} else					 
		c = lmaptab[c];			 /* use unshifted */

	/*
	 * Act on character.
	 */
	if (c == XXX)				
		return;				 /* char to ignore */

	if (c != SPC) {			 /* not special char? */
		if (shift & ALS)	 /* ALT (meta bit)? */
			c |= 0x80;	 /* set meta */
		isin(c);		 /* send the char */
	} else
		update_leds += isspecial(r);	 /* special chars */
	if (update_leds) {
		savests = sphi();
		outb(KBDATA, LEDCMD);
		ledcmd = 1;
		spl(savests);
	}
}

/*
 * Handle special input sequences.
 * The character passed is the key number.
 *
 * The keypad is translated by the following table,
 * the first entry is the normal sequence, the second the shifted,
 * and the third the alternate keypad sequence.
 */
static char *keypad[][3] = {
	{ "\33[H",  "7", "\33?w" },	/* 71 */
	{ "\33[A",  "8", "\33?x" },	/* 72 */
	{ "\33[V",  "9", "\33?y" },	/* 73 */
	{ "\33[D",  "4", "\33?t" },	/* 75 */
	{ "\0337",  "5", "\33?u" },	/* 76 */
	{ "\33[C",  "6", "\33?v" },	/* 77 */
	{ "\33[24H","1", "\33?q" },	/* 79 */
	{ "\33[B",  "2", "\33?r" },	/* 80 */
	{ "\33[U",  "3", "\33?s" },	/* 81 */
	{ "\33[@",  "0", "\33?p" },	/* 82 */
	{ "\33[P", ".",  "\33?n" }	/* 83 */
};

isspecial(c)
int c;
{
	register char *cp;
	register int s;
	int	update_leds = 0;

	cp = 0;

	switch (c) {
	case 15:					/* cursor back tab */
		cp = "\033[Z";
		break;
	case 59: case 60: case 61: case 62: case 63:	/* Function keys */
	case 64: case 65: case 66: case 67: case 68:
		/* offset to function string */
		if ( shift & ALS )
			cp = isfval[c-49];
		else
			cp = isfval[c-59];
		break;

	case 70:		/* Scroll Lock -- stop/start output */
	{
		static char cbuf[2];

		cp = &cbuf[0];  /* working buffer */
		if (!(istty.t_sgttyb.sg_flags&RAWIN)) {	/* not if in RAW mode */
			++update_leds;
			if (istty.t_flags & T_STOP) {	/* output stopped? */
			   cbuf[0] = istty.t_tchars.t_startc;  /* start it */
			   scroll = 0;
			} else {
			   cbuf[0] = istty.t_tchars.t_stopc;   /* stop output */
			   scroll = 1;
			}
		}
		break;
	}

	case 79:		/* 1/End */
	case 80:		/* 2/DOWN */
	case 81:		/* 3/PgDn */
	case 82:		/* 0/Ins */
	case 83:		/* ./Del */
		--c;		/* adjust code */
	case 75:		/* 4/LEFT */
	case 76:		/* 5 */
	case 77:		/* 6/RIGHT */
		--c;		/* adjust code */
	case 71:		/* 7/Home/Clear */
	case 72:		/* 8/UP */
	case 73:		/* 9/PgUp */
		s = 0;			/* start off with normal keypad */
		if (shift&NMLS)		/* num lock? */
			s = 1;		/* set shift pad */
		if (shift&SES)		/* shift? */
			s ^= 1;		/* toggle shift pad */
		if (shift&AKPS)		/* alternate pad? */
			s = 2;		/* set alternate pad */		
		cp = keypad[c-71][s];   /* get keypad value */
		break;
	}
	if (cp)					/* send string */
		while ((*cp != 0) && (*cp != -1))
			isin( *cp++ & 0377 );
	return update_leds;
}

/**
 *
 * void
 * ismmfunc( c )	-- process keyboard related output escape sequences
 * char c;
 */
void
ismmfunc(c)
register int c;
{
	switch (c) {
	case 't':	/* Enter numlock */
		shift |= NMLS;
		updleds();			/* update LED status */
		break;
	case 'u':	/* Leave numlock */
		shift &= ~NMLS;
		updleds();			/* update LED status */
		break;
	case '=':	/* Enter alternate keypad */
		shift |= AKPS;
		break;
	case '>':	/* Exit alternate keypad */
		shift &= ~AKPS;
		break;
	case 'c':	/* Reset terminal */
		islock = 0;
		shift  = 0;
		initkeys();
		updleds();			/* update LED status */
		break;
	}
}

/**
 *
 * void
 * isin( c )	-- append character to raw input silo
 * char c;
 */
static
isin( c )
register int c;
{
	/*
	 * Cache received character.
	 */
	istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c;

	if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) )
		istty.t_rawin.si_ix = 0;
}

/**
 *
 * void
 * isbatch()	-- raw input conversion routine
 *
 *	Action:	Enable the video display.
 *		Canonize the raw input silo.
 *
 *	Notes:	isbatch() was scheduled as a deferred process by isrint().
 */
static void
isbatch( tp )
register TTY * tp;
{
	register int c;
	static int lastc;

	/*
	 * Ensure video display is enabled.
	 */
	mm_von();

	isbusy = 0;

	/*
	 * Process all cached characters.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		/*
		 * Get next cached char.
		 */
		c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ];

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;

		if ( (islock == 0) || ISINTR || ISQUIT ) {
			ttin( tp, c );
		}

		else if ( (c == 'b') && (lastc == '\033') ) {
			islock = 0;
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else if ( (c == 'c') && (lastc == '\033') ) {
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else
			putchar('\007');

		lastc = c;
	}
}

/*
 * update the keyboard status LEDS
 */
updleds()
{
	int	s;

	s = sphi();
	outb(KBDATA, LEDCMD);
	ledcmd = 1;
	spl(s);
}

/*
 * unlock the scroll in case an interrupt character is received
 */
kbunscroll()
{
	scroll = 0;
	updleds();
}
0707070064030032041006440000030000030000011777770507310635300004700000000260/newbits/kernel/USRSRC/i8086/drv/lgl.h/* (-lgl
 * 	COHERENT Driver Kit Version (Beta)
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
0707070064030050651006440000030000030000011777770507310635300004600000016111/newbits/kernel/USRSRC/i8086/drv/lp.c/*
 * This is a driver for PC parallel printers.
 * It has been tested on an EPSON MX-80, Printronix P300, HP LaserJet II.
 * Supports up to three line printers.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <sys/devices.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/uproc.h>
#include <sys/stat.h>

/*
 * Patchable parameters.
 *
 *	LP0_OK specifies whether LP0 is always THERE.
 *	LPTIME specifies number of ticks between polls.
 *	LPWAIT specifies loop counter to wait in poll.
 *	LPTEST specifies whether or not to test for on-line conditition.
 */
int	LP0_OK = 0;
int	LPTIME = 4;
int	LPWAIT = 400;
int	LPTEST = 1;

/*
 * Driver configuration.
 */
int	lpload();
int	lpunload();
int	lpwrite();
int	lpopen();
int	lpclose();
int	lpintr();
int	nulldev();
int	nonedev();

CON	lpcon =	{
	DFCHR,				/* Flags */
	LP_MAJOR,				/* Major index */
	lpopen,				/* Open */
	lpclose,			/* Close */
	nulldev,			/* Block */
	nonedev,			/* Read */
	lpwrite,			/* Write */
	nonedev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	lpload,				/* Load */
	lpunload			/* Unload */
};

/*
 * Line Printer Registers.
 */
#define	LPDAT	(0)			/* Data port, lpbase + 0 */
#define	LPSTR	(1)			/* Status port, lpbase + 1 */
#define	LPCSR	(2)			/* Control port, lpbase + 2 */

/*
 * LP Flag Bits.
 */
#define	LPTHERE	0x01			/* Interface actually there */
#define	LPOPEN	0x02			/* Printer is open */
#define	LPSLEEP	0x04			/* Sleeping on buffer event */
#define	LPRAW	0x80			/* Raw mode */

/*
 * Printer database.
 * Terminated by lpbase = 0.
 * NLP = # entries - 1.
 */
static struct	lpinfo	{
	int	lpbase;			/* I/O Base address */
	int	lpflag;			/* Flags */
	int	lpcol;			/* Current horizontal position */
}	lpinfo[] = {
	{	0x3BC	},
	{	0x378	},
	{	0x278	},
	{	0x000	}
};
#define	NLP	(sizeof(lpinfo) / sizeof(lpinfo[0]) - 1)

/*
 * LP Status Register Bits.
 */
#define	ACK	0x80			/* Ack (active high) */
#define	BUSY	0x40			/* Busy (active high) */
#define	NOPAPER	0x20			/* No paper */
#define	ONLINE	0x10			/* On line */
#define	NERROR	0x08			/* Error (active low) */

/* IBM cable */
#define	IBMNBSY	0x80			/* Busy (active low) */
#define	IBMNACK	0x40			/* Ack (active low) */

/*
 * LP Control Register Bits.
 */
#define	IENABLE	0x10			/* Interrupt enable */
#define	SEL	0x08			/* Select input */
#define	NINIT	0x04			/* Initialise printer (active low) */
#define	AFEED	0x02			/* Auto line feed */
#define	STROBE	0x01			/* Strobe */

/*
 * On load
 * compute the port addresses,
 * reset the printer, and select it.
 */
static
lpload()
{
	register struct lpinfo * p;
	register int delay;
	static int notfirst;

	/*
	 * Only initialize hardware on first invocation.
	 * Necessary if used as console device [condev].
	 */
	if ( notfirst )
		return;
	notfirst = 1;

	/*
	 * Note: since some PC clones lp ports can't be read,
	 * their lpflag field has to be patched to 'LPTHERE'.
	 */
	if ( LP0_OK & 1 )
		lpinfo[0].lpflag |= LPTHERE;
	if ( LP0_OK & 2 )
		lpinfo[1].lpflag |= LPTHERE;
	if ( LP0_OK & 4 )
		lpinfo[2].lpflag |= LPTHERE;

	for ( p = lpinfo; p->lpbase ; ++p ) {

		/*
		 * Check printer port existence.
		 */
		if ( (p->lpflag & LPTHERE) == 0 ) {
			outb( p->lpbase+LPDAT, 0xA5 );
			delay = LPWAIT; do {
			} while (--delay);
			if ( inb(p->lpbase+LPDAT) == 0xA5 )
				p->lpflag |= LPTHERE;
		}

		/*
		 * Initialize and select printer.
		 */
		outb( p->lpbase+LPCSR, SEL );
		delay = LPWAIT; do {
		} while (--delay);
		outb( p->lpbase+LPCSR, SEL|NINIT );
	}
}

/*
 * On unload
 * cancel any timed functions.
 */
static
lpunload()
{
	lptimer();
}

/*
 * The open routine makes sure that
 * only one process has the printer open
 * at one time, and not too much else.
 */
static
lpopen(dev, mode)
dev_t	dev;
{
	register struct lpinfo * p;

	/*
	 * Illegal printer port.
	 */
	if ( (minor(dev) & ~LPRAW) >= NLP ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Access attributes.
	 */
	p = &lpinfo[ minor(dev) & ~LPRAW ];

	/*
	 * Attempt initialization if printer port not found.
	 */
	if ( (p->lpflag&LPTHERE) == 0 )
		lpload();

	/*
	 * Printer port not found.
	 */
	if ( (p->lpflag&LPTHERE) == 0 ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Printer port already open.
	 */
	if ( (p->lpflag&LPOPEN) != 0 ) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Printer powered off or off-line
	 */
	if (LPTEST && !(inb(p->lpbase+LPSTR) & ONLINE)) {
		u.u_error = EDATTN;
		return;
	}

	/*
	 * Flag port as being open.
	 */
	p->lpflag &= ~LPRAW;
	p->lpflag |= LPOPEN | minor(dev) & LPRAW;

	/*
	 * Initiate periodic printer scan if user open.
	 */
	if ( (SELF != NULL) && (SELF->p_pid != 0) )
		lptimer();
}

/*
 * The close routine marks the device as no longer open.
 */
static
lpclose(dev)
dev_t	dev;
{
	lpinfo[ minor(dev) & ~LPRAW ].lpflag &= ~LPOPEN;
}

/*
 * The write routine copies the
 * characters from the user buffer to
 * the printer buffer, expanding tabs and
 * keeping track of the current horizontal
 * position of the print head.
 */
static
lpwrite( dev, iop )
dev_t	dev;
IO	*iop;
{
	register struct lpinfo * p;
	register int	c;

	p = &lpinfo[ minor(dev) & ~LPRAW ];

	/*
	 * Writes from kernel are handled via busy-waits instead of timeouts.
	 */
	if (iop->io_seg == IOSYS) {

		while ( (c=iogetc(iop)) >= 0 ) {

			while ( (inb(p->lpbase+LPSTR) & IBMNBSY) == 0 )
				;

			outb( p->lpbase+LPDAT, c );
			outb( p->lpbase+LPCSR, SEL|NINIT|STROBE );
			outb( p->lpbase+LPCSR, SEL|NINIT );
		}
		return;
	}

	/*
	 * Writes from user are handled via lpchar() which uses timeouts.
	 */
	while ( (c=iogetc(iop)) >= 0 ) {

		if ( (p->lpflag&LPRAW) == 0 ) {

			switch (c) {

			case '\t':
				do {
					lpchar( p, ' ');
				} while ((++p->lpcol&07) != 0);
				continue;
	
			case '\n':
				lpchar( p, '\r');
				/* no break */

			case '\r':
			case '\f':
				p->lpcol = 0;
				break;
	
			case '\b':
				--p->lpcol;
				break;
	
			default:
				++p->lpcol;
			}
		}
		lpchar( p, c );

		if ( SELF->p_ssig!=0 && nondsig() ) {
			u.u_error = EINTR;
			break;
		}
	}
}

/*
 * Put a character into the printer buffer.
 * If the printer doesn't respond ready in a reasonable time
 * sleep for a while.
 */
static
lpchar( p, c )
register struct lpinfo *p;
int c;
{
	register int	s;

	s = LPWAIT;
	while ( (inb(p->lpbase+LPSTR) & IBMNBSY) == 0 ) {
		if ( --s == 0 ) {
			s = sphi();
			p->lpflag |= LPSLEEP;
			sleep((char *)p, 0, 0, 0);
			spl(s);
			s = LPWAIT;
		}
	}

	outb( p->lpbase+LPDAT, c );
	outb( p->lpbase+LPCSR, SEL|NINIT|STROBE );
	outb( p->lpbase+LPCSR, SEL|NINIT );
}

/*
 * Poll the line printer interface from the clock.
 * Turn it off when there is nothing left to do.
 */
static
lptimer()
{
	register struct lpinfo *p;
	int isopen = 0;
	static TIM tim;

	/*
	 * Scan all printers.
	 */
	for ( p = lpinfo; p->lpbase; ++p ) {

		/*
		 * Ignore unopened printers.
		 */
		if ( (p->lpflag & LPOPEN) == 0 )
			continue;

		++isopen;

		/*
		 * Check for sleeping process on ready printer.
		 */
		if((p->lpflag & LPSLEEP) && (inb(p->lpbase+LPSTR) & IBMNBSY)){
			p->lpflag &= ~LPSLEEP;
			wakeup((char *)p);
		}
	}

	/*
	 * Reschedule timer function if at least 1 printer is still open.
	 */
	if ( isopen )
		timeout( &tim, LPTIME, lptimer, &tim );
}
0707070064030141661004440000030000030000011777770507310635500004600000005773/newbits/kernel/USRSRC/i8086/drv/mm.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Memory Mapped Video
 * High level output routines.
 */
#include <sys/coherent.h>
#include <sys/sched.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/io.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <sys/timeout.h>

/* For beeper */
#define	TIMCTL	0x43			/* Timer control port */
#define	TIMCNT	0x42			/* Counter timer port */
#define	PORTB	0x61			/* Port containing speaker enable */
#define	FREQ	((int)(1193181L/440))	/* Counter for 440 Hz. tone */

int mmtime();

char mmbeeps;		/* number of ticks remaining on bell */
char mmesc;		/* last unserviced escape character */
int  mmcrtsav = 1;	/* crt saver enabled */
int  mmvcnt   = 900;	/* seconds remaining before crt saver is activated */

extern TTY istty;

/*
 * Start the output stream.
 * Called from `ttwrite' and `isrint' routines.
 */
TIM mmtim;

mmstart(tp)
register TTY *tp;
{
	int c;
	IO iob;
	static int mmbegun;

	while ((tp->t_flags&T_STOP) == 0) {
		if ((c = ttout(tp)) < 0)
			break;
		iob.io_seg  = IOSYS;
		iob.io_ioc  = 1;
		iob.io_base = &c;
		iob.io_flag = 0;
		mmwrite( makedev(2,0), &iob );
	}

	if (mmbegun == 0) {
		++mmbegun;
		timeout(&mmtim, HZ/10, mmtime, (char *)tp);
	}
}

mmtime(xp)
char *xp;
{
	register int s;

	s = sphi();
	if (mmbeeps < 0) {
		mmbeeps = 2;
		outb(TIMCTL, 0xB6);	/* Timer 2, lsb, msb, binary */
		outb(TIMCNT, FREQ&0xFF);
	        outb(TIMCNT, FREQ>>8);
		outb(PORTB, inb(PORTB) | 03);	/* Turn speaker on */
	}
	else if ((mmbeeps > 0) && (--mmbeeps == 0))
		outb( PORTB, inb(PORTB) & ~03 );

	if (mmesc) {
		ismmfunc(mmesc);
		mmesc = 0;
	}
	spl(s);

	ttstart( (TTY *) xp );

	timeout(&mmtim, HZ/10, mmtime, xp);
}

/**
 *
 * void
 * mmwatch()	-- turn video display off after 15 minutes inactivity.
 */
void
mmwatch()
{
	if ( (mmcrtsav > 0) && (mmvcnt > 0) && (--mmvcnt == 0) )
		mm_voff();
}

mmwrite( dev, iop )
dev_t dev;
register IO *iop;
{
	int ioc;
	int s;

	ioc = iop->io_ioc;

	/*
	 * Kernel writes.
	 */
	if (iop->io_seg == IOSYS) {
		while (mmgo(iop))
			;
	}

	/*
	 * Blocking user writes.
	 */
	else if ( (iop->io_flag & IONDLY) == 0 ) {
		do {
			while (istty.t_flags & T_STOP) {
				s = sphi();
				istty.t_flags |= T_HILIM;
				sleep((char*) &istty.t_oq,
					CVTTOUT, IVTTOUT, SVTTOUT);
				spl( s );
			}
			/*
			 * Signal received.
			 */
			if ( SELF->p_ssig && nondsig() ) {
				kbunscroll();	/* update kbd LEDS */
				/*
				 * No data transferred yet.
				 */
				if ( ioc == iop->io_ioc )
					u.u_error = EINTR;
				/*
				 * Transfer remaining data
				 * without pausing after scrolling.
				 */
				else while ( mmgo(iop) )
					;

				return;
			}
			mmgo(iop);
		} while ( iop->io_ioc );
	}

	/*
	 * Non-blocking user writes with output stopped.
	 */
	else if ( istty.t_flags & T_STOP ) {
		u.u_error = EAGAIN;
		return;
	}

	/*
	 * Non-blocking user writes do not pause after scrolling.
	 */
	else {
		while ( mmgo(iop) )
			;
	}
}
0707070064030112651006440000000000000000011777770507310635600004700000104560/newbits/kernel/USRSRC/i8086/drv/ati.m/ (lgl-
/ 	COHERENT Driver Kit Version 1.0.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ Array Technologies Inc - Graphics Solution - Device Driver
/
/	 Supports 40/80/132 column color text
/		     80/132 column monochrome text
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal information
/		CX    - input count
/		BP    - references terminal information
/		AH    - character attributes
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
/ 
////////

	NCB	= 2		/ number of horizontal bytes per char
	NCR	= 1		/ number of horizontal lines per char
	NHB	= 160		/ number of horizontal bytes per line
	NRB	= NCR*NHB	/ number of bytes per character row

	ATTR	= ah		/ attribute byte
	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	INTENSE	= 0x08		/ high intensity attribute bit
	BLINK	= 0x80		/ blinking attribute bit
	REVERSE	= 0x70		/ reverse video

////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_BASE	= 8

	IOSYS	= 0
	IOUSR	= 1

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_INVIS	= 20		/ cursor invisible mask
MM_NCOL		= 22		/ number of columns
MM_DATA		= 24		/ pointer to crt data
MM_MODE		= 26		/ mode register [0x21=col80/132,0x20=col40]

/ ASCII characters
AZERO		= 0x30
CLOWER		= 0x63
SEMIC		= 0x3B
SPACE		= 0x20

	.prvd
mmdata:	.word	mminit
	.word	0x03D4
	.word	0xB800
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, 23, 24, 0, 0, 0, 23
	.word	0
	.word	80
	.word	creg80
	.byte	0x21, 0x00
	.shri

////////
/
/ creg40, creg80, creg132 - crt register values for 40/80/132 column color
/         mreg80, mreg132 - crt register values for 80/132 column monochrome
/
////////

creg40:	.byte	0x38, 0x28, 0x2D, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

creg80:	.byte	0x71, 0x50, 0x5A, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

mreg80:	.byte	0x61, 0x50, 0x52, 0x0F, 0x19, 0x06, 0x19, 0x19
	.byte	0x02, 0x0D, 0x0B, 0x0C, 0x00, 0x00, 0x00, 0x00

#ifdef ATI_132
	.globl	creg132
creg132:.byte	0xB5, 0x84, 0x97, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

	.globl	mreg132
mreg132:.byte	0x9F, 0x84, 0x89, 0x0F, 0x19, 0x06, 0x19, 0x19
	.byte	0x02, 0x0D, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00
#endif

////////
/
/ mmgo( iop )
/ IO *iop;
/
////////

	.globl	mmgo_

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc
	cmp	IO_SEG(bx), $IOSYS
	je	0f
	mov	ds, uds_
0:	mov	bp, $mmdata

	mov	dx, MM_PORT(bp)		/ turn video off if color board
	cmp	dx, $0x3B4
	je	0f
	add	dx, $4
	movb	al, MM_MODE(bp)
	outb	dx, al
0:
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	sub	bx, bx
	movb	ATTR, MM_ATTR(bp)
	ijmp	MM_FUNC(bp)

exit:	pop	bx
	pop	es
	pop	ds
	movb	MM_ATTR(bp), ATTR
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, MM_PORT(bp)		/ adjust cursor location
	mov	bx, POS
	or	bx, MM_INVIS(bp)
	shr	bx, $1

	movb	al, $14
	outb	dx, al
	inc	dx
	movb	al, bh
	outb	dx, al
	dec	dx
	movb	al, $15
	outb	dx, al
	inc	dx
	movb	al, bl
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ turn video on
	add	dx, $4
	movb	al, MM_MODE(bp)
	orb	al, $0x08
	outb	dx, al
	mov	mmvcnt_, $300		/ 300 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $CLOWER		/ schedule keyboard initialization
	mov	MM_NCOL(bp), $80	/ set 80 column mode
	movb	MM_MODE(bp), $0x21
	mov	MM_DATA(bp), $creg80

#ifdef	ATI_132
	mov	dx, $0x3DF		/ clear 132 column color
	movb	al, $0x00		/ in mode select register
	outb	dx, al

	mov	dx, $0x3BA		/ clear 132 column monochrome
	movb	al, $0x00		/ in mode select register
	outb	dx, al
#endif

	call	int11_			/ read equipment status
	andb	al, $0x30		/ isolate video bits
	cmpb	al, $0x30		/ if monochrome
	jne	0f
	mov	MM_DATA(bp), $mreg80	/	set monochrome register info
	mov	MM_PORT(bp), $0x3B4	/	set monochrome port
	mov	MM_BASE(bp), $0xB000	/	set monochrome base
	mov	es, MM_BASE(bp)		/		and extra segment.

0:	call	newcrt			/ reprogram crt registers

reinit:	sub	ax, ax			/ regenerate row table
	mov	bx, $rowtab
1:	mov	ss:(bx), ax
	add	ax, MM_NCOL(bp)
	add	ax, MM_NCOL(bp)
	add	bx, $2
	cmp	bx, $rowend
	jb	1b

	mov	dx, MM_PORT(bp)		/ zero display offset
	movb	al, $12
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al
	dec	dx
	movb	al, $13
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ reset border to black
	add	dx, $5
	subb	al, al
	outb	dx, al

	mov	MM_INVIS(bp), $0
	movb	ATTR, $0x07
	movb	MM_ATTR(bp), ATTR
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ newcrt -- reload crt registers
/
/	Action:	Program crt registers with values defined in code space
/		at offset given by MM_DATA(bp).
/
/	Note:	AX, BX, DX, DI trashed on exit.
/
////////

newcrt:	mov	dx, MM_PORT(bp)		/ turn video off
	add	dx, $4
	movb	al, MM_MODE(bp)
	outb	dx, al

	mov	di, MM_DATA(bp)		/ program crt registers, last to first
	mov	bx, $15			/ [delay between i/o]
	mov	dx, MM_PORT(bp)		/ [NOTE:DI=obsolete screen offset]
0:	movb	al, bl
	outb	dx, al
	movb	al, cs:(bx,di)
	inc	dx
	outb	dx, al
	dec	dx
	dec	bx
	jge	0b
	ret

////////
/
/ mm_so - stand out - define 40 column attributes
/
////////

mm_so:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	mm_si

	mov	MM_NCOL(bp), $40	/	setup for 40 column color
	movb	MM_MODE(bp), $0x20
	mov	MM_DATA(bp), $creg40

#ifdef	ATI_132
	mov	dx, $0x3DF		/	clear 132 column color
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/ program crt registers
	jmp	reinit

////////
/
/ mm_si - define 80 column attributes
/
////////

mm_si:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	0f

	mov	MM_NCOL(bp), $80
	movb	MM_MODE(bp), $0x21
	mov	MM_DATA(bp), $creg80

#ifdef	ATI_132
	mov	dx, $0x3DF		/	clear 132 column color
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/	reprogram crt registers.
	jmp	reinit

0:	mov	MM_NCOL(bp), $80
	mov	MM_DATA(bp), $mreg80
	movb	MM_MODE(bp), $0x21

#ifdef	ATI_132
	mov	dx, $0x3BA		/	clear 132 column monochrome
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/	reprogram crt registers
	jmp	reinit

////////
/
/ mm_132 - define 132 column attributes
/
////////

mm_132:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	0f

#ifdef	ATI_132
	mov	MM_DATA(bp), $creg132	/	set color crt values
	mov	MM_NCOL(bp), $132	/	set columns to 132
	movb	MM_MODE(bp), $0x21

	call	newcrt			/	set 132 column crt values
					/	BEFORE setting mode select reg

	mov	dx, $0x3DF		/	set 132 columns
	movb	al, $0x10		/		in mode select register
	outb	dx, al
#endif
	jmp	reinit

0:
#ifdef	ATI_132
	mov	MM_NCOL(bp), $132	/	set columns to 132
	movb	MM_MODE(bp), $0x21	/	set 80/132 column display mode
	mov	MM_DATA(bp), $mreg132	/	set monochrome crt values

	call	newcrt			/	set 132 column crt values
					/	BEFORE setting mode select reg

	mov	dx, $0x3BA		/	set 132 columns monochrome
	movb	al, $0x08		/		in mode select register
	outb	dx, al
#endif
	jmp	reinit

////////
/
/ mmspec - schedule special keyboard function
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
	mov	si, ss:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, ss:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	cld
	rep
	movsw
	movb	al, $SPACE
	pop	di
	mov	cx, MM_NCOL(bp)
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, ss:rowtab(bx)
	call	exit
	jmp	eval

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, COL			/ reposition to ROW and COL
	shl	bx, $1			/ [trash BH]
	mov	POS, cs:coltab(bx)
	subb	bh, bh			/ [clear BH]
	movb	bl, ROW
	shlb	bl, $1
	add	POS, ss:rowtab(bx)
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	stosw
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jnb	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	sub	POS, $2
	subb	COL, $1
	jnb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
0:	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $SEMIC
	je	csi_n2
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	1f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

1:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csgtab(bx)

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jnb	0f
	subb	COL, COL		/ cannot step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process ESC [ > N1 h escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process ESC [ > N1 l escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	push	cx
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl
	movb	al, $SPACE
	rep
	stosw
	pop	cx
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	eval

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The 1st parameter (mm_n1) specifies the vertical   position MM_ROW(bp).
/	The 2nd parameter (mm_n2) specifies the horizontal position MM_COL(bp).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	orb	ROW, ROW
	je	0f
	decb	ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
	mov	si, ss:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, ss:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	rep
	movsw
	mov	di, ss:rowtab(bx)
	mov	cx, MM_NCOL(bp)
	movb	al, $SPACE
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input, and causing cursor to vanish.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2


////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

mm_e2:	push	cx
	movb	al, $SPACE
0:	mov	cx, MM_NCOL(bp)
	rep
	stosw
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

mm_e1:	push	cx
	mov	cx, POS
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

mm_e0:	push	cx
	shlb	bl, $1
	mov	cx, ss:rowtab+2(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, ss:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, ss:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, ss:rowtab(bx)
	jle	0f
	shr	cx, $1
	std
	rep
	movsw
	mov	di, ss:rowtab(bx)
	mov	cx, MM_NCOL(bp)
	movb	al, $SPACE
	cld
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	orb	ROW, ROW
	je	0f
	decb	ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	 MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_INVIS(bp), $0
	jmp	eval

0:	mov	MM_INVIS(bp), $-1
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					5 - slow blink
/					7 - reverse video
/					30-37 - foreground color
/					40-47 - background color
/					50-57 - border color
/
////////

mm_sgr:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	ATTR, $0x07
1:	jmp	eval
0:	cmpb	al, $1		/ bold
	jne	0f
	orb	ATTR, $INTENSE
	jmp	1b
0:	cmpb	al, $4		/ underline
	jne	0f
	cmp	MM_PORT(bp), $0x03D4	/ color card?
	je	1b			/ yes, ignore underline
	andb	ATTR, $~0x77
	orb	ATTR, $0x01
	jmp	1b
0:	cmpb	al, $5		/ blinking
	jne	0f
	orb	ATTR, $BLINK
	jmp	1b
0:	cmpb	al, $7		/ reverse video
	jne	0f
	movb	al, $0x70
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f
	movb	al, ah			/ yes, exchange foreground/background
	andb	al, $0x77
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
2:	andb	ATTR, $~0x77
	orb	ATTR, al
	jmp	1b
0:	cmp	MM_PORT(bp), $0x03D4	/ color card?
	jne	1b			/ no, ignore remaining options
0:	subb	al, $30		/ foreground color
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x07
	orb	ATTR, cs:fcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x70
	orb	ATTR, cs:bcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	movb	al, cs:fcolor(bx)
	push	dx
	mov	dx, MM_PORT(bp)
	add	dx, $5
	outb	dx, al
	pop	dx
/	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	mmbell	/	EOT  ENQ  ACK  BEL
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/	BS   HT   LF   VT
	.word	eval,	mm_cr,	mm_so,	mm_si	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
/ DEBUG: mm_132 is only inserted temporarily, for testing - 86/05/26
	.word	eval,	eval,	eval,	mm_132	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	mm_esc	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	  ! dquote # \040 - \043
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	$ % & quote \044 - \047
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	( ) * + \050 - \053
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	, - . / \054 - \057
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	0 1 2 3 \060 - \063
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	4 5 6 7 \064 - \067
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	8 9 : ; \070 - \073
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	< = > ? \074 - \077
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	@ A B C \100 - \103
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	D E F G \104 - \107
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	H I J K \110 - \113
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	L M N O \114 - \117
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	P Q R S \120 - \123
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	T U V W \124 - \127
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	X Y Z [ \130 - \133
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	\ ] ^ _ \134 - \137
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	` a b c \140 - \143
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	d e f g \144 - \147
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	h i j k \150 - \153
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	l m n o \154 - \157
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	p q r s \160 - \163
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	t u v w \164 - \167
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	x y z { \170 - \173
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	| } ~ ? \174 - \177

////////
/
/ esctab - table of functions indexed by escape characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/	NUL  SOH  STX  ETX
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	EOT  ENQ  ACK  BEL
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	BS   HT   LF   VT
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	FF   CR   SO   SI
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	DLE  DC1  DC2  DC3
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	DC4  NAK  SYN  ETB
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	CAN  EM   SUB  ESC
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! dquote # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & quote \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	mm_new	/	4 5 6 7 \064 - \067
	.word	mm_old,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	mmspec,	mmspec,	eval	/	< = > ? \074 - \077
	.word	eval,	eval,	eval,	eval	/	@ A B C \100 - \103
	.word	mm_ind,	mm_cnl,	eval,	eval	/	D E F G \104 - \107
	.word	eval,	eval,	eval,	eval	/	H I J K \110 - \113
	.word	eval,	mm_ri,	eval,	eval	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	eval	/	P Q R S \120 - \123
	.word	eval,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	eval,	csi_n1	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	mm_dmi,	eval,	mm_emi,	mminit	/	` a b c \140 - \143
	.word	eval,	eval,	eval,	eval	/	d e f g \144 - \147
	.word	eval,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	eval,	eval,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	eval,	eval	/	p q r s \160 - \163
	.word	mmspec,	mmspec,	eval,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	eval	/	EOT  ENQ  ACK  BEL
	.word	eval,	eval,	eval,	eval	/	BS   HT   LF   VT
	.word	eval,	eval,	eval,	eval	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
	.word	eval,	eval,	eval,	eval	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	eval	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! dquote # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & quote \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	eval	/	4 5 6 7 \064 - \067
	.word	eval,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	eval,	csi_gt,	eval	/	< = > ? \074 - \077
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/	@ A B C \100 - \103
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/	D E F G \104 - \107
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/	H I J K \110 - \113
	.word	mm_il,	mm_dl,	eval,	mm_ea	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	mm_ind	/	P Q R S \120 - \123
	.word	mm_ri,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	mm_cbt,	eval	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	mm_hpa,	mm_hpr,	eval,	eval	/	` a b c \140 - \143
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/	d e f g \144 - \147
	.word	eval,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	eval,	mm_sgr,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	mm_ssr,	eval	/	p q r s \160 - \163
	.word	eval,	eval,	mm_scr,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ csgtab - table of functions indexed by ESC [ > characters.
/
////////

csgtab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	eval	/	EOT  ENQ  ACK  BEL
	.word	eval,	eval,	eval,	eval	/	BS   HT   LF   VT
	.word	eval,	eval,	eval,	eval	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
	.word	eval,	eval,	eval,	eval	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	eval	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! dquote # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & quote \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	eval	/	4 5 6 7 \064 - \067
	.word	eval,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	eval,	eval,	eval	/	< = > ? \074 - \077
	.word	eval,	eval,	eval,	eval	/	@ A B C \100 - \103
	.word	eval,	eval,	eval,	eval	/	D E F G \104 - \107
	.word	eval,	eval,	eval,	eval	/	H I J K \110 - \113
	.word	eval,	eval,	eval,	eval	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	eval	/	P Q R S \120 - \123
	.word	eval,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	eval,	eval	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	eval,	eval,	eval,	eval	/	` a b c \140 - \143
	.word	eval,	eval,	eval,	eval	/	d e f g \144 - \147
	.word	mm_cgh,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	mm_cgl,	eval,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	eval,	eval	/	p q r s \160 - \163
	.word	eval,	eval,	eval,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ coltab - integer array of offsets to each column - up to 132 columns
/
////////

coltab:	.word	  0*NCB,   1*NCB,   2*NCB,   3*NCB
	.word	  4*NCB,   5*NCB,   6*NCB,   7*NCB
	.word	  8*NCB,   9*NCB,  10*NCB,  11*NCB
	.word	 12*NCB,  13*NCB,  14*NCB,  15*NCB
	.word	 16*NCB,  17*NCB,  18*NCB,  19*NCB
	.word	 20*NCB,  21*NCB,  22*NCB,  23*NCB
	.word	 24*NCB,  25*NCB,  26*NCB,  27*NCB
	.word	 28*NCB,  29*NCB,  30*NCB,  31*NCB
	.word	 32*NCB,  33*NCB,  34*NCB,  35*NCB
	.word	 36*NCB,  37*NCB,  38*NCB,  39*NCB
	.word	 40*NCB,  41*NCB,  42*NCB,  43*NCB
	.word	 44*NCB,  45*NCB,  46*NCB,  47*NCB
	.word	 48*NCB,  49*NCB,  50*NCB,  51*NCB
	.word	 52*NCB,  53*NCB,  54*NCB,  55*NCB
	.word	 56*NCB,  57*NCB,  58*NCB,  59*NCB
	.word	 60*NCB,  61*NCB,  62*NCB,  63*NCB
	.word	 64*NCB,  65*NCB,  66*NCB,  67*NCB
	.word	 68*NCB,  69*NCB,  70*NCB,  71*NCB
	.word	 72*NCB,  73*NCB,  74*NCB,  75*NCB
	.word	 76*NCB,  77*NCB,  78*NCB,  79*NCB
	.word	 80*NCB,  81*NCB,  82*NCB,  83*NCB
	.word	 84*NCB,  85*NCB,  86*NCB,  87*NCB
	.word	 88*NCB,  89*NCB,  90*NCB,  91*NCB
	.word	 92*NCB,  93*NCB,  94*NCB,  95*NCB
	.word	 96*NCB,  97*NCB,  98*NCB,  99*NCB
	.word	100*NCB, 101*NCB, 102*NCB, 103*NCB
	.word	104*NCB, 105*NCB, 106*NCB, 107*NCB
	.word	108*NCB, 109*NCB, 110*NCB, 111*NCB
	.word	112*NCB, 113*NCB, 114*NCB, 115*NCB
	.word	116*NCB, 117*NCB, 118*NCB, 119*NCB
	.word	120*NCB, 121*NCB, 122*NCB, 123*NCB
	.word	124*NCB, 125*NCB, 126*NCB, 127*NCB
	.word	128*NCB, 129*NCB, 130*NCB, 131*NCB

////////
/
/ rowtab - array of offsets to each row - up to 44 rows
/	   automatically regenerated by reinit().
/
/	NOTE: In kernel data space to allow modification in protected mode.
/
////////

	.shrd
rowtab:	.word	 0*NRB,	 1*NRB,	 2*NRB,	 3*NRB
	.word	 4*NRB,	 5*NRB,	 6*NRB,	 7*NRB
	.word	 8*NRB,	 9*NRB,	10*NRB,	11*NRB
	.word	12*NRB,	13*NRB,	14*NRB,	15*NRB
	.word	16*NRB,	17*NRB,	18*NRB,	19*NRB
	.word	20*NRB,	21*NRB,	22*NRB,	23*NRB
	.word	24*NRB,	25*NRB,	26*NRB,	27*NRB
	.word	28*NRB,	29*NRB,	30*NRB,	31*NRB
	.word	32*NRB,	33*NRB,	34*NRB,	35*NRB
	.word	36*NRB,	37*NRB,	38*NRB,	39*NRB
	.word	40*NRB,	41*NRB,	42*NRB,	43*NRB
rowend:
	.shri

////////
/
/ fcolor - foreground color
/ bcolor - background color
/
/	indexed by ansi color (black,red,green,brown,blue,magenta,cyan,white)
/	yields graphics color (black,blue,green,cyan,red,magenta,brown,white)
/		which is properly shifted for installation in attribute byte.
/
////////

fcolor:	.byte	0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
bcolor:	.byte	0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70

////////
/
/ mm_voff()	-- Disable video display.
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, mmdata+MM_PORT
	add	dx, $4
	movb	al, mmdata+MM_MODE
	outb	dx, al
	ret

////////
/
/ mm_von()	-- Enable video display
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, mmdata+MM_PORT	/ enable video display
	add	dx, $4
	movb	al, mmdata+MM_MODE
	orb	al, $0x08
	outb	dx, al
	mov	mmvcnt_, $300		/ 300 seconds before video disabled
	ret
0707070064030140061004440000030000030000011777770507310636500004600000020135/newbits/kernel/USRSRC/i8086/drv/ms.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 *	Microsoft bus mouse (rodent) driver.
 */

#include <sys/coherent.h>
#include <sys/uproc.h>
#include <sys/con.h>
#include <sys/devices.h>
#include <sys/ms.h>
#include <errno.h>

#define Help(fmt, p)		printf(fmt, p)
#define Help2(fmt, p, q)	printf(fmt, p, q)
#define Diag(fmt, p)		/* Help(fmt, p) */
#define Diag2(fmt, p, q)	/* Help2(fmt, p, q) */

/*
 *	global patchable definitions
 */
unsigned MSPORT  = 0x23C;	/* mouse 8255A registers: */
				/* modified mouse is 0x23C */
				/* Geac modified mouse is 0x230 */
unsigned MSIRQ   = 2;		/* mouse interrupt # */

/*
 *	driver function definitions
 */
int	msload();
int	msunload();
int	msopen();
int	msclose();
int	msioctl();
int	mspoll();
int	msintr();
int	nulldev();
int	nonedev();

/*
 *	configuration table
 */
CON mscon = {
	DFCHR|DFPOL,			/* flags	*/
	MS_MAJOR,			/* major index	*/
	msopen,				/* open		*/
	msclose,			/* close	*/
	nonedev,			/* block	*/
	nonedev,			/* read		*/
	nonedev,			/* write	*/
	msioctl,			/* ioctl	*/
	nulldev,			/* power fail	*/
	nulldev,			/* timeout	*/
	msload,				/* load		*/
	msunload,			/* unload	*/
	mspoll				/* poll		*/
};

/*
 *	ioctl function definitions
 */

int	ms_setup();
int	ms_setcrs();
int	ms_readcrs();
int	ms_setmick();
int	ms_readmick();
int	ms_readbtns();
int	ms_readstat();
int	ms_wait();

int (*ioctls[])() = {
  /*	   0	     1		 2	     3		  4		*/
	ms_setup, ms_setcrs, ms_readcrs, ms_setmick, ms_readmick,

  /*	     5		 6	   7					*/
	ms_readbtns, ms_readstat, ms_wait
};

/*
 *	hardware constants
 */
static	int	porta;			/* 	port A (read/write) */
static	int	portb;			/*	port B (read/write) */
static	int	portc;			/*	port C (read/write) */
static	int	portcm;			/*	control port (write only) */

static	int	u_stts	=  0;		/* changed-status flags */
static	int	u_mask	=  0;		/* user condition mask */

static	event_t	ipolls;

static struct msparms parms, initparm = {
	2, -16, 655, -16, 215, 8, 16
};

static struct mspos crsr, csav, initcrsr = { 320, 100 };

static struct msmick mick, initmick = { 0, 0 };

static struct msbuts buttons, initbuttons = {
	0,
	{	{0, {320, 100}},
		{0, {320, 100}},
		{0, {320, 100}},
		{0, {320, 100}}
	}
};

static	int	ms_inuse = 0;		/* is mouse in use ? */

msload()
{
	int s;

	porta  = MSPORT;
	portb  = MSPORT + 1;
	portc  = MSPORT + 2;
	portcm = MSPORT + 3;

	s = sphi();
	outb( portcm, 0x91 );		/* set 8255A mode 9 */
	outb( portc,  0x10 );		/* disable interrupt */
	setivec( MSIRQ, msintr );	/* set up irq vector */
	spl(s);

	return 0;
}

/*
 * Unload function.
 */
msunload()
{
	clrivec( MSIRQ );		/* release irq vector */
	outb( portcm, 0x91 );		/* set 8255A mode 9 */
	outb( portc,  0x10 );		/* disable interrupt */
}

msopen(dev, mode)
dev_t	dev;
{
	int	s;

	s = sphi(s);
	if (ms_inuse) {
		u.u_error = EDBUSY;
		spl(s);
		return( -1 );
	}

	outb( portcm, 0x91 );			/* set 8255A mode 9 */
	outb( portb,  0x5a );

	if( inb( portb ) != 0x5a) {		/* hardware installed? */
		u.u_error = ENXIO;
		spl(s);
		return( -1 );
	}

	outb( portc, 0x90 );
	inb( porta );
	outb( portc, 0xb0 );
	inb( porta );
	outb( portc, 0xd0 );
	inb( porta );
	outb( portc, 0xf0 );
	inb( porta );
	outb( portc, 0 );		/* clear all mouse registers */

/* set things */
	parms = initparm;
	crsr = csav = initcrsr;
	mick = initmick;
	buttons = initbuttons;
	u_stts = u.u_error = 0;
	ms_inuse = 1;
	spl(s);

	return( 0 );
}

msclose()
{
	int s;

	s = sphi();
	outb( portc, 0x10 );			/* disable interrupt */
	ms_inuse = u.u_error = 0;
	spl(s);
	return( 0 );
}

msioctl( dev, com, vec )
dev_t	dev;
int	com;
char	*vec;
{
	int s;

	s = sphi();
	if (com >= 0 && com < sizeof(ioctls)/sizeof(ioctls[0])) {
		(*ioctls[com])(vec);	/* indirect func call */
		u.u_error = 0;
	} else
		u.u_error = EINVAL;
	spl(s);
	if (u.u_error)
		return( -1 );

	return( 0 );
}

/*
 * Polling routine.
 * [System V.3 Compatible].
 */
mspoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	ev &= ~POLLPRI;
	ev &= ~POLLOUT;

	/*
	 * No input.
	 */
	if ( (u_stts & u_mask) == 0 ) {
		/*
		 * Enable monitor if blocking poll.
		 */
		if ( msec != 0 ) 
			pollopen( &ipolls );
		/*
		 * Look again to avoid interrupt race.
		 */
		if ( (u_stts & u_mask) == 0 )
			ev &= ~POLLIN;
	}

	return ev;
}

/*
 *	write setup structure
 */
ms_setup( newparm )
struct msparms *newparm;
{
	ukcopy(newparm, &parms, sizeof(struct msparms));
	if (parms.h_mpr == 0)
		parms.h_mpr = 1;
	if (parms.v_mpr == 0)
		parms.v_mpr = 1;
}

/*
 *	write cursor position
 */
ms_setcrs( pos )
struct mspos *pos;
{
	ukcopy(pos, &crsr, sizeof(struct mspos));
	u_stts &= ~MS_S_MOVE;		/* clear u_stts pos bit */
}

/*
 *	read cursor postion
 */
ms_readcrs( pos )
struct mspos *pos;
{
	kucopy(&crsr, pos, sizeof(struct mspos));
	u_stts &= ~MS_S_MOVE;		/* clear u_stts pos bit */
}

/*
 *	write mickey postion
 */
ms_setmick( pos )
struct msmick *pos;
{
	ukcopy(pos, &mick, sizeof(struct msmick));
}

/*
 *	read mickey postion
 */
ms_readmick( pos )
struct msmick *pos;
{
	kucopy(&mick, pos, sizeof(struct msmick));
}

/*
 *	read button status
 */
ms_readbtns( btns )
struct msbuts *btns;
{
	kucopy(&buttons, btns, sizeof(struct msbuts));
	u_stts &= ~MS_S_BUTTONS;		/* clear u_stts button bits */
}

/*
 *	read "changed status" mask
 */
ms_readstat( stat )
int *stat;
{
	kucopy(&u_stts, stat, sizeof(int));
}

/*
 *	wait on "changed status" mask
 */
ms_wait( flag )
int *flag;
{
	ukcopy(flag, &u_mask, sizeof(int));
	while ((u_mask & u_stts) == 0)	/* wait until any bit is on */
		sleep(&u_stts, 0x7fff, 0x7fff, 0);
	u_mask = 0;
}

/*
 *	mouse interrupt service routine
 */
msintr()
{
	static	int h_fpix =  0;			/* fractional pixel */
	static	int v_fpix = 0;				/* ditto */
	int	s, n_l, n_h, h_diff, v_diff, tmp, left, right;

	if (!ms_inuse)			/* dev not open - ignore interrupts */
		return;
	
	s = sphi();
	outb( portc, 0x90 );		/* get horizontal change */
	n_l = inb( porta );
	outb( portc, 0xb0 );
	n_h = inb( porta );
	h_diff = (char) ((n_l & 0x0f) | (n_h << 4));

	outb( portc, 0xd0 );		/* get vertical change */
	n_l = inb( porta );
	outb( portc, 0xf0 );
	n_h = inb( porta );
	v_diff = (char) ((n_l & 0x0f) | (n_h << 4));

	outb( portc, 0 );
	left = right = 0;				/* set button status */
	if (!(n_h & 0x80)) left = MS_L_DOWN;		/* left button.. */
	if ((buttons.bbstat & MS_L_DOWN) ^ left) {
		if (left)
			button(MS_B_L_PRESS,   MS_S_L_PRESS);
		else
			button(MS_B_L_RELEASE, MS_S_L_RELEASE);
	}
	if (!(n_h & 0x20))				/* right button.. */
		right = MS_R_DOWN;
	if ((buttons.bbstat & MS_R_DOWN) ^ right) {
		if (right)
			button(MS_B_R_PRESS,   MS_S_R_PRESS);
		else
			button(MS_B_R_RELEASE, MS_S_R_RELEASE);
	}

	buttons.bbstat = left | right;		/* set new button status */

	if (h_diff || v_diff) {			/* any motion? */
		mick.h_mick += h_diff;		/* yes - update positions */
		mick.v_mick += v_diff;
		if ((abs(h_diff) > parms.accel_t) || (abs(v_diff) > parms.accel_t)) {
			h_diff *= 2;
			v_diff *= 2;
		}

		if (h_diff) {			/* horizontal change */
			tmp   = h_fpix + 8 * h_diff;
			h_fpix = tmp % parms.h_mpr;
			tmp    = crsr.h_crsr + tmp / parms.h_mpr;
			crsr.h_crsr = c_range(tmp, parms.h_cmin, parms.h_cmax);
		}

		if (v_diff) {			/* vertical change */                                                                                                                                                                                           
			tmp   = v_fpix + 8 * v_diff;
			v_fpix = tmp % parms.v_mpr;
			tmp    = crsr.v_crsr + tmp / parms.v_mpr;
			crsr.v_crsr = c_range(tmp, parms.v_cmin, parms.v_cmax);
		}

		if ((crsr.h_crsr != csav.h_crsr) || (crsr.v_crsr != csav.v_crsr)) {
			u_stts |= MS_S_MOVE;
			csav = crsr;
		}
	}

	if (u_stts & u_mask) {
		wakeup(&u_stts);
		if ( ipolls.e_procp )
			pollwake( &ipolls );
	}

	spl(s);
}

/*
 *	update button-press/release data
 */
button( bp, sbit )
int bp;
unsigned sbit;
{
	++buttons.buts[bp].cnt;
	buttons.buts[bp].bpos = crsr;
	u_stts |= sbit;
}

/*
 *	force return value to be within specified range
 */
c_range(c, cmin, cmax)
int	c, cmin, cmax;
{
	if( c < cmin )
		c = cmin;
	else if( c > cmax )
		c = cmax;
	return( c );
}

abs(i)
int i;
{
	if (i < 0)
		return (-i);
	return i;
}
0707070064030034521004440000030000030000011777770507310636700004700000044047/newbits/kernel/USRSRC/i8086/drv/msg.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1986, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Messaging
 *
 *	This module provides System V compatible messaging operations.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Oct 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:09:07	src
 * *** empty log message ***
 * 
 * Revision 1.2	88/08/02  16:49:52	src
 * Bug:	msgget with IPC_CREAT could fail if message queue already
 * 	existed, and queue permissions were not an exact match
 * 	for requested permissions.
 * Fix:	Permission checking made more rigorous.
 * 
 * Revision 1.1	88/03/24  17:05:44	src
 * Initial revision
 * 
 * 87/04/24	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgctl() IPC_STAT check of polled devices modified.
 *
 * 87/04/01	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgctl() now correctly reports polling events on an IPC_STAT operation.
 *
 * 87/03/20	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgpoll() now correctly reports POLLOUT events.
 *
 * 87/01/20	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * msginit() is now more paranoid about validating NMSC, NMSG, NMSQID.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * msginit() now allocates message buffers in high memory.
 *
 * 86/12/12	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Added 3rd argument to msgpoll() to support non-blocking polls.
 *
 * 86/11/21	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Added support for System V.3 compatible polls.
 * Added msgpoll() routine and xmsqid_ds structure.
 *
 * 85/08/06	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msg.c split into configuration (msgcon.c) and implementation (msg.c).
 *
 * 85/07/22	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgget, msgctl, msgsnd, msgrcv now return immediately if u.u_error is set.
 *
 * 85/07/19	Allan Cornish
 * Msgrcv() now reports E2BIG if message is larger than size requested.
 * Msgfree() integrated into msginit() and msgrcv() functions.
 * Msgsnd() now checks for queue removal after waking from sleep.
 * Msgsnd() and msgrcv() now detect address faults and report EFAULT.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Replaced msgaccess() by calls to ipcaccess(), increasing shared ipc code.
 * Eliminated many calls to sphi() and spl().  They are not really required,
 * since system calls are synchronous unless they sleep or are interrupted.
 * Sleeps cause no problem, and interrupts do not affect messaging state.
 *
 * 85/06/19	Allan Cornish
 * Added code to msgctl to allow the owner of a queue to reduce msg_qbytes.
 * Previously only the super-user could modify msg_qbytes.
 *
 * 85/06/18	Allan Cornish
 * Added code to msgsnd to check for full queue (msg_cbytes >= msg_qbytes).
 * Integrated msgalloc function into msgsnd, since only called from there.
 * Fixed bug in msgrcv when msgtyp < 0, to treat msg_type as mesg priority.
 *
 * 85/05/10	Allan Cornish
 * C compiler bug in msginit caused 'mp->msg_spot = (wanted -= NMSC)' to fail.
 * For NMSG=10, NMSC=640, msg_spot always set to 0x1900 or 0xE980.
 * Code changed to 'wanted -= NMSC; mp->msg_spot = wanted'.
 *
 * 85/04/01	Allan Cornish
 * fixed qp->msg_last bug in msgrcv().
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <seg.h>
#include <msg.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif

/*
 * Extended message queue id data structure.
 *	- extended to support System V.3 compatible polls.
 */
struct xmsqid_ds {
	struct msqid_ds	msq;
	struct event	ipolls;
	struct event	opolls;
};

/*
 *	Message Information
 */

struct xmsqid_ds *msqs = 0;	/* Pointer to array of message queues */
				/* (first queue contains free message list) */

struct msg * msgs = 0;		/* Pointer to array of message headers */

static SEG * msgsp;		/* Segment containing messages */
#define	msgsel FP_SEL(msgsp->s_faddr)

/*
 *	Global Message Parameters
 */

unsigned NMSQID = 9;	/* allocated number of message queues */
unsigned NMSQB  = 2048;	/* default maximum queue size in bytes */
unsigned NMSG = 10;	/* allocated messages: (NMSG * NMSC) < 2^16 */
unsigned NMSC = 640;	/* maximum message text size */

/*
 * Message Device Initialization.
 *
 *	Initialize message ids.
 */

msginit()
{
	register struct xmsqid_ds *qp;
	register struct msg *mp;
	long wanted;
	int i;

	if ( NMSG == 0 )
		NMSQID = 0;
	if ( NMSC == 0 )
		NMSQID = 0;
	if ( NMSQID == 0 )
		return 0;

	if ( NMSQID > 128 )
		NMSQID = 128;

	/*
	 * Allocate message queues and message headers.
	 */
	wanted = (NMSQID * (long) sizeof(struct xmsqid_ds)) +
		(NMSG * (long) sizeof(struct msg));
	if (wanted > 16384) {
		printf("invalid NMSQID or NMSG kernel variable\n");
		NMSQID=0;
		return;
	}

	if ( msqs = kalloc( (unsigned) wanted) ) {

		/*
		 * Ensure allocated space is cleared.
		 */
		memset( msqs, 0, (unsigned) wanted );

		/*
		 * Message headers are contiguous to message queues.
		 */
		msgs = (struct msg *) (&msqs[NMSQID]);

		/*
		 * Allocate message buffers.
		 */
		wanted = (long) NMSG * NMSC;
		if ( wanted > 0xFFFFL ) {
			printf("invalid NMSG or NMSC kernel variable\n");
			kfree( msqs );
			NMSQID = 0;
			msqs   = 0;
			return;
		}

		msgsp = salloc( (size_t) wanted, SFHIGH|SFNSWP|SFNCLR );

		if ( msgsp == 0 ) {
			printf("could not salloc %u messages\n", NMSG);
			kfree( msqs );
			NMSQID = 0;
			msqs   = 0;
			return;
		}

		/*
		 * Initialize message queues.
		 */
		for ( qp = msqs, i = 0; i < NMSQID; i++, qp++ ) {

			qp->msq.msg_perm.seq  = i * 256;

			qp->ipolls.e_dnext =
			qp->ipolls.e_dlast = &qp->ipolls;

			qp->opolls.e_dnext =
			qp->opolls.e_dlast = &qp->opolls;
		}

		/*
		 * Initialize message headers, place on free queue.
		 */
		for ( qp = msqs, mp = &msgs[NMSG]; --mp >= msgs; ) {
			wanted -= NMSC;
			mp->msg_spot  = wanted;
			mp->msg_next  = qp->msq.msg_first;
			qp->msq.msg_first = mp;
		}
	}
	else {
		printf("could not kalloc %u message ids\n", NMSQID);
		NMSQID = 0;
	}
}


/*
 * Msgctl - Message Control Operations.
 */

umsgctl( qid, cmd, buf )

int qid;
int cmd;
struct msqid_ds *buf;

{
	register struct xmsqid_ds *qp;
	register struct msg *mp;
	unsigned n;

	/*
	 * Validate queue identifier.
	 */
	if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( (qp == 0) || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	/*
	 * Validate qid for all commands except for IPC_STAT.
	 */
	if ( (cmd != IPC_STAT) && (qp->msq.msg_perm.seq != qid) ) {
		u.u_error = EINVAL;
		return -1;
	}

	switch ( cmd ) {

	case IPC_STAT:
		/*
		 * Validate access authority.
		 */
		if ( (ipcaccess(&qp->msq.msg_perm) & MSG_R) == 0 ) {
			u.u_error = EACCES;
			break;
		}

		/*
		 * Copy queue info to user.
		 */
		kucopy( qp, buf, sizeof(struct msqid_ds) );

		/*
		 * Include input polls in receive waiting.
		 */
		if ( (qp->ipolls.e_dnext != NULL)
		  && (qp->ipolls.e_dnext != &qp->ipolls) ) {
			putuwd( &buf->msg_perm.mode,
				getuwd( &buf->msg_perm.mode ) | MSG_RWAIT );
		}

		/*
		 * Include output polls in write waiting.
		 */
		if ( (qp->opolls.e_dnext != NULL)
		  && (qp->opolls.e_dnext != &qp->opolls) ) {
			putuwd( &buf->msg_perm.mode,
				getuwd( &buf->msg_perm.mode ) | MSG_WWAIT );
		}

		/*
		 * Validate qid.
		 * Doing it now lets user get info on message queue.
		 */
		if ( qp->msq.msg_perm.seq != qid )
			u.u_error = EINVAL;
		break;

	case IPC_SET:
		/*
		 * Validate modify authority.
		 */
		if ( (u.u_uid != 0) && (u.u_uid != qp->msq.msg_perm.uid) ) {
			u.u_error = EPERM;
			break;
		}

		/*
		 * Get desired queue size.
		 */
		n = getuwd( &(buf->msg_qbytes) );
		if (u.u_error)
			break;

		/*
		 * Only super-user can increase queue size.
		 */
		if ( (u.u_uid != 0) && (n > qp->msq.msg_qbytes) ) {
			u.u_error = EPERM;
			break;
		}

		/*
		 * Set queue parameters.
		 */
		qp->msq.msg_perm.uid   = getuwd( &(buf->msg_perm.uid ) );
		qp->msq.msg_perm.gid   = getuwd( &(buf->msg_perm.gid ) );
		qp->msq.msg_perm.mode &= ~0777;
		qp->msq.msg_perm.mode |= getuwd( &(buf->msg_perm.mode) ) & 0777;
		qp->msq.msg_qbytes     = n;
		break;

	case IPC_RMID:
		/*
		 * Validate removal authority.
		 */
		if ( (u.u_uid != 0) && (u.u_uid != qp->msq.msg_perm.uid) ) {
			u.u_error = EPERM;
			break;
		}

		/*
		 * Free all messages on the queue being removed.
		 */
		while ( mp = qp->msq.msg_first ) {
			qp->msq.msg_first   = mp->msg_next;
			mp->msg_next        = msqs->msq.msg_first;
			msqs->msq.msg_first = mp;
		}

		/*
		 * Wakeup processes waiting for free message buffers.
		 */
		if ( msqs->msq.msg_perm.mode & MSG_RWAIT ) {
			msqs->msq.msg_perm.mode &= ~MSG_RWAIT;
			wakeup( msqs );
		}
		if ( msqs->ipolls.e_procp )
			pollwake( &msqs->ipolls );

		/*
		 * Initialize queue parameters.
		 */
		qp->msq.msg_last   = 0;
		qp->msq.msg_qnum   = 0;
		qp->msq.msg_cbytes = 0;
		if ( (qp->msq.msg_perm.seq & 0x00FF) == 0x00FF )
			qp->msq.msg_perm.seq &= 0x7F00;
		qp->msq.msg_perm.seq++;

		/*
		 * Wakeup processes sleeping on the removed message queue.
		 */
		if ( qp->msq.msg_perm.mode & (MSG_RWAIT|MSG_WWAIT) )
			wakeup( qp );
		if ( qp->ipolls.e_procp )
			pollwake( &qp->ipolls );
		if ( qp->opolls.e_procp )
			pollwake( &qp->opolls );

		qp->msq.msg_perm.mode = 0;
		break;

	default:
		u.u_error = EINVAL;
	}

	if ( u.u_error )
		return -1;

	return 0;
}

/*
 * Msgget - Get set of messages
 */

umsgget( mykey, msgflg )

key_t mykey;
int msgflg;

{
	register struct xmsqid_ds *qp;
	register struct xmsqid_ds *freeidp = 0;
	int rwmode;
	
	if ( msqs == 0 ) {

		msginit();

		if ( msqs == 0 ) {
			u.u_error = ENOMEM;
			return;
		}
	}

	/*
	 * Extract desired access mode from flags.
	 */
	rwmode = msgflg & 0777;

	/*
	 * Search for desired message queue [also for first free queue].
	 */
	for ( qp = &msqs[NMSQID]; --qp > msqs; ) {

		if ( (qp->msq.msg_perm.mode & IPC_ALLOC) == 0 ) {

			if ((freeidp == 0) ||
			    (freeidp->msq.msg_ctime > qp->msq.msg_ctime))
				freeidp = qp;
			continue;
		}

		if (mykey == IPC_PRIVATE)
			continue;

		if ( mykey == qp->msq.msg_perm.key ) {		/* found! */

			if ( (msgflg & IPC_CREAT) && (msgflg & IPC_EXCL) ) {
				u.u_error = EEXIST;
				return -1;
			}

			if ( (qp->msq.msg_perm.mode & rwmode) != rwmode ) {
				u.u_error = EACCES;
				return -1;
			}

			return qp->msq.msg_perm.seq;
		}
	}

	if ( ! (msgflg & IPC_CREAT) ) {
		u.u_error = ENOENT;
		return -1;
	}

	if ( (qp = freeidp) == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	qp->msq.msg_first  = 0;
	qp->msq.msg_last   = 0;
	qp->msq.msg_cbytes = 0;
	qp->msq.msg_qnum   = 0;
	qp->msq.msg_qbytes = NMSQB;
	qp->msq.msg_lspid  = 0;
	qp->msq.msg_lrpid  = 0;
	qp->msq.msg_stime  = 0;
	qp->msq.msg_rtime  = 0;
	qp->msq.msg_ctime  = timer.t_time;

	qp->msq.msg_perm.cuid = qp->msq.msg_perm.uid = u.u_uid;
	qp->msq.msg_perm.cgid = qp->msq.msg_perm.gid = u.u_gid;
	qp->msq.msg_perm.mode = rwmode | IPC_ALLOC;
	qp->msq.msg_perm.key  = mykey;

	return qp->msq.msg_perm.seq;
}

/*
 * Send a Message
 */

umsgsnd( qid, bufp, msgsz, msgflg )

int qid;
struct msgbuf *bufp;
unsigned msgsz, msgflg;

{
	register struct xmsqid_ds * qp;
	register struct msg      * mp;

	/*
	 * Validate queue identifier.
	 */
	if ((qid <= 0) || (qid/256 >= NMSQID) || (msgsz > NMSC) || (msqs==0)) {
		u.u_error = EINVAL;
		return -1;
	}

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( (qp->msq.msg_perm.seq != qid)
	  || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ((ipcaccess(&qp->msq.msg_perm) & MSG_W) == 0){ /* can't send mesg */
		u.u_error = EACCES;
		return -1;
	}

	/*
	 * Wait for a free message buffer
	 */
	while ( (msqs->msq.msg_first == 0)
	     || (qp->msq.msg_qbytes <= qp->msq.msg_cbytes)) {

		if ( msgflg & IPC_NOWAIT ) {
			u.u_error = EAGAIN;
			return -1;
		}

		if (qp->msq.msg_qbytes <= qp->msq.msg_cbytes) {
			qp->msq.msg_perm.mode |= MSG_WWAIT;
			sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );
		}
		else {
			msqs->msq.msg_perm.mode |= MSG_RWAIT;
			sleep( msqs, CVTTOUT, IVTTOUT, SVTTOUT );
		}

		/*
		 * Abort if a signal was received
		 */
		if (SELF->p_ssig && nondsig() ) {
			u.u_error = EINTR;
			return -1;
		}

		/*
		 * Abort if the message queue was removed.
		 */
		if ( qid != qp->msq.msg_perm.seq ) {
			u.u_error = EIDRM;
			return -1;
		}
	}

	/*
	 * Use first message on free message queue
	 */
	mp = msqs->msq.msg_first;
	mp->msg_ts = msgsz;

	/*
	 * Transfer the message type and text.
	 */
	ukcopy( &(bufp->mtype), &(mp->msg_type), sizeof(mp->msg_type) );
	if ( ufcopy( &bufp->mtext[0], mp->msg_spot, msgsel, msgsz ) != msgsz )
			u.u_error = EFAULT;

	/*
	 * Abort if address fault occured during transfer.
	 */
	if ( u.u_error )
		return -1;

	/*
	 * Move the message to the desired queue.
	 */
	msqs->msq.msg_first = mp->msg_next;
	mp->msg_next = 0;

	if ( qp->msq.msg_last )
		qp->msq.msg_last->msg_next = mp;
	else
		qp->msq.msg_first = mp;
	qp->msq.msg_last = mp;

	/*
	 * Update queue statistics.
	 */
	qp->msq.msg_cbytes += msgsz;
	qp->msq.msg_qnum++;
	qp->msq.msg_lspid = SELF->p_pid;
	qp->msq.msg_stime = timer.t_time;

	/*
	 * Wake processes waiting to receive.
	 */
	if ( qp->msq.msg_perm.mode & MSG_RWAIT ) {
		qp->msq.msg_perm.mode &= ~MSG_RWAIT;
		wakeup( qp );
	}
	if ( qp->ipolls.e_procp )
		pollwake( &qp->ipolls );

	return 0;
}

/*
 * Receive A Message
 */

umsgrcv( qid, bufp, msgsz, msgtyp, msgflg )

int qid;
struct msgbuf *bufp;
unsigned msgsz;
long msgtyp;
unsigned msgflg;

{
	register struct xmsqid_ds *qp;
	register struct msg *mp;
	register struct msg *prev;

	/*
	 * Validate queue identifier.
	 */
	if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( (qp->msq.msg_perm.seq != qid)
	  || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	/*
	 * Permission denied
	 */
	if ( (ipcaccess(&qp->msq.msg_perm) & MSG_R) == 0 ) {
		u.u_error = EACCES;
		return -1;
	}

	/*
	 * Wait for message
	 */
	for (;;) {

		mp   = qp->msq.msg_first;
		prev = 0;

		/*
		 * Find mesg of type <= abs(msgtyp)
		 */
		if ( msgtyp < 0 ) {

			struct msg *xp, *xprev;
			
			xp     = 0;
			xprev  = 0;
			msgtyp = -msgtyp;

			for ( ; mp != 0 ; prev = mp, mp = mp->msg_next ) {

				if (mp->msg_type > msgtyp)
					continue;

				if ((xp==0) || (mp->msg_type < xp->msg_type)) {
					xp    = mp;
					xprev = prev;
				}
			}
			mp     = xp;
			prev   = xprev;
			msgtyp = -msgtyp;
		}

		/*
		 * Find message of type == msgtyp
		 */
		else if ( msgtyp > 0 ) {

			while ( (mp != 0) && (mp->msg_type != msgtyp) ) {
				prev = mp;
				mp = mp->msg_next;
			}
		}

		/*
		 * Else take first message
		 */

		if ( mp )
			break;

		/*
		 * Can't wait to receive mesg
		 */
		if ( msgflg & IPC_NOWAIT ) {
			u.u_error = EAGAIN;
			return -1;
		}

		qp->msq.msg_perm.mode |= MSG_RWAIT;
		sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );

		/*
		 * Signal received
		 */
		if ( SELF->p_ssig && nondsig() ) {
			u.u_error = EINTR;
			return -1;
		}

		/*
		 * Not same q anymore
		 */
		if ( qid != qp->msq.msg_perm.seq ) {
			u.u_error = EIDRM;
			return -1;
		}
	}

	/*
	 * Ensure entire message can be transferred, or MSG_NOERROR asserted.
	 */
	if ( (msgsz < mp->msg_ts) && ((msgflg & MSG_NOERROR) == 0) ) {
		u.u_error = E2BIG;
		return -1;
	}

	/*
	 * Transfer message data
	 */
	if ( msgsz > mp->msg_ts )
		msgsz = mp->msg_ts;

	kucopy( &(mp->msg_type), &(bufp->mtype), sizeof(mp->msg_type) );
	if (fucopy( mp->msg_spot, msgsel, &(bufp->mtext[0]), msgsz ) != msgsz)
		u.u_error = EFAULT;

	/*
	 * Abort if address fault occurred during transfer.
	 */
	if ( u.u_error )
		return -1;

	/*
	 * Remove message from queue
	 */
	if ( prev )
		prev->msg_next = mp->msg_next;
	else
		qp->msq.msg_first = mp->msg_next;

	if ( qp->msq.msg_last == mp )
		qp->msq.msg_last = prev;

	/*
	 * Update queue statistics
	 */
	qp->msq.msg_cbytes -= mp->msg_ts;
	qp->msq.msg_qnum--;
	qp->msq.msg_lrpid = SELF->p_pid;
	qp->msq.msg_rtime = timer.t_time;

	/*
	 * Wakeup processes waiting to send.
	 */
	if (qp->msq.msg_perm.mode & MSG_WWAIT) {
		qp->msq.msg_perm.mode &= ~MSG_WWAIT;
		wakeup( qp );
	}
	if ( qp->opolls.e_procp )
		pollwake( &qp->opolls );

	/*
	 * Place message buffer on free message queue
	 */
	qp = msqs;
	mp->msg_next = qp->msq.msg_first;
	qp->msq.msg_first = mp;

	/*
	 * Wakeup processes waiting for empty message buffer
	 */
	if ( qp->msq.msg_perm.mode & MSG_RWAIT ) {
		qp->msq.msg_perm.mode &= ~MSG_RWAIT;
		wakeup( qp );
	}
	if ( msqs->ipolls.e_procp )
		pollwake( &msqs->ipolls );

	return msgsz;
}

/*
 * Msgpoll - Message Queue Polling.
 */
msgpoll( qid, ev, msec )
int qid;
int ev;
int msec;
{
	register struct xmsqid_ds * qp;

	/*
	 * Validate queue identifier.
	 */
	if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) )
		return POLLNVAL;

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0)
	  || (qp->msq.msg_perm.seq != qid) )
		return POLLHUP;

	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll.
	 */
	if ( ev & POLLIN ) {

		/*
		 * No messages on queue.
		 */
		if ( qp->msq.msg_qnum == 0 ) {
			/*
			 * Enable input monitor.
			 */
			if ( msec != 0 )
				pollopen( &qp->ipolls );
			ev &= ~POLLIN;
		}

		/*
		 * Prevent output monitor.
		 */
		else
			msec = 0;
	}

	/*
	 * Output poll.
	 */
	if ( ev & POLLOUT ) {

		/*
		 * Queue full.
		 */
		if ( qp->msq.msg_cbytes >= qp->msq.msg_qbytes ) {
			if ( msec != 0 )
				pollopen( &qp->opolls );
			ev &= ~POLLOUT;
		}

		/*
		 * No free message buffers.
		 */
		else if ( msqs->msq.msg_first == NULL ) {
			if ( msec != 0 )
				pollopen( &msqs->ipolls );
			ev &= ~POLLOUT;
		}
	}

	return ev;
}
0707070064030034531004440000030000030000011777770507310637300005200000006107/newbits/kernel/USRSRC/i8086/drv/msgcon.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Message Device Driver
 *
 *	This device driver provides System V compatible messaging operations.
 *	Operations are performed through the message device (/dev/msg).
 *	and are implemented as ioctl calls from msgctl, msgget, msgsnd, msgrcv
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Oct 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:09:32	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:05:49	src
 * Initial revision
 * 
 * 87/03/02	Allan Cornish		/usr/src/sys/i8086/drv/msgcon.c
 * Msgioctl() now supports long key [was short] on MSGGET operations.
 * This allows compatability with System V.
 *
 * 85/08/06	Allan Cornish
 * Msg.c split into configuration (msgcon.c) and implementation (msg.c).
 *
 * 85/07/03	Allan Cornish
 * Simplified msgopen by ignoring minor device, which previously had to be 0.
 *
 * 84/01/30	Allan Cornish
 * Initial revision.
 */

#include <coherent.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <con.h>
#include <msg.h>

/*
 * Functions.
 */

int msgopen();
int msgioctl();
int nulldev();
int nonedev();

/*
 * Device Configuration.
 */

CON msgcon = {
	DFCHR,			/* Flags			*/
	25,			/* Major Index			*/
	msgopen,		/* Open				*/
	nulldev,		/* Close			*/
	nonedev,		/* Block			*/
	nonedev,		/* Read				*/
	nonedev,		/* Write			*/
	msgioctl,		/* Ioctl			*/
	nulldev,		/* Power fail			*/
	nulldev,		/* Timeout			*/
	nulldev,		/* Load				*/
	nulldev			/* Unload			*/
};

/*
 * Message Device Open.
 */

static
msgopen( dev, mode )

dev_t dev;
int mode;

{
	extern struct msqid_ds * msqs; /* Pointer to array of message queues */

	if ( ! msqs )			/* message queues not initialized */
		msginit();

	if ( ! msqs )			/* no message queues */
		u.u_error = ENODEV;
}

/*
 * Message Device Ioctl.
 */

static
msgioctl( dev, com, vec )

dev_t dev;
int com;
register int *vec;

{
	switch ( com ) {

	case MSGCTL:
		putuwd( vec+0,
			umsgctl(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ) ));
		return;

	case MSGGET:
		putuwd( vec+0,
			umsgget(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ) ));
		return;

	case MSGSND:
		putuwd( vec+0,
			umsgsnd(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ) ));
		return;

	case MSGRCV:
		putuwd( vec+0,
			umsgrcv(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ),
				getuwd( vec+5 ),
				getuwd( vec+6 ) ));
		return;

	default:
		u.u_error = EINVAL;
		return;
	}
}
0707070064030073621006440000030000030000011777770507310637400005100000003246/newbits/kernel/USRSRC/i8086/drv/msgop.c/*
 * User Message Functions.
 *
 *	Note: msgget() must be first function called.
 *
 *	91/02/07	Hal Snyder	mwchwc!/u/libc/sys/msgop.c
 *	msgget():  sizeof(key_t) is 4, not 2.
 */
#include <sys/msg.h>
#include <errno.h>

static int  msgfno   = -1;
static char msgdev[] = "/dev/msg";

/*
 * Message Control Operations.
 */

msgctl( msqid, cmd, buf )

int msqid;
int cmd;
struct msqid_ds * buf;

{
	int parm[4];

	if ( msgfno < 0 ) {
		errno = ENODEV;
		return -1;
	}

	parm[0] = -1;
	parm[1] = msqid;
	parm[2] = cmd;
	parm[3] = (int) buf;

	ioctl( msgfno, MSGCTL, parm );
	return parm[0];
}

/*
 * Get Message Queue.
 */

msgget( key, msgflg )

key_t key;
int msgflg;

{
	int parm[4];

	if ( msgfno < 0 ) {

		msgfno = open(msgdev, 0);

		if ( msgfno < 0 ) {
			perror(msgdev);
			errno = ENODEV;
			return -1;
		}
	}

	parm[0] = -1;
	parm[1] = key;
	parm[2] = key >> 16;
	parm[3] = msgflg;

	ioctl( msgfno, MSGGET, parm );
	return parm[0];
}

/*
 * Send Message.
 */
 
msgsnd( msqid, msgp, msgsz, msgflg )

int msqid;
struct msgbuf *msgp;
int msgsz;
int msgflg;

{
	int parm[5];

	if ( msgfno < 0 ) {
		errno = ENODEV;
		return -1;
	}

	parm[0] = -1;
	parm[1] = msqid;
	parm[2] = (int) msgp;
	parm[3] = msgsz;
	parm[4] = msgflg;

	ioctl( msgfno, MSGSND, parm );
	return parm[0];
}

/*
 * Receive Message.
 */
 
msgrcv( msqid, msgp, msgsz, msgtyp, msgflg )

int msqid;
struct msgbuf *msgp;
int msgsz;
long msgtyp;
int msgflg;

{
	int parm[7];

	if ( msgfno < 0 ) {
		errno = ENODEV;
		return -1;
	}

	parm[0] = -1;
	parm[1] = msqid;
	parm[2] = (int) msgp;
	parm[3] = msgsz;
	parm[4] = (int) msgtyp;
	parm[5] = (int) (msgtyp >> 16);
	parm[6] = msgflg;

	ioctl( msgfno, MSGRCV, parm );
	return parm[0];
}
0707070064030034641006440000030000030000011777770507310637400004700000045224/newbits/kernel/USRSRC/i8086/drv/nkb.c/*
 * User configurable AT keyboard/display driver.
 * AT COHERENT
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <signal.h>
#include <sys/seg.h>
#include <sys/sched.h>
#include <sys/kb.h>

#define	ISMAJ		2		/* Keyboard major device */
#define	ISVEC		1		/* Keyboard interrupt vector */

#if	DEBUG
#define	KBDEBUG(x)	printf(x)	/* debugging output */
#define	KBDEBUG2(x,y)	printf(x,y)	/* debugging output */
#define	KBDEBUG3(x,y,z)	printf(x,y,z)	/* debugging output */
#else
#define	KBDEBUG(x)			/* no output */
#define	KBDEBUG2(x,y)			/* no output */
#define	KBDEBUG3(x,y,z)			/* no output */
#endif

/*
 * values for kbstate
 */
#define	KB_IDLE		0		/* nothing going on right now */
#define	KB_SINGLE	1		/* sent a single byte cmd to the kbd */
#define	KB_DOUBLE_1	2		/* sent 1st byte of 2-byte cmd to kbd */
#define	KB_DOUBLE_2	3		/* sent 2nd byte of 2-byte cmd to kbd */

/*
 * patchable params for non-standard keyboards
 */
int	KBDATA = 0x60;			/* Keyboard data */
int	KBCTRL = 0x61;			/* Keyboard control */
int	KBSTS_CMD = 0x64;		/* Keyboard status/command */
int	KBFLAG = 0x80;			/* Keyboard reset flag */
int	KBBOOT = 1;			/* 0: disallow reboot from keyboard */
int	KBTIMEOUT = 10000;		/* shouldn't need this much */
int	KBCMDBYTE = 0x05;		/* no translation */

/*
 * KBSTATUS bits
 */
#define	STS_OBUF_FULL	0x01		/* kbd output buffer full */
#define	STS_IBUF_FULL	0x02		/* kbd input buffer full */
#define	STS_SYSTEM	0x04
#define	STS_CMD_DATA	0x08		/* 1: command or status */
#define	STS_INHIBIT	0x10		/* 0: keyboard inhibited */
#define	STS_AUX_OBUF_FULL	0x20
#define	STS_TIMEOUT	0x40		/* general timeout */
#define	STS_PAR_ERR	0x80		/* parity error */

/*
 * The following are magic commands which read from or write to the
 * controller command byte. These get output to the KBSTS_CMD port.
 */
#define	C_READ_CMD	0x20		/* read controller command byte */
#define	C_WRITE_CMD	0x60		/* write controller command byte */
#define	C_TRANSLATE	0x40		/* translate enable bit in cmd byte */

/*
 * Globals
 * The keyboard mapping table is too large to fit into kernel data space,
 * so we need to allocate a segment to it.
 * The function keys tend to be small and tend to change substantially
 * more often than the mapping table, so we keep them in the kernel data space.
 */
static	unsigned shift;			/* state of all shift/lock keys */
static	SEG	*kbsegp;		/* keyboard table segment */
static	unsigned char	**funkeyp = 0;	/* ptr to array of func. keys ptrs */
static	FNKEY	*fnkeys = 0;		/* pointer to structure of values */
static	unsigned fklength;		/* length of k_fnval field in fnkeys */
static	unsigned prev_cmd;		/* previous command sent to KBD */
static	unsigned cmd2;			/* 2nd byte of command to KBD */
static	unsigned sh_index;		/* shift/lock state index */

/*
 * State variables.
 */
int		islock;			/* Keyboard locked flag */
int		isbusy;			/* Raw input conversion busy */
static	char	table_loaded;		/* true == keyboard table resident */
static	char	fk_loaded;		/* true == function keys resident */
static	int	kbstate = KB_IDLE;	/* current keyboard state */

/*
 * Functions.
 */
int		isrint();
int		istime();
void		isbatch();
int		mmstart();
int		isopen();
int		isclose();
int		isread();
int		mmwrite();
int		isioctl();
void		mmwatch();
int		isload();
int		isuload();
int		ispoll();
int		nulldev();
int		nonedev();
int		updleds();

/*
 * Configuration table.
 */
CON iscon ={
	DFCHR|DFPOL,			/* Flags */
	ISMAJ,				/* Major index */
	isopen,				/* Open */
	isclose,			/* Close */
	nulldev,			/* Block */
	isread,				/* Read */
	mmwrite,			/* Write */
	isioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	mmwatch,			/* Timeout */
	isload,				/* Load */
	isuload,			/* Unload */
	ispoll				/* Poll */
};

/*
 * Terminal structure.
 */
TTY	istty = {
	{0}, {0}, 0, mmstart, NULL, 0, 0
};

/*
 * Load entry point.
 */
isload()
{
	kbstate = KB_IDLE;
	table_loaded = 0;		/* no keyboard table yet */
	fk_loaded = 0;			/* no Fn keys yet */

	/*
	 * Enable mmwatch() invocation every second.
	 */
	drvl[ISMAJ].d_time = 1;

	/*
	 * Seize keyboard interrupt.
	 */
	setivec(ISVEC, isrint);

	/*
	 * Initiailize video display.
	 */
	mmstart( &istty );

	/*
	 * Allocate a segment to store the in-core keyboard table.
	 * This would be a lot more convenient in kernel data space,
	 * but small model COHERENT doesn't have that luxury.
	 */
	kbsegp = salloc((fsize_t)MAX_TABLE_SIZE, SFSYST|SFNSWP|SFHIGH);
	if (kbsegp == (SEG *)0)
		printf("kb: unable to allocate keyboard table segment\n");
	fklength = 0;
	KBDEBUG("Exiting kbload()\n");
}

/*
 * Unload entry point.
 */
isuload()
{
	if (kbstate != KB_IDLE)
		printf("kb: keyboard busy during unload\n");
	clrivec(ISVEC);
	if (kbsegp != (SEG *)0) {
		table_loaded = 0;
		sfree(kbsegp);
	}
}

/*
 * Open routine.
 */
isopen(dev)
dev_t dev;
{
	register int s;

	KBDEBUG(" kbopen()");
	if (minor(dev) != 0) {
		u.u_error = ENXIO;
		return;
	}
	if ((istty.t_flags&T_EXCL) != 0 && !super()) {
		u.u_error = ENODEV;
		return;
	}
	ttsetgrp(&istty, dev);

	s = sphi();
	if (istty.t_open++ == 0) {
		istty.t_flags = T_CARR;	/* indicate "carrier" */
		ttopen(&istty);
	}
	spl(s);
#if 0
	updleds();			/* update keyboard status LEDS */
#endif
}

/*
 * Close a tty.
 */
isclose(dev)
{
	register int s;

	s = sphi();
	if (--istty.t_open == 0) {
		ttclose(&istty);
	}
	spl(s);
}

/*
 * Read routine.
 */
isread(dev, iop)
dev_t dev;
IO *iop;
{
	ttread(&istty, iop, 0);
	if (istty.t_oq.cq_cc)
		mmtime(&istty);
}

/*
 * Ioctl routine.
 * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported.
 */
isioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	register int s;

	switch (com) {
	case TIOCSETF:
	case TIOCGETF:
		isfunction(com, (char *)vec);
		break;
	case TIOCSETKBT:
		issettable(vec);
		break;
	case TIOCGETKBT:
		isgettable(vec);
		break;
	default:				/* pass to TTY driver */
		s = sphi();
		ttioctl(&istty, com, vec);
		spl(s);
		break;
	}
}

/*
 * Set the in-core keyboard mapping table.
 * The table is sorted by scan code prior to calling ioctl().
 * All unused table entries (holes in the scan code map) have
 * a zero for the k_key field.
 * This makes key lookup at interrupt time fast by using the scan code
 * as an index into the table.
 */
issettable(vec)
char	*vec;
{
	register unsigned i;
	register int s;
	int timeout;
	register faddr_t faddr;		/* address of keyboard table */
	static	KBTBL	this_key;	/* current key from kbd table */
	unsigned int cmd_byte;

	KBDEBUG(" TIOCSETKBT");
	kb_cmd2(K_SCANCODE_CMD, 3);		/* select set 3 */
	kb_cmd(K_ALL_TMB_CMD);			/* default: TMB for all keys */
	faddr = kbsegp->s_faddr;
	for (i = 0; i < MAX_KEYS; ++i) {
		ukcopy(vec, &this_key, sizeof(this_key));
		kfcopy(&this_key, faddr, sizeof(this_key));
		faddr += sizeof(this_key);
		vec += sizeof(this_key);
		if (this_key.k_key != i && this_key.k_key != 0) {
			printf("kb: incorrect or unsorted table entry %d\n", i);
			u.u_error = EBADFMT;
			return;
		}
		if (this_key.k_key != i)
			continue;		/* no key */
		switch (this_key.k_flags&TMODE) {
		case T:				/* typematic */
			kb_cmd2(K_KEY_T_CMD, i);
			break;
		case M:				/* make only */
			kb_cmd2(K_KEY_M_CMD, i);
			break;
		case MB:			/* make/break */
			kb_cmd2(K_KEY_MB_CMD, i);
			break;
		case TMB:			/* typematic make/break */
			break;			/* this is the default */
		default:
			printf("kb: bad key mode\n");
		}
	}
	updleds();
	kb_cmd2(K_SCANCODE_CMD, 3);		/* select set 3 */
	kb_cmd(K_ENABLE_CMD);			/* start scanning */
	/*
	 * The following code disables translation from the on-board
	 * keyboard/aux controller. Without disabling translation, the
	 * received scan codes still look like code set 1 codes even
	 * though we put the keyboard controller in scan code set 3.
	 * Yes, this is progress....
	 */
#if 0
	while (inb(KBSTS_CMD) & STS_IBUF_FULL)
		;
	outb(KBSTS_CMD, C_READ_CMD);		/* read controller cmd byte */
	while (!(inb(KBSTS_CMD) & STS_OBUF_FULL))
		;
	cmd_byte = inb(KBDATA);
	KBDEBUG2(" cmd_byte=%x", cmd_byte);
#endif
	timeout = KBTIMEOUT;
	s = sphi();
	while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
		;
	outb(KBSTS_CMD, C_WRITE_CMD);		/* write controller cmd byte */
	for (timeout = 50; --timeout > 0; )
		;
	timeout = KBTIMEOUT;
	while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
		;
	outb(KBDATA, KBCMDBYTE);		 /* turn off translation */	
	timeout = KBTIMEOUT;
	while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
		;
	spl(s);
#if DEBUG
	kb_cmd2(K_SCANCODE_CMD, 0);		/* query s.c. mode */
#endif
	++table_loaded;
}

/*
 * Get the in-core keyboard mapping table and pass it to the user.
 */
isgettable(vec)
char	*vec;
{
	register unsigned i;
	register faddr_t faddr;		/* address of keyboard table */
	static	KBTBL	this_key;	/* current key from kbd table */

	KBDEBUG(" TIOCGETKBT");
	faddr = kbsegp->s_faddr;
	for (i = 0; i < MAX_KEYS; ++i) {
		fkcopy( faddr, &this_key, sizeof(this_key));
		kucopy( &this_key, vec, sizeof(this_key));
		faddr += sizeof(this_key);
		vec += sizeof(this_key);
	}
}

/*
 * Set and receive the function keys.
 */
isfunction(c, v)
int c;
FNKEY *v;
{
	register unsigned char *cp;
	register unsigned i;
	unsigned char	numkeys = 0;

	if (c == TIOCGETF) {
		KBDEBUG(" TIOCGETF");
		if (!fk_loaded)
			u.u_error = EINVAL;
		else
			kucopy(fnkeys, v, fklength);	/* copy ours to user */
	} else { /* TIOCSETF */
		/*
		 * If we had a previous function key arena, free it up.
		 * Since we don't know how large the function key arena will
		 * be, we must size it in the user data space prior to
		 * (re)kalloc()'ing it. This is ugly, but a helluva lot better
		 * than the old driver which used a hard coded limit of 150!
		 */
		KBDEBUG(" TIOCSETF");
		fk_loaded = 0;
		if (fnkeys != (FNKEY *)0)
			kfree(fnkeys);		/* free old arena */
		if (funkeyp != NULL)
			kfree(funkeyp);		/* free old ptr array */
		ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys));
		fklength = sizeof(FNKEY);
		cp = v->k_fnval;
		for (i = 0; i < numkeys; i++) {
			do {
				++fklength;
			} while (getubd(cp++) != DELIM);
		}
		fnkeys = (FNKEY *)kalloc(fklength);
		funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *));
		if (fnkeys == (FNKEY *)0 || funkeyp == NULL) {
			if (fnkeys != (FNKEY *)0) {
				kfree(fnkeys);
				fnkeys = 0;
			}
			if (funkeyp != NULL) {
				kfree(funkeyp);
				funkeyp = 0;
			}
			u.u_error = ENOMEM;
			return;
		}
		cp = fnkeys->k_fnval;			/* point to Fn ... */
		v = v->k_fnval;				/* ... key arena */
		for (i = 0; i < numkeys; i++) {
			funkeyp[i] = cp;	           /* save pointer */
			while ((*cp++ = getubd(v++)) != DELIM)  /* copy key */
				;
		}
		fnkeys->k_nfkeys = numkeys;
		fk_loaded = 1;
	}
}


/*
 * Poll routine.
 */
ispoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll failure.
	 */
	if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) {
		if ( msec != 0 )
			pollopen( &istty.t_ipolls );
		/*
		 * Second look AFTER enabling monitor, avoiding interrupt race.
		 */
		if ( istty.t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}
	return ev;
}

/*
 * Receive interrupt.
 */
isrint()
{
	register unsigned c;
	register unsigned r;
	static	char keyup;

	/*
	 * Schedule raw input handler if not already active.
	 */
	if ( !isbusy ) {
		defer( isbatch, &istty );
		isbusy = 1;
	}

	/*
	 * Pull character from the data
	 * port. Pulse the KBFLAG in the control
	 * port to reset the data buffer.
	 */
	r = inb(KBDATA) & 0xFF;
	c = inb(KBCTRL);
	outb(KBCTRL, c|KBFLAG);
	outb(KBCTRL, c);

	/*
	 * check returned value from keyboard to see if it's a command
	 * or status back to us. If not, it we assume that it's a key code.
	 */
	KBDEBUG2(" intr(%x)", r);
	switch (r) {
	case K_BREAK:
		keyup = 1;			/* key going up */
		break;
	case K_ECHO_R:
	case K_BAT_OK:
		break;				/* very nice, but ignored */
	case K_BAT_BAD:
		printf("kb: keyboard BAT failed\n");
		break;
	case K_RESEND:
		KBDEBUG("\nkb: request to resend command\n");
		outb(KBDATA, prev_cmd);
		break;
	case K_OVERRUN_23:
		printf("kb: keyboard buffer overrun\n");
		break;
	case K_ACK:
		/*
		 * we received an ACKnowledgement from the keyboard.
		 * advance the state machine and continue.
		 */
		KBDEBUG(" ACK");
		switch (kbstate) {
		case KB_IDLE:			/* shouldn't happen */
			printf("kb: ACK while keyboard idle\n");
			break;
		case KB_SINGLE:			/* done with 1-byte command */
		case KB_DOUBLE_2:		/* done w/ 2nd of 2-byte cmd */
			kbstate = KB_IDLE;
			wakeup(&kbstate);
			break;
		case KB_DOUBLE_1:
			kbstate = KB_DOUBLE_2;
			outb(KBDATA, cmd2);
			break;
		default:
			printf("kb: bad kbstate %d\n", kbstate);
			break;
		}
		break;
	default:
		process_key(r, keyup);
		keyup = 0;
	}
}

/*
 * Process a key given its scan code and direction.
 * 
 * In this table driven version of the keyboard driver, we trade off the
 * code complexity associated with all the black magic that used to be
 * performed on a per-key basis with the increased memory requirements
 * associated with the table driven approach.
 */
process_key( key, up)
unsigned key;
int	 up;
{
	register unsigned char *cp;
	KBTBL	key_vals;			/* table values for this key */
	unsigned val;
	unsigned char flags;

	KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down"));
	if (!table_loaded)
		return;				/* throw away key */
	fkcopy( kbsegp->s_faddr + (key * sizeof(KBTBL)),
		&key_vals, sizeof(key_vals));
	if (key_vals.k_key != key)		/* empty entry */
		return;
	flags = key_vals.k_flags;

	if (flags & S) {			/* some shift/lock key ? */
		switch (key_vals.k_val[BASE]) {
		case caps:
		case num:
			if (!up) {
				shift ^= (1 << key_vals.k_val[BASE]);
				updleds2();
			}
			break;
		case scroll:
			if (!up) {
				shift ^= (1 << key_vals.k_val[BASE]);
				updleds2();
				if (!(istty.t_sgttyb.sg_flags&RAWIN)) {
					if (istty.t_flags & T_STOP) {
						isin(istty.t_tchars.t_startc);
					} else {
						isin(istty.t_tchars.t_stopc);
					}
				}
			}
			break;
		default:
			if (up)
				shift &= ~(1 << key_vals.k_val[BASE]);
			else
				shift |= (1 << key_vals.k_val[BASE]);
			break;
		}
		/*
		 * Calculate the shift index based upon the state of
		 * the shift and lock keys.
		 */
		sh_index = BASE;		/* default condition */
		if (shift & (1 << altgr))
			sh_index = ALT_GR;
		else {
			if (shift & ((1 << lalt)|(1 << ralt)))
				sh_index |= ALT;
			if (shift & ((1 << lctrl)|(1 << rctrl)))
				sh_index |= CTRL;
			if (shift & ((1 << lshift)|(1 << rshift)))
				sh_index |= SHIFT;
		}
		return;
	} /* if (flags & S) */

	/*
	 * If the tty is not open or the key has no value in the current
	 * shift state, the key is just tossed away.
	 */
	if (up || !istty.t_open || key_vals.k_val[sh_index] == none)
		return;
	if (((flags & C) && (shift & (1 << caps)))
	   || ((flags & N) && (shift & (1 << num))))
		val = key_vals.k_val[sh_index^SHIFT];
	else
		val = key_vals.k_val[sh_index];

	/*
	 * Check for function key or special key implemented as
	 * a function key (reboot == f0, tab and back-tab, etc).
	 */
	if (flags & F) {
		if (val == 0 && !up && KBBOOT)
			boot();
		if (!fk_loaded || val >= fnkeys->k_nfkeys)
			return;
		if ((cp = funkeyp[val]) == NULL) /* has a value? */
			return;
		while (*cp != DELIM)
			isin(*cp++);		/* queue up Fn key value */
		return;
	}

	/*
	 * Normal key processing.
	 */
	isin(val);		 /* send the char */
	return;
}

/**
 *
 * void
 * ismmfunc( c )	-- process keyboard related output escape sequences
 * char c;
 */
void
ismmfunc(c)
register int c;
{
	switch (c) {
	case 't':	/* Enter numlock */
		shift |= (1 << num);
		updleds();			/* update LED status */
		break;
	case 'u':	/* Leave numlock */
		shift &= ~(1 << num);
		updleds();			/* update LED status */
		break;
	case '=':			/* Enter alternate keypad -- ignored */
	case '>':			/* Exit alternate keypad -- ignored */
		break;
	case 'c':	/* Reset terminal */
		islock = 0;
		break;
	}
}

/**
 *
 * void
 * isin( c )	-- append character to raw input silo
 * char c;
 */
static
isin( c )
register int c;
{
	/*
	 * Cache received character.
	 */
	istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c;

	if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) )
		istty.t_rawin.si_ix = 0;
}

/**
 *
 * void
 * isbatch()	-- raw input conversion routine
 *
 *	Action:	Enable the video display.
 *		Canonize the raw input silo.
 *
 *	Notes:	isbatch() was scheduled as a deferred process by isrint().
 */
static void
isbatch( tp )
register TTY * tp;
{
	register int c;
	static int lastc;

	/*
	 * Ensure video display is enabled.
	 */
	mm_von();
	isbusy = 0;

	/*
	 * Process all cached characters.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
		/*
		 * Get next cached char.
		 */
		c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ];

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;

		if ( (islock == 0) || ISINTR || ISQUIT ) {
			ttin( tp, c );
		} else if ( (c == 'b') && (lastc == '\033') ) {
			islock = 0;
			ttin( tp, lastc );
			ttin( tp, c );
		} else if ( (c == 'c') && (lastc == '\033') ) {
			ttin( tp, lastc );
			ttin( tp, c );
		} else
			putchar('\007');
		lastc = c;
	}
}

/*
 * update the keyboard status LEDS.
 * we chose the shift/lock key positions so this would be easy.
 * this flavor of routine is called while processing a system call on
 * behalf of the user.
 */
updleds()
{
	kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7);
}

/*
 * same as above, but callable from interrupt routines and other places
 * which cannot sleep() waiting for the state machine to go idle.
 */
updleds2()
{
	register timeout;
	register int s;

	timeout = KBTIMEOUT;
	s = sphi();
	while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
		;
	kbstate = KB_DOUBLE_1;
	cmd2 = (shift >> 1) & 0x7;
	prev_cmd = K_LED_CMD;
	outb(KBDATA, K_LED_CMD);
	spl(s);
}

/*
 * unlock the scroll in case an interrupt character is received
 */
kbunscroll()
{
	shift &= ~(1 << scroll);
	updleds();
}

/*
 * ship a single byte command to the keyboard
 */
kb_cmd(cmd)
unsigned cmd;
{
	register int timeout;
	register int s;

	s = sphi();
	KBDEBUG2(" kb_cmd(%x)", cmd);
	while (kbstate != KB_IDLE)
		sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	kbstate = KB_SINGLE;
	timeout = KBTIMEOUT;
	while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
		;
	if (!timeout)
		printf("kb: command timeout\n");
	else {
		outb(KBDATA, cmd);
		while (kbstate != KB_IDLE)
			sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	}
	spl(s);
}

/*
 * ship a two byte command to the keyboard
 */
kb_cmd2(cmd, arg)
unsigned cmd, arg;
{
	register int timeout;
	register int s;

	s = sphi();
	KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg);
	while (kbstate != KB_IDLE)
		sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	kbstate = KB_DOUBLE_1;
	cmd2 = arg;
	prev_cmd = cmd;
	timeout = KBTIMEOUT;
	while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
		;
	if (!timeout)
		printf("kb: command timeout\n");
	else {
		outb(KBDATA, cmd);
		while (kbstate != KB_IDLE)
			sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	}
	spl(s);
}

/* End of nkb.c */
0707070064030150251004440000030000030000011777770507310640000005100000004416/newbits/kernel/USRSRC/i8086/drv/pccon.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Configuration table.
 * 8088 Coherent, IBM PC.
 * Minimal system.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:09:51	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:05:55	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <mtype.h>
#include <sys/stat.h>

extern	CON	nlcon[];		/* Null device */
extern	CON	ctcon[];		/* Console terminal */

/*
 * Device table.
 */
DRV	drvl[NDRV] = {
	{nlcon},	{ctcon},	{NULL },	{NULL },  /*  0 -  3 */
	{NULL },	{NULL },	{NULL },	{NULL },  /*  4 -  7 */
	{NULL },	{NULL },	{NULL },	{NULL },  /*  8 - 11 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 12 - 15 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 16 - 19 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 20 - 23 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 24 - 27 */
	{NULL },	{NULL },	{NULL },	{NULL }   /* 28 - 31 */
};

/*
 * Time.
 */
TIME timer ={
	0,				/* Initial time */
	0,				/* Ticks */
	8*60,				/* Pacific */
	1				/* Daylight saving time */
};

/*
 * Devices and sizes.
 */
dev_t	rootdev = makedev(4, 4);	/* Root device */
dev_t	pipedev = makedev(4, 4);	/* Pipe device */
dev_t	swapdev = makedev(0, 0);	/* Swap device */
daddr_t	swapbot = 0;			/* Swap base */
daddr_t	swaptop = 0;			/* Swap end */
int	ronflag	= 0;			/* Not read only root device */
int	drvn	= NDRV;			/* Maximum number of devices */
int	mactype	= M_8086;		/* Machine type */

/*
 * Flexible param's
 */
int	NCLIST	= 8;		/* 8 clists per installed tty, never run out */
int	ALLSIZE = 7*1024;	/* 7K has been reasonable */
int	NINODE	= 64;		/* More than enough so far */
int	NBUF	= 16;		/* Stingy */
0707070064030074511006440000030000030000011777770507310640100004600000012220/newbits/kernel/USRSRC/i8086/drv/qq.c/*
 * qq - sample device driver using absolute memory addressing
 *
 * All this device does is read/write video ram.
 * It assumes that there is a monochrome adapter in use, so that video
 * ram starts at segment B000;  if color, this should be changed to B800.
 *
 * This driver does not do anything useful;  it is intended to serve as
 * an example.
 *
 * Here is how to make the driver and test it (you will need a COHERENT
 * Driver Kit installed on your system):
 * 1.	put this file, "qq.c", in /usr/src/sys/i8086/drv/qq.c
 * 2.	cut out the make file and store it in /usr/src/sys/i8086/drv/Mf.qq
 * 3.	cut out the config file and store it at /usr/sys/confdrv/qq
 * 4.	execute the following commands
 *		cd /usr/src/sys/i8086/drv
 *		make -f Mf.qq
 *		cd /usr/sys
 *		ldconfig qq
 *		drvld ldrv/qq
 * 5.	the driver should now be loaded - try "date > /dev/qq" or
 *	"cat < /dev/qq" (you will have to use Ctrl-C to stop the "cat"
 *	command)
 * 6.	to unload the driver, do "ps -d" to get the PID number for the driver;
 *	then do "kill kill nnn" where nnn is the process number for "<qq>"
 */
/****
Here is the makefile for the "qq" driver (cut it out of this file):
--------------- cut here -----------------
# Make file for a loadable driver

AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys \
	-I/usr/include/sys
AFLAGS=-gx

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

DRVOBJ=	objects/qq.o

qq: objects/qq.o
	rm -f $(USRSYS)/lib/qq.a
	ar rc $(USRSYS)/lib/qq.a objects/qq.o

objects/qq.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		qq.c
	$(CC) $(CFLAGS) -c -o $@ qq.c
--------------- cut here -----------------

Here is the configuration file for the "qq" driver.
Cut it out of this file and copy it to "/usr/sys/confdrv/qq".
When "ldconfig" is run, it will create a node for /dev/qq.
--------------- cut here -----------------
:
: 'Dummy driver for write to absolute RAM area'
:
UNDEF="${UNDEF} -u qqcon_ lib/qq.a"
PATCH="${PATCH} drvl_+70=qqcon_"
:
: devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/qq c 7  0 || exit 1
--------------- cut here -----------------
****/
#include "coherent.h"
#include "ins8250.h"
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/proc.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mmu.h>

/*
 * Definitions.
 *
 */
#define	MONOVIDEO	0xB000		/* monochrome text RAM segment */
#define	VIDLENGTH	(2048*2)	/* screen locations (2 bytes each) */

/*
 * Export Functions.
 */
int	qqload();
int	qqopen();
int	qqclose();
int	qqread();
int	qqwrite();
int	qqunload();

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON qqcon ={
	DFCHR,				/* Flags */
	7,				/* Major index */
	qqopen,				/* Open */
	qqclose,			/* Close */
	nulldev,			/* Block */
	qqread,				/* Read */
	qqwrite,			/* Write */
	nulldev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	qqload,				/* Load */
	qqunload,			/* Unload */
	nulldev				/* Poll */
};

/*
 * Local variables.
 */
static faddr_t	screen_fp;		/* (far *) to access screen */
static paddr_t	screen_base;		/* physical address of screen base */

/*
 * Load Routine.
 */
static qqload()
{
	/*
	 * Allocate a selector to map onto the video RAM.  ptov() will
	 * return the first available selector of the 8,192 possible.
	 * This is time consuming, so we only want to do this as part
	 * of our initialization code and not on every access.
	 *
	 * Since we are operating in 286 protected mode (ugh), the
	 * second argument to ptov() must not exceed 0x10000L.
	 */
	screen_base = (paddr_t)((long)(unsigned)MONOVIDEO << 4);
	screen_fp = ptov(screen_base, (fsize_t)VIDLENGTH);
}

static qqunload()
{
	/*
	 * We have to free up the selector now that we're done using it.
	 */
	vrelse(screen_fp);
}

/*
 * Open Routine.
 */
qqopen( dev, mode )
dev_t dev;
{
}

/*
 * Close Routine.
 */
qqclose( dev )
dev_t dev;
{
}

/*
 * Read Routine.
 */
qqread( dev, iop )
dev_t dev;
register IO * iop;
{
	static int offset;
	int c;
	/*
	 * Read a character code from video RAM
	 * Start reading RAM just after where previous read ended
	 *
	 * Note that "offset" is the value of the displacement into
	 * the screen RAM. Any expression which results in a value
	 * which is less than VIDLENGTH is OK here.
	 */
	while(iop->io_ioc) {
		c = ffbyte(screen_fp + offset); /* fetch a "far" byte */
		if(ioputc(c, iop) == -1)
			break;
		offset += 2;
		offset %= VIDLENGTH;
	}
}

/*
 * Write Routine.
 */
qqwrite( dev, iop )
dev_t dev;
register IO * iop;
{
	int offset = 0;
	int c;

	/*
	 * Write a character into the screen RAM
	 * Note that "offset" is the value of the displacement into
	 * the screen RAM. Any expression which results in a value
	 * which is less than VIDLENGTH is OK here.
	 */
	while ((c = iogetc(iop)) >= 0 && offset < VIDLENGTH) {
		sfbyte(screen_fp + offset, c);	   /* store a "far" byte */
		offset += 2;	/* skip attribute byte */
	}
}
0707070064030074541006440000030000030000011777770507310640200004600000010215/newbits/kernel/USRSRC/i8086/drv/rm.c/*
 * Block or character device RAM disk driver.
 */

#include	<sys/coherent.h>
#include	<sys/buf.h>
#include	<errno.h>
#include	<sys/uproc.h>
#include	<sys/seg.h>
#include	<sys/con.h>
#include	<sys/devices.h>
#include	<sys/inode.h>
#include	<sys/stat.h>

/*
 * Minor number encoding: dsssssss
 * d       drive number (0 or 1)
 * sssssss allocation size: 0 to free, 1-127 allocsize (n*ASIZE*BSIZE bytes)
 */
#define	rm_drive(dev)	(minor(dev) >> 7)
#define	rm_asize(dev)	(minor(dev) & 0x7F)
#define	ASIZE		128	/* allocation chunk size in blocks (64KB) */
#define NUM_RM		2	/* number of ram disks */
				/* - tied to dev encoding (see above) */

int	nulldev();
int	nonedev();
int	rmload();
int	rmuload();
int	rmopen();
int	rmclose();
int	rmread();
int	rmwrite();
int	rmblock();

CON	rmcon	= {
	DFBLK|DFCHR,
	RM_MAJOR,
	rmopen,			/* Open */
	rmclose,		/* Close */
	rmblock,		/* Block */
	rmread,			/* Read */
	rmwrite,		/* Write */
	nonedev,
	nulldev,
	nulldev,
	rmload,			/* Load */
	rmuload			/* Unload */
};

typedef struct rm {
	fsize_t	rm_size;	/* Size in allocation chunks */
	paddr_t	rm_paddr;	/* Physical base of ram disc segment */
	SEG	*rm_segp;	/* Segment pointer of ram device */
	BUF	rm_buf;		/* Static buffer for raw requests */
	int	rm_nopen;	/* Open count to avoid blowups */
} RM;
static	RM	rm[NUM_RM];

/*
 * Load.
 */
static
rmload()
{
}

/*
 * Unload.
 * Release the allocated buffers.
 */
static
rmuload()
{
	int i;

	for (i = 0; i < NUM_RM; i++){
		if (rm[i].rm_size != 0)
			sfree(rm[i].rm_segp);
	}
}

/*
 * Open.
 * Allocate on the first call.
 * Increment the open count.
 */
static
rmopen(dev, mode) dev_t dev; int mode;
{
	register RM *rmp;
	register fsize_t asize, osize;
	register SEG *segp;

	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;

	/* Fail on read before creation or bogus size. */
	if ((mode == IPR && osize == 0)
	 || (asize != 0 && osize != 0 && asize != osize)
	 || (asize == 0 && osize == 0)) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Allocate as required.
	 * Ignore case asize==0 && osize!=0, handled by rmclose().
	 * If asize!=0 && asize==osize, just bump the open count.
	 */
	if (asize != 0 && osize == 0) {
		segp = rmp->rm_segp = salloc((fsize_t)ASIZE*BSIZE*asize,
			SFSYST|SFNSWP|SFNCLR|SFHIGH);
		if (segp == NULL) {
			u.u_error = ENOMEM;
			return;
		}
		rmp->rm_size = asize;
		rmp->rm_paddr = segp->s_paddr;
		rmp->rm_nopen = 0;
		pclear(rmp->rm_paddr, 1024L);	/* clear 1st 2 blocks */
	}
	rmp->rm_nopen++;
}

/*
 * Close.
 * Decrement the open count.
 * Release the allocated buffer if minor number is 0.
 */
static
rmclose(dev) dev_t dev;
{
	register RM *rmp;
	register fsize_t asize, osize;

	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;

	if (osize == 0
	 || (asize != 0 && asize != osize)
	 || rmp->rm_nopen == 0) {
		u.u_error = ENXIO;
		return;
	}
	rmp->rm_nopen--;
	if (asize == 0) {
		if (rmp->rm_nopen != 0) {
			u.u_error = EDBUSY;
			return;
		}
		sfree(rmp->rm_segp);
		rmp->rm_size = 0;
	}
}

static
rmblock(bp) register BUF *bp;
{
	paddr_t base;
	dev_t dev;
	register RM *rmp;
	register fsize_t asize, osize;

	dev = bp->b_dev;
	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;
	if (osize == 0 || asize != osize)
		bp->b_flag |= BFERR;
	/*
	 * Make sure last block requested is within range of device.
	 */	
	else if ((bp->b_bno + bp->b_count/BSIZE - 1) >= asize*ASIZE)
		bp->b_flag |= BFERR;
	else {
		base = rmp->rm_paddr + (paddr_t)bp->b_bno * BSIZE;
		if (bp->b_req == BREAD)
			plrcopy(base, bp->b_paddr, (fsize_t)bp->b_count);
		else
			plrcopy(bp->b_paddr, base, (fsize_t)bp->b_count);
	}
	bdone(bp);
}

/*
 * The read routine calls the common raw I/O processing code,
 * using a static buffer header in the driver.
 */
static
rmread(dev, iop) register dev_t dev; IO *iop;
{
	register BUF *bufp;

	bufp = &rm[rm_drive(dev)].rm_buf;
	ioreq(bufp, iop, dev, BREAD, BFIOC|BFRAW);
}

/*
 * The write routine is just like the read routine,
 * except that the function code is write instead of read.
 */
static
rmwrite(dev, iop) register dev_t dev; IO *iop;
{
	register BUF *bufp;

	bufp = &rm[rm_drive(dev)].rm_buf;
	ioreq(bufp, iop, dev, BWRITE, BFIOC|BFRAW);
}

/* end of rm.c */
0707070064030150211004440000030000030000011777770507310640300004600000015106/newbits/kernel/USRSRC/i8086/drv/rp.c/*
 *	Ram Pipe Device Driver
 */

#include <coherent.h>
#include <con.h>
#include <seg.h>
#include <stat.h>
#include <sched.h>
#include <termio.h>
#include <v7sgtty.h>
#include <uproc.h>
#include <errno.h>

#define	MAXNRP	30		/* Maximum number of ram pipes (must be < 32) */
#define	NCPQ	2048		/* Size of pipe in bytes */
#define	RPMAJOR 22		/* Major device for ram pipes  */

/*
 *	function definitions
 */
int	rpopen();
int	rpread();
int	rpwrite();
int	rpioctl();
int	rppoll();
void	rpuload();
int	nulldev();
int	nonedev();


/*
 *	configuration table
 */
CON rpcon = {
	DFCHR|DFPOL,			/* flags	*/
	RPMAJOR,			/* major index	*/
	rpopen,				/* open		*/
	nulldev,			/* close	*/
	nonedev,			/* block	*/
	rpread,				/* read		*/
	rpwrite,			/* write	*/
	rpioctl,			/* ioctl	*/
	nulldev,			/* power fail	*/
	nulldev,			/* timeout	*/
	nulldev,			/* load		*/
	rpuload,			/* unload	*/
	rppoll				/* poll		*/
};

/*
 *	Ram Pipe Headers
 */
static
struct ring {
	unsigned short	q_size;		/* Number of characters in queue    */
	unsigned short	q_mask;		/* Ring buffer Mask: NCPQ-1	    */
	faddr_t		q_ifaddr;	/* Input virtual address	    */
	faddr_t		q_ofaddr;	/* Output virtual address	    */
	GATE		q_igate;	/* Read lock			    */
	GATE		q_ogate;	/* Write lock			    */
	event_t		q_ipoll;	/* Input polls			    */
	event_t		q_opoll;	/* Output polls			    */

} rpq[MAXNRP];

static SEG * rpsegp;
unsigned NRP = MAXNRP;

/*
 * Initialization Routine
 */
static
rpinit()
{
	register struct ring *rp;
	faddr_t faddr;
	paddr_t paddr;

	/*
	 * Ensure valid number of ram pipes
	 */
	if ( NRP > MAXNRP )
		NRP = MAXNRP;
		
	/*
	 * Allocate ram pipe segment, initialize ram pipe queues
	 */
	 if ( NRP != 0 ) {
		rpsegp = salloc((fsize_t)NRP*NCPQ, SFSYST|SFHIGH|SFNSWP|SFNCLR);

		if ( rpsegp == NULL )
			return -1;

		paddr = rpsegp->s_paddr;

		for ( rp = &rpq[0]; rp < &rpq[NRP]; rp++, paddr += NCPQ ) {

			faddr = ptov( paddr, (fsize_t)NCPQ );
			rp->q_size = 0;
			rp->q_mask = NCPQ - 1;

			rp->q_ifaddr = faddr;
			rp->q_ofaddr = faddr;
		}
	}
	return 0;
}

/*
 * Unload Routine.
 */
static void
rpuload()
{
	register struct ring *rp;

	/*
	 * Release virtual address mappers.
	 */
	for ( rp = &rpq[0]; rp < &rpq[NRP]; rp++ ) {
		if ( rp->q_ifaddr )
			vrelse( rp->q_ifaddr );
	}

	/*
	 * Release ring buffer storage.
	 */
	if ( rpsegp != NULL ) {
		sfree( rpsegp );
		rpsegp = NULL;
	}

	/*
	 * Erase private data.
	 */
	memset( &rpq[0], 0, sizeof(rpq) );
}

/*
 * Open Routine
 */
static
rpopen( dev, mode )
dev_t dev;
{
	int s;

	s = sphi();
	if ( rpq[0].q_mask == 0 )
		if ( rpinit() < 0 )
			u.u_error = ENOSPC;
	spl( s );
	if ( minor(dev) >= NRP )
		u.u_error = ENXIO;
}

/*
 * Ioctl Routine
 */
static
rpioctl( dev, com, vec )
dev_t dev;
{
	switch ( com ) {

	case TIOCQUERY:
		putuwd( vec, rpq[ minor(dev) ].q_size );
		return;

	case TIOCOUTQ:
		putuwd( vec, rpq[ minor(dev) ].q_size );
		return;

	case TIOCFLUSH:
	case TCFLSH:
		rpflush( &rpq[minor(dev)] );
		return;

	default:
		u.u_error = EINVAL;
		return;
	}
}

/*
 * Read Routine
 */
static
rpread( dev, iop )
dev_t dev;
register IO *iop;
{
	register struct ring *rp;
	unsigned n;
	int s;

	rp = &rpq[ minor(dev) ];
	s  = sphi();

	/*
	 * Wait until read is unlocked, and there is data to read
	 */
	while ( (rp->q_igate[0] != 0) || ((n = rp->q_size) == 0) ) {

		/*
		 * Non-blocking reads.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			return;
		}

		++rp->q_igate[1];
		sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT );
		--rp->q_igate[1];

		if ( SELF->p_ssig && nondsig() ) {	/* signal received */

			spl( s );
			u.u_error = EINTR;
			return;
		}
	}
	rp->q_igate[0] = 1;			/* lock read gate	    */
	spl( s );

	if ( n > iop->io_ioc )			/* more data than requested */
		n = iop->io_ioc;

	rucopy( rp, iop->io_base, n );		/* copy data to user space  */
	iop->io_base += n;
	iop->io_ioc  -= n;

	if ( rp->q_ogate[1] != 0 )		/* someone waiting to write */
		wakeup( rp->q_ogate );
	if ( rp->q_opoll.e_procp )		/* someone polling to write */
		pollwake( &rp->q_opoll );

	rp->q_igate[0] = 0;			/* unlock read gate	    */

	if ( rp->q_igate[1] != 0 )		/* others waiting to read   */
		wakeup( rp->q_igate );
}

/*
 * Write Routine
 */
static
rpwrite( dev, iop )
dev_t dev;
register IO *iop;
{
	register struct ring *rp;
	unsigned n;
	int s;

	rp = &rpq[ minor(dev) ];

	do {
		s  = sphi();
		/*
		 * Wait until write is unlocked and 512 free slots exist
		 */

		while ((rp->q_ogate[0] != 0) || ((n = NCPQ-rp->q_size) < 512)) {

			/*
			 * Non-blocking writes.
			 */
			if ( iop->io_flag & IONDLY ) {
				u.u_error = EAGAIN;
				return;
			}

			++rp->q_ogate[1];
			sleep( rp->q_ogate, CVTTOUT, IVTTOUT, SVTTOUT );
			--rp->q_ogate[1];

			if (SELF->p_ssig && nondsig()) { /* received signal */

				spl( s );
				u.u_error = EINTR;
				return;
			}
		}
		rp->q_ogate[0] = 1;		/* lock write gate	     */
		spl( s );

		if ( n > iop->io_ioc )
			n = iop->io_ioc;

		urcopy( iop->io_base, rp, n );	/* copy data from user space */
		iop->io_base += n;
		iop->io_ioc  -= n;

		rp->q_ogate[0] = 0;		/* unlock write gate	     */

		if ( rp->q_igate[1] != 0 )	/* someone waiting to read   */
			wakeup( rp->q_igate );

		if ( rp->q_ipoll.e_procp )	/* someone polling to read */
			pollwake( &rp->q_ipoll );

	} while ( iop->io_ioc != 0 );		/* until all data copied     */

	if (rp->q_ogate[1] != 0)		/* someone waiting to write  */
		wakeup( rp->q_ogate );
}

/*
 * Poll.
 */
rppoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	register struct ring *rp = &rpq[ minor(dev) ];

	ev &= ~POLLPRI;

	/*
	 * Input poll.
	 */
	if ( ev & POLLIN ) {

		/*
		 * Pipe empty.
		 */
		if ( FP_OFF(rp->q_ifaddr) == FP_OFF(rp->q_ofaddr) ) {
			if ( msec != 0 )
				pollopen( &rp->q_ipoll );
			ev &= ~POLLIN;
		}
	}

	/*
	 * Output poll.
	 */
	if ( ev & POLLOUT ) {

		/*
		 * Pipe not empty.
		 */
		if ( FP_OFF(rp->q_ifaddr) != FP_OFF(rp->q_ofaddr) ) {
			if ( msec != 0 )
				pollopen( &rp->q_opoll );
			ev &= ~POLLOUT;
		}
	}

	return ev;
}

/*
 * Flush queue
 */
static
rpflush( rp )
register struct ring *rp;
{
	register int s;

	s = sphi();

	/*
	 * Wait until read is unlocked, or nothing in queue
	 */

	while ((rp->q_size != 0) && (rp->q_igate[0] != 0) ) {

		++rp->q_igate[1];
		sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT );
		--rp->q_igate[1];

		if (SELF->p_ssig && nondsig()) { /* received signal	   */

			spl( s );
			u.u_error = EINTR;
			return;
		}
	}

	if (rp->q_size != 0) {			/* flush ram pipe	   */

		rp->q_ofaddr = rp->q_ifaddr;
		rp->q_size = 0;
	}
	spl( s );

	if (rp->q_ogate[1] != 0)		/* someone waiting to write */
		wakeup( rp->q_ogate );

	if ( rp->q_opoll.e_procp )		/* someone polling to write */
		pollwake( &rp->q_opoll );
}
0707070064030150201004440000030000030000011777770507310640500005000000005172/newbits/kernel/USRSRC/i8086/drv/rpas.s////////
/
/ Ram Pipe Device Driver Assembler Support
/
/	urcopy( up, np, n )	-- copy user data to pipe
/	rucopy( np, up, n )	-- copy pipe data to user
/
////////

	.globl	urcopy_
	.globl	rucopy_

////////
/
/ Offsets of fields within the ram pipe structure
/
////////

	Q_SIZE	= 0
	Q_MASK	= 2
	Q_IX	= 4
	Q_ISEG	= 6
	Q_OX	= 8
	Q_OSEG	= 10
	Q_IGATE	= 12
	Q_OGATE	= 14

////////
/
/ Urcopy ( up, rp, cnt )
/ char * up;
/ struct ring * rp;
/ unsigned cnt;
/
/	Input:	up  = pointer to user data to copy.
/		rp  = pointer to ring structure to copy data to.
/		cnt = number of data bytes to copy.
/
/	Action:	Copy CNT bytes from UP to RP->Q_IX.
/
/	Return:	Number of bytes transferred.
/
////////

urcopy_:				/ urcopy ( up, rp, cnt )
	push	si			/ register char *up;		/* SI */
	push	di			/ register struct ring *rp;	/* BX */
	push	bp			/ unsigned cnt;
	mov	bp, sp			/ {
	pushf				/	register char *cp;	/* DI */
	push	ds			/	register unsigned ret;	/* AX */
	push	es			/	register unsigned n;	/* CX */
					/	register unsigned m;	/* DX */
	mov	si, 8(bp)		/
	mov	bx, 10(bp)		/
	mov	cx, 12(bp)		/	n  = cnt;
	mov	dx, Q_MASK(bx)		/	m  = rp->q_mask;
	les	di, Q_IX(bx)		/	cp = rp->q_ix;
	mov	ds, uds_		/
					/
	cld				/
0:	movsb				/	do {	*cp++ = *up++;
	and	di, dx			/		wrap(cp);
	loop	0b			/	} while (--n != 0);
					/
	pop	es			/
	pop	ds			/
	mov	ax, 12(bp)		/	ret = cnt;
	cli				/	s   = sphi();
	mov	Q_IX(bx), di		/	rp->q_ix = cp;
	add	Q_SIZE(bx), ax		/	rp->q_size += ret;
	popf				/	spl( s );
	pop	bp			/
	pop	di			/	return ret;
	pop	si			/
	ret				/ }

////////
/
/ Rucopy ( rp, up, cnt )
/ struct ring * rp;
/ char * up;
/ unsigned cnt;
/
/	Input:	rp  = pointer to ring structure to copy data from.
/		up  = pointer to user data.
/		cnt = number of data bytes to copy.
/
/	Action:	Copy CNT bytes from RP->Q_OX to UP.
/
/	Return:	None.
/
////////

rucopy_:				/ rucopy ( rp, up, cnt )
	push	si			/ register struct ring *rp;	/* BX */
	push	di			/ register char * up;		/* DI */
	push	bp			/ unsigned cnt;
	mov	bp, sp			/ {
	pushf				/	register char *cp;	/* SI */
	push	ds			/	register unsigned ret;	/* AX */
	push	es			/	register unsigned n;	/* CX */
					/	register unsigned m;	/* DX */
	mov	bx, 8(bp)		/
	mov	di, 10(bp)		/
	mov	cx, 12(bp)		/
	mov	dx, Q_MASK(bx)		/	m = rp->q_mask;
	mov	es, uds_		/
	lds	si, Q_OX(bx)		/	cp = rp->q_ox;
					/
	cld				/
0:	movsb				/	do {	*up++ = *cp++;
	and	si, dx			/		wrap(cp);
	loop	0b			/	} while (--cnt != 0);
					/
	pop	es			/
	pop	ds			/
	mov	ax, 12(bp)		/	ret = cnt;
	cli				/	s   = sphi();
	mov	Q_OX(bx), si		/	rp->q_ox = cp;
	sub	Q_SIZE(bx), ax		/	rp->q_size -= ret;
	popf				/	spl( s );
	pop	bp			/
	pop	di			/	return ret;
	pop	si			/
	ret				/ }
0707070064030150221004440000030000030000011777770507310640600004600000050543/newbits/kernel/USRSRC/i8086/drv/rs.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Raw Serial Device Driver.
 *
 *	Provides fast, efficiently buffered serial i/o to COM1 & COM2.
 *	Supports an extreme subset of System V (termio) parameters.
 *		c_iflag: ISTRIP, IXON, IXANY, IGNBRK, INPCK, PARMRK, IGNPAR.
 * 		c_oflag: OPOST, ONLCR, ONLRET, TAB3.
 *		c_cflag: *.
 *
 */

#include <sys/coherent.h>
#include <sys/ins8250.h>
#include <sys/proc.h>
#include <sys/uproc.h>
#include <sys/con.h>
#include <sys/devices.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <termio.h>
#include <errno.h>

#define	COM1VEC		4		/* interrupt vector for COM1	*/
#define	COM2VEC		3		/* interrupt vector for COM2	*/

#define	COM1PORT	0x3F8		/* i/o port address for COM1	*/
#define	COM2PORT	0x2F8		/* i/o port address for COM2	*/

#ifdef	RS1
#	define	CFLAG	RS1CFLAG
#	define	MAJ	AL1_MAJOR	/* major device for /dev/rs1	*/
#	define	rscon	rs1con		/* configuration table for "	*/
#	define	rstty	rs1tty
#	define	IVEC	COM2VEC		/* interrupt vector for rs1	*/
#	define	PORT	COM2PORT	/* i/o port address for rs1	*/
#else
#	define	CFLAG	RS0CFLAG
#	define	MAJ	AL0_MAJOR	/* major device for /dev/rs0	*/
#	define	rscon	rs0con		/* configuration table for "	*/
#	define	rstty	rs0tty
#	define	IVEC	COM1VEC		/* interrupt vector for rs0	*/
#	define	PORT	COM1PORT	/* i/o port address for rs0	*/
#endif

#define	CTRLS	'\023'
#define	CTRLQ	'\021'

/*
 * Functions.
 */

int	rsload();
int	rsunload();
int	rsopen();
int	rsclose();
int	rsread();
int	rswrite();
int	rsioctl();
int	rspoll();
int	nulldev();
int	nonedev();

int	rsintr();
int	rsparam();

/*
 * Configuration table.
 */

CON rscon ={
	DFCHR|DFPOL,			/* Flags */
	MAJ,				/* Major index */
	rsopen,				/* Open */
	rsclose,			/* Close */
	nulldev,			/* Block */
	rsread,				/* Read */
	rswrite,			/* Write */
	rsioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	rsload,				/* Load */
	rsunload,			/* Unload */
	rspoll				/* Poll */
};

/*
 * Terminal structure.
 */

#define	RAWSZ	(2048-1)
#define	OUTSZ	(2048-1)

#define	NRAWC	((rsrawq.rq_ix - rsrawq.rq_ox) & RAWSZ)
#define	NOUTC	((rsoutq.rq_ix - rsoutq.rq_ox) & OUTSZ)

#define	TTSTOP	00001
#define	TTSBRK	00002
#define	CARRIER	00004

typedef
struct rawtty_s {
	unsigned	rt_state;	/* terminal state		*/
	int		rt_group;	/* controlling process group	*/
	unsigned	rt_ticks;	/* send break 1/10 sec counter	*/
	unsigned	rt_iflag;	/* termio input   flags		*/
	unsigned	rt_oflag;	/* termio output  flags		*/
	unsigned	rt_cflag;	/* termio control flags		*/
	unsigned char	rt_col;		/* current output column	*/
	unsigned char	rt_refc;	/* # procs accessing the port	*/
	unsigned char	rt_irefc;	/* # procs waiting for input	*/
	unsigned char	rt_orefc;	/* # procs waitint for output	*/
	unsigned char	rt_crefc;	/* # procs waiting for carrier	*/
	unsigned char	rt_drefc;	/* # procs waiting for drain	*/
	event_t		rt_ipolls;	/* Procs polling on input queue	*/
	event_t		rt_opolls;	/* Procs polling on output que  */
} RAWTTY;

typedef
struct iring_s {
	unsigned short	rq_mask;
	unsigned short	rq_ix;
	unsigned short	rq_ox;
	unsigned char	rq_cc[RAWSZ+1];
} IRING;

typedef
struct oring_s {
	unsigned short	rq_mask;
	unsigned short	rq_ix;
	unsigned short	rq_ox;
	unsigned char	rq_cc[OUTSZ+1];
} ORING;

/*
 * Local variables.
 */
unsigned CFLAG  = CLOCAL | CREAD | B1200 | CS8 | HUPCL;
RAWTTY	rstty;
static ORING	rsoutq;
static IRING	rsrawq;
static TIM	rstim;

/*
 * Time constant table.
 * Indexed by ioctl baud rate.
 */
static
int timeconst[] = {
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	48,				/* 2400 */
	24,				/* 4800 */
	12,				/* 9600 */
	6,				/* 19200/EXTA */
	6				/* 19200/EXTB */
};

/*
 * Rsload() -- Raw Serial Load Routine.
 *
 *	Action:	Define terminal parameters.
 *		Initialize terminal hardware.
 *		If serial port exists, seize its interrupt vector.
 *
 *	Return:	None.
 */

static
rsload()
{
	/*
	 * Initialize terminal parameters.
	 */
	rsoutq.rq_mask = OUTSZ;
	rsrawq.rq_mask = RAWSZ;

	/*
	 * Initialize terminal hardware.
	 */
	rsparam();

	/*
	 * If serial port exists, initialize interrupt vector.
	 */
	if ( inb(PORT+IER) == 0 ) {
		setivec( IVEC, rsintr);
		rscycle();
	}
}

/*
 * Rsunload() -- Raw Serial unload Routine.
 */

static
rsunload()
{
	timeout( &rstim, 0, NULL, 0 );	/* cancel timed function */
	clrivec( IVEC );		/* release interrupt vector */
	outb(PORT+IER, 0);		/* disable port interrupts */
	outb(PORT+MCR, MC_OUT2);	/* hangup port */
}

/*
 * Rsopen -- Open Routine.
 *
 *	Input:	dev = device to open.
 *		If high bit (0x80) set in minor, modem control is requested.
 *
 *	Action:	Validate minor device.
 *		Increment reference count.
 *		If first reference and parameters are not initialized,
 *			set default parameters and initialize hardware.
 *
 *	Return:	None.
 */

static
rsopen( dev, mode )

dev_t dev;

{
	register PROC *pp = SELF;

	/*
	 * Validate minor device.
	 */
	if (minor(dev) & ~0x80) {
		u.u_error = ENODEV;
		return;
	}

	/*
	 * Validate hardware.
	 */
	if (inb(PORT+IER) & ~(IE_RxI|IE_TxI|IE_LSI)) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Ensure controlling terminal and group fields initialized.
	 */
	if (pp->p_ttdev == NODEV)
		pp->p_ttdev = dev;
	if (pp->p_group == 0)
		pp->p_group = pp->p_pid;

	/*
	 * Check for first open.
	 */
	if (++rstty.rt_refc == 1) {

		if (pp->p_group == pp->p_pid)
			rstty.rt_group = pp->p_group;

		if ((rstty.rt_cflag & CBAUD) == B0) {

			/*
			 * Define terminal parameters.
			 */
			rstty.rt_state = 0;
			rstty.rt_col   = 0;
			rstty.rt_iflag = ISTRIP | IXON;
			rstty.rt_oflag = OPOST  | ONLCR | TAB3;
			rstty.rt_cflag = CFLAG;
			if ( minor(dev) & 0x80 )
				rstty.rt_cflag &= ~CLOCAL;

			/*
			 * Initialize terminal hardware.
			 */
			rsparam();
		}

		/*
		 * Discard input data.
		 */
		rsrawq.rq_ox = rsrawq.rq_ix;
	}

	/*
	 * If modem control is requested, check carrier.
	 */
	if ( minor(dev) & 0x80 ) {

		/*
		 * Delay until carrier is present.
		 */
		while ( (rstty.rt_state & CARRIER) == 0 ) {

			/*
			 * Sleep on carrier.
			 */
			++rstty.rt_crefc;
			sleep( &rstty.rt_crefc,
				CVTTOUT, IVTTOUT, SVTTOUT);
			--rstty.rt_crefc;

			/*
			 * Abort if non-ignored signal is received.
			 */
			if (SELF->p_ssig && nondsig()) {

				if (--rstty.rt_refc == 0) {
					rstty.rt_group = 0;
					rstty.rt_cflag = 0;
					rsparam();
				}
				u.u_error = EINTR;
				return;
			}
		}
	}
}

/*
 * Rsclose -- Close Routine.
 *
 *	Action:	Decrement reference count.
 *		If serial port is no longer referenced,
 *		and the hangup on last close bit is set in rt_cflag,
 *		clear terminal parameters, and initialize hardware.
 *
 *	Return:	None.
 *
 *	Note:	This routine does not wait for the output queue to empty.
 */

static
rsclose( dev )

dev_t dev;

{
	/*
	 * Check for last close and hangup on close.
	 */
	if ((rstty.rt_refc == 1) && (rstty.rt_cflag & HUPCL)) {

		/*
		 * Wait for output to drain.
		 */
		while ( rsoutq.rq_ox != rsoutq.rq_ix ) {

			++rstty.rt_drefc;
			sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT );
			--rstty.rt_drefc;

			if (rstty.rt_refc != 1) {
				rstty.rt_refc--;
				return;
			}

			if (SELF->p_ssig && nondsig())
				break;
		}

		/*
		 * Initialize terminal hardware.
		 */
		rstty.rt_group = 0;
		rstty.rt_cflag = 0;
		rsparam();

		/*
		 * Flush input and output queues.
		 */
		rsrawq.rq_ix =
		rsrawq.rq_ox =
		rsoutq.rq_ox =
		rsoutq.rq_ix = 0;
	}
	--rstty.rt_refc;
}

/*
 * Rsread -- Read Routine.
 *
 *	Input:	iop = pointer to structure containing i/o parameters.
 *
 *	Action:	Attempt to read data from input buffer until at least
 *		one character has been read, or a signal is received
 *		by the current process.
 *		Update the parameters in the io structure.
 *		If a signal is received, set errno to EINTR.
 *
 *	Return:	None.
 */

static
rsread( dev, iop )

dev_t dev;
register IO *iop;

{
	register int sioc;

	/*
	 * Remember original char count.
	 */
	sioc = iop->io_ioc;

	do {
		/*
		 * Transfer data until done or input buffer empty.
		 */
		rsin( &rsrawq, iop );

		/*
		 * Return if some data was transferred.
		 */
		if (sioc != iop->io_ioc)
			return;

		/*
		 * Non-blocking reads.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			return;
		}

		/*
		 * Sleep waiting for a signal or input data.
		 */
		++rstty.rt_irefc;
		sleep( &rstty.rt_irefc, CVTTOUT, IVTTOUT, SVTTOUT );
		--rstty.rt_irefc;

		/*
		 * Abort if a non-ignored signal was received.
		 */
		if (SELF->p_ssig && nondsig()) {
			u.u_error = EINTR;
			return;
		}

	} while (1);
}

/*
 * Rswrite -- Write Routine.
 */

static
rswrite( dev, iop )

dev_t dev;
register IO *iop;

{
	register int n;

	/*
	 * Non-blocking write.
	 */
	if ( iop->io_flag & IONDLY ) {

		/*
		 * Calculate free slots.
		 */
		n  = rsoutq.rq_mask - rsoutq.rq_ix + rsoutq.rq_ox;
		n &= rsoutq.rq_mask;

		/*
		 * Insufficient space.
		 */
		if ( n <= iop->io_ioc ) {
			u.u_error = EAGAIN;
			return;
		}
	}

	do {
		/*
		 * Transfer data until done or output queue full.
		 */
		rsout( &rsoutq, iop );

		/*
		 * Make sure the transmitter is operating.
		 */
		rsstart();

		/*
		 * Return if all data was transferred.
		 */
		if ( iop->io_ioc == 0 )
			return;

		/*
		 * Sleep waiting for a signal or room in the output queue.
		 */
		++rstty.rt_orefc;
		sleep( &rstty.rt_orefc, CVTTOUT, IVTTOUT, SVTTOUT );
		--rstty.rt_orefc;

		/*
		 * Abort if a non-ignored signal was received.
		 */
		if ( SELF->p_ssig && nondsig() ) {
			u.u_error = EINTR;
			return;
		}

	} while (1);
}

/*
 * Rspoll -- Polling Routine.
 */
static int
rspoll( dev, ev, msec )
dev_t dev;
register int ev;
int msec;
{
	/*
	 * No priority reports.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll with empty input ring.
	 */
	if ( (ev & POLLIN) && (rsrawq.rq_ix == rsrawq.rq_ox) ) {

		/*
		 * Blocking input poll.
		 */
		if ( msec != 0 )
			pollopen( &rstty.rt_ipolls );

		/*
		 * Second look and clear input report.
		 */
		if ( rsrawq.rq_ix == rsrawq.rq_ox )
			ev &= ~POLLIN;
	}

	/*
	 * Output poll with non-empty output ring.
	 */
	if ( (ev & POLLOUT) && (rsoutq.rq_ix != rsrawq.rq_ox) ) {

		/*
		 * Blocking output poll.
		 */
		if ( msec != 0 )
			pollopen( &rstty.rt_opolls );

		/*
		 * Second look and clear output report.
		 */
		if ( rsoutq.rq_ix != rsoutq.rq_ox )
			ev &= ~POLLOUT;
	}

	return ev;
}

/*
 * Cyclic [1 sec] Routine.
 */
static
rscycle()
{
	register PROC *pp;
	register int b;

	/*
	 * Check for carrier transitions.
	 */
	if ( inb( PORT + MSR ) & MS_RLSD ) {

		/*
		 * Have carrier.  Wake processes waiting for carrier.
		 */
		rstty.rt_state |= CARRIER;

		if ( rstty.rt_crefc )
			wakeup( &rstty.rt_crefc );
	}
	else if ((rstty.rt_state & CARRIER) && (rstty.rt_cflag&CLOCAL) == 0) {

		/*
		 * Lost carrier. Signal attached processes.
		 */
		rstty.rt_state &= ~CARRIER;

		if (rstty.rt_refc && (b = rstty.rt_group))
			for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw)
				if ( pp->p_group == b )
					sendsig( SIGHUP, pp );
	}

	/*
	 * Wakeup processes waiting to read if input data present.
	 */
	if ( rsrawq.rq_ix != rsrawq.rq_ox ) {
		if ( rstty.rt_irefc )
			wakeup( &rstty.rt_irefc );
		if ( rstty.rt_ipolls.e_procp )
			pollwake( &rstty.rt_ipolls );
	}

	/*
	 * Check for break being sent.
	 */
	if ( rstty.rt_ticks != 0 ) {

		if ( --rstty.rt_ticks == 0 ) {

			b = inb( PORT + LCR );
			outb( PORT + LCR, b & ~LC_SBRK );
			rstty.rt_state &= ~TTSBRK;
		}
	}

	/*
	 * Can check output if not sending break.
	 */
	if ( rstty.rt_ticks == 0 ) {

		/*
		 * Restart output if necessary.
		 */
		if ( rsoutq.rq_ox != rsoutq.rq_ix )
			rsstart();

		/*
		 * Wakeup processes waiting for drain if output queue empty.
		 */
		if ( rstty.rt_drefc ) {
			if ( rsoutq.rq_ix == rsoutq.rq_ox )
				wakeup( &rstty.rt_drefc );
		}

		/*
		 * Wakeup processes waiting to write if 512 slots are free.
		 */
		else if ( NOUTC < OUTSZ-512 ) {
			if ( rstty.rt_orefc )
				wakeup( &rstty.rt_orefc );
			if ( rstty.rt_opolls.e_procp )
				pollwake( &rstty.rt_opolls );
		}
	}

	timeout( &rstim, HZ/10, rscycle, 0 );
}

/*
 * Rsintr -- Serial Interrupt Handler.
 *
 *	Action:	Process all pending interrupt service requests
 *		on the serial port.
 *
 *	Return:	None.
 *
 *	Notes:	This routine must loop until all requests are serviced
 *		because of the edge sensitive nature of the programmable
 *		interrupt controller.
 */

static
rsintr()
{
	register int b;

	/*
	 * Service serial port interrupt requests, highest to lowest priority.
	 */
rescan:
	b = inb( PORT + IIR );

	switch ( b ) {

	case LS_INTR:
		/*
		 * Get line status (clear interrupt).
		 */
		b = inb( PORT + LSR );

		/*
		 * Check for received break.
		 */
		if (b & LS_BREAK) {

			/*
			 * Read the break char ('\0').
			 */
			rsrawq.rq_cc[ rsrawq.rq_ix ] = inb( PORT + DREG );

			/*
			 * Clear output stops.
			 */
			rstty.rt_state &= ~TTSTOP;

			/*
			 * Update input index if not ignoring break.
			 */
			if ((rstty.rt_iflag & IGNBRK) == 0) {
				rsrawq.rq_ix ++;
				rsrawq.rq_ix &= RAWSZ;
			}
		}

		/*
		 * Special handling if frame/parity error and checking enabled.
		 */
		if ((b & (LS_FRAME|LS_PARITY)) && (rstty.rt_iflag & INPCK)) {

			/*
			 * Ignore next input char if IGNPAR set.
			 */
			if (rstty.rt_iflag & IGNPAR)
				inb( PORT + DREG );
			/*
			 * Change next input char into 0377,0,ch if PARMRK set.
			 */
			else if (rstty.rt_iflag & PARMRK) {

				b = rsrawq.rq_ix;
				rsrawq.rq_cc[ b++ ] = 0377;
				b &= RAWSZ;
				rsrawq.rq_cc[ b++ ] = '\0';
				b &= RAWSZ;
				rsrawq.rq_cc[ b++ ] = inb( PORT + DREG );
				b &= RAWSZ;
				rsrawq.rq_ix = b;
			}

			/*
			 * Otherwise change next input char into null.
			 */
			else {
				inb( PORT + DREG );
				rsrawq.rq_cc[ rsrawq.rq_ix++ ] = '\0';
				rsrawq.rq_ix &= RAWSZ;
			}
		}
		goto rescan;

	case Rx_INTR:
		/*
		 * Read character from receive buffer.
		 */
		b = inb( PORT + DREG );

		/*
		 * Discard high bit if ISTRIP set.
		 */
		if ( rstty.rt_iflag & ISTRIP )
			b &= 0177;

		/*
		 * Check for output flow control if IXON set.
		 */
		if ( rstty.rt_iflag & IXON ) {

			/*
			 * Stop output if Ctl-S.
			 */
			if ( b == CTRLS ) {
				rstty.rt_state |= TTSTOP;
				goto rescan;
			}

			/*
			 * Resume output if Ctl-Q.
			 */
			if ( b == CTRLQ ) {
				rstty.rt_state &= ~TTSTOP;
				goto rescan;
			}

			/*
			 * Enable output if IXANY set.
			 */
			if ( rstty.rt_iflag & IXANY )
				rstty.rt_state &= ~TTSTOP;
		}

		/*
		 * Save the character in the input queue.
		 */
		rsrawq.rq_cc[ rsrawq.rq_ix++ ] = b;
		rsrawq.rq_ix &= RAWSZ;

		/*
		 * Save again if 0377 and parity marking enabled.
		 */
		if ((b == 0377)
		&&  ((rstty.rt_iflag & (INPCK|PARMRK)) == (INPCK|PARMRK))) {

			rsrawq.rq_cc[ rsrawq.rq_ix++ ] = b;
			rsrawq.rq_ix &= RAWSZ;
		}

		goto rescan;

	case Tx_INTR:
		rsstart();
		goto rescan;
	}
}

/*
 * Rsstart()
 *
 *	Action:	While output data is available, and the transmitter buffer
 *		is empty, transfer one character from the output queue to the
 *		transmit buffer.
 *
 *	Return:	None.
 */

static
rsstart()
{
	register int b;
	register int s;

	/*
	 * Can't transmit if output stopped or sending break.
	 */
	if ( rstty.rt_state & (TTSTOP|TTSBRK) )
		return;

	/*
	 * Can't transmit if modem control enabled without CTS present.
	 */
	if ( (rstty.rt_cflag & CLOCAL) == 0 )
		if ( (inb(PORT+MSR) & MS_CTS) == 0 )
			return;

	/*
	 * Disable interrupts to avoid critical race.
	 */
	s = sphi();

	/*
	 * Can transmit if output data available and transmit buffer empty.
	 */
	if ( (rsoutq.rq_ix != rsoutq.rq_ox)
	&&   (inb(PORT+LSR) & LS_TxRDY)	) {

		/*
		 * Get next char from output queue.
		 */
		b = rsoutq.rq_cc [ rsoutq.rq_ox ];

		if (rstty.rt_oflag & OPOST) {

			/*
			 * Printable characters increment the column.
			 */
			if (b >= ' ') {
				rstty.rt_col++;
			}
			/*
			 * Carriage return resets the column.
			 */
			else if (b == '\r') {
				rstty.rt_col = 0;
				if (rstty.rt_oflag & OCRNL)
					b = '\n';
			}
			/*
			 * New-line may also generate a carriage return.
			 */
			else if (b == '\n') {
				if (rstty.rt_oflag & ONLCR) {
					if (rstty.rt_col) {
						rstty.rt_col = 0;
						rsoutq.rq_ox--;
						b = '\r';
					}
				}
				else if (rstty.rt_oflag & ONLRET)
					rstty.rt_col = 0;
			}
			/*
			 * Backspace decrements the column.
			 */
			else if (b == '\b') {
				if (rstty.rt_col)
					--rstty.rt_col;
			}
			/*
			 * Tabs may generate spaces, always move to tab stop.
			 */
			else if (b == '\t') {
				if ((rstty.rt_oflag & TABDLY) == TAB3) {
					b = ' ';
					if (++rstty.rt_col & 7)
						rsoutq.rq_ox--;
				}
				else {
					rstty.rt_col |= 7;
					rstty.rt_col++;
				}
			}
		}
		rsoutq.rq_ox++;
		rsoutq.rq_ox &= OUTSZ;

		/*
		 * Transmit next char.
		 */
		outb( PORT+DREG, b );
	}

	spl(s);
}

/*
 * Ioctl Routine.
 */

static
rsioctl( dev, com, vec )

dev_t dev;
int com;
struct termio *vec;

{
	register int b;
	struct termio tb;

	switch (com) {

	case TCSETAW:	/* Set attributes after waiting for output to clear */
	case TCSETAF:	/* ditto, but also flush input queue */
	case TCSBRK:	/* wait for output to clear, send break */

		/*
		 * Delay until output queue is empty.
		 */
		while ( rsoutq.rq_ox != rsoutq.rq_ix ) {

			/*
			 * Sleep waiting for empty output queue.
			 */
			++rstty.rt_drefc;
			sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT);
			--rstty.rt_drefc;

			/*
			 * Abort if a non-ignored signal was received.
			 */
			if ( SELF->p_ssig && nondsig() ) {
				u.u_error = EINTR;
				return;
			}
		}

		if ( com == TCSBRK ) {

			b = inb( PORT + LCR );

			if ( vec == 0 ) {
				rstty.rt_ticks  = 3;	/* 0.2 to 0.3 sec */
				rstty.rt_state |= TTSBRK;
				b |= LC_SBRK;
			}
			else {
				rstty.rt_ticks  = 0;
				rstty.rt_state &= ~TTSBRK;
				b &= ~LC_SBRK;
			}

			outb( PORT + LCR, b );
			return;
		}
		/* no break */

	case TCSETA:
		/*
		 * Get new terminal attributes.
		 */
		ukcopy( vec, &tb, sizeof(tb) );
		if ( u.u_error )
			return;

		/*
		 * Set terminal attributes and hardware.
		 */
		rstty.rt_iflag = tb.c_iflag;
		rstty.rt_oflag = tb.c_oflag;
		if (rstty.rt_cflag != tb.c_cflag) {
			rstty.rt_cflag = tb.c_cflag;
			rsparam();
		}

		if ((rstty.rt_iflag & IXON) == 0)
			rstty.rt_state &= ~TTSTOP;

		/*
		 * Flush input queue if command was TCSETAF.
		 */
		if ( com == TCSETAF )
			rsrawq.rq_ox = rsrawq.rq_ix;
		break;

	case TCGETA:	/* Get terminal attributes */
		
		memset( &tb, 0, sizeof(tb) );
		tb.c_cflag = rstty.rt_cflag;
		tb.c_iflag = rstty.rt_iflag;
		tb.c_oflag = rstty.rt_oflag;

		/*
		 * Transfer terminal attributes to user space.
		 */
		kucopy( &tb, vec, sizeof(tb) );
		break;

	case TCFLSH:
		switch ((int) vec) {
		case 0:
			/* flush input queue */
			rsrawq.rq_ox = rsrawq.rq_ix;
			break;
		case 1:
			/* flush output queue */
			rsoutq.rq_ox = rsoutq.rq_ix;
			break;
		case 2:
			/* flush both input and output queues */
			rsrawq.rq_ox = rsrawq.rq_ix;
			rsoutq.rq_ox = rsoutq.rq_ix;
			break;
		default:
			u.u_error = EINVAL;
		}
		break;

	case TCXONC:
		switch ( (int) vec ) {
		case 0:
			/* stop output */
			rstty.rt_state |= TTSTOP;
			break;
		case 1:
			/* restart output */
			rstty.rt_state &= ~TTSTOP;
			rsstart();
			break;
		default:
			u.u_error = EINVAL;
		}
		break;

	default:
		u.u_error = EINVAL;
	}
}

/*
 * Rsparam -- Setup hardware parameters.
 */

static
rsparam()
{
	register int b;
	register int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Assert required modem control lines (DTR, RTS).
	 */
	if ((rstty.rt_cflag & CBAUD) == B0)
		outb( PORT+MCR, MC_OUT2 );
	else if ((rstty.rt_refc == 0) && (rstty.rt_cflag & HUPCL))
		outb( PORT+MCR, MC_OUT2 );
	else
		outb( PORT+MCR, MC_OUT2+MC_DTR+MC_RTS );

	/*
	 * Program baud rate.
	 */
	if (b = timeconst[ rstty.rt_cflag & CBAUD ]) {
		outb( PORT+LCR, LC_DLAB );
		outb( PORT+DLL, b );
		outb( PORT+DLH, b >> 8 );
	}

	/*
	 * Program character size, parity, and stop bits.
	 */
	switch (rstty.rt_cflag & CSIZE) {
	case CS5:		b = LC_CS5;			break;
	case CS6:		b = LC_CS6;			break;
	case CS7:		b = LC_CS7;			break;
	case CS8:		b = LC_CS8;			break;
	}

	switch (rstty.rt_cflag & (PARENB|PARODD)) {
	case PARENB:		b |= LC_PARENB|LC_PAREVEN;	break;
	case PARENB|PARODD:	b |= LC_PARENB;			break;
	}

	if (rstty.rt_cflag & CSTOPB)
		b |= LC_STOPB;

	if (rstty.rt_state & TTSBRK)
		b |= LC_SBRK;

	outb( PORT+LCR, b );

	/*
	 * Enable desired interrupts.
	 */
	b = 0;
	if (rstty.rt_cflag & CBAUD) {
		b = IE_TxI | IE_LSI;
		if (rstty.rt_cflag & CREAD)
			b |= IE_RxI;
	}
	outb( PORT+IER, b );

	/*
	 * Enable interrupts.
	 */
	spl( s );
}
0707070064030150161004440000030000030000011777770507310641300005000000004214/newbits/kernel/USRSRC/i8086/drv/rsas.s/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ Raw Serial Device Driver - Assembler Support
/
////////

////////
/
/ Locally defined global symbols
/
////////

	.globl	rsin_
	.globl	rsout_

////////
/
/ Offsets to fields in the IRING and ORING data structures.
/
////////

	Q_MASK	= 0
	Q_IX	= 2
	Q_OX	= 4
	Q_CC	= 6

////////
/
/ Offsets to fields in the IO data structure.
/
////////

	IO_IOC	= 2
	IO_BASE	= 8

////////
/
/ Rsin ( rawqp, iop )	-- transfer data from input ring to user
/ IRING *rawqp;
/ IO *iop;
/
////////

rsin_:
	push	si				/ Save SI, DI, BP, ES
	push	di
	push	bp
	mov	bp, sp
	push	es

	mov	bx, 10(bp)			/ User destination --> ES:DI
	mov	di, IO_BASE(bx)
	mov	es, uds_

	cld					/ Auto Increment
	mov	cx, IO_IOC(bx)			/ Byte count --> CX
	jcxz	1f

	mov	bx, 8(bp)			/ rawqp --> BX

	mov	si, Q_OX(bx)
	cmp	si, Q_IX(bx)			/ Input data available?
	je	1f

0:	movb	al, Q_CC(bx,si)			/ Yes,	read one character
	inc	si				/	update index
	and	si, Q_MASK(bx)			/	(wrap if necessary)
	stosb					/	write to user space
	cmp	si, Q_IX(bx)			/	More input data?
	loopne	0b				/

	mov	Q_OX(bx), si			/ Save revised index
	mov	bx, 10(bp)			/ Update io parameters
	mov	IO_BASE(bx), di
	mov	IO_IOC(bx), cx

1:	pop	es				/ Restore ES, BP, DI, SI.
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ Rsout( outqp, iop )	-- transfer data from user to output ring
/ ORING *outqp;
/ IO *iop;
/
////////

rsout_:
	push	si				/ Save SI, DI, BP, ES
	push	di
	push	bp
	mov	bp, sp
	push	es

	mov	bx, 10(bp)			/ User source --> ES:DI
	mov	di, IO_BASE(bx)
	mov	es, uds_

	mov	cx, IO_IOC(bx)			/ Byte count --> CX
	jcxz	2f

	mov	bx, 8(bp)			/ outqp --> BX
	mov	si, Q_IX(bx)

0:	movb	al, es:(di)
	inc	di
	movb	Q_CC(bx,si), al
	inc	si
	and	si, Q_MASK(bx)
	cmp	si, Q_OX(bx)
	loopne	0b

	jne	1f				/ If can't save last char
	dec	di				/	Undo changes.
	dec	si
	and	si, Q_MASK(bx)
	inc	cx

1:	mov	Q_IX(bx), si			/ Save revised index
	mov	bx, 10(bp)
	mov	IO_BASE(bx), di			/ Update io parameters
	mov	IO_IOC(bx), cx

2:	pop	es				/ Restore ES, BP, DI, SI.
	pop	bp
	pop	di
	pop	si
	ret
0707070064030150171006440000030000030000011777770507310641300005000000027231/newbits/kernel/USRSRC/i8086/drv/scsi.c/*
 * This is the generic SCSI part of the
 * Adaptec AHA154x host adapter driver for the AT.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.6  91/06/10  13:28:11  hal
 * Refix startup problem with HDGETA.  Text cleanup.
 * 
 * Revision 1.5  91/06/10  12:58:04  hal
 * Partial fix for HDGETA failing if partition table absent.
 * 
 * Revision 1.4  91/06/03  13:50:06  hal
 * Add HDSETA.
 * 
 * Revision 1.3	91/05/08  11:00:30	root
 * Make number of heads - SD_HDS - patchable for Tandy.
 * 
 * Revision 1.2	91/05/01  04:50:11	root
 * Debug code and d_time/sw_active imbalance fixed.
 * 
 * Revision 1.1	91/04/30  11:02:22	root
 * Shipped with COH 3.1.0
 * 
 */

#include	<sys/coherent.h>
#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/sdioctl.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>
#include	<sys/scsiwork.h>

extern	saddr_t sds;

/*
 * Configurable parameters
 *
 * Adaptec ROM translates at 64 heads, except the Tandy version, which
 * uses 16 heads.  Kernel variable SD_HDS is patchable for this reason.
 */
#ifdef TANDY
int SD_HDS = 16;
#else
int SD_HDS = 64;
#endif
int SD_SPT = 32;

#define NDRIVE	(8 * 4)			/* 8 SCSI ids and 4 LUNs */
#define	SDMAJOR	13			/* Major Device Number */
#define	SDDMA	5			/* Used for first party DMA */

/*
 * user configurable paramters
 */
int	SDIRQ	= 11;			/* Interrupt */
int	SDBASE	= 0x0330;		/* Port base */

/*
 *					LUN --------++
 * device macros			Special-+   ||
 * minor device bits are of the form:		76543210
 *						 |||  ||
 *					SCSI ID--+++  ||
 *					Partition ----++
 * Partition mapping:
 *
 * Description	   Special Bit	   Partition #		Device		Type
 * -----------	   -----------	   -----------		------		----
 * partition a		0		00		/dev/sd??a	disk
 * partition b		0		01		/dev/sd??b	disk
 * partition c		0		10		/dev/sd??c	disk
 * partition d		0		11		/dev/sd??d	disk
 * partition table	1		00		/dev/sd??x	disk
 * no rewind tape	1		01		/dev/sd??n	tape
 * UNALLOCATED		1		10		  ---		????
 * rewind tape device	1		11		/dev/sd??	tape
 */
#define	DRIVENO(minor)	(((minor) >> 2) & 0x1F)	/* SCSI ID + LUN */
#define	SCSIID(minor)	(((minor) >> 4) & 0x7)	/* SCSI ID */
#define	LUN(minor)	(((minor) >> 2) & 0x3)	/* Logical Unit Number */
#define	PARTITION(minor) ((minor) & 0x3)	/* Partition */
#define	sdmkdev(maj, s, drv)	makedev((maj), ((s)|((drv)<<2)))

/*
 * Driver configuration.
 */
void	sdload();
void	sdunload();
void	sdopen();
void	sdclose();
void	sdread();
void	sdwrite();
int	sdioctl();
void	sdblock();
int	sdwatch();
int	nulldev();
int	nonedev();

CON	sdcon	= {
	DFBLK|DFCHR,			/* Flags */
	SDMAJOR,			/* Major index */
	sdopen,				/* Open */
	sdclose,			/* Close */
	sdblock,			/* Block */
	sdread,				/* Read */
	sdwrite,			/* Write */
	sdioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	sdwatch,			/* Timeout */
	sdload,				/* Load */
	sdunload			/* Unload */
};

/*
 *	host adapter routines
 */
int	aha_load();		/* initialize host adapter, DMA */
void	aha_unload();		/* shutdown the host adapter */
int	aha_start();		/* see if there's work */
int	aha_command();

/*
 * Partition Parameters - copied from disk.
 *
 *	There are NPARTN positions for the user partitions in array PPARM,
 *	plus 1 additional position to span the entire drive.
 *	Array pparmp[] contains a pointer to a kalloc()'ed PPARM
 *	entry if the drive actually exists, is a disk drive and if someone
 *	has attmpted to read a partition table from the drive.
 */
typedef	struct	fdisk_s	PPARM[NPARTN + 1];	/* 4 partitions + whole drive */
static	PPARM *pparmp[NDRIVE];			/* one per possible drive */
#define	WHOLE_DRIVE	NPARTN			/* index for whole drive */
#define	PNULL	((PPARM *)0)

/*
 * Per disk controller data.
 * Only one host adapter; no more, no less.
 */
static
scsi_work_t	sd;

static	BUF	dbuf;			/* For raw I/O */
static	int	sw_active;

/**
 *
 * void
 * sdload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void
sdload()
{
	/*
	 * Initialize Drive Controller.
	 */
	sw_active = 0;
	if (aha_load(SDDMA, SDIRQ, SDBASE, &sd) < 0) {
		u.u_error = ENXIO;
		return;
	}
/*	aha_device_info(); */		/* enable after this gets fixed */
}

/**
 *
 * void
 * sdunload()	- unload routine.
 */
static void
sdunload()
{
	register int i;

	if (sw_active > 0)
		printf("aha154x: sdunload() athough %d active\n", sw_active);
	aha_unload(SDIRQ);
	for (i = 0; i < NDRIVE; ++i)
		if (pparmp[i] != PNULL)
			kfree(pparmp[i]);	/* free any partition tables */
}

/*
 * int
 * sdgetpartitions(dev)	- load partition table for specified drive
 *
 *			- return 1 on success and 0 on failure
 */
int sdgetpartitions(dev)
dev_t	dev;
{
	register int 	i;
	scsi_cmd_t	sc;
	unsigned char	*buffer;
	struct fdisk_s	*fdp;
	int	d = DRIVENO(minor(dev));

	pparmp[d] = kalloc(sizeof *pparmp[0]);
	fdp = (struct fdisk_s *) pparmp[d];	/* point to first entry */
	buffer = kalloc(36+1);
	if (buffer == NULL || pparmp[d] == PNULL) {
		printf("aha154x: out of kernel memory\n");
		u.u_error = EKSPACE;
		return 0;
	}
	kclear(pparmp[d], sizeof *pparmp[0]);
	sc.unit = d;
	sc.block = 0L;
	sc.blklen = 0;

	sc.buffer = VTOP2(buffer, sds);
	++drvl[SDMAJOR].d_time;	
#if	0
	sc.cmd = ScmdINQUIRY;
	sc.buflen = 36;
	aha_command(&sc);
	aha_command(&sc);
	buffer[36] = 0;
	printf("SCSI Disk %s", &buffer[8]);
#endif
	sc.cmd = ScmdREADCAPACITY;
	sc.buflen = 8;

	for(i = 0; i < sc.buflen; ++i)
		buffer[i] = 0;
	aha_command(&sc);
	aha_command(&sc);
#if	VERBOSE
	printf("buffer =");
	for(i = 0; i < sc.buflen; ++i)
		printf(" %x", buffer[i]);
	printf("\n");
#endif
	sc.block = (buffer[0]<<8) | buffer[1];
	sc.block <<= 16;
	sc.block |= (buffer[2]<<8) | buffer[3];

	sc.blklen = (buffer[6]<<8) | buffer[7];
#if	VERBOSE
	printf("SCSI %D. blocks of size %d\n", sc.block, sc.blklen);
#endif
	kfree(buffer);
	fdp[WHOLE_DRIVE].p_size = sc.block;
	--drvl[SDMAJOR].d_time;	
	return fdisk(sdmkdev(major(dev), SDEV, d), pparmp[d]);
}

/**
 *
 * void
 * sdopen(dev, mode)
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void
sdopen(dev, mode)
register dev_t	dev;
{
	register int p;			/* partition */
	register int d;			/* drive (SCSI ID + LUN) */
	struct fdisk_s	*fdp;		/* one partition entry */

	if (minor(dev) & SDEV) {
		if (PARTITION(minor(dev)) != 0) {	/* tape device ? */
			u.u_error = ENXIO;		/* not yet! */
devmsg(dev, "No tape yet");
		} else {
			++drvl[SDMAJOR].d_time;	
			++sw_active;
		}
		return;
	}

	d = DRIVENO(minor(dev));
	p = PARTITION(minor(dev));

	/*
	 * If partition not defined read partition characteristics.
	 */
	if (pparmp[d] == PNULL)   /* no entry yet for this drive ? */
		if (!sdgetpartitions(dev)) {
			u.u_error = ENXIO;
			return;
		}
	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	fdp = (struct fdisk_s *) pparmp[d];
	if ((fdp[p].p_base+fdp[p].p_size) > fdp[WHOLE_DRIVE].p_size) {
		u.u_error = EBADFMT;
	} else if (fdp[p].p_size == 0) {
		u.u_error = ENODEV;
	} else {
		++drvl[SDMAJOR].d_time;	
		++sw_active;
	}
}

void sdclose(dev)
{
	--drvl[SDMAJOR].d_time;	
	--sw_active;	
}

/**
 *
 * void
 * sdread(dev, iop)	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
sdread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq(&dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC);
}

/**
 *
 * void
 * sdwrite(dev, iop)	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
sdwrite(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq(&dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC);
}

/**
 *
 * int
 * sdioctl(dev, cmd, arg)
 * dev_t dev;
 * int cmd;
 * char * vec;
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static int
sdioctl(dev, cmd, vec)
register dev_t	dev;
int cmd;
char * vec;
{
	int d;
	hdparm_t hdparm;
	struct fdisk_s	*fdp;
	int do_getpt = 0;	/* 1 if need to call sdgetpartitions() */

	d = DRIVENO(minor(dev));

	/*
	 * Identify input/output request.
	 */
	switch (cmd) {

	case HDGETA:
		/*
		 * If haven't loaded partition table yet for this drive,
		 * try to do it now.  Note sdgetpartitions() will fail
		 * if there is a new drive (e.g. no signature).  But all
		 * we need is allocation of pparmp[d] and capacity read
		 * properly from the drive.
		 */
		if (pparmp[d] == PNULL) {
			do_getpt = 1;	/* REALLY just want Read Capacity */
			sdgetpartitions(dev);
			if (pparmp[d] == NULL) {
				u.u_error = ENXIO;
				return -1;
			}
		}
		fdp = (struct fdisk_s *) pparmp[d];
		*(short *)&hdparm.landc[0] =
		*(short *)&hdparm.ncyl[0] = fdp[WHOLE_DRIVE].p_size
						/ (SD_HDS * SD_SPT);
		hdparm.nhead = SD_HDS;
		hdparm.nspt = SD_SPT;
		kucopy(&hdparm, vec, sizeof hdparm);
		/*
		 * I know it's ugly.  But it gets around startup Catch-22.
		 *
		 * The fdisk command needs HDGETA.  HDGETA invokes
		 * sdgetpartitions(), but we want to call it again
		 * after the partition table has been created by the fdisk
		 * command.
		 */
		if (do_getpt) {
			kfree(pparmp[d]);
			pparmp[d] = PNULL;	/* force re-read of p. table */
		}
		return 0;
	case HDSETA:
		/*
		 * Set hard disk attributes.
		 */
		fdp = (struct fdisk_s *) pparmp[d];
		ukcopy(vec, &hdparm, sizeof hdparm);
		SD_HDS = hdparm.nhead;
		SD_SPT = hdparm.nspt;
		fdp[WHOLE_DRIVE].p_size =
			(long)(*(short *)&hdparm.ncyl[0])
			* (long)SD_HDS * (long)SD_SPT;

		return 0;
	case SCSI_HA_CMD:
		return aha_ioctl(cmd, vec);
	case SCSI_CMD:
		return 0;
	case SCSI_CMD_IN:
		return 0;
	case SCSI_CMD_OUT:
		return 0;

	default:
		u.u_error = EINVAL;
		return -1;
	}
}

/**
 *
 * void
 * sdblock(bp)	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void
sdblock(bp)
register BUF	*bp;
{
	register scsi_work_t *sw;
	register int s;
	struct	fdisk_s	*fdp;

	int p = PARTITION(minor(bp->b_dev));
	int drv = DRIVENO(minor(bp->b_dev));

	if (minor(bp->b_dev) & SDEV)
		p = WHOLE_DRIVE;
	bp->b_resid = bp->b_count;
	
	fdp = (struct fdisk_s *) pparmp[drv];

	/*
	 * Range check disk region.
	 */
	if (pparmp[drv] == PNULL) {
		if (p == WHOLE_DRIVE) {
			if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
				bp->b_flag |= BFERR;
				bdone(bp);
				return;
			}
		} else {
			printf("aha154x: no partition table\n");
			bp->b_flag |= BFERR;
			bdone(bp);
			return;
		}
	} else if ((bp->b_bno + (bp->b_count/BSIZE)) > fdp[p].p_size) {
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}

	bp->b_actf = NULL;
	sw = (scsi_work_t *)kalloc(sizeof(*sw));
	if (sw == (scsi_work_t *)0) {
		printf("aha154x: out of kernel memory\n");
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}
	sw->sw_bp = bp;
	sw->sw_drv = drv;
	sw->sw_type = 0;
	if (p != WHOLE_DRIVE)
		sw->sw_bno   = fdp[p].p_base + bp->b_bno;
	else
		sw->sw_bno   = bp->b_bno;
	sw->sw_retry = 1;

#if	VERBOSE
	printf("sdblock: drv %x bno %x:%x  bp=%x, flag = %o\n",
		drv, (long)sw->sw_bno, bp, bp->b_flag);
#endif

	s = sphi();
	if (sd.sw_actf == NULL)
		sd.sw_actf = sw;
	else
		sd.sw_actl->sw_actf = sw;
	sd.sw_actl = sw;
	spl(s);

	aha_start();
}

sdwatch()
{
	register i;

	if (i = aha_start())
#if	VERBOSE
		printf("sdwatch: started %d actions\n", i);
#else
		;
#endif
	if (i = aha_completed())
#if	VERBOSE
		printf("sdwatch: completed %d actions\n", i);
#else
		;
#endif
}
0707070064030150151004440000030000030000011777770507310641600004700000025272/newbits/kernel/USRSRC/i8086/drv/sem.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Semaphores
 *
 *	This module provides System V compatible semaphore operations.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:11:37	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:22	src
 * Initial revision
 * 
 * 85/08/06	Allan Cornish
 * Sem.c split into configuration (semcon.c) and implementation (sem.c).
 * Semload() renamed to seminit().
 *
 * 85/07/22	Allan Cornish
 * Semctl, semget, semop now return immediately if u.u_error is set.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Eliminated semlock() and semunlock() functions.
 * Replaced semaccess() by calls to ipcaccess(), increasing shared ipc code.
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <sem.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif

/*
 *	Semaphore Information
 */

#define	NSEMVAL	32767

static
struct semid_ds *semids = 0;

unsigned NSEMID = 16;
unsigned NSEM   = 16;
		    
/*
 * Semaphore Initialization.
 *
 *	Initialize semaphore ids.
 */

seminit()
{
	register struct semid_ds *semidp;

	if ( semids = kalloc( NSEMID * sizeof(struct semid_ds) ) ) {

		for ( semidp = &semids[NSEMID]; --semidp >= semids; )
			semidp->sem_perm.mode = 0;
	}
	else {
		printf("could not allocate %u semaphore ids\n", NSEMID);
		NSEMID = 0;
	}
}

/*
 * Semctl - Semaphore Control Operations.
 */

usemctl( semid, semnum, cmd, arg )

unsigned semid;
unsigned semnum;
int cmd;
union semun {
	int val;
	struct semid_ds *buf;
	unsigned short *array;
} arg;

{
	register struct semid_ds *semidp;
	register struct sem *semp;
	int nsems, val;

	if ( u.u_error )
		return -1;

	if ( semid >= NSEMID ) {
		u.u_error = EINVAL;
		return -1;
	}

	semidp = &semids[semid];

	if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ((ipcaccess( &semidp->sem_perm ) & SEM_R) == 0) { /* can't read */
		u.u_error = EACCES;
		return -1;
	}

	if ( semnum >= semidp->sem_nsems ) {
		u.u_error = EFBIG;
		return -1;
	}

	semp = &semidp->sem_base[semnum];

	switch ( cmd ) {

	case GETVAL:		/* Return value of semval */
		return semp->semval;

	case SETVAL:						/* Set semval */
		if ((ipcaccess( &semidp->sem_perm ) & SEM_A) == 0) {
			u.u_error = EACCES;	/* can't alter */
			return -1;
		}

		if ( arg.val < 0 ) {			/* illegal value */
			u.u_error = ERANGE;
			return -1;
		}

		if ( semp->semval = arg.val ) {

			if ( semp->semncnt )
				wakeup( &semp->semncnt );
		}
		else {
			if ( semp->semzcnt )
				wakeup( &semp->semzcnt );
		}

		return 0;

	case GETPID:		/* Return value of sempid */
		return semp->sempid;

	case GETNCNT:		/* Return value of semncnt */
		return semp->semncnt;

	case GETZCNT:		/* Return value of semzcnt */
		return semp->semzcnt;

	case GETALL:		/* Return semvals array */
		nsems = semidp->sem_nsems;
		semp  = semidp->sem_base;

		while ( --nsems >= 0 ) {

			putuwd( (arg.array)++, (semp++)->semval );

			if ( u.u_error )
				return -1;
		}
		return 0;

	case SETALL:		/* Set semvals array */
		if ( (ipcaccess( &semidp->sem_perm ) & SEM_A) == 0 ) {
			u.u_error = EACCES;
			return -1;
		}
		nsems = semidp->sem_nsems;
		semp  = semidp->sem_base;

		while ( --nsems >= 0 ) {

			if ( (val = getuwd( arg.array )) < 0 ) {

				if ( u.u_error == 0 )
					u.u_error = ERANGE;
			}
			else
				semp->semval = val;
			arg.array++;
			semp++;
		}
		if ( u.u_error )
			return -1;
		return 0;

	case IPC_STAT:
		kucopy( semidp, arg.buf, sizeof(struct semid_ds) );
		return 0;

	case IPC_SET:
		if ( (u.u_uid != 0) && (u.u_uid != semidp->sem_perm.uid) ) {
			u.u_error = EPERM;
			return -1;
		}
		semidp->sem_perm.uid   = getuwd( &((arg.buf)->sem_perm.uid ) );
		semidp->sem_perm.gid   = getuwd( &((arg.buf)->sem_perm.gid ) );
		semidp->sem_perm.mode  =
			(getuwd(&((arg.buf)->sem_perm.mode))&0777) | IPC_ALLOC;
		return 0;

	case IPC_RMID:
		if ( (u.u_uid != 0) && (u.u_uid != semidp->sem_perm.uid) ) {
			u.u_error = EPERM;
			return -1;
		}
		semidp->sem_perm.seq++;
		semp = &semidp->sem_base[ semidp->sem_nsems ];

		while ( --semp >= semidp->sem_base ) {

			if ( semp->semncnt )
				wakeup( &semp->semncnt );
			if ( semp->semzcnt )
				wakeup( &semp->semzcnt );
		}

		kfree( semidp->sem_base );
		semidp->sem_perm.mode = 0;
		return 0;

	default:
		u.u_error = EINVAL;
		return -1;
	}
}

/*
 * Semget - Get set of semaphores
 */

usemget( skey, nsems, semflg )

key_t skey;
unsigned nsems;
int semflg;

{
	register struct semid_ds *semidp;
	register struct sem *semp;
	struct semid_ds *freeidp = 0;

	if ( u.u_error )
		return -1;

	if ( nsems >= NSEM ) {
		u.u_error = EINVAL;
		return -1;
	}

	for ( semidp = &semids[NSEMID]; --semidp >= semids; ) {

		if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {

			if ((freeidp == 0) ||
			    (freeidp->sem_ctime > semidp->sem_ctime))
				freeidp = semidp;
			continue;
		}

#ifdef	IPC_PRIVATE
		if (skey == IPC_PRIVATE)
			continue;
#endif

		if (skey == semidp->sem_perm.key) {		/* found! */

			if ( (semflg & IPC_CREAT) && (semflg & IPC_EXCL) ) {
				u.u_error = EEXIST;
				return -1;
			}

			if ((semidp->sem_perm.mode & semflg) != (semflg&0777)) {
				u.u_error = EACCES;
				return -1;
			}

			if ( semidp->sem_nsems < nsems ) {
				u.u_error = EINVAL;
				return -1;
			}

			return semidp - semids;
		}
	}

	if ( !(semflg & IPC_CREAT) ) {
		u.u_error = ENOENT;
		return -1;
	}

	if ( freeidp == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	semidp = freeidp;
	semidp->sem_base = kalloc( nsems * sizeof(struct sem) );

	if (semidp->sem_base == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	semidp->sem_nsems = nsems;
	semidp->sem_otime = 0;
	semidp->sem_ctime = timer.t_time;

	for ( semp = &semidp->sem_base[nsems]; --semp >= semidp->sem_base; )
		semp->semval = semp->sempid = semp->semncnt = semp->semzcnt = 0;

	semidp->sem_perm.cuid = semidp->sem_perm.uid = u.u_uid;
	semidp->sem_perm.cgid = semidp->sem_perm.gid = u.u_gid;
	semidp->sem_perm.mode = (semflg & 0777) | IPC_ALLOC;
	semidp->sem_perm.key  = skey;

	return semidp - semids;
}

/*
 * Semop - Semaphore Operations.
 */

usemop( semid, sops, nsops )

unsigned semid;
struct sembuf *sops;
unsigned nsops;

{
	register struct semid_ds *semidp;
	register struct sem *semp;
	struct sembuf *sp;
	unsigned n, semnum, semflg;
	int semop, oval;

	if ( u.u_error )
		return -1;

	if ( semid >= NSEMID ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ( nsops >= NSEM ) {
		u.u_error = E2BIG;
		return -1;
	}

	semidp = &semids[semid];

	if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ( (ipcaccess( &semidp->sem_perm ) & SEM_A) == 0 ) {
		u.u_error = EACCES;
		return -1;
	}

	sp = sops;
	n  = nsops;

	while ( n > 0 ) {				/* do semaphore ops  */

		semnum = getuwd( & (sp->sem_num) );
		semop  = getuwd( & (sp->sem_op ) );
		semflg = getuwd( & (sp->sem_flg) );

		if ( (u.u_error != 0) || (semnum >= semidp->sem_nsems) ) {

			while ( --sp >= sops ) {	/* undo prev semops  */

				semnum = getuwd( &sp->sem_num );
				semop  = getuwd( &sp->sem_op  );
				semp   = &semidp->sem_base[ semnum ];
				semundo( semp, semop );
			}

			if ( u.u_error == 0 )
				u.u_error = EFBIG;
			return -1;
		}

		semp = &semidp->sem_base[semnum];

		if ( (oval = semdo( semp, semop )) < 0 ) { /* can't do semop */

			while ( --sp >= sops ) {	/* undo prev semops  */

				unsigned unnum = getuwd( &sp->sem_num );
				int	 unop  = getuwd( &sp->sem_op  );
				semundo( &semidp->sem_base[ unnum ], unop);
			}

			if ( u.u_error )
				return -1;

			if ( semflg & IPC_NOWAIT ) {
				u.u_error = EAGAIN;
				return -1;
			}

			if ( semop < 0 ) {	/* wait for non-zero */

				if (semwait( semidp, &semp->semncnt ) < 0 )
					return -1;
			}
			else {			/* wait for zero */

				if ( semwait( semidp, &semp->semzcnt ) < 0 )
					return -1;
			}

			sp = sops;	/* retry set of semaphore operations */
			n = nsops;
			continue;
		}

		++sp;
		--n;
	}

	for (sp=sops,n=nsops; n > 0; --n,++sp) {/* save pid in each semaphore */

		semnum = getuwd( &sp->sem_num );
		semidp->sem_base[ semnum ].sempid = SELF->p_pid;
	}

	semidp->sem_otime = timer.t_time;	/* ajust operation time */
	return oval;				/* return last prev semval */
}

/*
 * Do a Semaphore Operation.
 *
 *	Input:	semp  = pointer to semaphore
 *		semop = semaphore operation
 *
 *	Action:	If semop < 0 and semval > semop then add semop to semval.
 *		If semop > 0 then add semop to semval.
 *
 *	Return:	Previous semval.
 */

static
semdo( semp, semop )

register struct sem * semp;
register int semop;

{
	int ret;

	ret = semp->semval;

	if ( semop < 0 ) {			/* want to decrement semval */

		semop = -semop;

		if ( semp->semval < semop )	/* can't decrement semval */
			return -1;

		semp->semval -= semop;

		if ( (semp->semval == 0)  && (semp->semzcnt != 0) )
			wakeup( &semp->semzcnt );
	}
	else if ( semop > 0 ) {			/* want to increment semval */

		if ( (semp->semval + semop) > NSEMVAL) {
		
			u.u_error = ERANGE;
			return -1;
		}

		semp->semval += semop;

		if ( semp->semncnt )
			wakeup( &semp->semncnt );
	}
	else /* if ( semop == 0 ) */ {

		if ( semp->semval != 0 )
			return -1;
	}
	return ret;
}

/*
 * Undo a Semaphore Operation.
 */

static
semundo( semp, semop )

register struct sem * semp;
register int semop;

{
	if ( semp->semval -= semop ) {

		if ( semp->semncnt )
			wakeup( &semp->semncnt );
	}
	else {
		if ( semp->semzcnt )
			wakeup( &semp->semzcnt );
	}
}

/*
 * Wait on Semaphore Event
 *
 *	Input:	semidp = pointer to semaphore id structure.
 *		ep     = pointer to semncnt or semzcnt event to wait for.
 *
 *	Action:	Sleep on a semaphore event.
 *		If semaphore id has been deleted, error return.
 *		If signal has been received, error return.
 *
 *	Output:	 0 = Status ok.
 *		-1 = Error occurred, errno is set.
 */

static
semwait( semidp, ep )

register struct semid_ds * semidp;
register unsigned short *ep;
{
	unsigned seqn;

	seqn = semidp->sem_perm.seq;
	++(*ep);
	sleep( ep, CVTTOUT, IVTTOUT, SVTTOUT );

	if (semidp->sem_perm.seq != seqn ) {	/* semaphore id gone */
		u.u_error = EIDRM;
		return -1;
	}

	--(*ep);

	if ( SELF->p_ssig && nondsig() ) {	/* signal received */
		u.u_error = EINTR;
		return -1;
	}
	return 0;
}
0707070064030150141004440000030000030000011777770507310642100005200000005210/newbits/kernel/USRSRC/i8086/drv/semcon.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Semaphore Device Driver
 *
 *	This device driver provides System V compatible semaphore operations.
 *	Operations are performed through the semaphore device (/dev/sem).
 *	and are implemented as ioctl calls from semctl, semget, semop
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:11:55	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:26	src
 * Initial revision
 * 
 * 87/03/02	Allan Cornish		/usr/src/sys/i8086/drv/semcon.c
 * Semioctl() now supports long key [was short] on SEMGET operations.
 * This allows compatability with System V.
 *
 * 85/08/06	Allan Cornish
 * Sem.c split into configuration (semcon.c) and implementation (sem.c).
 * Semload() renamed to seminit().
 *
 * 85/07/03	Allan Cornish
 * Eliminated semopen() and semclose() functions.
 *
 * 84/09/30	Allan Cornish
 * Initial Revision.
 */

#include <coherent.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <con.h>
#include <sem.h>

/*
 * Functions.
 */

int seminit();
int semioctl();
int nulldev();
int nonedev();

/*
 * Device Configuration.
 */

CON semcon = {
	DFCHR,			/* Flags			*/
	23,			/* Major Index			*/
	nulldev,		/* Open				*/
	nulldev,		/* Close			*/
	nonedev,		/* Block			*/
	nonedev,		/* Read				*/
	nonedev,		/* Write			*/
	semioctl,		/* Ioctl			*/
	nulldev,		/* Power fail			*/
	nulldev,		/* Timeout			*/
	seminit,		/* Load				*/
	nulldev			/* Unload			*/
};

/*
 * Semaphore Device Ioctl.
 */

static
semioctl( dev, com, vec )

dev_t dev;
int com;
register int *vec;

{
	switch ( com ) {

	case SEMCTL:
		putuwd( vec+0,
			usemctl(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ) ));
		return;

	case SEMGET:
		putuwd( vec+0,
			usemget(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ) ));
		return;

	case SEMOP:
		putuwd( vec+0,
			usemop(	getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ) ));
		return;

	default:
		u.u_error = EINVAL;
		return;
	}
}
0707070064030150131004440000030000030000011777770507310642200004700000011362/newbits/kernel/USRSRC/i8086/drv/shm.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985, 1984
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Shared Memory Device Driver
 *
 *	This device driver provides System V compatible shared memory operations.
 *	Operations are performed through the shared memory device (/dev/shm).
 *	and are implemented as ioctl calls from shmctl, shmget, shmat, shmdt
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:12:17	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:32	src
 * Initial revision
 * 
 * 85/10/16	Allan Cornish
 * Driver split into shmcon.c, shm.c [driver implementation, System V shm].
 *
 * 85/07/22	Allan Cornish
 * Shmget, shmctl now return immediately if u.u_error is set.
 *
 * 85/07/19	Allan Cornish
 * Separation of io_seek into shmid and off improved through type casting.
 * Errno set to EFAULT if fucopy() or ufcopy() report no bytes transferred.
 * This would occur if an user address fault occurred.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Replaced shmaccess() by calls to ipcaccess(), increasing shared ipc code.
 * Eliminated shmlock() and shmunlock(), as shared memory use is synchronous.
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <seg.h>
#include <shm.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif


extern	unsigned NSHMID;
extern	struct shmid_ds *shmids;
extern	struct seg **shmsegs;

/*
 * Shmctl - Shared Memory Control Operations.
 */

ushmctl( shmid, cmd, buf )

unsigned shmid;
int cmd;
struct shmid_ds *buf;

{
	register struct shmid_ds *idp;
	int ret = 0;

	if ( u.u_error )
		return -1;

	if ( shmid >= NSHMID ) {
		u.u_error = EINVAL;
		return -1;
	}

	idp = &shmids[shmid];

	if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EINVAL;
		return -1;
	}

	switch ( cmd ) {

	case IPC_STAT:
		if ( ( ipcaccess( &idp->shm_perm ) & SHM_R ) == 0 ) {
			u.u_error = EACCES;
			return -1;
		}
		kucopy( idp, buf, sizeof(struct shmid_ds) );
		ret = 0;
		break;

	case IPC_SET:
		if ( (u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid) ) {
			u.u_error = EPERM;
			ret = -1;
			break;
		}
		idp->shm_perm.uid   = getuwd( &(buf->shm_perm.uid ) );
		idp->shm_perm.gid   = getuwd( &(buf->shm_perm.gid ) );
		idp->shm_perm.mode &= ~0777;
		idp->shm_perm.mode |= getuwd(&(buf->shm_perm.mode)) & 0777;
		ret = 0;
		break;

	case IPC_RMID:
		if ( (u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid) ) {
			u.u_error = EPERM;
			ret = -1;
			break;
		}
		idp->shm_perm.seq++;
		sfree(shmsegs[shmid]);
		idp->shm_perm.mode = 0;
		ret = 0;
		break;

	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * Shmget - Get Shared Memory Segment
 */

ushmget( skey, size, shmflg )

key_t skey;
unsigned size;
int shmflg;

{
	register struct shmid_ds *idp;
	struct shmid_ds *freeidp = 0;

	if ( u.u_error )
		return -1;

	for ( idp = &shmids[NSHMID]; --idp >= shmids; ) {

		if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {

			if ((freeidp == 0) ||
			    (freeidp->shm_ctime > idp->shm_ctime))
				freeidp = idp;
			continue;
		}

#ifdef	IPC_PRIVATE
		if (skey == IPC_PRIVATE)
			continue;
#endif

		if (skey == idp->shm_perm.key) {		/* found! */

			if ( (shmflg & IPC_CREAT) && (shmflg & IPC_EXCL) ) {

				u.u_error = EEXIST;
				return -1;
			}

			if ((idp->shm_perm.mode & shmflg) != (shmflg&0777)) {

				u.u_error = EACCES;
				return -1;
			}

			if ( idp->shm_segsz < size ) {

				u.u_error = EINVAL;
				return -1;
			}

			return idp - shmids;
		}
	}

	if ( !(shmflg & IPC_CREAT) ) {
		u.u_error = ENOENT;
		return -1;
	}

	if ( freeidp == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	idp = freeidp;

	if ((shmsegs[idp - shmids] = salloc((size_t) size, SFNSWP)) == NULL){
		u.u_error = ENOSPC;
		return -1;
	}

	idp->shm_segsz = size;
	idp->shm_atime = 0;
	idp->shm_dtime = 0;
	idp->shm_ctime = timer.t_time;
	idp->shm_cpid  = SELF->p_pid;
	idp->shm_perm.cuid = idp->shm_perm.uid = u.u_uid;
	idp->shm_perm.cgid = idp->shm_perm.gid = u.u_gid;
	idp->shm_perm.mode = (shmflg & 0777) | IPC_ALLOC;
	idp->shm_perm.key  = skey;

#ifdef	IPC_PRIVATE
	if ( skey == IPC_PRIVATE )
		idp->shm_perm.mode |= SHM_DEST;
#endif

	return idp - shmids;
}
0707070064030150121004440000030000030000011777770507310642300005200000012664/newbits/kernel/USRSRC/i8086/drv/shmcon.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Shared Memory Device Driver
 *
 *	This device driver provides System V compatible shared memory operations.
 *	Operations are performed through the shared memory device (/dev/shm).
 *	and are implemented as ioctl calls from shmctl, shmget, shmat, shmdt
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:12:40	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:36	src
 * Initial revision
 * 
 * 87/03/02	Allan Cornish		/usr/src/sys/i8086/drv/shmcon.c
 * Shmioctl() now supports long key [was short] on SHMGET operations.
 * This allows compatability with System V.
 *
 * 85/10/16	Allan Cornish
 * Driver split into shmcon.c, shm.c [driver implementation, system V shm].
 *
 * 85/07/22	Allan Cornish
 * Shmget, shmctl now return immediately if u.u_error is set.
 *
 * 85/07/19	Allan Cornish
 * Separation of io_seek into shmid and off improved through type casting.
 * Errno set to EFAULT if fucopy() or ufcopy() report no bytes transferred.
 * This would occur if an user address fault occurred.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Replaced shmaccess() by calls to ipcaccess(), increasing shared ipc code.
 * Eliminated shmlock() and shmunlock(), as shared memory use is synchronous.
 *
 * 84/09/30	Allan Cornish
 * Initial Revision.
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <seg.h>
#include <shm.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif

/*
 * Functions.
 */

int shmload();
int shmread();
int shmwrite();
int shmioctl();
int nulldev();
int nonedev();

/*
 * Device Configuration.
 */

CON shmcon = {
	DFCHR,			/* Flags			*/
	24,			/* Major Index			*/
	nulldev,		/* Open				*/
	nulldev,		/* Close			*/
	nonedev,		/* Block			*/
	shmread,		/* Read				*/
	shmwrite,		/* Write			*/
	shmioctl,		/* Ioctl			*/
	nulldev,		/* Power fail			*/
	nulldev,		/* Timeout			*/
	shmload,		/* Load				*/
	nulldev			/* Unload			*/
};

unsigned NSHMID = 16;
struct shmid_ds *shmids;
struct seg **shmsegs;

/*
 * Shared Memory Device Load.
 */

static
shmload()
{
	register struct shmid_ds * idp;
	register unsigned wanted;
	
	if ( NSHMID == 0 )
		return 0;

	wanted = NSHMID * (sizeof(struct shmid_ds) + sizeof(struct seg *));

	if ( (shmids = kalloc( wanted )) == 0 ) {

		printf("couldn't kalloc %u shared memory ids\n", NSHMID );
		NSHMID = 0;
		return 0;
	}
	shmsegs = (struct seg *) &shmids[ NSHMID ];

	for ( idp = &shmids[NSHMID]; --idp >= shmids; )
		idp->shm_perm.mode = 0;

	return 0;
}

/*
** Shared Memory Read.
*/

static
shmread( dev, iop )

dev_t dev;
register IO *iop;

{
	register struct shmid_ds *idp;
	int shmid;
	unsigned off;
	faddr_t faddr;

	off   = ((unsigned *) &iop->io_seek)[0];
	shmid = ((unsigned *) &iop->io_seek)[1];

	if ( shmid >= NSHMID ) {
		u.u_error = EFAULT;
		return -1;
	}

	idp = &shmids[shmid];

	if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EIDRM;
		return -1;
	}

	if ( (ipcaccess(&idp->shm_perm) & SHM_R) == 0 ) {
		u.u_error = EACCES;
		return -1;
	}

	if ( ((long) off + iop->io_ioc) > idp->shm_segsz ) {
		u.u_error = EFAULT;
		return -1;
	}

	FP_SEL(faddr) = FP_SEL(shmsegs[shmid]->s_faddr);
	FP_OFF(faddr) = off;

	if ( ! fucopy( faddr, iop->io_base, iop->io_ioc ) ) {
		u.u_error = EFAULT;
		return -1;
	}

	iop->io_ioc = 0;
	return 0;
}

/*
** Shared Memory Write.
*/

static
shmwrite( dev, iop )

dev_t dev;
register IO *iop;

{
	register struct shmid_ds *idp;
	int shmid;
	unsigned off;
	faddr_t faddr;

	off   = ((unsigned *) &iop->io_seek)[0];
	shmid = ((unsigned *) &iop->io_seek)[1];

	if ( shmid >= NSHMID ) {
		u.u_error = EFAULT;
		return -1;
	}

	idp = &shmids[shmid];

	if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EIDRM;
		return -1;
	}

	if ( (ipcaccess(&idp->shm_perm) & SHM_W) == 0 ) {
		u.u_error = EFAULT;
		return -1;
	}

	if ( ((long) off + iop->io_ioc) > idp->shm_segsz ) {
		u.u_error = EFAULT;
		return -1;
	}

	FP_SEL(faddr) = FP_SEL(shmsegs[shmid]->s_faddr);
	FP_OFF(faddr) = off;

	if ( ! ufcopy(iop->io_base, faddr, iop->io_ioc ) ) {
		u.u_error = EFAULT;
		return -1;
	}

	iop->io_ioc = 0;
	return 0;
}

/*
 * Shared Memory Device Ioctl.
 *
 *	Input:	dev = shared memory device (/dev/shm).
 *		com = command to perform (SHMCTL, SHMGET,SHMAT).
 *		vec = pointer to return value, followed by parameters.
 *
 *	Action:	Initiate command.
 *		Save commands return value in *vec.
 */

static
shmioctl( dev, com, vec )

dev_t dev;
int com;
int *vec;

{
	switch ( com ) {

	case SHMCTL:
		putuwd( vec+0,
			ushmctl( getuwd( vec+1 ),
				 getuwd( vec+2 ),
				 getuwd( vec+3 ) ));
		break;

	case SHMGET:
		putuwd( vec+0,
			ushmget( getuwd( vec+1 ),
				 getuwd( vec+2 ),
				 getuwd( vec+3 ),
				 getuwd( vec+4 ) ));
		break;

	default:
		u.u_error = EINVAL;
		break;
	}
}
0707070064030150111006440000030000030000011777770507310642400004600000142370/newbits/kernel/USRSRC/i8086/drv/ss.c/*
 * Device driver for Seagate ST01/ST02 scsi host adapters.
 *
 * To do:
 *	nonzero LUN's
 *	start new command during disconnect
 *	rewrite as single state machine, instead of 7 of them
 *	separate SCSI layer from host-dependent stuff
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 3.3  91/06/21  10:46:27  hal
 * Now talks to TMC-881 + ST4350N.
 * 
 * Revision 3.2  91/06/20  17:10:32  hal
 * First version for TMC-881.
 * 
 * Revision 3.1  91/06/17  07:43:25  hal
 * Add TMC-840 code.
 * 
 * Revision 1.1  91/06/17  07:42:27  hal
 * Add TMC-840 code.
 * 
 * 
 */

/*
 * Debug levels.
 * DEBUG = 0	No debug output.
 * DEBUG = 1	Debug output on error only.
 * DEBUG = 2	Debug output on error and at other selected places.
 * DEBUG = 3	Print state machine trace.
 * DEBUG = 4	Print info xfer phases and msg_in values.
 */
#if (DEBUG >= 1)
static int s_id;
#define PR1(str)		printf("%s%d ", str, s_id)
#else
#define PR1(str)
#endif
#if (DEBUG >= 2)
#define PR2(str)		printf(str)
#else
#define PR2(str)
#endif
#if (DEBUG >= 3)
#define PR3(str)		printf("%s%d ", str, s_id)
#else
#define PR3(str)
#endif
#if (DEBUG >= 4)
#define PR4(str)		printf("%s%d ", str, s_id)
#else
#define PR4(str)
#endif

/*
 * Includes.
 */
#include	<sys/coherent.h>
#include	<sys/io.h>
#include	<sys/sched.h>
#include	<sys/uproc.h>
#include	<sys/proc.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/devices.h>		/* SCSI_MAJOR */
#include	<errno.h>
#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<sys/scsiwork.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

#define SS_RAM		0x1800	/* Offset of parameter RAM */

				/* Future Domain */
#define FD_CSR		0x1C00	/* Offset of control/status register */
#define FD_DAT		0x1E00	/* Offset of data port */

				/* Seagate */
#define SS_CSR		0x1A00	/* Offset of control/status register */
#define SS_DAT		0x1C00	/* Offset of data port */

#define SS_RAM_LEN	128	/* ST0x has 128 bytes of RAM */
#define SS_DAT_LEN	0x400	/* Byte range mapped to data port */
#define SS_SEL_LEN	0x2000	/* Total size of memory-mapped area */

#define WC_ENABLE_SCSI	0x80	/* Write Control (WC) register bits */
#define WC_ENABLE_IRPT	0x40
#define WC_ENABLE_PRTY	0x20
#define WC_ARBITRATE	0x10
#define WC_ATTENTION	0x08
#define WC_BUSY  	0x04
#define WC_SELECT  	0x02
#define WC_SCSI_RESET  	0x01

#define RS_ARBIT_COMPL	0x80	/* Read STATUS (RS) register bits */
#define RS_PRTY_ERROR	0x40
#define RS_SELECT	0x20
#define RS_REQUEST	0x10
#define RS_CTRL_DATA	0x08
#define RS_I_O  	0x04
#define RS_MESSAGE  	0x02
#define RS_BUSY  	0x01

#define DEV_SCSI_ID(dev)	((dev >> 4) & 0x0007)
#define DEV_LUN(dev)		((dev >> 2) & 0x0003)
#define DEV_DRIVE(dev)		((dev >> 2) & 0x001F)
#define DEV_PARTN(dev)		(dev & 0x0003)
#define DEV_SPECIAL(dev)	(dev & 0x0080)

#define HIPRI_RETRIES	5000	/* # of times to retry while hogging CPU */
#define LOPRI_RETRIES	5	/* # of retries with sleep between tries */
#define WHOLE_DRIVE	NPARTN
#define RESET_TICKS	50	/* # of clock ticks for reset settling */
#define LOAD_DELAY	30000	/* Loop counter during ssload() only */

#define BUS_FREE	((ffbyte(ss_csr) & (RS_BUSY | RS_SELECT)) == 0)
#define TGT_RSEL	\
	(  (ffbyte(ss_csr) & (RS_SELECT |  RS_I_O   )) \
	&& (ffbyte(ss_dat) & (host_id   | (1<<s_id) )) )

#define DELAY_ARB	10	/* delays units are 10 msec (clock ticks) */
#define DELAY_BDR	30
#define DELAY_BSY	20
#define DELAY_RES	50
#define DELAY_RST	40

#define MAX_AVL_COUNT	100
#define MAX_BDR_COUNT	3
#define MAX_BSY_COUNT	3
#define MAX_TRY_COUNT	10
#define INL_MAX_REQ_POLL	800000L
#define WKG_MAX_REQ_POLL	20000L

typedef unsigned char	uchar;
typedef unsigned int	uint;
typedef unsigned long	ulong;

typedef enum {			/* values for current driver state */
	SST_DEQUEUE =0,
	SST_BUS_DEV_RESET,
	SST_HIPRI_RESET,
	SST_LOPRI_RESET,
	SST_POLL_ARBITN,
	SST_POLL_BEGIN_IO,
	SST_POLL_RESELECT,
	SST_REQ_SENSE,
	SST_RESET_OFF
} SST_TYPE;

typedef enum {			/* values for input to recovery routine */
	RV_A_TIMEOUT,
	RV_P_TIMEOUT,
	RV_R_TIMEOUT,
	RV_BF_TIMEOUT,
	RV_CS_BUSY,
	RV_CS_CHECK
} RV_TYPE;

typedef struct ss {
	ulong	capacity;
	ulong	blocklen;
	ulong	bno;
	int	msg_in;
	int	dr_watch;
	uchar	cmdbuf[G1CMDLEN];
	int	cmdlen;
	int	cmd_bytes_out;
	int	cmdstat;
	BUF	*bp;		/* current I/O request node, or NULL */
	struct	fdisk_s parmp[NPARTN+1];
	SST_TYPE state;
	TIM	tim;		/* for target-specific timers */
	uchar	avl_count;
	uchar	bdr_count;
	uchar	bsy_count;
	uchar	try_count;
	uint	busy:1;		/* 1 if command uses local buffer */
	uint	expired:1;	/* 1 if target's timer has expired */
	uint	ptab_read:1;	/* 1 if partition table has been read */
	uint	waiting:1;	/* 1 if target timer is running */
}	ss_type;

typedef struct {
	uint	ncyl;
	uchar	nhead;
	uchar	nspt;
}	drv_parm_type;

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */

/* functions from bufq.c */
extern int bufq_init();
extern void bufq_rlse();
extern void bufq_wr_tail();
extern BUF * bufq_rd_head();
extern BUF * bufq_rm_head();

/* functions from ssas.s */
extern void	ss_get();
extern int	ss_put();
extern int	nulldev();
extern int	nonedev();
extern unsigned char ffbyte();

static void	ssopen();		/* CON functions */
static void	ssclose();
static void	ssblock();
static void	ssread();
static void	sswrite();
static int	ssioctl();
static void	sswatch();
static void	ssload();
static void	ssunload();

static int	bus_dev_reset();	/* additional support functions */
static int	chk_reconn();
static void	do_connect();
static void	dummy_reconn();
static int	far_info_xfer();
static int	host_ident();
static int	init_call();
static void	init_pointers();
static int	inquiry();
static int	local_info_xfer();
static int	mode_sense();
static void	next_req();
static void	nonpolled();
static int	read_cap();
static void	recover();
static int	req_sense();
static int	rsel_handshake();
static void	ssdelay();
static void	ss_finished();
static void	ss_mach();
static void	set_timeout();
static int	ssinit();
static void	ssintr();
static int	start_arb();
static void	stop_timeout();
static uchar	xpmod();

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
CON	sscon	= {
	DFBLK|DFCHR,			/* Flags */
	SCSI_MAJOR,			/* Major index */
	ssopen,				/* Open */
	ssclose,			/* Close */
	ssblock,			/* Block */
	ssread,				/* Read */
	sswrite,			/* Write */
	ssioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	sswatch,			/* Timeout */
	ssload,				/* Load */
	ssunload,			/* Unload */
	nulldev				/* Poll */
};

	/* Patch these Export Variables to configure the driver. */
/*
 * In the low byte of NSDRIVE, bit n is 1 if SCSI ID n is an installed target.
 * The high byte indicates which type of host adapter:
 *   00 - ST01/ST02
 *   80 - TMC-845/850/860/875/885
 *   40 - TMC-840/841/880/881
 */
uint	NSDRIVE = 0x0000;
uint	SS_INT = 5;		/* ST0[12] use either IRQ3 or IRQ5 */
uint	SS_BASE = 0xCA00;	/* Segment addr of ST0x communication area */

/* ncyl, nhead, nspt */
drv_parm_type drv_parm[MAX_SCSI_ID] = {
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0}
};

static BUF	dbuf;		/* For raw I/O */
static paddr_t	ss_base;	/* physical address of ST0x comm area */
static faddr_t	ss_fp;		/* (far *) to ST0x comm area */

static faddr_t	ss_ram;		/* (far *) to parameter RAM */
static faddr_t	ss_csr;		/* (far *) to control/status */
static faddr_t	ss_dat;		/* (far *) to data port */

static TIM	delay_tim;	/* needed for calls to ssdelay() */
static int	do_sst_op;	/* 1 when state machine iteration continues */
static int	ss_expired;	/* 1 after local timeout */

static uint	max_req_poll;	/* this changes after initialization */

static uchar	host_id;	/* Host is SCSI ID #7 for Seagate, 6 for FD */
static uchar	swap_status_bits;

static ss_type	*ss_tbl;	/* points to block of "ss" structs */
static ss_type  *ss[MAX_SCSI_ID];

/*
 * host_claimed is -1 if host is available, else it's the SCSI id of the
 *	target that claims the host.
 *
 * host is claimed at start of any of the follwoing:
 *	SCSI bus reset
 *	arbitration for block i/o request
 *	reselect
 *
 * host is released at:
 *	end of SCSI bus reset
 *	completion (successful or not) of block i/o request (ss_finished)
 *	disconnect <-- temporarily disabled
 */
static int	host_claimed;

/*
 * ssload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void ssload()
{
	int erf = 0;  /* 1 if error occurs */
	int i;
	int max_id = -1;
	int num_drives = 0;

	/*
	 * Allocate a selector to map into ST0x memory-mapped comm area.
	 */
	ss_base = (paddr_t)((long)(unsigned)SS_BASE << 4);
	ss_fp = ptov(ss_base, (fsize_t)SS_SEL_LEN);

	ss_ram = ss_fp + SS_RAM;

	/*
	 * Primitive test of ST0x RAM.
	 */
	sfword(ss_ram, 0xA55A);
	sfword(ss_ram + 2, 0x3CC3);
	sfword(ss_ram + SS_RAM_LEN - 4, 0xA55A);
	sfword(ss_ram + SS_RAM_LEN - 2, 0x3CC3);
	if (ffword(ss_ram) != 0xA55A		/* fetch a "far" word */
	||  ffword(ss_ram + 2) != 0x3CC3
	||  ffword(ss_ram + SS_RAM_LEN - 4) != 0xA55A
	||  ffword(ss_ram + SS_RAM_LEN - 2) != 0x3CC3) {
		printf("Error - host failed memory test\n");
		erf = 1;
	}

	/*
	 * Set host-dependent constants.
	 */
	switch(NSDRIVE >> 8) {
	case 0x00:	/* ST01/ST02 */
		ss_csr = ss_fp + SS_CSR;
		ss_dat = ss_fp + SS_DAT;
		host_id = 0x80;		/* host is id #7 */
		break;
	case 0x80:	/* TMC-845/850/860/875/885 */
		ss_csr = ss_fp + FD_CSR;
		ss_dat = ss_fp + FD_DAT;
		host_id = 0x40;		/* host is id #6 */
		break;
	case 0x40:	/* TMC-840/841/880/881 */
		ss_csr = ss_fp + SS_CSR;
		ss_dat = ss_fp + SS_DAT;
		host_id = 0x40;		/* host is id #6 */
		swap_status_bits = 1;
		break;
	}
	NSDRIVE &= ~(uint)host_id;

	/*
	 * Allocate drive structs.
	 *
	 * Do a single call to kalloc() then put allocated pieces into
	 * array ss.
	 *
	 * First allocate and clear storage.  Then hook up the pointers.
	 */
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID; i++)
			if ((NSDRIVE >> i) & 1) {
				max_id = i;
				num_drives++;
			}
		if (num_drives == 0) {
			printf("Error - ss has no valid target id's\n");
			erf = 1;
		} else if ((ss_tbl = kalloc(num_drives*sizeof(ss_type)))
		== NULL) {
			printf("Error - ss can't allocate structs\n");
			erf = 1;
		} else
			kclear(ss_tbl, num_drives * sizeof(ss_type));
	}
	if (!erf) {
		ss_type *foo = ss_tbl;

		for (i = 0; i < MAX_SCSI_ID; i++)
			if ((NSDRIVE >> i) & 1)
				ss[i] = foo++;
	}

	/*
	 * Claim IRQ vector.
	 */
	setivec(SS_INT, ssintr);

	/*
	 * Initialize drives we know about (i.e. in NSDRIVE bitmap).
	 */
	host_claimed = -1;
	bufq_init(max_id + 1);
	max_req_poll = INL_MAX_REQ_POLL;
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID; i++)
			if ((NSDRIVE >> i) & 1)
				ssinit(i);
	}
	max_req_poll = WKG_MAX_REQ_POLL;
}

/*
 * ssunload()	- unload routine.
 */
static void ssunload()
{
	/*
	 * Deallocate driver heap space.
	 */
	if (ss_tbl)
		kfree(ss_tbl);
	bufq_rlse();

	/*
	 * Free the ST0x selector.
	 */
	vrelse(ss_fp);

	/*
	 * Release IRQ vector.
	 */
	clrivec(SS_INT);
}

/*
 * ssopen()
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void ssopen(dev, mode)
register dev_t	dev;
{
	int drive, partn;
	struct	fdisk_s	*fdp;
	ss_type * ssp;
	int s_id;
	uchar * msg;

	/*
	 * Set up local variables.
	 */
	drive = DEV_SCSI_ID(dev);
	partn = DEV_PARTN(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;

#if (DEBUG >= 3)
devmsg(dev, "ssopen");
#endif

	/*
	 * LUN must be zero.
	 * SCSI id must have corresponding 1 in NSDRIVE bitmapped variable.
	 */
	if (DEV_LUN(dev) != 0 || ((1 << drive) & NSDRIVE) == 0) {
		msg = "bad LUN or SCSI id";
		u.u_error = ENXIO;
		goto bad_open;
	}

	/*
	 * If "special" bit is set, partition field must be zero.
	 */
	if (DEV_SPECIAL(dev) && partn != 0) {
		msg = "bad special partition";
		u.u_error = ENXIO;
		goto bad_open;
	}

	/*
	 * Subscripting gimmick for partition table.
	 */
	if (dev & SDEV)
		partn = WHOLE_DRIVE;

	/*
	 * If not accessing whole drive and the partition table has not
	 * been read yet, try to read it now.
	 * Do this by calling fdisk() with partition table device on the drive
	 * that is being accessed.
	 */
	if (partn != WHOLE_DRIVE && !(ssp->ptab_read)) {
		int fdisk_dev;

		fdisk_dev = (dev | SDEV) & 0xfff0;

#if (DEBUG >=3)
		devmsg(fdisk_dev, "calling fdisk");
		if (fdisk(fdisk_dev, fdp)) {
			int p;

			fdp[WHOLE_DRIVE].p_size = ssp->capacity;
			fdp[WHOLE_DRIVE].p_base = 0;
			printf("fdisk() succeeded\n");
			for (p=0; p<=WHOLE_DRIVE; p++)
	printf("p=%d base=%ld size=%ld\n", p, fdp[p].p_base, fdp[p].p_size);
			ssp->ptab_read = 1;
		} else {
			printf("fdisk() failed\n");
			u.u_error = ENXIO;
			goto bad_open;
		}
#else
		if (fdisk(fdisk_dev, fdp)) {
			fdp[WHOLE_DRIVE].p_size = ssp->capacity;
			fdp[WHOLE_DRIVE].p_base = 0;
			ssp->ptab_read = 1;
		} else {
			msg = "bad partition table";
			u.u_error = ENXIO;
			goto bad_open;
		}
#endif

	}

	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	if (partn != WHOLE_DRIVE
	&& (fdp[partn].p_base+fdp[partn].p_size) > fdp[WHOLE_DRIVE].p_size) {
		msg = "partition exceeds drive capacity";
		u.u_error = EBADFMT;
		goto bad_open;
	}

	if (partn != WHOLE_DRIVE && fdp[partn].p_size == 0) {
		msg = "partition not found";
		u.u_error = ENODEV;
		goto bad_open;
	}

	/*
	 * OK to open the device.
	 * Start watchdog timer (if not already started) for the host adapter.
	 */
	++drvl[SCSI_MAJOR].d_time;
	++ssp->dr_watch;
	goto end_open;

bad_open:
	devmsg(dev, msg);
end_open:
	return;
}

/*
 * ssclose()
 */
static void ssclose(dev)
dev_t dev;
{
	ss_type * ssp;
	int s_id;

	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];

	/*
	 * Decrement the number of watchdog timer requests open for host
	 * adapter and for target.
	 */
	--drvl[SCSI_MAJOR].d_time;
	--ssp->dr_watch;

#if (DEBUG >= 3)
devmsg(dev, "ssclose");
#endif

}

/*
 * ssread()	- read a block from the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void ssread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
}

/*
 * sswrite()	- write a block to the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void sswrite(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
}

/*
 * ssioctl()
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 */
static int ssioctl(dev, cmd, vec)
register dev_t	dev;
int cmd;
char * vec;
{
	int ret = 0;
	hdparm_t hdparm;
	struct	fdisk_s	*fdp;
	int s_id;
	ss_type * ssp;

	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;

	switch(cmd) {
	case HDGETA:
		/*
		 * Get hard disk attributes.
		 */
PR3("HDGETA");
		fdp = ssp->parmp;
		*(short *)&hdparm.landc[0] =
		*(short *)&hdparm.ncyl[0] = drv_parm[s_id].ncyl;
		hdparm.nhead = drv_parm[s_id].nhead;
		hdparm.nspt = drv_parm[s_id].nspt;
#if (DEBUG >= 3)
printf("ncyl=%d nhead=%d nspt=%d\n",
  hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt);
#endif
		kucopy(&hdparm, vec, sizeof hdparm);
		ret = 0;
		break;
	case HDSETA:
		/*
		 * Set hard disk attributes.
		 */
PR3("HDSETA");
		fdp = ssp->parmp;
		ukcopy(vec, &hdparm, sizeof hdparm);
		drv_parm[s_id].ncyl = *(short *)&hdparm.ncyl[0];
		drv_parm[s_id].nhead = hdparm.nhead;
		drv_parm[s_id].nspt = hdparm.nspt;
#if (DEBUG >= 3)
printf("ncyl=%d nhead=%d nspt=%d\n",
  hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt);
#endif
		ret = 0;
		break;
	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * ssblock()	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void ssblock(bp)
register BUF	*bp;
{
	struct	fdisk_s	*fdp;
	int partition, drive, s_id;
	dev_t dev;
	ss_type * ssp;
	uchar * msg = NULL;

	/*
	 * Set up local variables.
	 */
	dev = bp->b_dev;
	partition = DEV_PARTN(dev);
	drive = DEV_DRIVE(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	if (dev & SDEV)
		partition = WHOLE_DRIVE;
	fdp = ssp->parmp;

	bp->b_resid = bp->b_count;
#if (DEBUG >= 2)
if (bp->b_count != BSIZE)
	printf("b_count=%d ", bp->b_count);
#endif

	/*
	 * Range check disk region.
	 */
	if (!(ssp->ptab_read)) {
		if ( partition == WHOLE_DRIVE ) {
			if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
				msg = "invalid request";
				bp->b_flag |= BFERR;
				goto bad_blk;
			}
		} else {
			msg = "no partition table";
			bp->b_flag |= BFERR;
			goto bad_blk;
		}
	}

	/*
	 * Check for read at end of partition.
	 * (Need to return with b_resid = BSIZE to signal end of volume.)
	 */
	else if ((bp->b_req == BREAD) && (bp->b_bno == fdp[partition].p_size)) {
		goto bad_blk;
	}

	/*
	 * Check for read past end of partition.
	 */
	else if ( (bp->b_bno + (bp->b_count/BSIZE))
	> fdp[partition].p_size ) {
		msg = "partition overrun";
		bp->b_flag |= BFERR;
		goto bad_blk;
	}

	/*
	 * Fail if request is for zero bytes or is not even # of blocks.
	 */
	if ((bp->b_count % BSIZE) || bp->b_count == 0) {
		msg = "invalid byte count";
		bp->b_flag |= BFERR;
		goto bad_blk;
	}

	/*
	 * Operation appears valid.
	 * Fill fields in the node and queue the request.
	 */
	bufq_wr_tail(s_id, bp);
	ss_mach(s_id);
	goto end_blk;

	/*
	 * Operation cannot be done.  Release the kernel buffer structure.
	 * Value of "bp->b_flag" tells caller if error occurred.
	 */
bad_blk:
	if (msg)
		devmsg(dev, msg);
	bdone(bp);

end_blk:
	return;
}

/*
 * ssintr()	- Interrupt routine.
 *
 * If we have been reselected by a recognized target device
 *	let kernel get out of interrupt mode (defer) and do SCSI
 *	reconnect stuff.
 */
static void ssintr()
{
	int s_id;

	s_id = chk_reconn();
	if (s_id != -1) {
		if (ss[s_id]->state == SST_POLL_RESELECT)
			defer(ss_mach, s_id);
		else
			defer(dummy_reconn, s_id);
PR3("!");
	}
}

/*
 * dummy_reconn()
 *
 * Somehow we are in a state where the driver software does not expect
 * a reconnect but a device is trying one anyway.  Go thru the motions
 * of reconnect because not servicing a hanging reselect seems to leave
 * the target hung - in such a way that it fails to respond to reset
 * messages and to reset on the SCSI bus.
 */
static void dummy_reconn(s_id)
int s_id;
{
	int bus_timeout;
	uchar phase_type;
	int s;
	int msg_in;
	int cmdstat;
	int xfer_good = 1;
PR1("DUM");
	if (ss[s_id]->state == SST_POLL_RESELECT) {
		defer(ss_mach, s_id);
		goto dum_done;
	}
	if (!rsel_handshake())
		goto dum_done;

	s = sphi();
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		switch (xpmod(phase_type)) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
			case MSG_DISCONNECT:
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			}
			break;
		case XP_MSG_OUT:
			sfbyte(ss_dat, MSG_NOP); 
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
			break;
		case XP_STAT_IN:
			cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
		case XP_DATA_OUT:
			xfer_good = 0;
			break;
		case XP_DATA_IN:
			ffbyte(ss_dat);
			break;
		default:
			break;
		} /* endswitch */
	} /* endwhile */
	spl(s);

dum_done:
	return;
}

/*
 * sswatch()
 *
 * Invoked once per second if any devices going through this driver are open.
 * Poll for any reselect, in case interrupt got lost.
 */
static void sswatch()
{
	int s_id;
	ss_type * ssp;

	for (s_id = 0; s_id < MAX_SCSI_ID; s_id++) {
		ssp = ss[s_id];
		if (ssp && ssp->dr_watch)
			defer(ss_mach, s_id);
	} /* endfor */
}

/*
 * bus_wait()
 *
 * Wait for specified bit values to appear in Status Register.
 * This uses a tight loop and does not expect to be interrupted.
 *
 * Argument "flags" is a double-byte value;  the high byte is ANDed with
 * status register contents, and the result is tested for equality with
 * the low byte.
 *
 * Return 1 if values wanted appeared, 0 if timeout occurred.
 */
static int bus_wait(flags)
unsigned short flags;
{
	int found, i;
	unsigned char status;

	found = 0;
	for ( i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & (flags >> 8)) == (flags & 0xff)) {
			found = 1;
			break;
		}
	}

#if (DEBUG >= 1)
	if (!found)
		printf("TO:f=%x s=%x ", flags, status);
#endif

	return found;
}

/*
 * ssinit()
 *
 * Attempt to initialize the (unique) drive with a given SCSI id.
 * Assume only one drive per SCSI id, having LUN = 0.
 * 
 * Return 1 if success, 0 if failure.
 */
static int ssinit(s_id)
int s_id;
{
	int retval = 1;
	uchar query_buf[MODESENSELEN];
	ss_type * ssp = ss[s_id];
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

	printf("SCSI ID %d  LUN 0\n", s_id);
	if (retval)
		if (init_call(inquiry, s_id, query_buf)) {
			query_buf[INQUIRYLEN] = 0;
#if (debug >= 2)
			devmsg(dev, query_buf + 8);
#endif
			if (query_buf[0] == 0) {
				retval = 1;
			} else
				devmsg(dev, "Not Direct Access Device");
		} else
			devmsg(dev, "Inquiry Failed");

	if (retval)
		if (init_call(read_cap, s_id, query_buf)) {
			retval = 1;
			ssp->capacity = query_buf[3] | (query_buf[2] << 8)
			| (((long)(query_buf[1])) << 16)
			| (((long)(query_buf[0])) << 24);
			ssp->blocklen = query_buf[7] | (query_buf[6] << 8)
			| (((long)(query_buf[5])) << 16)
			| (((long)(query_buf[4])) << 24);

			printf("Capacity=%ld blocks  Block length=%ld\n",
				ssp->capacity, ssp->blocklen);
		} else
			devmsg(dev, "Read Capacity Failed");

	if (retval)
		if (init_call(mode_sense, s_id, query_buf)) {
			/*
			 * Display physical drive parameters.
			 */
#define FMT_PG	(4+8+8+12)
#define DDG_PG	(4+8+8+12+24)
			uchar heads;
			unsigned short spt;
			ulong cyls;

			spt=((int)query_buf[FMT_PG+10]<<8)
				+ query_buf[FMT_PG+11];
			cyls=((int)query_buf[DDG_PG+2]<<16)
				+ ((int)query_buf[DDG_PG+3]<<8)
				+ query_buf[DDG_PG+4];
			heads=query_buf[DDG_PG+5];

			printf("Physical:  cylinders=%ld ", cyls);
			printf("heads=%d ", heads);
			printf("spt=%d\n", spt);

			if (drv_parm[s_id].ncyl == 0) {
				drv_parm[s_id].ncyl = cyls;
				drv_parm[s_id].nhead = heads;
				drv_parm[s_id].nspt = spt;
			} else {
				printf("Logical:  cylinders=%d ",
					drv_parm[s_id].ncyl);
				printf("heads=%d ", drv_parm[s_id].nhead);
				printf("spt=%d\n", drv_parm[s_id].nspt);
			}
		} else
			devmsg(dev, "Mode Sense Failed");

	return retval;
}

/*
 * far_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * This includes message in/out, command in/out, and data in/out.
 *
 * If cmdlen is nonzero, cmdbuf is an array of bytes of that length,
 * to be sent to the target.
 *
 * Return 1 if bus timeout did not occur, else 0.
 *
 * pseudocode:
 *
 * while (wait for REQ true or BUSY false on SCSI bus)
 *   if (BUSY false)
 *     break from while loop
 *   else
 *     switch (xfer phase = RS_CTRL_DATA|RS_I_O|RS_MESSAGE)
 *       case XP_MSG_IN/XP_MSG_OUT/...
 *         handle the indicated information transfer phase
 *     endswitch
 *   endif
 * endwhile
 */
static int far_info_xfer(s_id)
int s_id;
{
	int bus_timeout;
	uchar phase_type;
	uchar msg_in;
	int s;
	int bytes_to_send;
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int xfer_good = 1;
	int xfer_count = bp->b_count - bp->b_resid;
	int irpts_masked;
int block_done=0;

	ssp->cmd_bytes_out = 0;
	ssp->msg_in = -1;

	irpts_masked = 0;
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		if (!irpts_masked) {
			s = sphi();
			irpts_masked = 1;
		}
		switch (xpmod(phase_type)) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
PR4("Mcc");
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			case MSG_DISCONNECT:
PR4("Mdc");
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			case MSG_SAVE_DPTR:
PR4("Msd");
				break;
			case MSG_RSTOR_DPTR:
PR4("Mrd");
				break;
			case MSG_ABORT:
PR4("Mab");
				break;
			case MSG_DEV_RESET:
PR4("Mdr");
				break;
			case MSG_IDENTIFY:
PR4("Mmi");
				break;
			case MSG_IDENT_DC:
PR4("Mmd");
				break;
			}
			break;
		case XP_MSG_OUT:
PR4("MO");
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.  Abort the bus cycle.
			 */
			sfbyte(ss_dat, MSG_NOP); 
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
			break;
		case XP_STAT_IN:
PR4("SI");
			ssp->cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 * Reset SCSI bus if too many command bytes are wanted.
			 */
			bytes_to_send = ssp->cmdlen - ssp->cmd_bytes_out;
			if(bytes_to_send > 0) {
				sfbyte(ss_dat, ssp->cmdbuf[ssp->cmd_bytes_out++]);
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (bytes_to_send == 1) {
PR4("CO");
					if (bp->b_req == BREAD) {
						if (irpts_masked) {
							spl(s);
							irpts_masked = 0;
						}
					}
				}
			} else {	/* This case should not happen. */
				xfer_good = 0;
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.
			 */
			if (block_done) {
				xfer_good = 0;
PR1("Data in overrun");
			} else if (bp->b_req != BREAD) {
				xfer_good = 0;
			} else {
#if 0
				int getbval;

				block_done=1;
PR4("DI");
				if(getbval = ss_getb(ss_dat,
				bp->b_faddr + xfer_count)) {
					xfer_good = 0;
#if (DEBUG >= 1)
printf("getb=%d ", getbval);
#endif
				}
#else
				block_done=1;
				ffcopy(ss_dat, bp->b_faddr + xfer_count, BSIZE);
#endif
			}
			break;
		case XP_DATA_OUT:
			/*
			 * Copy output buffer bytes to data register.
			 */
			if (block_done) {
				xfer_good = 0;
PR1("Data out overrun");
			} else if (bp->b_req != BWRITE) {
				xfer_good = 0;
			} else {
#if 0
				int putbval;
				block_done=1;
PR4("DO");
				if (putbval = ss_putb(ss_dat,
				bp->b_faddr + xfer_count)) {
					xfer_good = 0;
#if (DEBUG >= 1)
printf("putb=%d ", putbval);
#endif
				}
#else
				block_done=1;
				ffcopy(bp->b_faddr + xfer_count, ss_dat, BSIZE);
#endif
				if (irpts_masked) {
					spl(s);
					irpts_masked = 0;
				}
			}
			break;
		default:
			break;
		} /* endswitch */
	}
	if (irpts_masked)
		spl(s);

#if (DEBUG >= 1)
	switch(ssp->cmdstat) {
	case -1:
		if (msg_in != MSG_DISCONNECT)
			printf("CS-",ssp->cmdstat);
		break;
	case CS_GOOD:
		break;
	case CS_CHECK:
		printf("CSK",ssp->cmdstat);
		break;
	case CS_BUSY:
		printf("CSY",ssp->cmdstat);
		break;
	case CS_RESERVED:
	default:
		printf("CS%x",ssp->cmdstat);
	}
#endif

	return (bus_timeout) ? 0 : 1 ;
}

/*
 * req_wait()
 *
 * This routine is called at the start of each information transfer
 * phase and after the last such phase.
 *
 * It returns 1 if REQ is asserted on the SCSI bus, meaning another phase
 * may begin, and 0 otherwise.  A REQ signal will not be seen if the function
 * times out or if BUSY drops.  A value of 1 is written to the pointer argument
 * if timeout occurred, else 0 is written.
 */
static int req_wait(to_ptr)
int *to_ptr;
{
	int req_found;
	unsigned char status;
	ulong poll_ct;
	int s;

	s = splo();
	*to_ptr = 1;
	req_found = 0;
	for (poll_ct = 0L; poll_ct < max_req_poll; poll_ct++) {
		status = ffbyte(ss_csr);
		if (status & RS_REQUEST) {
			req_found = 1;
			*to_ptr = 0;
			break;
		} else if ((status & RS_BUSY) == 0) {
			*to_ptr = 0;
			break;
		}
	}

#if (DEBUG >= 1)
	if (*to_ptr) {
		printf("TX: s=%x ", status);
	}
#endif

	spl(s);
	return req_found;
}

/*
 * req_sense()
 *
 * Request Sense for a device.  The main reason for doing this is to
 * clear a standing Command Status of Device Check.
 *
 * Full results are discarded.  Return 1 if Device returns No Sense or
 * or Unit Attention.  Else return 0.
 *
 */
static int req_sense(s_id)
int s_id;
{
	uchar sense_buf[SENSELEN];
	uchar cmdbuf[G0CMDLEN];
	int ret = 0;

	cmdbuf[0] = ScmdREQUESTSENSE;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = SENSELEN;
	cmdbuf[5] = 0;

#if (DEBUG >= 2)
{int i; for (i=0; i<SENSELEN; i++) sense_buf[i]=0;}
#endif

PR2("rqs:");
	if (!start_arb()) {
PR2("NO arb");
#if (DEBUG >= 2)
printf("status=%x ", ffbyte(ss_csr));
#endif
		goto rqs_done;
	}

	if (!host_ident(s_id, 0)) {
PR2("NO host ident");
#if (DEBUG >= 2)
printf("status=%x ", ffbyte(ss_csr));
#endif
		goto rqs_done;
	}

	if(!local_info_xfer(cmdbuf, G0CMDLEN, sense_buf, SENSELEN, NULL, 0)) {
PR2("NO local xfer");
		goto rqs_done;
	} else {
		/*
		 * Return 1 if drive responded with any of these sense keys:
		 *	0x00	No Sense
		 *	0x06	Unit Attention
		 *	0x0B	Aborted Command
		 * In any of the above cases, a retry will likely succeed
		 * without Buse Device Reset or SCSI Bus Reset.
		 */
		switch (sense_buf[2]) {
		case 0x00:
		case 0x06:
		case 0x0B:
			ret = 1;
			break;
		} /* endswitch */
	}

rqs_done:
#if (DEBUG >= 2)
{
	int i;

	for (i=0; i<SENSELEN;i++)
		printf("%x ", sense_buf[i]);
	printf("\n");
}
#endif
	return ret;
}

/*
 * inquiry()
 *
 * Inquiry command for a device.
 * Find out if device is direct access, removable, etc.
 *
 * Put result of inquiry into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int inquiry(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G0CMDLEN];

	cmdbuf[0] = ScmdINQUIRY;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = INQUIRYLEN;
	cmdbuf[5] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, buf, INQUIRYLEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * mode_sense()
 *
 * Mode Sense command for a device.
 * Use this to get disk parameters:
 *	number of cylinders
 *	number of heads
 *	number of sectors per track.
 *
 * Put result of mode sense into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int mode_sense(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G0CMDLEN];

	cmdbuf[0] = ScmdMODESENSE;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0x3F;
	cmdbuf[3] = 0;
	cmdbuf[4] = MODESENSELEN;
	cmdbuf[5] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, buf, MODESENSELEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * read_cap()
 *
 * Read Capacity command for a device.
 *
 * Return 1 if command succeeds, else 0.
 */
static int read_cap(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G1CMDLEN];

	cmdbuf[0] = ScmdREADCAPACITY;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = 0;
	cmdbuf[5] = 0;
	cmdbuf[6] = 0;
	cmdbuf[7] = 0;
	cmdbuf[8] = 0;
	cmdbuf[9] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G1CMDLEN, buf, READCAPLEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * bus_dev_reset()
 *
 * Send Bus Device Reset message to the given SCSI id.
 * Return 1 if host adapter was not busy and no obvious timeouts occurred,
 * else 0.
 */
static int bus_dev_reset(s_id)
{
	int bdr_ok = 1;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

PR1("BDR");
	if (bdr_ok) {
		/*
		 * Do ST0x arbitration.
		 *
		 * De-assert SCSI enable bit.
		 * Write my SCSI id to port.
		 * Start arbitration.
		 */
		sfbyte(ss_csr, WC_ENABLE_PRTY);
		sfbyte(ss_dat, host_id);
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ARBITRATE);

		/*
		 * SCSI spec says there is "no maximum" to the wait for
		 * arbitration complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			bdr_ok = 0;
		}
	}

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	if (bdr_ok) {
		sfbyte(ss_dat, host_id | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION);

		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
		sfbyte(ss_dat, MSG_DEV_RESET);
		if (!bus_wait((0xFF << 8) | 0))
			bdr_ok = 0;
	}

	return bdr_ok;
}

/*
 * chk_reconn()
 *
 * Check SELECT to see if any SCSI device has tried to reconnect to the host
 * adapter.  Called if there is an interrupt, and by the timer in case
 * we somehow lose an interrupt.
 *
 * Return -1 if no reselect detected, or the SCSI ID of the reselecting
 * target if there is one.
 */
static int chk_reconn()
{
	uchar csr, dat;
	int s_id = -1;

	csr = ffbyte(ss_csr);
	if (csr & (RS_SELECT | RS_I_O)) {
		dat = ffbyte(ss_dat);
		if ((dat & host_id) && (dat & NSDRIVE)) {
			dat &= ~host_id;
			s_id = 0;
			while (dat >>=1)
				s_id++;
		}
	}

	return s_id;
}

/*
 * ss_mach()
 *
 *	Gives a distinct state machine for each target device.
 */
void	ss_mach(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp;

	do_sst_op = 1; /* plan to run this routine again in most cases */
	while (do_sst_op) {
		bp = ssp->bp;  /* nonpolled() below can change ssp->bp */
		switch (ssp->state) {
		/*
		 * Polling states execute whether ssp->waiting or not.
		 */
		case SST_POLL_ARBITN:
PR3("XPAR");
			if (ffbyte(ss_csr) & RS_ARBIT_COMPL) {
				ssp->waiting = 0;
				if (host_ident(s_id, 1))
					do_connect(s_id);
				else
					recover(s_id, RV_P_TIMEOUT);
			} else {
				if (ssp->expired) {
					ssp->expired = 0;
					recover(s_id, RV_A_TIMEOUT);
				} else
					do_sst_op = 0;
			}
			break;
		case SST_POLL_RESELECT:
PR3("XPRS");
			if (TGT_RSEL) {
				ssp->waiting = 0;
				if (host_claimed == -1)
					host_claimed = s_id;
				else if (host_claimed != s_id) {
#if (DEBUG >= 1)
	printf("%d->%d ", host_claimed, s_id);
#endif
				}
				if (rsel_handshake()) {
					do_connect(s_id);
				} else {
					recover(s_id, RV_P_TIMEOUT);
				}
			} else  { /* Reselect poll is negative */
				if (ssp->expired) {
					ssp->expired = 0;
					recover(s_id, RV_R_TIMEOUT);
				} else
					do_sst_op = 0;
			}
			break;
		case SST_POLL_BEGIN_IO:
PR3("XPBI");
			if (bp == NULL)
				ssp->state = SST_DEQUEUE;
			else {
				/*
				 * At this point a SCSI command is about to
				 * be initiated.  It may be a retry.
				 */
				if (host_claimed == -1 && BUS_FREE && BUS_FREE) {
					ssp->waiting = 0;
					init_pointers(s_id);
					if (start_arb()) {
						host_claimed = s_id;
						if (host_ident(s_id, 1)) {
							do_connect(s_id);
						} else {
							recover(s_id, RV_P_TIMEOUT);
						}
					} else {
	/*
	 * If arbitration does not succeed right away, it is usually
	 * because another drive is trying to reselect the host.
	 */
						set_timeout(s_id, DELAY_ARB);
					}
				} else { /* host busy or bus not free */
					int o_id;

					if ((o_id = chk_reconn()) != -1)
						defer(dummy_reconn, s_id);
					++ssp->avl_count;
					if (ssp->avl_count >= MAX_AVL_COUNT)
						recover(s_id, RV_BF_TIMEOUT);
					else
						set_timeout(s_id, DELAY_BSY);
				}
			}
			break;
		default:
			if (ssp->waiting)
				do_sst_op = 0;
			else {
				/*
				 * Nonpolling states execute only if no
				 * target timer is running.
				 */
				nonpolled(s_id);
			}
		} /* endswitch */
	} /* endwhile */
}

/*
 * nonpolled()
 *
 * Part of ss_mach() - handling of nonpolling states is taken out simply
 * for readability.
 */
static void nonpolled(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	struct	fdisk_s	*fdp;
	int partition;
	dev_t dev;

	switch (ssp->state) {
	case SST_BUS_DEV_RESET:
PR3("XBDR");
		if (bus_dev_reset(s_id)) {
			do_sst_op = 0;
			set_timeout(s_id, DELAY_BDR);
			ssp->state = SST_REQ_SENSE;
		} else
			recover(s_id, RV_P_TIMEOUT);
		break;
	case SST_DEQUEUE:
		if(bufq_rd_head(s_id) != NULL && !ssp->busy) {
PR3("XDQU");
			ssp->busy = 1;
			bp = bufq_rm_head(s_id);
			ssp->bp = bp;
			dev = bp->b_dev;
			partition = DEV_PARTN(dev);
			if (dev & SDEV)
				partition = WHOLE_DRIVE;
			fdp = ssp->parmp;
			if (partition != WHOLE_DRIVE)
				ssp->bno = fdp[partition].p_base + bp->b_bno;
			else
				ssp->bno = bp->b_bno;
			if (bp->b_req == BREAD)
				ssp->cmdbuf[0] = ScmdREADEXTENDED;
			else
				ssp->cmdbuf[0] = ScmdWRITEXTENDED;
			ssp->cmdbuf[1] = 0;
			ssp->cmdbuf[2] = ssp->bno >> 24;
			ssp->cmdbuf[3] = ssp->bno >> 16;
			ssp->cmdbuf[4] = ssp->bno >>  8;
			ssp->cmdbuf[5] = ssp->bno;
			ssp->cmdbuf[6] = 0;
			ssp->cmdbuf[7] = 0;
			ssp->cmdbuf[8] = 1;
			ssp->cmdbuf[9] = 0;
			ssp->cmdlen = G1CMDLEN;
			init_pointers(s_id);
			ssp->bdr_count = 0;
			ssp->bsy_count = 0;
			ssp->try_count = 0;
			ssp->state = SST_POLL_BEGIN_IO;
		} else /* queue is empty or ssp->busy */
			do_sst_op = 0;
		break;
	case SST_HIPRI_RESET:
	case SST_LOPRI_RESET:
PR1("XRST");
		/*
		 * SST_LOPRI_RESET is same as SST_HIPRI_RESET for now.
		 * Later, can implement a delay to allow other targets to
		 * finish pending operations.
		 */
		if (host_claimed == s_id || host_claimed == -1) {
			host_claimed = s_id;
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_SCSI_RESET); /* reset ON */
			ssp->state = SST_RESET_OFF;
			set_timeout(s_id, DELAY_RST);
PR1("+");
		} else
			set_timeout(s_id, DELAY_RST);
		break;
	case SST_REQ_SENSE:
PR1("XRQS");
		/*
		 * Come here at end of SCSI Bus reset (and at other times).
		 * If we have host claimed, release it.
		 */
		if (host_claimed == s_id)
			host_claimed = -1;
		if (req_sense(s_id))
			ssp->state = SST_POLL_BEGIN_IO;
		else
			recover(s_id, RV_P_TIMEOUT);
		break;
	case SST_RESET_OFF:
PR3("XRFF");
		sfbyte(ss_csr, WC_ENABLE_PRTY); /* reset OFF */
		ssp->state = SST_REQ_SENSE;
		set_timeout(s_id, DELAY_RST);
	} /* endswitch */
}

/*
 * start_arb()
 *
 * return 1 if host adapter returned Arbitration Complete within allotted
 * number of tries, else 0
 */
static int start_arb()
{
	int ret = 0;
	int poll_ct;

	sfbyte(ss_csr, WC_ENABLE_PRTY);
	sfbyte(ss_dat, host_id);
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ARBITRATE);

	/*
	 * SCSI spec says there is "no maximum" to the wait for arbitration
	 * complete.
	 */
	for (poll_ct = 0; poll_ct < HIPRI_RETRIES; poll_ct++) {
		if (ffbyte(ss_csr) & RS_ARBIT_COMPL) {
			ret = 1;
			break;
		} else if (chk_reconn() != -1) {
			sfbyte(ss_csr, WC_ENABLE_PRTY);
			break;
		}
	}
#if (DEBUG >= 1)
if (!ret)
	PR1("oSA");
#endif
	return ret;
}

/*
 * host_ident()
 *
 * This routine is the bridge in a SCSI bus cycle between Abitration
 * Complete and the Information Transfer phases.
 *
 * return 1 if everything went ok, 0 in case of timeout
 */
static int host_ident(s_id, disconnect)
int s_id;
int disconnect;
{
	int ret = 0;

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	sfbyte(ss_dat, host_id | (1 << s_id));	/* Write both SCSI id's */
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

	if (bus_wait(RS_BUSY << 8 | RS_BUSY)) {
		/*
		 * Assert ATTN so target expects incoming message byte.
		 */
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION);

		if (bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE))) {
			if (disconnect)
				sfbyte(ss_dat, MSG_IDENT_DC);
			else
				sfbyte(ss_dat, MSG_IDENTIFY);
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ENABLE_IRPT);
			ret = 1;
		} else {
PR1("oHI2");
		}
	} else {
PR1("oHI1");
	}
	return ret;
}

/*
 * rsel_handshake()
 *
 * After Reselect is detected, a couple steps are needed before entering
 * Information Transfer phases.  This routine does those steps.
 *
 * return 1 if ok, 0 in case of timeout.
 */
static int rsel_handshake()
{
	int ret = 0;

	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_BUSY);
	if (bus_wait(RS_SELECT << 8 | 0)) {
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
		ret = 1;
	}
	return ret;
}

/*
 * set_timeout()
 *
 * Start a timer so as not to wait forever in case something goes wrong while
 * waiting for an event.  Available delays are:
 *
 * 	DELAY_ARB -	wait for arbitration complete
 * 	DELAY_BDR -	allow settling time after Bus Device Reset
 * 	DELAY_BSY -	wait for not HOST_BUSY and bus free
 * 	DELAY_RES -	wait for reselect by target
 * 	DELAY_RST -	allow settling times when doing SCSI Bus Reset
 *
 * Second argument is number of clock ticks to wait until timer expiration.
 */
static void set_timeout(s_id, delay)
int s_id, delay;
{
	ss_type * ssp = ss[s_id];

	ssp->expired = 0;
	ssp->waiting = 1;
	do_sst_op =  0;
	timeout(&(ssp->tim), delay, stop_timeout, s_id);
}

/*
 * stop_timeout()
 *
 * Called on expiration of the timer for a given target.
 * Don't expire a timer if it's no longer active.
 */
static void stop_timeout(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];

	if (ssp->waiting) {
		ssp->expired = 1;
		ssp->waiting = 0;
	}
	ss_mach(s_id);
}

/*
 * init_pointers()
 *
 * Initialize command and data pointers when starting (or restarting)
 * a block i/o command.
 */
static void init_pointers(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

	ssp->cmdstat = -1;
	ssp->cmd_bytes_out = 0;
	ssp->avl_count = 0;
}

/*
 * recover()
 *
 * This routine is called directly or indirectly from ss_mach().  It
 * determines what to do when the interface fails to behave as desired.
 *
 * Arguments are the SCSI id of the target HDC and an error type.
 * Error types are:
 *
 * RV_A_TIMEOUT (arbitration timeout)
 * Host adapter takes too long to respond with arbitration complete.
 * 
 * RV_P_TIMEOUT (protocol timeout)
 * Timeout waiting for desired SCSI bus status while connected to a target.
 * 
 * RV_R_TIMEOUT (reconnect timeout)
 * Timeout after target disconnects, waiting for reconnect.
 * 
 * RV_BF_TIMEOUT (bus free timeout)
 * Waited too long for host not busy and BUS_FREE.
 * 
 * RV_CS_BUSY (target device busy)
 * Command status returned was Busy.
 * 
 * RV_CS_CHECK (target device check)
 * Command status returned was CHECK.
 * 
 * Whenever an error occurs, one of the above inputs, together with the SCSI id
 * of the target, is sent to the recovery process.  The recovery process in turn
 * programs the next state for the machine.
 */
static void recover(s_id, errtype)
int s_id;
RV_TYPE errtype;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

#if (DEBUG >= 1)
int foo;
if ((foo=chk_reconn()) != -1)
	printf("HONK%d ", foo);
#endif

	++ssp->try_count;
	if (ssp->try_count < MAX_TRY_COUNT) {

		switch (errtype) {

		case RV_CS_BUSY:
			++ssp->bsy_count;
			if (ssp->bsy_count < MAX_BSY_COUNT) {
				ssp->state = SST_POLL_BEGIN_IO;
				set_timeout(s_id, DELAY_BSY);
			} else
				ssp->state = SST_BUS_DEV_RESET;
			break;

		case RV_CS_CHECK:
			ssp->state = SST_REQ_SENSE;
			break;

		case RV_P_TIMEOUT:
			/* fall thru */
		case RV_R_TIMEOUT:
			++ssp->bdr_count;
			if (ssp->bdr_count < MAX_BDR_COUNT)
				ssp->state = SST_BUS_DEV_RESET;
			else
				ssp->state = SST_LOPRI_RESET;
			break;

		case RV_BF_TIMEOUT:
			/* fall thru */
		case RV_A_TIMEOUT:
			ssp->state = SST_HIPRI_RESET;
		}
	} else { /* try_count >= MAX_TRY_COUNT */
		if (bp) {
			bp->b_flag |= BFERR;
			printf("(%d,%d): ", major(bp->b_dev), minor(bp->b_dev));
			printf("%s error bno=%ld\n",
				(bp->b_req == BREAD) ? "read" : "write",
				bp->b_bno);
		}
		ss_finished(s_id);
	}
}

/*
 * ss_finished
 *
 * Release current i/o buffer to the O/S.
 */
static void ss_finished(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int go_again = 1;

	if (host_claimed == s_id)
		host_claimed = -1;
	ssp->busy = 0;
	if (bp) {
		if (!(bp->b_flag & BFERR))
			bp->b_resid -= BSIZE;
		if ((bp->b_flag & BFERR) || bp->b_resid == 0) {
			ssp->bp = NULL;
			bdone(bp);
			go_again = 0;
		}
	}
	if (go_again) {
		ssp->state = SST_POLL_BEGIN_IO;
		ssp->bdr_count = 0;
		ssp->bsy_count = 0;
		ssp->try_count = 0;

		ssp->bno++;
		ssp->cmdbuf[2] = ssp->bno >> 24;
		ssp->cmdbuf[3] = ssp->bno >> 16;
		ssp->cmdbuf[4] = ssp->bno >>  8;
		ssp->cmdbuf[5] = ssp->bno;
	} else {
		/*
		 * After processing a kernel i/o request, stop the
		 * state machine for the current id.  Then start
		 * this or some other machine which has a request
		 * pending.
		 */
		do_sst_op =  0;
		ssp->state = SST_DEQUEUE;
		next_req(s_id);
	}
}

/*
 * next_req()
 *
 * Given the SCSI id where an i/o request just completed, start handling
 * another i/o request - which may be for the same or other SCSI id.
 * For now, use round-robin scheduling.
 */
static void next_req(s_id)
int s_id;
{
	int next_id = s_id;

	while (1) {
		next_id++;
		if (next_id >= MAX_SCSI_ID)
			next_id = 0;
		if (ss[next_id]
		&& (ss[next_id]->state != SST_DEQUEUE || bufq_rd_head(next_id))) {
			defer(ss_mach, next_id);
			break;
		}
		if (next_id == s_id)
			break;
	}
}

/*
 * do_connect()
 *
 * This function is called when the host is successfully connected to
 * the target.  It invokes information transfer protocol and then sets
 * up some sort of recovery unless the command completed successfully
 * or there was a normal disconnect.
 */
static void do_connect(s_id)
int s_id;
{
	int result;
	ss_type * ssp = ss[s_id];

	result = far_info_xfer(s_id);
	if (!result)
		recover(s_id, RV_P_TIMEOUT);
	else if (ssp->msg_in == MSG_DISCONNECT) {
		ssp->state = SST_POLL_RESELECT;
		set_timeout(s_id, DELAY_RES);
#if 0
		if (host_claimed == s_id)
			host_claimed = -1;
#endif
	} else if (ssp->msg_in == MSG_CMD_CMPLT && ssp->cmdstat == CS_GOOD)
		ss_finished(s_id);
	else if (ssp->cmdstat == CS_BUSY)
		recover(s_id, RV_CS_BUSY);
	else if (ssp->cmdstat == CS_CHECK)
		recover(s_id, RV_CS_CHECK);
	else  /* something else went wrong */
		recover(s_id, RV_P_TIMEOUT);
}

/*
 * local_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * Transfer is for a command which will produce local results in the driver.
 * Other ...info_xfer routine handles kernel block i/o commands.
 *
 * Return 1 if transfer succeeded, else 0.
 *
 */
static int local_info_xfer(cmdbuf, cmdlen, inbuf, inlen, outbuf, outlen)
uchar * cmdbuf, * inbuf, * outbuf;
uint cmdlen, inlen, outlen;
{
	int bus_timeout;
	uchar phase_type;
	int s;
	int cmd_bytes_out = 0;
	int data_bytes_in = 0;
	int data_bytes_out = 0;
	int ret = 0;
	int xfer_good = 1;
	int cmdstat = -1;
	int msg_in = -1;
#if (DEBUG >= 1)
int x, xct=0;
uchar xch[100];
#endif

	s = sphi();
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
#if (DEBUG >= 1)
if (xct < 100)
	xch[xct++]=phase_type;
#endif
		switch (xpmod(phase_type)) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
			case MSG_DISCONNECT:
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			}
			break;
		case XP_MSG_OUT:
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.
			 */
			sfbyte(ss_dat, MSG_NOP); 
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
			break;
		case XP_STAT_IN:
			cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 */
			if (cmd_bytes_out < cmdlen) {
				sfbyte(ss_dat, cmdbuf[cmd_bytes_out++]);
#if 1
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (cmd_bytes_out == cmdlen) {
					spl(s);
					s = sphi();
				}
#endif
			} else {	/* This case should not happen. */
				xfer_good = 0;
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.  Else toss it.
			 */
			if (data_bytes_in < inlen) {
#if 0
				do {
					inbuf[data_bytes_in++] = ffbyte(ss_dat);
				} while (data_bytes_in < inlen);
#else
				inbuf[data_bytes_in++] = ffbyte(ss_dat);
#endif
			} else
				xfer_good = 0;
			break;
		case XP_DATA_OUT:
			/*
			 * Copy output buffer bytes to data register.
			 */
			if (data_bytes_out < outlen) {
				sfbyte(outbuf[data_bytes_out++], ss_dat);
			} else { /* This case should not happen. */
				xfer_good = 0;
			}
			break;
		default:
			break;
		} /* endswitch */
	}
	spl(s);

	if (bus_timeout) {
PR1("oLX1");
	} else if (!xfer_good) {
PR1("oLX2");
	} else if (cmdstat != CS_GOOD) {
PR1("oLX3");
#if (DEBUG >= 1)
printf("cmdstat=%x ", cmdstat);
#endif
	} else
		ret = 1;
#if (DEBUG >= 1)
if (!ret) {
	printf("csr=%x ", ffbyte(ss_csr));
	printf("xct=%d  ", xct);
	for (x=0; x < xct; x++)
		printf("%x ", xch[x]);
}
#endif

	return ret;
}

/*
 * scsireset()
 *
 * Reset the SCSI bus.
 * Allow settling time when turning reset on/off.
 * Settling times were determined empirically.
 * Each tick is 10 msec.
 */
static void scsireset()
{
	int s;

#if (DEBUG >= 1)
printf("scsireset ");
#endif
	s = splo();
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_SCSI_RESET);
	ssdelay(RESET_TICKS);
	sfbyte(ss_csr, WC_ENABLE_PRTY);
	ssdelay(RESET_TICKS);
	spl(s);
}

/*
 * ssdelay()
 *
 * Delay for some number of arbitrary ticks.
 *
 * Using sleep() causes a panic if this driver is linked to the kernel,
 * even though this routine is called only via ssload().
 */
static void ssdelay(ticks)
int ticks;
{
#if 0
	timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
#else
	int i, j;

	for (i = 0; i < ticks; i++)
		for (j = 0; j < LOAD_DELAY; j++);
#endif
}

/*
 * init_call()
 *
 * Call SCSI command function during initialization, with error recovery.
 * If the simple command fails, try a Bus Device Reset, then SCSI Bus reset.
 */
static int init_call(fn, s_id, buf)
int (*fn)();
int s_id;
uchar * buf;
{
	int ret = 1;
	int i;
	int o_id;
int s;
s=sphi();
	for (i = 0; i < 2; i++) {
		o_id = chk_reconn();
		if (o_id != -1)
			dummy_reconn(s_id);
		if ((*fn)(s_id, buf))
			goto init_call_done;

		req_sense(s_id);
		if ((*fn)(s_id, buf))
			goto init_call_done;

		if (bus_dev_reset(s_id)) {
			ssdelay(RESET_TICKS);
			req_sense(s_id);
			if ((*fn)(s_id, buf))
				goto init_call_done;
		}

		scsireset();
		req_sense(s_id);
		if ((*fn)(s_id, buf))
			goto init_call_done;
	}

	ret = 0;

init_call_done:
spl(s);
	return ret;
}

/*
 * xpmod()
 *
 * Command/Data and Message bits are swapped on-board (outside the chip)
 * on older Future Domain host boards.
 */
static uchar xpmod(oldphase)
uchar oldphase;
{
	uchar ret = oldphase;

	if (swap_status_bits) {
		ret &= ~(RS_CTRL_DATA | RS_MESSAGE);
		if (oldphase & RS_MESSAGE)
			ret |= RS_CTRL_DATA;
		if (oldphase & RS_CTRL_DATA)
			ret |= RS_MESSAGE;
	}
	return ret;
} 
0707070064030150071006440000030000030000011777770507310643700005000000010222/newbits/kernel/USRSRC/i8086/drv/ssas.s////////
/
/ I/O for Seagate ST01/ST02 SCSI Host Adapters.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.7  91/06/01  10:51:00  hal
/ Add ffcopy().
/ 
/ Revision 1.6  91/06/01  10:32:51  hal
/ Do handshaking both ways.  Now names are ss_getb()/ss_putb().
/ 
/ Revision 1.5	91/05/20  17:22:03	root
/ Not using ss_put() any more.
/ 
/ Revision 1.4	91/05/20  16:21:35	root
/ Call to ss_putc() now works.
/ 
/ Revision 1.3	91/05/20  10:23:13	root
/ Drop 3rd arg.  Same code for Seagate & Future Domain.
/ 
/ Revision 1.2	91/05/17  00:24:17	root
/ Code ss_put - use REQ handshake.
/ 
/ Revision 1.1	91/05/16  14:16:21	root
/ Initial version - no code yet for ss_put().
/ 
/
/	Since these functions are called from the midst of C code in
/	the "ss" driver, they need to preserve the following registers:
/		SI  DI  SP  BP    SS  DS  ES
/	Additionally, surrounding C code is expected to leave the "D"
/	CPU flag clear (string op's increment index registers).
/
////////

////////
/
/	Export functions.
/
////////
	.globl	ss_getb_
	.globl	ss_putb_
	.globl	ffcopy_

////////
/
/ Constants
/
/	Relative to the RAM base address of the host adapter, offsets
/	for Control/Status Register (CSR) and Data Port (DAT) differ
/	between Seagate and Future Domain as follows:
/			Seagate		Future Domain
/		SS_CSR	0x1A00		0x1C00
/		SS_DAT	0x1C00		0x1E00
/	The difference between these (CSR_OFF) is 0x200 in either case.
/
////////

	BSIZE	= 0x200		/ Disk block size in bytes
	CSR_OFF	= 0x200

	REQ_LIM = 500
	RS_REQUEST = 0x10

////////
/
/ ss_getb(ss_dat_fp, buf_fp)
/ faddr_t ss_dat_fp, buf_fp;
/
/ Fetch input bytes from host adapter and store at buffer address.
/
/ Do REQ handshaking and return the number of bytes remaining to transfer.
/ (So return value of 0 means no error.)
/
/ Here is the stack after initial "push bp":
/
/	10(bp)	FP_SEL(buf_fp)
/	8(bp)	FP_OFF(buf_fp)
/	6(bp)	FP_SEL(ss_dat_fp)
/	4(bp)	FP_OFF(ss_dat_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ss_getb_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si

	lds	si, 4(bp)	/ ss_dat_fp to DS:SI
	mov	bx, si		/ .. and to DS:BX
	sub	bx, $CSR_OFF	/ ss_csr to DS:BX
	les	di, 8(bp)	/ buf_fp to ES:DI
	mov	cx, $BSIZE	/ rep count to CX

G01:				/ start outer loop - reading bytes from SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
G02:				/ start inner loop - polling for REQ
	movb	dl, (bx)
	testb	dl, $RS_REQUEST
	jne	G03		/ got REQ
	dec	ax
	jnz	G02		/ no REQ - look again
	jmp	G04		/ no REQ - give up

G03:				/ got REQ - ok to read a byte
	movsb
	loop	G01
G04:				/ all done
	mov	ax, cx		/ normal exit returns 0

	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

////////
/
/ int ss_putb(ss_dat_fp, buf_fp)
/ faddr_t ss_dat_fp, buf_fp;
/
/ Write output bytes to host adapter from buffer address.
/
/ Return the number of bytes remaining to be sent (should be 0).
/
/ Here is the stack after initial "push bp":
/
/	10(bp)	FP_SEL(buf_fp)
/	8(bp)	FP_OFF(buf_fp)
/	6(bp)	FP_SEL(ss_dat_fp)
/	4(bp)	FP_OFF(ss_dat_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ss_putb_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si 
	lds	si, 8(bp)	/ buf_fp to DS:SI
	les	di, 4(bp)	/ ss_dat_fp  to ES:DI
	mov	bx, di		/ .. and to ES:BX
	sub	bx, $CSR_OFF	/ ss_csr to ES:BX
	mov	cx, $BSIZE	/ count to CX

P01:				/ start outer loop - writing bytes to SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
P02:				/ start inner loop - polling for REQ
	movb	dl, es:(bx)
	testb	dl, $RS_REQUEST
	jne	P03		/ got REQ
	dec	ax
	jnz	P02		/ no REQ - look again
	jmp	P04		/ no REQ - give up

P03:				/ got REQ - ok to write a byte
	movsb
	loop	P01
P04:				/ all done - now restore registers
	mov	ax, cx
	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

////////
/
/ void ffcopy(from_fp, to_fp, count)
/ faddr_t from_fp, to_fp;
/ int count;
/
/ Copy count bytes from from_fp to to_fp.
/
/ Here is the stack after initial "push bp":
/
/	12(bp)	count
/	10(bp)	FP_SEL(to_fp)
/	8(bp)	FP_OFF(to_fp)
/	6(bp)	FP_SEL(from_fp)
/	4(bp)	FP_OFF(from_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ffcopy_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si

	lds	si, 4(bp)	/ from_fp  to DS:SI
	les	di, 8(bp)	/ to_fp to ES:DI
	mov	cx, 12(bp)	/ rep count to CX
	rep
	movsb

	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret
0707070064030150101004440000030000030000011777770507310644000004600000055161/newbits/kernel/USRSRC/i8086/drv/st.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * This is a driver for the
 * Archive SC-400 Series Tape Controller.
 */
#include	<sys/coherent.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/const.h>
#include	<sys/devices.h>
#include	<sys/inode.h>
#include 	<sys/mtioctl.h>
#include	<sys/sched.h>
#include	<sys/seg.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>

/*
 * Fixed parameters.
 */
#define	NCMDS	8			/* Max # chained commands */

/*
 * Configurable parameters
 */
int	STIRQ	= 3;			/* IRQ Level 3 */
int	STPORT	= 0x200;		/* I/O Port    */
int	STDMA	= 1;			/* DMA Channel */

#define	BIT(n)		(1 << (n))

/*
 * Forward referenced functions.
 */
void	stcache();
void	stflush();
void	stinvoke();
void	ststart();
void	stintr();
void	strecov();
void	stnext();
void	stdiag();
void	stspin();

/*
 * Driver configuration.
 */
int	stload();
int	stuload();
int	stopen();
int	stclose();
int	stread();
int	stwrite();
int	stioctl();
void	stwatch();
int	nulldev();
int	nonedev();

CON	stcon	= {
	DFCHR,				/* Flags	*/
	ST_MAJOR,				/* Major index	*/
	stopen,				/* Open		*/
	stclose,			/* Close	*/
	nonedev,			/* Block	*/
	stread,				/* Read		*/
	stwrite,			/* Write	*/
	stioctl,			/* Ioctl	*/
	nulldev,			/* Powerfail	*/
	stwatch,			/* Timeout	*/
	stload,				/* Load		*/
	stuload				/* Unload	*/
};

/*
 * I/O Port Addresses
 */
#define	DATA_REG	(STPORT+0)	/* Data register */
#define	CTRL_REG	(STPORT+1)	/* Control/Status register */
#define	DMAGO_REG	(STPORT+2)	/* DMA Go register */
#define	DMARST_REG	(STPORT+3)	/* DMA reset register */

/*
 * Control Register
 */
#define	CR_RSTSAC	BIT(7)		/* 1 -> reset control micro	*/
#define	CR_REQ		BIT(6)		/* 1 -> request to LSI chip	*/
#define	CR_IEN		BIT(5)		/* 1 -> enables interrupts	*/
#define	CR_DNIEN	BIT(4)		/* 1 -> enable DONE interrupts	*/

/*
 * Status Register
 */
#define	SR_IRQF		BIT(7)		/* 1 -> Interrupt Request Flag	*/
#define	SR_NRDY		BIT(6)		/* 0 -> Ready			*/
#define	SR_NEXC		BIT(5)		/* 0 -> Exception		*/
#define	SR_DONE		BIT(4)		/* 1 -> DMA Done		*/
#define	SR_TO_PC	BIT(3)		/* 1 -> Direction is to PC	*/

/*
 * Controller Commands.
 */
#define	CC_SELECT	0x01		/* Select Drive 0 		*/
#define	CC_LOCK		0x11		/* Select Drive 0 and Lock	*/
#define	CC_BOT		0x21		/* Rewind to beginning of tape	*/
#define	CC_ERASE	0x22		/* Completely erase cartridge	*/
#define	CC_TENSION	0x24		/* Wind tape to BOT, EOT, BOT	*/
#define	CC_AUTO		0x25		/* Select auto-initialization	*/
#define	CC_QIC11	0x26		/* Select QIC-11 media format	*/
#define	CC_QIC24	0x27		/* Select QIC-24 media format	*/
#define	CC_WRITE	0x40		/* Write to tape		*/
#define	CC_WFM		0x60		/* Write file mark		*/
#define	CC_READ		0x80		/* Read from tape		*/
#define	CC_RFM		0xA0		/* Skip past next file mark	*/
#define	CC_SENSE	0xC0		/* Read controller status	*/

/*
 * Sense Status Bytes 0 and 1.
 */
#define	SS0_FIL		BIT(0)		/* File Mark Detected		*/
#define	SS0_BNL		BIT(1)		/* Bad Block Not located	*/
#define	SS0_UDA		BIT(2)		/* Unrecoverable data error	*/
#define	SS0_EOM		BIT(3)		/* End of media			*/
#define	SS0_WRP		BIT(4)		/* Write Protected Cartridge	*/
#define	SS0_USL		BIT(5)		/* Unselected Drive		*/
#define	SS0_CNI		BIT(6)		/* Cartridge Not In Place	*/
#define	SS0_ERR		(SS0_BNL+SS0_UDA+SS0_USL+SS0_CNI)

#define	SS1_POR		BIT(0)		/* Power on Reset Occurred	*/
#define	SS1_BOM		BIT(3)		/* Beginning of media		*/
#define	SS1_MBD		BIT(4)		/* Marginal Block Detected	*/
#define	SS1_NDT		BIT(5)		/* No Data Detected		*/
#define	SS1_ILL		BIT(6)		/* Illegal Command		*/
#define	SS1_ERR		(SS1_NDT+SS1_ILL)

/*
 * Device States.
 */
#define	SDEAD	0		/* controller not found    */
#define	SIDLE	1		/* controller idle	   */
#define	SCMD	2		/* initiating command	   */
#define	SRUN	3		/* performing command	   */
#define	SRDWR	4		/* starting read/write	   */
#define	SBLOCK	5		/* performing read/write   */
#define	SBLEND	6		/* concluding block i/o	   */
#define	SSENSE	7		/* reading status bytes	   */
#define	SSDONE	8		/* concluding status sense */

/*
 * Driver State Information.
 */
struct st_s {
	int	st_state;
	int	st_mode;		/* IPR or IPW			*/
	int	st_iocmd;		/* CC_READ or CC_WRITE		*/
	int	st_cmd;			/* last command	executed	*/
	int	st_cmds[NCMDS];		/* list of chained commands	*/
	int	st_ncmds;		/* num of chained commands	*/
	int	st_iswr;
	int	st_wasio;
	int	st_iseof;
	int	st_error;
	paddr_t	st_paddr;
	fsize_t	st_resid;
	fsize_t	st_size;
	saddr_t	st_sel;
	SEG *	st_seg;
	char	st_status[6];
	int	st_nstat;
	int	st_rdys;		/* number of ready watchdogs	*/
	int	st_nlost;		/* number of lost interrupts	*/
} st;

/**
 *
 * void
 * stload()		-- initialize tape device
 *
 *	Action:	Reset tape controller and drive.
 *		Seize tape interrupt vector.
 *
 *	Note:	If the tape controller is present and operational,
 *		a interrupt will occur and set st.st_state to SIDLE.
 */
static
stload()
{
	/*
	 * Paranoia - Turn off DMA.
	 * Should already be turned off.
	 */
	dmaoff( STDMA );

	/*
	 * Reset tape controller and drive
	 */
	outb( CTRL_REG, CR_RSTSAC );

	/*
	 * Wait at least 25 microseconds
	 */
	stspin( 25 );

	/*
	 * Terminate reset condition
	 */
	outb( CTRL_REG, CR_IEN );

	/*
	 * Seize tape interrupt vector.
	 */
	setivec( STIRQ, &stintr );
}

/**
 *
 * stuload( dev )		-- Unload tape device.
 * dev_t dev;
 */
stuload( dev )
dev_t dev;
{
	/*
	 * Turn off DMA.
	 */
	dmaoff( STDMA );

	/*
	 * Release tape interrupt vector.
	 */
	clrivec( STIRQ );

	/*
	 * Disable tape interrupts.
	 */
	outb( CTRL_REG, 0 );
}

/**
 *
 * stopen( dev, mode )		-- open tape device
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev  = tape device to be opened.
 *		mode = desired access mode.
 *
 *	Action:	Refuse access if tape drive does not exist or is in use.
 *		Refuse simultaneous read and write access.
 *		Refuse access if cartridge is not inserted in tape drive.
 *		Refuse write access to a write protected cartridge.
 *		Allocate tape cache.
 *		Initialize device state.
 *		Lock tape cartridge.
 */
static
stopen( dev, mode )
register dev_t	dev;
register int	mode;
{
	int s;

	/*
	 * Refuse access if no tape drive.
	 */
	if ( st.st_state == SDEAD ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Refuse access if tape drive is already open.
	 */
	if ( st.st_mode != 0 ) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Access must be read-only or write-only.
	 */
	if ( (mode != IPR) && (mode != IPW) ) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * Wait for tape drive to become idle.
	 */
	if ( stwait() < 0 ) {
		u.u_error = EINTR;
		return;
	}

	/*
	 * Initialize tape interface.
	 */
	s = sphi();
	outb( DMARST_REG, 0 );
	outb( CTRL_REG, CR_IEN );
	spl( s );

	/*
	 * Obtain tape status.
	 */
	stinvoke( CC_SENSE );

	/*
	 * Wait for tape status.
	 */
	if ( stwait() < 0 ) {
		u.u_error = EINTR;
		return;
	}

	/*
	 * Refuse access if no cartridge.
	 */
	if ( st.st_status[0] & (SS0_CNI|SS0_USL) ) {
		u.u_error = EDATTN;
		return;
	}

	/*
	 * Refuse write access to a write protected cartridge.
	 */
	if ( (mode == IPW) && (st.st_status[0] & SS0_WRP) ) {
		u.u_error = EROFS;
		return;
	}

	/*
	 * Calculate desired cache size in Kbytes.
	 */
	st.st_size = minor(dev) & ~0x80;
	if ( st.st_size == 0 )
		st.st_size = 256;

	/*
	 * Allocate cache
	 */
	for ( st.st_size *= 1024; st.st_size != 0; st.st_size -= 1024 )
		if ( st.st_seg = salloc( st.st_size, SFSYST|SFNSWP|SFNCLR ) )
			break;

	/*
	 * Refuse access if couldn't allocate cache.
	 */
	if ( st.st_seg == 0 ) {
		u.u_error = ENOMEM;
		return;
	};

	/*
	 * Initialize device state.
	 */
	st.st_sel   = FP_SEL(st.st_seg->s_faddr);
	st.st_iswr  = (mode == IPW);
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = (mode == IPW) ? st.st_size : 0 ;
	st.st_iocmd = (mode == IPW) ? CC_WRITE : CC_READ ;
	st.st_mode  = mode;
	st.st_iseof = 0;
	st.st_wasio = 0;
	st.st_error = 0;
	st.st_rdys  = 0;
	st.st_nlost = 0;

	/*
	 * Lock cartridge if at beginning of media.
	 */
	if ( st.st_status[1] & SS1_BOM )
		stinvoke( CC_LOCK );
}

/**
 *
 * stclose( dev, mode )		-- close tape device
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev  = tape device to be closed.
 *		mode = access mode.
 *
 *	Action:	If access mode was for writing, flush the tape cache.
 *		If data was written to tape, write a file mark.
 *		If data was read from tape on the non rewinding device,
 *		read until end of file or an error is encountered.
 *		Rewind the tape if the rewinding device is open.
 *		Unlock the tape cartridge.
 *		Clear tape state and release tape cache memory.
 */
static
stclose( dev, mode )
register dev_t dev;
{
	/*
	 * Check if tape was opened for writing.
	 */
	if ( st.st_iswr ) {

		/*
		 * Flush the tape cache.
		 */
		stflush();

		/*
		 * Write a file mark if data was written to tape.
		 */
		if ( st.st_wasio )
			stinvoke( CC_WFM );
	}

	/*
	 * Check if non-rewinding device was opened for reading.
	 */
	else if ( st.st_wasio && (dev & 0x80 ) ) {

		/*
		 * Read file mark if not just past one.
		 */
		if ( (st.st_status[0] & SS0_FIL) == 0 )
			stinvoke( CC_RFM );
	}

	/*
	 * Rewinding device.
	 */
	if ( (dev & 0x80) == 0 ) {

		/*
		 * Wait for controller to idle.
		 */
		while ( stwait() < 0 )
			;

		/*
		 * Initiate rewind.
		 */
		stinvoke( CC_BOT   );

		/*
		 * Unlock the drive [turn off the light].
		 */
		stinvoke( CC_SELECT );
	}

	/*
	 * Clear tape state, releasing tape cache.
	 */
	sfree( st.st_seg );
	st.st_seg  = 0;
	st.st_mode = 0;
}

/**
 *
 * stread( dev, iop )	-- tape device read
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = tape device to be read from.
 *		iop = pointer to IO structure.
 *
 *	Action:	Transfer data from tape cache to user memory,
 *		filling the cache as required by initiating reads from tape.
 */

static
stread( dev, iop )
dev_t	dev;
register IO * iop;
{
	register int n;
	register int ioc;

	ioc = iop->io_ioc;
	
	while ( iop->io_ioc > 0 ) {

		/*
		 * Check for empty cache.
		 */
		while ( st.st_resid == 0 ) {

			/*
			 * Special handling if end of file was encountered.
			 */
			if ( st.st_iseof ) {

				/*
				 * Clear EOF if no data was transferred yet.
				 */
				if ( ioc == iop->io_ioc )
					st.st_iseof = 0;

				return;
			}

			/*
			 * Abort on I/O error.
			 */
			if ( u.u_error = st.st_error ) {
				stdiag();
				return;
			}

			/*
			 * Fill the cache from tape.
			 */
			stcache();
		}

		/*
		 * Determine max data transferable in one chunk.
		 */
		n = iop->io_ioc;
		if ( n > st.st_resid )
			n = st.st_resid;

		/*
		 * Transfer some data from cache to user memory.
		 */
		if ( pucopy( st.st_paddr, iop->io_base, n ) != n )
			return;

		/*
		 * Update addresses and counts.
		 */
		iop->io_base += n;
		iop->io_ioc  -= n;
		st.st_resid  -= n;
		st.st_paddr  += n;
	}
}

/**
 *
 * stwrite( dev, iop )	-- write to tape device
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = tape device to be written to.
 *		iop = pointer to IO structure.
 *
 *	Action:	Transfer data from user memory to tape cache,
 *		flushing the cache as required by initiating writes to tape.
 */

static
stwrite( dev, iop )
dev_t	dev;
register IO *iop;
{
	register int n;

	while ( iop->io_ioc > 0 ) {

		/*
		 * Determine max data transferable in one chunk.
		 */
		n = iop->io_ioc;
		if ( n > st.st_resid )
			n = st.st_resid;

		/*
		 * Transfer some data from user memory to cache.
		 */
		if ( upcopy( iop->io_base, st.st_paddr, n ) != n )
			break;

		/*
		 * Update addresses and counts.
		 */
		iop->io_base += n;
		iop->io_ioc  -= n;
		st.st_paddr  += n;
		st.st_resid  -= n;

		/*
		 * Flush the cache to tape if full.
		 */
		if ( st.st_resid == 0 )
			stflush();

		/*
		 * Abort on I/O error.
		 */
		if ( u.u_error = st.st_error ) {
			stdiag();
			return;
		}
	}
}

/**
 *
 * stioctl( dev, cmd, arg )	-- service tape I/O control requests
 * int dev;
 * int cmd;
 * int arg;
 *
 *	Input:	dev = tape device to be serviced
 *		cmd = ioctl command
 *		arg = argument to ioctl command
 *
 *	Action:	Service tape I/O control request.
 */

static
stioctl( dev, cmd, arg )
{
	if ( st.st_iswr )
		stflush();

	st.st_error = EINVAL;

	switch ( cmd ) {

	case MTERASE:
		stinvoke( CC_ERASE );
		break;

	case MTTENSE:
		stinvoke( CC_TENSION );
		break;

	case MTREWIND:
		if ( st.st_iswr && st.st_wasio ) {
			stinvoke( CC_WFM );
			st.st_wasio = 0;
		}
		stinvoke( CC_BOT );
		break;

	case MTWEOF:
		if ( st.st_iswr ) {
			stinvoke( CC_WFM );
			st.st_wasio = 0;
		}
		break;

	case MTFSKIP:
		if ( ! st.st_iswr ) {
			if ( ! st.st_iseof )
				stinvoke( CC_RFM );
			st.st_iseof = 0;
			st.st_resid = 0;
		}
		break;
	}

	/*
	 * Record tape error code.
	 */
	u.u_error = st.st_error;
}

/**
 *
 * void
 * stcache()	-- read from tape into cache
 *
 *	Action:	Read as much data as possible into the tape cache.
 *		Set st.st_paddr to the cache address.
 *		Set st.st_resid to the number of data bytes in the cache.
 */
static void
stcache()
{
	/*
	 * Try to fill cache from tape.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size;
	ststart();

	/*
	 * Update cache information.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size - st.st_resid;

	/*
	 * Clear the cache on I/O error.
	 */
	if ( st.st_error )
		st.st_resid = 0;
}

/**
 *
 * void
 * stflush()	-- flush cache to tape
 *
 *	Action:	Ensure tape cache is block aligned.
 *		Write cache to the tape.
 *		Set st.st_paddr to the cache address.
 *		Set st.st_resid to the number of cache bytes available.
 */
static void
stflush()
{
	static char zc;

	/*
	 * Check for empty cache.
	 */
	if ( st.st_resid == st.st_size )
		return;

	/*
	 * Block align the cache.
	 */
	while ( st.st_resid % BSIZE ) {
		kpcopy( &zc, st.st_paddr, 1 );
		st.st_paddr++;
		st.st_resid--;
	}

	/*
	 * Flush the cache to tape.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size - st.st_resid;
	ststart();

	/*
	 * Update cache information.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size;
}

/**
 *
 * void
 * stinvoke()	-- start tape control operation
 *
 *	Action:	Initiate tape control operation.
 */
static void
stinvoke( cmd )
int cmd;
{
	register int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Wait for controller to become idle.
	 */
	while ( st.st_state != SIDLE ) {

		/*
		 * Create chained command if possible.
		 */
		if ( st.st_ncmds < NCMDS ) {
			st.st_cmds[ st.st_ncmds++ ] = cmd;
			spl( s );
			return;
		}

		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
	}

	/*
	 * Setup for tape operation.
	 */
	drvl[ST_MAJOR].d_time = 1;
	st.st_state = SCMD;
	st.st_error = 0;
	st.st_rdys  = 0;
	stspin( 100 );

	/*
	 * Request tape operation.
	 * Do NOT wait for results.
	 */
	outb( DATA_REG, st.st_cmd = cmd );
	outb( CTRL_REG, CR_IEN+CR_REQ );

	/*
	 * Enable interrupts.
	 */
	spl( s );
}

/**
 *
 * void
 * ststart()	-- start tape read/write operation
 *
 *	Action:	Initiate tape read/write operation.
 *		Wait for tape operation to complete.
 */
static void
ststart()
{
	register int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Wait for controller to become idle.
	 */
	while ( st.st_state != SIDLE )
		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );

	/*
	 * Setup for tape read/write.
	 */
	drvl[ST_MAJOR].d_time = 1;
	st.st_state = SRDWR;
	st.st_error = 0;
	st.st_rdys  = 0;
	stspin( 100 );

	/*
	 * Tape read/write was last command executed.
	 */
	if ( st.st_cmd == st.st_iocmd ) {
		/*
		 * Resume tape i/o operation.
		 * Simulate RDY interrupt.
		 */
		stintr();
	}
	else {
		/*
		 * Request tape operation.
		 */
		outb( DATA_REG, st.st_cmd = st.st_iocmd );
		outb( CTRL_REG, CR_IEN+CR_REQ );
	}

	/*
	 * Wait for tape operation to complete.
	 */
	while ( st.st_state != SIDLE )
		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );

	/*
	 * Enable interrupts.
	 */
	spl( s );
}

/**
 *
 * void
 * stintr()	-- tape interrupt handler
 *
 *	Action:	Service tape interrupts.
 *		Perform transitions to new tape states.
 *		Wake sleeping processes if appropriate.
 */
static void
stintr()
{
	register int csr;
	register int s;

	s   = sphi();
	csr = inb( CTRL_REG );

	/*
	 * Initiate exception recovery.
	 */
	if ( (csr & SR_NEXC) == 0 ) {
		strecov();
		spl( s );
		return;
	}

	/*
	 * Clear ready watchdog count.
	 */
	st.st_rdys = 0;

	/*
	 * Process normal operations.
	 */
	switch ( st.st_state ) {

	case SCMD:
		/*
		 * Command has been acknowledged.
		 * Wait for command completion.
		 */
		outb( CTRL_REG, CR_IEN );
 		st.st_state = (st.st_cmd == CC_SENSE) ? SSENSE : SRUN;
 		st.st_nstat = 0;
		break;

	case SRUN:
		/*
		 * Command has completed.
		 * Chain a sense status command if no other chained commands.
		 */
		if ( st.st_ncmds == 0 )
			st.st_cmds[ st.st_ncmds++ ] = CC_SENSE;

		/*
		 * Initiate next chained command.
		 */
		stnext();
		break;

	case SRDWR:
		/*
		 * Read/Write command had been acknowledged.
		 * Clear tape request, enable done interrupt.
		 */
		outb( CTRL_REG, CR_IEN+CR_DNIEN );

		/*
		 * Define direct memory access parameters.
		 */
		dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr );

		/*
		 * If tape read command, wait for interface to switch direction
		 */
		if ( st.st_iocmd == CC_READ )
			while ( (inb(CTRL_REG) & SR_TO_PC) != SR_TO_PC )
				;

		/*
		 * Enable DMA transfer on tape interface and at DMA controller chip.
		 */
		st.st_state = SBLOCK;
		outb( DMAGO_REG, 0 );
		dmago( STDMA );
		break;

	case SBLOCK:
		/*
		 * Perform Block I/O.
		 * Ignore RDY interrupt, wait for [DMA] DONE interrupt.
		 */
		if ( (csr & SR_DONE) == 0 )
			break;

		/*
		 * Turn off DMA.
		 */
		dmaoff( STDMA );

		/*
		 * If more data remains to be transferred, reenable DMA.
		 * NOTE: do -= BEFORE if() to avoid potential compiler bug.
		 */
		st.st_resid -= BSIZE;
		if ( st.st_resid > 0 ) {
			st.st_paddr += BSIZE;
			dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr );
			outb( DMAGO_REG, 0 );
			dmago( STDMA );
			break;
		}

		/*
		 * Disable done interrupt.
		 * Wait for I/O completion.
		 */
		outb( CTRL_REG, CR_IEN );
		st.st_state = SBLEND;
		break;

	case SBLEND:
		/*
		 * Completion of Block I/O.
		 * Clear the file mark and beginning of media indicators.
		 * Record the fact that data has been transferred.
		 */
		st.st_status[0] &= ~SS0_FIL;
		st.st_status[1] &= ~SS1_BOM;
		st.st_wasio = 1;
		stnext();
		break;

	case SSENSE:
		/*
		 * Sense Status Byte.
		 * Wait for availability.
		 */
		do {
			csr = inb(CTRL_REG) & (SR_NRDY|SR_TO_PC);
		} while ( csr != SR_TO_PC );

		/*
		 * Save status byte.
		 */
		st.st_status[st.st_nstat] = inb(DATA_REG);

		/*
		 * Acknowledge reception.
		 * CR_REQ must be present for at least 20 microseconds.
		 */
		outb( CTRL_REG, CR_IEN+CR_REQ );
		stspin( 20 );
		outb( CTRL_REG, CR_IEN );

		/*
		 * Change state to status completion if all bytes saved.
		 */
		if ( ++(st.st_nstat) == 6 )
			st.st_state = SSDONE;
		break;

	case SSDONE:
		/*
		 * Completion of Sense Status Command.
		 * Check for file mark.
		 */
		if ( st.st_status[0] & SS0_FIL ) {
			outb( DMARST_REG, 0 );
			st.st_iseof = 1;
		}

		/*
		 * Check for I/O error.
		 */
		else if ( (st.st_status[0] & SS0_ERR) ||
			  (st.st_status[1] & SS1_ERR) ) {
			st.st_error = EIO;
		}

		/*
		 * Check for write protected cartridge.
		 */
		else if ( (st.st_iocmd == CC_WRITE) &&
			  (st.st_status[0] & SS0_WRP) ) {
			st.st_error = EROFS;
		}

		stnext();
		break;
	}

	spl( s );
}

/**
 *
 * void
 * strecov()	-- initiate recovery from exception conditions
 *
 *	Action:	Invoked when the tape controller asserts EXCEPTION.
 *		A sense status command is initiated to clear the exception.
 */
static void
strecov()
{
	/*
	 * Ensure tape interface is idle.
	 */
	outb( CTRL_REG, CR_IEN );
	stspin( 100 );

	/*
	 * Turn off DMA on read/write exception.
	 */
	if ( st.st_cmd == st.st_iocmd )
		dmaoff( STDMA );

	/*
	 * Initiate sense status command.
	 */
	outb( DATA_REG, st.st_cmd = CC_SENSE );
	outb( CTRL_REG, CR_IEN+CR_REQ );
	drvl[ST_MAJOR].d_time = 1;
	st.st_state = SCMD;
	st.st_error = 0;
	st.st_rdys  = 0;
}

/**
 *
 * static void
 * stnext()	-- initiate next chained command.
 */
static void
stnext()
{
	/*
	 * Ensure tape interface is idle.
	 */
	outb( CTRL_REG, CR_IEN );
	drvl[ST_MAJOR].d_time = 0;
	st.st_state = SIDLE;
	stspin( 100 );

	/*
	 * Initiate a chained command.
	 */
	if ( st.st_ncmds ) {
		outb( DATA_REG, st.st_cmd = st.st_cmds[ --st.st_ncmds ] );
		outb( CTRL_REG, CR_IEN+CR_REQ );
		drvl[ST_MAJOR].d_time = 1;
		st.st_state = SCMD;
		st.st_error = 0;
		st.st_rdys  = 0;
		return;
	}

	/*
	 * Wake waiting processes.
	 */
	wakeup( &st );
}

/**
 *
 * void
 * stwatch()	-- periodic [1 sec] watchdog
 *
 *	Action:	If an exception condition exists, initate recovery actions.
 *		If ready condition exists for 1-2 seconds, simulate interrupt.
 *
 *	Notes:	If an exception condition occurs after a ready interrupt has
 *		been serviced, but before the ready condition is cleared,
 *		the exception interrupt will not occur, and is simulated here.
 */
static void
stwatch()
{
	register int csr;
	register int s;

	/*
	 * Disable interrupts, preventing critical race with stintr().
	 */
	s   = sphi();
	csr = inb(CTRL_REG);

	/*
	 * Initiate recovery from exception conditions.
	 */
	if ( (csr & SR_NEXC) == 0 )
		strecov();

	/*
	 * Reset ready watchdog if not ready.
	 */
	else if ( csr & SR_NRDY ) 
		st.st_rdys = 0;

	/*
	 * Simulate lost ready interrupts after 2 seconds.
	 */
	else if ( ++st.st_rdys >= 2 )
		stintr();

	/*
	 * Enable interrupts.
	 */
	spl( s );
}

/**
 * 
 * void
 * stdiag()	- Report tape status.
 *
 *	Action:	Identify and report the highest priority tape error.
 *		There will normally only be one valid error present.
 *		The USL error can invalidate most remaining flags.
 *		The CNI error can invalidate cartridge related flags.
 *
 *	Notes:	Never called from interrupt level, but always from background.
 */
static void
stdiag()
{
	if ( st.st_status[0] & SS0_USL )
		printf( "st: Unselected Drive\n" );

	else if ( st.st_status[0] & SS0_CNI )
		printf( "st: Cartridge missing\n" );

	else if ( st.st_status[1] & SS1_NDT )
		printf( "st: No data detected\n" );

	else if ( st.st_status[0] & SS0_BNL )
		printf( "st: Bad block not located\n" );

	else if ( st.st_status[0] & SS0_UDA )
		printf( "st: Unrecoverable data error\n" );

	else if ( st.st_status[1] & SS1_ILL )
		printf( "st: Illegal command\n" );

	else
		printf( "st: %x\n", (st.st_status[1] << 8) + st.st_status[0] );
}

/**
 *
 * int
 * stwait()	-- wait for tape controller to idle.
 *
 *	Return:	0  = tape controller idle.
 *		-1 = signal received.
 */
static int
stwait()
{
	int s;

	s = sphi();
	while ( st.st_state != SIDLE ) {

		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );

		if ( SELF->p_ssig ) {
			spl( s );
			return -1;
		}
	}
	spl( s );

	return 0;
}

/**
 *
 * void
 * stspin( usec )	-- delay execution
 * int usec;
 *
 *	Input:	usec = number of micro-seconds to delay.
 *
 *	Action:	Wait at least 'usec' micro-seconds.
 *
 *	Notes:	Provides minimum delay required at times by tape controller.
 *		Should function properly up to at least 16 Mhz system clock.
 */

static void
stspin( usec )
register int usec;
{
	while ( --usec >= 0 )
		;
}
0707070064030150061006440000030000030000011777770507310644500005400000000634/newbits/kernel/USRSRC/i8086/drv/template.c/*
 * File:
 *
 * Purpose:
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2  91/06/20  14:55:08  bin
 * update provided by hal
 * 
 */

/*
 * Includes.
 */

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
0707070064030150051004440000030000030000011777770507310644500004600000064442/newbits/kernel/USRSRC/i8086/drv/tn.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Tiac ARCNET PC-234 Device Driver
 *
 * True support for up to 4 network cards through minor devices 0-3.
 * Up to 4 protocols now supported.  Novell access is through normal
 * minor device.  Netbios access is through novell minor device + 16.
 */

#include <sys/coherent.h>
#include <sys/con.h>
#include <sys/devices.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/tnioctl.h>
#include <errno.h>

/*
 * External functions.
 */
extern int  wakeup();
extern void pollwake();
extern void defer();

/*
 * Driver functions.
 */
void	tnopen();
void	tnclose();
int	tnread();
int	tnwrite();
int	tnioctl();
void	tncycle();
void	tnload();
void	tnuload();
int	tnpoll();
int 	nonedev();
int	nulldev();
void	tn0intr();
void	tn1intr();
void	tn2intr();
void	tn3intr();
void	tnintr();

/*
 * Driver Configuration.
 */
CON
tncon = {
	DFCHR|DFPOL,			/* Flags	*/
	TN_MAJOR,			/* Major Index	*/
	tnopen,				/* Open		*/
	tnclose,			/* Close	*/
	nonedev,			/* Block	*/
	tnread,				/* Read		*/
	tnwrite,			/* Write	*/
	tnioctl,			/* Ioctl	*/
	nulldev,			/* Power fail	*/
	tncycle,			/* Timeout	*/
	tnload,				/* Load		*/
	tnuload,			/* Unload	*/
	tnpoll				/* Poll		*/
};

/*
 * Interrupt Entry Points.
 */
void (*tnintf[4])() = {
	tn0intr,
	tn1intr,
	tn2intr,
	tn3intr
};

#define	BIT(n)		(1 << (n))

/*
 * Bitmask, indexed by bit numbers 0..7.
 */
static unsigned char bitm[8] = { BIT(0), BIT(1), BIT(2), BIT(3),
				 BIT(4), BIT(5), BIT(6), BIT(7) };

/*
 * Patchable parameters - Cards 0-3.
 */
		/* Card    0       1       2      3  */
int	TNIRQ [4] = {      2,      7,      4,      0 };
saddr_t	TNSEL [4] = { 0xD000, 0x0000, 0x0000, 0x0000 };
int	TNPORT[4] = {  0x2E0,  0x220,  0x240,  0x000 };

/*
 * Patchable parameters - Prefix Byte.
 * Indexed by high nibble of minor device.
 */
int	TNPREFIX[4] = { 0x00,   0xF3,   0x00,   0x00 };

/*
 * Patchable variables.
 * TNTIME = Transmit watchdog timer in seconds.
 */
int TNTIME = 5;

/*
 * Register addresses.
 */
#define	NIR		(tp->tnport)	/* Network Interrupt Mask Reg (w)  */
#define	NSR		(tp->tnport)	/* Network Status Register    (r)  */
#define	NCR		(tp->tnport+1)	/* Network Command Register   (w)  */
#define	NZR		(tp->tnport+8)	/* Network Zap (reset) Reg    (w)  */

/*
 * Network Interrupt Register (NIR).
 */
#define	NI_Tx		BIT(0)		/* Enable Transmitter Avail Intr   */
#define	NI_RECON	BIT(2)		/* Enable Reconfiguration   Intr   */
#define	NI_Rx		BIT(7)		/* Enable Receiver Full     Intr   */

/*
 * Network Status Register (NSR).
 */
#define	NS_TxRDY	BIT(0)		/* Transmitter Available	   */
#define	NS_TxACK	BIT(1)		/* Transmit Message Acknowledged   */
#define	NS_RECON	BIT(2)		/* Network Reconfiguration	   */
#define	NS_TEST		BIT(3)		/* Test				   */
#define	NS_POR		BIT(4)		/* Power on Reset		   */
#define	NS_ETS1		BIT(5)		/* Extended Timeout Status 1	   */
#define	NS_ETS2		BIT(6)		/* Extended Timeout Status 2	   */
#define	NS_RxRDY	BIT(7)		/* Packet Received - Receiver Off  */

/*
 * Network Command Register (NCR).
 */
#define	NC_TxDIS	(((0)<<3) + 1)	/* Disable Transmitter		   */
#define	NC_RxDIS	(((0)<<3) + 2)	/* Disable Receiver		   */
#define	NC_TxENA(n)	(((n)<<3) + 3)	/* Enable Transmitter on Page n	   */
#define	NC_RxENA(n)	(((n)<<3)+0x84)	/* Enable Receiver    on Page n    */
#define	NC_DFC		(((1)<<3) + 5)	/* Define Configuration (2k buf)   */
#define	NC_POR		(((1)<<3) + 6)	/* Clear NS_POR flag		   */
#define	NC_RECON	(((2)<<3) + 6)	/* Clear NS_RECON flag		   */

/*
 * Packet Control.
 */
struct tnet_s {

	/*
	 * Four buffers per card - 2 receive, 2 transmit.
	 */
	struct tnbuf_s {		/* tnget*,tnput* use tn_sel:tn_off */
		unsigned	tn_off;	/* tn_sel:tn_off  = current byte   */
		saddr_t		tn_sel;	/* network buffer selector	   */
		struct tnbuf_s *tn_next;/* pointer to next pkt in queue	   */
		unsigned	tn_ena;	/* Command to enable packet	   */
		unsigned	tn_base;/* tn_sel:tn_base = pkt address	   */
		unsigned	tn_xnid;/* Transmit node id		   */
		unsigned	tn_xlen;/* Transmit length		   */
	} tnbuf [4];

	struct tnbuf_s *	RxBusy[4];/* Queues of full receive packets*/
	struct tnbuf_s *	RxIdle;	/* Queue of empty receive packets  */

	struct tnbuf_s *	TxBusy;	/* Queue of full transmit packets  */
	struct tnbuf_s *	TxIdle;	/* Queue of empty transmit packets */

	event_t			RxPoll[4];/* Polls for input packets	   */
	event_t			TxPoll;	/* Polls for empty output packets  */

	char			RxReq[4];/* 1 = Proc waiting for recv buf  */
	char			TxReq;	/* 1 = Proc waiting for xmit buf   */
	char			refc[4];/* # opens, indexed by prefix code */

	unsigned		tnmask;	/* Interrupt enable mask	   */
	unsigned		tnport;	/* Base I/O port		   */
	char			tnaddr[8];/* ARC-NET Node ID, low byte 1st */

	unsigned		tntime;	/* transmit watchdog timer	   */
	unsigned		recon;	/* number of long reconfigurations */
	unsigned		pri;	/* priority event occurred	   */
	long			rbolt;	/* lbolt at last reconfiguration   */
	unsigned char		bad[32];/* bit mask of bad nodes	   */
	unsigned char		mod[32];/* bit mask of changed nodes	   */
	long			recons;	/* reconfiguration statistic	   */
	SEG *			statseg;/* Segment containing stats	   */

} tnet [4];

/*
 * Load Routine.
 */
void
tnload()
{
	register struct tnet_s  * tp;
	register struct tnbuf_s * np;
	faddr_t faddr;
	paddr_t paddr;
	int i;
	int nid;
	long delay;

	for ( tp = &tnet[0], i = 0; i < 4; i++, tp++ ) {

		/*
		 * Validate patchable parameters.
		 */
		if ( (TNSEL[i] == 0) || (TNPORT[i] == 0) || (TNIRQ[i] == 0) ) {
			TNPORT[i] = 0;
			TNSEL[i]  = 0;
			TNIRQ[i]  = 0;
			continue;
		}

		tp->tnport = TNPORT[i];

		/*
		 * Clear Power-On-Reset Flag.
		 */
		outb( NCR, NC_POR );

		/*
		 * Validate card presence.
		 * NOTE: tp->tnport must be programmed before using NIR macro.
		 */
		if ( inb(NSR) & (NS_TEST|NS_POR) ) {
			tp->tnport = 0;
			continue;
		}

		/*
		 * Convert physical address into virtual address.
		 */
		paddr = TNSEL[i] << 4L;
		faddr = ptov( paddr, (fsize_t) 2048 );

		/*
		 * Verify dual-port memory existence.
		 * NOTE: Do not overwrite first two bytes [0xD1,nid].
		 */
		sfword( faddr+8, 0x1234 );
		if ( ffword( faddr+8 ) != 0x1234 ) {
			vrelse( faddr );
			tp->tnport = 0;
			continue;
		}

		/*
		 * Allocate statistics segment.
		 */
		tp->statseg = salloc( (fsize_t) (256*NTNST*4), SFSYST|SFHIGH );

		/*
		 * Out of memory.
		 */
		if ( ! tp->statseg ) {
			printf( "tn%d: out of memory\n", i );
			vrelse( faddr );
			tp->tnport = 0;
			continue;
		}

		tp->tnbuf[0].tn_sel =
		tp->tnbuf[1].tn_sel =
		tp->tnbuf[2].tn_sel =
		tp->tnbuf[3].tn_sel = FP_SEL(faddr);

		tp->tnbuf[0].tn_ena  = NC_TxENA(0);
		tp->tnbuf[1].tn_ena  = NC_TxENA(1);
		tp->tnbuf[2].tn_ena  = NC_RxENA(2);
		tp->tnbuf[3].tn_ena  = NC_RxENA(3);

		tp->tnbuf[0].tn_base = 0 * 512;
		tp->tnbuf[1].tn_base = 1 * 512;
		tp->tnbuf[2].tn_base = 2 * 512;
		tp->tnbuf[3].tn_base = 3 * 512;

		/*
		 * Initialize transmit idle queue.
		 */
		tp->TxIdle		= &tp->tnbuf[0];
		tp->tnbuf[0].tn_next	= &tp->tnbuf[1];

		/*
		 * Initialize receive idle queue.
		 */
		tp->RxIdle		= &tp->tnbuf[2];
		tp->tnbuf[2].tn_next	= &tp->tnbuf[3];

		/*
		 * Validate Node Id.
		 */
		np = &tp->tnbuf[0];
		np->tn_off = 0;
		if ( tngetc(np) != 0xD1 ) {

			/*
			 * Initiate Power On Reset.
			 */
			outb( NZR, 1 );

			/*
			 * Wait minimimum of 180 [suggest 250] milli-seconds.
			 * Should function properly up to at least 16 Mhz clock.
			 */
			for ( delay = 250000L; --delay != 0; )
				;
		}

		/*
		 * Validate and Remember Node Id.
		 */
		np->tn_off = 0;
		if ( tngetc(np) == 0xD1 )
			tp->tnaddr[0] = tngetc( np );

		/*
		 * Record starting time of statistics collection.
		 */
		faddr = tp->statseg->s_faddr + TnELAPSED*4;
		for ( nid = 0; nid < 256; nid++, faddr += NTNST*4 )
			kfcopy( &lbolt, faddr, sizeof(lbolt) );

		memset( tp->bad, -1, 32 );	/* Assume LAN is down	   */
		memset( tp->mod,  0, 32 );	/* Assume no node changes  */
		tp->tnmask = NI_Rx | NI_RECON;	/* Interrupts to enable    */
		outb( NIR, 0 );			/* Disable Interrupts	   */
		outb( NCR, NC_POR );		/* Clear POR Flag	   */
		outb( NCR, NC_DFC );		/* Define 2K buf config	   */
		outb( NCR, NC_TxDIS );		/* Disable Transmitter	   */
		outb( NCR, tp->RxIdle->tn_ena);	/* Enable receiver	   */
		setivec( TNIRQ[i], tnintf[i] );	/* Seize Interrupt Vector  */
		outb( NIR, tp->tnmask );	/* Enable Interrupts       */
	}

	/*
	 * Enable watchdog timer
	 */
	drvl[TN_MAJOR].d_time = 1;
}

/*
 * Unload Routine.
 */
void
tnuload( dev )
dev_t dev;
{
	register struct tnet_s  * tp;
	register int i;
	faddr_t faddr;

	/*
	 * Disable watchdog timer.
	 */
	drvl[TN_MAJOR].d_time = 0;

	/*
	 * Scan network adaptors.
	 */
	for ( tp = &tnet[0], i = 0; i < 4; i++, tp++ ) {

		if ( tp->tnport == 0 )
			continue;

		/*
		 * Disable Interrupts
		 */
		outb( NIR, 0 );

		/*
		 * Release interrupt vector.
		 */
		clrivec( TNIRQ[i] );

		/*
		 * Release virtual address AFTER disabling interrupts.
		 */
		if ( FP_SEL(faddr) = tp->tnbuf[0].tn_sel )
			vrelse( faddr );

		/*
		 * Release stats segment.
		 */
		if ( tp->statseg != NULL )
			sfree( tp->statseg );
	}
}

/*
 * Open Routine.
 *
 *	Low nibble  of minor device is card identifier 0 to 3.
 *	High nibble of minor device is code identifier 0 to 3.
 */
void
tnopen( dev, mode )
dev_t dev;
{
	register struct tnet_s * tp;
	int card = (dev & 0x0F);
	int code = (dev & 0xF0) >> 4;

	/*
	 * Validate minor device and card existence.
	 */
	if ( (card > 3) || (code > 3) || (tnet[card].tnport == 0)) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Code identifiers 1 to 3 are only valid if a prefix code is known.
	 */
	if ( (code > 0) && (TNPREFIX[code] == 0) ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Access network information.
	 */
	tp = &tnet[card];

	/*
	 * Increment reference count (# opens).
	 */
	tp->refc[code]++;
}

/*
 * Close Routine.
 */
void
tnclose( dev )
dev_t dev;
{
	register struct tnet_s  * tp =tp = &tnet[ dev & 3];
	register struct tnbuf_s * np;
	int code = (dev & 0x30) >> 4;
	int s;

	/*
	 * Decrement reference count.
	 */
	if ( --tp->refc[code] != 0 )
		return;

	/*
	 * Last close.
	 * Release all queued packets.
	 */
	while ( np = tp->RxBusy[code] ) {
		s = sphi( );
		tp->RxBusy[code] = np->tn_next;
		tn_rxena( tp, np );
		spl( s );
	}
}

/*
 * Watchdog Timing Routine
 *
 *	If transmit has been enabled for 1-2 seconds:
 *		Abort transmission of packet, forcing interrupt.
 */
void
tncycle( )
{
	register struct tnet_s * tp;
	register int code;
	int s;

	/*
	 * Scan all network cards.
	 */
	for ( tp = &tnet[0]; tp <= &tnet[3]; tp++ ) {

		if ( ! tp->tnport )
			continue;

		/*
		 * Disable interrupts.
		 */
		s = sphi();

		/*
		 * Enable broadcasts after 5 seconds without reconfiguration.
		 */
		if ( (tp->recon > 0) && ((lbolt - tp->rbolt) > (5*HZ)) ) {
			/*
			 * LAN was previously down.
			 */
			if ( tp->bad[0] & 1 ) {
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnSTATMOD*4, 1 );
				tp->mod[0] |= 1;
				tp->pri = 1;
			}
			tp->bad[0] &= ~1;
			tp->recon   =  0;
		}

		/*
		 * Discard bad packet on transmit watchdog timeout.
		 */
		if ( (tp->tntime > 0) && (--(tp->tntime) == 0) )
			outb( NCR, NC_TxDIS );

		/*
		 * Enable interrupts.
		 */
		spl( s );

		/*
		 * LAN/DEVICE UP/DOWN event has occurred.
		 */
		if ( tp->pri == 1 ) {

			tp->pri = 2;

			for ( code = 0; code < 4; code++ )
				if ( tp->RxPoll[code].e_procp )
					pollwake( &tp->RxPoll[code] );
		}
	}
}

static
tnioctl( dev, com, arg )
dev_t dev;
int com;
register tnattr_t * arg;
{
	register struct tnet_s * tp = &tnet[dev & 3];
	faddr_t fp;
	int nid;
	long t;
	tnattr_t local;			/* to avoid fucopy() problems */

	switch ( com ) {

	case TNGETA:
	case TNGETAF:
		/*
		 * Access node statistics.
		 */
		nid = getubd( &arg->host[5] );
		fp  = tp->statseg->s_faddr + nid * (NTNST*4);

		/*
		 * Disable interrupts to avoid race condition with tnintr().
		 */
		sphi();

		/*
		 * Copy node status.
		 */
		if ( tp->bad[nid/8] & bitm[nid%8] )
			putubd( &arg->bad, 1 );
		else
			putubd( &arg->bad, 0 );

		/*
		 * Copy network reconfigurations to user space.
		 * NOTE: This is not a node statistic, but a network stat.
		 */
		kucopy( &tp->recons, &arg->recons, sizeof(tp->recons) );

		/*
		 * Copy node statistics to user space.
		 */
		fkcopy( fp, &local.stats[0], sizeof(local.stats) );
		kucopy( &local.stats[0], &arg->stats[0], sizeof(arg->stats) );

		/*
		 * Copy true elapsed time of statistics collection.
		 */
		fkcopy( fp+TnELAPSED*4, &t, sizeof(t) );
		t = lbolt - t;
		kucopy( &t, &arg->stats[TnELAPSED], sizeof(arg->stats[0]) );

		/*
		 * Clear node statistics.
		 * NOTE: Elapsed time statistic is time of last clear.
		 */
		if ( com == TNGETAF ) {
			fclear( fp, NTNST * 4 );
			kfcopy( &lbolt, fp+TnELAPSED*4, sizeof(lbolt) );
			if ( nid == 0 )
				tp->recons = 0;
		}

		/*
		 * Enable interrupts.
		 */
		splo();

		return( 0 );

	default:
		u.u_error = EINVAL;
	}
}

/*
 * Polling Routine.
 *
 *	Note:	Double-looks are performed to prevent critical race with
 *		interrupt handlers,  without having to disable interrupts.
 */
static
tnpoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	register struct tnet_s * tp = &tnet[dev & 3];
	int code = (dev & 0x30) >> 4;
	int rev = 0;

	/*
	 * Fast check for priority, input, and output polls.
	 * Priority poll checks for LAN UP/DOWN transition.
	 * Input    poll checks for a full receive buffer.
	 * Output   poll checks for an empty transmit buffer, or LAN down.
	 */
	if ( (ev & POLLPRI) && (tp->pri != 0) )
		rev |= POLLPRI;
	if ( (ev & POLLIN) && (tp->RxBusy[code] != NULL) )
		rev |= POLLIN;
	if ( (ev & POLLOUT) && ((tp->TxIdle != 0) || (tp->bad[0] & 1)) )
		rev |= POLLOUT;

	/*
	 * Fast check found an event, or this is a non-blocking poll.
	 */
	if ( (rev != 0) || (msec == 0) )
		return( rev );

	/*
	 * Blocking Input poll.
	 */
	if ( ev & POLLIN ) {

		pollopen( &tp->RxPoll[code] );

		/*
		 * Second look to avoid interrupt race.
		 */
		if ( tp->RxBusy[code] )
			return( POLLIN );
	}

	/*
	 * Blocking Output poll.
	 */
	if ( ev & POLLOUT ) {

		pollopen( &tp->TxPoll );

		/*
		 * Second look to avoid interrupt race.
		 * NOTE: When the LAN is down broadcasts [nid 0] are disabled.
		 */
		if ( (tp->TxIdle != 0) || (tp->bad[0] & 1) )
			return( POLLOUT );
	}

	return( rev );
}

/*
 * Interrupt Entry Point - Card 0.
 */
void
tn0intr()
{
	tnintr( &tnet[0] );
}

/*
 * Interrupt Entry Point - Card 1.
 */
void
tn1intr()
{
	tnintr( &tnet[1] );
}

/*
 * Interrupt Entry Point - Card 2.
 */
void
tn2intr()
{
	tnintr( &tnet[2] );
}

/*
 * Interrupt Entry Point - Card 3.
 */
void
tn3intr()
{
	tnintr( &tnet[3] );
}

/*
 * Interrupt Handler.
 *
 *	Process transmit/receive interrupts.
 */
void
tnintr( tp )
register struct tnet_s * tp;
{
	register struct tnbuf_s * np;
	register int csr;
	int nid;
	int n;
	int bit;

	/*
	 * Read interrupt status.
	 * Disable interrupts to ensure edge occurs later.
	 */
	csr = inb( NSR );
	tp->tnmask = NI_RECON;
	outb( NIR, 0 );

	/*
	 * Reconfigurations with a period of 840 msec [600-1100]
	 * increment tp->recon.  Other periods clear tp->recon.
	 * After 5 reconfigurations at 840 msecs, the network is down.
	 * After 1 reconfiguration at another interval, the network is up.
	 * Network also comes up in tncycle() 5 seconds after last reconfig.
	 */
	if ( csr & NS_RECON ) {

		outb( NCR, NC_RECON );
		nid = (unsigned) (lbolt - tp->rbolt) * (1000/HZ);
		tp->rbolt = lbolt;
		tp->recons++;

		/*
		 * Not a chained reconfiguration.
		 * Assume the network is up.
		 * NOTE: Expect 840 msecs, but allow interrupt latency slip.
		 */
		if ( (nid < 700) || (nid > 1000) ) {
			if ( tp->bad[0] & 1 ) {
				tp->mod[0] |=  1;
				tp->bad[0] &= ~1;
				tp->pri = 1;
			}
			tp->recon   =  0;
		}

		/*
		 * Chained reconfiguration - threshold exceeded.
		 */
		else if ( (++(tp->recon) == 5) && ((tp->bad[0] & 1) == 0) ) {
			faddr_t fp = tp->statseg->s_faddr;
			aflong( fp+TnSTATMOD*4, 1 );
			memset( tp->bad, -1, sizeof(tp->bad) );
			tp->mod[0] |= 1;
			tp->pri = 1;
		}
	}

	/*
	 * Service Power on Resets.
	 */
	if ( csr & NS_POR ) {

		csr &= ~(NS_RxRDY|NS_TxRDY);	/* Ignore receive/transmit */
		outb( NCR, NC_DFC );		/* Define 2K buf config	   */
		outb( NCR, NC_POR );		/* Clear POR flag	   */

		/*
		 * Enable receiver
		 */
		if ( np = tp->RxIdle )
			outb( NCR, np->tn_ena );

		/*
		 * Enable transmitter
		 */
		if ( np = tp->TxBusy )
			outb( NCR, np->tn_ena );
	}

	/*
	 * Service transmit interupts if transmit is pending.
	 */
	if ( np = tp->TxBusy ) {

		tp->tnmask |= NI_Tx;

		/*
		 * Check for transmission completed.
		 */
		if ( csr & NS_TxRDY ) {

			/*
			 * Destination Node Id is in 2nd byte of packet.
			 */
			np->tn_off = np->tn_base + 1;
			nid = tngetc( np );

			/*
			 * Get length of short/long packets.
			 */
			n = 256 - tngetc(np);
			if ( n == 256 )
				n = 512 - tngetc(np);

			/*
			 * Transmitted packet was acknowledged.
			 */
			if ( csr & NS_TxACK ) {
				/*
				 * Adjust global and node statistics.
				 */
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnTxPACKS*4, 1 );
				aflong( fp+TnTxBYTES*4, n );
				fp += nid * (NTNST * 4);
				aflong( fp+TnTxPACKS*4, 1 );
				aflong( fp+TnTxBYTES*4, n );
			}

			/*
			 * Transmitted packet was discarded.
			 * NOTE: Do not flag broadcast [nid 0] as bad.
			 */
			else if ( nid != 0 ) {
				/*
				 * Adjust global and node statistics.
				 */
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnDISCARD*4, 1 );
				fp += nid * (NTNST * 4);
				aflong( fp+TnDISCARD*4, 1 );
				aflong( fp+TnSTATMOD*4, 1 );

				/*
				 * Flag node as being bad.
				 */
				bit = bitm[ nid % 8 ];
				tp->bad[ nid / 8 ] |= bit;
				tp->mod[ nid / 8 ] |= bit;
				tp->pri = 1;
			}

			/*
			 * Move packet buffer to idle transmit queue.
			 */
			tp->TxBusy  = np->tn_next;
			np->tn_next = tp->TxIdle;
			tp->TxIdle  = np;

			/*
			 * Check for another packet to transmit.
			 */
			if ( np = tp->TxBusy ) {

				/*
				 * Enable transmitter, start watchdog timer.
				 */
				outb( NCR, np->tn_ena );
				tp->tntime = TNTIME;
			}

			/*
			 * Disable Transmit Interrupt, clear watchdog timer.
			 */
			else {
				tp->tnmask &= ~NI_Tx;
				tp->tntime  =  0;
			}

			/*
			 * Wake processes waiting to transmit.
			 */
			if ( tp->TxReq ) {
				tp->TxReq = 0;
				defer( wakeup, &tp->TxReq );
			}

			if ( tp->TxPoll.e_procp )
				defer( pollwake, &tp->TxPoll );
		}
	}

	/*
	 * Check for receive request.
	 */
	if ( np = tp->RxIdle ) {

		tp->tnmask |= NI_Rx;

		/*
		 * Check for packet received.
		 */
		if ( csr & NS_RxRDY ) {

			/*
			 * Remove first packet from receive ready queue.
			 * Re-enable receiver or disable receive interrupts.
			 */
			if ( tp->RxIdle = np->tn_next ) {
				outb( NCR, np->tn_next->tn_ena );
				np->tn_next = 0;
			}
			else
				tp->tnmask &= ~NI_Rx;

			/*
			 * Source Node Id is in 1st byte of packet.
			 */
			np->tn_off = np->tn_base;
			nid = tngetc( np );

			/*
			 * Try to establish our Node Id if not already set.
			 * Destination Node Id (our station)
			 * is in 2nd byte of the received packet.
			 * NOTE: Always read node id byte.
			 *	 This ensures offset bytes can be read.
			 */
			if ( (n = tngetc(np)) && (tp->tnaddr[0] == 0) )
				tp->tnaddr[0] = n;

			/*
			 * Get offset to first data byte in short/long packet.
			 * Short packet offset is in 3rd byte of packet.
			 * Long  packet offset is in 4th byte of packet.
			 */
			if ( n = tngetc(np) )
				np->tn_off = np->tn_base + n;
			else
				np->tn_off = np->tn_base + tngetc(np);

			/*
			 * LAN has come up.
			 * Clear bad flag for the broadcast node.
			 */
			if ( tp->bad[0] & 1 ) {
				tp->bad[ 0 ] &= ~1;
				tp->mod[ 0 ] |=  1;
				tp->pri = 1;
			}

			/*
			 * Node has come up.
			 * Clear bad flag for the Source Node.
			 */
			bit = bitm[ nid % 8 ];
			if ( tp->bad[ nid / 8 ] & bit ) {
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnSTATMOD*4, 1 );
				fp += nid * (NTNST * 4);
				aflong( fp+TnSTATMOD*4, 1 );
				tp->bad[ nid / 8 ] &= ~bit;
				tp->mod[ nid / 8 ] |=  bit;
				tp->pri = 1;
			}

			/*
			 * Get first data byte from packet.
			 */
			bit = tngetc( np );

			/*
			 * Determine prefix code associated with packet.
			 */
			for ( n = 3; n > 0; n-- ) {
				if ( TNPREFIX[n] == bit )
					break;
			}

			/*
			 * Interface is open.
			 */
			if ( tp->refc[n] ) {

				/*
				 * Append received packet to received queue.
				 * NOTE: At most 2 packets in any queue.
				 */
				if ( tp->RxBusy[n] )
					tp->RxBusy[n]->tn_next = np;
				else
					tp->RxBusy[n] = np;
	
				/*
				 * Wake processes waiting to read.
				 */
				if ( tp->RxReq[n] ) {
					tp->RxReq[n] = 0;
					defer( wakeup, &tp->RxReq[n] );
				}
	
				if ( tp->RxPoll[n].e_procp )
					defer( pollwake, &tp->RxPoll[n] );
			}

			/*
			 * Interface is closed.
			 * Return packet to end of receive idle queue.
			 */
			else
				tn_rxena( tp, np );
		}
	}

	/*
	 * Restore interrupt mask.
	 */
	outb( NIR, tp->tnmask );
}

/*
 * Read Routine.
 *
 *	Wait for a packet to be received.
 *	Transform packet header and copy packet body.
 *	Place packet buffer on receive idle queue.
 *	If receiver was inhibited, enable receiver.
 */


tnread ( dev, iop )

dev_t dev;
register IO * iop;

{
	register struct tnet_s  * tp = &tnet[ dev & 3 ];
	register struct tnbuf_s * np;
	int code = (dev & 0x30) >> 4;
	unsigned len;
	unsigned cnt;
	unsigned srcid;
	int s;

	/*
	 * Driver information requested.
	 */
	if ( iop->io_ioc <= 2 + sizeof(tp->bad) + sizeof(tp->mod) ) {

		/*
		 * Supply null byte, then our node id.
		 */
		ioputc( 0, iop );
		ioputc( tp->tnaddr[0], iop );

		/*
		 * Bad and modified node bit masks requested.
		 * Disable interrupts during transfer to prevent
		 * critical race with tnintr().
		 */
		if ( iop->io_ioc == sizeof(tp->bad) + sizeof(tp->mod) ) {
			sphi();
			iowrite( iop, tp->bad, sizeof(tp->bad) );
			iowrite( iop, tp->mod, sizeof(tp->mod) );
			kclear( tp->mod, sizeof(tp->mod) );
			tp->pri = 0;
			splo();
		}

		/*
		 * Bad node bit mask requested.
		 */
		else if ( iop->io_ioc == sizeof(tp->bad) )
			iowrite( iop, tp->bad, sizeof(tp->bad) );

		return;
	}

	/*
	 * Wait for packet reception.
	 */
	for ( ; ; ) {

		s = sphi( );

		/*
		 * Check for received packet.
		 */
		if ( np = tp->RxBusy[code] ) {
			tp->RxBusy[code] = np->tn_next;
			np->tn_next = 0;
			spl( s );
			break;
		}

		/*
		 * Non-blocking reads.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			spl( s );
			return;
		}

		tp->RxReq[code] = 1;

		sleep( &tp->RxReq[code], CVTTIN, IVTTIN, SVTTIN );
		spl( s );

		/*
		 * Check for pending signal.
		 */
		if ( nondsig() ) {
			u.u_error = EINTR;
			return;
		}
	}

	/*
	 * Copy source and destination node ids
	 */
	np->tn_off = np->tn_base;
	ioputc( srcid = tngetc(np), iop );
	ioputc( tngetc(np), iop );

	/*
	 * Check for short packet.
	 */
	if ( cnt = tngetc(np) ) {

		np->tn_off = np->tn_base + cnt;
		len = 256 - cnt;
	}

	/*
	 * Check for long packet.
	 */
	else if ( cnt = tngetc(np) ) {

		np->tn_off = np->tn_base + cnt;
		len = 512 - cnt;
	}

	/*
	 * Check for non-empty packet.
	 */
	if ( cnt != 0 ) {

		/*
		 * Truncate packet if necessary.
		 */
		if ( iop->io_ioc < len )
			len = iop->io_ioc;

		/*
		 * Copy packet body.
		 */
		tucopy( np, iop->io_base, len );
		iop->io_ioc  -= len;
		iop->io_base += len;
	}

	/*
	 * Adjust received data statistics.
	 */
	if ( tp->statseg != NULL ) {
		faddr_t fp = tp->statseg->s_faddr;
		aflong( fp+TnRxPACKS*4, 1 );
		aflong( fp+TnRxBYTES*4, len );
		fp += srcid * (NTNST * 4);
		aflong( fp+TnRxPACKS*4, 1 );
		aflong( fp+TnRxBYTES*4, len );
	}

	/*
	 * Enable packet reception with buffer.
	 */
	tn_rxena( tp, np );
}


/*
 * Write Routine.
 *
 *	Wait for a empty transmit buffer to become available.
 *	Format the buffer and place on transmit queue.
 *	If transmit queue was empty, start transmitter.
 */

tnwrite ( dev, iop )

dev_t dev;
register IO * iop;

{
	register struct tnet_s  * tp = &tnet[ dev & 3 ];
	register struct tnbuf_s * np;
	unsigned len, cnt;
	int dstid;
	int s;

	/*
	 * Validate size of write.
	 */
	if ( ( iop->io_ioc < 3 ) || ( iop->io_ioc > 510 ) ) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * Destination Node Id is 2nd byte of write.
	 */
	iogetc( iop );
	dstid = iogetc( iop );

	/*
	 * Wait for empty transmit buffer.
	 */
	for ( ; ; ) {

		/*
		 * If Destination Node appears bad, set errno to EDATTN.
		 */
		if ( tp->bad[ dstid / 8 ] & (1 << (dstid % 8)) ) {
			u.u_error = EDATTN;
			return;
		}

		s = sphi( );

		/*
		 * Check for empty transmit buffer.
		 */
		if ( np = tp->TxIdle ) {

			tp->TxIdle  = np->tn_next;
			np->tn_next = 0;
			spl( s );
			break;
		}

		/*
		 * Non-blocking writes.
		 */
		if ( iop->io_flag & IONDLY ) {
			/*
			 * Adjust delayed write stats.
			 */
			faddr_t fp = tp->statseg->s_faddr;
			aflong( fp+TnWRTDLYS*4, 1 );
			fp += dstid * (NTNST * 4);
			aflong( fp+TnWRTDLYS*4, 1 );

			u.u_error = EAGAIN;
			spl( s );
			return;
		}

		tp->TxReq = 1;
		sleep( &tp->TxReq, CVTTOUT, IVTTOUT, SVTTOUT );
		spl( s );

		/*
		 * Check for pending signal.
		 */
		if ( nondsig() ) {
			u.u_error = EINTR;
			return;
		}
	}

	/*
	 * Copy source and destination node ids
	 * NOTE: Hardware inserts source node id automatically.
	 */
	np->tn_off = np->tn_base;
	tnputc( np, 0 );
	tnputc( np, dstid );

	len = iop->io_ioc;

	/*
	 * Check for long packet.
	 */
	if ( len > 253 ) {
		tnputc( np, 0 );
		tnputc( np, cnt = 512 - len );
		np->tn_off = np->tn_base + cnt;
	}

	/*
	 * Short packet.
	 */
	else {
		tnputc( np, cnt = 256 - len );
		np->tn_off = np->tn_base + cnt;
	}

	/*
	 * Copy packet body.
	 */
	utcopy( iop->io_base, np, len );
	iop->io_base += len;
	iop->io_ioc  -= len;

	/*
	 * Record length in header structure.
	 */
	np->tn_xlen = iop->io_ioc;

	sphi();

	/*
	 * Put packet on transmit ready queue, prime transmitter if necessary.
	 */
	if ( ! tp->TxBusy ) {
		tp->TxBusy = np;
		outb( NCR, np->tn_ena );	 /* enable transmitter	*/
		outb( NIR, tp->tnmask |= NI_Tx); /* enable xmit intr	*/
		tp->tntime = TNTIME;		 /* restart watchdog	*/
	}
	else
		tp->TxBusy->tn_next = np;

	spl(s);
}

/*
 * Enable packet reception with buffer.
 */
tn_rxena( tp, np )
register struct tnet_s  * tp;
register struct tnbuf_s * np;
{
	int s;

	s = sphi( );

	/*
	 * Put packet on receive ready queue, prime receiver if necessary.
	 */
	if ( tp->RxIdle == NULL ) {
		tp->RxIdle = np;
		outb( NCR, np->tn_ena );
		outb( NIR, tp->tnmask |= NI_Rx );
	}
	else
		tp->RxIdle->tn_next = np;

	np->tn_next = 0;
	spl( s );
}

/*
 * Adjust far long.
 */
static
aflong( fp, i )
faddr_t fp;
int i;
{
	long lw;

	fkcopy( fp, &lw, sizeof(lw) );
	lw += i;
	kfcopy( &lw, fp, sizeof(lw) );
}
0707070064030150031004440000030000030000011777770507310645300005000000007023/newbits/kernel/USRSRC/i8086/drv/tnas.s/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ Tiac Network Assembler Support
/
/	tngetc( np )		-- get a character from a tiac network buffer
/	tnputc( np, c)		-- put a character into a tiac network buffer
/	tucopy( np, up, n)	-- copy n bytes from tiac buffer to user space
/	utcopy( up, np, n)	-- copy n bytes from user space to tiac buffer
/
////////

	.globl	tngetc_
	.globl	tnputc_
	.globl	tucopy_
	.globl	utcopy_

////////
/
/ Tngetc ( np )
/
/	Input:	np = pointer to seg:offset pair for tiac network buffer
/
/	Action:	Read character from network buffer, increment offset.
/
/	Return:	Character.
/
////////

tngetc_:				/ tngetc( np )
	push	si			/ char **np;
	push	bp			/ {
	mov	bp, sp			/	register char c;	/* AX */
	mov	bx, 6(bp)		/	register char *cp;	/* SI */
	push	ds			/
	lds	si, (bx)		/	cp = *np;
	cld				/
	lodsb				/	c = *cp++;
	pop	ds			/
	mov	(bx), si		/	*np = cp;
	subb	ah, ah			/
	pop	bp			/	return( c );
	pop	si			/ }
	ret

////////
/
/ Tnputc ( np, c )
/ char **np;
/ char c;
/
/	Input:	np = pointer to seg:offset pair for tiac network buffer
/		c  = character to transfer
/
/	Action:	Transfer character C to network buffer, increment offset.
/
/	Return:	Character C.
/
////////

tnputc_:				/ tnputc( np, c )
	push	di			/ char **np;			/* BX */
	push	bp			/ char c;			/* AX */
	mov	bp, sp			/ {
	mov	ax, 8(bp)		/	register char *cp;	/* DI */
	mov	bx, 6(bp)		/
	push	es			/
	les	di, (bx)		/	cp = *np;
	cld				/
	stosb				/	*cp++ = c;
	pop	es			/
	mov	(bx), di		/	*np = cp;
	pop	bp			/
	pop	di			/	return c;
	ret				/ }

////////
/
/ utcopy( up, np, n )
/ char * up;
/ char **np;
/ unsigned n;
/
/	Input:	up = offset in user data space for source data
/		np = pointer to seg:offset pair	for tiac network buffer
/		n  = number of bytes to transfer
/
/	Action:	Copy N bytes from user data space to network data space.
/		Add N to network data space offset.
/
/	Return: None.
/
////////

utcopy_:				/ utcopy( up, np, n )
	push	si			/
	push	di			/ register char *  up;		/* SI */
	push	bp			/ register char ** np;		/* BX */
	mov	bp, sp			/ register unsigned n;		/* CX */
	push	ds			/
	push	es			/ {
	mov	bx, 10(bp)		/	register char * cp;	/* DI */
					/
	les	di, (bx)		/	cp = *np;
					/
	mov	si, 8(bp)		/	up;
	mov	ds, uds_		/
					/
	mov	cx, 12(bp)		/	n;
					/
	cld				/
	clc				/
	rcr	cx, $1			/
	rep				/	for ( ; n != 0; --n )
	movsw				/		*cp++ = *up++;
	rcl	cx, $1			/
	rep				/
	movsb				/
					/
	pop	es			/
	pop	ds			/
	mov	(bx), di		/	*np = cp;
	pop	bp			/ }
	pop	di
	pop	si
	ret

////////
/
/ tucopy( np, up, n )
/ char **np;
/ char * up;
/ unsigned n;
/
/	Input:	np = pointer to seg:offset pair	for tiac network buffer
/		up = offset in user data space for destination
/		n  = number of bytes to transfer
/
/	Action:	Copy N bytes from network data space to user data space.
/		Add N to network data space offset.
/
/	Return: None.
/
////////

tucopy_:				/ tucopy( np, up, n )
	push	si			/
	push	di			/ register char ** np;		/* BX */
	push	bp			/ register char *  up;		/* DI */
	mov	bp, sp			/ register unsigned n;		/* CX */
	push	ds			/
	push	es			/ {
	mov	bx, 8(bp)		/	register char * cp;	/* SI */
					/
	mov	di, 10(bp)		/	up;
	mov	es, uds_		/
					/
	lds	si, (bx)		/	cp = *np;
					/
	mov	cx, 12(bp)		/	n;
					/
	cld				/
	clc				/
	rcr	cx, $1			/
	rep				/	for ( ; n != 0; --n )
	movsw				/		*up++ = *cp++;
	rcl	cx, $1			/
	rep				/
	movsb				/
					/
	pop	es			/
	pop	ds			/
	mov	(bx), si		/	*np = cp;
	pop	bp			/ }
	pop	di
	pop	si
	ret
0707070064030104430407770000030000030000011777770507310645400004500000000000/newbits/kernel/USRSRC/i8086/drv/RCS0707070064030110721004440000030000030000011777770507310645400006000000063306/newbits/kernel/USRSRC/i8086/drv/RCS/Makefile,vhead     1.7;
branch   ;
access   ;
symbols  ;
locks    bin:1.7;
comment  @@;


1.7
date     91.07.24.07.58.40;  author bin;  state Exp;
branches ;
next     1.6;

1.6
date     91.07.15.14.46.09;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.07.03.13.19.17;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.06.20.14.46.25;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.41.07;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.18.08.18.14;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     90.08.02.13.38.48;  author root;  state Exp;
branches ;
next     ;


desc
@From alpha driver kit
@


1.7
log
@update prov by hal
@
text
@# Makefile for AT specific Coherent drivers

# System utility directory
USRSYS=/usr/sys

# Source directory
USRSRC=/usr/src/sys

# Loadable driver directory
LDRV=$(USRSYS)/ldrv

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

# Object directory
KOBJ=/usr/kobj

ARCHIVES=\
	$(USRSYS)/lib/al.a \
	$(USRSYS)/lib/at.a \
	$(USRSYS)/lib/ati.a \
	$(USRSYS)/lib/fl.a \
	$(USRSYS)/lib/gr.a \
	$(USRSYS)/lib/hs.a \
	$(USRSYS)/lib/kb.a \
	$(USRSYS)/lib/lp.a \
	$(USRSYS)/lib/mm.a \
	$(USRSYS)/lib/ms.a \
	$(USRSYS)/lib/rm.a \
	$(USRSYS)/lib/rs.a \
	$(USRSYS)/lib/st.a \
	$(USRSYS)/lib/tn.a \

DRVOBJ=\
	$(KOBJ)/alx.o \
	$(KOBJ)/at.o \
	$(KOBJ)/atas.o \
	$(KOBJ)/ms.o \
	$(KOBJ)/ati.o \
	$(KOBJ)/com1.o $(KOBJ)/com2.o \
	$(KOBJ)/fdisk.o \
	$(KOBJ)/fl.o \
	$(KOBJ)/fontw.o \
	$(KOBJ)/gr.o $(KOBJ)/gras.o \
	$(KOBJ)/hs.o \
	$(KOBJ)/kb.o \
	$(KOBJ)/mm.o \
	$(KOBJ)/lp.o \
	$(KOBJ)/mmas.o \
	$(KOBJ)/rm.o \
	$(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o \
	$(KOBJ)/st.o \
	$(KOBJ)/tn.o $(KOBJ)/tnas.o

DRIVERS=\
	$(LDRV)/al0 \
	$(LDRV)/al1 \
	$(LDRV)/at \
	$(LDRV)/fl \
	$(LDRV)/gr \
	$(LDRV)/hs \
	$(LDRV)/lp \
	$(LDRV)/mm \
	$(LDRV)/ms \
	$(LDRV)/rm

install: $(ARCHIVES) $(DRIVERS)
	@@exec /bin/sync

all:	$(DRVOBJ)
	@@exec /bin/sync

$(USRSYS)/lib/al.a: $(KOBJ)/com1.o $(KOBJ)/com2.o $(KOBJ)/alx.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/at.a: $(KOBJ)/at.o $(KOBJ)/atas.o $(KOBJ)/fdisk.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/ati.a: $(KOBJ)/mm.o $(KOBJ)/ati.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/fl.a: $(KOBJ)/fl.o
	rm -f $(USRSYS)/lib/fl.a
	ar rc $(USRSYS)/lib/fl.a $(KOBJ)/fl.o
$(USRSYS)/lib/gr.a: $(KOBJ)/mm.o $(KOBJ)/gr.o $(KOBJ)/gras.o \
				$(KOBJ)/fontw.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/hs.a: $(KOBJ)/hs.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/kb.a: $(KOBJ)/kb.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/lp.a: $(KOBJ)/lp.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/mm.a: $(KOBJ)/mm.o $(KOBJ)/mmas.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/ms.a: $(KOBJ)/ms.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/rm.a: $(KOBJ)/rm.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/rs.a: $(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/st.a: $(KOBJ)/st.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/tn.a: $(KOBJ)/tn.o $(KOBJ)/tnas.o
	rm -f $@@
	ar rc $@@ $<

$(KOBJ)/alx.o:				\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		alx.c
	$(CC) $(CFLAGS) -c -o $@@ alx.c

$(KOBJ)/at.o: at.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h
	$(CC) $(CFLAGS) -DVERBOSE=1 -c -o $@@ at.c

$(KOBJ)/atas.o: atas.s
	$(AS) -go $@@ $<

$(KOBJ)/ati.o: ati.m
	$(CC) $(CFLAGS) -DATI_132=1 -c -o $@@ ati.m

$(KOBJ)/com1.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM1=1 -c -o $@@ al.c

$(KOBJ)/com2.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM2=1 -c -o $@@ al.c

$(KOBJ)/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@@ fdisk.c

$(KOBJ)/fl.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdioctl.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		fl.c
	$(CC) $(CFLAGS) -c -o $@@ fl.c

$(KOBJ)/fontw.o: tools/fontgen.c
	$(CC) -o tools/fontgen tools/fontgen.c
	exec tools/fontgen > fontw.s
	exec /bin/rm tools/fontgen
	$(AS) -gxo $(KOBJ)/fontw.o fontw.s
	exec /bin/rm fontw.s

$(KOBJ)/gr.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		gr.c
	$(CC) $(CFLAGS) -c -o $@@ gr.c

$(KOBJ)/gras.o: gras.m
	$(CC) $(CFLAGS) -c -o $@@ gras.m

$(KOBJ)/hgas.o: gras.s
	$(CC) $(CFLAGS) -c -o $@@ -DHERCULES gras.m

$(KOBJ)/hs.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		hs.c
	$(CC) $(CFLAGS) -c -o $@@ hs.c

$(KOBJ)/kb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		kb.c
	$(CC) $(CFLAGS) -c -o $@@ kb.c

$(KOBJ)/lp.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		lp.c
	$(CC) $(CFLAGS) -c -o $@@ lp.c

$(KOBJ)/mm.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/sched.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/timeout.h	\
		mm.c
	$(CC) $(CFLAGS) -c -o $@@ mm.c

$(KOBJ)/mmas.o: mmas.m
	$(CC) $(CFLAGS) -c -o $@@ mmas.m

$(KOBJ)/ms.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/ms.h		\
		$(USRINC)/errno.h	\
		ms.c
	$(CC) $(CFLAGS) -c -o $@@ ms.c

$(KOBJ)/rm.o: rm.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/buf.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/stat.h
	$(CC) $(CFLAGS) -c -o $@@ rm.c

$(KOBJ)/rs0.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS0 -c -o $@@ rs.c

$(KOBJ)/rs1.o: 				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS1 -c -o $@@ rs.c

$(KOBJ)/rsas.o: rsas.s
	$(AS) -gxo $@@ rsas.s

$(KOBJ)/st.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/const.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/mtioctl.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		st.c
	$(CC) $(CFLAGS) -c -o $@@ st.c

$(KOBJ)/tn.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		tn.c
	$(CC) $(CFLAGS) -c -o $@@ tn.c

$(KOBJ)/tnas.o: tnas.s
	$(AS) -gxo $@@ tnas.s

# How to make loadable drivers.

$(LDRV)/al0:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al0 )

$(LDRV)/al1:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al1 )

$(LDRV)/at:	$(USRSYS)/lib/at.a
	( cd $(USRSYS); ldconfig at )

$(LDRV)/fl:	$(USRSYS)/lib/fl.a
	( cd $(USRSYS); ldconfig fl )

$(LDRV)/gr:	$(USRSYS)/lib/gr.a
	( cd $(USRSYS); ldconfig gr )

$(LDRV)/hs:	$(USRSYS)/lib/hs.a
	( cd $(USRSYS); ldconfig hs )

$(LDRV)/lp:	$(USRSYS)/lib/lp.a
	( cd $(USRSYS); ldconfig lp )

$(LDRV)/mm:	$(USRSYS)/lib/mm.a
	( cd $(USRSYS); ldconfig mm )

$(LDRV)/ms:	$(USRSYS)/lib/ms.a
	( cd $(USRSYS); ldconfig ms )

$(LDRV)/rm:	$(USRSYS)/lib/rm.a
	( cd $(USRSYS); ldconfig rm )
@


1.6
log
@update by hal for relocateable objects
@
text
@a1 2
# Environment variable USRSYS must be defined!  It used to be /usr/sys - 
# Environment variable KOBJ must be defined!  Try /tmp/kobj
d3 9
d16 2
a17 7
DEBUG=0
AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/icpp
CFLAGS=
AFLAGS=-gx
NKB=nkb
d19 1
a19 4
# Loadable driver directory
LDRV=$(USRSYS)/ldrv

ARCHIVES=$(USRSYS)/lib/aha154x.a \
d26 1
d35 1
a35 1
DRVOBJ=	$(KOBJ)/aha.o \
a38 1
	$(KOBJ)/bufq.o \
a46 2
	$(KOBJ)/nkb.o \
	$(KOBJ)/gkb.o \
a52 3
	$(KOBJ)/scsi.o \
	$(KOBJ)/ss.o \
	$(KOBJ)/ssas.o \
d54 1
a54 1
	$(KOBJ)/tn.o $(KOBJ)/tnas.o \
d56 1
a56 1
DRIVERS=$(LDRV)/aha154x \
d66 1
a66 2
	$(LDRV)/rm \
	$(LDRV)/ss \
d74 1
a74 1
$(USRSYS)/lib/aha154x.a: $(KOBJ)/scsi.o $(KOBJ)/aha.o $(KOBJ)/fdisk.o
a76 3
$(USRSYS)/lib/al.a: $(KOBJ)/com1.o $(KOBJ)/com2.o $(KOBJ)/alx.o
	rm -f $@@
	ar rc $@@ $<
d80 1
a80 1
$(USRSYS)/lib/ati.a: $(KOBJ)/mm.o $(KOBJ)/ati.o $(KOBJ)/$(NKB).o
d87 1
a87 1
				$(KOBJ)/fontw.o $(KOBJ)/$(NKB).o
d93 3
d99 1
a99 1
$(USRSYS)/lib/mm.a: $(KOBJ)/mm.o $(KOBJ)/mmas.o $(KOBJ)/$(NKB).o
d111 1
a111 1
$(USRSYS)/lib/ss.a: $(KOBJ)/ss.o $(KOBJ)/ssas.o $(KOBJ)/bufq.o $(KOBJ)/fdisk.o
a113 3
$(USRSYS)/lib/st.a: $(KOBJ)/st.o
	rm -f $@@
	ar rc $@@ $<
a117 11
$(KOBJ)/aha.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/buf.h		\
		$(SYSINC)/sched.h		\
		$(SYSINC)/scsiwork.h	\
		$(SYSINC)/aha154x.h	\
		aha.c
	$(CC) $(CFLAGS) -c -o $@@ aha.c

d133 1
a133 1
	$(CC) $(CFLAGS) -c -o $(KOBJ)/alx.o alx.c
d135 13
a147 2
$(KOBJ)/at.o: at.c
	$(CC) $(CFLAGS) -DVERBOSE=1 -c -o $@@ $<
d152 2
a153 4
$(KOBJ)/ati.o: ati.s
	$(CPP) -E -DATI_132=1 ati.s > ati.i
	$(AS) -gxo $(KOBJ)/ati.o ati.i
	exec /bin/rm -f ati.i
a154 8
$(KOBJ)/bufq.o:			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/buf.h		\
		bufq.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o $@@ bufq.c

d162 1
d181 1
d193 1
a193 1
$(KOBJ)/dmareq.o:			\
a198 1
		$(SYSINC)/dmac.h	\
a199 16
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		dmareq.c
	$(CC) $(CFLAGS) -c -o $@@ dmareq.c

$(KOBJ)/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
d212 1
d236 1
d245 2
a246 4
$(KOBJ)/gras.o: gras.s
	$(CPP) -E gras.s > gras.i
	$(AS) -gxo $@@ gras.i
	exec /bin/rm -f gras.i
d249 1
a249 3
	$(CPP) -E -DHERCULES gras.s > hgas.i
	$(AS) -gxo $@@ hgas.i
	exec /bin/rm -f hgas.i
a250 3
$(KOBJ)/hd.o: hd.c
	$(CC) $(CFLAGS) -c -o $@@ hd.c

d256 1
d271 1
d282 1
a282 1
$(KOBJ)/gkb.o:				\
d287 1
a289 32
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		gkb.c
	$(CC) $(CFLAGS) -c -o $@@ gkb.c

$(KOBJ)/nkb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/kb.h		\
		nkb.c
	$(CC) $(CFLAGS) -c -o $@@ nkb.c

$(KOBJ)/lp.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
d312 2
a313 4
$(KOBJ)/mmas.o: mmas.s
	-$(CPP) -E mmas.s > mmas.i
	$(AS) -gxo $@@ mmas.i
	exec /bin/rm -f mmas.i
d321 1
d327 12
a338 1
$(KOBJ)/rm.o: rm.c
d346 1
d362 1
d376 2
a377 1
$(KOBJ)/scsi.o:				\
a379 41
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/sdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/scsiwork.h	\
		scsi.c
	$(CC) $(CFLAGS) -c -o $(KOBJ)/scsi.o scsi.c

$(KOBJ)/ss.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/io.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/proc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ss.h		\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/scsiwork.h	\
		ss.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o $(KOBJ)/ss.o ss.c

$(KOBJ)/ssas.o:				\
		ssas.s
	$(AS) -go $@@ $<

$(KOBJ)/st.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
d382 1
d399 1
a412 3
$(LDRV)/aha154x:	$(USRSYS)/lib/aha154x.a
	( cd $(USRSYS); ldconfig aha154x )

a441 3

$(LDRV)/ss:	$(USRSYS)/lib/ss.a
	( cd $(USRSYS); ldconfig ss )
@


1.5
log
@update provided by hal
@
text
@d3 1
d35 26
a60 25
DRVOBJ=	objects/aha.o \
	objects/alx.o \
	objects/at.o \
	objects/atas.o \
	objects/bufq.o \
	objects/ms.o \
	objects/ati.o \
	objects/com1.o objects/com2.o \
	objects/fdisk.o \
	objects/fl.o \
	objects/fontw.o \
	objects/gr.o objects/gras.o \
	objects/hs.o \
	objects/nkb.o \
	objects/kb.o \
	objects/mm.o \
	objects/lp.o \
	objects/mmas.o \
	objects/rm.o \
	objects/rs0.o objects/rs1.o objects/rsas.o \
	objects/scsi.o \
	objects/ss.o \
	objects/ssas.o \
	objects/st.o \
	objects/tn.o objects/tnas.o \
d81 1
a81 1
$(USRSYS)/lib/aha154x.a: objects/scsi.o objects/aha.o objects/fdisk.o
d84 1
a84 1
$(USRSYS)/lib/al.a: objects/com1.o objects/com2.o objects/alx.o
d87 1
a87 1
$(USRSYS)/lib/at.a: objects/at.o objects/atas.o objects/fdisk.o
d90 1
a90 1
$(USRSYS)/lib/ati.a: objects/mm.o objects/ati.o objects/$(NKB).o
d93 1
a93 1
$(USRSYS)/lib/fl.a: objects/fl.o
d95 3
a97 3
	ar rc $(USRSYS)/lib/fl.a objects/fl.o
$(USRSYS)/lib/gr.a: objects/mm.o objects/gr.o objects/gras.o \
				objects/fontw.o objects/$(NKB).o
d100 1
a100 1
$(USRSYS)/lib/hs.a: objects/hs.o
d103 1
a103 1
$(USRSYS)/lib/lp.a: objects/lp.o
d106 1
a106 1
$(USRSYS)/lib/mm.a: objects/mm.o objects/mmas.o objects/$(NKB).o
d109 1
a109 1
$(USRSYS)/lib/ms.a: objects/ms.o
d112 1
a112 1
$(USRSYS)/lib/rm.a: objects/rm.o
d115 1
a115 1
$(USRSYS)/lib/rs.a: objects/rs0.o objects/rs1.o objects/rsas.o
d118 1
a118 1
$(USRSYS)/lib/ss.a: objects/ss.o objects/ssas.o objects/bufq.o objects/fdisk.o
d121 1
a121 1
$(USRSYS)/lib/st.a: objects/st.o
d124 1
a124 1
$(USRSYS)/lib/tn.a: objects/tn.o objects/tnas.o
d128 1
a128 1
objects/aha.o:				\
d139 1
a139 1
objects/alx.o:				\
d154 1
a154 1
	$(CC) $(CFLAGS) -c -o objects/alx.o alx.c
d156 1
a156 1
objects/at.o: at.c
d159 1
a159 1
objects/atas.o: atas.s
d162 1
a162 1
objects/ati.o: ati.s
d164 1
a164 1
	$(AS) -gxo objects/ati.o ati.i
d167 1
a167 1
objects/bufq.o:			\
d175 1
a175 1
objects/com1.o: 			\
d193 1
a193 1
objects/com2.o: 			\
d211 1
a211 1
objects/dmareq.o:			\
d228 1
a228 1
objects/fdisk.o:			\
d241 1
a241 1
objects/fl.o:				\
d258 1
a258 1
objects/fontw.o: tools/fontgen.c
d262 1
a262 1
	$(AS) -gxo objects/fontw.o fontw.s
d265 1
a265 1
objects/gr.o:				\
d278 1
a278 1
objects/gras.o: gras.s
d283 1
a283 1
objects/hgas.o: gras.s
d288 1
a288 1
objects/hd.o: hd.c
d291 1
a291 1
objects/hs.o:				\
d305 1
a305 1
objects/kb.o:				\
d320 1
a320 1
objects/nkb.o:				\
d328 15
d352 1
a352 1
objects/lp.o:				\
d367 1
a367 1
objects/mm.o:				\
d381 1
a381 1
objects/mmas.o: mmas.s
d386 1
a386 1
objects/ms.o:				\
d397 1
a397 1
objects/rm.o: rm.c
d400 1
a400 1
objects/rs0.o:				\
d415 1
a415 1
objects/rs1.o: 				\
d430 1
a430 1
objects/rsas.o: rsas.s
d433 1
a433 1
objects/scsi.o:				\
d447 1
a447 1
	$(CC) $(CFLAGS) -c -o objects/scsi.o scsi.c
d449 1
a449 1
objects/ss.o:				\
d467 1
a467 1
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o objects/ss.o ss.c
d469 1
a469 1
objects/ssas.o:				\
d473 1
a473 1
objects/st.o:				\
d490 1
a490 1
objects/tn.o:				\
d503 1
a503 1
objects/tnas.o: tnas.s
@


1.4
log
@update provided by hal
@
text
@d14 1
d47 3
a49 1
	objects/nkb.o objects/mm.o \
d88 1
a88 1
$(USRSYS)/lib/ati.a: objects/mm.o objects/ati.o objects/nkb.o
d95 1
a95 1
				objects/fontw.o objects/nkb.o
d104 1
a104 1
$(USRSYS)/lib/mm.a: objects/mm.o objects/mmas.o objects/nkb.o
d303 15
d326 1
a328 1
		$(SYSINC)/timeout.h	\
d331 1
@


1.3
log
@bob h added new environment variable $USRKER for header file paths
for kernel specific headers.
@
text
@a6 2
KERINC=$(USRKER)/src/sys/sys
DRVINC=$(USRKER)/src/sys/i8086/sys
d12 1
a12 1
CFLAGS=-I$(KERINC) -I$(DRVINC)
a14 2
# USRSYS=$USRSYS

d124 1
a124 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d126 1
a126 1
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
d129 2
a130 2
		$(DRVINC)/scsiwork.h	\
		$(DRVINC)/aha154x.h	\
d135 2
a136 2
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d141 2
a142 2
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
d146 1
a146 1
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
d163 1
a163 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d165 1
a165 1
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
d171 3
a173 3
		$(DRVINC)/al.h		\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d178 2
a179 2
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
d183 1
a183 1
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
d189 3
a191 3
		$(DRVINC)/al.h		\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d196 2
a197 2
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
d201 1
a201 1
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
d208 1
a208 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d212 1
a212 1
		$(DRVINC)/dmac.h	\
d225 1
a225 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d238 1
a238 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d242 1
a242 1
		$(DRVINC)/dmac.h	\
d245 1
a245 1
		$(DRVINC)/i8086.h	\
d261 1
a261 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d287 1
a287 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d292 1
a292 1
		$(DRVINC)/ins8250.h	\
d295 1
a295 1
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
d301 1
a301 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d306 1
a306 1
		$(DRVINC)/i8086.h	\
d311 1
a311 1
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
d317 1
a317 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d322 1
a322 1
		$(DRVINC)/i8086.h	\
d332 1
a332 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d339 1
a339 1
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
d351 1
a351 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d365 1
a365 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d370 1
a370 1
		$(DRVINC)/ins8250.h	\
d380 1
a380 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d385 1
a385 1
		$(DRVINC)/ins8250.h	\
d398 1
a398 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d400 1
a400 1
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
d409 1
a409 1
		$(DRVINC)/scsiwork.h	\
d414 1
a414 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d416 1
a416 1
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
d425 1
a425 1
		$(DRVINC)/ss.h		\
d429 1
a429 1
		$(DRVINC)/scsiwork.h	\
d439 1
a439 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d455 1
a455 1
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
@


1.2
log
@update provided by hal
@
text
@d7 2
a8 2
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
@


1.1
log
@Initial revision
@
text
@a0 1
#
d2 1
a2 6
#
AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys -I/usr/include/sys
AFLAGS=-gx
a8 1
USRSYS=/usr/sys
d10 15
a24 1
ARCHIVES=$(USRSYS)/lib/al.a \
a26 1
	$(USRSYS)/lib/gm.a \
a32 1
	$(USRSYS)/lib/rp.a \
d37 5
a41 1
DRVOBJ=	objects/alx.o \
d48 3
a50 3
	objects/gr.o objects/gras.o objects/gmas.o \
	objects/hs.o objects/clocked.o \
	objects/kb.o objects/mm.o \
a53 1
	objects/rp.o objects/rpas.o \
d55 3
d61 14
a74 1
install: $(ARCHIVES)
d80 3
d84 8
a91 5
	rm -f $(USRSYS)/lib/al.a
	ar rc $(USRSYS)/lib/al.a objects/com1.o objects/com2.o objects/alx.o
$(USRSYS)/lib/ati.a: objects/mm.o objects/ati.o objects/kb.o
	rm -f $(USRSYS)/lib/ati.a
	ar rc $(USRSYS)/lib/ati.a objects/mm.o objects/ati.o objects/kb.o
a94 5
$(USRSYS)/lib/gm.a: objects/mm.o objects/gr.o objects/gmas.o \
				objects/fontw.o objects/kb.o
	rm -f $(USRSYS)/lib/gm.a
	ar rc $(USRSYS)/lib/gm.a objects/mm.o objects/gr.o objects/gmas.o \
				objects/fontw.o objects/kb.o
d96 6
a101 7
				objects/fontw.o objects/kb.o
	rm -f $(USRSYS)/lib/gr.a
	ar rc $(USRSYS)/lib/gr.a objects/mm.o objects/gr.o objects/gras.o \
				objects/fontw.o objects/kb.o
$(USRSYS)/lib/hs.a: objects/hs.o objects/clocked.o
	rm -f $(USRSYS)/lib/hs.a
	ar rc $(USRSYS)/lib/hs.a objects/hs.o objects/clocked.o
d103 5
a107 5
	rm -f $(USRSYS)/lib/lp.a
	ar rc $(USRSYS)/lib/lp.a objects/lp.o
$(USRSYS)/lib/mm.a: objects/mm.o objects/mmas.o objects/kb.o
		rm -f $(USRSYS)/lib/mm.a
	ar rc $(USRSYS)/lib/mm.a objects/mm.o objects/mmas.o objects/kb.o
d109 2
a110 2
	rm -f $(USRSYS)/lib/ms.a
	ar rc $(USRSYS)/lib/ms.a objects/ms.o
d112 2
a113 5
	rm -f $(USRSYS)/lib/rm.a
	ar rc $(USRSYS)/lib/rm.a objects/rm.o
$(USRSYS)/lib/rp.a: objects/rp.o objects/rpas.o
	rm -f $(USRSYS)/lib/rp.a
	ar rc $(USRSYS)/lib/rp.a objects/rp.o objects/rpas.o
d115 5
a119 2
	rm -f $(USRSYS)/lib/rs.a
	ar rc $(USRSYS)/lib/rs.a objects/rs0.o objects/rs1.o objects/rsas.o
d121 2
a122 2
	rm -f $(USRSYS)/lib/st.a
	ar rc $(USRSYS)/lib/st.a objects/st.o
d124 2
a125 2
	rm -f $(USRSYS)/lib/tn.a
	ar rc $(USRSYS)/lib/tn.a objects/tn.o objects/tnas.o
d127 11
d153 1
a153 1
	$(CC) $(CFLAGS) -c -o $@@ alx.c
d155 6
d162 2
a163 2
	exec /lib/cpp -E -DATI_132=1 ati.s > ati.i
	exec /bin/as -gxo $@@ ati.i
d166 7
a172 2
objects/clocked.o: clocked.s
	$(AS) -go $@@ $<
d175 1
d193 1
d257 6
a262 6
objects/fontw.o: fontgen.c
	$(CC) -i fontgen.c
	exec ./fontgen > $*.s
	exec /bin/rm fontgen
	$(AS) -gxo $@@ $*.s
	exec /bin/rm $*.s
a263 5
objects/gmas.o: gras.s
	exec /lib/cpp -E -DTECMAR gras.s > gmas.i
	exec /bin/as -gxo $@@ gmas.i
	exec /bin/rm -f gmas.i

d278 2
a279 2
	exec /lib/cpp -E gras.s > gras.i
	exec /bin/as -gxo $@@ gras.i
d283 2
a284 2
	exec /lib/cpp -E -DHERCULES gras.s > hgas.i
	exec /bin/as -gxo $@@ hgas.i
d288 1
a288 1
	$(CC) $(CFLAGS) -c -o $@@ $<
d304 1
a304 1
objects/kb.o:				\
d317 2
a318 2
		kb.c
	$(CC) $(CFLAGS) -c -o $@@ kb.c
d350 2
a351 2
	-/lib/cpp -E mmas.s > mmas.i
	exec /bin/as -gxo $@@ mmas.i
d366 1
a366 1
	$(CC) $(CFLAGS) -c -o $@@ $<
d368 1
a368 1
objects/rp.o:				\
a373 18
		$(SYSINC)/seg.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/v7sgtty.h	\
		rp.c
	$(CC) $(CFLAGS) -c -o $@@ rp.c

objects/rpas.o: rpas.s
	$(AS) -gxo $@@ $<

objects/rs0.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
d399 1
a399 1
	$(AS) -gxo $@@ $<
d401 40
d472 39
a510 1
	$(AS) -gxo $@@ $<
@
0707070064030147751004440000030000030000011777770507310646200005500000001704/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.dg,vhead     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.02.26.10.17.47;  author root;  state Exp;
branches ;
next	;


desc
@Makefile for "dg" - Digiboard PC/Xe device driver.
@



1.1
log
@First RCS version
@
text
@# Make file for a loadable driver

AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys \
	-I/usr/include/sys
AFLAGS=-gx

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

DRVOBJ=	objects/dg.o

dg: objects/dg.o
	rm -f $(USRSYS)/lib/dg.a
	ar rc $(USRSYS)/lib/dg.a objects/dg.o

objects/dg.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		dg.c
	$(CC) $(CFLAGS) -c -o $@@ dg.c
@
0707070064030104401004440000030000030000011777770507310646300005500000007251/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.ss,vhead     1.8;
branch   ;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.8
date     91.05.21.13.55.54;  author root;  state Exp;
branches ;
next     1.7;

1.7
date     91.05.16.14.15.39;  author root;  state Exp;
branches ;
next     1.6;

1.6
date     91.05.15.21.58.33;  author root;  state Exp;
branches ;
next     1.5;

1.5
date     91.04.16.01.46.27;  author root;  state Exp;
branches ;
next     1.4;

1.4
date     91.04.10.13.56.42;  author root;  state Exp;
branches ;
next     1.3;

1.3
date     91.03.25.19.08.16;  author root;  state Exp;
branches ;
next     1.2;

1.2
date     91.03.21.11.43.44;  author root;  state Exp;
branches ;
next     1.1;

1.1
date     91.03.06.08.05.47;  author root;  state Exp;
branches ;
next     ;


desc
@Makefile for Seagate SCSI driver
@


1.8
log
@Use bufq.c not ssqueue.c.
@
text
@# (lgl-
# 	COHERENT Driver Kit Version 1.1.0
# 	Copyright (c) 1982, 1990 by Mark Williams Company.
# 	All rights reserved. May not be copied without permission.
# -lgl)
#
# Makefile for Seagate ST01/ST02 SCSI driver "ss"
#
AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/icpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys -I/usr/include/sys
DEBUG=1
AFLAGS=-gx
OBJECTS=objects/ss.o objects/fdisk.o objects/bufq.o objects/ssas.o

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

ss: $(USRSYS)/lib/ss.a
	:

$(USRSYS)/lib/ss.a: $(OBJECTS)
	rm -f $(USRSYS)/lib/ss.a
	ar rc $(USRSYS)/lib/ss.a $(OBJECTS)

objects/ss.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
		$(SYSINC)/io.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/proc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(DRVINC)/ss.h		\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(DRVINC)/scsiwork.h	\
		ss.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o objects/ss.o ss.c

objects/ssas.o:				\
		ssas.s
	$(AS) -go $@@ ssas.s

objects/bufq.o:			\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
		$(SYSINC)/buf.h		\
		bufq.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o $@@ bufq.c

objects/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
		$(SYSINC)/con.h \
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@@ fdisk.c
@


1.7
log
@Add ssas.s module.
@
text
@d15 1
a15 1
OBJECTS=objects/ss.o objects/fdisk.o objects/ssqueue.o objects/ssas.o
d55 1
a55 1
objects/ssqueue.o:			\
d60 2
a61 2
		ssqueue.c
	$(CC) $(CFLAGS) -c -o $@@ ssqueue.c
@


1.6
log
@Add ability to define DEBUG level.
@
text
@d15 1
a15 1
OBJECTS=objects/ss.o objects/fdisk.o objects/ssqueue.o
d51 4
@


1.5
log
@ssqueue.c - remove dependency on scsiwork.h
@
text
@d13 1
d49 1
a49 1
	$(CC) $(CFLAGS) -DVERBOSE=1 -c -o objects/ss.o ss.c
@


1.4
log
@Add ss.h (and other dependencies) to ss.c
@
text
@a54 1
		$(DRVINC)/scsiwork.h	\
@


1.3
log
@add ssqueue.c to ss
@
text
@d30 18
a47 1
objects/ss.o: ss.c
d64 1
a64 1
		$(SYSINC)/con.h		\
@


1.2
log
@add fdisk.[co] to ss.a
@
text
@a8 2
# $Log: updateprovbyha,v $
# Revision 1.1.1.1  2019/05/29 04:56:34  root
# coherent
#
#
d14 1
d26 1
a26 1
$(USRSYS)/lib/ss.a: objects/ss.o objects/fdisk.o
d28 1
a28 1
	ar rc $(USRSYS)/lib/ss.a objects/ss.o objects/fdisk.o
d33 9
d46 1
a46 1
					$(SYSINC)/fun.h \
@


1.1
log
@Initial version for test builds
@
text
@d9 2
d27 1
a27 1
$(USRSYS)/lib/ss.a: objects/ss.o
d29 1
a29 1
	ar rc $(USRSYS)/lib/ss.a objects/ss.o
d33 13
@
0707070064030104451004440000030000030000011777770507310646400005500000043607/newbits/kernel/USRSRC/i8086/drv/RCS/aha.c,vhead     1.6;
branch   ;
access   ;
symbols  ;
locks    bin:1.6;
comment  @ * @;


1.6
date     91.06.20.14.46.55;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.06.18.08.09.48;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.06.17.12.26.42;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.10.14.44.27;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.05.01.04.54.43;  author root;  state Exp;
branches ;
next     1.1;

1.1
date     91.04.30.11.01.41;  author root;  state Exp;
branches ;
next     ;


desc
@Adaptec-specific code for "sd" driver.
@


1.6
log
@update provided by hal
@
text
@/*
 * This is the host adaptor specific portion of the
 * Adaptec AHA154x driver.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	91/05/01  04:54:43	root
 * Debug code and kalloc arg fixes.
 * 
 * Revision 1.1	91/04/30  11:01:41	root
 * Shipped with COH 3.1.0
 * 
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/sched.h>

#include <sys/scsiwork.h>
#include <sys/aha154x.h>

extern	saddr_t	sds;		/* System Data Selector */
static	paddr_t	sds_physical;	/* as physical address */
static	short	aha_i_o_base;
static	char	aha_loaded;	/* did load() find a host adaptor? */
static	char	dev_bit_map[8];	/* one byte per SCSI-ID; one bit per LUN */
char	drive_info[MAX_SCSI_ID * MAX_LUN]; /* "per drive" info/flags */

void	aha_intr();		/* interrupt service routine */

#define	MIN_MAILBOX	1
int	MAX_MAILBOX = { 8 };	/* tunable value */

static	scsi_work_t	*scsi_work_queue;
static	mailentry	*mailbox_in, *mailbox_out;
static	char		*aha_err_msg = { "no message" };

static	long	aha_timeout[] = { 
#define	TIMEOUT_PRESENT	0
	0x30000L,
#define	TIMEOUT_SENDCMD	1
	0x10000L,
#define	TIMEOUT_POLL	2
	0x100L,
};

#if	0
static
OUTB( port, value )
short port;
{	printf( "<O(%x,%x)>", port, value );
	outb( port, value );	}
INB( port )
short port;
{	register i = inb(port);
	printf( "<I(%x)=%x>", port, i );
	return i;	}
#else
#define	OUTB( port, value )	outb( port, value )
#define	INB(port)	inb(port)
#endif

#if	VERBOSE
#define	SETMSG(msg)	aha_err_msg = msg

static
char	*aha_last_msg()
{
	return aha_err_msg;
}

#else

#define	SETMSG(msg)
static
char	*aha_last_msg()
{
	return "error messages not verbose";
} 
#endif

static
int	no_mem()
{
	printf("aha154x: out of kernel memory\n");
}

int	aha_set_base( base )
{
	register i;

	i = aha_i_o_base;
	aha_i_o_base = base;
	return i;
}

int	aha_get_base()
{
	return aha_i_o_base;
}

aha_process( ccb )
ccb_t *ccb;
{
	register scsi_work_t *sw = ccb->ccb_sw;
	register BUF *bp;

#if	VERBOSE
	printf( "aha_process: ccb %x ", ccb );
	printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
	aha_ccb_print( ccb );
#endif
	if( ccb->ccb_sw == 0 ) {
#if	VERBOSE
		printf( "process: ccb %x with NULL sw\n", ccb );
#endif
		++ccb->opcode;
		wakeup( ccb );
		return;
	}

	bp = sw->sw_bp;
#if	VERBOSE
	printf( "bp = %x\n", bp );
#endif
	if( (ccb->hoststatus != 0) || (ccb->targetstatus != 0) ) {
		if( --sw->sw_retry > 0
		   || (ccb->targetstatus == CHECK_TARGET_STATUS
		   && ccb->cmd_status[12] == SENSE_UNIT_ATTENTION)) {
			int s = sphi();
			if( scsi_work_queue->sw_actf == NULL ) {
				scsi_work_queue->sw_actf = sw;
			} else {
				scsi_work_queue->sw_actl->sw_actf = sw;
			}
			scsi_work_queue->sw_actl = sw;
			spl(s);
			aha_start();
			return;
		}
		bp->b_flag |= BFERR;
	} else
		bp->b_resid = 0;
#if	VERBOSE
	printf( "bp flag = %o\n", bp->b_flag );
#endif
	bdone( bp );
	kfree( sw );
	kfree( ccb );
}

static
int	aha_1out( value )
{
	register i;

	while( (i = INB(aha_i_o_base + AHA_STATUS) & AHA_CDOPFULL) != 0 )
		if( (i & AHA_INVDCMD)
		 || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE) )
			return -1;
	OUTB( aha_i_o_base + AHA_WRITE, value );
	return 0;
}

static
int	aha_1in()
{
	register i;

	while( (i = INB(aha_i_o_base + AHA_STATUS) & AHA_DIPFULL) == 0 )
		if( (i & AHA_INVDCMD)
		 || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE) )
			return -1;
	return INB( aha_i_o_base + AHA_READ ) & 0xFF;
}

static
void	aha_cmd_out( value )
{
	register long l;
	register int i;

	for( l = aha_timeout[TIMEOUT_SENDCMD]; --l > 0; )
		if( ((i=INB(aha_i_o_base + AHA_STATUS))
		    & AHA_SCSIIDLE ) != 0 ) {
			aha_1out( value );
			return;
		}
#if	VERBOSE
		else
			printf( "aha: cmd_out status = %x\r", i );
#endif
	SETMSG( "timeout sending cmd byte" );
	printf( "aha154x: timeout sending cmd byte\n" );
}

static
int	aha_poll()
{
	register i;
	register l = aha_timeout[TIMEOUT_POLL];
	while( (--l > 0 )
	  &&  ((i = INB(aha_i_o_base + AHA_INTERRUPT)) & AHA_CMD_DONE) == 0 )
		;
	if( l == 0 )
		printf( "aha154x: aha_poll timed out\n" );

	i = INB(aha_i_o_base + AHA_STATUS);
	OUTB( aha_i_o_base + AHA_CONTROL, AHA_INTRRESET );
	return i;
}

static
void	aha_get_data( vec, cnt )
char	*vec;
int	cnt;
{
	while( --cnt >= 0 )
		*vec++ = aha_1in();
	aha_poll();
}

static
int	aha_present()
{
	long	l;

	if( INB(aha_i_o_base) == 0xFF ) {
		SETMSG( "no adapter found at io base" );
		return -3;
	}
	for( l = aha_timeout[TIMEOUT_PRESENT];
		(--l > 0) && (INB(aha_i_o_base + AHA_STATUS) & AHA_SELFTEST); )
			;
	if( l == 0 ) {
		SETMSG( "selftest not completed" );
		return -1;
	}
	if( INB(aha_i_o_base + AHA_STATUS) & AHA_DIAGFAIL ) {
		SETMSG( "diagnostics failed" );
		return -2;
	}
	if( INB(aha_i_o_base + AHA_STATUS) & AHA_INITMAIL ) {
		SETMSG( "mailbox initialization needed" );
		return 1;
	}
	if( INB(aha_i_o_base + AHA_STATUS) & AHA_SCSIIDLE ) {
		SETMSG( "adaptor okay, idle" );
		return 0;
	}
	SETMSG( "unknown status at start" );
	return -4;
}

static
void	aha_l_to_p3( value, vec )
paddr_t	value;
unsigned char *vec;
{
	register i;

	for( i = 3; --i >= 0; ) {
		vec[i] = value & 0xFF;
		value >>= 8;
	}
}

static
char	*aha_p3_to_v( vec )
unsigned char *vec;
{
	paddr_t adr;

	adr = vec[0];
	adr <<= 16;
	adr |= (vec[1]<<8) | vec[2];
	adr -= sds_physical;
	return (char *)adr;
}

aha_device_info()
{
	register i;
	static char buf[256];

	aha_cmd_out( AHA_DO_GET_DEVICES );
	aha_get_data( &buf[0], 8 );
	for( i = 0; i < 8; ++i )
		if( buf[i] != 0 )
			printf( "[%d] %x ", i, buf[i] );
	printf( "\n" );
}

int	aha_unload( ireq )
{
#if	VERBOSE
	printf( "aha_unload: %x\n", ireq );
#endif
	/*
	 *	we should really verify that everything
	 *	out there gets flushed.
	 */
	if (!aha_loaded)
		return;
	if( mailbox_out ) {
		kfree( mailbox_out );
		mailbox_out = 0;
	}
	clrivec( ireq );
}

int	aha_load( dma, ireq, base, head )
scsi_work_t *head;
{
	register int	i;
	unsigned char	adr[4];

#if	VERBOSE
	printf( "aha_load( %d, %d, 0x%x );\n", dma, ireq, base );
#endif
	aha_set_base(base);
	if( mailbox_out == 0 ) {
		if( (mailbox_out = 
		     kalloc(2 * MAX_MAILBOX * sizeof(mailentry))) == 0 ) {
			no_mem();
			return -1;
		} else
			mailbox_in = &mailbox_out[MAX_MAILBOX];
	}

	for( i = 0; i < MAX_MAILBOX; ++i )
		mailbox_out[i].cmd = mailbox_in[i].cmd = 0;

	sds_physical = VTOP2( 0, sds );
	aha_l_to_p3( VTOP2( mailbox_out, sds ), &adr[1] );
	adr[0] = MAX_MAILBOX;

	/*
	 * setup HW
	 */
	setivec( ireq, aha_intr );
	outb( 0xD6, 0xC1 );		/* DMA is currently hard coded for */
	outb( 0xD4, 0x01 );		/* DMA channel 5 */


	OUTB( aha_i_o_base+AHA_CONTROL, AHA_HARDRESET );
	if (aha_present() < 0) {
		printf("aha154x: initialization error or host adaptor not ");
		printf("found at 0x%x\n", aha_i_o_base);
		return -1;
	}
	aha_cmd_out( AHA_DO_MAILBOX_INIT );
	for( i = 0; i < 4; ++i )
		aha_1out( adr[i] );
	scsi_work_queue = head;
	++aha_loaded;
	return MAX_MAILBOX;
}

aha_command( sc )
register scsi_cmd_t *sc;
{
	register i;
	register ccb_t *ccb;

	short	count = sc->blklen;
	long	block = sc->block;

	ccb = (ccb_t *) kalloc(sizeof (ccb_t));
	if (ccb == (ccb_t *) 0) {
		no_mem();
		return -1;
	}
#if	VERBOSE
	printf( "aha_command( SCSI ID %d, LUN %d, c %x, b %D",
		sc->unit >> 2, sc->unit & 0x3, sc->cmd, sc->block ); 
	printf( " [%d] @@%x:%x )\n",
		sc->buflen, sc->buffer );
#endif
	ccb->ccb_sw = 0;
	ccb->opcode = 0;			/* SCSI_INITIATOR*/
	ccb->target = (sc->unit & 0x1C) << 3;	/* SCSI ID */
	ccb->target |= sc->unit & 0x3;		/* LUN */
	if( (ccb->cmd_status[0] = sc->cmd) == ScmdWRITEXTENDED ) {
		ccb->target |= AHA_CCB_DATA_OUT;
	} else { /* READEXT, READCAP, INQUIRY */
		ccb->target |= AHA_CCB_DATA_IN;
	}
	ccb->cmd_status[1] = 0;
	ccb->cmd_status[2] = block;
	ccb->cmd_status[3] = block >>16;
	ccb->cmd_status[4] = block >> 8;
	ccb->cmd_status[5] = block;
	ccb->cmd_status[6] = 0;
	ccb->cmd_status[7] = count / 512;
	ccb->cmd_status[8] = count;
	ccb->cmd_status[9] = 0;
	ccb->cmdlen = 10;
	ccb->senselen = MAX_SENSEDATA;

	aha_l_to_p3( (long)sc->buflen, ccb->datalen );
	aha_l_to_p3( sc->buffer, ccb->dataptr );
	aha_l_to_p3( VTOP2( ccb, sds ), mailbox_out[0].adr );
#if	VERBOSE
	aha_ccb_print( ccb );
#endif
	mailbox_out[0].cmd = MBO_TO_START;
	aha_1out( AHA_DO_SCSI_START );
	while( ccb->opcode == 0 )
		sleep( ccb, CVBLKIO, IVBLKIO, SVBLKIO );
	
#if	VERBOSE
	printf( "done with status = %d, %d\n",
		ccb->hoststatus, ccb->targetstatus );
#endif
	if( (ccb->targetstatus == CHECK_TARGET_STATUS)
	   && (ccb->cmd_status[12] != SENSE_UNIT_ATTENTION) ) {
		printf( "aha: SCSI ID %d LUN %d. SCSI sense =",
		(sc->unit >> 2), sc->unit & 0x3 );
		for( i = 0; i < ccb->senselen; ++i )
			printf( " %x", ccb->cmd_status[10+i] );
		printf( "\n" );
	}
	i = ccb->hoststatus | ccb->targetstatus;
	kfree( ccb );
	return i;
}

ccb_t	*buildccb( sw )
register scsi_work_t *sw;
{
	register ccb_t *ccb;
	ccb = (ccb_t *)kalloc(sizeof(ccb_t));

#if	VERBOSE
	printf( "build: drv = %x, bno = %D  ",
		sw->sw_drv, sw->sw_bno );
#endif
	ccb->ccb_sw = sw;
	ccb->opcode = 0;			/* SCSI INITIATOR */
	ccb->target = (sw->sw_drv & 0x1C) << 3;	/* SCSI ID */
	ccb->target |= (sw->sw_drv) & 0x3;	/* LUN */
	if( sw->sw_bp->b_req == BREAD ) {
		ccb->target |= AHA_CCB_DATA_IN;
		ccb->cmd_status[0] = ScmdREADEXTENDED;
	} else {
		ccb->target |= AHA_CCB_DATA_OUT;
		ccb->cmd_status[0] = ScmdWRITEXTENDED;
	}
	ccb->cmd_status[2] = 0;
	ccb->cmd_status[3] = sw->sw_bno >>16;
	ccb->cmd_status[4] = sw->sw_bno >> 8;
	ccb->cmd_status[5] = sw->sw_bno;
	ccb->cmd_status[6] = 0;
	ccb->cmd_status[7] = sw->sw_bp->b_count / (512*256L);
	ccb->cmd_status[8] = sw->sw_bp->b_count / 512;
	ccb->cmd_status[9] = 0;
	ccb->cmdlen = 10;
	ccb->senselen = MAX_SENSEDATA;

	aha_l_to_p3( (long)sw->sw_bp->b_count, ccb->datalen );
	aha_l_to_p3( vtop(sw->sw_bp->b_faddr), ccb->dataptr );
	return ccb;
#if	0
/* start of ioctl code */
	if( f == SASI_CMD_IN )
		ccb->target |= AHA_CCB_DATA_IN;
	else if( f == SASI_CMD_OUT )
		ccb->target |= AHA_CCB_DATA_OUT;
	else
		ccb->target |=	 AHA_CCB_DATA_IN
				|AHA_CCB_DATA_OUT;
#endif
}

aha_start()
{
	register i, s, n = 0;
	scsi_work_t *sw;
	static char locked;

	s = sphi();
	if( locked ) {
		spl(s);
		return;
	}
	++locked;
	spl(s);

	while( (sw = scsi_work_queue->sw_actf) != NULL ) {
		for( i = MIN_MAILBOX; i < MAX_MAILBOX; ++i )
			if( mailbox_out[i].cmd == MBO_IS_FREE ) {
				register ccb_t *ccb;
				int s;

				++n;
				ccb = buildccb( sw );
#if	VERBOSE
				aha_ccb_print( ccb );
#endif
				aha_l_to_p3( VTOP2( ccb, sds ),
						mailbox_out[i].adr );
				mailbox_out[i].cmd = MBO_TO_START;
#if	VERBOSE
				printf( "MBO[%d] = %x:%x:%x:%x, ccb = %x ",
					i, mailbox_out[i].cmd,
					mailbox_out[i].adr[0],
					mailbox_out[i].adr[1],
					mailbox_out[i].adr[2], ccb );
	printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
#endif
				aha_1out( AHA_DO_SCSI_START );

				s = sphi();
				sw = scsi_work_queue->sw_actf = sw->sw_actf;
				if( sw == NULL )
					scsi_work_queue->sw_actl = NULL;
				spl(s);

				if( sw == NULL )
					break;
			}
		if( i == MAX_MAILBOX )
			break;
	}
	--locked;
	return n;
}

int	aha_completed()
{
	register i, n;

	for( n = 0, i = 0; i < MAX_MAILBOX; ++i )
		if( mailbox_in[i].cmd != MBI_IS_FREE ) {
#if	VERBOSE
			printf( "aha: mail[%d] = %x:%x:%x:%x\n",
				i, mailbox_in[i].cmd,
				mailbox_in[i].adr[0],
				mailbox_in[i].adr[1],
				mailbox_in[i].adr[2] );
#endif
			defer( aha_process,
				aha_p3_to_v( mailbox_in[i].adr ) );
			mailbox_in[i].cmd = MBI_IS_FREE;
			++n;
		}
	return n;
}

void	aha_intr()
{
	register i;

#if	VERBOSE
	printf( "aha_interrupt routine\n" );
#endif
	if( ((i = INB(aha_i_o_base+AHA_INTERRUPT)) & AHA_ANY_INTER) == 0 )
		printf( "aha: spurious interrupt %x\n", i );
#if	VERBOSE
	printf( "aha_interrupt: %x\n", i );
#endif
	switch( i & AHA_ALL_INTERRUPTS ) {
	case AHA_RESETED:
#if	VERBOSE
		printf( "aha: reseted\n" );
#endif
		break;
	case AHA_CMD_DONE:
#if	VERBOSE
		printf( "aha: adapter command completed\n" );
#endif
		break;
	case AHA_MBO_EMPTY:
#if	VERBOSE
		printf( "aha: MAILBOX emptied\n" );
#endif
		defer( aha_start, (char *)0 );
		break;
	case AHA_MBI_STORED:
#if	VERBOSE
		printf( "aha: MAILBOX in stored\n" );
#endif
		aha_completed();
		break;
	default:
		printf( "aha: multiple interrupts not yet handled\n" );
	}
	outb( aha_i_o_base+AHA_CONTROL, AHA_INTRRESET );
}

aha_ioctl()
{
	printf( "aha_ioctl: Not implemented\n" );
}

#if	VERBOSE
static	unsigned char vec[256];

static	aha_ports_are() {
	printf( "aha_ports_are: %x %x %x\n",
		INB(aha_i_o_base+0),
		INB(aha_i_o_base+1),
		INB(aha_i_o_base+2) );
}

static	aha_inquiry_is() {
	printf( "aha_inquiry:" );
	printf( "... aha_present = %d, ", aha_present() );
	printf( "%s\n", aha_last_msg() );
	aha_cmd_out( AHA_DO_INQUIRY );

	aha_get_data( &vec[0], 4 );
	printf( " board id '%c'", vec[0] );
	printf( ", options '%c'", vec[1] );
	printf( ", HW '%c'", vec[2] );
	printf( ", FW '%c'\n", vec[3] );
}

void	aha_setup_is() {
	register i;

	printf( "Setup and Data:\n" );
	aha_cmd_out( AHA_DO_GET_SETUP );
	aha_cmd_out( 16 );
	aha_get_data( &vec[0], 16 );
	printf( "  Data Xfer %s Sync (J1)\n", (vec[0]&1) ? "is" : "not" );
	printf( "  Parity %s Enabled (J1)\n", (vec[0]&2) ? "is" : "not" );
	switch( vec[1] ) {
	case AHA_SPEED_5_0_MB:
		printf( "  5.0 Mb/sec.\n" );	break;
	case AHA_SPEED_6_7_MB:
		printf( "  6.7 Mb/sec.\n" );	break;
	case AHA_SPEED_8_0_MB:
		printf( "  8.0 Mb/sec.\n" );	break;
	case AHA_SPEED_10_MB:
		printf( "  10 Mb/sec.\n" );	break;
	case AHA_SPEED_5_7_MB:
		printf( "  5.7 Mb/sec.\n" );	break;
	default:
		if( vec[1] & 0x80 )
			printf( "  Pulse Read %d, Write %d, Strobe off %d\n",
				50*(2+(vec[1]>>4)&0x7), 50*(2+(vec[1]&7)),
				vec[1] & 0x80 ? 150 : 100 );
	}
	printf( "  Bus Time ON %d, OFF %d\n", vec[2], vec[3] );
	printf( "  %d Mailboxes at %x|%x|%x\n", vec[4],
		vec[5], vec[6], vec[7] );
	for( i = 0; i < 8; ++i )
		if( vec[i+8] )
			printf( "  Target [%d] = Sync Neg %x\n", i, vec[i+8] );
}

static	aha_mailboxes_are( n, adr )
mailentry *adr;
{
	register i;

	printf( "addresses for mailbox is %x:%x\n", (long)adr );
	for( i = 0; i < n; ++i, ++adr )
		printf( "  mbo[%x] = %x %x|%x|%x\n",
			i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2] );
	for( i = 0; i < n; ++i, ++adr )
		printf( "  mbi[%x] = %x %x|%x|%x\n",
			i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2] );
}

void	aha_status()
{
	aha_ports_are();
	aha_inquiry_is();
	aha_devices_are();
	aha_setup_is();
	aha_mailboxes_are( MAX_MAILBOX, mailbox_out );
}

aha_ccb_print( ccb )
ccb_t	*ccb;
{
	register i;
	register unsigned char *cp;

	printf( "ccb @@%x, sw @@%x, bp @@%x, flag %o\n",
		ccb, ccb->ccb_sw, ccb->ccb_sw->sw_bp,
		ccb->ccb_sw->sw_bp->b_flag );
	printf( "op %d, ", ccb->opcode );
	printf( "target ID=%d, ", (ccb->target>>5) & 0x7 );
	printf( "LUN=%d, ", (ccb->target & 0x7) );
	printf( "dir=%s%s\n",	(ccb->target&AHA_CCB_DATA_IN)?"IN":"",
				(ccb->target&AHA_CCB_DATA_OUT)?"OUT":"" );
	printf( "data len %x|%x|%x, adr %x|%x|%x\n",
		ccb->datalen[0],ccb->datalen[1],ccb->datalen[2],
		ccb->dataptr[0],ccb->dataptr[1],ccb->dataptr[2] );
	printf( "status host=%x, target=%x\n",
		ccb->hoststatus, ccb->targetstatus );
	printf( "cmddata[%d]:", ccb->cmdlen );
	for( i = 0, cp = ccb->cmd_status; i < ccb->cmdlen; ++i )
		printf( " %x", *cp++ );
	printf( "\nrequest sense[%d]:", ccb->senselen );
	for( i = 0; i < ccb->senselen; ++i )
		printf( " %x", *cp++ );
	if( i = cp[-1] ) {
		printf( "\n   + " );
		while( --i >= 0 )
			printf( " %x", *cp++ );
	}
	printf( "\n" );
}

#endif	/* VERBOSE */

@


1.5
log
@update provided by hal
@
text
@d13 1
a13 1
#include "coherent.h"
d17 2
a18 2
#include "scsiwork.h"
#include "aha154x.h"
@


1.4
log
@new version provided y hal for v321
@
text
@@


1.3
log
@initial version prov by hal
@
text
@d13 1
a13 1
#include <sys/coherent.h>
@


1.2
log
@Debug code and kalloc arg fixes.
@
text
@d6 3
d106 1
d108 1
a108 2
printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
#if	VERBOSE
a130 6
printf("0-swq-f=%x\n", scsi_work_queue->sw_actf);
{BUF *bp=sw->sw_bp;
printf("bno=%lx count=%d ", bp->b_bno, bp->b_count);
printf("faddr=%lx resid=%d ", bp->b_faddr, bp->b_resid);
printf("req=%x bp=%x\n", bp->b_req, bp);
}
a331 1
printf("B");
a332 1
printf("C");
a353 1
printf("1-swq-f=%x\n", scsi_work_queue->sw_actf);
a400 1
printf("D");
d433 1
a433 1
#if	1
d460 1
a460 7
printf("E");
{BUF *bp=sw->sw_bp;
printf("bno=%lx count=%d ", bp->b_bno, bp->b_count);
printf("faddr=%lx resid=%d ", bp->b_faddr, bp->b_resid);
printf("req=%x bp=%x\n", bp->b_req, bp);
}
	aha_l_to_p3( VTOP(sw->sw_bp->b_faddr), ccb->dataptr );
d479 1
a479 1
printf("aha_start ");
a494 1
printf("before buildccb\n");
a495 1
printf("after buildccb\n");
a498 1
printf("F");
d502 1
a502 1
#if	1
d508 1
a508 1
printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
a513 1
printf("2-swq-f=%x\n", scsi_work_queue->sw_actf);
d531 1
a531 1
printf("aha_completed ");
d534 1
a534 1
#if	1
@


1.1
log
@Shipped with COH 3.1.0
@
text
@d5 4
a8 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
a11 2
#include <sys/mmu.h>
#include <sys/types.h>
d103 2
a105 1
	printf( "aha_process: ccb %x\n", ccb );
d126 1
a126 1
			if( scsi_work_queue->sw_actf == NULL )
d128 7
a134 1
			else
d136 1
d335 4
a338 2
	sds_physical = vtop( 0, sds );
	aha_l_to_p3( vtop( mailbox_out, sds ), &adr[1] );
d359 1
d373 1
a373 1
	ccb = (ccb_t *) kalloc(sizeof *ccb);
d407 2
a408 1
	aha_l_to_p3( vtop( ccb, sds ), mailbox_out[0].adr );
d438 1
a438 1
	ccb = (ccb_t *)kalloc(10 + sizeof *ccb);
d440 1
a440 1
#if	VERBOSE
d467 7
a473 1
	aha_l_to_p3( vtop(sw->sw_bp->b_faddr), ccb->dataptr );
d492 1
a492 1

d508 1
d510 1
d514 2
a515 1
				aha_l_to_p3( vtop( ccb, sds ),
d518 2
a519 2
#if	VERBOSE
				printf( "MBO[%d] = %x:%x:%x:%x, ccb = %x\n",
d524 1
d530 1
d548 1
a548 1

d551 1
a551 1
#if	VERBOSE
@
0707070064030106211004440000030000030000011777770507310647000005400000032374/newbits/kernel/USRSRC/i8086/drv/RCS/al.c,vhead     1.8;
branch   ;
access   ;
symbols  ;
locks    bin:1.8;
comment  @ * @;


1.8
date     91.08.01.13.47.28;  author bin;  state Exp;
branches ;
next     1.7;

1.7
date     91.06.20.14.47.12;  author bin;  state Exp;
branches ;
next     1.6;

1.6
date     91.06.18.08.10.26;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.06.17.12.27.58;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.06.10.14.44.45;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.02.22.16.05.43;  author root;  state Exp;
branches ;
next     1.2;

1.2
date     91.02.21.11.21.28;  author hal;  state Exp;
branches ;
next     1.1;

1.1
date     91.02.21.11.07.36;  author hal;  state Exp;
branches ;
next     ;


desc
@@


1.8
log
@updated by hal to include rts/cts handshaking.
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/31  16:06:33  hal
 * Change include usage.  Use AL[01]_MAJOR.
 * 
 * Revision 1.2	91/02/21  11:21:28	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 * 
 * Revision 1.1	91/02/21  11:07:36	hal
 * Used in COH Release 3.0.0 - no COM3/COM4
 * 
 -lgl) */
/*
 * Driver for an IBM PC asyncronous
 * line, using interrupts. The interface
 * uses a Natty/WD 8250 chip.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <sys/clist.h>
#include <sys/ins8250.h>
#include <sys/sched.h>
#include <sys/al.h>
#include <sys/devices.h>

#define	minor_st(dev)	(dev & 0x3f)
#define	DEV_TTY		(alttab[minor_st(dev)])
#define ALPORT		(((COM_DDP *)(DEV_TTY.t_ddp))->port)

/*
 * This driver can be compiled to drive any possible
 * async port by appropriate definitions of:
 *	ALPORT[ab]	the io port address(es)
 *	ALNUM[ab]	com index number (0..3 for com[1..4])
 *	ALINT	the interrupt level
 *	ALNAME	the xxcon name
 *	ALMAJ	the major device number
 *      ALCNT	number of ports sharing the interrupt
 *
 *	NOTE:	if ALCNT is changed, alttab and alintr will need hacking
 * Common code for the different ports is handled by alx.c
 */

#ifdef ALCOM1			/* COM1_3 definitions */
#define ALPORTa	0x3F8		/* Base of com1 port */
#define ALPORTb	0x3E8		/* Base of com3 port */
#define ALNUMa	0		/* com1 has com number of 0 */
#define ALNUMb	2		/* com3 has com number of 2 */
#define ALINT	4		/* Interrupt level of com1_3 ports */
#define	ALNAME	a0con		/* CON name of com1_3 ports */
#define ALMAJ	AL0_MAJOR	/* Major number of com1_3 port */
#define ALCNT	A0CNT		/* Number of ports for this IRQ */
#define ALSPEEDa C1BAUD		/* Name of patchable variable for com1 speed */
#define ALSPEEDb C3BAUD		/* Name of patchable variable for com3 speed */
#endif

#ifdef ALCOM2			/* COM2_4 definitions */
#define ALPORTa	0x2F8		/* Base of com2 port */
#define ALPORTb	0x2E8		/* Base of com4 port */
#define ALNUMa	1		/* com2 has com number of 1 */
#define ALNUMb	3		/* com4 has com number of 3 */
#define ALINT	3		/* Interrupt level of com2_4 ports */
#define ALNAME	a1con		/* CON name of com2_4 ports */
#define ALMAJ	AL1_MAJOR	/* Major number of com2_4 ports */
#define ALCNT	A1CNT		/* Number of ports for this IRQ */
#define ALSPEEDa C2BAUD		/* Name of patchable variable for com2 speed */
#define ALSPEEDb C4BAUD		/* Name of patchable variable for com4 speed */
#endif

/*
 * Functions.
 */
int	alxopen();
int	alxclose();
int	alxioctl();
int	alxtimer();
int	alxparam();
int	alxcycle();
int	alxstart();
int	alxbreak();

int	alintr();
int	alopen();
int	alclose();
int	alread();
int	alwrite();
int	alioctl();
int	alload();
int	alunload();
int	alpoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON ALNAME ={
	DFCHR|DFPOL,			/* Flags */
	ALMAJ,				/* Major index */
	alopen,				/* Open */
	alclose,			/* Close */
	nulldev,			/* Block */
	alread,				/* Read */
	alwrite,			/* Write */
	alioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	alxtimer,			/* Timeout */
	alload,				/* Load */
	alunload,			/* Unload */
	alpoll				/* Poll */
};

/*
 * Terminal structures.
 */
static COM_DDP	* ddp;
static TTY	* alttab;
static TTY	* irqtty;  /* point to alttab entry which is IRQ-enabled */

/*
 * to change default speeds - patch kernel variables C1BAUD..C4BAUD
 *   new value should be one of B0..B9600 in /usr/include/sgtty.h
 */
int ALSPEEDa = B9600;
int ALSPEEDb = B9600;

/*
 * to enable com[34], patch here
 *	A0CNT should be 2 if you want com3, 1 otherwise
 *	A1CNT should be 2 if you want com4, 1 otherwise
 */
int ALCNT = 2;

static
alload()
{
	register int s;
	static int init;
	extern int albaud[];
	int port, i;

	if (init == 0
	  && (alttab = (TTY *)kalloc(ALCNT * sizeof(TTY)))
	  && (ddp = (COM_DDP *)kalloc(ALCNT * sizeof(COM_DDP)))) {
		kclear(alttab, ALCNT*sizeof(TTY));
		kclear(ddp, ALCNT*sizeof(COM_DDP));
		s = sphi();
		++init;

		alttab[0].t_dispeed = alttab[0].t_dospeed = ALSPEEDa;
		alttab[0].t_ddp = (char *)&ddp[0];
		tp_table[ALNUMa] = alttab; /* set TTY pointers for polling */
		ddp[0].port = ALPORTa;
		ddp[0].com_num = ALNUMa;

		if (ALCNT > 1) {
			alttab[1].t_dispeed = alttab[1].t_dospeed = ALSPEEDb;
			alttab[1].t_ddp = (char *)&ddp[1];
			tp_table[ALNUMb] = alttab+1;
			ddp[1].port = ALPORTb;
			ddp[1].com_num = ALNUMb;
		}

		for (i = 0;  i < ALCNT; i++) {
			int speed = alttab[i].t_dospeed;

			/* port = base I/O address */
			port = ((COM_DDP *)(alttab[i].t_ddp))->port;
			outb(port+IER, 0);	/* disable port interrupts */
			if (inb(port+IER) == 0) {
				outb(port+MCR, 0);  /* hangup port */
				outb(port+LCR, LC_DLAB);
				outb(port+DLL, albaud[speed]);
				outb(port+DLH, albaud[speed] >> 8);
				outb(port+LCR, LC_CS8);
			}
			alttab[i].t_start = alxstart;
			alttab[i].t_param = alxparam;
			alttab[i].t_cs_sel= cs_sel();
		}

		setivec(ALINT, alintr);     /* set interrupt vector */
		spl(s);
	}
}

static
alunload()
{
	int port, i;

	for (i = 0;  i < ALCNT; i++) {
		port = ((COM_DDP *)(alttab[i].t_ddp))->port;
		outb(port+IER, 0);	/* disable port interrupts */
		outb(port+MCR, 0);	/* hangup port */
		timeout(alttab[i].t_rawtim, 0, NULL, 0);/* cancel timer */
	}
	clrivec(ALINT);			/* release interrupt vector */
	kfree(alttab);
	kfree(ddp);
}

static
alopen(dev, mode)
dev_t	dev;
int	mode;
{
	if (minor_st(dev) < ALCNT) {
		alload();
		alxcycle(&DEV_TTY);
		alxopen(dev, mode, &DEV_TTY, &irqtty);
	} else
		u.u_error = ENXIO;
}

static
alclose(dev, mode)
dev_t	dev;
int	mode;
{
	register int s;

	if (--DEV_TTY.t_open == 0) {	/* Last open */
		s = sphi();
		alxclose(dev, mode, &DEV_TTY);
		spl(s);
	}
}

static
alread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ttread(&DEV_TTY, iop);
}

static
alwrite(dev, iop)
dev_t	dev;
register IO	*iop;
{
	register int c;

	/*
	 * Treat user writes through tty driver.
	 */
	if (iop->io_seg != IOSYS) {
		ttwrite(&DEV_TTY, iop);
		return;
	}

	/*
	 * Treat kernel writes by blocking on transmit buffer.
	 */
	while ((c = iogetc(iop)) >= 0) {
		/*
		 * Wait until transmit buffer is empty.
		 * Check twice to prevent critical race with interrupt handler.
		 */
		for (;;) {
			if (inb(ALPORT+LSR) & LS_TxRDY)
				if (inb(ALPORT+LSR) & LS_TxRDY)
					break;
		}

		/*
		 * Output the next character.
		 */
		outb(ALPORT+DREG, c);
	}
}

static
alioctl(dev, com, vec)
dev_t	dev;
struct sgttyb *vec;
{
	alxioctl(dev, com, vec, &DEV_TTY);
}

static
alpoll(dev, ev, msec)
dev_t dev;
int ev;
int msec;
{
	return ttpoll(&DEV_TTY, ev, msec);
}

static
alintr()
{
	alxintr(irqtty);
}
@


1.7
log
@update provided by hal
@
text
@d6 4
a9 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d33 1
d60 1
a60 1
#define ALMAJ	5		/* Major number of com1_3 port */
d73 1
a73 1
#define ALMAJ	6		/* Major number of com2_4 ports */
d151 1
a151 1
	if ( init == 0
d173 1
a173 1
		for ( i = 0;  i < ALCNT; i++ ) {
d179 1
a179 1
			if ( inb(port+IER) == 0 ) {
d182 3
a184 3
				outb(port+DLL, albaud[speed] );
				outb(port+DLH, albaud[speed] >> 8 );
				outb(port+LCR, LC_CS8 );
d192 1
a192 1
		spl( s );
d201 1
a201 1
	for ( i = 0;  i < ALCNT; i++ ) {
d207 1
a207 1
	clrivec( ALINT );			/* release interrupt vector */
d219 2
a220 2
		alxcycle( &DEV_TTY );
		alxopen( dev, mode, &DEV_TTY, &irqtty);
d234 1
a234 1
		alxclose( dev, mode, &DEV_TTY );
d244 1
a244 1
	ttread(&DEV_TTY, iop, 0);
d257 2
a258 2
	if ( iop->io_seg != IOSYS ) {
		ttwrite( &DEV_TTY, iop, 0 );
d265 1
a265 1
	while ( (c = iogetc(iop)) >= 0 ) {
d271 2
a272 2
			if ( inb(ALPORT+LSR) & LS_TxRDY )
				if ( inb(ALPORT+LSR) & LS_TxRDY )
d279 1
a279 1
		outb( ALPORT+DREG, c );
d292 1
a292 1
alpoll( dev, ev, msec )
d297 1
a297 1
	return ttpoll( &DEV_TTY, ev, msec );
@


1.6
log
@update provided by hal
@
text
@d19 2
a20 2
#include <coherent.h>
#include <i8086.h>
d26 2
a27 2
#include <clist.h>
#include <ins8250.h>
d29 1
a29 1
#include <al.h>
@


1.5
log
@new version provided y hal for v321
@
text
@@


1.4
log
@initial version prov by hal
@
text
@d21 1
a21 1
#include <con.h>
d23 3
a25 3
#include <stat.h>
#include <tty.h>
#include <uproc.h>
d28 1
a28 1
#include <sched.h>
@


1.3
log
@alxintr():  add irq_mode argument;  use alx.c 1.5
@
text
@d299 1
a299 1
	alxintr(irqtty, 1);
@


1.2
log
@Used in COH Release 3.1.0 - add COM3/COM4 and polling
@
text
@d7 3
d299 1
a299 1
	alxintr(irqtty);
@


1.1
log
@Used in COH Release 3.0.0 - no COM3/COM4
@
text
@d1 4
a4 8
/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
d6 4
a9 4
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
a14 37
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.2	89/03/31  16:16:50 	src
 * Bug:	Did not cancel timed functions during an unload.  This could result
 * 	in a system panic.
 * Fix:	Now cancels timed functions during an unload. (ABC)
 * 
 * Revision 2.1	88/09/03  06:02:24 	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:04:07	src
 * Initial revision
 * 
 * 88/01/23	Allan Cornish		/usr/src/sys/i8086/drv/al.c
 * Unload function added to support loadable device drivers.
 *
 * 86/12/12	Allan Cornish		/usr/src/sys/i8086/drv/al.c
 * Added 3rd argument to alpoll() to support non-blocking poll.
 *
 * 86/11/24	Allan Cornish		/usr/src/sys/i8086/drv/al.c
 * The new tty struct raw input and output buffers are now used.
 * Moved alstart() to alx.c/alxstart().
 * Replaced altime() by alxcycle().
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/i8086/drv/al.c
 * Added support for non-blocking read/write, and System V.3 compatible polls.
 * alintr() now uses defer() rather than timeout() to delay call to altime().
 * Increased raw input buffer size from 48 to 64 bytes.
 *
 * 86/07/27	Allan Cornish		/usr/src/sys/i8086/drv/al.c
 * Made alload() disable interrupts, and verify hardware existence.
 * Revised to use ins8250.h header file rather than wd8250.h.
 *
 * 85/06/27	Allan Cornish		/usr/src/sys/i8086/drv/al.c
 * Made alintr() recognize received XOFF characters immediately,
 * rather than deferring recognization through timeout() to altime().
 * This is necessary to avoid input buffer overflow in some printers.
d26 1
d28 4
d35 2
a36 1
 *	ALPORT	the io port address
d40 3
d46 11
a56 5
#ifdef ALCOM1		/* COM1 definitions */
#define ALPORT	0x3F8		/* Base of com1 port */
#define ALINT	4		/* Interrupt level of com1 port */
#define	ALNAME	a0con		/* CON name of com1 port */
#define ALMAJ	5		/* Major number of com1 port */
d59 11
a69 5
#ifdef ALCOM2		/* COM2 definitions */
#define ALPORT	0x2F8		/* Base of com2 port */
#define ALINT	3		/* Interrupt level of com2 port */
#define ALNAME	a1con		/* CON name of com2 port */
#define ALMAJ	6		/* Major number of com2 port */
a71 7
#ifdef ALCOM3		/* COM3 definitions */
#define ALPORT	0x2F0		/* Base of com3 port */
#define ALINT	2		/* Interrupt level of com3 port */
#define ALNAME	a2con		/* CON name of com3 port */
#define ALMAJ	3		/* Major number of com3 port */
#endif

d116 1
a116 1
 * Terminal structure.
d118 3
a120 1
static TTY	altty = { {0}, {0}, ALPORT, alxstart, alxparam, B9600, B9600 };
d122 14
d142 1
d144 6
a149 3
	s = sphi();
	if ( init == 0 ) {
		outb(ALPORT+IER, 0);	    /* disable port interrupts */
d151 13
a163 7
		if ( inb(ALPORT+IER) == 0 ) {
			outb(ALPORT+MCR, MC_OUT2);  /* hangup port */
			outb(ALPORT+LCR, LC_DLAB);
			outb(ALPORT+DLL, albaud[B9600] );
			outb(ALPORT+DLH, albaud[B9600] >> 8 );
			outb(ALPORT+LCR, LC_CS8 );
			setivec(ALINT, alintr);     /* set interrupt vector */
d165 21
a186 1
	spl( s );
d192 8
d201 2
a202 3
	outb(ALPORT+IER, 0);			/* disable port interrupts */
	outb(ALPORT+MCR, MC_OUT2);		/* hangup port */
	timeout( &altty.t_rawtim, 0, NULL, 0 );	/* cancel cyclic timer */
d210 6
a215 3
	alload();
	alxcycle( &altty );
	alxopen( dev, mode, &altty );
d225 1
a225 1
	if (--altty.t_open == 0) {	/* Last open */
d227 1
a227 1
		alxclose( dev, mode, &altty );
d237 1
a237 1
	ttread(&altty, iop, 0);
d251 1
a251 1
		ttwrite( &altty, iop, 0 );
a258 1

d281 1
a281 1
	alxioctl(dev, com, vec, &altty);
d290 1
a290 1
	return ttpoll( &altty, ev, msec );
d296 1
a296 1
	alxintr( &altty );
@
0707070064030105321004440000030000030000011777770507310647300005500000105463/newbits/kernel/USRSRC/i8086/drv/RCS/alx.c,vhead     1.12;
branch   ;
access   ;
symbols  ;
locks    bin:1.12;
comment  @ * @;


1.12
date     91.08.06.10.32.23;  author bin;  state Exp;
branches ;
next     1.11;

1.11
date     91.08.01.13.48.25;  author bin;  state Exp;
branches ;
next     1.10;

1.10
date     91.08.01.10.04.16;  author hal;  state Exp;
branches ;
next     1.9;

1.9
date     91.06.20.14.47.20;  author bin;  state Exp;
branches ;
next     1.8;

1.8
date     91.06.18.08.10.35;  author bin;  state Exp;
branches ;
next     1.7;

1.7
date     91.06.17.12.28.08;  author bin;  state Exp;
branches ;
next     1.6;

1.6
date     91.04.03.18.55.07;  author root;  state Exp;
branches ;
next     1.5;

1.5
date     91.04.02.17.53.37;  author root;  state Exp;
branches ;
next     1.4;

1.4
date     91.02.22.09.21.17;  author root;  state Exp;
branches ;
next     1.3;

1.3
date     91.02.21.14.58.16;  author root;  state Exp;
branches ;
next     1.2;

1.2
date     91.02.21.11.21.40;  author hal;  state Exp;
branches 1.2.1.1 1.2.2.1;
next     1.1;

1.1
date     91.02.21.11.08.31;  author hal;  state Exp;
branches ;
next     ;

1.2.1.1
date     91.02.21.12.37.34;  author root;  state Exp;
branches ;
next     ;

1.2.2.1
date     91.02.21.13.58.46;  author root;  state Exp;
branches ;
next     ;


desc
@@


1.12
log
@2nd rts/cts version form hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.7  91/08/02  07:59:27  hal
 * Raw input silo uses last slot for byte count.
 * Modem control now gives RTS/CTS flow control:
 * 	CTS is checked 10x/sec (probably not often enough).
 * 	On Rx_INT, check T_ISTOP and rawin silo levels; drop RTS if need to.
 * 
 * Revision 1.6	91/04/03  18:55:07	root
 * alxclose():  do closing state machine BEFORE dropping control lines.
 * alxioctl():  save and restore interrupt enable register.
 * alxopen():   wait for pending last close (fixes SLOW port bug).
 * This version needs al.h 1.3 or later.
 *
 * Revision 1.5	91/04/02  17:53:37	root
 * save MSR delta status; add MS_INTR handling; use al.h 1.2
 *
 * Revision 1.4	91/02/22  09:21:17	root
 * alxintr():  replace repeated use of ALPORT macro by local variable
 *
 * Revision 1.3	91/02/21  14:58:16	root
 * Fix unconditional "hupcl" bug in 3.1.0 version.
 *
 * Revision 1.2	91/02/21  11:21:40	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 *
 * Revision 1.1	91/02/21  11:08:31	hal
 * Used in COH Release 3.0.0 - no COM3/COM4
 *
 -lgl) */
/*
 * Shared parts of IBM async port drivers.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/al.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <sys/timeout.h>
#include <sys/clist.h>
#include <sys/ins8250.h>
#include <sys/sched.h>

#define ALPORT	(((COM_DDP *)(tp->t_ddp))->port)
#define AL_TIM	(((COM_DDP *)(tp->t_ddp))->tim)
#define AL_NUM	(((COM_DDP *)(tp->t_ddp))->com_num)
#define AL_MSR_DELTAS	(((COM_DDP *)(tp->t_ddp))->msr_deltas)
#define AL_H_CLOSE	(((COM_DDP *)(tp->t_ddp))->h_close)

#define DTRTMOUT  3	/* DTR timeout interval in seconds for close */
#define	IENABLE	(IE_RxI+IE_TxI+IE_LSI+IE_MSI)

/*
 * For rawin silo (see ktty.h), use last element of si_buf to count the number
 * of characters in the silo.
 */
#define SILO_CHAR_COUNT	si_buf[SI_BUFSIZ-1]
#define SILO_HIGH_MARK	(SI_BUFSIZ-SI_BUFSIZ/4)
#define MAX_SILO_INDEX	(SI_BUFSIZ-2)
#define MAX_SILO_CHARS	(SI_BUFSIZ-1)

int	al_sg_set = 0;
int	al_sg_clr = 0;
static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */

/*
 * functions herein
 */
int	alxopen();
int	alxclose();
int	alxtimer();
int	alxioctl();
int	alxparam();
int	alxcycle();
int	alxstart();
int	alxbreak();
int	alxintr();
static	int alxclk();
static	set_poll_rate();

/*
 * Baud rate table and polling rate table.
 * Indexed by ioctl bit rates.
 */
int albaud[] ={
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	alp_rate[] is tied to albaud[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int alp_rate[] ={			/* baud/6 or zero */
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	the following is for debug only
 */
#if 0
#define CDUMP(text)	cdump(text);

cdump(message)
char *message;
{
	int i, b;

	for (i = 0; i < NUM_AL_PORTS; i++) {
		b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
		printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
	}
	printf("poll=%d ", poll_rate);
	printf("%s\n", message);
}
#else
#define CDUMP(text)
#endif

/*
 * alxopen()
 */
alxopen(dev, mode, tp, irqtty)
dev_t	dev;
int	mode;
register TTY	*tp, **irqtty;
{
	register int	s;
	register int	b;
	register int	minor_h;  /* minor device number including high bit */
	unsigned char	msr;

	minor_h = minor(dev);     /* complete minor number */

	b = ALPORT;

	if (inb(b+IER) & ~IENABLE) { /* chip not found */
		u.u_error = ENXIO;
		return;
	}

	if ((tp->t_flags & T_EXCL) && !super()) {
		u.u_error = ENODEV;
		return;
	}

	if (drvl[major(dev)].d_time != 0) {	/* Modem settling */
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Can't open a polled port if another driver is using polling.
	 */
	if (dev & CPOLL && poll_owner & ~ POLL_AL) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * exclusion conditions:
	 *	can't have same port polled and IRQ at once
	 *	can't have both com[13] or both com[24] IRQ at once
	 */
	if (dev & CPOLL) {
		if (com_usage[AL_NUM] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	} else {
		if (com_usage[AL_NUM] == COM_POLLED
		   || com_usage[AL_NUM ^ 2] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	}

	if (tp->t_open == 0) {        /* not already open */
		/*
		 * Wait for pending last close (if any) to finish.
		 */
		while (AL_H_CLOSE) {
   	  		sleep((char *)(&AL_H_CLOSE), CVTTOUT, IVTTOUT,
				SVTTOUT);
		}
		s = sphi();
		/*
		 * Raise basic modem control lines even if modem
		 * control hasn't been specified.
		 * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
		 * since we can't have two UART's on same IRQ with MC_OUT2 on
		 */
		if (dev & CPOLL) {
			outb(b+MCR, MC_RTS|MC_DTR);
		} else {
			*irqtty = tp_table[AL_NUM];
			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
		}

		outb(b+IER, IENABLE);        /* enable interrupts */

		if ((minor_h & NMODC) == 0) {	/* want modem control? */
			tp->t_flags |= T_MODC | T_HOPEN | T_STOP;
			while (1) {	/* wait for carrier */
				msr = inb(b+MSR);
				AL_MSR_DELTAS |= msr;
				if (msr & MS_RLSD)
					break;
	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
					SVTTOUT);	/* wait for carrier */
		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
					outb(b+MCR, inb(b+MCR)&MC_OUT2);
	                    		/*
					 * make sure port is hungup
					 * disable all ints except for TxI
					 */
			    		outb(b+IER, IE_TxI);
					u.u_error = EINTR;
					spl(s);
					return;
				}
			}
			tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
			if (msr & MS_CTS)
				tp->t_flags &= ~T_STOP;
		} else {
			tp->t_flags &= ~T_MODC;		/* no modem control */
		}
	        tp->t_flags |= T_CARR;			/* carrier on */
		ttopen(tp);				/* stty inits */

		/*
		 * Allow custom modification of defaults.
		 */
		tp->t_sgttyb.sg_flags |=  al_sg_set;
		tp->t_sgttyb.sg_flags &= ~al_sg_clr;
		alxparam(tp);
		spl(s);
	} else {			        /* already open */
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
	   	    if ((tp->t_flags & T_MODC)==0) { /* already not modem control? */
			u.u_error = ENODEV;     /* yes, don't allow open */
			return;
		    }
		} else {		         /* don't want modem control */
			if (tp->t_flags & T_MODC) { /* already modem control? */
				u.u_error = ENODEV; /* yes, don't allow open */
				return;
			}
		}
	}
	tp->t_open++;
	ttsetgrp(tp, dev);

	/*
	 * now that we've successfully opened, designate port as
	 * polled or interrupt driven to avoid future conflicts
	 */
	if (dev & CPOLL) {
		com_usage[AL_NUM] = COM_POLLED;
		set_poll_rate();
	} else {				/* irq-driven port */
		com_usage[AL_NUM] = COM_IRQ;
	}

	CDUMP((dev&CPOLL)?"open polled":"open irq")
}

/*
 * alxclose()
 *
 *	Called at high priority on last close for the device.
 */
alxclose(dev, mode, tp)
dev_t	dev;
int	mode;
TTY	*tp;
{
	register unsigned holdflags;
	register int b;
	int state, maj;
	int s;

	/*
	 * Called at high priority by alclose after al_buff is drained
	 */
	holdflags = tp->t_flags;	/* save flags */
	AL_H_CLOSE = 1;			/* disallow reopen til done closing */
	ttclose(tp);			/* clear flags */
	b = ALPORT;
	/*
	 * ttclose() only emptied the output queue tp->t_oq;
	 * now wait for the silo tp->rawout to empty
	 * and allow a delay for the UART on-chip xmit buffer to empty
	 * state 2: waiting for silo to empty
	 * state 1: stalling so UART can empty xmit buffer
	 * state 0: done!  ok to shut off IRQ for this chip by clearing MC_OUT2
	 */
	state = 2;
	while (state) {
		timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
		sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
			state--;
	}

	/*
	 * If not hanging in open
	 */
	if ((holdflags & T_HOPEN) == 0) {
		/*
		 * Disable all ints except TxI
		 */
		outb(b+IER, IE_TxI);
	} else {
		/*
		 * Flags for first open
		 */
		tp->t_flags = T_MODC | T_HOPEN;
	}

	/*
	 * If hupcls
	 */
	if (holdflags & T_HPCL) {
		/*
		 * Hangup port
		 */
		s = sphi();
		outb(b+MCR, inb(b+MCR)&MC_OUT2);
		spl(s);

		/*
		 * Hold dtr low for timeout
		 */
		maj = major(dev);
		drvl[maj].d_time = 1;
		sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
		drvl[maj].d_time = 0;
	}
	s = sphi();
	outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
	spl(s);
	com_usage[AL_NUM] = COM_UNUSED;
	set_poll_rate();
	AL_H_CLOSE = 0;		/* allow reopen - done closing */
	wakeup((char *)&AL_H_CLOSE);
	CDUMP("closed")
}

/*
 * Common c_timer routine for async ports.
 */
alxtimer(dev)
dev_t dev;
{
	if (++drvl[major(dev)].d_time > DTRTMOUT)
		wakeup((char *)&drvl[major(dev)].d_time);
}


/*
 * Common c_ioctl routine for async ports.
 */
alxioctl(dev, com, vec, tp)
dev_t	dev;
struct sgttyb *vec;
register TTY 	*tp;
{
	register int	s, b;
	int stat1, stat2;
	unsigned char	msr;
	unsigned char ier_save;

	s = sphi();
	b = ALPORT;
	ier_save=inb(b+IER);
	stat1 = inb(b+MCR);		/* get current MCR register status */
	stat2 = inb(b+LCR);		/* get current LCR register status */

	switch(com) {
	case TIOCSBRK:			/* set BREAK */
		outb(b+LCR, stat2|LC_SBRK);
		break;
	case TIOCCBRK:			/* clear BREAK */
		outb(b+LCR, stat2 & ~LC_SBRK);
		break;
	case TIOCSDTR:			/* set DTR */
		outb(b+MCR, stat1|MC_DTR);
		break;
	case TIOCCDTR:			/* clear DTR */
		outb(b+MCR, stat1 & ~MC_DTR);
		break;
	case TIOCSRTS:			/* set RTS */
		outb(b+MCR, stat1|MC_RTS);
		break;
	case TIOCCRTS:			/* clear RTS */
		outb(b+MCR, stat1 & ~MC_RTS);
		break;
	case TIOCRSPEED:		/* set "raw" I/O speed divisor */
		outb(b+LCR, stat2|LC_DLAB);  /* set speed latch bit */
		outb(b+DLL, (unsigned) vec);
		outb(b+DLH, (unsigned) vec >> 8);
		outb(b+LCR, stat2);       /* reset latch bit */
		break;
	case TIOCWORDL:		/* set word length and stop bits */
		outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
		break;
	case TIOCRMSR:		/* get CTS/DSR/RI/RLSD (MSR) */
		msr = inb(b+MSR);
		AL_MSR_DELTAS |= msr;
		stat1 = msr >> 4;
		kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
		break;
	default:
		ttioctl(tp, com, vec);
	}
	outb(b+IER, ier_save);
	spl(s);
}

alxparam(tp)
TTY	*tp;
{
	register int	b;
	register int	baud;
	int s;

	b = ALPORT;

	/*
	 * error if input speed not the same as output speed
	 */
	if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
		u.u_error = ENODEV;
		return;
 	}

	if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
		if (tp->t_flags & T_MODC) {  /* modem control? */
			tp->t_flags &= ~T_CARR;  /* indicate no carrier */
			s = sphi();
			outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
			spl(s);
		}
	}

	if (baud) {
		unsigned char ier_save;

		s=sphi();
		ier_save=inb(b+IER);	/* some chips need this */
		outb(b+LCR, LC_DLAB);
		outb(b+DLL, baud);
		outb(b+DLH, baud >> 8);
		switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
		case EVENP:
			outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN);
			break;

		case ODDP:
			outb(b+LCR, LC_CS7 + LC_PARENB);
			break;

		default:
			outb(b+LCR, LC_CS8);
			break;
		}
		outb(b+IER, ier_save);
		spl(s);
	}
	set_poll_rate();
}

/*
 * Middle level processor.
 *
 *	Invoked 10 times per second.
 *	Checks modem status for loss of carrier.
 *	Tranfers rawin buffer [from intr level] to canonical input queue.
 *	Transfers output queue to rawout buffer [for intr level].
 */
alxcycle(tp)
register TTY * tp;
{
	register int b;
	register int n;
	unsigned char msr, mcr;
	int s;

	/*
	 * Check modem status every ten clock ticks.
	 *
	 * Modem status interrupts were not enabled due to 8250 hardware bug.
	 * Enabling modem status and receive interrupts may cause lockup
	 * on older parts.
	 *
	 * Also check if input silo is nearly full in case we need RTS
	 * flow control.
	 */
	if (tp->t_flags & T_MODC) {

		/*
		 * Get status
		 */
		msr = inb(ALPORT+MSR);
		AL_MSR_DELTAS |= msr;

		/*
		 * Carrier changed.
		 */
		if (AL_MSR_DELTAS & MS_DRLSD) {
			AL_MSR_DELTAS &= ~MS_DRLSD;
			/*
			 * wakeup open
			 */
			if (tp->t_open == 0) {
				wakeup((char *)(&tp->t_open));
			}

			/*
			 * carrier off?
			 */
			else if ((msr & MS_RLSD) == 0) {
				/*
				 * clear carrier flag; send hangup signal
				 */
				s = sphi();
				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
				tp->t_rawin.SILO_CHAR_COUNT = 0;
				spl(s);
				tthup(tp);
			}
		}

		/*
		 * CTS changed.
		 */
		if (AL_MSR_DELTAS & MS_DCTS) {
			AL_MSR_DELTAS &= ~MS_DCTS;
			if (msr & MS_CTS)
				tp->t_flags &= ~T_STOP;
			else
				tp->t_flags |= T_STOP;
		}

		/*
		 * If input silo not nearly full, assert RTS.
		 */
		if (tp->t_rawin.SILO_CHAR_COUNT <= SILO_HIGH_MARK) {
			mcr = inb(ALPORT+MCR);
			if ((mcr & MC_RTS) == 0) {
printf("%x RTS ON\n", ALPORT);
				outb(ALPORT+MCR, mcr | MC_RTS);
			}
		}
	}

	/*
	 * Empty raw input buffer.
	 * If modem control enabled and tt input queue is at high limit
	 * (e.g., tp->t_iq.cq_cc >= IHILIM), don't copy from rawin silo
	 * to tt input queue.
	 */
	if (!(tp->t_flags & T_MODC) || !(tp->t_flags & T_ISTOP))
		while (tp->t_rawin.SILO_CHAR_COUNT > 0) {
			ttin(tp, tp->t_rawin.si_buf[tp->t_rawin.si_ox]);
			if (tp->t_rawin.si_ox < MAX_SILO_INDEX)
				tp->t_rawin.si_ox++;
			else
				tp->t_rawin.si_ox = 0;
			tp->t_rawin.SILO_CHAR_COUNT--;
		}

	/*
	 * Calculate free output slot count.
	 */
	n  = sizeof(tp->t_rawout.si_buf) - 1;
	n += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	n %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ((--n >= 0) && ((b = ttout(tp)) >= 0)) {
		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = b;
		if (tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1)
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, wake sleeping processes, etc.
	 */
	ttstart(tp);

	/*
	 * Schedule next cycle.
	 */
	timeout(&tp->t_rawtim, HZ/10, alxcycle, tp);
}

/*
 * Serial Transmit Start Routine.
 */
alxstart(tp)
register TTY * tp;
{
	register int b;
	register int s;
	extern alxbreak();

	/*
	 * Read line status register AFTER disabling interrupts.
	 */
	s = sphi();
	b = inb(ALPORT+LSR);

	/*
	 * Process break indication.
	 * NOTE: Break indication cleared when line status register was read.
	 */
	if (b & LS_BREAK)
		defer(alxbreak, tp);

	/*
	 * Transmitter is empty, output data is pending.
	 */
	if ((b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox)) {
		outb(	ALPORT+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);
		if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
			tp->t_rawout.si_ox = 0;
	}
	spl(s);
}

/*
 * Serial Received Break Handler.
 */
alxbreak(tp)
TTY * tp;
{
	ttsignal(tp, SIGINT);
}

/*
 * Serial Interrupt Handler.
 */
alxintr(tp)
register TTY * tp;
{
	register int	b;
	int port = ALPORT;
	unsigned char mcr;

rescan:
	switch (inb(port+IIR)) {

	case LS_INTR:
		if (inb(port+LSR) & LS_BREAK)
			defer(alxbreak, tp);
		goto rescan;

	case Rx_INTR:
		b = inb(port+DREG);
		if (tp->t_open == 0)
			goto rescan;
		/*
		 * Must recognize XOFF quickly to avoid transmit overrun.
		 * Recognize XON here as well to avoid race conditions.
		 */
		if ((tp->t_sgttyb.sg_flags & RAWIN) == 0) {
			/*
			 * XOFF.
			 */
			if (tp->t_tchars.t_stopc == (b & 0177)) {
				tp->t_flags |= T_STOP;
				goto rescan;
			}

			/*
			 * XON.
			 */
			if (tp->t_tchars.t_startc == (b & 0177)) {
				tp->t_flags &= ~T_STOP;
				goto rescan;
			}
		}

		/*
		 * Save char in raw input buffer.
		 */
		if (tp->t_rawin.SILO_CHAR_COUNT < MAX_SILO_CHARS) {
			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = b;
			if (tp->t_rawin.si_ix < MAX_SILO_INDEX)
				tp->t_rawin.si_ix++;
			else
				tp->t_rawin.si_ix = 0;
			tp->t_rawin.SILO_CHAR_COUNT++;
		}
		if (tp->t_flags & T_MODC)
			if ((tp->t_flags & T_ISTOP)
			|| (tp->t_rawin.SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
				mcr = inb(port+MCR);
				if (mcr & MC_RTS) {
					outb(port+MCR, mcr & ~MC_RTS);
printf("%x RTS OFF\n", port);
				}
			}
		goto rescan;

	case Tx_INTR:
		/*
		 * Do nothing if no raw output data or output is stopped.
		 */
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox) {
			goto rescan;
		}
		if (tp->t_flags & T_STOP)
			goto rescan;

		/*
		 * Transmit next char in raw output buffer.
		 */
		outb(port+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ]);

		/*
		 * Adjust raw output buffer output index.
		 */
		if (++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf))
			tp->t_rawout.si_ox = 0;

		/*
		 * Try to fill buffer if now empty.
		 */
		if (tp->t_rawout.si_ox == tp->t_rawout.si_ix) {
			defer(alxcycle, tp);
		}
		goto rescan;

	case MS_INTR:
		AL_MSR_DELTAS |= inb(port+MSR);
		defer(alxcycle, tp);
		goto rescan;
	}
}

/*
 * alxclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int alxclk()
{
	static int count;
	int i;

	for (i = 0; i < NUM_AL_PORTS;  i++)
		if (com_usage[i] == COM_POLLED)
			alxintr(tp_table[i]);
	count++;
	if (count >= poll_divisor)
		count = 0;
	return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_AL)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
		if (com_usage[port_num] == COM_POLLED) {
			port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
			if (max_rate < port_rate)
				max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in alxclk() */
		altclk_out();		/* stop previous polling */
		poll_owner &= ~ POLL_AL;
		if (max_rate) {	/* resume polling at new rate if needed */
			poll_owner |= POLL_AL;
			altclk_in(poll_rate, alxclk);
		}
		CDUMP("new rate")
	}
}
@


1.11
log
@updated by hal to include rts/cts handshaking
@
text
@d6 7
a12 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d58 1
a58 1
#define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)
d65 1
a65 1
#define SILO_HIGH_MARK	(SI_BUFSIZ-26)
d327 1
d374 1
d376 1
d386 1
d388 1
d487 1
d489 1
d533 1
a533 1
	unsigned char	msr;
a537 2
	 * Modem status interrupts are not enabled due to 8250 hardware bug.
	 * Enabling modem status and receive interrupts may cause lockup.
d539 4
a550 1
		s = sphi();
a552 1
		spl(s);
d596 5
a600 1
			outb(ALPORT+MCR, inb(ALPORT+MCR) | MC_RTS);
d610 1
a610 1
	if (!(tp->t_flags & T_MODC) || !(tp->t_flags & T_ISTOP)) 
d701 1
d748 9
a756 4
		if ((tp->t_flags & T_MODC)
		&& (tp->t_rawin.SILO_CHAR_COUNT > SILO_HIGH_MARK)) {
			outb(port+MCR, inb(port+MCR) & ~MC_RTS);
		}
d772 1
a772 1
		outb(	port+DREG,
d791 1
@


1.10
log
@Fix '&' for '&=' in alxcycle().
@
text
@d12 1
a12 1
 * 
d15 1
a15 1
 * 
d18 1
a18 1
 * 
d21 1
a21 1
 * 
d24 1
a24 1
 * 
d54 9
d79 1
a79 1
static	int	alxclk();
d176 1
a176 1
	if ( inb(b+IER) & ~IENABLE ) { /* chip not found */
d202 1
a202 1
	 *	can't have both com[13] or both com[24] IRQ at once 
d238 1
a238 1
	
d240 1
a240 1
	
d242 1
a242 1
			tp->t_flags |= T_MODC | T_HOPEN; /* yes, set flags */
d263 2
d266 1
a266 1
			tp->t_flags &= ~T_MODC;		/* no modem control */ 
d281 1
a281 1
			u.u_error = ENODEV;     /* yes, don't allow open */	
d310 2
d348 1
a348 1
	if ( (holdflags & T_HOPEN) == 0 ) {
d391 1
a391 1
	if ( ++drvl[major(dev)].d_time > DTRTMOUT )
d416 1
a416 1
	case TIOCSBRK:			/* set BREAK */		
d424 1
a424 1
		break;	
d426 1
a426 1
		outb(b+MCR, stat1 & ~MC_DTR);	
d429 1
a429 1
		outb(b+MCR, stat1|MC_RTS);	
d432 2
a433 2
		outb(b+MCR, stat1 & ~MC_RTS);	
		break;	
d448 1
a448 1
		break;	
d469 1
a469 1
		u.u_error = ENODEV;	  
d490 1
a490 1
			outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN );
d494 1
a494 1
			outb(b+LCR, LC_CS7 + LC_PARENB );
d498 1
a498 1
			outb(b+LCR, LC_CS8 );
d515 1
a515 1
alxcycle( tp )
d524 1
a524 1
	 * Check modem status every clock tick.
d527 3
d531 1
a531 1
	if ( tp->t_flags & T_MODC ) {
d544 1
a544 1
		if ( AL_MSR_DELTAS & MS_DRLSD ) {
d549 1
a549 1
			if ( tp->t_open == 0 ) {
d556 1
a556 1
			else if ( (msr & MS_RLSD) == 0 ) {
d560 1
d562 3
a564 1
				tthup( tp );
d567 18
d589 3
d593 9
a601 7
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );
		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}
d613 1
a613 1
	while ( (--n >= 0) && ((b = ttout(tp)) >= 0) ) {
d615 1
a615 1
		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
d624 1
a624 1
	ttstart( tp );
d629 1
a629 1
	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
d635 1
a635 1
alxstart( tp )
d652 2
a653 2
	if ( b & LS_BREAK )
		defer( alxbreak, tp );
d658 1
a658 1
	if ( (b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
d660 2
a661 2
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
d664 1
a664 1
	spl( s );
d670 2
a671 2
alxbreak( tp )
register TTY * tp;
d673 1
a673 1
	ttsignal( tp, SIGINT );
d679 1
a679 1
alxintr( tp )
d686 1
a686 1
	switch ( inb(port+IIR) ) {
d689 2
a690 2
		if ( inb(port+LSR) & LS_BREAK )
			defer( alxbreak, tp );
d695 1
a695 1
		if ( tp->t_open == 0 )
d701 1
a701 1
		if ( (tp->t_sgttyb.sg_flags & RAWIN) == 0 ) {
d705 1
a705 1
			if ( tp->t_tchars.t_stopc == (b & 0177) ) {
d713 1
a713 1
			if ( tp->t_tchars.t_startc == (b & 0177) ) {
d722 12
a733 3
		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
			tp->t_rawin.si_ix = 0;
d740 1
a740 1
		if ( tp->t_rawout.si_ix == tp->t_rawout.si_ox ) {
d743 1
a743 1
		if ( tp->t_flags & T_STOP )
d750 1
a750 1
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
d755 1
a755 1
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
d761 2
a762 2
		if ( tp->t_rawout.si_ox == tp->t_rawout.si_ix ) {
			defer( alxcycle, tp );
d765 1
a765 1
		
@


1.9
log
@update provided by hal
@
text
@d529 1
a529 1
			AL_MSR_DELTAS & ~MS_DRLSD;
@


1.8
log
@update provided by hal
@
text
@d32 3
a34 3
#include <coherent.h>
#include <i8086.h>
#include <al.h>
d41 2
a42 2
#include <clist.h>
#include <ins8250.h>
@


1.7
log
@new version provided y hal for v321
@
text
@@


1.6
log
@alxclose():  do closing state machine BEFORE dropping control lines.
alxioctl():  save and restore interrupt enable register.
alxopen():   wait for pending last close (fixes SLOW port bug).
This version needs al.h 1.3 or later.
@
text
@d7 6
d35 1
a35 1
#include <con.h>
d37 3
a39 3
#include <stat.h>
#include <tty.h>
#include <uproc.h>
d43 1
a43 1
#include <sched.h>
@


1.5
log
@save MSR delta status; add MS_INTR handling; use al.h 1.2
@
text
@d7 3
d43 1
d144 3
d203 7
d217 1
a217 1
		if (dev & CPOLL)
d219 1
a219 1
		else {
d291 3
d306 3
a308 2
	holdflags = tp->t_flags;       /* save flags */
	ttclose(tp);		       /* clear flags */
d310 15
d349 1
a357 15
	/*
	 * ttclose() only emptied the output queue tp->t_oq;
	 * now wait for the silo tp->rawout to empty
	 * and allow a delay for the UART on-chip xmit buffer to empty
	 * state 2: waiting for silo to empty
	 * state 1: stalling so UART can empty xmit buffer
	 * state 0: done!  ok to shut off IRQ for this chip by clearing MC_OUT2
	 */
	state = 2;
	while (state) {
		timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
		sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
			state--;
	}
d361 2
d388 1
d392 1
d433 1
d462 1
a462 1
		char ier_save=inb(b+IER);	/* some chips need this */
d465 1
@

			else if ( (b & MS_RLSD) == 0 ) {
d683 4
@
	outb(	ALPORT+DREG,
@


1.2
log
@Used in COH Release 3.1.0 - add COM3/COM4 and polling
@
text
@d7 3
d327 1
a327 1
	outb(b+MCR, 0);
@


1.2.2.1
log
@Multiple changes for Larry Rachman
@
text
@d1 2
a2 1
/* (-lgl * 	COHERENT Driver Kit Version 1.1.0
a4 4
 -lgl) */
 
/*
 * This branch (1.2.2) has these additions to the COH 3.1.0 release:
a5 8
 * Extended diagnostics (more calls to CDUMP).
 * Save & restore IER during calls to alxioctl().
 * Add case to alxintr() to clear MS_INTR.
 * Add msr_deltas field to COM_DDP struct.
 * Save MSR delta bits whenever MSR is read.
 * Do software edge trigger during alxintr().
 * Replace repeated uses of ALPORT macro in alxintr() by local variable.
 *
a6 3
 * Revision 1.2	91/02/21  11:21:40	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 * 
d9 2
a10 2
 */
 
a29 1
#define AL_MSR_DELTAS	(((COM_DDP *)(tp->t_ddp))->msr_deltas)
d36 1
a36 1
static	int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
d111 1
a111 1
#if 1
a137 1
	char msr;
d203 1
a203 5
			while (1) {	/* wait for carrier */
				msr = inb(b+MSR);
				AL_MSR_DELTAS |= msr;
				if (msr & MS_RLSD)
					break;
a350 2
	char ier_save;
	char msr;
a351 1
CDUMP("start ioctl")
a353 1
	ier_save=inb(b+IER);		/* some chips need this */
d386 1
a386 3
		msr = inb(b+MSR);
		AL_MSR_DELTAS |= msr;
		stat1 = msr >> 4;
a391 1
	outb(b+IER, ier_save);
a392 1
CDUMP("end ioctl")
d401 1
a401 2
	
CDUMP("start set params")
a442 1
CDUMP("end set params")
a457 2
	int s;
	char msr;
d469 1
a469 4
		s = sphi();
		msr = inb(ALPORT+MSR);
		AL_MSR_DELTAS |= msr;
		spl(s);
d474 1
a474 2
		if ( AL_MSR_DELTAS & MS_DRLSD ) {
			AL_MSR_DELTAS & ~MS_DRLSD;
d485 1
a485 1
			else if ( (msr & MS_RLSD) == 0 ) {
a585 1
	int port = ALPORT;
d588 1
a588 1
	switch ( inb(port+IIR) ) {
d591 1
a591 1
		if ( inb(port+LSR) & LS_BREAK )
d596 1
a596 1
		b = inb(port+DREG);
d642 1
a642 1
		outb(	port+DREG,
a657 4
		
	case MS_INTR:
		AL_MSR_DELTAS |= inb(port+MSR);
		goto rescan;
a658 9
	/*
	 * Some UARTs need the following on edge-triggered interrupt systems.
	 */
	{ 
		char ier_save;
		ier_save=inb(port+IER);
		outb(port+IER,0);
		outb(port+IER,ier_save);
	}	
@


1.2.1.1
log
@Preliminary Enahancements for Esa Ahola
@
text
@a6 3
 * Revision 1.2	91/02/21  11:21:40	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 * 
a9 7
 * Add IE_ALL bit mask and use it when checking for UART existence.
 * Save delta status of CD - but not on per port basis.
 * Fix unconditional "hupcl" bug in 3.1.0 version.
 * Add RTS handshaking.
 * Add CTS handshaking.
 * Save and restore IER during alxioctl() call as well as alxparam().
 *
a32 1
#define IE_ALL	(IE_RxI|IE_TxI|IE_LSI|IE_MSI)
a36 4
static int drlsd;	/* delta carrier detect - set by alxintr(), read
			   by alxcycle() */
static int rawin_ct;	/* number of characters in input silo */			   
static int want_rts;
d143 1
a143 1
	if ( inb(b+IER) & ~IE_ALL ) { /* chip not found */
a197 1
		want_rts = 1;
a207 1
					want_rts = 0;
a300 1
		want_rts = 0;
d324 1
a324 4
	/*
	 * Turn off MC_OUT2 so IRQ can be used by other port.
	 */
	outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
a350 1
	char ier_save;
a352 1
	ier_save=inb(b+IER);	/* some chips need this */
a391 1
	outb(b+IER, ier_save);
a415 1
			want_rts = 0;
d474 1
a474 2
		if ((b & MS_DRLSD) || drlsd) {
			drlsd = 0;
a489 1
				rawin_ct = 0;
a504 3
	rawin_ct = 0;
	if (want_rts)
		outb(b+MCR, inb(b+MCR) | MC_RTS);
d627 1
a627 8
			rawin_ct++;
		/*
		 * Preliminary code!
		 * De-assert RTS if we are close to filling the input silo.
		 */	
		if (want_rts && (sizeof(tp->t_rawin.si_buf) - rawin_ct < 4))
			outb(b+MCR, inb(b+MCR) & ~MC_RTS);
			goto rescan;
a657 16
		
	case MS_INTR:
		/*
		 * This is preliminary code - use delta of CTS from
		 * modem to implement flow control.
		 *
		 * Sense delta of RLSD for use by alxcycle().
		 */
		b = inb(ALPORT+MSR);
		if (b & MS_DCTS)
			if (b & MS_CTS)
				tp->t_flags &= ~T_STOP;
			else
				tp->t_flags |= T_STOP;
		if (b & MS_DRLSD)
			drlsd = 1;		
@


1.1
log
@Used in COH Release 3.0.0 - no COM3/COM4
@
text
@d1 10
a12 42
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	90/06/07  14:10:04 	bin
 * steve 6/7/90
 * On last line of alxopen(), changed dev_t argument in ttsetgrp() call
 * from "dev&~NMODC" to "dev".  The old version masked off the modem control
 * bit, so e.g. opening /dev/com2l set the process tty field p_ttdev to
 * /dev/com2r instead of com2l;  then a subsequent open of /dev/tty would
 * fail, because alxopen() would find the device already open with modem control
 * and return ENXIO; thus, /dev/tty would not work on the serial port.
 * 
 * Revision 1.1	90/06/07  14:06:13 	bin
 * Initial MWC RCS revision, as received from Inetco.
 * 
 * Revision 2.3	89/08/01  14:21:52 	src
 * Bug:	#include <timeout.h> not accurate; timeout.h now in /usr/include/sys.
 * Fix:	#include <sys/timeout.h> now used. (ABC)
 * 
 * Revision 2.2	89/03/31  15:28:43 	src
 * Bug:	Break interrupt not always received properly in CBREAK mode.
 * Fix:	Line status register is read during output check as well
 * 	as during interrupts.  Reading the register clears the break
 * 	indication.  Output check now services break indication (ABC).
 * 
 * Revision 2.1	88/09/03  13:02:35	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:04:11	src
 * Initial revision
 * 
 * 87/07/08	Allan Cornish		/usr/src/sys/i8086/drv/alx.c
 * alxcycle() now programs timeout in HZ/10 seconds, rather than 1 clock tick.
 *
 * 86/11/24	Allan Cornish		/usr/src/sys/i8086/drv/alx.c
 * alxcycle(), alxstart(), and alxintr() routines added.
 *
 * 86/07/27	Allan Cornish		/usr/src/sys/i8086/drv/alx.c
 * Revised to use ins8250.h header file rather than wd8250.h.
 *
 * 85/07/18	Allan Cornish
 * Created al_sg_set and al_sg_clr variables, which contain sg_flag bits
 * to be set and cleared, respectively, on first open of al[01][m].
d16 1
d27 4
a30 2
#define ALPORT	((unsigned)tp->t_ddp)
#define minor_st(dev)	(dev&0177)
d34 3
a36 2
int al_sg_set = 0;
int al_sg_clr = 0;
d39 16
a54 1
 * Baud rate table.
d80 27
d108 23
a130 1
alxopen(dev, mode, tp)
d133 1
a133 1
register TTY	*tp;
d141 1
a141 4
	if (minor_st(dev) >= 1) {	/* minor without high bit */
		u.u_error = ENXIO;
		return;
	}
a142 2
	b = ALPORT;

d148 2
a149 2
	if ((tp->t_flags & T_EXCL) && !super()) 
	{	u.u_error = ENODEV;
d152 3
a154 2
	if (drvl[major(dev)].d_time != 0)	/* Modem settling */
	{	u.u_error = EDBUSY;
a156 2
	if (tp->t_open == 0) {        /* not already open */
	   s = sphi();
d158 7
a164 2
     	   /* Raise basic modem control lines even if modem */
	   /* control hasn't been specified.		    */
d166 17
a182 2
   	   outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);   /* raise lines (yes, MC_OUT2!) */
	   outb(b+IER, IENABLE);        /* enable interrupts */
d184 40
a223 2
	   if ((minor_h & NMODC) == 0) {  /* want modem control? */
	      tp->t_flags |= T_MODC | T_HOPEN;  /* yes, set flags */
d225 19
a243 26
	      while ((inb(b+MSR) & MS_RLSD) == 0) {  /* no carrier? */
   	  	 sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
			SVTTOUT);  /* wait for carrier */
	 	 if (SELF->p_ssig && nondsig()) {  /* signal? */
	            outb(b+MCR, MC_OUT2);    /* make sure port is hungup */
		    outb(b+IER, IE_TxI);     /* disable all ints but TxI */
		    u.u_error = EINTR;
   		    spl(s);
	   	    return;
 		 }
	      }
 	      tp->t_flags &= ~T_HOPEN;   /* no longer hanging in open */
	   }
	   else
              tp->t_flags &= ~T_MODC;    /* no modem control */ 

           tp->t_flags |= T_CARR;        /* carrier on */

	   ttopen(tp);   		 /* stty inits */
	   /*
	    * Allow custom modification of defaults.
	    */
	   tp->t_sgttyb.sg_flags |=  al_sg_set;
	   tp->t_sgttyb.sg_flags &= ~al_sg_clr;
	   alxparam(tp);
	   spl(s);
a244 13
	else 			         /* already open */
	{  if ((minor_h & NMODC) == 0)   /* want modem control? */
	   {  if ((tp->t_flags & T_MODC)==0)  /* already not modem control? */
	      {  u.u_error = ENODEV;     /* yes, don't allow open */	
	         return;
	      }
	   }
	   else			         /* don't want modem control */
	      if (tp->t_flags & T_MODC)  /* already modem control? */
	      {  u.u_error = ENODEV;     /* yes, don't allow open */	   
	         return;
	      }	   
	}
d247 13
d269 1
d286 1
a286 2
	}
	else {
d300 1
a300 2
		outb(b+MCR, MC_OUT2);

d304 4
a307 4
		b = major(dev);
		drvl[b].d_time = 1;
		sleep((char *)&drvl[b].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
		drvl[b].d_time = 0;
d309 19
d354 2
a355 2
	stat1 = inb(b+MCR);      /* get current MCR register status */
	stat2 = inb(b+LCR);	 /* get current LCR register status */
d358 1
a358 1
	case TIOCSBRK:		/* set BREAK */		
d361 1
a361 1
	case TIOCCBRK:		/* clear BREAK */
d364 1
a364 1
	case TIOCSDTR:		/* set DTR */
d367 1
a367 1
	case TIOCCDTR:		/* clear DTR */
d370 1
a370 1
	case TIOCSRTS:		/* set RTS */
d373 1
a373 1
	case TIOCCRTS:		/* clear RTS */
d376 1
a376 1
	case TIOCRSPEED:	/* set "raw" I/O speed divisor */
d400 1
d404 3
a406 1
	/* error if input speed not the same as output speed */
d408 2
a409 2
	   u.u_error = ENODEV;	  
	   return;
d412 5
a416 6
	if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) 
	{  if (tp->t_flags & T_MODC)    /* modem control? */
	   {   tp->t_flags &= ~T_CARR;  /* indicate no carrier */
	       outb(b+MCR, MC_OUT2);       /* hangup */
	   }
	   return;
d419 2
a420 7
	outb(b+LCR, LC_DLAB);
	outb(b+DLL, baud);
	outb(b+DLH, baud >> 8);
	switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
	case EVENP:
		outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN );
		return;
d422 8
a429 3
	case ODDP:
		outb(b+LCR, LC_CS7 + LC_PARENB );
		return;
d431 10
a440 3
	default:
		outb(b+LCR, LC_CS8 );
		return;
d442 1
a474 1

a498 1

a499 1

a516 1

a517 1

a561 1

a563 1

a596 1

a598 1

a603 1

a624 1

d633 1
a633 1
		if ( tp->t_rawout.si_ix == tp->t_rawout.si_ox )
d635 1
d654 1
a654 1
		if ( tp->t_rawout.si_ox == tp->t_rawout.si_ix )
d656 1
d660 60
@
0707070064030104351004440000030000030000011777770507310650300005400000075311/newbits/kernel/USRSRC/i8086/drv/RCS/at.c,vhead     1.8;
branch   ;
access   ;
symbols  ;
locks    bin:1.8;
comment  @ * @;


1.8
date     91.06.20.14.47.50;  author bin;  state Exp;
branches ;
next     1.7;

1.7
date     91.06.18.08.10.54;  author bin;  state Exp;
branches ;
next     1.6;

1.6
date     91.06.17.12.28.56;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.05.22.15.06.59;  author hal;  state Exp;
branches ;
next     1.4;

1.4
date     91.03.14.14.22.32;  author root;  state Exp;
branches ;
next     1.3;

1.3
date     91.03.05.08.56.39;  author root;  state Exp;
branches ;
next     1.2;

1.2
date     91.03.05.08.55.18;  author root;  state Exp;
branches ;
next     1.1;

1.1
date     91.03.05.08.53.51;  author root;  state Exp;
branches ;
next     ;


desc
@Device driver for ST506 AT-style hard drive controller.
@


1.8
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.5  91/05/22  15:06:59  hal
 * Don't force 8's bit of control byte.
 * 
 * Revision 1.4	91/03/14  14:22:32	hal
 *
 -lgl) */
/*
 * This is a driver for the
 * hard disk on the AT.
 *
 * Reads drive characteristics from ROM (thru interrupt vector 0x41 and 0x46).
 * Reads partition information from disk.
 */
#include	<sys/coherent.h>
#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>

extern	saddr_t	sds;		/* System Data Selector */

/*
 * Configurable parameters
 */
#define	HDMAJOR	11			/* Major Device Number */
#define	HDIRQ	14			/* Level 14 */
#define	HDBASE	0x01F0			/* Port base */
#define NDRIVE	2			/* only two drives supported */
#define	SOFTLIM	6			/*  (7) num of retrys before diag */
#define	HARDLIM	8			/* number of retrys before fail */
#define	BADLIM	100			/* num to stop recov if flagged bad */

#define	BIT(n)		(1 << (n))

#define	CMOSA	0x70			/* write cmos address to this port */
#define	CMOSD	0x71			/* read cmos data through this port */

#ifndef	ATCACHE
#	if VERBOSE > 0
#		define	ATCACHE	2	/* local cache size in blocks */
#	else
#		define	ATCACHE 0	/* no cache for small code */
#	endif
#endif

/*
 * Driver configuration.
 */
void	atload();
void	atunload();
void	atopen();
void	atread();
void	atwrite();
int	atioctl();
void	atwatch();
void	atblock();
int	nulldev();
int	nonedev();

CON	atcon	= {
	DFBLK|DFCHR,			/* Flags */
	HDMAJOR,			/* Major index */
	atopen,				/* Open */
	nulldev,			/* Close */
	atblock,			/* Block */
	atread,				/* Read */
	atwrite,			/* Write */
	atioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	atwatch,			/* Timeout */
	atload,				/* Load */
	atunload			/* Unload */
};

/*
 * Forward Referenced Functions.
 */
void	atreset();
int	atdequeue();
void	atstart();
void	atintr();
void	atdefer();
int	aterror();
void	atrecov();
void	atdone();

/*
 * I/O Port Addresses
 */
#define	DATA_REG	(HDBASE+0)	/* data (r/w) */
#define	AUX_REG		(HDBASE+1)	/* error(r), write precomp cyl/4 (w) */
#define	NSEC_REG	(HDBASE+2)	/* sector count (r/w) */
#define	SEC_REG		(HDBASE+3)	/* sector number (r/w) */
#define	LCYL_REG	(HDBASE+4)	/* low cylinder (r/w) */
#define	HCYL_REG	(HDBASE+5)	/* high cylinder (r/w) */
#define	HDRV_REG	(HDBASE+6)	/* drive/head (r/w) (D<<4)+(1<<H) */
#define	CSR_REG		(HDBASE+7)	/* status (r), command (w) */
#define	HF_REG		0x3F6

/*
 * Error from AUX_REG (r)
 */
#define	DAM_ERR		BIT(0)		/* data address mark not found */
#define	TR0_ERR		BIT(1)		/* track 000 not found */
#define	ABT_ERR		BIT(2)		/* aborted command */
#define	ID_ERR		BIT(4)		/* id not found */
#define	ECC_ERR		BIT(6)		/* data ecc error */
#define	BAD_ERR		BIT(7)		/* bad block detect */

/*
 * Status from CSR_REG (r)
 */
#define	ERR_ST		BIT(0)		/* error occurred */
#define	INDEX_ST	BIT(1)		/* index pulse */
#define	SOFT_ST		BIT(2)		/* soft (corrected) ECC error */
#define	DRQ_ST		BIT(3)		/* data request */
#define	SKC_ST		BIT(4)		/* seek complete */
#define	WFLT_ST		BIT(5)		/* improper drive operation */
#define	RDY_ST		BIT(6)		/* drive is ready */
#define	BSY_ST		BIT(7)		/* controller is busy */


/*
 * Commands to CSR_REG (w)
 */
#define	RESTORE(rate)	(0x10+(rate))	/* X */
#define	SEEK(rate)	(0x70+(rate))	/* X */
#define	READ_CMD	(0x20)		/* X */
#define	WRITE_CMD	(0x30)		/* X */
#define	FORMAT_CMD	(0x50)		/* X */
#define	VERIFY_CMD	(0x40)		/* X */
#define	DIAGNOSE_CMD	(0x90)		/* X */
#define	SETPARM_CMD	(0x91)		/* X */

/*
 * Device States.
 */
#define	SIDLE	0			/* controller idle */
#define	SRETRY	1			/* seeking */
#define	SREAD	2			/* reading */
#define	SWRITE	3			/* writing */

/*
 * Drive Parameters - copied from ROM.
 * If patched, use the given values instead of reading from the ROM.
 * NOTE: Exactly duplicates hdparm_s struct.
 */
struct dparm_s {
	unsigned short	d_ncyl;		/* number of cylinders */
	unsigned char	d_nhead;	/* number of heads */
	unsigned short	d_rwcc;		/* reduced write current cyl */
	unsigned short	d_wpcc;		/* write pre-compensation cyl */
	unsigned char	d_eccl;		/* max ecc data length */
	unsigned char	d_ctrl;		/* control byte */
	unsigned char	d_fill2[3];
	unsigned short	d_landc;	/* landing zone cylinder */
	unsigned char	d_nspt;		/* number of sectors per track */
	unsigned char	d_fill3;

}	atparm[ NDRIVE ] = {
	0				/* Initialized to allow patching */
};

/*
 * Partition Parameters - copied from disk.
 *
 *	There are NDRIVE * NPARTN positions for the user partitions,
 *	plus NDRIVE additional partitions to span each drive.
 *
 *	Aligning partitions on cylinder boundaries:
 *	Optimal partition size: 2 * 3 * 4 * 5 * 7 * 17 = 14280 blocks
 *	Acceptable partition size:  3 * 4 * 5 * 7 * 17 =  7140 blocks
 */
static
struct fdisk_s pparm[NDRIVE*NPARTN + NDRIVE];

/*
 * Per disk controller data.
 * Only one controller; no more, no less.
 */
static
struct	at	{
	BUF		*at_actf;	/* Link to first */
	BUF		*at_actl;	/* Link to last */
	faddr_t		at_faddr;	/* Source/Dest virtual address */
	daddr_t		at_bno;		/* Block # on disk */
	unsigned	at_nsec;	/* # of sectors on current transfer */
	unsigned	at_drv;
	unsigned	at_head;
	unsigned	at_cyl;
	unsigned	at_sec;
	unsigned	at_partn;
	unsigned char	at_dtype[ NDRIVE ];	/* drive type, 0 if unused */
	unsigned char	at_tries;
	unsigned char	at_state;
	unsigned char	at_caching;		/* caching in progress */
#if	ATCACHE > 0
	unsigned char	at_cdrv[ ATCACHE ];	/* cached drive */
	daddr_t		at_cbno[ ATCACHE ];	/* cached block number */
	unsigned char *	at_cbuf[ ATCACHE ];	/* cached block */
#endif
	unsigned	at_bad_drv;
	unsigned	at_bad_head;
	unsigned	at_bad_cyl;
}	at;

static BUF	dbuf;			/* For raw I/O */

int	ATBSYW = 50;			/* patchable */
static char timeout_msg[] = "at%d: TO\n";

/**
 *
 * void
 * atload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void
atload()
{
	register int u;
	register struct dparm_s * dp;
	struct { unsigned off, seg; } p;

	/*
	 * Obtain Drive Types.
	 *
	 *	High nibble of CMOS 0x12 is drive 0's type.
	 *	Low  nibble of CMOS 0x12 is drive 1's type.
	 */
	outb( CMOSA, 0x12 );
	/* delay */
	u = inb(CMOSD);
	at.at_dtype[0] = u >> 4;
	at.at_dtype[1] = u & 15;

	/*
	 * Interrupt Vector 0x41 points to Drive 0 Characteristics.
	 */
	pkcopy( (paddr_t) (0x41*4), &p, sizeof p );

	/*
	 * Obtain Drive Characteristics.
	 */
	for ( u = 0, dp = &atparm[0]; u < NDRIVE; ++dp, ++u ) {

		if ( dp->d_ncyl == 0 ) {
			/* Not patched, use the ROM drive table values. */
			pkcopy( (paddr_t) (p.seg << 4L) + p.off,
				dp, sizeof(*dp) );
		}
		else {
			/*
			 * Avoid incomplete patching.
			 */
			if (at.at_dtype[u] == 0)
				at.at_dtype[u] = 1;
			if ( dp->d_nspt == 0 )
				dp->d_nspt = 17;
#if FORCE_CTRL_8
			if ( dp->d_nhead > 8 )
				dp->d_ctrl |= 8;
#endif

#if VERBOSE > 0
			printf(
	"at%d: ncyl=%d nhead=%d wpcc=%d eccl=%d ctrl=%d landc=%d nspt=%d\n",
				u,
				dp->d_ncyl,
				dp->d_nhead,
				dp->d_wpcc,
				dp->d_eccl,
				dp->d_ctrl,
				dp->d_landc,
				dp->d_nspt );
#endif
		}

		/*
		 * Interrupt Vector 0x46 points to Drive 1 Characteristics.
		 */
		pkcopy( (paddr_t) (0x46*4), &p, sizeof p );
	}

	/*
	 * Initialize Drive Size.
	 */
	for ( u = 0, dp = &atparm[0]; u < NDRIVE; ++dp, ++u ) {

		if ( at.at_dtype[u] == 0 )
			continue;

		pparm[NDRIVE*NPARTN + u].p_size =
			(long) dp->d_ncyl * dp->d_nhead * dp->d_nspt;
	}

	/*
	 * Initialize Drive Controller.
	 */
	atreset();

	setivec( HDIRQ, atintr );

#if ATCACHE > 0
	at.at_cdrv[0] = -1;
	at.at_cbuf[0] = kalloc( BSIZE );
#endif

#if ATCACHE > 1
	at.at_cdrv[1] = -1;
	at.at_cbuf[1] = kalloc( BSIZE );
#endif

	at.at_bad_drv = -1;
}

/**
 *
 * void
 * atunload()	- unload routine.
 */
static void
atunload()
{
	clrivec( HDIRQ );
}

/**
 *
 * void
 * atreset()	-- reset hard disk controller, define drive characteristics.
 */
static void
atreset()
{
	register int u;
	register struct dparm_s * dp;

	/*
	 * Reset controller for a minimum of 4.8 microseconds.
	 */
	outb( HF_REG, 4 );
	for ( u = 100; --u != 0; )
		;
	outb( HF_REG, atparm[0].d_ctrl & 0x0F );
	myatbsyw(0);
	if ( inb(AUX_REG) != 0x01 )
		printf("at: AT disk controller not present (reset)\n");

	/*
	 * Initialize drive parameters.
	 */
	for ( u = 0, dp = &atparm[0]; u < NDRIVE; ++dp, ++u ) {

		if ( at.at_dtype[u] == 0 )
			continue;

		myatbsyw(u);

		/*
		 * Set drive characteristics.
		 * 0x1F1 - AUX_REG
		 * 0x1F2 - NSEC_REG
		 * 0x1F3 - SEC_REG
		 * 0x1F4 - LCYL_REG
		 * 0x1F5 - HCYL_REG
		 * 0x1F6 - HDRV_REG
		 * 0x1F7 - CSR_REG
		 */
		outb( HF_REG,	dp->d_ctrl );
		outb( AUX_REG,  dp->d_wpcc / 4 );
		outb( NSEC_REG, dp->d_nspt );
		outb( SEC_REG, 0x01 );
		outb( LCYL_REG, (char)(dp->d_ncyl) );
		outb( HCYL_REG, (char)(dp->d_ncyl >> 8) );
		outb( HDRV_REG, 0xA0 + (u<<4) + dp->d_nhead - 1 );
		outb( CSR_REG,  SETPARM_CMD );
		myatbsyw(u);

		/*
		 * Restore heads.
		 */
		outb( CSR_REG, RESTORE(0) );
		myatbsyw(u);
	}
}

/**
 *
 * void
 * atopen( dev, mode )
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void
atopen( dev, mode )
register dev_t	dev;
{
	register int d;		/* drive */
	register int p;		/* partition */

	p = minor(dev) % (NDRIVE*NPARTN);

	if ( minor(dev) & SDEV ) {
		d = minor(dev) % NDRIVE;
		p += NDRIVE * NPARTN;
	}
	else
		d = minor(dev) / NPARTN;

	if ( (d >= NDRIVE) || (at.at_dtype[d] == 0) ) {
		u.u_error = ENXIO;
		return;
	}

	if ( minor(dev) & SDEV )
		return;

	/*
	 * If partition not defined read partition characteristics.
	 */
	if ( pparm[p].p_size == 0 )
		fdisk( makedev( major(dev), SDEV + d), &pparm[ d * NPARTN ] );

	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	if ((pparm[p].p_base+pparm[p].p_size) > pparm[d+NDRIVE*NPARTN].p_size)
		u.u_error = EBADFMT;
	else if ( pparm[p].p_size == 0 )
		u.u_error = ENODEV;
}

/**
 *
 * void
 * atread( dev, iop )	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
atread( dev, iop )
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
}

/**
 *
 * void
 * atwrite( dev, iop )	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
atwrite( dev, iop )
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
}

/**
 *
 * int
 * atioctl( dev, cmd, arg )
 * dev_t dev;
 * int cmd;
 * char * vec;
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static int
atioctl( dev, cmd, vec )
register dev_t	dev;
int cmd;
char * vec;
{
	int d;

	/*
	 * Identify drive number.
	 */
	if ( minor(dev) & SDEV )
		d = minor(dev) % NDRIVE;
	else
		d = minor(dev) / NPARTN;

	/*
	 * Identify input/output request.
	 */
	switch ( cmd ) {

	case HDGETA:
		/*
		 * Get hard disk attributes.
		 */
		kucopy( &atparm[d], vec, sizeof(atparm[0]) );
		return( 0 );

	case HDSETA:
		/* Set hard disk attributes. */
		ukcopy(vec, &atparm[d], sizeof(atparm[0]));
		at.at_dtype[d] = 1;		/* set drive type nonzero */
		pparm[NDRIVE * NPARTN + d].p_size =
			(long) atparm[d].d_ncyl * atparm[d].d_nhead * atparm[d].d_nspt;
		atreset();
		return 0;

	default:
		u.u_error = EINVAL;
		return( -1 );
	}
}

/**
 *
 * void
 * atwatch()		- guard against lost interrupt
 *
 *	Action:	If drvl[HDMAJOR] is greater than zero, decrement it.
 *		If it decrements to zero, simulate a hardware interrupt.
 */
static void
atwatch()
{
	register BUF * bp = at.at_actf;
	register int s;

	s = sphi();
	if ( --drvl[HDMAJOR].d_time > 0 ) {
		spl(s);
		return;
	}
	printf("at%d%c: bno=%U head=%u cyl=%u <Watchdog Timeout>\n",
		at.at_drv,
		(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
		bp->b_bno, at.at_head, at.at_cyl );

	/*
	 * Reset hard disk controller.
	 *
	 * Mark current cylinder as bad so atstart() will fail.
	 * Otherwise would lock up if this track NEVER gives enough IRQ's.
	 */
	at.at_bad_drv	= at.at_drv;
	at.at_bad_head	= at.at_head;
	at.at_bad_cyl	= at.at_cyl;
	atreset();
	atstart();
	spl(s);
}

/**
 *
 * void
 * atblock( bp )	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void
atblock(bp)
register BUF	*bp;
{
	register struct fdisk_s *pp;
	int partn = minor(bp->b_dev) % (NDRIVE*NPARTN);

	bp->b_resid = bp->b_count;

	if ( minor(bp->b_dev) & SDEV )
		partn += NDRIVE * NPARTN;

	pp = &pparm[ partn ];

	/*
	 * Check for read at end of partition.
	 */
	if ( (bp->b_req == BREAD) && (bp->b_bno == pp->p_size) ) {
		bdone(bp);
		return;
	}

	/*
	 * Range check disk region.
	 */
	if ( ((bp->b_bno + (bp->b_count/BSIZE)) > pp->p_size)
	|| (bp->b_count % BSIZE) || bp->b_count == 0) {
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}

	bp->b_actf = NULL;
	if (at.at_actf == NULL)
		at.at_actf = bp;
	else
		at.at_actl->b_actf = bp;
	at.at_actl = bp;

	if ( at.at_state == SIDLE )
		if ( atdequeue() )
			atstart();
}

/**
 *
 * int
 * atdequeue()		- obtain next disk read/write operation
 *
 *	Action:	Pull some work from the disk queue.
 *
 *	Return:	0 = no work.
 *		* = work to do.
 */
static int
atdequeue()
{
	register BUF * bp;
	register struct fdisk_s * pp;
	unsigned int nspt;

	for (;;) {
		at.at_caching = 0;
		at.at_tries   = 0;

		if ( (bp = at.at_actf) == NULL )
			return (0);

		at.at_partn = minor( bp->b_dev ) % (NDRIVE*NPARTN);

		if ( minor(bp->b_dev) & SDEV ) {
			at.at_partn += (NDRIVE*NPARTN);
			at.at_drv  = minor( bp->b_dev ) % NDRIVE;
		}
		else
			at.at_drv = minor( bp->b_dev ) / NPARTN;
		nspt = atparm[at.at_drv].d_nspt;

		pp = &pparm[ at.at_partn ];
		at.at_bno   = pp->p_base + bp->b_bno;
		at.at_nsec  = bp->b_count / BSIZE;
		at.at_faddr = bp->b_faddr;

#if ATCACHE > 0
		if ( bp->b_req == BWRITE ) {

			/*
			 * Invalidate cache if write might overlap.
			 */
			if ( at.at_nsec > 1 ) {
				at.at_cdrv[0] = -1;
#if ATCACHE > 1
				at.at_cdrv[1] = -1;
#endif
			}
			else if ( at.at_bno == at.at_cbno[0] )
				at.at_cdrv[0] = -1;
#if ATCACHE > 1
			else if ( at.at_bno == at.at_cbno[1] )
				at.at_cdrv[1] = -1;
#endif
		}
		else if ( at.at_nsec == 1 ) {

			/*
			 * Test for cache hit on block 0.
			 */
			if ( (at.at_drv == at.at_cdrv[0])
			&&   (at.at_bno == at.at_cbno[0]) ) {

				kpcopy( at.at_cbuf[0],
					bp->b_paddr, BSIZE );
				at.at_actf  = bp->b_actf;
				bp->b_resid = 0;
				bdone(bp);
				continue;
			}

#if ATCACHE > 1
			/*
			 * Test for cache hit on block 1.
			 */
			if ( (at.at_drv == at.at_cdrv[1])
			&&   (at.at_bno == at.at_cbno[1]) ) {

				kpcopy( at.at_cbuf[1],
					bp->b_paddr, BSIZE );
				at.at_actf  = bp->b_actf;
				bp->b_resid = 0;
				bdone(bp);
				continue;
			}
#endif

			/*
			 * Enable caching if no backlog for disk i/o.
			 */
			if ( bp->b_actf == NULL ) {
				/*
				 * Enable caching on single block reads
				 * when at least one block left on same track.
				 */
				at.at_caching = nspt - 1 - (at.at_bno % nspt);
#if ATCACHE > 1
				if ( at.at_caching >= 2 ) {
					at.at_caching   = 2;
					at.at_cdrv[2-1] = -1;
				}
#endif

				if ( at.at_caching ) {
					at.at_nsec  += at.at_caching;
					at.at_cdrv[1-1] = -1;
				}
			}
		}
#endif

		return (1);
	}
}

/**
 *
 * void
 * atstart()	- start or restart next disk read/write operation.
 *
 *	Action:	Initiate disk read/write operation.
 */
static void
atstart()
{
	register struct dparm_s *dp;

	dp = &atparm[ at.at_drv ];

	at.at_cyl  = (at.at_bno / dp->d_nspt) / dp->d_nhead;
	at.at_head = (at.at_bno / dp->d_nspt) % dp->d_nhead;
	at.at_sec  = (at.at_bno % dp->d_nspt) + 1;

	/*
	 * Check for repeated access to most recently identified bad track.
	 */
	if ( (at.at_drv  == at.at_bad_drv )
	  && (at.at_cyl  == at.at_bad_cyl )
	  && (at.at_head == at.at_bad_head) ) {
	  	BUF * bp = at.at_actf;
		printf( "at%d%c: bno=%U head=%u cyl=%u <Track Flagged Bad>\n",
			at.at_drv,
			(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
			bp->b_bno,
			at.at_head,
			at.at_cyl );
		bp->b_flag |= BFERR;
		atdone(bp);
		return;
	}

	myatbsyw(at.at_drv);

	outb( HF_REG,   dp->d_ctrl );
	outb( AUX_REG,  dp->d_wpcc / 4 );
	outb( NSEC_REG, at.at_nsec );
	outb( SEC_REG,  at.at_sec );
	outb( LCYL_REG, at.at_cyl );
	outb( HCYL_REG, at.at_cyl >> 8 );
	outb( HDRV_REG, (at.at_drv << 4) + at.at_head + 0xA0 );

	if ( at.at_actf->b_req == BWRITE ) {

		outb( CSR_REG, WRITE_CMD );

		while ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

		atsend( at.at_faddr );
		at.at_state = SWRITE;
	}
	else {
		outb( CSR_REG, READ_CMD );
		at.at_state = SREAD;
	}
	drvl[HDMAJOR].d_time = 2;
}

/**
 *
 * void
 * atintr()	- Interrupt routine.
 *
 */
static void
atintr()
{
	defer( atdefer, 0 );
}

/**
 *
 * void
 * atdefer()	- Deferred service of hard disk interrupt.
 *
 *	Action:	Service disk interrupt.
 *		Transfer required data.
 *		Update state.
 */
static void
atdefer()
{
	register BUF * bp = at.at_actf;

	switch ( at.at_state ) {

	case SRETRY:
		atstart();
		break;

	case SREAD:
		/*
		 * Check for I/O error before waiting for data.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

		/*
		 * Wait for data, or forever.
		 */
		if ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

#if ATCACHE > 0
		/*
		 * Cache data block.
		 */
		if ( at.at_caching == at.at_nsec )
			atrecv( at.at_cbuf[ at.at_nsec - 1 ], sds );
		else
#endif

		/*
		 * Read data block.
		 */
			atrecv( at.at_faddr );

		/*
		 * Check for I/O error after reading data.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

#if ATCACHE > 0
		/*
		 * Validate cached blocks.
		 */
		if ( at.at_caching == at.at_nsec ) {
			at.at_cbno[ at.at_nsec - 1 ] = at.at_bno;
			at.at_cdrv[ at.at_nsec - 1 ] = at.at_drv;
			at.at_caching--;
		}
		else
#endif
		{
			FP_OFF(at.at_faddr) += BSIZE;
			bp->b_resid -= BSIZE;
		}

		at.at_tries = 0;
		at.at_bno++;

		/*
		 * Check for end of transfer.
		 */
		if ( --at.at_nsec == 0 )
			atdone( bp );
		break;

	case SWRITE:
		/*
		 * Check for I/O error.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

		FP_OFF(at.at_faddr) += BSIZE;
		bp->b_resid -= BSIZE;
		at.at_tries  = 0;
		at.at_bno++;

		/*
		 * Check for end of transfer.
		 */
		if ( --at.at_nsec == 0 ) {
			atdone( bp );
			break;
		}

		/*
		 * Wait for ability to send data, or forever.
		 */
		while ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

		/*
		 * Send data block.
		 */
		atsend( at.at_faddr );
	}
}

/**
 *
 * int
 * aterror()
 *
 *	Action:	Check for drive error.
 *		If found, increment error count and report it.
 *
 *	Return: 0 = No error found.
 *		1 = Error occurred.
 */
static int
aterror()
{
	register BUF * bp = at.at_actf;
	register int csr;
	register int aux;

	if ( (csr = inb(CSR_REG)) & (ERR_ST|WFLT_ST) ) {

		aux = inb(AUX_REG);

		/*
		 * Don't retry or report failures on cache reads.
		 */
#if ATCACHE > 0
		if ((at.at_state == SREAD) && (at.at_caching == at.at_nsec)) {
			at.at_tries = BADLIM;
			return 1;
		}
#endif

		if ( aux & BAD_ERR ) {
			at.at_tries	= BADLIM;
			at.at_bad_drv	= at.at_drv;
			at.at_bad_head	= at.at_head;
			at.at_bad_cyl	= at.at_cyl;
		}
		else if ( ++at.at_tries < SOFTLIM )
			return 1;

		printf( "at%d%c: bno=%U head=%u cyl=%u",
			at.at_drv,
			(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
			(bp->b_count/BSIZE) + bp->b_bno
				+ at.at_caching - at.at_nsec,
			at.at_head, at.at_cyl );

#if VERBOSE > 0
		if ( (csr & RDY_ST) == 0 )
			printf(" <Drive Not Ready>");
		if ( csr & WFLT_ST )
			printf(" <Write Fault>");

		if ( aux & DAM_ERR )
			printf(" <No Data Addr Mark>");
		if ( aux & TR0_ERR )
			printf(" <Track 0 Not Found>" );
		if ( aux & ID_ERR )
			printf(" <ID Not Found>" );
		if ( aux & ECC_ERR )
			printf(" <Bad Data Checksum>" );
		if ( aux & ABT_ERR )
			printf(" <Command Aborted>" );
#else
		if ( (csr & (RDY_ST|WFLT_ST)) != RDY_ST )
			printf( " csr=%x", csr );
		if ( aux & (DAM_ERR|TR0_ERR|ID_ERR|ECC_ERR|ABT_ERR) )
			printf( " aux=%x", aux );
#endif
		if ( aux & BAD_ERR )
			printf(" <Block Flagged Bad>" );

		if ( at.at_tries < HARDLIM )
			printf(" retrying...");
		printf("\n");
		return 1;
	}
	return 0;
}

/**
 *
 * void
 * atrecov()
 *
 *	Action:	Attempt recovery.
 */
static void
atrecov()
{
	register BUF *bp = at.at_actf;
	register int cmd = SEEK(0);
	register int cyl = at.at_cyl;

	switch ( at.at_tries ) {

	case 1:
	case 2:
		/*
		 * Move in 1 cylinder, then retry operation
		 */
		if ( --cyl < 0 )
			cyl += 2;
		break;

	case 3:
	case 4:
		/*
		 * Move out 1 cylinder, then retry operation
		 */
		if ( ++cyl >= atparm[ at.at_drv ].d_ncyl )
			cyl -= 2;
		break;

	case 5:
	case 6:
		/*
		 * Seek to cylinder 0, then retry operation
		 */
		cyl = 0;
		break;

	default:
		/*
		 * Restore drive, then retry operation
		 */
		cmd = RESTORE(0);
		cyl = 0;
		break;
	}

	/*
	 * Retry operation [after repositioning head]
	 */
	if ( at.at_tries < HARDLIM ) {
		drvl[HDMAJOR].d_time = (cmd == RESTORE(0)) ? 5 : 2;
		outb( LCYL_REG, cyl );
		outb( HCYL_REG, cyl >> 8 );
		outb( HDRV_REG, (at.at_drv << 4) + 0xA0 );
		outb( CSR_REG, cmd );
		at.at_state = SRETRY;
	}

	/*
	 * Give up on block.
	 */
	else {
		/*
		 * Not a cache-read error.
		 */
#if ATCACHE > 0
		if ( (at.at_state != SREAD) || (at.at_caching != at.at_nsec) )
#endif
			bp->b_flag |= BFERR;

		atdone(bp);
	}
}

/**
 *
 * void
 * atdone( bp )
 * BUF * bp;
 *
 *	Action:	Release current i/o buffer to the O/S.
 */
static void
atdone( bp )
register BUF * bp;
{
	drvl[HDMAJOR].d_time = 0;
	at.at_state = SIDLE;
	at.at_actf  = bp->b_actf;
	bdone(bp);

	if ( atdequeue() )
		atstart();
}

int
myatbsyw(unit) int unit;
{
	register int n, status;

	for (n = ATBSYW; n > 0; --n)
		if ((status = atbsyw()) != 0)
			return status;
	printf(timeout_msg, unit);
	return 0;
}
@


1.7
log
@update provided by hal
@
text
@d20 1
a20 1
#include	<coherent.h>
@


1.6
log
@new version provided y hal for v321
@
text
@d748 396
@


1.5
log
@Don't force 8's bit of control byte.
@
text
@d6 4
a9 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
a747 396
					at.at_nsec  += at.at_caching;
					at.at_cdrv[1-1] = -1;
				}
			}
		}
#endif

		return (1);
	}
}

/**
 *
 * void
 * atstart()	- start or restart next disk read/write operation.
 *
 *	Action:	Initiate disk read/write operation.
 */
static void
atstart()
{
	register struct dparm_s *dp;

	dp = &atparm[ at.at_drv ];

	at.at_cyl  = (at.at_bno / dp->d_nspt) / dp->d_nhead;
	at.at_head = (at.at_bno / dp->d_nspt) % dp->d_nhead;
	at.at_sec  = (at.at_bno % dp->d_nspt) + 1;

	/*
	 * Check for repeated access to most recently identified bad track.
	 */
	if ( (at.at_drv  == at.at_bad_drv )
	  && (at.at_cyl  == at.at_bad_cyl )
	  && (at.at_head == at.at_bad_head) ) {
	  	BUF * bp = at.at_actf;
		printf( "at%d%c: bno=%U head=%u cyl=%u <Track Flagged Bad>\n",
			at.at_drv,
			(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
			bp->b_bno,
			at.at_head,
			at.at_cyl );
		bp->b_flag |= BFERR;
		atdone(bp);
		return;
	}

	myatbsyw(at.at_drv);

	outb( HF_REG,   dp->d_ctrl );
	outb( AUX_REG,  dp->d_wpcc / 4 );
	outb( NSEC_REG, at.at_nsec );
	outb( SEC_REG,  at.at_sec );
	outb( LCYL_REG, at.at_cyl );
	outb( HCYL_REG, at.at_cyl >> 8 );
	outb( HDRV_REG, (at.at_drv << 4) + at.at_head + 0xA0 );

	if ( at.at_actf->b_req == BWRITE ) {

		outb( CSR_REG, WRITE_CMD );

		while ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

		atsend( at.at_faddr );
		at.at_state = SWRITE;
	}
	else {
		outb( CSR_REG, READ_CMD );
		at.at_state = SREAD;
	}
	drvl[HDMAJOR].d_time = 2;
}

/**
 *
 * void
 * atintr()	- Interrupt routine.
 *
 */
static void
atintr()
{
	defer( atdefer, 0 );
}

/**
 *
 * void
 * atdefer()	- Deferred service of hard disk interrupt.
 *
 *	Action:	Service disk interrupt.
 *		Transfer required data.
 *		Update state.
 */
static void
atdefer()
{
	register BUF * bp = at.at_actf;

	switch ( at.at_state ) {

	case SRETRY:
		atstart();
		break;

	case SREAD:
		/*
		 * Check for I/O error before waiting for data.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

		/*
		 * Wait for data, or forever.
		 */
		if ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

#if ATCACHE > 0
		/*
		 * Cache data block.
		 */
		if ( at.at_caching == at.at_nsec )
			atrecv( at.at_cbuf[ at.at_nsec - 1 ], sds );
		else
#endif

		/*
		 * Read data block.
		 */
			atrecv( at.at_faddr );

		/*
		 * Check for I/O error after reading data.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

#if ATCACHE > 0
		/*
		 * Validate cached blocks.
		 */
		if ( at.at_caching == at.at_nsec ) {
			at.at_cbno[ at.at_nsec - 1 ] = at.at_bno;
			at.at_cdrv[ at.at_nsec - 1 ] = at.at_drv;
			at.at_caching--;
		}
		else
#endif
		{
			FP_OFF(at.at_faddr) += BSIZE;
			bp->b_resid -= BSIZE;
		}

		at.at_tries = 0;
		at.at_bno++;

		/*
		 * Check for end of transfer.
		 */
		if ( --at.at_nsec == 0 )
			atdone( bp );
		break;

	case SWRITE:
		/*
		 * Check for I/O error.
		 */
		if ( aterror() ) {
			atrecov();
			break;
		}

		FP_OFF(at.at_faddr) += BSIZE;
		bp->b_resid -= BSIZE;
		at.at_tries  = 0;
		at.at_bno++;

		/*
		 * Check for end of transfer.
		 */
		if ( --at.at_nsec == 0 ) {
			atdone( bp );
			break;
		}

		/*
		 * Wait for ability to send data, or forever.
		 */
		while ( atdrqw() == 0 )
			printf( timeout_msg, at.at_drv );

		/*
		 * Send data block.
		 */
		atsend( at.at_faddr );
	}
}

/**
 *
 * int
 * aterror()
 *
 *	Action:	Check for drive error.
 *		If found, increment error count and report it.
 *
 *	Return: 0 = No error found.
 *		1 = Error occurred.
 */
static int
aterror()
{
	register BUF * bp = at.at_actf;
	register int csr;
	register int aux;

	if ( (csr = inb(CSR_REG)) & (ERR_ST|WFLT_ST) ) {

		aux = inb(AUX_REG);

		/*
		 * Don't retry or report failures on cache reads.
		 */
#if ATCACHE > 0
		if ((at.at_state == SREAD) && (at.at_caching == at.at_nsec)) {
			at.at_tries = BADLIM;
			return 1;
		}
#endif

		if ( aux & BAD_ERR ) {
			at.at_tries	= BADLIM;
			at.at_bad_drv	= at.at_drv;
			at.at_bad_head	= at.at_head;
			at.at_bad_cyl	= at.at_cyl;
		}
		else if ( ++at.at_tries < SOFTLIM )
			return 1;

		printf( "at%d%c: bno=%U head=%u cyl=%u",
			at.at_drv,
			(bp->b_dev & SDEV) ? 'x' : at.at_partn % NPARTN + 'a',
			(bp->b_count/BSIZE) + bp->b_bno
				+ at.at_caching - at.at_nsec,
			at.at_head, at.at_cyl );

#if VERBOSE > 0
		if ( (csr & RDY_ST) == 0 )
			printf(" <Drive Not Ready>");
		if ( csr & WFLT_ST )
			printf(" <Write Fault>");

		if ( aux & DAM_ERR )
			printf(" <No Data Addr Mark>");
		if ( aux & TR0_ERR )
			printf(" <Track 0 Not Found>" );
		if ( aux & ID_ERR )
			printf(" <ID Not Found>" );
		if ( aux & ECC_ERR )
			printf(" <Bad Data Checksum>" );
		if ( aux & ABT_ERR )
			printf(" <Command Aborted>" );
#else
		if ( (csr & (RDY_ST|WFLT_ST)) != RDY_ST )
			printf( " csr=%x", csr );
		if ( aux & (DAM_ERR|TR0_ERR|ID_ERR|ECC_ERR|ABT_ERR) )
			printf( " aux=%x", aux );
#endif
		if ( aux & BAD_ERR )
			printf(" <Block Flagged Bad>" );

		if ( at.at_tries < HARDLIM )
			printf(" retrying...");
		printf("\n");
		return 1;
	}
	return 0;
}

/**
 *
 * void
 * atrecov()
 *
 *	Action:	Attempt recovery.
 */
static void
atrecov()
{
	register BUF *bp = at.at_actf;
	register int cmd = SEEK(0);
	register int cyl = at.at_cyl;

	switch ( at.at_tries ) {

	case 1:
	case 2:
		/*
		 * Move in 1 cylinder, then retry operation
		 */
		if ( --cyl < 0 )
			cyl += 2;
		break;

	case 3:
	case 4:
		/*
		 * Move out 1 cylinder, then retry operation
		 */
		if ( ++cyl >= atparm[ at.at_drv ].d_ncyl )
			cyl -= 2;
		break;

	case 5:
	case 6:
		/*
		 * Seek to cylinder 0, then retry operation
		 */
		cyl = 0;
		break;

	default:
		/*
		 * Restore drive, then retry operation
		 */
		cmd = RESTORE(0);
		cyl = 0;
		break;
	}

	/*
	 * Retry operation [after repositioning head]
	 */
	if ( at.at_tries < HARDLIM ) {
		drvl[HDMAJOR].d_time = (cmd == RESTORE(0)) ? 5 : 2;
		outb( LCYL_REG, cyl );
		outb( HCYL_REG, cyl >> 8 );
		outb( HDRV_REG, (at.at_drv << 4) + 0xA0 );
		outb( CSR_REG, cmd );
		at.at_state = SRETRY;
	}

	/*
	 * Give up on block.
	 */
	else {
		/*
		 * Not a cache-read error.
		 */
#if ATCACHE > 0
		if ( (at.at_state != SREAD) || (at.at_caching != at.at_nsec) )
#endif
			bp->b_flag |= BFERR;

		atdone(bp);
	}
}

/**
 *
 * void
 * atdone( bp )
 * BUF * bp;
 *
 *	Action:	Release current i/o buffer to the O/S.
 */
static void
atdone( bp )
register BUF * bp;
{
	drvl[HDMAJOR].d_time = 0;
	at.at_state = SIDLE;
	at.at_actf  = bp->b_actf;
	bdone(bp);

	if ( atdequeue() )
		atstart();
}

int
myatbsyw(unit) int unit;
{
	register int n, status;

	for (n = ATBSYW; n > 0; --n)
		if ((status = atbsyw()) != 0)
			return status;
	printf(timeout_msg, unit);
	return 0;
}
@


1.4
log
@Don't barf if trying to read part of a block in raw device
@
text
@d6 2
a7 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d268 1
d271 1
@


1.3
log
@General fixes added so we also work with Perstor PS180-16FN HDC
@
text
@d5 3
d616 2
a617 1
	if ( (bp->b_bno + (bp->b_count/BSIZE)) > pp->p_size ) {
@


1.2
log
@Shipped with COHERENT driver kit 1.1.0
@
text
@d364 7
d375 3
d380 1
a381 2
		myatbsyw(u);

d383 1
a383 1
		 * Seek to cylinder 0, set step rate to 35 microseconds.
d385 1
a385 5
		outb( LCYL_REG, 0 );
		outb( HCYL_REG, 0 );
		outb( HDRV_REG, (u << 4) + 0xA0 );
		outb( CSR_REG, SEEK(0) );

d559 1
a559 3

#if EBUG > 0
	printf("at%d%c: bno=%U head=%u cyl=%u reset controller\n",
d562 1
a562 3
		bp->b_bno,
		at.at_head, at.at_cyl );
#endif
d566 3
a568 1
	 * Retry operation.
d570 3
a979 2

#if EBUG == 0
a981 1
#endif
@


1.1
log
@Released with COHERENT 3.0.0
@
text
@d1 5
d8 1
a8 1
 * hard disk on the IBM AT machine.
a11 1
 *
d147 1
d195 1
a195 1
	unsigned char	at_dtype[ NDRIVE ];
d252 1
d260 2
d350 1
a350 1
		printf("at: reset failure\n" );
d517 1
a517 1
		kucopy( &atparm[d], vec, sizeof(hdparm_t) );
d520 9
d640 1
d657 1
d723 1
a723 1
				at.at_caching = 16 - (at.at_bno % 17);
@
0707070064030104331004440000030000030000011777770507310651300005600000005060/newbits/kernel/USRSRC/i8086/drv/RCS/atas.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    ;
comment  @@;


1.2
date     91.05.30.09.19.35;  author hal;  state Exp;
branches ;
next     1.1;

1.1
date     91.05.30.09.17.53;  author hal;  state Exp;
branches ;
next     ;


desc
@Assembler i/o for "at" driver.
@


1.2
log
@Extend loop timers for faster 486's.
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ AT Hard Disk Assembler Support
/
/ atsend( off, seg ) - send 512 bytes from seg:off into hard disk buffer
/ atrecv( off, seg ) - receive 512 bytes from hard disk buffer into seg:off.
/ DRQ is not checked.  DRQ must be true before atsend/atrecv are called.
/
/ atbsyw()	     - wait while controller is busy
/ atdrqw()	     - wait for controller to request data transfer
/
////////

	.globl	atsend_
	.globl	atrecv_
	.globl	atbsyw_
	.globl	atdrqw_

	CSR_REG	= 0x01F7
	BSY_ST	= 0x80
	DRQ_ST	= 0x08

////////
/
/ void
/ atsend( fp )	-- send 512 bytes to AT disk controller.
/ faddr_t fp;
/
/	Input:	fp = far pointer [sel:off] to data buffer.
/
/	Action:	Transfer 512 bytes to AT disk controller from buffer.
/
////////

atsend_:
	push	si
	push	ds
	push	bp
	mov	bp, sp
	lds	si, 8(bp)
	mov	cx, $256
	mov	dx, $0x1F0
	cld
	rep
	outs
	pop	bp
	pop	ds
	pop	si
	ret

////////
/
/ void
/ atrecv( fp )	-- receive 512 bytes from AT disk controller.
/ faddr_t fp;
/
/	Input:	fp = far pointer [sel:off] to data buffer.
/
/	Action:	Transfer 512 bytes from AT disk controller to buffer.
/
////////

atrecv_:
	push	di
	push	es
	push	bp
	mov	bp, sp
	les	di, 8(bp)
	mov	cx, $256
	mov	dx, $0x1F0
	cld
	rep
	ins
	pop	bp
	pop	es
	pop	di
	ret

////////
/
/ atbsyw()	-- wait for AT disk controller to become not busy
/
/	Return:	0 = timeout
/		* = not busy
/
////////

atbsyw_:
	mov	dx, $CSR_REG
	mov	bx, $4		/ add another layer of iteration for 486's
0:	mov	cx, $-1
1:	inb	al, dx
	testb	al, $BSY_ST
	loopne	1b
	je	2f		/ not busy - return nonzero value
	dec	bx
	jne	0b
2:	mov	ax, cx
	ret

////////
/
/ atdrqw()	-- wait for AT disk controller to initiate data request
/
/	Return:	0 = timeout
/		* = data requested
/
////////

atdrqw_:
	mov	dx, $CSR_REG
	mov	bx, $4
0:	mov	cx, $-1
1:	inb	al, dx
	testb	al, $DRQ_ST
	loope	1b
	jne	2f		/ not busy - return nonzero value
	dec	bx
	jne	0b
2:	mov	ax, cx
	ret
@


1.1
log
@Shipped with COH 3.0.0 and 3.1.0.
@
text
@a93 1
	mov	cx, $-1
d95 3
a97 1
0:	inb	al, dx
d99 5
a103 2
	loopne	0b
	mov	ax, cx
a115 1
	mov	cx, $-1
d117 3
a119 1
0:	inb	al, dx
d121 5
a125 2
	loope	0b
	mov	ax, cx
@
0707070064030104341004440000030000030000011777770507310651300005600000007607/newbits/kernel/USRSRC/i8086/drv/RCS/bufq.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3;
comment  @ * @;


1.3
date     91.06.20.14.48.32;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.05.21.23.23.36;  author hal;  state Exp;
branches ;
next     1.1;

1.1
date     91.05.21.13.54.11;  author root;  state Exp;
branches ;
next     ;


desc
@Generic block device queueing.
@


1.3
log
@update provided by hal
@
text
@/*
 * File:	bufq.c
 *
 * Purpose:
 *	Queueing routines for SCSI driver.
 *	Should be generalizable for other hard drives.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2  91/05/21  23:23:36  hal
 * Enhanced debug printout.
 * 
 * Revision 1.1  91/05/21  13:54:11  root
 * First running version.
 * 
 */

/*
 * Includes.
 */
#include <sys/coherent.h>
#include <sys/buf.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */
typedef struct {
	BUF	* head;	/* point to first node */
	BUF	* tail;	/* point to last node */
	int	count;	/* number of nodes in the queue */
} bufq_type;

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
static int	num_q;		/* number of queues in use */
static bufq_type  * bufq_q;	/* pointer to allocated queue structs */

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
int bufq_init();
void bufq_rlse();
void bufq_wr_tail();
BUF * bufq_rd_head();
BUF * bufq_rm_head();

/*
 * Debug macros.
 */
#if (DEBUG >= 3)
#define QSIZE	printf("Q%d:%d ", s_id, bqp->count)
#else
#if (DEBUG >= 2)
#define QSIZE	{if (bqp->count>1)printf("Q%d:%d ", s_id, bqp->count);}
#else
#define QSIZE
#endif
#endif

/*
 * bufq_init()
 *
 * Set up the desired number of queues.
 *
 * Return 1 if ok, 0 if kalloc() failed.
 */
int bufq_init(qcount)
int qcount;
{
	int ret;

	if (qcount > 0 && (bufq_q = kalloc(qcount*sizeof(bufq_type)))) {
		ret = 1;
		kclear(bufq_q, qcount*sizeof(bufq_type));
		num_q = qcount;
#if (DEBUG >= 2)
printf("%d queues allocated\n", qcount);
#endif
	} else
		ret = 0;

	return ret;
}

/*
 * bufq_rlse()
 *
 * Deallocate buffer queue structs.
 */
void bufq_rlse()
{
	num_q = 0;
	if (bufq_q)
		kfree(bufq_q);
}

/*
 * bufq_wr_tail()
 *
 * Append a BUF object to the doubly-linked queue.
 * Object to be inserted has been allocated by the caller.
 * Run at high priority.
 */
void bufq_wr_tail(s_id, bp)
int s_id;
BUF * bp;
{
	int s;
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		s = sphi();
		if (bqp->count == 0) {
			bqp->head = bqp->tail = bp;
			bp->b_actf = bp->b_actl = NULL;
		} else {
			bqp->tail->b_actf = bp;
			bp->b_actf = NULL;
			bp->b_actl = bqp->tail;
			bqp->tail = bp;
		}
		bqp->count++;
QSIZE;
		spl(s);
	}
}

/*
 * bufq_rd_head()
 *
 * Nondestructively fetch the head entry in the queue - i.e., this routine
 * does not remove an entry from the queue (see ss_rm_head() for that).
 * Return NULL if queue is empty, else return pointer to head item.
 */
BUF * bufq_rd_head(s_id)
int s_id;
{
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		return bqp->head;
	} else
		return NULL;
}

/*
 * bufq_rm_head()
 *
 * Delete head item from the queue.  Return a pointer to the node deleted,
 * or NULL if the queue was already empty.
 * Run at high priority.
 *
 * This routine does NOT deallocate the node.  That must be done by the
 * calling function after this routine runs.
 */
BUF * bufq_rm_head(s_id)
int s_id;
{
	BUF * ret;
	int s;
	bufq_type * bqp;

	if (s_id < num_q) {
		bqp = bufq_q + s_id;
		s = sphi();
		if (bqp->count > 0) {
			ret = bqp->head;
			if (bqp->count == 1) {
				bqp->head = bqp->tail = NULL;
			} else {
				bqp->head = bqp->head->b_actf;
				bqp->head->b_actl = NULL;
			}
			bqp->count--;
QSIZE;
		} else
			ret = NULL;
		spl(s);
	} else
		ret = NULL;

	return ret;
}
@


1.2
log
@Enhanced debug printout.
@
text
@d9 3
d20 1
a20 1
#include <coherent.h>
@


1.1
log
@First running version.
@
text
@d8 4
a11 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d57 1
a57 1
#if (DEBUG >= 2)
d60 3
d65 1
@
0707070064030104311004440000030000030000011777770507310651400005400000040371/newbits/kernel/USRSRC/i8086/drv/RCS/dg.c,vhead     1.3;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.3
date     91.03.05.12.23.42;  author root;  state Exp;
branches ;
next	1.2;

1.2
date     91.03.01.13.29.12;  author root;  state Exp;
branches ;
next	1.1;

1.1
date     91.02.28.14.53.22;  author root;  state Exp;
branches ;
next	;


desc
@Device driver for Digiboard PC/Xe intelligent multiport controller.
@


1.3
log
@Fix cast on dg_ram_base
@
text
@/*
 * dg - device driver for Digiboard PC/Xe intelligent multiport controller
 *
 * $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 */
 
/*
 * Various notes:
 *
 *	FEP = front-end-processor (the 80186 on the Digiboard)
 *
 *	At port DG_IOB:
 *		the 2's bit is 1 to enable DPRAM, 0 to disable
 *		the 4's bit is 1 to reset FEP, 0 to clear reset 
 *
 *	There is a bug in the current ldlib.a version of setivec and clrivec:
 *	they only work during xxload() and xxunload() due to use of "ucs"
 *	instead of "getcs()" to determine the CS for the interrupt routine.
 */

/*
 * Definitions.
 *
 */
#define	DG_RAM_LENGTH	0x10000L
#define DG_MEMORY_SEG	0xF000		/* dual-port ram base on FEP side */
#define DG_BIOS_ADDR	0xF800
#define DG_FEPOS_ADDR	0x2000
#define DG_BIOS_LOADER	0x80		/* minor number to write to BIOS */
#define DG_FEPOS_LOADER	0x40		/* minor number to write to FEPOS */
#define DG_BIOS_LENGTH	0x800		/* PC/Xe BIOS is 2k bytes */
#define DG_BIOS_CONFIRM	0x0C00		/* look for "GD" here */
#define DG_FEP_CONFIRM	0x0D20		/* look for "OS" here */
#define DG_BIOS_REQ	0x0C40		/* Start FEP BIOS requests here */
#define BIOS_GOOD	('G' + ('D'<<8))	/* "GD" */
#define FEPOS_GOOD	('O' + ('S'<<8))	/* "OS" */

#define CSTART		0x400		/* start addr of command queue */
#define NPORT		0x0C22		/* addr of # of ports */
#define CIN		0x0D10		/* addr for command in pointer */
#define COUT		0x0D12		/* addr for command out pointer */
#define ISTART		0x800		/* start addr of event queue */
#define EIN		0x0D18		/* addr for event in pointer */
#define EOUT		0x0D1A		/* addr for event out pointer */
#define INTERVAL	0x0E04		/* addr for ticks between irpts */
#define EVENT_LEN	4		/* bytes per FEP event */
#define COMMAND_LEN	4		/* bytes per FEP command */

/*
 * Includes.
 */
#include "coherent.h" 
#include <sys/io.h>		/* IO */
#include <sys/sched.h>		/* [CIS]VPAUSE */
#include <sys/uproc.h>		/* u.u_error */
#include <sys/proc.h>		/* wakeup();
				   includes sys/types.h - faddr_t, paddr_t
				   and sys/timeout.h - TIM
				   needs coherent.h for KERNEL */
#include <sys/con.h>		/* CON */
#include <sys/stat.h>		/* minor(dev) */
#include <devices.h>		/* device major numbers, including PE_MAJOR */
#include <errno.h>

/*
 * Export Functions.
 */

/*
 * Export variables - these may be patched in order to configure the driver.
 */
long	DG_RAM = 0xF0000L;	/* segment for 64k of dual-port RAM */
int	DG_IOB = 0x200;		/* address of i/o byte for controller */
int	DG_INT = 15;		/* IRQ number for board's interrupt */

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Local functions.
 */
static dgload();
static dgunload();
static dgopen();
static dgclose();
static dgread();
static dgwrite();
static void dgdelay();
static dg_start_timing();
static dg_stop_timing();
static int dginit2();
static int dginit3();
static void dgintr();
 
/*
 * Local variables.
 */
static faddr_t	dg_ram_fp;	/* (far *) to access screen */
static paddr_t	dg_ram_base;	/* physical address of screen base */
static TIM	delay_tim;	/* needed for calls to timeout() */
static TIM	timeout_tim;	/* needed for calls to timeout() */
static int	dg_expired;	/* TRUE after local timeout */
static int	bios_loading;	/* TRUE if minor device for BIOS load open */
static int	fepos_loading;	/* TRUE if minor device for FEPOS load open */
static int	load_byte_ct;	/* place-holder for BIOS/FEPOS load */
static int	board_ready;	/* TRUE when all board initialization done */
static int	dg_bios_wait;	/* TRUE if waiting for BIOS to be loaded */
static int	dg_fepos_wait;	/* TRUE if waiting for FEPOS to be loaded */
static int	nport;		/* number of ports on the Digiboard */
static int	test_irq;	/* TRUE during startup */

/*
 * Configuration table - another export variable.
 */
CON dgcon ={
	DFCHR,				/* Flags */
	PE_MAJOR,			/* Major index */
	dgopen,				/* Open */
	dgclose,			/* Close */
	nulldev,			/* Block */
	dgread,				/* Read */
	dgwrite,			/* Write */
	nulldev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	dgload,				/* Load */
	dgunload,			/* Unload */
	nulldev				/* Poll */
};

/*
 * Load Routine.
 */
static dgload()
{
	char v;

	setivec(DG_INT, dgintr);
	/*
	 * Allocate a selector to map onto the dual-port RAM.  ptov() will
	 * return the first available selector of the 8,192 possible.
	 */
	dg_ram_base = (paddr_t)((long)(unsigned)DG_RAM << 4);
	dg_ram_fp = ptov(dg_ram_base, (fsize_t)DG_RAM_LENGTH);
	
	/*
	 * Reset the board and wait.
	 * Actual delay is a tick = 0.01 sec; only need 1msec.
	 */
	outb(DG_IOB, 0x04);
	dgdelay(1);
	
	/*
	 * Read board ID.
	 */
	v = inb(DG_IOB);
	if ((v & 0x01) == 0x01) {
		printf("Error - board type is PC/Xi\n");
		return;
	} else {
		outb(DG_IOB, 0x05);	/* hold FEP reset */
		v = inb(DG_IOB);
		if ((v & 0x01) == 0x01) {
			printf("Error - board type is PC/Xm\n");
			return;
		} else
			printf("PC/Xe ID found\n");
	}
	
	/*
	 * Board Reset.
	 */
	outb(DG_IOB, 0x04);	/* reset board */
	dg_start_timing(100);	/* start 1-second timer */
	while ((inb(DG_IOB) & 0x0E) != 0x04) {
		if (dg_expired) {
			printf("Error - PC/Xe failed to reset\n");
			return;
		}
		dgdelay(10);
	}
	outb(DG_IOB, 0x06);	/* enable memory */
	printf("PC/Xe passed reset\n");

	/*
	 * Minimal test of PC/Xe's 64k of dual-ported RAM.
	 */
	sfword(dg_ram_fp, 0xA55A);		/* store a "far" word */
	sfword(dg_ram_fp + 2, 0x3CC3);
	sfword(dg_ram_fp + 0xFFFC, 0xA55A);
	sfword(dg_ram_fp + 0xFFFE, 0x3CC3);
	if (ffword(dg_ram_fp) != 0xA55A		/* fetch a "far" word */
	||  ffword(dg_ram_fp + 2) != 0x3CC3
	||  ffword(dg_ram_fp + 0xFFFC) != 0xA55A
	||  ffword(dg_ram_fp + 0xFFFE) != 0x3CC3) {
		printf("Error - PC/Xe failed memory test\n");
		return;
	} else
		printf("PC/Xe passed memory test\n");
		
	/*
	 * Load and execute the PC/Xe BIOS
	 */
	outb(DG_IOB, 0x06);	/* enable memory */
	dg_bios_wait = 1;
	printf("PC/Xe waiting for BIOS load\n");
}

static dgunload()
{
	if (board_ready) {
		board_ready = 0;
	}
	
	/*
	 * Turn off and unhook interrupts from FEPOS
	 */
	sfword(dg_ram_fp+INTERVAL, 0);	/* stop host interrupts */
	outb(DG_IOB, 0x04);		/* Disable DPRAM and hold FEP reset */
	clrivec(DG_INT);

	/*
	 * We have to free up the selector now that we're done using it.
	 */
	vrelse(dg_ram_fp);
}

/*
 * Open Routine.
 */
static dgopen( dev, mode )
dev_t dev;
{
	/*
	 * If minor number has 128's bit set to 1, this is an attempt to
	 * transfer the BIOS to the FEP.
	 */
	if (minor(dev) & DG_BIOS_LOADER) {
		if (bios_loading) {
			u.u_error = EDBUSY;
			return;
		} else {
			/*
			 * Only allow BIOS xfer if we are waiting for it.
			 */
			if (dg_bios_wait) {
				bios_loading = 1;
				load_byte_ct = 0;
			} else {
				u.u_error = EIO;
				return;
			}
		}
	/*
	 * If minor number has 64's bit set to 1, this is an attempt to
	 * transfer the FEPOS to the FEP.
	 */
	} else if (minor(dev) & DG_FEPOS_LOADER) {
		if (fepos_loading) {
			u.u_error = EDBUSY;
			return;
		} else {
			/*
			 * Only allow FEPOS xfer if we are waiting for it.
			 */
			if (dg_fepos_wait) {
				fepos_loading = 1;
				load_byte_ct = 0;
			} else {
				u.u_error = EIO;
				return;
			}
		}
	} else {
	}
}

/*
 * Close Routine.
 */
static dgclose( dev )
dev_t dev;
{
	/*
	 * If minor number has 128's bit set to 1, this is an attempt to
	 * transfer the BIOS to the FEP.
	 */
	if (minor(dev) & DG_BIOS_LOADER) {
		bios_loading = 0;
		/*
		 * Only set dg_fepos_wait if enough bytes got written.
		 */
		if (load_byte_ct == DG_BIOS_LENGTH) {
			/*
			 * After BIOS is xferred, try to finish
			 * PC/Xe initialization.
			 */
			if (dginit2()) {
				dg_bios_wait = 0;
				dg_fepos_wait = 1;
				printf("PC/Xe waiting for FEPOS load\n");
			}
		}
	/*
	 * If minor number has 64's bit set to 1, this is an attempt to
	 * transfer the FEPOS to the FEP.
	 */
	} else if (minor(dev) & DG_FEPOS_LOADER) {
		fepos_loading = 0;
		/*
		 * After BIOS is xferred, try to finish
		 * PC/Xe initialization.
		 */
		if (dginit3()) {
			dg_fepos_wait = 0;
			board_ready = 1;
			printf("PC/Xe ready for use\n");
		}
	} else {
	}
}

/*
 * Read Routine.
 */
static dgread( dev, iop )
dev_t dev;
register IO * iop;
{
#if 0
	static int offset;
	int c;
	/*
	 * Read a character code from video RAM
	 * Start reading RAM just after where previous read ended
	 *
	 * Note that "offset" is the value of the displacement into
	 * the screen RAM. Any expression which results in a value
	 * which is less than DG_RAM_LENGTH is OK here.
	 */
	while(iop->io_ioc) {
		c = ffbyte(dg_ram_fp + offset); /* fetch a "far" byte */
		if(ioputc(c, iop) == -1)
			break;
		offset += 2;
		offset %= DG_RAM_LENGTH;
	}
#endif	
}

/*
 * Write Routine.
 */
static dgwrite( dev, iop )
dev_t dev;
register IO * iop;
{
	/*
	 * If minor number has 128's bit set to 1, this is an attempt to
	 * transfer the BIOS to the FEP.
	 */
	if (minor(dev) & DG_BIOS_LOADER) {
		int c;

		while ((c = iogetc(iop)) >= 0 && load_byte_ct < DG_BIOS_LENGTH) {
			sfbyte(dg_ram_fp + DG_BIOS_ADDR + load_byte_ct, c);
			load_byte_ct++;
		}
	/*
	 * If minor number has 64's bit set to 1, this is an attempt to
	 * transfer the FEPOS to the FEP.
	 */
	} else if (minor(dev) & DG_FEPOS_LOADER) {
		int c;

		while ((c = iogetc(iop)) >= 0) {
			sfbyte(dg_ram_fp + DG_FEPOS_ADDR + load_byte_ct, c);
			load_byte_ct++;
		}
	} else {
	}
}

/*
 * Delay for some number of clock ticks.
 * 286/386 kernel ticks are at 100Hz
 * Use kernel function sleep(), which is NOT the system call by that name.
 */
static void dgdelay(ticks)
int ticks;
{
	timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
}

/*
 * Start a timeout for some number of ticks.
 * Caller knows timer has expired when "dg_expired" goes to 1.
 *
 * Sample invocation:
 *	dg_start_timing(n);
 *	while (check for desired event fails) {
 *		if (dg_expired) {
 *			...failure stuff..
 *			break;
 *		}
 *		dgdelay(m); <= needed to allow kernel to update timers
 *	}
 */
static dg_start_timing(ticks)
int ticks;
{
	dg_expired = 0;
	timeout(&timeout_tim, ticks, dg_stop_timing, 1);
}

/*
 * Stub function called only by dg_start_timing()
 */
static dg_stop_timing(flagval)
int flagval;
{
	dg_expired = flagval;
}

/*
 * Second part of PC/Xe initialization - done after the BIOS has been
 * written to dual-ported RAM.
 */
static int dginit2()
{
	/*
	 * Execute FEP BIOS
	 */
	sfword(dg_ram_fp + DG_BIOS_CONFIRM, 0);	/* clear confirm word */
	outb(DG_IOB, 0x02);			/* Release reset */
	dg_start_timing(1000);			/* start 10-second timer */

	while (ffword(dg_ram_fp + DG_BIOS_CONFIRM) != BIOS_GOOD) {
		if (dg_expired) {
			printf("Error - PC/Xe BIOS won't start\n");
			return 0;
		}
		dgdelay(10);
	}
	printf("PC/Xe BIOS started\n");

	return 1;
}

/*
 * Third part of PC/Xe initialization - done after the FEPOS has been
 * written to dual-ported RAM.
 */
static int dginit3()
{
	int cmd;

	/*
	 * Ask FEP BIOS to move FEPOS into host memory.
	 */
	sfword(dg_ram_fp + DG_BIOS_REQ, 0x0002);
	sfword(dg_ram_fp + DG_BIOS_REQ+2, DG_MEMORY_SEG+0x200);
	sfword(dg_ram_fp + DG_BIOS_REQ+4, 0x0000);
	sfword(dg_ram_fp + DG_BIOS_REQ+6, 0x0200);
	sfword(dg_ram_fp + DG_BIOS_REQ+8, 0x0000);
	sfword(dg_ram_fp + DG_BIOS_REQ+0xA, 0x2000);
	outb(DG_IOB, 0x0A);			/* Toggle interrupt */
	outb(DG_IOB, 0x02);
	dg_start_timing(100);			/* start 1-second timer */
	while (ffword(dg_ram_fp + DG_BIOS_REQ) != 0) {
		if (dg_expired) {
			printf("Error - PC/Xe FEPOS move failed\n");
			return;
		}
		dgdelay(10);
	}
	printf("PC/Xe FEPOS relocated to host RAM\n");

	/*
	 * Execute FEPOS
	 */
	sfword(dg_ram_fp + DG_BIOS_REQ, 0x0001);
	sfword(dg_ram_fp + DG_BIOS_REQ+2, 0x0200);
	sfword(dg_ram_fp + DG_BIOS_REQ+4, 0x0004);
	sfword(dg_ram_fp + DG_FEP_CONFIRM, 0);	/* clear confirm word */
	outb(DG_IOB, 0x0A);			/* Toggle interrupt */
	outb(DG_IOB, 0x02);
	dg_start_timing(500);			/* start 5-second timer */
	while (ffword(dg_ram_fp + DG_FEP_CONFIRM) != FEPOS_GOOD) {
		if (dg_expired) {
			printf("Error - PC/Xe FEPOS won't start\n");
			printf("Failure code (%x)\n",
				ffword(dg_ram_fp + DG_BIOS_REQ));
			return 0;
		}
		dgdelay(10);
	}
	printf("PC/Xe FEPOS started\n");
	nport = ffbyte(dg_ram_fp+NPORT);

	/*
	 * Enable and test interrupts from FEP
	 */
	sfword(dg_ram_fp+INTERVAL, 1);		/* request host interrupts */
	cmd = ffword(dg_ram_fp+CIN);		/* get command pointer */
	sfword(dg_ram_fp+CSTART+cmd, 0xA1FF);	/* send an invalid command */
	sfword(dg_ram_fp+CSTART+cmd+2, 0xC3B2);
	sfword(dg_ram_fp+CIN, (cmd+4)&0x3ff);	/* update command pointer */
	dg_start_timing(100);			/* start 1-second timer */
	test_irq = 1;
	while (test_irq) {
		if (dg_expired) {
			printf("Error - PC/Xe no FEPOS interrupts\n");
			return 0;
		}
		dgdelay(10);
	}
	printf("PC/Xe interrupts working\n");
	
	return 1;
}

/*
 * Interrupt handler.
 *
 * No specific action is needed to clear the interrupt
 * as it was a pulse sent from the FEPOS to host's IRQ line.
 */
static void dgintr()
{
	int cin, cout, ein, eout;
	unsigned char event[EVENT_LEN];
	int i;

	cin = ffword(dg_ram_fp+CIN);
	cout = ffword(dg_ram_fp+COUT);
	ein = ffword(dg_ram_fp+EIN);
	eout = ffword(dg_ram_fp+EOUT);

	if (board_ready) {
		/*
		 * Remove all packets from event queue.
		 */
		while (ffword(dg_ram_fp+EIN) != ffword(dg_ram_fp+EOUT)) {
			eout = ffword(dg_ram_fp+EOUT);
			for (i = 0; i < EVENT_LEN; i++)
				event[i] = ffbyte(dg_ram_fp+ISTART+eout+i);
			printf("%x %x %x %x\n", event[0],event[1],event[2],event[3]);	
			sfword(dg_ram_fp+EOUT, (eout+4)&0x3ff);
		}
	} else {	/* e.g., if test_irq is TRUE */
		test_irq = 0;
		/*
		 * Attempt to clear the IRQ condition in the FEP.
		 */
		sfword(dg_ram_fp+EOUT, ffword(dg_ram_fp+EIN));
	}
}
@


1.2
log
@Fully initializes O.K. but no functional I/O yet
@
text
@d4 1
a4 1
 * $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
d6 1
d148 1
a148 1
	dg_ram_base = (paddr_t)DG_RAM << 4;
@


1.1
log
@starts FEPOS ok but first IRQ causes panic
@
text
@d4 2
d7 14
a27 2
#define DG_BIOS_FILE	"/drv/xabios.bin"
#define DG_FEPOS_FILE	"/drv/xafep.bin"
d75 1
a75 1
int	DG_INT = 12;		/* IRQ number for board's interrupt */
d114 1
d142 1
d171 1
a171 1
			printf("Digiboard PC/Xe ID found\n");
d181 1
a181 1
			printf("Error - Digiboard failed to reset\n");
d200 1
a200 1
		printf("Error - Digiboard failed memory test\n");
a216 15
		/*
		 * Turn off and unhook interrupts from FEPOS
		 */
#if 0		 
		clrivec(DG_INT);
#else
	clrivec(03);	
	clrivec(04);	
	clrivec(05);	
	clrivec(07);	
	clrivec(10);	
	clrivec(11);	
	clrivec(12);	
	clrivec(15);	
#endif	
d218 7
d445 1
a445 1
			printf("Error - Digiboard BIOS won't start\n");
d451 1
a451 1
	
d477 1
a477 1
			printf("Error - Digiboard FEPOS move failed\n");
d496 1
a496 1
			printf("Error - Digiboard FEPOS won't start\n");
a504 1
	printf("Board is PC/%de\n", nport);
a508 15

printf("about to setivec\n");
#if 0
	setivec(DG_INT, dgintr);
#else
	setivec(03,dgintr);	
	setivec(04,dgintr);	
	setivec(05,dgintr);	
	setivec(07,dgintr);	
	setivec(10,dgintr);	
	setivec(11,dgintr);	
	setivec(12,dgintr);	
	setivec(15,dgintr);	
#endif	
printf("about to enable host irq's\n");	
a509 1
printf("getting command pointer\n");	
a510 1
printf("about to send invalid command\n");	
d514 11
a524 15
printf("invalid command sent\n");	
	dgdelay(100);				/* wait 1 second */
	sfword(dg_ram_fp+INTERVAL, 0);		/* stop host interrupts */
#if 0
{ int t;
	sfword(dg_ram_fp+INTERVAL, 1);		/* request host interrupts */
	t = ffword(dg_ram_fp+0x0D18);		/* get command pointer */
	sfword(dg_ram_fp+0x400+t, 0xA1FF);	/* send an invalid command */
	sfword(dg_ram_fp+0x402+t, 0xC3B2);
	sfword(dg_ram_fp+0xD18, (t+4)&0x3ff);	/* update command pointer */
	dgdelay(1000);				/* wait 10 seconds */
	sfword(dg_ram_fp+INTERVAL, 0);		/* stop host interrupts */
	dgintr();
}	
#endif
d537 2
a538 3
	char event[EVENT_LEN];
	int i,j=0;
#define ILIMIT 5	
a539 1
	printf("Interrupt handler called\n");
a543 1
	printf("cin=%x cout=%x ein=%x eout=%x\n",cin,cout,ein,eout);
d545 17
a561 7
	while (ffword(dg_ram_fp+EIN) != ffword(dg_ram_fp+EOUT)&&j < ILIMIT) {
		eout = ffword(dg_ram_fp+EOUT);
		for (i = 0; i < EVENT_LEN; i++)
			event[i] = ffbyte(dg_ram_fp+ISTART+eout+i);
		printf("%x %x %x %x\n", event[0],event[1],event[2],event[3]);	
		sfword(dg_ram_fp+EOUT, (eout+4)&0x3ff);
		j++;
@
0707070064030103711004440000030000030000011777770507310652000005700000005452/newbits/kernel/USRSRC/i8086/drv/RCS/fdisk.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3;
comment  @ * @;


1.3
date     91.06.20.14.48.58;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.18.08.18.56;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.03.25.19.09.17;  author root;  state Exp;
branches 1.1.1.1;
next     ;

1.1.1.1
date     91.03.25.19.24.46;  author root;  state Exp;
branches ;
next     1.1.1.2;

1.1.1.2
date     91.04.19.10.16.50;  author root;  state Exp;
branches ;
next     ;


desc
@function called by device drivers to load partition table
@


1.3
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/**
 *
 * fdisk( dev, fp )	--	Fixed Disk Configuration
 * dev_t dev;
 * struct fdisk_s *fp;
 *
 *	Input:	dev = special device to read partition information from
 * 		fp  = pointer to memory-resident partition info (to update)
 *
 *	Action:	Open special device for reading.
 *		Read first block from the device.
 *		If valid signature present on block,
 *			copy partition information to memory
 *
 *	Return:	1 = partition information successfully updated
 *		0 = failure (could not read block, or bad signature)
 */

#include <sys/coherent.h>
#include <sys/uproc.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/fdisk.h>
#include <sys/buf.h>
#include <sys/con.h>

fdisk( dev, fp )
dev_t dev;
register struct fdisk_s *fp;
{
	register struct hdisk_s *hp;
	BUF *bp;
	int s, i;
	int ret = 0;

	s = sphi( );
	dopen( dev, IPR, DFBLK );

	if ( u.u_error == 0 ) {		/* special device now open */

		if (bp = bread(dev, (daddr_t) 0, 1)) {	/* data read */

			/* buffer cache is in kernel data space */
			hp = FP_OFF(bp->b_faddr);

			if ( hp->hd_sig == HDSIG ) {	/* valid data */

				for (i=0; i < NPARTN; ++i)
					*fp++ = hp->hd_partn[i];

				ret   = 1;
			}
			brelease( bp );
		}
		dclose( dev );
	}
	spl( s );
	return ret;
}
@


1.2
log
@update provided by hal
@
text
@d24 1
a24 1
#include "coherent.h"
@


1.1
log
@used in COHERENT 3.1.0
@
text
@d24 2
a25 2
#include <coherent.h>
#include <uproc.h>
d27 1
a27 1
#include <inode.h>
d29 2
a30 2
#include <buf.h>
#include <con.h>
@


1.1.1.1
log
@debug printf's added
@
text
@a5 3
/*
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 */
a39 1
int erf = -1;
a57 1
else erf=1;
a61 1
else erf=0;
d63 1
a63 7
switch (erf) {
case 0:
	devmsg(dev, "fdisk: open failed");
	break;
case 1:
	devmsg(dev, "fdisk: bad signature");
	break;
a64 2
	return ret;
}
@


1.1.1.2
log
@Debug printf's added.
@
text
@d45 1
a45 1
printf("fdisk(): special dev open\n");
a56 2
			} else {
printf("fdisk(): sig=%x, want=%x\n", hp->hd_sig, HDSIG);
a58 2
		} else {
printf("fdisk(): bread failed\n");
a60 2
	} else {
printf("fdisk(): special dev not open\n");
d63 8
d73 6
@
0707070064030106721004440000030000030000011777770507310652100005400000041042/newbits/kernel/USRSRC/i8086/drv/RCS/hs.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3;
comment  @ * @;


1.3
date     91.06.20.14.49.59;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.31.30;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.02.25.16.05.15;  author root;  state Exp;
branches 1.1.1.1;
next     ;

1.1.1.1
date     91.02.25.16.11.56;  author root;  state Exp;
branches ;
next     ;


desc
@Multiport (8250-type) serial driver.
@


1.3
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Polled Serial Port Device Driver.
 * - supports version 7 compatible ioctl
 */

#include <sys/coherent.h>
#include <sys/ins8250.h>
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/proc.h>
#include <sys/tty.h>		/* indirectly includes sgtty.h */
#include <sys/con.h>
#include <errno.h>
#include <sys/sched.h>		/* CVTTOUT, IVTTOUT, SVTTOUT */
#include <sys/poll_clk.h>

/*
 * Definitions.
 *
 * HSBAUD is the highest baud rate supported by this driver
 * HS_HZ is the polling rate, i.e. the number of times per second
 *   at which all open ports are checked for input, output, and
 *   line status changes
 * MAX_HSNUM is the maximum number of devices that can be polled
 *   using this driver and can be revised up or down
 * PORT is a convenience macro for the base address of a port
 * port_config is the structure of the initial configuration for each
 *   polled port;  note that "speed" is NOT the actual baud rate, but
 *   the value of the symbol for that baud rate as defined in
 *   /usr/include/sgtty.h
 */
#define	HSBAUD	9600
#define	HS_HZ	(HSBAUD/6)
#define MAX_HSNUM	8
#define	PORT	((int)(tp->t_ddp))
struct port_config {
	int	addr;	/* base address of the 8250-family UART */
	int	speed;	/* B0..B19200 */
};

/*
 * Export Variables - these can be patched without recompiling and linking
 *
 * HSNUM is the actual number of polled serial ports, and should be
 *   less than or equal to MAX_HSNUM
 * HS_PORTS is an array of address/speed pairs, one for each port
 */
int	HSNUM = 4;
struct port_config HS_PORTS[MAX_HSNUM] = {
	{ 0x3F8, B9600 },
	{ 0x2F8, B9600 },
	{ 0x3E8, B9600 },
	{ 0x2E8, B9600 }
};

/*
 * Export Functions.
 */
int	hsload();
int	hsopen();
int	hsclose();
int	hsread();
int	hswrite();
int	hsioctl();
int	hsunload();
int	hspoll();

int	hscycle();
int	hsintr();
int	hsparam();
int	hsstart();
int	hsclk();
int	set_poll_rate();

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON hscon ={
	DFCHR|DFPOL,			/* Flags */
	7,				/* Major index */
	hsopen,				/* Open */
	hsclose,			/* Close */
	nulldev,			/* Block */
	hsread,				/* Read */
	hswrite,			/* Write */
	hsioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	hsload,				/* Load */
	hsunload,			/* Unload */
	hspoll				/* Poll */
};

/*
 * Local variables.
 */
static TTY *hstty;
static TTY *hslimtty;
static TIM hstim;
static int poll_divisor;	/* used in hsclk() and set_poll_rate() */

/*
 * Time constant table.
 * Indexed by ioctl baud rate.
 */
static
int timeconst[] = {
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	6,				/* EXTA */
	6				/* EXTB */
};

/*
 * poll_hz[] is tied to timeconst[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int poll_hz[] ={
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 * Load Routine.
 */
static hsload()
{
	register TTY * tp;
	register int port;
	int i, b;

	if ((hstty = (TTY *)kalloc(HSNUM*sizeof(TTY))) == 0) {
		printf("hsload: can't allocate tty's\n");
		return;
	}
	kclear(hstty, HSNUM*sizeof(TTY));

	for (i = 0; i < HSNUM; i++) {
		port = HS_PORTS[i].addr;
		tp = hstty + i;

		outb( port+MCR, 0 );
		outb( port+IER, 0 );

		if ( inb( port+IER ) )
			break;

		tp->t_cs_sel  = cs_sel();
		tp->t_start   = hsstart;
		tp->t_param   = hsparam;
		tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
		tp->t_dispeed = tp->t_dospeed = HS_PORTS[i].speed;
		tp->t_ddp     = port;

		b = timeconst[ tp->t_sgttyb.sg_ospeed ];
		outb( port+LCR, LC_DLAB );
		outb( port+DLL, b );
		outb( port+DLH, b >> 8);
		outb( port+LCR, LC_CS8);

		hslimtty = tp;
	}
}

static hsunload()
{
	if (hstty != (TTY *)0)
		kfree(hstty);
}

/*
 * Open Routine.
 */
hsopen( dev, mode )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];
	register int b;
	int s;

	/*
	 * Verify hardware exists.
	 */
	if ( (PORT == 0) || (inb(PORT+IER) & ~IE_TxI) ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Can't open if another driver is using polling
	 */
	if (poll_owner & ~ POLL_HS) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Initialize if not already open.
	 */
	if ( ++tp->t_open == 1 ) {
		ttopen( tp );

		if ( dev & 0x80 ) {
			s = sphi();
			b = inb(PORT+MSR);
			tp->t_flags |= T_MODC + T_STOP;
			if ( b & MS_CTS )
				tp->t_flags &= ~T_STOP;
			if ( b & MS_DSR )
				tp->t_flags |=  T_CARR;
			spl( s );
		} else  {
			tp->t_flags &= ~T_MODC;
			tp->t_flags |=  T_CARR;
		}
		hscycle( tp );
	}
	ttsetgrp( tp, dev );
	set_poll_rate();
}

/*
 * Close Routine.
 */
hsclose( dev )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];

	/*
	 * Reset if last close.
	 */
	if ( tp->t_open == 1 ) {
		int state;

		ttclose( tp );
		/*
		 * ttclose() only emptied the output queue tp->t_oq;
		 * now wait 0.1 sec for the silo tp->rawout to empty
		 * and allow a delay for the UART on-chip xmit buffer to empty
		 *
		 * state 2: waiting for silo to empty
		 * state 1: stalling so UART can empty xmit buffer
		 * state 0: done!
		 */
		state = 2;
		while (state) {
			timeout(&hstim, 10, wakeup, (int)&hstim);
			sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
			if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
				state--;
		}
	}

	--tp->t_open;
	set_poll_rate();
}

/*
 * Read Routine.
 */
hsread( dev, iop )
dev_t dev;
register IO * iop;
{
	ttread( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Write Routine.
 */
hswrite( dev, iop )
dev_t dev;
register IO * iop;
{
	ttwrite( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Ioctl Routine.
 */
hsioctl( dev, com, vec )
dev_t dev;
int com;
struct sgttyb * vec;
{
	ttioctl( &hstty[ dev & 15 ], com, vec );
}

/*
 * Polling Routine.
 */
hspoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	return ttpoll( &hstty[ dev & 15 ], ev, msec );
}

/*
 * Cyclic routine - invoked every clock tick to perform raw input/output.
 *
 *	Notes:	Invoked 10 times per second.
 */
hscycle( tp )
register TTY * tp;
{
	register int resid;
	register int c;

	/*
	 * Process rawin buf.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}

	/*
	 * Calculate free output slot count.
	 */
	resid  = sizeof(tp->t_rawout.si_buf) - 1;
	resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	resid %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--resid >= 0) && ((c = ttout(tp)) >= 0) ) {

		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;

		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, waking processes waiting to output, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	if ( tp->t_open != 0 )
		timeout( &tp->t_rawtim, HZ/10, hscycle, tp );
}

/*
 * Clock Interrupt driven Polling routine.
 */
hsintr()
{
	register TTY * tp = &hstty[0];
	register int b;

	do {
		if ( tp->t_open == 0 )
			continue;

		/*
		 * Check modem status if modem control is enabled.
		 */
		if ( tp->t_flags & T_MODC ) {

			b = inb( PORT+MSR );

			if ( b & (MS_DCTS|MS_DDSR) ) {

				if ( b & MS_DCTS ) {
					if ( b & MS_CTS )
						tp->t_flags &= ~T_STOP;
					else
						tp->t_flags |=  T_STOP;
				}
				if ( b & MS_DDSR ) {
					if ( b & MS_DSR )
						tp->t_flags |=  T_CARR;
					else {
						tp->t_flags &= ~T_CARR;
						tthup( tp );
					}
				}
			}
		}

		b = inb( PORT+LSR );

		if ( (b & LS_BREAK) && (tp->t_flags & T_CARR) )
			ttsignal( tp, SIGINT );

		/*
		 * Receive ready.
		 */
		if ( b & LS_RxRDY ) {

			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(PORT+DREG);

			if ( tp->t_flags & T_CARR ) {

				if ( ++(tp->t_rawin.si_ix) >=
						sizeof(tp->t_rawin.si_buf) )
					tp->t_rawin.si_ix = 0;
			}
		}

		/*
		 * Transmit ready and raw output data exists.
		 */
		if ( (b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
		  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

			outb(	PORT+DREG,
				tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

			if ( ++(tp->t_rawout.si_ox) >=
					sizeof(tp->t_rawout.si_buf) )
				tp->t_rawout.si_ox = 0;
		}

	} while ( ++tp <= hslimtty );
}

/*
 * Set hardware parameters.
 */
hsparam( tp )
register TTY * tp;
{
	register int b;
	int s;

	s = sphi();
	/*
	 * Assert required modem control lines (DTR, RTS).
	 */
	b = 0;
	if ( tp->t_sgttyb.sg_ospeed != B0 )
		b |=  MC_DTR | MC_RTS;
	outb( PORT+MCR, b );

	/*
	 * Program baud rate.
	 */
	if (b = timeconst[ tp->t_sgttyb.sg_ospeed ]) {
		outb( PORT+LCR, LC_DLAB );
		outb( PORT+DLL, b );
		outb( PORT+DLH, b >> 8 );
	}

	/*
	 * Program character size, parity.
	 */
	switch ( tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW) ) {
	case ODDP:		b = LC_CS7|LC_PARENB;		 break;
	case EVENP:		b = LC_CS7|LC_PARENB|LC_PAREVEN; break;
	default:		b = LC_CS8;			 break;
	}
	outb( PORT+LCR, b );

	/*
	 * Enable Transmit Buffer Empty Interrupts.
	 */
	outb( PORT+IER, IE_TxI );

	spl(s);
	set_poll_rate();
}

/*
 * Start Routine.
 */
hsstart( tp )
register TTY * tp;
{
	register int s;

	/*
	 * Transmit buffer is empty, and raw output buffer is not.
	 */
	s = sphi();
	if ( (inb( PORT+LSR ) & LS_TxRDY)
	  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

		/*
		 * Send next char from raw output buffer.
		 */
		outb( PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}

/*
 * hsclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int hsclk()
{
  static int count;

  hsintr();
  count++;
  if (count >= poll_divisor)
    count = 0;
  return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_HS)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < HSNUM; port_num++) {
		if (hstty[port_num].t_open) {
		  port_rate = poll_hz[hstty[port_num].t_sgttyb.sg_ispeed];
		  if (max_rate < port_rate)
			max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in hsclk() */
		altclk_out();		/* stop previous polling */
		poll_owner &= ~POLL_HS;
		if (max_rate) {	/* resume polling at new rate if needed */
			altclk_in(poll_rate, hsclk);
			poll_owner |= POLL_HS;
		}
	}
}
@


1.2
log
@new version provided y hal for v321
@
text
@d11 2
a12 2
#include "coherent.h"
#include "ins8250.h"
a18 1
#include <sys/timeout.h>	/* TIM */
d20 1
a20 1
#include <poll_clk.h>
@


1.1
log
@Shipped with COHERENT 3.1.0
@
text
@d20 1
a20 1
#include <sched.h>		/* CVTTOUT, IVTTOUT, SVTTOUT */
@


1.1.1.1
log
@Add MSR delta save and modem control.  Doesn't work.
@
text
@a4 2
 *
 *	$Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
a36 3
 *
 * "PORT" is a macro yielding the 8250 base address, given the "tp" pointer.
 * "PORT_NUM" is a macro yielding the port index (0..MAX_HSNUM-1) given "tp".
d41 1
a41 3
#define	PORT		(HS_PORTS[(int)(tp->t_ddp)].addr)
#define	PORT_NUM	((int)(tp->t_ddp))
#define MSR_DELTAS	(MS_DCTS | MS_DDSR | MS_TERI | MS_DRLSD)
d63 1
a63 3
 * 8250's MSR delta bits are cleared each time the MSR is read.
 * But different parts of the driver look for deltas of different bits.
 * Array msr[] saves delta bits until they are needed.
a64 4
static char msr[MAX_HSNUM];
/*
 * Export Functions.
 */
d200 1
a200 1
		tp->t_ddp     = i;
d225 1
a225 1
	int port = PORT;
d227 1
a227 2
	char msr_ch;
printf("hsopen #%d: enter, count=%d\n", PORT_NUM, tp->t_open);
d231 1
a231 1
	if ( (port == 0) || (inb(port+IER) & ~IE_TxI) ) {
d235 1
a235 1
	
d237 1
a237 1
	 * Don't allow open if flagged for exclusive use and not super-user.
a238 16
	if ((tp->t_flags & T_EXCL) && !super()) {
		u.u_error = ENODEV;
		return;
	}

	/*
	 * Don't open if modem is settling from previous close.
	 */
	if (drvl[major(dev)].d_time != 0) {	/* Modem settling */
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Can't open if another driver is using polling
	 */
d247 1
a247 6
	if ( tp->t_open++ == 0 ) {
		hscycle( tp );
		/*
		 * ttopen() will call hsparam()
		 * hsparam() asserts DTR and RTS and sets polling rate
		 */
d250 1
a250 1
		if (dev & 0x80) { /* if modem control... */
d252 3
a254 23
			tp->t_flags |= T_MODC + T_STOP + T_HOPEN;
			/*
			 * Sleep while waiting for carrier.
			 */
			while(1) {
				msr_ch = inb(port + MSR);
				msr[PORT_NUM] |= msr_ch & MSR_DELTAS; 
				if (msr_ch & MS_RLSD)
					break;
	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
					SVTTOUT);	/* wait for carrier */
		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
					outb(port+MCR, 0);  /* kill RTS/DTR */
					u.u_error = EINTR;
					spl(s);
					tp->t_open = 0;
					return;
				}
			}
			tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
			msr_ch = inb(port + MSR);
			msr[PORT_NUM] |= msr_ch & MSR_DELTAS; 
			if (msr_ch & MS_CTS)
d256 2
d263 1
d266 1
a266 1
printf("hsopen #%d: leave, count=%d\n", PORT_NUM, tp->t_open);
d276 1
a276 1
printf("hsclose #%d: enter, count=%d\n", PORT_NUM, tp->t_open);
a281 2
		int holdflags = tp->t_flags;	/* save flags */
		int port = PORT;
d283 1
a283 10
		ttclose( tp );			/* clears flags */

		if (holdflags & T_HOPEN) {  /* if waiting for RLSD... */
			/*
			 * Flags for first open
			 * (clear T_HPCL)
			 */
			tp->t_flags = T_MODC | T_HOPEN;
		}

a284 18
		 * If hupcls
		 */
		if (holdflags & T_HPCL) {
			int maj;
			/*
			 * Hangup port
			 */
			outb(port+MCR, 0);
			/*
			 * Hold dtr low for timeout
			 */
			maj = major(dev);
			drvl[maj].d_time = 1;
			sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
			drvl[maj].d_time = 0;
		}
		
		/*
a303 1
printf("hsclose #%d: leave, count=%d\n", PORT_NUM, tp->t_open);
a357 1
	int msr_ch;
d360 1
a360 1
	 * Check modem status every clock tick.
a361 40
	if ( tp->t_flags & T_MODC ) {
		/*
		 * Get status
		 */
		msr_ch = inb(PORT + MSR);
		msr[PORT_NUM] |= msr_ch & MSR_DELTAS; 

		/*
		 * Carrier changed.
		 */
		if ( msr[PORT_NUM] & MS_DRLSD ) {
			if (msr_ch & MS_RLSD)
				tp->t_flags |= T_CARR;  /* carrier on */
			else
				tp->t_flags &= ~T_CARR; /* no carrier */

			msr[PORT_NUM] &= ~MS_DRLSD;
			/*
			 * wakeup open
			 */
			if ( tp->t_open == 0 ) {
				wakeup((char *)(&tp->t_open));
			}

			/*
			 * carrier off?
			 */
			else if ( (msr_ch & MS_RLSD) == 0 ) {
				/*
				 * clear carrier flag; send hangup signal
				 */
				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
				tthup( tp );
			}
		}
	}

	/*
	 * Process rawin buf.
	 */
a410 1
	char msr_ch;
a412 2
		int port = PORT, port_num = PORT_NUM;	/* for speed */

d421 1
a421 2
			msr_ch = inb(port + MSR);
			msr[port_num] |= msr_ch & MSR_DELTAS; 
d423 16
a438 6
			if ( msr[port_num] & MS_DCTS ) {
				msr[port_num] &= ~MS_DCTS;
				if ( msr_ch & MS_CTS )
					tp->t_flags &= ~T_STOP;
				else
					tp->t_flags |=  T_STOP;
d442 1
a442 1
		b = inb( port+LSR );
d452 1
a452 1
			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(port+DREG);
d468 1
a468 1
			outb(port+DREG,
a573 1
printf("set_poll_rate()\n");
a587 1
printf("port %d  rate=%d\n", port_num, port_rate);		  
a598 1
printf("altclk_out()\n");		
a601 1
printf("altclk_in(%d, hsclk)\n", poll_rate);			
@
0707070064030106661004440000030000030000011777770507310652500005400000020361/newbits/kernel/USRSRC/i8086/drv/RCS/lp.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.06.20.14.50.37;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.17.12.32.34;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.06.18.23.34;  author norm;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.06.18.22.30;  author hal;  state Exp;
branches ;
next     ;


desc
@Parallel printer driver - no interrupts!
@


1.4
log
@update provided by hal
@
text
@/*
 * This is a driver for PC parallel printers.
 * It has been tested on an EPSON MX-80, Printronix P300, HP LaserJet II.
 * Supports up to three line printers.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/uproc.h>
#include <sys/stat.h>

#define	LPMAJ	3				/* major device # */

/*
 * Patchable parameters.
 *
 *	LP0_OK specifies whether LP0 is always THERE.
 *	LPTIME specifies number of ticks between polls.
 *	LPWAIT specifies loop counter to wait in poll.
 *	LPTEST specifies whether or not to test for on-line conditition.
 */
int	LP0_OK = 0;
int	LPTIME = 4;
int	LPWAIT = 400;
int	LPTEST = 1;

/*
 * Driver configuration.
 */
int	lpload();
int	lpunload();
int	lpwrite();
int	lpopen();
int	lpclose();
int	lpintr();
int	nulldev();
int	nonedev();

CON	lpcon =	{
	DFCHR,				/* Flags */
	LPMAJ,				/* Major index */
	lpopen,				/* Open */
	lpclose,			/* Close */
	nulldev,			/* Block */
	nonedev,			/* Read */
	lpwrite,			/* Write */
	nonedev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	lpload,				/* Load */
	lpunload			/* Unload */
};

/*
 * Line Printer Registers.
 */
#define	LPDAT	(0)			/* Data port, lpbase + 0 */
#define	LPSTR	(1)			/* Status port, lpbase + 1 */
#define	LPCSR	(2)			/* Control port, lpbase + 2 */

/*
 * LP Flag Bits.
 */
#define	LPTHERE	0x01			/* Interface actually there */
#define	LPOPEN	0x02			/* Printer is open */
#define	LPSLEEP	0x04			/* Sleeping on buffer event */
#define	LPRAW	0x80			/* Raw mode */

/*
 * Printer database.
 * Terminated by lpbase = 0.
 * NLP = # entries - 1.
 */
static struct	lpinfo	{
	int	lpbase;			/* I/O Base address */
	int	lpflag;			/* Flags */
	int	lpcol;			/* Current horizontal position */
}	lpinfo[] = {
	{	0x3BC	},
	{	0x378	},
	{	0x278	},
	{	0x000	}
};
#define	NLP	(sizeof(lpinfo) / sizeof(lpinfo[0]) - 1)

/*
 * LP Status Register Bits.
 */
#define	ACK	0x80			/* Ack (active high) */
#define	BUSY	0x40			/* Busy (active high) */
#define	NOPAPER	0x20			/* No paper */
#define	ONLINE	0x10			/* On line */
#define	NERROR	0x08			/* Error (active low) */

/* IBM cable */
#define	IBMNBSY	0x80			/* Busy (active low) */
#define	IBMNACK	0x40			/* Ack (active low) */

/*
 * LP Control Register Bits.
 */
#define	IENABLE	0x10			/* Interrupt enable */
#define	SEL	0x08			/* Select input */
#define	NINIT	0x04			/* Initialise printer (active low) */
#define	AFEED	0x02			/* Auto line feed */
#define	STROBE	0x01			/* Strobe */

/*
 * On load
 * compute the port addresses,
 * reset the printer, and select it.
 */
static
lpload()
{
	register struct lpinfo * p;
	register int delay;
	static int notfirst;

	/*
	 * Only initialize hardware on first invocation.
	 * Necessary if used as console device [condev].
	 */
	if ( notfirst )
		return;
	notfirst = 1;

	/*
	 * Note: since some PC clones lp ports can't be read,
	 * their lpflag field has to be patched to 'LPTHERE'.
	 */
	if ( LP0_OK & 1 )
		lpinfo[0].lpflag |= LPTHERE;
	if ( LP0_OK & 2 )
		lpinfo[1].lpflag |= LPTHERE;
	if ( LP0_OK & 4 )
		lpinfo[2].lpflag |= LPTHERE;

	for ( p = lpinfo; p->lpbase ; ++p ) {

		/*
		 * Check printer port existence.
		 */
		if ( (p->lpflag & LPTHERE) == 0 ) {
			outb( p->lpbase+LPDAT, 0xA5 );
			delay = LPWAIT; do {
			} while (--delay);
			if ( inb(p->lpbase+LPDAT) == 0xA5 )
				p->lpflag |= LPTHERE;
		}

		/*
		 * Initialize and select printer.
		 */
		outb( p->lpbase+LPCSR, SEL );
		delay = LPWAIT; do {
		} while (--delay);
		outb( p->lpbase+LPCSR, SEL|NINIT );
	}
}

/*
 * On unload
 * cancel any timed functions.
 */
static
lpunload()
{
	lptimer();
}

/*
 * The open routine makes sure that
 * only one process has the printer open
 * at one time, and not too much else.
 */
static
lpopen(dev, mode)
dev_t	dev;
{
	register struct lpinfo * p;

	/*
	 * Illegal printer port.
	 */
	if ( (minor(dev) & ~LPRAW) >= NLP ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Access attributes.
	 */
	p = &lpinfo[ minor(dev) & ~LPRAW ];

	/*
	 * Attempt initialization if printer port not found.
	 */
	if ( (p->lpflag&LPTHERE) == 0 )
		lpload();

	/*
	 * Printer port not found.
	 */
	if ( (p->lpflag&LPTHERE) == 0 ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Printer port already open.
	 */
	if ( (p->lpflag&LPOPEN) != 0 ) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Printer powered off or off-line
	 */
	if (LPTEST && !(inb(p->lpbase+LPSTR) & ONLINE)) {
		u.u_error = EDATTN;
		return;
	}

	/*
	 * Flag port as being open.
	 */
	p->lpflag &= ~LPRAW;
	p->lpflag |= LPOPEN | minor(dev) & LPRAW;

	/*
	 * Initiate periodic printer scan if user open.
	 */
	if ( (SELF != NULL) && (SELF->p_pid != 0) )
		lptimer();
}

/*
 * The close routine marks the device as no longer open.
 */
static
lpclose(dev)
dev_t	dev;
{
	lpinfo[ minor(dev) & ~LPRAW ].lpflag &= ~LPOPEN;
}

/*
 * The write routine copies the
 * characters from the user buffer to
 * the printer buffer, expanding tabs and
 * keeping track of the current horizontal
 * position of the print head.
 */
static
lpwrite( dev, iop )
dev_t	dev;
IO	*iop;
{
	register struct lpinfo * p;
	register int	c;

	p = &lpinfo[ minor(dev) & ~LPRAW ];

	/*
	 * Writes from kernel are handled via busy-waits instead of timeouts.
	 */
	if (iop->io_seg == IOSYS) {

		while ( (c=iogetc(iop)) >= 0 ) {

			while ( (inb(p->lpbase+LPSTR) & IBMNBSY) == 0 )
				;

			outb( p->lpbase+LPDAT, c );
			outb( p->lpbase+LPCSR, SEL|NINIT|STROBE );
			outb( p->lpbase+LPCSR, SEL|NINIT );
		}
		return;
	}

	/*
	 * Writes from user are handled via lpchar() which uses timeouts.
	 */
	while ( (c=iogetc(iop)) >= 0 ) {

		if ( (p->lpflag&LPRAW) == 0 ) {

			switch (c) {

			case '\t':
				do {
					lpchar( p, ' ');
				} while ((++p->lpcol&07) != 0);
				continue;
	
			case '\n':
				lpchar( p, '\r');
				/* no break */

			case '\r':
			case '\f':
				p->lpcol = 0;
				break;
	
			case '\b':
				--p->lpcol;
				break;
	
			default:
				++p->lpcol;
			}
		}
		lpchar( p, c );

		if ( SELF->p_ssig!=0 && nondsig() ) {
			u.u_error = EINTR;
			break;
		}
	}
}

/*
 * Put a character into the printer buffer.
 * If the printer doesn't respond ready in a reasonable time
 * sleep for a while.
 */
static
lpchar( p, c )
register struct lpinfo *p;
int c;
{
	register int	s;

	s = LPWAIT;
	while ( (inb(p->lpbase+LPSTR) & IBMNBSY) == 0 ) {
		if ( --s == 0 ) {
			s = sphi();
			p->lpflag |= LPSLEEP;
			sleep((char *)p, 0, 0, 0);
			spl(s);
			s = LPWAIT;
		}
	}

	outb( p->lpbase+LPDAT, c );
	outb( p->lpbase+LPCSR, SEL|NINIT|STROBE );
	outb( p->lpbase+LPCSR, SEL|NINIT );
}

/*
 * Poll the line printer interface from the clock.
 * Turn it off when there is nothing left to do.
 */
static
lptimer()
{
	register struct lpinfo *p;
	int isopen = 0;
	static TIM tim;

	/*
	 * Scan all printers.
	 */
	for ( p = lpinfo; p->lpbase; ++p ) {

		/*
		 * Ignore unopened printers.
		 */
		if ( (p->lpflag & LPOPEN) == 0 )
			continue;

		++isopen;

		/*
		 * Check for sleeping process on ready printer.
		 */
		if((p->lpflag & LPSLEEP) && (inb(p->lpbase+LPSTR) & IBMNBSY)){
			p->lpflag &= ~LPSLEEP;
			wakeup((char *)p);
		}
	}

	/*
	 * Reschedule timer function if at least 1 printer is still open.
	 */
	if ( isopen )
		timeout( &tim, LPTIME, lptimer, &tim );
}
@


1.3
log
@new version provided y hal for v321
@
text
@d6 2
a7 2
#include <coherent.h>
#include <i8086.h>
a13 1
#include <sys/timeout.h>
@


1.2
log
@Add patchable variable LPTEST for 3.0.0 compatibility.
@
text
@d8 1
a8 1
#include <con.h>
d10 4
a13 4
#include <io.h>
#include <proc.h>
#include <uproc.h>
#include <stat.h>
@


1.1
log
@Shipped with 3.1.0
@
text
@a0 5
/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
d24 1
d26 4
a29 3
int LP0_OK = 0;
int LPTIME = 4;
int LPWAIT = 400;
d225 1
a225 1
	if ((inb(p->lpbase+LPSTR) & ONLINE) == 0) {
@
0707070064030104251004440000030000030000011777770507310652700005700000004225/newbits/kernel/USRSRC/i8086/drv/RCS/msgop.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.2
date     91.06.03.19.53.53;  author hal;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.03.19.52.40;  author hal;  state Exp;
branches ;
next     ;


desc
@Original, nfg with COH 3.X.X.
@


1.2
log
@fixed to run with COH 3.1.0+
@
text
@/*
 * User Message Functions.
 *
 *	Note: msgget() must be first function called.
 *
 *	91/02/07	Hal Snyder	mwchwc!/u/libc/sys/msgop.c
 *	msgget():  sizeof(key_t) is 4, not 2.
 */
#include <sys/msg.h>
#include <errno.h>

static int  msgfno   = -1;
static char msgdev[] = "/dev/msg";

/*
 * Message Control Operations.
 */

msgctl( msqid, cmd, buf )

int msqid;
int cmd;
struct msqid_ds * buf;

{
	int parm[4];

	if ( msgfno < 0 ) {
		errno = ENODEV;
		return -1;
	}

	parm[0] = -1;
	parm[1] = msqid;
	parm[2] = cmd;
	parm[3] = (int) buf;

	ioctl( msgfno, MSGCTL, parm );
	return parm[0];
}

/*
 * Get Message Queue.
 */

msgget( key, msgflg )

key_t key;
int msgflg;

{
	int parm[4];

	if ( msgfno < 0 ) {

		msgfno = open(msgdev, 0);

		if ( msgfno < 0 ) {
			perror(msgdev);
			errno = ENODEV;
			return -1;
		}
	}

	parm[0] = -1;
	parm[1] = key;
	parm[2] = key >> 16;
	parm[3] = msgflg;

	ioctl( msgfno, MSGGET, parm );
	return parm[0];
}

/*
 * Send Message.
 */
 
msgsnd( msqid, msgp, msgsz, msgflg )

int msqid;
struct msgbuf *msgp;
int msgsz;
int msgflg;

{
	int parm[5];

	if ( msgfno < 0 ) {
		errno = ENODEV;
		return -1;
	}

	parm[0] = -1;
	parm[1] = msqid;
	parm[2] = (int) msgp;
	parm[3] = msgsz;
	parm[4] = msgflg;

	ioctl( msgfno, MSGSND, parm );
	return parm[0];
}

/*
 * Receive Message.
 */
 
msgrcv( msqid, msgp, msgsz, msgtyp, msgflg )

int msqid;
struct msgbuf *msgp;
int msgsz;
long msgtyp;
int msgflg;

{
	int parm[7];

	if ( msgfno < 0 ) {
		errno = ENODEV;
		return -1;
	}

	parm[0] = -1;
	parm[1] = msqid;
	parm[2] = (int) msgp;
	parm[3] = msgsz;
	parm[4] = (int) msgtyp;
	parm[5] = (int) (msgtyp >> 16);
	parm[6] = msgflg;

	ioctl( msgfno, MSGRCV, parm );
	return parm[0];
}
@


1.1
log
@Initial revision
@
text
@d5 3
a8 1
 
d52 1
a52 1
	int parm[3];
d56 1
a56 1
		if ( (msgfno = open(msgdev, 0)) < 0 ) {
d58 1
d67 2
a68 1
	parm[2] = msgflg;
@
0707070064030106531004440000030000030000011777770507310652700005400000012137/newbits/kernel/USRSRC/i8086/drv/RCS/rm.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.06.20.14.52.16;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.15.10.01;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.06.18.25.45;  author norm;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.06.18.24.51;  author hal;  state Exp;
branches ;
next     ;


desc
@Ram disk driver.
@


1.4
log
@update provided by hal
@
text
@/*
 * Block or character device RAM disk driver.
 */

#include	<sys/coherent.h>
#include	<sys/buf.h>
#include	<errno.h>
#include	<sys/uproc.h>
#include	<sys/seg.h>
#include	<sys/con.h>
#include	<sys/inode.h>
#include	<sys/stat.h>

/*
 * Minor number encoding: dsssssss
 * d       drive number (0 or 1)
 * sssssss allocation size: 0 to free, 1-127 allocsize (n*ASIZE*BSIZE bytes)
 */
#define	rm_drive(dev)	(minor(dev) >> 7)
#define	rm_asize(dev)	(minor(dev) & 0x7F)
#define	ASIZE		128	/* allocation chunk size in blocks (64KB) */
#define	RMMAJ		8	/* major # for driver */
#define NUM_RM		2	/* number of ram disks */
				/* - tied to dev encoding (see above) */

int	nulldev();
int	nonedev();
int	rmload();
int	rmuload();
int	rmopen();
int	rmclose();
int	rmread();
int	rmwrite();
int	rmblock();

CON	rmcon	= {
	DFBLK|DFCHR,
	RMMAJ,
	rmopen,			/* Open */
	rmclose,		/* Close */
	rmblock,		/* Block */
	rmread,			/* Read */
	rmwrite,		/* Write */
	nonedev,
	nulldev,
	nulldev,
	rmload,			/* Load */
	rmuload			/* Unload */
};

typedef struct rm {
	fsize_t	rm_size;	/* Size in allocation chunks */
	paddr_t	rm_paddr;	/* Physical base of ram disc segment */
	SEG	*rm_segp;	/* Segment pointer of ram device */
	BUF	rm_buf;		/* Static buffer for raw requests */
	int	rm_nopen;	/* Open count to avoid blowups */
} RM;
static	RM	rm[NUM_RM];

/*
 * Load.
 */
static
rmload()
{
}

/*
 * Unload.
 * Release the allocated buffers.
 */
static
rmuload()
{
	int i;

	for (i = 0; i < NUM_RM; i++){
		if (rm[i].rm_size != 0)
			sfree(rm[i].rm_segp);
	}
}

/*
 * Open.
 * Allocate on the first call.
 * Increment the open count.
 */
static
rmopen(dev, mode) dev_t dev; int mode;
{
	register RM *rmp;
	register fsize_t asize, osize;
	register SEG *segp;

	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;

	/* Fail on read before creation or bogus size. */
	if ((mode == IPR && osize == 0)
	 || (asize != 0 && osize != 0 && asize != osize)
	 || (asize == 0 && osize == 0)) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Allocate as required.
	 * Ignore case asize==0 && osize!=0, handled by rmclose().
	 * If asize!=0 && asize==osize, just bump the open count.
	 */
	if (asize != 0 && osize == 0) {
		segp = rmp->rm_segp = salloc((fsize_t)ASIZE*BSIZE*asize,
			SFSYST|SFNSWP|SFNCLR|SFHIGH);
		if (segp == NULL) {
			u.u_error = ENOMEM;
			return;
		}
		rmp->rm_size = asize;
		rmp->rm_paddr = segp->s_paddr;
		rmp->rm_nopen = 0;
		pclear(rmp->rm_paddr, 1024L);	/* clear 1st 2 blocks */
	}
	rmp->rm_nopen++;
}

/*
 * Close.
 * Decrement the open count.
 * Release the allocated buffer if minor number is 0.
 */
static
rmclose(dev) dev_t dev;
{
	register RM *rmp;
	register fsize_t asize, osize;

	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;

	if (osize == 0
	 || (asize != 0 && asize != osize)
	 || rmp->rm_nopen == 0) {
		u.u_error = ENXIO;
		return;
	}
	rmp->rm_nopen--;
	if (asize == 0) {
		if (rmp->rm_nopen != 0) {
			u.u_error = EDBUSY;
			return;
		}
		sfree(rmp->rm_segp);
		rmp->rm_size = 0;
	}
}

static
rmblock(bp) register BUF *bp;
{
	paddr_t base;
	dev_t dev;
	register RM *rmp;
	register fsize_t asize, osize;

	dev = bp->b_dev;
	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;
	if (osize == 0 || asize != osize)
		bp->b_flag |= BFERR;
	else if (bp->b_bno >= asize*ASIZE)
		bp->b_flag |= BFERR;
	else {
		base = rmp->rm_paddr + (paddr_t)bp->b_bno * BSIZE;
		if (bp->b_req == BREAD)
			plrcopy(base, bp->b_paddr, (fsize_t)BSIZE);
		else
			plrcopy(bp->b_paddr, base, (fsize_t)BSIZE);
	}
	bdone(bp);
}

/*
 * The read routine calls the common raw I/O processing code,
 * using a static buffer header in the driver.
 */
static
rmread(dev, iop) register dev_t dev; IO *iop;
{
	register BUF *bufp;

	bufp = &rm[rm_drive(dev)].rm_buf;
	ioreq(bufp, iop, dev, BREAD, BFIOC|BFRAW);
}

/*
 * The write routine is just like the read routine,
 * except that the function code is write instead of read.
 */
static
rmwrite(dev, iop) register dev_t dev; IO *iop;
{
	register BUF *bufp;

	bufp = &rm[rm_drive(dev)].rm_buf;
	ioreq(bufp, iop, dev, BWRITE, BFIOC|BFRAW);
}

/* end of rm.c */
@


1.3
log
@bob h changed <header> references to include sys/ for con.h, uproc.h,
buf.h and seg.h
@
text
@d5 1
a5 1
#include	<coherent.h>
@


1.2
log
@Do salloc with SFHIGH.
@
text
@d6 1
a6 1
#include	<buf.h>
d8 3
a10 3
#include	<uproc.h>
#include	<seg.h>
#include	<con.h>
@


1.1
log
@Shipped with 3.1.0.
@
text
@a0 5
/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
d113 2
a114 1
		segp = rmp->rm_segp = salloc((fsize_t)ASIZE*BSIZE*asize, SFSYST|SFNSWP|SFNCLR);
@
0707070064030106461004440000030000030000011777770507310653100005600000041322/newbits/kernel/USRSRC/i8086/drv/RCS/scsi.c,vhead     1.8;
branch   ;
access   ;
symbols  ;
locks    bin:1.8;
comment  @ * @;


1.8
date     91.06.20.14.52.50;  author bin;  state Exp;
branches ;
next     1.7;

1.7
date     91.06.18.08.14.13;  author bin;  state Exp;
branches ;
next     1.6;

1.6
date     91.06.17.12.35.18;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.06.10.10.25.03;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.06.03.13.50.06;  author hal;  state Exp;
branches ;
next     1.3;

1.3
date     91.05.08.11.00.30;  author root;  state Exp;
branches 1.3.1.1;
next     1.2;

1.2
date     91.05.01.04.50.11;  author root;  state Exp;
branches ;
next     1.1;

1.1
date     91.04.30.11.02.22;  author root;  state Exp;
branches ;
next     ;

1.3.1.1
date     91.05.08.11.01.47;  author root;  state Exp;
branches ;
next     ;


desc
@Somewhat Adaptec-independent code for "sd" driver.
@


1.8
log
@update provided by hal
@
text
@/*
 * This is the generic SCSI part of the
 * Adaptec AHA154x host adapter driver for the AT.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.6  91/06/10  13:28:11  hal
 * Refix startup problem with HDGETA.  Text cleanup.
 * 
 * Revision 1.5  91/06/10  12:58:04  hal
 * Partial fix for HDGETA failing if partition table absent.
 * 
 * Revision 1.4  91/06/03  13:50:06  hal
 * Add HDSETA.
 * 
 * Revision 1.3	91/05/08  11:00:30	root
 * Make number of heads - SD_HDS - patchable for Tandy.
 * 
 * Revision 1.2	91/05/01  04:50:11	root
 * Debug code and d_time/sw_active imbalance fixed.
 * 
 * Revision 1.1	91/04/30  11:02:22	root
 * Shipped with COH 3.1.0
 * 
 */

#include	<sys/coherent.h>
#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/sdioctl.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>
#include	<sys/scsiwork.h>

extern	saddr_t sds;

/*
 * Configurable parameters
 *
 * Adaptec ROM translates at 64 heads, except the Tandy version, which
 * uses 16 heads.  Kernel variable SD_HDS is patchable for this reason.
 */
#ifdef TANDY
int SD_HDS = 16;
#else
int SD_HDS = 64;
#endif
int SD_SPT = 32;

#define NDRIVE	(8 * 4)			/* 8 SCSI ids and 4 LUNs */
#define	SDMAJOR	13			/* Major Device Number */
#define	SDDMA	5			/* Used for first party DMA */

/*
 * user configurable paramters
 */
int	SDIRQ	= 11;			/* Interrupt */
int	SDBASE	= 0x0330;		/* Port base */

/*
 *					LUN --------++
 * device macros			Special-+   ||
 * minor device bits are of the form:		76543210
 *						 |||  ||
 *					SCSI ID--+++  ||
 *					Partition ----++
 * Partition mapping:
 *
 * Description	   Special Bit	   Partition #		Device		Type
 * -----------	   -----------	   -----------		------		----
 * partition a		0		00		/dev/sd??a	disk
 * partition b		0		01		/dev/sd??b	disk
 * partition c		0		10		/dev/sd??c	disk
 * partition d		0		11		/dev/sd??d	disk
 * partition table	1		00		/dev/sd??x	disk
 * no rewind tape	1		01		/dev/sd??n	tape
 * UNALLOCATED		1		10		  ---		????
 * rewind tape device	1		11		/dev/sd??	tape
 */
#define	DRIVENO(minor)	(((minor) >> 2) & 0x1F)	/* SCSI ID + LUN */
#define	SCSIID(minor)	(((minor) >> 4) & 0x7)	/* SCSI ID */
#define	LUN(minor)	(((minor) >> 2) & 0x3)	/* Logical Unit Number */
#define	PARTITION(minor) ((minor) & 0x3)	/* Partition */
#define	sdmkdev(maj, s, drv)	makedev((maj), ((s)|((drv)<<2)))

/*
 * Driver configuration.
 */
void	sdload();
void	sdunload();
void	sdopen();
void	sdclose();
void	sdread();
void	sdwrite();
int	sdioctl();
void	sdblock();
int	sdwatch();
int	nulldev();
int	nonedev();

CON	sdcon	= {
	DFBLK|DFCHR,			/* Flags */
	SDMAJOR,			/* Major index */
	sdopen,				/* Open */
	sdclose,			/* Close */
	sdblock,			/* Block */
	sdread,				/* Read */
	sdwrite,			/* Write */
	sdioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	sdwatch,			/* Timeout */
	sdload,				/* Load */
	sdunload			/* Unload */
};

/*
 *	host adapter routines
 */
int	aha_load();		/* initialize host adapter, DMA */
void	aha_unload();		/* shutdown the host adapter */
int	aha_start();		/* see if there's work */
int	aha_command();

/*
 * Partition Parameters - copied from disk.
 *
 *	There are NPARTN positions for the user partitions in array PPARM,
 *	plus 1 additional position to span the entire drive.
 *	Array pparmp[] contains a pointer to a kalloc()'ed PPARM
 *	entry if the drive actually exists, is a disk drive and if someone
 *	has attmpted to read a partition table from the drive.
 */
typedef	struct	fdisk_s	PPARM[NPARTN + 1];	/* 4 partitions + whole drive */
static	PPARM *pparmp[NDRIVE];			/* one per possible drive */
#define	WHOLE_DRIVE	NPARTN			/* index for whole drive */
#define	PNULL	((PPARM *)0)

/*
 * Per disk controller data.
 * Only one host adapter; no more, no less.
 */
static
scsi_work_t	sd;

static	BUF	dbuf;			/* For raw I/O */
static	int	sw_active;

/**
 *
 * void
 * sdload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void
sdload()
{
	/*
	 * Initialize Drive Controller.
	 */
	sw_active = 0;
	if (aha_load(SDDMA, SDIRQ, SDBASE, &sd) < 0) {
		u.u_error = ENXIO;
		return;
	}
/*	aha_device_info(); */		/* enable after this gets fixed */
}

/**
 *
 * void
 * sdunload()	- unload routine.
 */
static void
sdunload()
{
	register int i;

	if (sw_active > 0)
		printf("aha154x: sdunload() athough %d active\n", sw_active);
	aha_unload(SDIRQ);
	for (i = 0; i < NDRIVE; ++i)
		if (pparmp[i] != PNULL)
			kfree(pparmp[i]);	/* free any partition tables */
}

/*
 * int
 * sdgetpartitions(dev)	- load partition table for specified drive
 *
 *			- return 1 on success and 0 on failure
 */
int sdgetpartitions(dev)
dev_t	dev;
{
	register int 	i;
	scsi_cmd_t	sc;
	unsigned char	*buffer;
	struct fdisk_s	*fdp;
	int	d = DRIVENO(minor(dev));

	pparmp[d] = kalloc(sizeof *pparmp[0]);
	fdp = (struct fdisk_s *) pparmp[d];	/* point to first entry */
	buffer = kalloc(36+1);
	if (buffer == NULL || pparmp[d] == PNULL) {
		printf("aha154x: out of kernel memory\n");
		u.u_error = EKSPACE;
		return 0;
	}
	kclear(pparmp[d], sizeof *pparmp[0]);
	sc.unit = d;
	sc.block = 0L;
	sc.blklen = 0;

	sc.buffer = VTOP2(buffer, sds);
	++drvl[SDMAJOR].d_time;	
#if	0
	sc.cmd = ScmdINQUIRY;
	sc.buflen = 36;
	aha_command(&sc);
	aha_command(&sc);
	buffer[36] = 0;
	printf("SCSI Disk %s", &buffer[8]);
#endif
	sc.cmd = ScmdREADCAPACITY;
	sc.buflen = 8;

	for(i = 0; i < sc.buflen; ++i)
		buffer[i] = 0;
	aha_command(&sc);
	aha_command(&sc);
#if	VERBOSE
	printf("buffer =");
	for(i = 0; i < sc.buflen; ++i)
		printf(" %x", buffer[i]);
	printf("\n");
#endif
	sc.block = (buffer[0]<<8) | buffer[1];
	sc.block <<= 16;
	sc.block |= (buffer[2]<<8) | buffer[3];

	sc.blklen = (buffer[6]<<8) | buffer[7];
#if	VERBOSE
	printf("SCSI %D. blocks of size %d\n", sc.block, sc.blklen);
#endif
	kfree(buffer);
	fdp[WHOLE_DRIVE].p_size = sc.block;
	--drvl[SDMAJOR].d_time;	
	return fdisk(sdmkdev(major(dev), SDEV, d), pparmp[d]);
}

/**
 *
 * void
 * sdopen(dev, mode)
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void
sdopen(dev, mode)
register dev_t	dev;
{
	register int p;			/* partition */
	register int d;			/* drive (SCSI ID + LUN) */
	struct fdisk_s	*fdp;		/* one partition entry */

	if (minor(dev) & SDEV) {
		if (PARTITION(minor(dev)) != 0) {	/* tape device ? */
			u.u_error = ENXIO;		/* not yet! */
devmsg(dev, "No tape yet");
		} else {
			++drvl[SDMAJOR].d_time;	
			++sw_active;
		}
		return;
	}

	d = DRIVENO(minor(dev));
	p = PARTITION(minor(dev));

	/*
	 * If partition not defined read partition characteristics.
	 */
	if (pparmp[d] == PNULL)   /* no entry yet for this drive ? */
		if (!sdgetpartitions(dev)) {
			u.u_error = ENXIO;
			return;
		}
	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	fdp = (struct fdisk_s *) pparmp[d];
	if ((fdp[p].p_base+fdp[p].p_size) > fdp[WHOLE_DRIVE].p_size) {
		u.u_error = EBADFMT;
	} else if (fdp[p].p_size == 0) {
		u.u_error = ENODEV;
	} else {
		++drvl[SDMAJOR].d_time;	
		++sw_active;
	}
}

void sdclose(dev)
{
	--drvl[SDMAJOR].d_time;	
	--sw_active;	
}

/**
 *
 * void
 * sdread(dev, iop)	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
sdread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq(&dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC);
}

/**
 *
 * void
 * sdwrite(dev, iop)	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void
sdwrite(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq(&dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC);
}

/**
 *
 * int
 * sdioctl(dev, cmd, arg)
 * dev_t dev;
 * int cmd;
 * char * vec;
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static int
sdioctl(dev, cmd, vec)
register dev_t	dev;
int cmd;
char * vec;
{
	int d;
	hdparm_t hdparm;
	struct fdisk_s	*fdp;
	int do_getpt = 0;	/* 1 if need to call sdgetpartitions() */

	d = DRIVENO(minor(dev));

	/*
	 * Identify input/output request.
	 */
	switch (cmd) {

	case HDGETA:
		/*
		 * If haven't loaded partition table yet for this drive,
		 * try to do it now.  Note sdgetpartitions() will fail
		 * if there is a new drive (e.g. no signature).  But all
		 * we need is allocation of pparmp[d] and capacity read
		 * properly from the drive.
		 */
		if (pparmp[d] == PNULL) {
			do_getpt = 1;	/* REALLY just want Read Capacity */
			sdgetpartitions(dev);
			if (pparmp[d] == NULL) {
				u.u_error = ENXIO;
				return -1;
			}
		}
		fdp = (struct fdisk_s *) pparmp[d];
		*(short *)&hdparm.landc[0] =
		*(short *)&hdparm.ncyl[0] = fdp[WHOLE_DRIVE].p_size
						/ (SD_HDS * SD_SPT);
		hdparm.nhead = SD_HDS;
		hdparm.nspt = SD_SPT;
		kucopy(&hdparm, vec, sizeof hdparm);
		/*
		 * I know it's ugly.  But it gets around startup Catch-22.
		 *
		 * The fdisk command needs HDGETA.  HDGETA invokes
		 * sdgetpartitions(), but we want to call it again
		 * after the partition table has been created by the fdisk
		 * command.
		 */
		if (do_getpt) {
			kfree(pparmp[d]);
			pparmp[d] = PNULL;	/* force re-read of p. table */
		}
		return 0;
	case HDSETA:
		/*
		 * Set hard disk attributes.
		 */
		fdp = (struct fdisk_s *) pparmp[d];
		ukcopy(vec, &hdparm, sizeof hdparm);
		SD_HDS = hdparm.nhead;
		SD_SPT = hdparm.nspt;
		fdp[WHOLE_DRIVE].p_size =
			(long)(*(short *)&hdparm.ncyl[0])
			* (long)SD_HDS * (long)SD_SPT;

		return 0;
	case SCSI_HA_CMD:
		return aha_ioctl(cmd, vec);
	case SCSI_CMD:
		return 0;
	case SCSI_CMD_IN:
		return 0;
	case SCSI_CMD_OUT:
		return 0;

	default:
		u.u_error = EINVAL;
		return -1;
	}
}

/**
 *
 * void
 * sdblock(bp)	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void
sdblock(bp)
register BUF	*bp;
{
	register scsi_work_t *sw;
	register int s;
	struct	fdisk_s	*fdp;

	int p = PARTITION(minor(bp->b_dev));
	int drv = DRIVENO(minor(bp->b_dev));

	if (minor(bp->b_dev) & SDEV)
		p = WHOLE_DRIVE;
	bp->b_resid = bp->b_count;
	
	fdp = (struct fdisk_s *) pparmp[drv];

	/*
	 * Range check disk region.
	 */
	if (pparmp[drv] == PNULL) {
		if (p == WHOLE_DRIVE) {
			if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
				bp->b_flag |= BFERR;
				bdone(bp);
				return;
			}
		} else {
			printf("aha154x: no partition table\n");
			bp->b_flag |= BFERR;
			bdone(bp);
			return;
		}
	} else if ((bp->b_bno + (bp->b_count/BSIZE)) > fdp[p].p_size) {
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}

	bp->b_actf = NULL;
	sw = (scsi_work_t *)kalloc(sizeof(*sw));
	if (sw == (scsi_work_t *)0) {
		printf("aha154x: out of kernel memory\n");
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}
	sw->sw_bp = bp;
	sw->sw_drv = drv;
	sw->sw_type = 0;
	if (p != WHOLE_DRIVE)
		sw->sw_bno   = fdp[p].p_base + bp->b_bno;
	else
		sw->sw_bno   = bp->b_bno;
	sw->sw_retry = 1;

#if	VERBOSE
	printf("sdblock: drv %x bno %x:%x  bp=%x, flag = %o\n",
		drv, (long)sw->sw_bno, bp, bp->b_flag);
#endif

	s = sphi();
	if (sd.sw_actf == NULL)
		sd.sw_actf = sw;
	else
		sd.sw_actl->sw_actf = sw;
	sd.sw_actl = sw;
	spl(s);

	aha_start();
}

sdwatch()
{
	register i;

	if (i = aha_start())
#if	VERBOSE
		printf("sdwatch: started %d actions\n", i);
#else
		;
#endif
	if (i = aha_completed())
#if	VERBOSE
		printf("sdwatch: completed %d actions\n", i);
#else
		;
#endif
}
@


1.7
log
@update provided by hal
@
text
@d26 1
a26 1
#include	<coherent.h>
d35 1
a35 1
#include	<scsiwork.h>
@


1.6
log
@new version provided y hal for v321
@
text
@@


1.5
log
@initial version prov by hal
@
text
@d3 1
a3 1
 * Adaptec AHA154x host adaptor driver for the AT.
d6 6
d119 1
a119 1
 *	hostadaptor routines
d121 2
a122 2
int	aha_load();		/* initialize hostadaptor, DMA */
void	aha_unload();		/* shutdown the host adaptor */
d165 1
a165 1
	if (aha_load( SDDMA, SDIRQ, SDBASE, &sd ) < 0) {
d182 3
a184 3
	if( sw_active > 0 )
		printf( "aha154x: sdunload() athough %d active\n", sw_active );
	aha_unload( SDIRQ );
d218 1
a218 1
	sc.buffer = VTOP2( buffer, sds );
d223 2
a224 2
	aha_command( &sc );
	aha_command( &sc );
d226 1
a226 1
	printf( "SCSI Disk %s", &buffer[8] );
d231 1
a231 1
	for( i = 0; i < sc.buflen; ++i )
d233 2
a234 2
	aha_command( &sc );
	aha_command( &sc );
d236 4
a239 4
	printf( "buffer =" );
	for( i = 0; i < sc.buflen; ++i )
		printf( " %x", buffer[i] );
	printf( "\n" );
d247 1
a247 1
	printf( "SCSI %D. blocks of size %d\n", sc.block, sc.blklen );
d252 1
a252 1
	return fdisk( sdmkdev(major(dev), SDEV, d), pparmp[d]);
d258 1
a258 1
 * sdopen( dev, mode )
d269 1
a269 1
sdopen( dev, mode )
d276 2
a277 2
	if ( minor(dev) & SDEV ) {
		if ( PARTITION(minor(dev)) != 0 ) {	/* tape device ? */
d293 1
a293 1
	if ( pparmp[d] == PNULL )   /* no entry yet for this drive ? */
d304 1
a304 1
	} else if ( fdp[p].p_size == 0 ) {
d312 1
a312 1
void sdclose( dev )
d321 1
a321 1
 * sdread( dev, iop )	- write a block to the raw disk
d331 1
a331 1
sdread( dev, iop )
d335 1
a335 1
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
d341 1
a341 1
 * sdwrite( dev, iop )	- write a block to the raw disk
d351 1
a351 1
sdwrite( dev, iop )
d355 1
a355 1
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
d361 1
a361 1
 * sdioctl( dev, cmd, arg )
d374 1
a374 1
sdioctl( dev, cmd, vec )
d382 1
d389 1
a389 1
	switch ( cmd ) {
d400 1
d402 1
a402 2
			if (pparmp[d] == NULL ||
			((struct fdisk_s *)pparmp[d])[WHOLE_DRIVE].p_size == 0L) {
d413 13
a425 1
		kucopy( &hdparm, vec, sizeof hdparm );
d441 1
a441 1
		return aha_ioctl( cmd, vec );
d458 1
a458 1
 * sdblock( bp )	- queue a block to the disk
d476 1
a476 1
	if ( minor(bp->b_dev) & SDEV )
d485 2
a486 2
	if ( pparmp[drv] == PNULL ) {
		if ( p == WHOLE_DRIVE ) {
d498 1
a498 1
	} else if ( (bp->b_bno + (bp->b_count/BSIZE)) > fdp[p].p_size ) {
d505 1
a505 1
	sw = (scsi_work_t *)kalloc( sizeof(*sw) );
d515 1
a515 1
	if ( p != WHOLE_DRIVE )
d522 2
a523 2
	printf( "sdblock: drv %x bno %x:%x  bp=%x, flag = %o\n",
		drv, (long)sw->sw_bno, bp, bp->b_flag );
d541 1
a541 1
	if( i = aha_start() )
d543 1
a543 1
		printf( "sdwatch: started %d actions\n", i );
d547 1
a547 1
	if( i = aha_completed() )
d549 1
a549 1
		printf( "sdwatch: completed %d actions\n", i );
@


1.4
log
@Add HDSETA.
@
text
@d5 4
a8 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d385 11
a395 2
		if (pparmp[d] == PNULL)
			if (!sdgetpartitions(dev)) {
d399 1
@


1.3
log
@Make number of heads - SD_HDS - patchable for Tandy.
@
text
@d6 3
d41 1
a44 1
#define	NSEC	32			/* controller fakes this value */
d390 1
a390 1
						/ (SD_HDS * NSEC);
d392 1
a392 1
		hdparm.nspt = NSEC;
d395 13
@


1.3.1.1
log
@Print messages on open, devmsgs when open fails.
@
text
@a283 1
devmsg(dev, "sdgetpartitions() failed");
a289 2
printf("base=%ld size=%ld ", fdp[p].p_base, fdp[p].p_size);
printf("cap=%ld\n", fdp[WHOLE_DRIVE].p_size);
a291 1
devmsg(dev, "partition past end of drive");
a293 1
devmsg(dev, "partition size 0");
@


1.2
log
@Debug code and d_time/sw_active imbalance fixed.
@
text
@d6 3
d29 3
d33 6
d41 1
a41 2
#define	NHEAD	64			/* controller fakes this value */
#define	NSEC	32			/* likewise... */
d205 1
a205 1
printf("A");
d267 1
d290 1
a290 1
	if ((fdp[p].p_base+fdp[p].p_size) > fdp[WHOLE_DRIVE].p_size)
d292 1
a292 1
	else if ( fdp[p].p_size == 0 )
d294 1
a294 1
	else {
d387 2
a388 2
						/ (NHEAD * NSEC);
		hdparm.nhead = NHEAD;
a483 1
	++drvl[SDMAJOR].d_time;	
@


1.1
log
@Shipped with COH 3.1.0
@
text
@d5 4
a8 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
a18 1
#include	<sys/mmu.h>
d194 2
a195 1
	sc.buffer = vtop( buffer, sds );
d254 1
a254 1
		if ( PARTITION(minor(dev)) != 0 )	/* tape device ? */
d256 4
@
0707070064030106361004440000030000030000011777770507310653500005400000211643/newbits/kernel/USRSRC/i8086/drv/RCS/ss.c,vhead     2.16;
branch   ;
access   ;
symbols  ;
locks    bin:2.16;
comment  @ * @;


2.16
date     91.06.20.14.53.35;  author bin;  state Exp;
branches ;
next     2.15;

2.15
date     91.06.18.08.15.11;  author bin;  state Exp;
branches ;
next     2.14;

2.14
date     91.06.17.12.36.22;  author bin;  state Exp;
branches ;
next     2.13;

2.13
date     91.06.10.10.25.27;  author bin;  state Exp;
branches ;
next     2.12;

2.12
date     91.05.31.13.18.39;  author hal;  state Exp;
branches ;
next     2.11;

2.11
date     91.05.30.15.43.17;  author hal;  state Exp;
branches ;
next     2.10;

2.10
date     91.05.29.11.14.24;  author hal;  state Exp;
branches ;
next     2.9;

2.9
date     91.05.22.01.38.55;  author hal;  state Exp;
branches ;
next     2.8;

2.8
date     91.05.21.23.13.15;  author hal;  state Exp;
branches ;
next     2.7;

2.7
date     91.05.21.19.10.43;  author hal;  state Exp;
branches ;
next     2.6;

2.6
date     91.05.21.13.53.22;  author root;  state Exp;
branches ;
next     2.5;

2.5
date     91.05.20.18.02.52;  author root;  state Exp;
branches ;
next     2.4;

2.4
date     91.05.20.17.22.06;  author root;  state Exp;
branches ;
next     2.3;

2.3
date     91.05.20.16.20.33;  author root;  state Exp;
branches ;
next     2.2;

2.2
date     91.05.20.10.23.58;  author root;  state Exp;
branches ;
next     2.1;

2.1
date     91.05.17.14.26.12;  author root;  state Exp;
branches ;
next     ;


desc
@ST01/ST02 Device Driver.
@


2.16
log
@update provided by hal
@
text
@/*
 * Device driver for Seagate ST01/ST02 scsi host adapters.
 *
 * To do:
 *	nonzero LUN's
 *	start new command during disconnect
 *	rewrite as single state machine, instead of 7 of them
 *	separate SCSI layer from host-dependent stuff
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 3.1  91/06/17  07:43:25  hal
 * Add TMC-840 code.
 * 
 * Revision 1.1  91/06/17  07:42:27  hal
 * Add TMC-840 code.
 * 
 * 
 */

/*
 * Debug levels.
 * DEBUG = 0	No debug output.
 * DEBUG = 1	Debug output on error only.
 * DEBUG = 2	Debug output on error and at other selected places.
 * DEBUG = 3	Print state machine trace.
 * DEBUG = 4	Print info xfer phases and msg_in values.
 */
#if (DEBUG >= 1)
static int s_id;
#define PR1(str)		printf("%s%d ", str, s_id)
#else
#define PR1(str)
#endif
#if (DEBUG >= 2)
#define PR2(str)		printf(str)
#else
#define PR2(str)
#endif
#if (DEBUG >= 3)
#define PR3(str)		printf("%s%d ", str, s_id)
#else
#define PR3(str)
#endif
#if (DEBUG >= 4)
#define PR4(str)		printf("%s%d ", str, s_id)
#else
#define PR4(str)
#endif

/*
 * Includes.
 */
#include	<sys/coherent.h>
#include	<sys/io.h>
#include	<sys/sched.h>
#include	<sys/uproc.h>
#include	<sys/proc.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/devices.h>		/* SCSI_MAJOR */
#include	<errno.h>
#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<sys/scsiwork.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

#define SS_RAM		0x1800	/* Offset of parameter RAM */

				/* Future Domain */
#define FD_CSR		0x1C00	/* Offset of control/status register */
#define FD_DAT		0x1E00	/* Offset of data port */

				/* Seagate */
#define SS_CSR		0x1A00	/* Offset of control/status register */
#define SS_DAT		0x1C00	/* Offset of data port */

#define SS_RAM_LEN	128	/* ST0x has 128 bytes of RAM */
#define SS_DAT_LEN	0x400	/* Byte range mapped to data port */
#define SS_SEL_LEN	0x2000	/* Total size of memory-mapped area */

#define WC_ENABLE_SCSI	0x80	/* Write Control (WC) register bits */
#define WC_ENABLE_IRPT	0x40
#define WC_ENABLE_PRTY	0x20
#define WC_ARBITRATE	0x10
#define WC_ATTENTION	0x08
#define WC_BUSY  	0x04
#define WC_SELECT  	0x02
#define WC_SCSI_RESET  	0x01

#define RS_ARBIT_COMPL	0x80	/* Read STATUS (RS) register bits */
#define RS_PRTY_ERROR	0x40
#define RS_SELECT	0x20
#define RS_REQUEST	0x10
#define RS_CTRL_DATA	0x08
#define RS_I_O  	0x04
#define RS_MESSAGE  	0x02
#define RS_BUSY  	0x01

#define DEV_SCSI_ID(dev)	((dev >> 4) & 0x0007)
#define DEV_LUN(dev)		((dev >> 2) & 0x0003)
#define DEV_DRIVE(dev)		((dev >> 2) & 0x001F)
#define DEV_PARTN(dev)		(dev & 0x0003)
#define DEV_SPECIAL(dev)	(dev & 0x0080)

#define HIPRI_RETRIES	5000	/* # of times to retry while hogging CPU */
#define LOPRI_RETRIES	5	/* # of retries with sleep between tries */
#define WHOLE_DRIVE	NPARTN
#define RESET_TICKS	50	/* # of clock ticks for reset settling */
#define LOAD_DELAY	10000	/* Loop counter during ssload() only */

#define BUS_FREE	((ffbyte(ss_csr) & (RS_BUSY | RS_SELECT)) == 0)
#define TGT_RSEL	\
	(  (ffbyte(ss_csr) & (RS_SELECT |  RS_I_O   )) \
	&& (ffbyte(ss_dat) & (host_id   | (1<<s_id) )) )

#define DELAY_ARB	10	/* delays units are 10 msec (clock ticks) */
#define DELAY_BDR	30
#define DELAY_BSY	20
#define DELAY_RES	50
#define DELAY_RST	40

#define MAX_AVL_COUNT	100
#define MAX_BDR_COUNT	3
#define MAX_BSY_COUNT	3
#define MAX_TRY_COUNT	10
#define INL_MAX_REQ_POLL	100000L
#define WKG_MAX_REQ_POLL	5000L

typedef unsigned char	uchar;
typedef unsigned int	uint;
typedef unsigned long	ulong;

typedef enum {			/* values for current driver state */
	SST_DEQUEUE =0,
	SST_BUS_DEV_RESET,
	SST_HIPRI_RESET,
	SST_LOPRI_RESET,
	SST_POLL_ARBITN,
	SST_POLL_BEGIN_IO,
	SST_POLL_RESELECT,
	SST_REQ_SENSE,
	SST_RESET_OFF
} SST_TYPE;

typedef enum {			/* values for input to recovery routine */
	RV_A_TIMEOUT,
	RV_P_TIMEOUT,
	RV_R_TIMEOUT,
	RV_BF_TIMEOUT,
	RV_CS_BUSY,
	RV_CS_CHECK
} RV_TYPE;

typedef struct ss {
	ulong	capacity;
	ulong	blocklen;
	ulong	bno;
	int	msg_in;
	int	dr_watch;
	uchar	cmdbuf[G1CMDLEN];
	int	cmdlen;
	int	cmd_bytes_out;
	int	cmdstat;
	BUF	*bp;		/* current I/O request node, or NULL */
	struct	fdisk_s parmp[NPARTN+1];
	SST_TYPE state;
	TIM	tim;		/* for target-specific timers */
	uchar	avl_count;
	uchar	bdr_count;
	uchar	bsy_count;
	uchar	try_count;
	uint	busy:1;		/* 1 if command uses local buffer */
	uint	expired:1;	/* 1 if target's timer has expired */
	uint	ptab_read:1;	/* 1 if partition table has been read */
	uint	waiting:1;	/* 1 if target timer is running */
}	ss_type;

typedef struct {
	uint	ncyl;
	uchar	nhead;
	uchar	nspt;
}	drv_parm_type;

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */

/* functions from bufq.c */
extern int bufq_init();
extern void bufq_rlse();
extern void bufq_wr_tail();
extern BUF * bufq_rd_head();
extern BUF * bufq_rm_head();

/* functions from ssas.s */
extern void	ss_get();
extern int	ss_put();
extern int	nulldev();
extern int	nonedev();
extern unsigned char ffbyte();

static void	ssopen();		/* CON functions */
static void	ssclose();
static void	ssblock();
static void	ssread();
static void	sswrite();
static int	ssioctl();
static void	sswatch();
static void	ssload();
static void	ssunload();

static int	bus_dev_reset();	/* additional support functions */
static int	chk_reconn();
static void	do_connect();
static void	dummy_reconn();
static int	far_info_xfer();
static int	host_ident();
static int	init_call();
static void	init_pointers();
static int	inquiry();
static int	local_info_xfer();
static int	mode_sense();
static void	next_req();
static void	nonpolled();
static int	read_cap();
static void	recover();
static int	req_sense();
static int	rsel_handshake();
static void	ssdelay();
static void	ss_finished();
static void	ss_mach();
static void	set_timeout();
static int	ssinit();
static void	ssintr();
static int	start_arb();
static void	stop_timeout();
static uchar	xpmod();

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
CON	sscon	= {
	DFBLK|DFCHR,			/* Flags */
	SCSI_MAJOR,			/* Major index */
	ssopen,				/* Open */
	ssclose,			/* Close */
	ssblock,			/* Block */
	ssread,				/* Read */
	sswrite,			/* Write */
	ssioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	sswatch,			/* Timeout */
	ssload,				/* Load */
	ssunload,			/* Unload */
	nulldev				/* Poll */
};

	/* Patch these Export Variables to configure the driver. */
/*
 * In the low byte of NSDRIVE, bit n is 1 if SCSI ID n is an installed target.
 * The high byte indicates which type of host adapter:
 *   00 - ST01/ST02
 *   80 - TMC-845/850/860/875/885
 *   40 - TMC-840/841/880/881
 */
uint	NSDRIVE = 0x0000;
uint	SS_INT = 5;		/* ST0[12] use either IRQ3 or IRQ5 */
uint	SS_BASE = 0xCA00;	/* Segment addr of ST0x communication area */

/* ncyl, nhead, nspt */
drv_parm_type drv_parm[MAX_SCSI_ID] = {
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0}
};

static BUF	dbuf;		/* For raw I/O */
static paddr_t	ss_base;	/* physical address of ST0x comm area */
static faddr_t	ss_fp;		/* (far *) to ST0x comm area */

static faddr_t	ss_ram;		/* (far *) to parameter RAM */
static faddr_t	ss_csr;		/* (far *) to control/status */
static faddr_t	ss_dat;		/* (far *) to data port */

static TIM	delay_tim;	/* needed for calls to ssdelay() */
static int	do_sst_op;	/* 1 when state machine iteration continues */
static int	ss_expired;	/* 1 after local timeout */

static uint	max_req_poll;	/* this changes after initialization */

static uchar	host_id;	/* Host is SCSI ID #7 for Seagate, 6 for FD */
static uchar	swap_status_bits;

static ss_type	*ss_tbl;	/* points to block of "ss" structs */
static ss_type  *ss[MAX_SCSI_ID];

/*
 * host_claimed is -1 if host is available, else it's the SCSI id of the
 *	target that claims the host.
 *
 * host is claimed at start of any of the follwoing:
 *	SCSI bus reset
 *	arbitration for block i/o request
 *	reselect
 *
 * host is released at:
 *	end of SCSI bus reset
 *	completion (successful or not) of block i/o request (ss_finished)
 *	disconnect <-- temporarily disabled
 */
static int	host_claimed;

/*
 * ssload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void ssload()
{
	int erf = 0;  /* 1 if error occurs */
	int i;
	int max_id = -1;
	int num_drives = 0;

	/*
	 * Allocate a selector to map into ST0x memory-mapped comm area.
	 */
	ss_base = (paddr_t)((long)(unsigned)SS_BASE << 4);
	ss_fp = ptov(ss_base, (fsize_t)SS_SEL_LEN);

	ss_ram = ss_fp + SS_RAM;

	/*
	 * Primitive test of ST0x RAM.
	 */
	sfword(ss_ram, 0xA55A);
	sfword(ss_ram + 2, 0x3CC3);
	sfword(ss_ram + SS_RAM_LEN - 4, 0xA55A);
	sfword(ss_ram + SS_RAM_LEN - 2, 0x3CC3);
	if (ffword(ss_ram) != 0xA55A		/* fetch a "far" word */
	||  ffword(ss_ram + 2) != 0x3CC3
	||  ffword(ss_ram + SS_RAM_LEN - 4) != 0xA55A
	||  ffword(ss_ram + SS_RAM_LEN - 2) != 0x3CC3) {
		printf("Error - host failed memory test\n");
		erf = 1;
	}

	/*
	 * Set host-dependent constants.
	 */
	switch(NSDRIVE >> 8) {
	case 0x00:	/* ST01/ST02 */
		ss_csr = ss_fp + SS_CSR;
		ss_dat = ss_fp + SS_DAT;
		host_id = 0x80;		/* host is id #7 */
		break;
	case 0x80:	/* TMC-845/850/860/875/885 */
		ss_csr = ss_fp + FD_CSR;
		ss_dat = ss_fp + FD_DAT;
		host_id = 0x40;		/* host is id #6 */
		break;
	case 0x40:	/* TMC-840/841/880/881 */
		ss_csr = ss_fp + SS_CSR;
		ss_dat = ss_fp + SS_DAT;
		host_id = 0x40;		/* host is id #6 */
		swap_status_bits = 1;
		break;
	}
	NSDRIVE &= ~(uint)host_id;

	/*
	 * Allocate drive structs.
	 *
	 * Do a single call to kalloc() then put allocated pieces into
	 * array ss.
	 *
	 * First allocate and clear storage.  Then hook up the pointers.
	 */
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID; i++)
			if ((NSDRIVE >> i) & 1) {
				max_id = i;
				num_drives++;
			}
		if (num_drives == 0) {
			printf("Error - ss has no valid target id's\n");
			erf = 1;
		} else if ((ss_tbl = kalloc(num_drives*sizeof(ss_type)))
		== NULL) {
			printf("Error - ss can't allocate structs\n");
			erf = 1;
		} else
			kclear(ss_tbl, num_drives * sizeof(ss_type));
	}
	if (!erf) {
		ss_type *foo = ss_tbl;

		for (i = 0; i < MAX_SCSI_ID; i++)
			if ((NSDRIVE >> i) & 1)
				ss[i] = foo++;
	}

	/*
	 * Claim IRQ vector.
	 */
	setivec(SS_INT, ssintr);

	/*
	 * Initialize drives we know about (i.e. in NSDRIVE bitmap).
	 */
	host_claimed = -1;
	bufq_init(max_id + 1);
	max_req_poll = INL_MAX_REQ_POLL;
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID; i++)
			if ((NSDRIVE >> i) & 1)
				ssinit(i);
	}
	max_req_poll = WKG_MAX_REQ_POLL;
}

/*
 * ssunload()	- unload routine.
 */
static void ssunload()
{
	/*
	 * Deallocate driver heap space.
	 */
	if (ss_tbl)
		kfree(ss_tbl);
	bufq_rlse();

	/*
	 * Free the ST0x selector.
	 */
	vrelse(ss_fp);

	/*
	 * Release IRQ vector.
	 */
	clrivec(SS_INT);
}

/*
 * ssopen()
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void ssopen(dev, mode)
register dev_t	dev;
{
	int drive, partn;
	struct	fdisk_s	*fdp;
	ss_type * ssp;
	int s_id;
	uchar * msg;

	/*
	 * Set up local variables.
	 */
	drive = DEV_SCSI_ID(dev);
	partn = DEV_PARTN(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;

#if (DEBUG >= 3)
devmsg(dev, "ssopen");
#endif

	/*
	 * LUN must be zero.
	 * SCSI id must have corresponding 1 in NSDRIVE bitmapped variable.
	 */
	if (DEV_LUN(dev) != 0 || ((1 << drive) & NSDRIVE) == 0) {
		msg = "bad LUN or SCSI id";
		u.u_error = ENXIO;
		goto bad_open;
	}

	/*
	 * If "special" bit is set, partition field must be zero.
	 */
	if (DEV_SPECIAL(dev) && partn != 0) {
		msg = "bad special partition";
		u.u_error = ENXIO;
		goto bad_open;
	}

	/*
	 * Subscripting gimmick for partition table.
	 */
	if (dev & SDEV)
		partn = WHOLE_DRIVE;

	/*
	 * If not accessing whole drive and the partition table has not
	 * been read yet, try to read it now.
	 * Do this by calling fdisk() with partition table device on the drive
	 * that is being accessed.
	 */
	if (partn != WHOLE_DRIVE && !(ssp->ptab_read)) {
		int fdisk_dev;

		fdisk_dev = (dev | SDEV) & 0xfff0;

#if (DEBUG >=3)
		devmsg(fdisk_dev, "calling fdisk");
		if (fdisk(fdisk_dev, fdp)) {
			int p;

			fdp[WHOLE_DRIVE].p_size = ssp->capacity;
			fdp[WHOLE_DRIVE].p_base = 0;
			printf("fdisk() succeeded\n");
			for (p=0; p<=WHOLE_DRIVE; p++)
	printf("p=%d base=%ld size=%ld\n", p, fdp[p].p_base, fdp[p].p_size);
			ssp->ptab_read = 1;
		} else {
			printf("fdisk() failed\n");
			u.u_error = ENXIO;
			goto bad_open;
		}
#else
		if (fdisk(fdisk_dev, fdp)) {
			fdp[WHOLE_DRIVE].p_size = ssp->capacity;
			fdp[WHOLE_DRIVE].p_base = 0;
			ssp->ptab_read = 1;
		} else {
			msg = "bad partition table";
			u.u_error = ENXIO;
			goto bad_open;
		}
#endif

	}

	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	if (partn != WHOLE_DRIVE
	&& (fdp[partn].p_base+fdp[partn].p_size) > fdp[WHOLE_DRIVE].p_size) {
		msg = "partition exceeds drive capacity";
		u.u_error = EBADFMT;
		goto bad_open;
	}

	if (partn != WHOLE_DRIVE && fdp[partn].p_size == 0) {
		msg = "partition not found";
		u.u_error = ENODEV;
		goto bad_open;
	}

	/*
	 * OK to open the device.
	 * Start watchdog timer (if not already started) for the host adapter.
	 */
	++drvl[SCSI_MAJOR].d_time;
	++ssp->dr_watch;
	goto end_open;

bad_open:
	devmsg(dev, msg);
end_open:
	return;
}

/*
 * ssclose()
 */
static void ssclose(dev)
dev_t dev;
{
	ss_type * ssp;
	int s_id;

	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];

	/*
	 * Decrement the number of watchdog timer requests open for host
	 * adapter and for target.
	 */
	--drvl[SCSI_MAJOR].d_time;	
	--ssp->dr_watch;

#if (DEBUG >= 3)
devmsg(dev, "ssclose");
#endif

}

/*
 * ssread()	- read a block from the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void ssread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
}

/*
 * sswrite()	- write a block to the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void sswrite(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
}

/*
 * ssioctl()
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 */
static int ssioctl(dev, cmd, vec)
register dev_t	dev;
int cmd;
char * vec;
{
	int ret = 0;
	hdparm_t hdparm;
	struct	fdisk_s	*fdp;
	int s_id;
	ss_type * ssp;

	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;

	switch(cmd) {
	case HDGETA:
		/*
		 * Get hard disk attributes.
		 */
PR3("HDGETA");
		fdp = ssp->parmp;
		*(short *)&hdparm.landc[0] =
		*(short *)&hdparm.ncyl[0] = drv_parm[s_id].ncyl;
		hdparm.nhead = drv_parm[s_id].nhead;
		hdparm.nspt = drv_parm[s_id].nspt;
#if (DEBUG >= 3)
printf("ncyl=%d nhead=%d nspt=%d\n",
  hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt);
#endif
		kucopy(&hdparm, vec, sizeof hdparm);
		ret = 0;
		break;
	case HDSETA:
		/*
		 * Set hard disk attributes.
		 */
PR3("HDSETA");
		fdp = ssp->parmp;
		ukcopy(vec, &hdparm, sizeof hdparm);
		drv_parm[s_id].ncyl = *(short *)&hdparm.ncyl[0];
		drv_parm[s_id].nhead = hdparm.nhead;
		drv_parm[s_id].nspt = hdparm.nspt;
#if (DEBUG >= 3)
printf("ncyl=%d nhead=%d nspt=%d\n",
  hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt);
#endif
		ret = 0;
		break;
	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * ssblock()	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void ssblock(bp)
register BUF	*bp;
{
	struct	fdisk_s	*fdp;
	int partition, drive, s_id;
	dev_t dev;
	ss_type * ssp;
	uchar * msg = NULL;

	/*
	 * Set up local variables.
	 */
	dev = bp->b_dev;
	partition = DEV_PARTN(dev);
	drive = DEV_DRIVE(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	if (dev & SDEV)
		partition = WHOLE_DRIVE;
	fdp = ssp->parmp;

	bp->b_resid = bp->b_count;
#if (DEBUG >= 2)
if (bp->b_count != BSIZE)
	printf("b_count=%d ", bp->b_count);
#endif

	/*
	 * Range check disk region.
	 */
	if (!(ssp->ptab_read)) {
		if ( partition == WHOLE_DRIVE ) {
			if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
				msg = "invalid request";
				bp->b_flag |= BFERR;
				goto bad_blk;
			}
		} else {
			msg = "no partition table";
			bp->b_flag |= BFERR;
			goto bad_blk;
		}
	}

	/*
	 * Check for read at end of partition.
	 * (Need to return with b_resid = BSIZE to signal end of volume.)
	 */
	else if ((bp->b_req == BREAD) && (bp->b_bno == fdp[partition].p_size)) {
		goto bad_blk;
	}

	/*
	 * Check for read past end of partition.
	 */
	else if ( (bp->b_bno + (bp->b_count/BSIZE))
	> fdp[partition].p_size ) {
		msg = "partition overrun";
		bp->b_flag |= BFERR;
		goto bad_blk;
	}

	/*
	 * Fail if request is for zero bytes or is not even # of blocks.
	 */
	if ((bp->b_count % BSIZE) || bp->b_count == 0) {
		msg = "invalid byte count";
		bp->b_flag |= BFERR;
		goto bad_blk;
	}

	/*
	 * Operation appears valid.
	 * Fill fields in the node and queue the request.
	 */
	bufq_wr_tail(s_id, bp);
	ss_mach(s_id);
	goto end_blk;

	/*
	 * Operation cannot be done.  Release the kernel buffer structure.
	 * Value of "bp->b_flag" tells caller if error occurred.
	 */
bad_blk:
	if (msg)
		devmsg(dev, msg);
	bdone(bp);

end_blk:
	return;
}

/*
 * ssintr()	- Interrupt routine.
 *
 * If we have been reselected by a recognized target device
 *	let kernel get out of interrupt mode (defer) and do SCSI
 *	reconnect stuff.
 */
static void ssintr()
{
	int s_id;

	s_id = chk_reconn();
	if (s_id != -1) {
		if (ss[s_id]->state == SST_POLL_RESELECT)
			defer(ss_mach, s_id);
		else
			defer(dummy_reconn, s_id);
PR3("!");
	}
}

/*
 * dummy_reconn()
 *
 * Somehow we are in a state where the driver software does not expect
 * a reconnect but a device is trying one anyway.  Go thru the motions
 * of reconnect because not servicing a hanging reselect seems to leave
 * the target hung - in such a way that it fails to respond to reset
 * messages and to reset on the SCSI bus.
 */
static void dummy_reconn(s_id)
int s_id;
{
	int bus_timeout;
	uchar phase_type;
	int s;
	int msg_in;
	int cmdstat;
	int xfer_good = 1;
PR1("DUM");
	if (ss[s_id]->state == SST_POLL_RESELECT) {
		defer(ss_mach, s_id);
		goto dum_done;
	}
	if (!rsel_handshake())
		goto dum_done;

	s = sphi();
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		switch (xpmod(phase_type)) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
			case MSG_DISCONNECT:
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			}
			break;
		case XP_MSG_OUT:
			sfbyte(ss_dat, MSG_NOP); 
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
			break;
		case XP_STAT_IN:
			cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
		case XP_DATA_OUT:
			xfer_good = 0;
			break;
		case XP_DATA_IN:
			ffbyte(ss_dat);
			break;
		default:
			break;
		} /* endswitch */
	} /* endwhile */
	spl(s);

dum_done:
	return;
}

/*
 * sswatch()
 *
 * Invoked once per second if any devices going through this driver are open.
 * Poll for any reselect, in case interrupt got lost.
 */
static void sswatch()
{
	int s_id;
	ss_type * ssp;

	for (s_id = 0; s_id < MAX_SCSI_ID; s_id++) {
		ssp = ss[s_id];
		if (ssp && ssp->dr_watch)
			defer(ss_mach, s_id);
	} /* endfor */
}

/*
 * bus_wait()
 *
 * Wait for specified bit values to appear in Status Register.
 * This uses a tight loop and does not expect to be interrupted.
 *
 * Argument "flags" is a double-byte value;  the high byte is ANDed with
 * status register contents, and the result is tested for equality with
 * the low byte.
 *
 * Return 1 if values wanted appeared, 0 if timeout occurred.
 */
static int bus_wait(flags)
unsigned short flags;
{
	int found, i;
	unsigned char status;

	found = 0;
	for ( i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & (flags >> 8)) == (flags & 0xff)) {
			found = 1;
			break;
		}
	}

#if (DEBUG >= 1)
	if (!found)
		printf("TO:f=%x s=%x ", flags, status);
#endif

	return found;
}

/*
 * ssinit()
 *
 * Attempt to initialize the (unique) drive with a given SCSI id.
 * Assume only one drive per SCSI id, having LUN = 0.
 * 
 * Return 1 if success, 0 if failure.
 */
static int ssinit(s_id)
int s_id;
{
	int retval = 1;
	uchar query_buf[MODESENSELEN];
	ss_type * ssp = ss[s_id];
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

	printf("SCSI ID %d  LUN 0\n", s_id);
	if (retval)
		if (init_call(inquiry, s_id, query_buf)) {
			query_buf[INQUIRYLEN] = 0;
#if (debug >= 2)
			devmsg(dev, query_buf + 8);
#endif
			if (query_buf[0] == 0) {
				retval = 1;
			} else
				devmsg(dev, "Not Direct Access Device");
		} else
			devmsg(dev, "Inquiry Failed");

	if (retval)
		if (init_call(read_cap, s_id, query_buf)) {
			retval = 1;
			ssp->capacity = query_buf[3] | (query_buf[2] << 8)
			| (((long)(query_buf[1])) << 16)
			| (((long)(query_buf[0])) << 24);
			ssp->blocklen = query_buf[7] | (query_buf[6] << 8)
			| (((long)(query_buf[5])) << 16)
			| (((long)(query_buf[4])) << 24);

			printf("Capacity=%ld blocks  Block length=%ld\n",
				ssp->capacity, ssp->blocklen);
		} else
			devmsg(dev, "Read Capacity Failed");

	if (retval)
		if (init_call(mode_sense, s_id, query_buf)) {
			/*
			 * Display physical drive parameters.
			 */
#define FMT_PG	(4+8+8+12)
#define DDG_PG	(4+8+8+12+24)
			uchar heads;
			unsigned short spt;
			ulong cyls;

			spt=((int)query_buf[FMT_PG+10]<<8)
				+ query_buf[FMT_PG+11];
			cyls=((int)query_buf[DDG_PG+2]<<16)
				+ ((int)query_buf[DDG_PG+3]<<8)
				+ query_buf[DDG_PG+4];
			heads=query_buf[DDG_PG+5];

			printf("Physical:  cylinders=%ld ", cyls);
			printf("heads=%d ", heads);
			printf("spt=%d\n", spt);

			if (drv_parm[s_id].ncyl == 0) {
				drv_parm[s_id].ncyl = cyls;
				drv_parm[s_id].nhead = heads;
				drv_parm[s_id].nspt = spt;
			} else {
				printf("Logical:  cylinders=%d ",
					drv_parm[s_id].ncyl);
				printf("heads=%d ", drv_parm[s_id].nhead);
				printf("spt=%d\n", drv_parm[s_id].nspt);
			}
		} else
			devmsg(dev, "Mode Sense Failed");

	return retval;
}

/*
 * far_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * This includes message in/out, command in/out, and data in/out.
 *
 * If cmdlen is nonzero, cmdbuf is an array of bytes of that length,
 * to be sent to the target.
 *
 * Return 1 if bus timeout did not occur, else 0.
 *
 * pseudocode:
 *
 * while (wait for REQ true or BUSY false on SCSI bus)
 *   if (BUSY false)
 *     break from while loop
 *   else
 *     switch (xfer phase = RS_CTRL_DATA|RS_I_O|RS_MESSAGE)
 *       case XP_MSG_IN/XP_MSG_OUT/...
 *         handle the indicated information transfer phase
 *     endswitch
 *   endif
 * endwhile
 */
static int far_info_xfer(s_id)
int s_id;
{
	int bus_timeout;
	uchar phase_type;
	uchar msg_in;
	int s;
	int bytes_to_send;
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int xfer_good = 1;
	int xfer_count = bp->b_count - bp->b_resid;
	int irpts_masked;
int block_done=0;

	ssp->cmd_bytes_out = 0;
	ssp->msg_in = -1;

	irpts_masked = 0;
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		if (!irpts_masked) {
			s = sphi();
			irpts_masked = 1;
		}
		switch (xpmod(phase_type)) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
PR4("Mcc");
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			case MSG_DISCONNECT:
PR4("Mdc");
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			case MSG_SAVE_DPTR:
PR4("Msd");
				break;
			case MSG_RSTOR_DPTR:
PR4("Mrd");
				break;
			case MSG_ABORT:
PR4("Mab");
				break;
			case MSG_DEV_RESET:
PR4("Mdr");
				break;
			case MSG_IDENTIFY:
PR4("Mmi");
				break;
			case MSG_IDENT_DC:
PR4("Mmd");
				break;
			}
			break;
		case XP_MSG_OUT:
PR4("MO");
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.  Abort the bus cycle.
			 */
			sfbyte(ss_dat, MSG_NOP); 
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
			break;
		case XP_STAT_IN:
PR4("SI");
			ssp->cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 * Reset SCSI bus if too many command bytes are wanted.
			 */
			bytes_to_send = ssp->cmdlen - ssp->cmd_bytes_out;
			if(bytes_to_send > 0) {
				sfbyte(ss_dat, ssp->cmdbuf[ssp->cmd_bytes_out++]);
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (bytes_to_send == 1) {
PR4("CO");
					if (bp->b_req == BREAD) {
						if (irpts_masked) {
							spl(s);
							irpts_masked = 0;
						}
					}
				}
			} else {	/* This case should not happen. */
				xfer_good = 0;
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.
			 */
			if (block_done) {
				xfer_good = 0;
PR1("Data in overrun");
			} else if (bp->b_req != BREAD) {
				xfer_good = 0;
			} else {
#if 0
				int getbval;

				block_done=1;
PR4("DI");
				if(getbval = ss_getb(ss_dat,
				bp->b_faddr + xfer_count)) {
					xfer_good = 0;
#if (DEBUG >= 1)
printf("getb=%d ", getbval);
#endif
				}
#else
				block_done=1;
				ffcopy(ss_dat, bp->b_faddr + xfer_count, BSIZE);
#endif
			}
			break;
		case XP_DATA_OUT:
			/*
			 * Copy output buffer bytes to data register.
			 */
			if (block_done) {
				xfer_good = 0;
PR1("Data out overrun");
			} else if (bp->b_req != BWRITE) {
				xfer_good = 0;
			} else {
#if 0
				int putbval;
				block_done=1;
PR4("DO");
				if (putbval = ss_putb(ss_dat,
				bp->b_faddr + xfer_count)) {
					xfer_good = 0;
#if (DEBUG >= 1)
printf("putb=%d ", putbval);
#endif
				}
#else
				block_done=1;
				ffcopy(bp->b_faddr + xfer_count, ss_dat, BSIZE);
#endif
				if (irpts_masked) {
					spl(s);
					irpts_masked = 0;
				}
			}
			break;
		default:
			break;
		} /* endswitch */
	}
	if (irpts_masked)
		spl(s);

#if (DEBUG >= 1)
	switch(ssp->cmdstat) {
	case -1:
		if (msg_in != MSG_DISCONNECT)
			printf("CS-",ssp->cmdstat);
		break;
	case CS_GOOD:
		break;
	case CS_CHECK:
		printf("CSK",ssp->cmdstat);
		break;
	case CS_BUSY:
		printf("CSY",ssp->cmdstat);
		break;
	case CS_RESERVED:
	default:
		printf("CS%x",ssp->cmdstat);
	}
#endif

	return (bus_timeout) ? 0 : 1 ;
}

/*
 * req_wait()
 *
 * This routine is called at the start of each information transfer
 * phase and after the last such phase.
 *
 * It returns 1 if REQ is asserted on the SCSI bus, meaning another phase
 * may begin, and 0 otherwise.  A REQ signal will not be seen if the function
 * times out or if BUSY drops.  A value of 1 is written to the pointer argument
 * if timeout occurred, else 0 is written.
 */
static int req_wait(to_ptr)
int *to_ptr;
{
	int req_found;
	unsigned char status;
	ulong poll_ct;

	*to_ptr = 1;
	req_found = 0;
	for (poll_ct = 0L; poll_ct < max_req_poll; poll_ct++) {
		status = ffbyte(ss_csr);
		if (status & RS_REQUEST) {
			req_found = 1;
			*to_ptr = 0;
			break;
		} else if ((status & RS_BUSY) == 0) {
			*to_ptr = 0;
			break;
		}
	}

#if (DEBUG >= 1)
	if (*to_ptr) {
		printf("TX: s=%x ", status);
	}
#endif

	return req_found;
}

/*
 * req_sense()
 *
 * Request Sense for a device.  The main reason for doing this is to
 * clear a standing Command Status of Device Check.
 *
 * Full results are discarded.  Return 1 if Device returns No Sense or
 * or Unit Attention.  Else return 0.
 *
 */
static int req_sense(s_id)
int s_id;
{
	uchar sense_buf[SENSELEN];
	uchar cmdbuf[G0CMDLEN];
	int ret = 0;

	cmdbuf[0] = ScmdREQUESTSENSE;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = SENSELEN;
	cmdbuf[5] = 0;

#if (DEBUG >= 2)
{int i; for (i=0; i<SENSELEN; i++) sense_buf[i]=0;}
#endif

PR2("rqs:");
	if (!start_arb()) {
PR2("NO arb");
#if (DEBUG >= 2)
printf("status=%x ", ffbyte(ss_csr));
#endif
		goto rqs_done;
	}

	if (!host_ident(s_id, 0)) {
PR2("NO host ident");
#if (DEBUG >= 2)
printf("status=%x ", ffbyte(ss_csr));
#endif
		goto rqs_done;
	}

	if(!local_info_xfer(cmdbuf, G0CMDLEN, sense_buf, SENSELEN, NULL, 0)) {
PR2("NO local xfer");
		goto rqs_done;
	} else {
		/*
		 * Return 1 if drive responded with any of these sense keys:
		 *	0x00	No Sense
		 *	0x06	Unit Attention
		 *	0x0B	Aborted Command
		 * In any of the above cases, a retry will likely succeed
		 * without Buse Device Reset or SCSI Bus Reset.
		 */
		switch (sense_buf[2]) {
		case 0x00:
		case 0x06:
		case 0x0B:
			ret = 1;
			break;
		} /* endswitch */
	}

rqs_done:
#if (DEBUG >= 2)
{
	int i;

	for (i=0; i<SENSELEN;i++)
		printf("%x ", sense_buf[i]);
	printf("\n");
}
#endif
	return ret;
}

/*
 * inquiry()
 *
 * Inquiry command for a device.
 * Find out if device is direct access, removable, etc.
 *
 * Put result of inquiry into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int inquiry(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G0CMDLEN];

	cmdbuf[0] = ScmdINQUIRY;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = INQUIRYLEN;
	cmdbuf[5] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, buf, INQUIRYLEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * mode_sense()
 *
 * Mode Sense command for a device.
 * Use this to get disk parameters:
 *	number of cylinders
 *	number of heads
 *	number of sectors per track.
 *
 * Put result of mode sense into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int mode_sense(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G0CMDLEN];

	cmdbuf[0] = ScmdMODESENSE;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0x3F;
	cmdbuf[3] = 0;
	cmdbuf[4] = MODESENSELEN;
	cmdbuf[5] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, buf, MODESENSELEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * read_cap()
 *
 * Read Capacity command for a device.
 *
 * Return 1 if command succeeds, else 0.
 */
static int read_cap(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G1CMDLEN];

	cmdbuf[0] = ScmdREADCAPACITY;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = 0;
	cmdbuf[5] = 0;
	cmdbuf[6] = 0;
	cmdbuf[7] = 0;
	cmdbuf[8] = 0;
	cmdbuf[9] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G1CMDLEN, buf, READCAPLEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * bus_dev_reset()
 *
 * Send Bus Device Reset message to the given SCSI id.
 * Return 1 if host adapter was not busy and no obvious timeouts occurred,
 * else 0.
 */
static int bus_dev_reset(s_id)
{
	int bdr_ok = 1;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

PR1("BDR");
	if (bdr_ok) {
		/*
		 * Do ST0x arbitration.
		 *
		 * De-assert SCSI enable bit.
		 * Write my SCSI id to port.
		 * Start arbitration.
		 */
		sfbyte(ss_csr, WC_ENABLE_PRTY);
		sfbyte(ss_dat, host_id);
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ARBITRATE);

		/*
		 * SCSI spec says there is "no maximum" to the wait for
		 * arbitration complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			bdr_ok = 0;
		}
	}

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	if (bdr_ok) {
		sfbyte(ss_dat, host_id | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION);

		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
		sfbyte(ss_dat, MSG_DEV_RESET);
		if (!bus_wait((0xFF << 8) | 0))
			bdr_ok = 0;
	}

	return bdr_ok;
}

/*
 * chk_reconn()
 *
 * Check SELECT to see if any SCSI device has tried to reconnect to the host
 * adapter.  Called if there is an interrupt, and by the timer in case
 * we somehow lose an interrupt.
 *
 * Return -1 if no reselect detected, or the SCSI ID of the reselecting
 * target if there is one.
 */
static int chk_reconn()
{
	uchar csr, dat;
	int s_id = -1;

	csr = ffbyte(ss_csr);
	if (csr & (RS_SELECT | RS_I_O)) {
		dat = ffbyte(ss_dat);
		if ((dat & host_id) && (dat & NSDRIVE)) {
			dat &= ~host_id;
			s_id = 0;
			while (dat >>=1)
				s_id++;
		}
	}

	return s_id;
}

/*
 * ss_mach()
 *
 *	Gives a distinct state machine for each target device.
 */
void	ss_mach(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp;
	int s;

	do_sst_op = 1; /* plan to run this routine again in most cases */
	while (do_sst_op) {
		bp = ssp->bp;  /* nonpolled() below can change ssp->bp */
		switch (ssp->state) {
		/*
		 * Polling states execute whether ssp->waiting or not.
		 */
		case SST_POLL_ARBITN:
PR3("XPAR");
			if (ffbyte(ss_csr) & RS_ARBIT_COMPL) {
				ssp->waiting = 0;
				if (host_ident(s_id, 1))
					do_connect(s_id);
				else
					recover(s_id, RV_P_TIMEOUT);
			} else {
				if (ssp->expired) {
					ssp->expired = 0;
					recover(s_id, RV_A_TIMEOUT);
				} else
					do_sst_op = 0;
			}
			break;
		case SST_POLL_RESELECT:
PR3("XPRS");
			if (TGT_RSEL) {
				ssp->waiting = 0;
				if (host_claimed == -1)
					host_claimed = s_id;
				else if (host_claimed != s_id) {
#if (DEBUG >= 1)
	printf("%d->%d ", host_claimed, s_id);
#endif
				}
				if (rsel_handshake()) {
					do_connect(s_id);
				} else {
					recover(s_id, RV_P_TIMEOUT);
				}
			} else  { /* Reselect poll is negative */
				if (ssp->expired) {
					ssp->expired = 0;
					recover(s_id, RV_R_TIMEOUT);
				} else
					do_sst_op = 0;
			}
			break;
		case SST_POLL_BEGIN_IO:
PR3("XPBI");
			if (bp == NULL)
				ssp->state = SST_DEQUEUE;
			else {
				/*
				 * At this point a SCSI command is about to
				 * be initiated.  It may be a retry.
				 */
				if (host_claimed == -1 && BUS_FREE && BUS_FREE) {
					ssp->waiting = 0;
					init_pointers(s_id);
					if (start_arb()) {
						host_claimed = s_id;
						if (host_ident(s_id, 1)) {
							do_connect(s_id);
						} else {
							recover(s_id, RV_P_TIMEOUT);
						}
					} else {
	/*
	 * If arbitration does not succeed right away, it is usually
	 * because another drive is trying to reselect the host.
	 */
						set_timeout(s_id, DELAY_ARB);
					}
				} else { /* host busy or bus not free */
					int o_id;

					if ((o_id = chk_reconn()) != -1)
						defer(dummy_reconn, s_id);
					++ssp->avl_count;
					if (ssp->avl_count >= MAX_AVL_COUNT)
						recover(s_id, RV_BF_TIMEOUT);
					else
						set_timeout(s_id, DELAY_BSY);
				}
			}
			break;
		default:
			if (ssp->waiting)
				do_sst_op = 0;
			else {
				/*
				 * Nonpolling states execute only if no
				 * target timer is running.
				 */
				nonpolled(s_id);
			}
		} /* endswitch */
	} /* endwhile */
}

/*
 * nonpolled()
 *
 * Part of ss_mach() - handling of nonpolling states is taken out simply
 * for readability.
 */
static void nonpolled(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	struct	fdisk_s	*fdp;
	int partition;
	dev_t dev;

	switch (ssp->state) {
	case SST_BUS_DEV_RESET:
PR3("XBDR");
		if (bus_dev_reset(s_id)) {
			do_sst_op = 0;
			set_timeout(s_id, DELAY_BDR);
			ssp->state = SST_REQ_SENSE;
		} else
			recover(s_id, RV_P_TIMEOUT);
		break;
	case SST_DEQUEUE:
		if(bufq_rd_head(s_id) != NULL && !ssp->busy) {
PR3("XDQU");
			ssp->busy = 1;
			bp = bufq_rm_head(s_id);
			ssp->bp = bp;
			dev = bp->b_dev;
			partition = DEV_PARTN(dev);
			if (dev & SDEV)
				partition = WHOLE_DRIVE;
			fdp = ssp->parmp;
			if (partition != WHOLE_DRIVE)
				ssp->bno = fdp[partition].p_base + bp->b_bno;
			else
				ssp->bno = bp->b_bno;
			if (bp->b_req == BREAD)
				ssp->cmdbuf[0] = ScmdREADEXTENDED;
			else
				ssp->cmdbuf[0] = ScmdWRITEXTENDED;
			ssp->cmdbuf[1] = 0;
			ssp->cmdbuf[2] = ssp->bno >> 24;
			ssp->cmdbuf[3] = ssp->bno >> 16;
			ssp->cmdbuf[4] = ssp->bno >>  8;
			ssp->cmdbuf[5] = ssp->bno;
			ssp->cmdbuf[6] = 0;
			ssp->cmdbuf[7] = 0;
			ssp->cmdbuf[8] = 1;
			ssp->cmdbuf[9] = 0;
			ssp->cmdlen = G1CMDLEN;
			init_pointers(s_id);
			ssp->bdr_count = 0;
			ssp->bsy_count = 0;
			ssp->try_count = 0;
			ssp->state = SST_POLL_BEGIN_IO;
		} else /* queue is empty or ssp->busy */
			do_sst_op = 0;
		break;
	case SST_HIPRI_RESET:
	case SST_LOPRI_RESET:
PR1("XRST");
		/*
		 * SST_LOPRI_RESET is same as SST_HIPRI_RESET for now.
		 * Later, can implement a delay to allow other targets to
		 * finish pending operations.
		 */
		if (host_claimed == s_id || host_claimed == -1) {
			host_claimed = s_id;
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_SCSI_RESET); /* reset ON */
			ssp->state = SST_RESET_OFF;
			set_timeout(s_id, DELAY_RST);
PR1("+");
		} else
			set_timeout(s_id, DELAY_RST);
		break;
	case SST_REQ_SENSE:
PR1("XRQS");
		/*
		 * Come here at end of SCSI Bus reset (and at other times).
		 * If we have host claimed, release it.
		 */
		if (host_claimed == s_id)
			host_claimed = -1;
		if (req_sense(s_id))
			ssp->state = SST_POLL_BEGIN_IO;
		else
			recover(s_id, RV_P_TIMEOUT);
		break;
	case SST_RESET_OFF:
PR3("XRFF");
		sfbyte(ss_csr, WC_ENABLE_PRTY); /* reset OFF */
		ssp->state = SST_REQ_SENSE;
		set_timeout(s_id, DELAY_RST);
	} /* endswitch */
}

/*
 * start_arb()
 *
 * return 1 if host adapter returned Arbitration Complete within allotted
 * number of tries, else 0
 */
static int start_arb()
{
	int ret = 0;
	int poll_ct;

	sfbyte(ss_csr, WC_ENABLE_PRTY);
	sfbyte(ss_dat, host_id);
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ARBITRATE);

	/*
	 * SCSI spec says there is "no maximum" to the wait for arbitration
	 * complete.
	 */
	for (poll_ct = 0; poll_ct < HIPRI_RETRIES; poll_ct++) {
		if (ffbyte(ss_csr) & RS_ARBIT_COMPL) {
			ret = 1;
			break;
		} else if (chk_reconn() != -1) {
			sfbyte(ss_csr, WC_ENABLE_PRTY);
			break;
		}
	}
#if (DEBUG >= 1)
if (!ret)
	PR1("oSA");
#endif
	return ret;
}

/*
 * host_ident()
 *
 * This routine is the bridge in a SCSI bus cycle between Abitration
 * Complete and the Information Transfer phases.
 *
 * return 1 if everything went ok, 0 in case of timeout
 */
static int host_ident(s_id, disconnect)
int s_id;
int disconnect;
{
	int ret = 0;

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	sfbyte(ss_dat, host_id | (1 << s_id));	/* Write both SCSI id's */
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

	if (bus_wait(RS_BUSY << 8 | RS_BUSY)) {
		/*
		 * Assert ATTN so target expects incoming message byte.
		 */
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION);

		if (bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE))) {
			if (disconnect)
				sfbyte(ss_dat, MSG_IDENT_DC);
			else
				sfbyte(ss_dat, MSG_IDENTIFY);
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ENABLE_IRPT);
			ret = 1;
		} else {
PR1("oHI2");
		}
	} else {
PR1("oHI1");
	}
	return ret;
}

/*
 * rsel_handshake()
 *
 * After Reselect is detected, a couple steps are needed before entering
 * Information Transfer phases.  This routine does those steps.
 *
 * return 1 if ok, 0 in case of timeout.
 */
static int rsel_handshake()
{
	int ret = 0;

	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_BUSY);
	if (bus_wait(RS_SELECT << 8 | 0)) {
		sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
		ret = 1;
	}
	return ret;
}

/*
 * set_timeout()
 *
 * Start a timer so as not to wait forever in case something goes wrong while
 * waiting for an event.  Available delays are:
 *
 * 	DELAY_ARB -	wait for arbitration complete
 * 	DELAY_BDR -	allow settling time after Bus Device Reset
 * 	DELAY_BSY -	wait for not HOST_BUSY and bus free
 * 	DELAY_RES -	wait for reselect by target
 * 	DELAY_RST -	allow settling times when doing SCSI Bus Reset
 *
 * Second argument is number of clock ticks to wait until timer expiration.
 */
static void set_timeout(s_id, delay)
int s_id, delay;
{
	ss_type * ssp = ss[s_id];

	ssp->expired = 0;
	ssp->waiting = 1;
	do_sst_op =  0;
	timeout(&(ssp->tim), delay, stop_timeout, s_id);
}

/*
 * stop_timeout()
 *
 * Called on expiration of the timer for a given target.
 * Don't expire a timer if it's no longer active.
 */
static void stop_timeout(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];

	if (ssp->waiting) {
		ssp->expired = 1;
		ssp->waiting = 0;
	}
	ss_mach(s_id);
}

/*
 * init_pointers()
 *
 * Initialize command and data pointers when starting (or restarting)
 * a block i/o command.
 */
static void init_pointers(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

	ssp->cmdstat = -1;
	ssp->cmd_bytes_out = 0;
	ssp->avl_count = 0;
}

/*
 * recover()
 *
 * This routine is called directly or indirectly from ss_mach().  It
 * determines what to do when the interface fails to behave as desired.
 *
 * Arguments are the SCSI id of the target HDC and an error type.
 * Error types are:
 *
 * RV_A_TIMEOUT (arbitration timeout)
 * Host adapter takes too long to respond with arbitration complete.
 * 
 * RV_P_TIMEOUT (protocol timeout)
 * Timeout waiting for desired SCSI bus status while connected to a target.
 * 
 * RV_R_TIMEOUT (reconnect timeout)
 * Timeout after target disconnects, waiting for reconnect.
 * 
 * RV_BF_TIMEOUT (bus free timeout)
 * Waited too long for host not busy and BUS_FREE.
 * 
 * RV_CS_BUSY (target device busy)
 * Command status returned was Busy.
 * 
 * RV_CS_CHECK (target device check)
 * Command status returned was CHECK.
 * 
 * Whenever an error occurs, one of the above inputs, together with the SCSI id
 * of the target, is sent to the recovery process.  The recovery process in turn
 * programs the next state for the machine.
 */
static void recover(s_id, errtype)
int s_id;
RV_TYPE errtype;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

#if (DEBUG >= 1)
int foo;
if ((foo=chk_reconn()) != -1)
	printf("HONK%d ", foo);
#endif

	++ssp->try_count;
	if (ssp->try_count < MAX_TRY_COUNT) {

		switch (errtype) {

		case RV_CS_BUSY:
			++ssp->bsy_count;
			if (ssp->bsy_count < MAX_BSY_COUNT) {
				ssp->state = SST_POLL_BEGIN_IO;
				set_timeout(s_id, DELAY_BSY);
			} else
				ssp->state = SST_BUS_DEV_RESET;
			break;

		case RV_CS_CHECK:
			ssp->state = SST_REQ_SENSE;
			break;

		case RV_P_TIMEOUT:
			/* fall thru */
		case RV_R_TIMEOUT:
			++ssp->bdr_count;
			if (ssp->bdr_count < MAX_BDR_COUNT)
				ssp->state = SST_BUS_DEV_RESET;
			else
				ssp->state = SST_LOPRI_RESET;
			break;

		case RV_BF_TIMEOUT:
			/* fall thru */
		case RV_A_TIMEOUT:
			ssp->state = SST_HIPRI_RESET;
		}
	} else { /* try_count >= MAX_TRY_COUNT */
		if (bp) {
			bp->b_flag |= BFERR;
			printf("(%d,%d): ", major(bp->b_dev), minor(bp->b_dev));
			printf("%s error bno=%ld\n",
				(bp->b_req == BREAD) ? "read" : "write",
				bp->b_bno);
		}
		ss_finished(s_id);
	}
}

/*
 * ss_finished
 *
 * Release current i/o buffer to the O/S.
 */
static void ss_finished(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int go_again = 1;

	if (host_claimed == s_id)
		host_claimed = -1;
	ssp->busy = 0;
	if (bp) {
		if (!(bp->b_flag & BFERR))
			bp->b_resid -= BSIZE;
		if ((bp->b_flag & BFERR) || bp->b_resid == 0) {
			ssp->bp = NULL;
			bdone(bp);
			go_again = 0;
		}
	}
	if (go_again) {
		ssp->state = SST_POLL_BEGIN_IO;
		ssp->bdr_count = 0;
		ssp->bsy_count = 0;
		ssp->try_count = 0;

		ssp->bno++;
		ssp->cmdbuf[2] = ssp->bno >> 24;
		ssp->cmdbuf[3] = ssp->bno >> 16;
		ssp->cmdbuf[4] = ssp->bno >>  8;
		ssp->cmdbuf[5] = ssp->bno;
	} else {
		/*
		 * After processing a kernel i/o request, stop the
		 * state machine for the current id.  Then start
		 * this or some other machine which has a request
		 * pending.
		 */
		do_sst_op =  0;
		ssp->state = SST_DEQUEUE;
		next_req(s_id);
	}
}

/*
 * next_req()
 *
 * Given the SCSI id where an i/o request just completed, start handling
 * another i/o request - which may be for the same or other SCSI id.
 * For now, use round-robin scheduling.
 */
static void next_req(s_id)
int s_id;
{
	int next_id = s_id;

	while (1) {
		next_id++;
		if (next_id >= MAX_SCSI_ID)
			next_id = 0;
		if (ss[next_id]
		&& (ss[next_id]->state != SST_DEQUEUE || bufq_rd_head(next_id))) {
			defer(ss_mach, next_id);
			break;
		}
		if (next_id == s_id)
			break;
	}
}

/*
 * do_connect()
 *
 * This function is called when the host is successfully connected to
 * the target.  It invokes information transfer protocol and then sets
 * up some sort of recovery unless the command completed successfully
 * or there was a normal disconnect.
 */
static void do_connect(s_id)
int s_id;
{
	int result;
	ss_type * ssp = ss[s_id];

	result = far_info_xfer(s_id);
	if (!result)
		recover(s_id, RV_P_TIMEOUT);
	else if (ssp->msg_in == MSG_DISCONNECT) {
		ssp->state = SST_POLL_RESELECT;
		set_timeout(s_id, DELAY_RES);
#if 0
		if (host_claimed == s_id)
			host_claimed = -1;
#endif
	} else if (ssp->msg_in == MSG_CMD_CMPLT && ssp->cmdstat == CS_GOOD)
		ss_finished(s_id);
	else if (ssp->cmdstat == CS_BUSY)
		recover(s_id, RV_CS_BUSY);
	else if (ssp->cmdstat == CS_CHECK)
		recover(s_id, RV_CS_CHECK);
	else  /* something else went wrong */
		recover(s_id, RV_P_TIMEOUT);
}

/*
 * local_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * Transfer is for a command which will produce local results in the driver.
 * Other ...info_xfer routine handles kernel block i/o commands.
 *
 * Return 1 if transfer succeeded, else 0.
 *
 */
static int local_info_xfer(cmdbuf, cmdlen, inbuf, inlen, outbuf, outlen)
uchar * cmdbuf, * inbuf, * outbuf;
uint cmdlen, inlen, outlen;
{
	int bus_timeout;
	uchar phase_type;
	int s;
	int cmd_bytes_out = 0;
	int data_bytes_in = 0;
	int data_bytes_out = 0;
	int ret = 0;
	int xfer_good = 1;
	int cmdstat = -1;
	int msg_in = -1;
#if (DEBUG >= 1)
int x, xct=0;
uchar xch[100];
#endif

	s = sphi();
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
#if (DEBUG >= 1)
if (xct < 100)
	xch[xct++]=phase_type;
#endif
		switch (xpmod(phase_type)) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
			case MSG_DISCONNECT:
				sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_IRPT);
				break;
			}
			break;
		case XP_MSG_OUT:
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.
			 */
			sfbyte(ss_dat, MSG_NOP); 
			sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
			break;
		case XP_STAT_IN:
			cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 */
			if (cmd_bytes_out < cmdlen) {
				sfbyte(ss_dat, cmdbuf[cmd_bytes_out++]);
#if 1
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (cmd_bytes_out == cmdlen) {
					spl(s);
					s = sphi();
				}
#endif
			} else {	/* This case should not happen. */
				xfer_good = 0;
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.  Else toss it.
			 */
			if (data_bytes_in < inlen) {
#if 0
				do {
					inbuf[data_bytes_in++] = ffbyte(ss_dat);
				} while (data_bytes_in < inlen);
#else
				inbuf[data_bytes_in++] = ffbyte(ss_dat);
#endif
			} else
				xfer_good = 0;
			break;
		case XP_DATA_OUT:
			/*
			 * Copy output buffer bytes to data register.
			 */
			if (data_bytes_out < outlen) {
				sfbyte(outbuf[data_bytes_out++], ss_dat);
			} else { /* This case should not happen. */
				xfer_good = 0;
			}
			break;
		default:
			break;
		} /* endswitch */
	}
	spl(s);

	if (bus_timeout) {
PR1("oLX1");
	} else if (!xfer_good) {
PR1("oLX2");
	} else if (cmdstat != CS_GOOD) {
PR1("oLX3");
#if (DEBUG >= 1)
printf("cmdstat=%x ", cmdstat);
#endif
	} else
		ret = 1;
#if (DEBUG >= 1)
if (!ret) {
	printf("csr=%x ", ffbyte(ss_csr));
	printf("xct=%d  ", xct);
	for (x=0; x < xct; x++)
		printf("%x ", xch[x]);
}
#endif

	return ret;
}

/*
 * scsireset()
 *
 * Reset the SCSI bus.
 * Allow settling time when turning reset on/off.
 * Settling times were determined empirically.
 * Each tick is 10 msec.
 */
static void scsireset()
{
#if (DEBUG >= 1)
printf("scsireset ");
#endif
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_SCSI_RESET);
	ssdelay(RESET_TICKS);
	sfbyte(ss_csr, WC_ENABLE_PRTY);
	ssdelay(RESET_TICKS);
}

/*
 * ssdelay()
 *
 * Delay for some number of arbitrary ticks.
 *
 * Using sleep() causes a panic if this driver is linked to the kernel,
 * even though this routine is called only via ssload().
 */
static void ssdelay(ticks)
int ticks;
{
#if 0
	timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
#else
	int i, j;

	for (i = 0; i < ticks; i++)
		for (j = 0; j < LOAD_DELAY; j++);
#endif
}

/*
 * init_call()
 *
 * Call SCSI command function during initialization, with error recovery.
 * If the simple command fails, try a Bus Device Reset, then SCSI Bus reset.
 */
static int init_call(fn, s_id, buf)
int (*fn)();
int s_id;
uchar * buf;
{
	int ret = 1;
	int i;
	int o_id;
int s;
s=sphi();
	for (i = 0; i < 2; i++) {
		o_id = chk_reconn();
		if (o_id != -1)
			dummy_reconn(s_id);
		if ((*fn)(s_id, buf))
			goto init_call_done;

		if (bus_dev_reset(s_id)) {
			ssdelay(RESET_TICKS);
			req_sense(s_id);
			if ((*fn)(s_id, buf))
				goto init_call_done;
		}

		scsireset();
		req_sense(s_id);
		if ((*fn)(s_id, buf))
			goto init_call_done;
	}

	ret = 0;

init_call_done:
spl(s);
	return ret;
}

/*
 * xpmod()
 *
 * Command/Data and Message bits are swapped on-board (outside the chip)
 * on older Future Domain host boards.
 */
static uchar xpmod(oldphase)
uchar oldphase;
{
	uchar ret = oldphase;

	if (swap_status_bits) {
		ret &= ~(RS_CTRL_DATA | RS_MESSAGE);
		if (oldphase & RS_MESSAGE)
			ret |= RS_CTRL_DATA;
		if (oldphase & RS_CTRL_DATA)
			ret |= RS_MESSAGE;
	}
	return ret;
} 
@


2.15
log
@update provided by hal
@
text
@d53 1
a53 1
#include	<coherent.h>
a61 1

d65 1
a65 1
#include	<scsiwork.h>
@


2.14
log
@new version provided y hal for v321
@
text
@@


2.13
log
@initial version prov by hal
@
text
@d11 2
a12 3
 * Revision 2.12  91/05/31  13:18:39  hal
 * Force parity on as Conner drives act dead without it.
 * Slow down data in phase in local_info_xfer() for 486 + Conner.
d14 2
a15 2
 * Revision 2.11  91/05/30  15:43:17  hal
 * Add SS_DELAY and slow down delays for 486.
a16 2
 * Revision 2.10  91/05/29  11:14:24  hal
 * Send MSG_NOP's for slow machines.  More debug output.
a17 27
 * Revision 2.9  91/05/22  01:38:55  hal
 * Overlapping disconnects give bad reads.
 * 
 * Revision 2.8  91/05/21  23:13:15  hal
 * Round robin scheduler.  HDSETA.  Bump MAX_AVL_COUNT.
 * 
 * Revision 2.7  91/05/21  19:10:43  hal
 * Balance host_claimed - needs debugging.
 * 
 * Revision 2.6  91/05/21  13:53:22  root
 * Patch NSDRIVE for Future Domain.  Call per/id queue fns.
 * 
 * Revision 2.5  91/05/20  18:02:52  root
 * Remove test code.
 * 
 * Revision 2.4	91/05/20  17:22:06	root
 * Not using ss_put() any more.
 * 
 * Revision 2.3	91/05/20  16:20:33	root
 * Call to ss_putc() now works.
 * 
 * Revision 2.2	91/05/20  10:23:58	root
 * Modify ss_get/ss_put calls for Future Domain & drop 3rd arg.
 * 
 * Revision 2.1	91/05/17  14:26:12	root
 * Debug level up to 4 tracking write problem.
 * 
a107 1

d118 1
d123 1
a123 1
	&& (ffbyte(ss_dat) & (SS_HOST   | (1<<s_id) )) )
d135 2
d249 1
d275 5
a279 4
 * Two test drives in use:
 *
 * ST1126N, SCSI 0  LUN 0  (Unit 0)
 * ST1201N, SCSI 1  LUN 0  (Unit 1)
d281 3
a283 6
int	NSDRIVE = 0x0000;	/* Bitmap of attached SCSI drives. */
				/* Set NSDRIVE highest bit for Future Domain */
int	SS_INT = 5;		/* ST0[12] use either IRQ3 or IRQ5 */
int	SS_BASE = 0xDE00;	/* Segment addr of ST0x communication area */
int	SS_DELAY = 10000;	/* Loop counter during ssload() only */
int	SS_HOST = 0x80;		/* Host is SCSI ID #7 for Seagate, 6 for FD */
d286 1
a286 5
drv_parm_type drv_parm[MAX_SCSI_ID-1] = {
#if 0
	{ 987, 20, 17},		/* Unit 0 */
	{ 1004, 4, 52},		/* Unit 1 */
#endif
d308 5
d314 1
a314 1
static ss_type  *ss[MAX_SCSI_ID-1];
a352 8
	if (NSDRIVE & 0x8000) { /* Future Domain */
		ss_csr = ss_fp + FD_CSR;
		ss_dat = ss_fp + FD_DAT;
	} else { /* Seagate */
		ss_csr = ss_fp + SS_CSR;
		ss_dat = ss_fp + SS_DAT;
	}

d364 1
a364 1
		printf("Error - ST0x failed memory test\n");
d369 23
d400 1
a400 1
		for (i = 0; i < MAX_SCSI_ID -1; i++)
d418 1
a418 1
		for (i = 0; i < MAX_SCSI_ID -1; i++)
d433 1
d435 1
a435 1
		for (i = 0; i < MAX_SCSI_ID -1; i++)
d439 1
a477 1
	int valid_open;
d481 1
a485 1
	valid_open = 1;
d501 1
a501 1
PR1("bad LUN or SCSI id");
d503 1
a503 1
		valid_open = 0;
d509 2
a510 2
	if (valid_open && DEV_SPECIAL(dev) && partn != 0) {
PR1("bad special partition");
d512 1
a512 1
		valid_open = 0;
d518 1
a518 1
	if (valid_open && dev & SDEV)
d520 1
d527 1
a527 1
	if (valid_open && partn != WHOLE_DRIVE && !(ssp->ptab_read)) {
d546 1
a546 1
			valid_open = 0;
d554 1
a554 1
PR1("bad partition table");
d556 1
a556 1
			valid_open = 0;
d565 1
a565 1
	if (valid_open && partn != WHOLE_DRIVE
d567 1
a567 1
PR1("partition overrun");
d569 1
a569 1
		valid_open = 0;
d572 2
a573 2
	if (valid_open && partn != WHOLE_DRIVE && fdp[partn].p_size == 0) {
PR1("partition not found");
d575 1
a575 1
		valid_open = 0;
d582 8
a589 4
	if (valid_open) {
		++drvl[SCSI_MAJOR].d_time;
		++ssp->dr_watch;
	}
d754 1
a754 1
				goto bad_open;
d759 1
a759 1
			goto bad_open;
d768 1
a768 1
		goto bad_open;
d778 1
a778 1
		goto bad_open;
d787 1
a787 1
		goto bad_open;
d796 1
a796 1
	goto end_open;
d802 1
a802 1
bad_open:
d807 1
a807 1
end_open:
d861 1
a861 1
		switch (phase_type) {
d906 1
a906 1
	for (s_id = 0; s_id < MAX_SCSI_ID-1; s_id++) {
d1080 1
a1080 1
		switch (phase_type) {
d1255 1
a1255 1
	int req_found, i;
d1257 1
d1261 1
a1261 1
	for (i = 0; i < HIPRI_RETRIES; i++) {
d1478 1
a1478 1
		sfbyte(ss_dat, SS_HOST);
d1494 1
a1494 1
		sfbyte(ss_dat, SS_HOST | (1 << s_id));	/* Write both SCSI id's */
d1537 2
a1538 2
		if ((dat & SS_HOST) && (dat & NSDRIVE)) {
			dat &= ~SS_HOST;
d1768 2
a1769 1
	int ret;
d1772 1
a1772 1
	sfbyte(ss_dat, SS_HOST);
d1779 8
a1786 5
	if (bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL))
		ret = 1;
	else {
		ret = 0;
PR1("oSA");
d1788 5
d1812 1
a1812 1
	sfbyte(ss_dat, SS_HOST | (1 << s_id));	/* Write both SCSI id's */
d2069 1
a2069 1
		if (next_id >= MAX_SCSI_ID - 1)
d2151 1
a2151 1
		switch (phase_type) {
d2268 1
a2268 2
 * Delay for some number of clock ticks.
 * 286/386 kernel ticks are at 100Hz
d2270 2
a2271 2
 * WARNING:  Since this routine uses sleep(), it is callable ONLY from
 * ssload()/ssunload()/ssopen()/ssclose().
d2283 1
a2283 1
		for (j = 0; j < SS_DELAY; j++);
d2329 21
@


2.12
log
@Force parity on as Conner drives act dead without it.
Slow down data in phase in local_info_xfer() for 486 + Conner.
@
text
@d11 4
a144 1
#define HOST_ID		0x80	/* Host adapter is SCSI ID #7 */
d153 1
a153 1
	&& (ffbyte(ss_dat) & (HOST_ID   | (1<<s_id) )) )
d162 3
a164 3
#define MAX_BDR_COUNT	2
#define MAX_BSY_COUNT	2
#define MAX_TRY_COUNT	7
d312 1
d1017 5
d1026 5
a1031 5
#if (DEBUG >= 1)
			printf("Physical: %d sectors per track  ", spt);
			printf("%ld cylinders  ", cyls);
			printf("%d heads\n\n", heads);
#endif
d1169 3
a1172 1
				ss_get(ss_dat, bp->b_faddr + xfer_count);
d1174 11
d1197 2
a1199 1
				ss_get(bp->b_faddr + xfer_count, ss_dat);
d1201 11
d1337 12
a1348 1
		if (sense_buf[2] == 0x00)	/* No Sense.  AOK */
d1350 2
a1351 2
		else if (sense_buf[2] == 0x06 && sense_buf[12] == 0x29)
			ret = 1;
a1358 1
	printf("rqs: ");
d1484 1
a1484 1
		sfbyte(ss_dat, HOST_ID);
d1500 1
a1500 1
		sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
d1543 2
a1544 2
		if ((dat & HOST_ID) && (dat & NSDRIVE)) {
			dat &= ~HOST_ID;
d1777 1
a1777 1
	sfbyte(ss_dat, HOST_ID);
d1809 1
a1809 1
	sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
d1995 4
a1998 1
PR1("BF4 ");
@


2.11
log
@Add SS_DELAY and slow down delays for 486.
@
text
@d11 3
d870 1
a870 1
				sfbyte(ss_csr, WC_ENABLE_IRPT);
d876 1
a876 1
			sfbyte(ss_csr, WC_ENABLE_SCSI);
d1085 1
a1085 1
				sfbyte(ss_csr, WC_ENABLE_IRPT);
d1090 1
a1090 1
				sfbyte(ss_csr, WC_ENABLE_IRPT);
d1119 1
a1119 1
			sfbyte(ss_csr, WC_ENABLE_SCSI);
d1434 4
d1439 3
a1441 3
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */
d1457 1
a1457 1
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);
d1464 1
a1464 1
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);
d1472 1
a1472 1
		sfbyte(ss_csr, WC_ENABLE_SCSI);
d1694 1
a1694 1
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET); /* reset ON */
d1716 1
a1716 1
		sfbyte(ss_csr, 0); /* reset OFF */
d1732 3
a1734 3
	sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
	sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
	sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */
d1766 1
a1766 1
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);
d1772 1
a1772 1
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);
d1780 1
a1780 1
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ENABLE_IRPT);
d1803 1
a1803 1
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
d1805 1
a1805 1
		sfbyte(ss_csr, WC_ENABLE_SCSI);
d2107 1
a2107 1
				sfbyte(ss_csr, WC_ENABLE_IRPT);
d2117 1
a2117 1
			sfbyte(ss_csr, WC_ENABLE_SCSI);
d2147 1
d2151 3
d2209 1
a2209 1
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
d2211 1
a2211 1
	sfbyte(ss_csr, 0);
@


2.10
log
@Send MSG_NOP's for slow machines.  More debug output.
@
text
@d11 3
d305 1
d752 1
a752 1
				msg = "invlaid request";
d1275 25
a1299 2
	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, sense_buf, SENSELEN, NULL, 0)) {
d1306 11
d2223 1
a2223 1
		for (j = 0; j < 4000; j++);
@


2.9
log
@Overlapping disconnects give bad reads.
@
text
@a4 1
 *	make ssinit() more rugged
d6 3
d11 3
d49 1
d246 1
d296 1
a296 1
 * CP340,   SCSI 3  LUN 0  (Unit 3)
d298 1
a298 1
int	NSDRIVE = 0x8003;	/* Bitmap of attached SCSI drives. */
d305 1
d308 1
a309 1
	{ 964, 5, 17},		/* Unit 3 */
d312 3
a361 1

d363 1
a363 1
	 * Claim IRQ vector.
a364 5
	setivec(SS_INT, ssintr);

	/*
	 * Allocate a selector to map into ST0x memory-mapped comm area.
	 */
d426 5
d502 1
d511 1
d554 1
d567 1
d573 1
a648 3
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
a649 1

d722 1
d748 1
a748 1
PR1("BF1");
d753 1
a753 2
PR1("BF2");
			devmsg(dev, "no partition table");
d772 1
a772 1
PR1("BF3");
d781 1
d799 3
a801 1
		bdone(bp);
d820 4
a823 1
		defer(ss_mach, s_id);
d829 63
d960 1
a960 39
/* FOO */
int foo, junk, phase_type;
	if ((foo=chk_reconn()) != -1) {
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY | WC_ATTENTION);
		if (bus_wait(RS_SELECT << 8 | 0)) {
			sfbyte(ss_csr, WC_ENABLE_SCSI);
			if (req_wait(&junk)) {
phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
printf("phase type=%d\n", phase_type);
if (phase_type == XP_MSG_IN) {
	junk = ffbyte(ss_dat);
	printf("msg in=%x\n", junk);
	req_wait(&junk);
	phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
}
if (phase_type == XP_MSG_OUT) {
	sfbyte(ss_dat, MSG_ABORT);
	printf("MSG_ABORT sent\n");
	if (!req_wait(&junk))
		printf("req_wait failed\n");
	phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
}
if (phase_type == XP_DATA_IN) {
	junk = ffbyte(ss_dat);
	printf("data_in=%x\n", junk);
	if (!req_wait(&junk))
		printf("req_wait failed\n");
	phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
}
junk = ffbyte(ss_csr);
printf("status=%x\n", junk);
			} else
printf("req_wait failed\n");
		} else {
			printf("rsel_handshake failed\n");
		}
		printf("** id %d tried to reselect **\n", foo);
	}
/* FOO */
d983 3
a985 3
#if (DEBUG >= 3)
printf("capacity=%ld   block length=%ld\n", ssp->capacity, ssp->blocklen);
#endif
d991 3
a993 1
#if (DEBUG >= 3)
d996 3
d1000 15
a1014 10
uchar heads;
unsigned short spt;
ulong cyls;

spt=((int)query_buf[FMT_PG+10]<<8) + query_buf[FMT_PG+11];
cyls=((int)query_buf[DDG_PG+2]<<16) + ((int)query_buf[DDG_PG+3]<<8) + query_buf[DDG_PG+4];
heads=query_buf[DDG_PG+5];
printf("%d sectors per track\n", spt);
printf("%ld cylinders\n", cyls);
printf("%d heads\n", heads);
d1111 1
a1112 1
			sfbyte(ss_dat, MSG_ABORT); 
a1142 1
PR4("DI");
d1147 7
a1153 4
if (block_done)
printf("Data in overrun ");
block_done=1;
			if (bp->b_req == BREAD)
d1155 2
a1156 2
			else
				xfer_good = 0;
d1162 8
a1169 3
			if (bp->b_req == BWRITE) {
#if 1
				int res=0;
a1170 5
if (block_done)
	printf("Data out overrun ");
block_done=1;
/*				res=ss_put(ss_dat, bp->b_faddr + xfer_count);*/
				ss_get(bp->b_faddr + xfer_count, ss_dat);
d1175 1
a1175 11
#if (DEBUG >= 3)
				printf("p%d ", res);
#else
#if (DEBUG >= 1)
				if(res!=0)
					printf("p%d ", res);
#endif
#endif
#endif
			} else /* This case should not happen. */
				xfer_good = 0;
d1183 1
d1185 17
a1201 16
switch(ssp->cmdstat) {
case -1:
	if (msg_in != MSG_DISCONNECT)
		printf("CS-",ssp->cmdstat);
	break;
case CS_GOOD:
	break;
case CS_CHECK:
	printf("CSK",ssp->cmdstat);
	break;
case CS_BUSY:
	printf("CSY",ssp->cmdstat);
	break;
case CS_RESERVED:
default:
	printf("CS%x",ssp->cmdstat);
d1203 2
a1205 2
	return (bus_timeout) ? 0 : 1 ;
}
a1547 1
/*						ssp->state = SST_POLL_ARBITN;*/
d1551 4
d1685 2
d1695 6
a1700 1
	return bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL);
d1737 2
d1740 2
d2044 4
d2052 4
d2069 1
a2069 1
			 * asserting ATTENTION.  Abort the bus cycle.
d2071 1
a2072 1
			sfbyte(ss_dat, MSG_ABORT); 
d2083 1
d2091 1
d2102 3
a2104 1
				inbuf[data_bytes_in++] = ffbyte(ss_dat);
d2106 1
a2106 1
				ffbyte(ss_dat);
d2124 10
a2133 1
	if (!bus_timeout && xfer_good && cmdstat == CS_GOOD)
d2135 8
d2178 1
d2181 6
d2202 3
a2204 1

d2206 3
d2228 1
@


2.8
log
@Round robin scheduler.  HDSETA.  Bump MAX_AVL_COUNT.
@
text
@d9 3
d142 2
a143 2
#define DELAY_BSY	10
#define DELAY_RES	40
d883 1
a883 1
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
d885 1
a885 1
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);
a893 1
	printf("phase type=%d\n", phase_type);
d898 3
a900 3
	ssdelay(30);
	junk = ffbyte(ss_csr);
	printf("status=%x\n", junk);
d902 9
d1456 1
a1456 2
			if ((host_claimed == -1 || host_claimed == s_id)
			&& TGT_RSEL) {
d1458 7
a1464 1
				host_claimed = s_id;
a1487 1
					host_claimed = s_id;
d1491 1
d1498 5
a1502 1
						ssp->state = SST_POLL_ARBITN;
d1603 1
d1804 6
d1916 2
a1917 1
		if (ss[next_id] && bufq_rd_head(next_id)) {
d1946 1
a1946 1
#if 1
@


2.7
log
@Balance host_claimed - needs debugging.
@
text
@a4 1
 *	set host_claimed conscientiously
d9 3
d41 1
a41 1
#define PR1(str)		printf(str)
d51 1
a51 1
#define PR3(str)		printf(str)
d56 1
a56 1
#define PR4(str)		printf(str)
d143 1
a143 1
#define MAX_AVL_COUNT	10
d239 1
d244 1
d288 1
a288 1
int	NSDRIVE = 0x8001;	/* Bitmap of attached SCSI drives. */
d295 1
a295 1
	{ 1068, 9, 36},		/* Unit 0 */
d331 1
a331 1
 *	disconnect
d653 4
a656 1
PR3("HDGETA ");
d666 1
a666 1
		kucopy( &hdparm, vec, sizeof hdparm );
d669 16
d733 1
a733 1
PR1("BF1 ");
d738 1
a738 1
PR2("BF2 ");
d758 1
a758 1
PR3("BF3 ");
d877 31
d909 1
a909 1
		if (inquiry(s_id, query_buf)) {
d922 1
a922 1
		if (read_cap(s_id, query_buf)) {
d937 1
a937 1
		if (mode_sense(s_id, query_buf)) {
a1009 1
PR4("MI");
d1013 1
a1013 1
PR4("cc ");
d1018 1
a1018 1
PR4("dc ");
d1023 1
a1023 1
PR4("sd ");
d1026 1
a1026 1
PR4("rd ");
d1029 1
a1029 1
PR4("ab ");
d1032 1
a1032 1
PR4("dr ");
d1035 1
a1035 1
PR4("mi ");
d1038 1
a1038 1
PR4("md ");
d1043 1
a1043 1
PR4("MO ");
d1052 1
a1052 1
PR4("SI ");
d1067 1
a1067 1
PR4("CO ");
d1080 1
a1080 1
PR4("DI ");
d1100 1
a1100 1
PR4("DO ");
a1117 10
#else
				uchar dat;
if (i==0)
	PR4("DO");
/***FOOO***/
				dat = ffbyte(bp->b_faddr + xfer_count + i);
				sfbyte(ss_dat, dat);
				i++;
if (i==BSIZE)
	PR4("n ");
d1332 1
a1332 2
PR1("bdr");

d1428 1
a1428 1
PR3("PA ");
d1444 1
a1444 1
PR3("PR ");
d1463 1
a1463 1
PR3("PBI ");
d1525 1
a1525 1
PR3("BDR ");
d1535 1
a1535 1
PR3("DQ ");
d1572 1
a1572 1
PR1("rst");
d1578 7
a1584 4
		host_claimed = s_id;
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET); /* reset ON */
		ssp->state = SST_RESET_OFF;
		set_timeout(s_id, DELAY_RST);
d1587 1
a1587 1
PR1("RQS ");
d1600 1
a1600 1
PR3("RFF ");
d1860 8
a1867 1
	} else
d1869 2
d1874 25
d1918 1
d1921 1
d2040 3
d2064 37
@


2.6
log
@Patch NSDRIVE for Future Domain.  Call per/id queue fns.
@
text
@d6 2
a8 3
 *	backoff & retry when bdr or req sense needed
 *	nonzero LUN's
 *
d10 3
d34 3
a36 2
 * DEBUG = 2	Debug output on error only and at other selected places.
 * DEBUG = 3	Maximum debug output.
a58 7
#if 0
/* TEMPORARY S**T */
#define bufq_rd_head(s_id)	ssq_rd_head()
#define bufq_rm_head(s_id)	ssq_rm_head()
#define bufq_wr_tail(s_id, foo)	ssq_wr_tail(foo)
#endif

d125 1
a125 1
#define HIPRI_RETRIES	4000	/* # of times to retry while hogging CPU */
d128 1
d246 1
d308 1
a308 2
static int	num_drives;	/* number of controller SCSI id's */

a309 1
static int	host_claimed;	/* -1 or SCSI id of target using the host */
d316 16
d342 1
d344 1
d1401 19
a1451 17
		case SST_POLL_RESELECT:
PR3("PR ");
			if (TGT_RSEL) {
				ssp->waiting = 0;
				if (rsel_handshake()) {
					do_connect(s_id);
				} else {
					recover(s_id, RV_P_TIMEOUT);
				}
			} else  { /* Reselect poll is negative */
				if (ssp->expired) {
					ssp->expired = 0;
					recover(s_id, RV_R_TIMEOUT);
				} else
					do_sst_op = 0;
			}
			break;
d1536 1
d1543 6
a1766 1
			host_claimed = -1;
d1823 3
a1825 1
 * the target.
a1833 2
	if (host_claimed == s_id)
		host_claimed = -1;
d1839 2
a1945 1
	host_claimed = -1;
d1948 32
@


2.5
log
@Remove test code.
@
text
@a0 1
#define FUT_DOM 0
a5 1
 *	works but hogs CPU during big dd to /dev/null
a6 4
 *	bufq_rd_head()
 *	bufq_rm_head()
 *	bufq_wr_tail()
 *
a8 1
 *	assembler I/O
d10 4
a13 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d56 1
d61 1
d91 5
a95 4
#if FUT_DOM
#define SS_CSR		0x1C00	/* Offset of control/status register */
#define SS_DAT		0x1E00	/* Offset of data port */
#else
a97 1
#endif
d211 6
a216 4
/* functions from ssqueue.c */
extern void ssq_wr_tail();
extern BUF * ssq_rd_head();
extern BUF * ssq_rm_head();
d286 2
a287 1
int	NSDRIVE = 1;		/* Bitmap of attached SCSI drives. */
d293 2
a294 1
	{ 1004, 4, 52},		/* Unit 0 */
d296 1
a297 2
	{ 964, 5, 17},		/* Unit 3 */
	{ 0, 0, 0},
d329 1
a342 2
	ss_csr = ss_fp + SS_CSR;
	ss_dat = ss_fp + SS_DAT;
d344 8
d377 2
a378 1
			if ((NSDRIVE >> i) & 1)
d380 1
d403 1
d421 1
@


2.4
log
@Not using ss_put() any more.
@
text
@a0 1
static int rwhi;
d18 3
a916 1
uchar lphase=0xff;
a920 4
#if (DEBUG >= 2)
	rwhi=0;
#endif

a923 7
#if (DEBUG >= 2)
if (rwhi) {
	rwhi=0;
	printf("lp=%x cp=%x\n", (int)lphase, (int)phase_type);
}
lphase=phase_type;
#endif
d1118 1
a1118 4
#if (DEBUG >= 2)
if (i>100) {
	printf("rw=%d ", i);
	rwhi=i;
a1119 1
#endif
a1120 3
	return req_found;
}

a1387 1
/*					s=sphi();*/
a1390 1
/*							spl(s);*/
a1391 1
/*							spl(s);*/
a1394 1
/*						spl(s);*/
a1410 1
/*				s=sphi();*/
a1412 1
/*					spl(s);*/
a1413 1
/*					spl(s);*/
@


2.3
log
@Call to ss_putc() now works.
@
text
@d1 1
d19 3
d317 1
a318 30
 * ss_putC()
 *
 * return # of bytes remaining to be sent from current block
 * - should be 0
 *
 * temporary C code
 */
int ss_putC(ss_dat_fp, buf_fp)
faddr_t ss_dat_fp, buf_fp;
{
	uchar dat;
	int i, junk;
#if 0
	faddr_t req_waitA();
	printf("ss_stat=%x ", ffbyte(ss_csr));
	printf("ss_datA=%lx ", req_waitA(ss_dat_fp, buf_fp));
#endif
	for (i = 0; i < BSIZE; i++) {
/*		if (!req_wait(&junk)) */
		if (!req_waitA(ss_dat_fp, buf_fp))
			break;
		dat = ffbyte(buf_fp + i);
		sfbyte(ss_dat_fp, dat);
	}
	return BSIZE - i;
}

/*
 * ssload()	- load routine.
 *
d915 1
a915 1
int i=0;
a918 2
	s = sphi();
	irpts_masked = 1;
d920 5
d927 11
d1000 4
a1003 2
						spl(s);
						s = sphi();
d1030 1
a1030 1
				int res;
d1035 2
a1036 1
				res=ss_put(ss_dat, bp->b_faddr + xfer_count);
d1129 1
a1129 1
if (i>100)
d1131 2
d1405 1
a1405 1
					s=sphi();
d1409 1
a1409 1
							spl(s);
d1411 1
a1411 1
							spl(s);
d1415 1
a1415 1
						spl(s);
d1432 1
a1432 1
				s=sphi();
d1435 1
a1435 1
					spl(s);
d1437 1
a1437 1
					spl(s);
@


2.2
log
@Modify ss_get/ss_put calls for Future Domain & drop 3rd arg.
@
text
@d18 3
d125 1
a125 1
#define HIPRI_RETRIES	400	/* # of times to retry while hogging CPU */
d313 29
d938 1
d945 2
d1038 1
a1038 1
#if 0
d1045 4
d1075 2
a1076 1
	spl(s);
d1136 5
@


2.1
log
@Debug level up to 4 tracking write problem.
@
text
@d1 1
d17 4
a20 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d83 5
d90 1
d271 6
d281 1
a281 4
#define NCYL	1004
#define NHEAD	4
#define NSPT	52

d283 1
a283 1
	{ NCYL, NHEAD, NSPT},
d286 1
a288 1
	{ 0, 0, 0},
d994 1
a994 1
				ss_get(ss_fp, bp->b_faddr + xfer_count, BSIZE);
a998 1
PR4("DO ");
d1003 1
a1003 1
#if 1
d1005 1
d1009 1
a1009 1
				res=ss_put(ss_fp, bp->b_faddr + xfer_count, BSIZE);
d1020 3
a1022 1

d1026 2
@
0707070064030104211004440000030000030000011777770507310655400005600000022727/newbits/kernel/USRSRC/i8086/drv/RCS/ss.fsa,vhead     1.4;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.4
date     91.04.26.15.40.25;  author root;  state Exp;
branches ;
next	1.3;

1.3
date     91.04.25.17.12.33;  author root;  state Exp;
branches ;
next	1.2;

1.2
date     91.04.24.10.28.04;  author root;  state Exp;
branches ;
next	1.1;

1.1
date     91.04.23.17.32.53;  author root;  state Exp;
branches ;
next	;


desc
@Text specification for Seagate SCSI state machine.
@


1.4
log
@Use ss.std 1.2.  Need to spell out reset recovery.
@
text
@$Log: updateprovbyha,v $
@Revision 1.1.1.1  2019/05/29 04:56:34  root
@coherent
@
 * Revision 1.3	91/04/25  17:12:33	root
 * Clarify, with aid of ss.std rev.1.
 * 
 * Revision 1.2	91/04/24  10:28:04	root
 * Case 1.a. completed.
 * 
 * Revision 1.1	91/04/23  17:32:53	root
 * Unfinished draft.
 * 

State Machine for ss Driver.
----------------------------

Host States.
	H_IDLE.
		Host adapter not in use.  May be awaiting reselect on one
		or more devices.

	H_ARBITRATING.
		Awaiting arbitration complete on some drive.

	H_SCSI_RESET.
		The host adapter needs to do, or is in the process of doing, a
		SCSI bus reset.  This will occur if a target fails to respond
		to a Bus Device Reset message.

Target States.
	T_IDLE.
		Target device not in use.  No reselect pending.

	T_DISCONNECTED.
		Disconnected;  reselect is expected from this device.

	T_BUSY.
		Target device failed with Device Busy status.  Waiting to
		repeat previous command.

	T_REQ_SENSE.
		Need to send Request Sense command to the given target.
		Either the target device failed the previous command with
		Device Check status, or the target has just executed a Bus
		Device Reset, or the host has just asserted (and released)
		Reset on the SCSI bus.

	T_TIMED_OUT.
		Target device failed with a timeout at some point during a
		SCSI bus cycle.  Waiting to retry previous command.

	T_DEV_RESET.
		The try count for a request has been exhausted.  The target
		device should be sent a Bus Device Reset message.

	T_SETTLING.
		A Bus Device Reset has occurred or a Reselect has failed.
		We need to wait a certain amount of time, then return the
		target state to T_IDLE.

Inputs.
	I_CALL_SSBLOCK.
		The kernel routine dblock() has called the block routine
		for this drive.  The incoming block request has been appended
		to the request queue before the state machine is executed.

	I_RESELECT.
		An IRQ for the host has occurred, indicating that SELECT has
		gone active on the SCSI bus, and the interrupt handler has
		determined that a specific target is reconnecting.

	I_HOST_WATCHDOG.
		Started when arbitration takes a long time.  The host adapter
		is polled at frequent intervals for arbitration complete, using
		timeouts.  If this watchdog timer decrements to zero, the
		attempt to seize SCSI bus control has failed.  Once started,
		the host watchdog will be invoked once per second.  Input to
		state machine occurs if the timer decrements to zero.

	I_TGT_WATCHDOG.
		A target watchdog is started when the target device disconnects
		in the middle of a block i/o command, in order to prevent
		waiting forever after a disconnect.  If the timer decrements to
		zero, the command being executed has failed.  Once started, a
		target watchdog will be invoked once per second until stopped.

	I_HOST_TIMEOUT.
		A timeout set for the host adapter has expired.  Only one host
		timeout may be set at a time.

	I_TGT_TIMEOUT.
		A timeout set for a target device has expired.  Only one target
		timeout per device may be set at a time.

input = I_CALL_SSBLOCK (valid arguments assumed).
	host_state = H_IDLE.
		Load arguments to ssblock() into a request node and place at
		tail of request queue for the target.
		If tgt_state = T_IDLE
			Read block request for this drive nondestructively from
			head of request queue and load the work structure for
			this drive.
			device_try_count <- 0
			Send control codes to start arbitration.
			Go into high priority loop looking for arbitration
			complete.
			If arbitration not complete at end of loop
				device_try_count++
				if (device_try_count too high)
					Set host timeout to 0 msec.
					host_state <- H_SCSI_RESET.
				else
					Set host timeout to 20 msec
					host_state <- H_ARBITRATING.
					Start host watchdog.
			Else // arbitration complete
				Stop host watchdog.
				INFO_XFER
		tgt_state != T_IDLE
			Drive is busy and has pending timeout or watchdog.
			Do nothing.
	host_state != H_IDLE
		Host is busy with arbitration or reset.
		Do nothing.

input = I_RESELECT.
	host_state = H_IDLE.
		If tgt_state = T_DISCONNECTED
			INFO_XFER
		tgt_state != T_DISCONNECTED
			ignore the interrupt
	host_state != H_IDLE
		ignore the interrupt

input = I_HOST_WATCHDOG
	if timer count is zero
		shut off host watchdog timer
		host_state = H_ARBITRATING
			Set host timeout to 0 msec.
			host_state <- H_SCSI_RESET
		host_state != H_ARBITRATING
			ignore the watchdog timeout
	else
		decrement timer count

input = I_TGT_WATCHDOG.
	if timer count is zero
		shut off target watchdog timer
		host_state = H_ARBITRATING
			Set host timeout to 0 msec.
			host_state <- H_SCSI_RESET
		host_state != H_ARBITRATING
			ignore the watchdog timeout
	else
		decrement timer count


INFO_XFER
	Attempt to perform information transfer phases.
	Allow interrupts after last byte of command is sent.
	Update static byte counts for the current request.
	When information transfer phase ends:
	If disconnect message was received
		Start target watchdog.
		tgt_state <- T_DISCONNECTED.
	else if command status is BUSY
		device_try_count++
		if (device_try_count too high)
			Set target timeout to 0 msec.
			tgt_state <- T_DEV_RESET.
		else
			Set target timeout to 250 msec.
			tgt_state <- T_BUSY.
	else if command status is CHECK
		device_try_count++
		if (device_try_count too high)
			tgt_state <- T_DEV_RESET.
		else
			tgt_state <- T_REQ_SENSE.
		Set target timeout to 0 msec.
	else if command status is COMPLETE
		Turn off target watchdog.
		If this was a kernel block request
			Update b_resid.
			Release buffer to the kernel.
		Clear work structure for the drive.
		Set target timeout to 0 msec.
		tgt_state <- T_IDLE
	else // something timed out during SCSI cycle
		device_try_count++
		if (device_try_count too high)
			Set target timeout to 0 msec.
			tgt_state <- T_DEV_RESET.
		else
			Set target timeout to 250 msec.
			tgt_state <- T_TIMED_OUT.
(end INFO_XFER)
@


1.3
log
@Clarify, with aid of ss.std rev.1.
@
text
@d2 3
d71 6
a76 2
		Once started, the host watchdog will be invoked once per second
		until stopped.
d79 5
a83 2
		Once started, a target watchdog will be invoked once per second
		until stopped.
d93 2
a94 2
1. Host State = H_IDLE.
	a.  input = I_CALL_SSBLOCK (valid arguments assumed).
d106 9
a114 4
				host_state <- H_ARBITRATING.
				Set host timeout to 250 msec
				Start host watchdog.
			Else
d116 2
a117 39
				Attempt to get to information transfer phases.
				Allow interrupts after last byte of command
				is sent.
				Update static byte counts for the current
				request.
				When information transfer phase ends:
				If disconnect message was received
					Start target watchdog.
					tgt_state <- T_DISCONNECTED.
				else if command status is BUSY
					device_try_count++
					if (device_try_count too high)
						tgt_state <- T_DEV_RESET.
					else
						Set target timeout to 250 msec.
						tgt_state <- T_BUSY.
				else if command status is CHECK
					device_try_count++
					if (device_try_count too high)
						tgt_state <- T_DEV_RESET.
					else
						tgt_state <- T_REQ_SENSE.
					Set target timeout to 0 msec. (defer)
				else if command status is COMPLETE
					Turn off target watchdog.
					If this was a kernel block request
						Update b_resid.
						Release buffer to the kernel.
					Clear work structure for the drive.
					Set target timeout to 0 msec. (defer)
					(tgt_state is still T_IDLE)
				else // something timed out during SCSI cycle
					device_try_count++
					if (device_try_count too high)
						tgt_state <- T_DEV_RESET.
					else
						Set target timeout to 250 msec.
						tgt_state <- T_TIMED_OUT.
		Else // tgt_state != T_IDLE
d120 6
a125 1
	b.  input = I_RESELECT.
d127 5
a131 6
		else // tgt_state != T_DISCONNECTED
			(need to discard this try)
			Set target timeout to 20 msec.
			tgt_state <- T_SETTLING
	c.  input = I_WATCHDOG.
	d.  input = I_TO_HOST.
d133 10
a142 6
2. Host State = H_ARBITRATING.
	a.  input = I_CALL_SSBLOCK.
	b.  input = I_INTERRUPT.
	c.  input = I_WATCHDOG.
		Cancel host adapter timeout.
	d.  input = I_TO_HOST.
d144 52
a195 5
3. Host State = H_xxx.
	a.  input = I_CALL_SSBLOCK.
	b.  input = I_INTERRUPT.
	c.  input = I_WATCHDOG.
	d.  input = I_TO_HOST.
@


1.2
log
@Case 1.a. completed.
@
text
@d2 3
d9 2
a10 2
State Machines for ss Driver.
-----------------------------
d20 5
d36 6
a41 3
	T_CHECK.
		Target device failed with Device Check status.  Need to
		execute Request Sense and repeat previous command.
d49 1
a49 1
		device should be sent a Bus Device Reset command.
d51 5
d59 2
a60 1
		for this drive.
d62 1
a62 1
	I_INTERRUPT.
d64 2
a65 1
		gone active on the SCSI bus.
a91 1
			Start host watchdog.
d98 1
d122 2
a123 2
						Set target timeout to 0 msec. (defer)
						tgt_state <- T_CHECK.
d130 2
a131 1
					tgt_state <- T_IDLE.
d142 6
a147 1
	b.  input = I_INTERRUPT.
@


1.1
log
@Unfinished draft.
@
text
@d1 4
a4 1
$Log: updateprovbyha,v $
Revision 1.1.1.1  2019/05/29 04:56:34  root
coherent

d30 1
a30 1
		execute Request Status and repeat previous command.
d36 4
a73 1
			device_reset_done  <- 0
d93 6
a98 2
					Set target timeout to 250 msec.
					tgt_state <- T_BUSY.
d100 6
a105 2
					Set target timeout to 0 msec. (defer)
					tgt_state <- T_CHECK.
d114 6
a119 2
					Set target timeout to 250 msec.
					tgt_state <- T_BUSY.
@
0707070064030104201004440000030000030000011777770507310655700006200000004302/newbits/kernel/USRSRC/i8086/drv/RCS/ss.recover,vhead     1.1;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.1
date     91.05.09.15.13.07;  author root;  state Exp;
branches ;
next	;


desc
@Error recovery pseudocode.
@



1.1
log
@initial incomplete draft
@
text
@/*
 * ss.recover - list of ST01/ST02 i/o failures and what to do when they happen.
 * 
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 */
Here are the inputs to the recovery state machine:

A_TIMEOUT (arbitration timeout)
Host adapter takes too long to respond with arbitration complete.

P_TIMEOUT (protocol timeout)
Timeout waiting for desired SCSI bus status while connected to a target.

R_TIMEOUT (reconnect timeout)
Timeout after target disconnects, waiting for reconnect.

TGT_BUSY (target device busy)
Command status returned was BUSY.

TGT_CHECK (target device check)
Command status returned was CHECK.

For each device there are values for the current block I/O request.  These
include
	arb_count
	Number of times we have polled the host adapter while waiting for
	arbitration complete.

	bdr_count
	Number of times we have tried Bus Device Reset while attempting the
	current request.

	bsy_count
	Number of times we have received Device Busy status while attempting
	the current request.

	try_count
	Total number of times the current request has been attempted.
All of these are initialized to zero when a new block request is taken from
the queue.

Whenever an error occurs, one of the above inputs, together with the SCSI id
of the target, is sent to the recovery process.  The recovery process in turn
places commands on the state machine stack and invokes the state machine.
Here is the pseudocode for the recovery process:

add 1 to try_count
if try_count < MAX_TRY_COUNT (6)
	push SST_BLOCKIO
	switch error_type
	case TGT_BUSY
		add 1 to bsy_count
		if bsy_count < MAX_BSY_COUNT (2)
			push SST_WAIT BSY_DELAY
		else
			push SST_BUS_DEV_RST
		endif
	case TGT_CHECK
		push SST_REQ_SENSE
	case P_TIMEOUT, R_TIMEOUT
		add 1 to bdr_count
		if bdr_count < MAX_BDR_COUNT (2)
			push SST_BUS_DEV_RST
		else
			push SST_LOPRI_RESET
		endif
	case A_TIMEOUT
		push SST_HIPRI_RESET
	endswitch
else // try_count >= MAX_TRY_COUNT
	set BFERR in buffer from kernel
	target is IDLE
	cleanup - bdone(), etc.
endif
invoke target stack machine (defer)
@
0707070064030104171004440000030000030000011777770507310655700005600000044236/newbits/kernel/USRSRC/i8086/drv/RCS/ss.sst,vhead     1.8;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.8
date     91.05.15.15.34.38;  author root;  state Exp;
branches ;
next	1.7;

1.7
date     91.05.14.10.06.56;  author root;  state Exp;
branches ;
next	1.6;

1.6
date     91.05.13.09.58.46;  author root;  state Exp;
branches ;
next	1.5;

1.5
date     91.05.13.06.19.28;  author root;  state Exp;
branches ;
next	1.4;

1.4
date     91.05.12.14.20.12;  author root;  state Exp;
branches ;
next	1.3;

1.3
date     91.05.11.14.24.56;  author root;  state Exp;
branches ;
next	1.2;

1.2
date     91.05.11.12.28.56;  author root;  state Exp;
branches ;
next	1.1;

1.1
date     91.05.09.15.18.32;  author root;  state Exp;
branches ;
next	;


desc
@Stack machine pseudocode.
@


1.8
log
@Mostly in step with ss.c.1.40.
@
text
@/*
 * ss.sst - Seagate SCSI state machine (one per target device)
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.7	91/05/14  10:06:56	root
 * Minor revisions during coding of main state machine.
 * 
 * Revision 1.6	91/05/13  09:58:46	root
 * First complete draft.
 * 
 * Revision 1.5	91/05/13  06:19:28	root
 * Rethreading main loop.
 * 
 * Revision 1.4	91/05/12  14:20:12	root
 * Adding timeout logic.
 * 
 * Revision 1.3	91/05/11  14:24:56	root
 * Includes error recovery - still quite incomplete.
 *
 * Revision 1.2	91/05/11  12:28:56	root
 * Further draft as of 05/10
 *
 * Revision 1.1	91/05/09  15:18:32	root
 * Initial incomplete draft.
 */

Things to do.
=============
	RV_BF_TIMEOUT
	"special"

Host status.
============
	host_busy - arbitrating or connected to a target device

Target status.
==============
	TG_BUSY - processing a block i/o request.  Don't start another block
		i/o request.
	TG_WAITING - if this status is TRUE, a timer has been started.  Don't
		start another command until either the timer expires or the
		awaited condition has occurred.  Things to wait for are listed
		under set_timeout().

Commands that appear on the stack.
==================================
	SST_BUS_DEV_RESET
	SST_DEQUEUE (initial value for current state)
	SST_HIPRI_RESET
	SST_LOPRI_RESET
	SST_POLL_ARBITN
	SST_POLL_BEGIN_IO
	SST_POLL_RESELECT
	SST_REQ_SENSE
	SST_RESET_DONE
	SST_RESET_OFF

Block I/O counters.
===================
For each device there are values for the current block I/O request.  These
are
	avl_count
	Number of times we have polled for (not host_busy) and BUS_FREE
	(i.e., host available).

	bdr_count
	Number of times we have tried Bus Device Reset while attempting the
	current request.

	bsy_count
	Number of times we have received Device Busy status while attempting
	the current request.

	try_count
	Total number of times the current request has been attempted.
All of these are initialized to zero when a new block request = taken from
the queue.

Pseudocode for the machine.
===========================
do_sst_op = TRUE  // plan to run this routine again in most cases
while (do_sst_op)
	switch (current state)
	// polling state execute whether TG_WAITING or not
	case SST_POLL_ARBITN
		if arbitration complete
			TG_WAITING = FALSE
			if host_identify succeeds
				do_connect()
			else
				recover(RV_P_TIMEOUT)
			endif
		else
			if timer has expired
				recover(RV_A_TIMEOUT)
			else
				do_sst_op = FALSE
			endif
		endif
	case SST_POLL_BEGIN_IO
		if current request = NULL
			target_state = SST_DEQUEUE
		else
			if not host_busy and bus free
				host_busy = TRUE
				TG_WAITING = FALSE
				reset data pointers
				if current request is buffer i/o
					reset b_resid
				endif
				// may be retrying a block request
				start arbitration
				if arbitration complete
					if host_identify succeeds
						do_connect()
					else
						recover(RV_P_TIMEOUT)
					endif
				else
					target_state = SST_POLL_ARBITN
					set_timeout(DELAY_ARB)
				endif
			else  // host_busy or bus not free
				set_timeout(DELAY_BSY)
			endif
		endif
	case SST_POLL_RESELECT
		if target is doing Reselect
			TG_WAITING = FALSE
			if reconnect handshake succeeds
				do_connect()
			else
				recover(RV_P_TIMEOUT)
			endif
		else  // Reselect poll = negative
			if timer has expired
				recover(RV_R_TIMEOUT)
			else
				do_sst_op = FALSE
			endif
		endif
	default
		if TG_WAITING
			do_sst_op = FALSE
		else
	// nonpolling states execute only if no target timer is running
			switch (current state)
	case SST_BUS_DEV_RESET
		try sending Bus Device Reset message to target
		if successful
			do_sst_op = FALSE
			set_timeout(DELAY_BDR)
			target_state = SST_REQ_SENSE
		else
			recover(RV_P_TIMEOUT)
		endif
	case SST_DEQUEUE
		if block i/o queue for target not empty and not TG_BUSY
			TG_BUSY = TRUE
			remove head request from queue
			form current block request - initialize try counts, etc.
			target_state = SST_POLL_BEGIN_IO
		else // queue is empty or TG_BUSY
			do_sst_op = FALSE
		endif
	case SST_HIPRI_RESET
		turn on Reset bus line
		target_state = SST_RESET_OFF
		set_timeout(DELAY_RST)
	case SST_LOPRI_RESET
		// same as SST_HIPRI_RESET for now;  later, can implement
		a delay to allow other targets to finish pending operations
	case SST_REQ_SENSE
		try sending Request Sense command to target (no disconnect)
		if successful
			target_state = SST_POLL_BEGIN_IO
		else
			recover(RV_P_TIMEOUT)
		endif
	case SST_RESET_DONE
		target_state = SST_POLL_BEGIN_IO
	case SST_RESET_OFF
		turn off Reset bus line
		target_state = SST_RESET_DONE
		set_timeout(DELAY_RST)
			endswitch
		endif
	endswitch
endwhile

Subroutines.
============

do_connect
----------
if current request is buffer i/o
	try_info_xfer()
else
	special_xfer()
endif
host_busy = FALSE
if transfer timed out
	recover(RV_P_TIMEOUT)
else if Disconnect message was received
	target_state = SST_POLL_RESELECT
	set_timeout(DELAY_RES)
else if Command Complete
	cleanup - bdone(), etc.
	current request = NULL
	TG_BUSY = FALSE
	if current request is buffer i/o
		target_state = SST_DEQUEUE
	else
		special status = TRUE
		wakeup special
	endif
else if Busy
	recover(RV_CS_BUSY)
else if Check
	recover(RV_CS_CHECK)
else  // something else went wrong
	recover(RV_P_TIMEOUT)
endif

recover
-------
Here are the inputs to the error recovery process:

RV_A_TIMEOUT (arbitration timeout)
Host adapter takes too long to respond with arbitration complete.

RV_P_TIMEOUT (protocol timeout)
Timeout waiting for desired SCSI bus status while connected to a target.

RV_R_TIMEOUT (reconnect timeout)
Timeout after target disconnects, waiting for reconnect.

RV_CS_BUSY (target device busy)
Command status returned was Busy.

RV_CS_CHECK (target device check)
Command status returned was CHECK.

Whenever an error occurs, one of the above inputs, together with the SCSI id
of the target, is sent to the recovery process.  The recovery process in turn
programs the next state for the machine.

add 1 to try_count
if try_count < MAX_TRY_COUNT (6)
	switch error_type
	case RV_CS_BUSY
		add 1 to bsy_count
		if bsy_count < MAX_BSY_COUNT (2)
			target_state = SST_POLL_BEGIN_IO
			set_timeout(DELAY_BSY)
		else
			target_state = SST_BUS_DEV_RST
		endif
	case RV_CS_CHECK
		target_state = SST_REQ_SENSE
	case RV_P_TIMEOUT, RV_R_TIMEOUT
		add 1 to bdr_count
		if bdr_count < MAX_BDR_COUNT (2)
			target_state = SST_BUS_DEV_RST
		else
			target_state = SST_LOPRI_RESET
		endif
	case RV_A_TIMEOUT
		target_state = SST_HIPRI_RESET
	endswitch
else // try_count >= MAX_TRY_COUNT
	set BFERR in buffer from kernel
	TG_BUSY = FALSE
	cleanup - bdone(), etc.
	current request = NULL
	if current request is buffer i/o
		target_state = SST_DEQUEUE
	else
		special status = FALSE
		wakeup special
	endif
endif

set_timeout
-----------
Start a timer so as not to wait forever in case something goes wrong while
waiting for an event.  Available delays are:
	DELAY_ARB -	wait for arbitration complete
	DELAY_BDR -	allow settling time after Bus Device Reset
	DELAY_BSY -	wait for (not host_busy) and bus free
	DELAY_RES -	wait for reselect by target
	DELAY_RST -	allow settling times when doing SCSI Bus Reset

TG_WAITING = TRUE
do_sst_op = FALSE
do call to kernel timeout with function that will:
	set TG_WAITING to FALSE
	invoke the state machine

Interrupt.
==========
if a device is doing Reselect
	defer state machine
endif

Watchdog.
=========
Whenever any open is pending for the target, invoke the state machine once
per second.

Block function in CON structure.
================================
If block request is valid
	create a new node
	put it at tail of request queue
	target_state = SST_DEQUEUE
else
	BFERR, etc.
endif

Special commands.
=================
This includes Inquiry, Read Capacity, and Mode Sense.
@


1.7
log
@Minor revisions during coding of main state machine.
@
text
@d5 3
d29 2
d34 1
a34 1
	HOST_BUSY - arbitrating or connected to a target device
d61 4
a64 4
include
	arb_count
	Number of times we have polled the host adapter while waiting for
	arbitration complete.
d104 2
a105 2
			if not HOST_BUSY and bus free
				HOST_BUSY = TRUE
d123 1
a123 1
			else  // HOST_BUSY or bus not free
d201 1
a201 1
HOST_BUSY = FALSE
d290 1
a290 1
	DELAY_BSY -	wait for not HOST_BUSY and bus free
@


1.6
log
@First complete draft.
@
text
@d5 3
a25 1
	startup and other special commands - Inquiry, Read Capacity, etc.
d35 1
a35 1
	TG_WAITING - if this status = TRUE, a timer has been started.  Don't
d43 1
a43 1
	SST_DEQUEUE (initial value for current command)
d78 2
a79 2
	switch (current command)
	// polling commands execute whether TG_WAITING or not
d83 5
a87 1
			do_connect()
d108 7
a114 1
				if timeout
a116 2
				else // arbitration complete
					do_connect()
d123 1
a123 1
		if target = doing Reselect
d126 1
a126 1
				do_reconnect()
d141 2
a142 2
	// nonpolling commands execute only if no target timer is running
			switch (current command)
d158 1
a158 1
		else // queue = empty or TG_BUSY
a174 2
			endswitch
		endif
d181 2
d241 1
a241 1
places commands on the state machine stack.
d297 1
a297 1
if a device is doing Reselect and that device is at SST_POLL_RESELECT
@


1.5
log
@Rethreading main loop.
@
text
@d2 1
a2 1
 * ss.sst - Seagate SCSI stack machine (one per target device)
d5 3
d23 1
a23 12
	startup
	watchdog
	timeouts
	stack machine vs. single current command - this is mainly a problem
		in case of error recovery where we "push" a retry under
		e.g. a Bus Device Reset
	while loop - poll for any awaited activity
	checklist of SST_ commands
	SST_DEQUEUE
	what if another target resets the host?
		rely on usual error handling
	when to turn off TIMING
d27 1
a27 1
	BUSY - arbitrating or connected to a target device
d31 6
a36 10
	BUSY - processing a block i/o request.  Don't start another block i/o
		request.
	DISCONNECTED - awaiting reselect to complete the pending block
		request.  Only pay attention to Reselect when DISCONNECTED.
	TIMING - in each case below, a timer has been started.  Don't start
		another command until either the timer expires or the awaited
		condition has occurred.  Things to wait for are:
			arbitration complete
			target not BUSY
			reselect interrupt
a39 1
	SST_BEGIN_IO
d41 1
a41 1
	SST_DEQUEUE (initial value for current command?!)
d45 1
a45 1
	SST_POLL_CS_BUSY
d48 2
a50 17
Inputs to the error recovery process.
=====================================
A_TIMEOUT (arbitration timeout)
Host adapter takes too long to respond with arbitration complete.

P_TIMEOUT (protocol timeout)
Timeout waiting for desired SCSI bus status while connected to a target.

R_TIMEOUT (reconnect timeout)
Timeout after target disconnects, waiting for reconnect.

TGT_BUSY (target device busy)
Command status returned was BUSY.

TGT_CHECK (target device check)
Command status returned was CHECK.

d69 1
a69 1
All of these are initialized to zero when a new block request is taken from
a73 1

d77 1
a77 1
	// polling commands execute whether target is WAITING or not
d80 1
a80 1
			target is not WAITING
d84 1
a84 1
				recover(A_TIMEOUT)
d89 11
a99 5
	case SST_BEGIN_IO
		if host not BUSY and bus free
			target is not WAITING
			if current request is not NULL
				reset b_resid and data pointers
d103 2
a104 2
					push SST_POLL_ARBITN
					set_timeout(ARB_DELAY)
d108 2
a110 2
		else  // host is BUSY or bus not free
			set_timeout(BSY_DELAY)
d113 6
a118 18
		If target is DISCONNECTED
		// avoid race condition with host interrupt
			target is not DISCONNECTED
			// mask host interrupt
			if target is doing Reselect
				target is not WAITING
				if reconnect handshake succeeds
					do_reconnect()
				else
					recover(P_TIMEOUT)
				endif
			else  // Reselect poll is negative
				if timer has expired
					recover(R_TIMEOUT)
				else
					do_sst_op = FALSE
					target is DISCONNECTED
				endif
d120 6
d128 1
a128 1
		if target is WAITING
d131 1
a131 1
	// nonpolling commands execute only if target is not WAITING
d134 8
d143 2
a144 2
		if block i/o queue for target not empty and target is not BUSY
			target is BUSY
d147 2
a148 2
			push SST_POLL_CS_BUSY
		else // queue is empty or target is BUSY
d152 3
d156 2
d159 6
d167 6
a174 27
======
while (do_sst_op and target is not TIMING)
	if stack empty
		if block i/o queue for target not empty and target is not BUSY
			target is BUSY
			remove head request from queue
			form current block request - initialize try counts, etc.
			push SST_POLL_CS_BUSY
		else // queue is empty or target is BUSY
			do_sst_op = FALSE
		endif
	else // stack not empty
		remove top command from stack
		switch (command)
		case SST_POLL_CS_BUSY
			do_blockio()
		case SST_BUS_DEV_RESET
		case SST_DEQUEUE
		case SST_HIPRI_RESET
		case SST_LOPRI_RESET
		case SST_POLL_ARBITN
		case SST_REQ_SENSE
		case SST_POLL_RESELECT
			ignore the command
		endswitch
	endif
endwhile // do_sst_op
d179 1
a179 1
do_blockio
d181 6
a186 6


do_connect
----------
try_info_xfer()
host is not BUSY
d188 1
a188 1
	recover(P_TIMEOUT)
d190 2
a191 3
	push SST_POLL_RESELECT
	set_timeout(RECON_DELAY)
	target is DISCONNECTED
d194 8
a201 3
	current request is NULL
	push SST_DEQUEUE
	target is not BUSY
d203 1
a203 1
	recover(TGT_BUSY)
d205 1
a205 1
	recover(TGT_CHECK)
d207 1
a207 1
	recover(P_TIMEOUT)
d212 17
a234 1
	push SST_POLL_CS_BUSY
d236 1
a236 1
	case TGT_BUSY
d239 2
a240 1
			set_timeout(BSY_DELAY)
d242 1
a242 1
			push SST_BUS_DEV_RST
d244 3
a246 3
	case TGT_CHECK
		push SST_REQ_SENSE
	case P_TIMEOUT, R_TIMEOUT
d249 1
a249 1
			push SST_BUS_DEV_RST
d251 1
a251 1
			push SST_LOPRI_RESET
d253 2
a254 2
	case A_TIMEOUT
		push SST_HIPRI_RESET
d258 1
a258 1
	target is not BUSY
d260 7
a266 2
	current request is NULL
	push SST_DEQUEUE
d273 5
a277 3
	ARB_DELAY -	wait for arbitration complete
	BSY_DELAY -	wait for target not busy
	RECON_DELAY -	wait for reselect by target
d279 1
a279 1
target is TIMING
d281 3
a283 1
do call to kernel sleep with function that will turn off timing
d287 2
a288 2
if a device is doing Reselect and that device is DISCONNECTED
	defer stack machine
d290 19
@


1.4
log
@Adding timeout logic.
@
text
@d5 3
d23 9
d39 4
a42 2
	BUSY - processing a block i/o request
	DISCONNECTED - awaiting reselect to complete the pending block request
d54 1
d58 2
a60 1
	SST_TRY_RECONNECT
d103 8
a110 7
do_sst_op = TRUE  // plan to run this routine again under most cases
If target is DISCONNECTED  // avoid race condition with host interrupt
	target is not DISCONNECTED  // mask host interrupt
	if target is doing Reselect
		discard all pending commands on stack
		if reconnect handshake succeeds
			do_reconnect()
d112 5
a116 1
			recover(R_TIMEOUT)
d118 62
a179 7
	else if stack not empty
		remove top command from stack
		switch (command)
		case SST_TRY_RECONNECT		// timed out if we're here
		endswitch
	endif
endif
d186 1
a186 1
			push SST_BEGIN_IO
d193 1
a193 1
		case SST_BEGIN_IO
d196 1
d201 1
a201 1
		case SST_TRY_RECONNECT
a212 13
if host is BUSY or bus not free
	push SST_BEGIN_IO
	set_timeout(BSY_DELAY)
else // host not BUSY and bus free
	reset b_resid and data pointers - may be retrying a block request
	start arbitration
	if timeout
		push SST_POLL_ARBITN
		set_timeout(ARB_DELAY)
	else // arbitration complete
		do_connect()
	endif
endif
d221 1
a221 1
	push SST_TRY_RECONNECT
d245 1
a245 1
	push SST_BEGIN_IO
@
T_ARB_DELAY
	SST_WAIT_BSY_DELAY
	SST_WAIT_RECON_DELAY
d87 1
a87 1
defer_machine = TRUE  // plan to run this routine again under most cases
a100 1
		case SST_WAIT_RECON_DELAY	// set timer interval
d103 24
a126 8
else if stack empty
	if block i/o queue for target not empty and target is not BUSY
		target is BUSY
		remove head request from queue
		form current block request - initialize try counts, etc.
		push SST_BLOCKIO
	else // queue is empty or target is BUSY
		defer_machine = FALSE
d128 1
a128 19
else // stack not empty
	remove top command from stack
	switch (command)
	case SST_BLOCKIO
		do_blockio()
	case SST_BUS_DEV_RESET
	case SST_HIPRI_RESET
	case SST_LOPRI_RESET
	case SST_POLL_ARBITN
	case SST_REQ_SENSE
	case SST_TRY_RECONNECT
		ignore the command
	case SST_WAIT_ARB_DELAY
	case SST_WAIT_BSY_DELAY
	case SST_WAIT_RECON_DELAY
		ignore the command
	endswitch
endif
defer stack machine
d137 2
a138 2
	push SST_BLOCKIO
	push SST_WAIT_BSY_DELAY
d144 1
a144 1
		push SST_WAIT_ARB_DELAY
d158 1
a158 1
	push SST_WAIT_RECON_DELAY
d162 2
d181 1
a181 1
	push SST_BLOCKIO
d186 1
a186 1
			push SST_WAIT BSY_DELAY
d204 1
a204 1
	target is IDLE
d206 2
d210 12
a223 1

@
hine
d106 1
a106 1
		 do nothing
a116 1
	case SST_RECONNECT
d119 1
d123 1
d126 1
d134 1
a134 1
if host not IDLE or bus not free
d137 1
a137 2
	defer stack machine
else // host IDLE and bus free
a138 1
	host is ARBITRATING
a142 1
		defer stack machine
d144 1
a144 21
		host is CONNECTED
		try_info_xfer()
		host is IDLE
		if transfer timed out
			recover(P_TIMEOUT)
		else if Disconnect message was received
			push SST_TRY_RECONNECT
			push SST_WAIT_RECON_DELAY
			target is DISCONNECTED
			defer stack machine
		else if Command Complete
			cleanup - bdone(), etc.
			target is IDLE
			defer stack machine
		else if Busy
			recover(TGT_BUSY)
		else if Check
			recover(TGT_CHECK)
		else  // something else went wrong
			recover(P_TIMEOUT)
		endif
d148 20
d169 35
a207 2
	discard all pending commands on stack
	push SST_RECONNECT
@


1.1
log
@initial incomplete draft
@
text
@d4 4
a7 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d17 1
d27 16
a42 5
"tail recur" means re-execute the stack algorithm as if the given command
is the top item on the stack

If stack empty
	if block i/o queue for target not empty
d45 4
a48 3
		tail recur SST_BLOCKIO
	else // queue is empty
		return
d59 1
d76 2
a77 1
	tail recur SST_WAIT_BSY_DELAY
d84 2
a85 1
		tail recur SST_WAIT_ARB_DELAY
d94 3
a96 1
			tail recur SST_WAIT_RECON_DELAY
d99 2
a100 1
			tail recur - no command
d110 10
@
0707070064030104161004440000030000030000011777770507310656300005600000004061/newbits/kernel/USRSRC/i8086/drv/RCS/ss.std,vhead     1.2;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.2
date     91.04.26.15.39.32;  author root;  state Exp;
branches ;
next	1.1;

1.1
date     91.04.25.17.11.09;  author root;  state Exp;
branches ;
next	;


desc
@State Transition "Diagram" (Table) for Seagate SCSI driver.
@


1.2
log
@Second partial draft.
@
text
@$Log: updateprovbyha,v $
@Revision 1.1.1.1  2019/05/29 04:56:34  root
@coherent
@
 * Revision 1.1	91/04/25  17:11:09	root
 * Initial partial draft.
 * 

State Transition Diagram for ss driver.
---------------------------------------

(H_IDLE		T_IDLE		I_CALL_SSBLOCK)
	(H_ARBITRATING	T_IDLE		)
		Arbitration fails.
	(H_IDLE		T_BUSY		)
		Command status returned is BUSY.
	(H_IDLE		T_DEV_RESET	)
		Command try count exhausted.
	(H_IDLE		T_DISCONNECTED	)
		Normal disonnect.
	(H_IDLE		T_IDLE		)
		Command status returned is COMPLETE.
	(H_IDLE		T_REQ_SENSE	)
		Command status returned is CHECK.
	(H_IDLE		T_TIMED_OUT	)
		An awaited bus phase did not occur within the required interval.

(H_IDLE		~T_IDLE		I_CALL_SSBLOCK)
		Take no action.  Remain in current state.

(~H_IDLE	T_IDLE		I_CALL_SSBLOCK)
		Take no action.  Remain in current state.

(H_IDLE		T_DISCONNECTED	I_RESELECT)
	(H_IDLE		T_BUSY		)
		Command status returned is BUSY.
	(H_IDLE		T_DEV_RESET	)
		Command try count exhausted.
	(H_IDLE		T_DISCONNECTED	)
		Normal disonnect.
	(H_IDLE		T_IDLE		)
		Command status returned is COMPLETE.
	(H_IDLE		T_REQ_SENSE	)
		Command status returned is CHECK.
	(H_IDLE		T_TIMED_OUT	)
		An awaited bus phase did not occur within the required interval.

(H_IDLE		~T_DISCONNECTED	I_RESELECT)
	No change in state.
		Reselect was attempted when it is not expected.

(~H_IDLE	T_DISCONNECTED	I_RESELECT)
	No change in state.
		Reselect was attempted when it is not expected.

(H_ARBITRATING	T_IDLE		I_HOST_WATCHDOG)
	(H_SCSI_RESET		T_IDLE		)
		The wait for arbitration complete was too long.

(H_ARBITRATING	~T_IDLE		I_HOST_WATCHDOG)
	Illegal state!

(~H_ARBITRATING	~T_IDLE		I_HOST_WATCHDOG)
	No change in state.
		Watchdog unexpected.
@


1.1
log
@Initial partial draft.
@
text
@d1 4
a4 1
$Log: updateprovbyha,v $
Revision 1.1.1.1  2019/05/29 04:56:34  root
coherent

d32 12
d46 2
d50 13
@
0707070064030104151004440000030000030000011777770507310656400006100000162754/newbits/kernel/USRSRC/i8086/drv/RCS/ss01_20.c,vhead     1.20;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.20
date     91.04.09.14.23.49;  author root;  state Exp;
branches ;
next	1.19;

1.19
date     91.03.26.23.15.47;  author root;  state Exp;
branches ;
next	1.18;

1.18
date     91.03.25.20.11.30;  author root;  state Exp;
branches ;
next	1.17;

1.17
date     91.03.25.19.06.36;  author root;  state Exp;
branches ;
next	1.16;

1.16
date     91.03.22.17.40.03;  author root;  state Exp;
branches ;
next	1.15;

1.15
date     91.03.21.16.44.03;  author root;  state Exp;
branches ;
next	1.14;

1.14
date     91.03.20.17.25.14;  author root;  state Exp;
branches ;
next	1.13;

1.13
date     91.03.18.17.43.18;  author root;  state Exp;
branches ;
next	1.12;

1.12
date     91.03.14.17.22.28;  author root;  state Exp;
branches ;
next	1.11;

1.11
date     91.03.14.15.45.12;  author root;  state Exp;
branches ;
next	1.10;

1.10
date     91.03.13.17.08.03;  author root;  state Exp;
branches ;
next	1.9;

1.9
date     91.03.12.16.08.23;  author root;  state Exp;
branches ;
next	1.8;

1.8
date     91.03.11.17.41.10;  author root;  state Exp;
branches ;
next	1.7;

1.7
date     91.03.08.17.07.28;  author root;  state Exp;
branches ;
next	1.6;

1.6
date     91.03.07.16.41.31;  author root;  state Exp;
branches ;
next	1.5;

1.5
date     91.03.07.11.48.39;  author root;  state Exp;
branches ;
next	1.4;

1.4
date     91.03.06.16.31.45;  author root;  state Exp;
branches ;
next	1.3;

1.3
date     91.03.05.17.03.43;  author root;  state Exp;
branches ;
next	1.2;

1.2
date     91.03.05.12.25.20;  author root;  state Exp;
branches ;
next	1.1;

1.1
date     91.03.04.17.51.00;  author root;  state Exp;
branches ;
next	;


desc
@Seagate ST01/ST02 hard disk SCSI device driver.
@


1.20
log
@Reads boot sector 100 times using IRQ on reconnect
@
text
@int rpt_irpt;
int busted;
/*
 * This is a driver for Seagate ST01/ST02 scsi hard disk controllers.
 *
 * To do:
 *	turn on interrupts
 *	figure out a better storage class for rqs
 *      make input buffer for commands dynamic (?)
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.19	91/03/26  23:15:47	root
 * Reads partition table in prototype code
 * 
 * Revision 1.18	91/03/25  20:11:30	root
 * first raw read - disconnects
 * 
 * Revision 1.17	91/03/25  19:06:36	root
 * calls ssqueue functions - need real i/o
 * 
 * Revision 1.16	91/03/22  17:40:03	root
 * Need to do more with ss_start()
 * 
 * Revision 1.15	91/03/21  16:44:03	root
 * getting ready to call fdisk - finish ss_start next
 * 
 * Revision 1.14	91/03/20  17:25:14	root
 * Inquiry and Read Capacity working
 * 
 * Revision 1.13	91/03/18  17:43:18	root
 * add retry logic to scsicmd(); general cleanup
 * 
 * Revision 1.12	91/03/14  17:22:28	root
 * Test Ready now works, including Req Sense
 * 
 * Revision 1.11	91/03/14  15:45:12	root
 * has trouble with Test Ready using bus_info_xfer fsa
 * 
 * Revision 1.10	91/03/13  17:08:03	root
 * still more to do on bus_info_xfer
 * 
 * Revision 1.9	91/03/12  16:08:23	root
 * need to finish bus_info_xfer()
 * 
 * Revision 1.8	91/03/11  17:41:10	root
 * started ssopen()/wrote stub for ssinit()
 * 
 * Revision 1.7	91/03/08  17:07:28	root
 * Does Test Read and Request Sense properly.
 * 
 * Revision 1.6	91/03/07  16:41:31	root
 * sends Test Ready, Starts to Request Sense
 * 
 * Revision 1.5	91/03/07  11:48:39	root
 * Now sends Identify and Abort messages & completes a SCSI bus cycle
 *
 * Revision 1.4	91/03/06  16:31:45	root
 * tried to send Identify message - get status 0x40 & fail
 *
 * Revision 1.3	91/03/05  17:03:43	root
 * Goes thru arbitration (sans IRQ) successfully
 *
 */

/*
 * Definitions.
 */
#define DEV_SCSI_ID(dev)	((dev >> 4) & 0x0007)
#define DEV_LUN(dev)		((dev >> 2) & 0x0003)
#define DEV_DRIVE(dev)		((dev >> 2) & 0x001F)
#define DEV_PARTN(dev)		(dev & 0x0003)
#define DEV_SPECIAL(dev)	(dev & 0x0080)

#define SS_RAM		0x1800	/* Offset of parameter RAM */
#define SS_CSR		0x1A00	/* Offset of control/status register */
#define SS_DAT		0x1C00	/* Offset of data port */

#define SS_RAM_LEN	128	/* ST0x has 128 bytes of RAM */
#define SS_DAT_LEN	0x400	/* Byte range mapped to data port */
#define SS_SEL_LEN	0x2000	/* Total size of memory-mapped area */

#define WC_ENABLE_SCSI	0x80	/* Write Control (WC) register bits */
#define WC_ENABLE_IRPT	0x40
#define WC_ENABLE_PRTY	0x20
#define WC_ARBITRATE	0x10
#define WC_ATTENTION	0x08
#define WC_BUSY  	0x04
#define WC_SELECT  	0x02
#define WC_SCSI_RESET  	0x01

#define RS_ARBIT_COMPL	0x80	/* Read STATUS (RS) register bits */
#define RS_PRTY_ERROR	0x40
#define RS_SELECT	0x20
#define RS_REQUEST	0x10
#define RS_CTRL_DATA	0x08
#define RS_I_O  	0x04
#define RS_MESSAGE  	0x02
#define RS_BUSY  	0x01

#define HOST_ID		0x80	/* Host adapter is SCSI ID #7 */
#define HIPRI_RETRIES	400	/* # of times to retry while hogging CPU */
#define LOPRI_RETRIES	5	/* # of retries with sleep between tries */
#define WHOLE_DRIVE	NPARTN

#define G0CMDLEN	6	/* Group 0 commands are 6 bytes long  */
#define G1CMDLEN	10	/* Group 1 commands are 10 bytes long */
#define SENSELEN	22	/* number of bytes returned w/ req sense */
#define INQUIRYLEN	54	/* number of bytes returned w/ inquiry */

				/* Message types */
#define MSG_CMD_CMPLT	0x00	/* Command Complete */
#define MSG_SAVE_DPTR	0x02	/* Save SCSI data pointer */
#define MSG_RSTOR_DPTR	0x03	/* Restore SCSI pointers */
#define MSG_DISCONNECT	0x04	/* Target is about to disconnect */
#define MSG_ABORT	0x06	/* End the current SCSI bus cycle */
#define MSG_DEV_RESET	0x0C	/* Bus Device Reset */
#define MSG_IDENT_DC	0xC0	/* Identify, with Disconnect allowed */

#define CS_GOOD		0x00	/* Command Status from the drive */
#define CS_CHECK	0x02
#define CS_BUSY		0x08
#define CS_RESERVED	0x18

				/* Device States */
#define	SIDLE		0	/* controller idle */
#define	SRETRY		1	/* seeking */
#define	SREAD		2	/* reading */
#define	SWRITE		3	/* writing */

/*
 * Information Transfer Phase masks -
 * setting of RS_MESSAGE, RS_I_O, and RS_CTRL_DATA determines which of six
 * possible info transfer phases is occurring.
 */
#define XP_MSG_IN	(RS_MESSAGE | RS_I_O | RS_CTRL_DATA)
#define XP_MSG_OUT	(RS_MESSAGE          | RS_CTRL_DATA)
#define XP_STAT_IN	(             RS_I_O | RS_CTRL_DATA)
#define XP_CMD_OUT	(                      RS_CTRL_DATA)
#define XP_DATA_IN	(             RS_I_O               )
#define XP_DATA_OUT	(                                 0)

#define DEBUG	1
#if DEBUG
int stats[100], statsptr;
#define PUSHI		{ if(statsptr<100)stats[statsptr++] = i; }
#define POPI		{ printf("%d:",statsptr);while(statsptr)\
				printf("%d ",stats[--statsptr]);printf("\n");}
#define SSTELL(foo)	printf(foo)
#define SSTATUS		{uchar status = ffbyte(ss_csr);printf("status=%x\n", status);}
#define SSDUMP(ssp, text) {int i;\
	printf("%s: msg_in=%x cmdstat=%x\n", text, ssp->msg_in,\
	ssp->cmdstat);if(ssp->cmdlen)for(i=0;i<ssp->cmdlen;i++)\
	printf(" %x", ssp->cmdbuf[i]);printf(" cmd_bytes_out=%d",\
	ssp->cmd_bytes_out);\
	if(ssp->data_bytes_in)for(i=0;i<ssp->data_bytes_in;i++)\
	printf(" %x", ssp->in_buf[i]);printf(" data_bytes_in=%d\n",\
	ssp->data_bytes_in);}
#else
#define PUSHI
#define POPI
#define SSTELL(foo)
#define SSTATUS
#define SSDUMP(ssp, text)
#endif

/*
 * Includes.
 */
#include	<coherent.h>
#include	<sys/io.h>
#include	<sys/sched.h>
#include	<sys/uproc.h>
#include	<sys/proc.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<devices.h>		/* SCSI_MAJOR */
#include	<errno.h>

#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<scsiwork.h>

/*
 * Export Functions.
 */

/*
 * Export Variables - patch these to configure the driver.
 */
int	NSDRIVE = 1;		/* Bitmap of attached SCSI drives. */
int	SS_INT = 5;		/* ST0[12] use either IRQ3 or IRQ5 */
int	SS_BASE = 0xDE00;	/* Segment addr of ST0x communication area */

/*
 * Import Functions.
 */
extern int	nulldev();
extern int	nonedev();
extern unsigned char ffbyte();

extern void ssq_wr_tail();
extern scsi_work_t * ssq_rd_head();
extern scsi_work_t * ssq_rm_head();

/*
 * Local Functions.
 */
static void	ssload();
static void	ssunload();
static void	ssopen();
static void	ssclose();
static void	ssread();
static void	sswrite();
static int	ssioctl();
static void	sswatch();
static void	ssblock();
static int	ssinit();
static int	scsicmd();
static void	scsireset();
static void	ssdelay();
static int	bus_pre_xfer();
static int	bus_info_xfer();
static void	ss_start_timing();
static void	ss_stop_timing();
static int	req_sense();
static int	inquiry();
static int	read_cap();
static void	ssintr();
static void	ss_start();
static void	ss_done();
static void	do_ss();
static void	bus_dev_reset();

/*
 * Local Variables.
 */
static BUF	dbuf;		/* For raw I/O */
static paddr_t	ss_base;	/* physical address of ST0x comm area */
static faddr_t	ss_fp;		/* (far *) to ST0x comm area */

static faddr_t	ss_ram;		/* (far *) to parameter RAM */
static faddr_t	ss_csr;		/* (far *) to control/status */
static faddr_t	ss_dat;		/* (far *) to data port */

static int	num_drives;	/* number of controller SCSI id's */
static struct ss *ss_block;	/* points to block of "ss" structs */
static int	st0x_busy;	/* 1 if SCSI host adapter busy */

static TIM	delay_tim;	/* needed for calls to ssdelay() */
static TIM	timeout_tim;	/* needed for calls to timeout() */
static int	ss_expired;	/* 1 after local timeout */
static int	ss_state;	/* starts at SIDLE */

/*
 * Driver CON entry - an export variable.
 */
CON	sscon	= {
	DFBLK|DFCHR,			/* Flags */
	SCSI_MAJOR,			/* Major index */
	ssopen,				/* Open */
	ssclose,			/* Close */
	ssblock,			/* Block */
	ssread,				/* Read */
	sswrite,			/* Write */
	ssioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	sswatch,			/* Timeout */
	ssload,				/* Load */
	ssunload,			/* Unload */
	nulldev				/* Poll */
};

/*
 * A per-drive structure - ss
 */
#define IN_BUF_SIZE	512
typedef unsigned char	uchar;

static struct ss	{
	long	capacity;
	long	blocklen;
	int	msg_in;
	uchar	cmdbuf[G1CMDLEN];
	int	cmdlen;
	int	cmd_bytes_out;
	int	cmdstat;
	uchar	in_buf[IN_BUF_SIZE];
	int	in_buf_len;
	int	data_bytes_in;
	struct	fdisk_s parmp[NPARTN+1];
	unsigned int	ptab_read:1;  /* 1 if partition table has been read */
	unsigned int	id_busy:1;  /* 1 if device with this SCSI id busy */
} *ss[MAX_SCSI_ID-1], rqs;

/*
 * ssload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void ssload()
{
	int erf = 0;  /* 1 if error occurs */
	int i;

	/*
	 * Claim IRQ vector.
	 */
	setivec(SS_INT, ssintr);

	/*
	 * Allocate a selector to map into ST0x memory-mapped comm area.
	 */
	ss_base = (paddr_t)((long)(unsigned)SS_BASE << 4);
	ss_fp = ptov(ss_base, (fsize_t)SS_SEL_LEN);

	ss_ram = ss_fp + SS_RAM;
	ss_csr = ss_fp + SS_CSR;
	ss_dat = ss_fp + SS_DAT;

	/*
	 * Primitive test of ST0x RAM.
	 */
	sfword(ss_ram, 0xA55A);
	sfword(ss_ram + 2, 0x3CC3);
	sfword(ss_ram + SS_RAM_LEN - 4, 0xA55A);
	sfword(ss_ram + SS_RAM_LEN - 2, 0x3CC3);
	if (ffword(ss_ram) != 0xA55A		/* fetch a "far" word */
	||  ffword(ss_ram + 2) != 0x3CC3
	||  ffword(ss_ram + SS_RAM_LEN - 4) != 0xA55A
	||  ffword(ss_ram + SS_RAM_LEN - 2) != 0x3CC3) {
		printf("Error - ST0x failed memory test\n");
		erf = 1;
	}

	/*
	 * Allocate drive structs.
	 *
	 * Do a single call to kalloc() then put allocated pieces into
	 * array ss.
	 */
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				num_drives++;
		if (num_drives == 0) {
			printf("Error - ss has no valid target id's\n");
			erf = 1;
		} else if ((ss_block = kalloc(num_drives*sizeof(struct ss)))
		== NULL) {
			printf("Error - ss can't allocate structs\n");
			erf = 1;
		} else
			kclear(ss_block, num_drives * sizeof(struct ss));
	}
	if (!erf) {
		struct ss *foo = ss_block;

		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				ss[i] = foo++;
	}

	/*
	 * Initialize drives we know about (i.e. in NSDRIVE bitmap).
	 */
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				ssinit(i);
	}
}

/*
 * ssunload()	- unload routine.
 */
static void ssunload()
{
	/*
	 * Deallocate driver heap space.
	 */
	if (ss_block)
		kfree(ss_block);

	/*
	 * Free the ST0x selector.
	 */
	vrelse(ss_fp);

	/*
	 * Release IRQ vector.
	 */
	clrivec(SS_INT);
}

/*
 * ssopen()
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void ssopen( dev, mode )
register dev_t	dev;
{
	int drive, partn;
	int erf = 0;

	drive = DEV_SCSI_ID(dev);
	partn = DEV_PARTN(dev);

	/*
	 * LUN must be zero.
	 * SCSI id must have corresponding 1 in NSDRIVE bitmapped variable.
	 */
	if (DEV_LUN(dev) != 0 || ((1 << drive) & NSDRIVE) == 0) {
		u.u_error = ENXIO;
		erf = 1;
	}

	/*
	 * If "special" bit is set, partition must be zero.
	 */
	if (!erf && DEV_SPECIAL(dev) && partn != 0) {
		u.u_error = ENXIO;
		erf = 1;
	}

	/*
	 * If "special" bit is NOT set, error return for now.
	 */
	if (!erf && !DEV_SPECIAL(dev)) {
		u.u_error = ENXIO;
		erf = 1;
	}

	/*
	 * OK - open the device.
	 */
	if (!erf) {
		++drvl[SCSI_MAJOR].d_time;
	}
#if 0
	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	if ((pparm[p].p_base+pparm[p].p_size) > pparm[d+NDRIVE*NPARTN].p_size)
		u.u_error = EBADFMT;
	else if ( pparm[p].p_size == 0 )
		u.u_error = ENODEV;
#endif
}

/*
 * ssclose()
 */
static void ssclose( dev )
dev_t dev;
{
	--drvl[SCSI_MAJOR].d_time;	
}

/*
 * ssread()	- write a block to the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void ssread( dev, iop )
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
}

/*
 * sswrite()	- write a block to the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void sswrite( dev, iop )
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
}

/*
 * ssioctl()
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static int ssioctl( dev, cmd, vec )
register dev_t	dev;
int cmd;
char * vec;
{
	int ret = 0;

	switch(cmd) {
	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * ssblock()	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void ssblock(bp)
register BUF	*bp;
{
	register scsi_work_t *sw;
	register int s;
	struct	fdisk_s	*fdp;
	int partition, drive, s_id;
	dev_t dev;
	struct ss * ssp;

	/*
	 * Set up local variables.
	 */
	dev = bp->b_dev;
	partition = DEV_PARTN(dev);
	drive = DEV_DRIVE(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];

	if (dev & SDEV)
		partition = WHOLE_DRIVE;
	bp->b_resid = bp->b_count;
	
	fdp = ssp->parmp;

	/*
	 * Range check disk region.
	 */
	if (!(ssp->ptab_read)) {
		if ( partition == WHOLE_DRIVE ) {
			if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
				bp->b_flag |= BFERR;
				bdone(bp);
				return;
			}
		} else {
			devmsg(dev, "no partition table");
			bp->b_flag |= BFERR;
			bdone(bp);
			return;
		}
	}
	/*
	 * Check for read at end of partition.
	 * (Need to return with b_resid = BSIZE to signal end of volume.)
	 */
	else if ((bp->b_req == BREAD) && (bp->b_bno == fdp[partition].p_size)) {
		bdone(bp);
		return;
	}
	/*
	 * Check for read past end of partition.
	 */
	else if ( (bp->b_bno + (bp->b_count/BSIZE))
	> fdp[partition].p_size ) {
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}

	bp->b_actf = NULL;
	sw = (scsi_work_t *)kalloc( sizeof(*sw) );
	if (sw == NULL) {
		devmsg(dev, "out of kernel memory");
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}
	sw->sw_bp = bp;
	sw->sw_drv = drive;
	if (partition != WHOLE_DRIVE)
		sw->sw_bno = fdp[partition].p_base + bp->b_bno;
	else
		sw->sw_bno = bp->b_bno;
	sw->sw_retry = 1;

printf("ssblock: drv %x bno %x:%x  bp=%x, flag = %o\n",
	drive, (long)sw->sw_bno, bp, bp->b_flag);

	ssq_wr_tail(sw);
	if (ss_state == SIDLE)
		ss_start();
}

/*
 * ssintr()	- Interrupt routine.
 */
#if 0
static int irpted;
static long x;
for (x = 0, irpted = 0; x < 100000L; x++)  if (irpted) break;
#endif

static void ssintr()
{
	printf("@@");
	rpt_irpt=1;
	wakeup(&rpt_irpt);
}

/*
 * sswatch()
 */
static void sswatch()
{
	printf("*");
	busted = 1;
	drvl[SCSI_MAJOR].d_time=0;
	wakeup(&rpt_irpt);
}

/*
 * bus_wait()
 *
 * Wait for specified bit values to appear in Status Register.
 * This uses a tight loop and does not expect to be interrupted.
 *
 * Argument "flags" is a double-byte value;  the high byte is ANDed with
 * status register contents, and the result is tested for equality with
 * the low byte.
 *
 * Return 1 if values wanted appeared, 0 if timeout occurred.
 */
static int bus_wait(flags)
unsigned short flags;
{
	int found, i;
	unsigned char status;

	found = 0;
	for ( i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & (flags >> 8)) == (flags & 0xff)) {
			found = 1;
			break;
		}
	}

	if (!found)
		printf("ST0x timeout;  flags=%x status=%x\n", flags, status);

	return found;
}

/*
 * ssinit()
 *
 * Attempt to initialize the (unique) drive with a given SCSI id.
 * Assume only one drive per SCSI id, having LUN = 0.
 * 
 * Return 1 if success, 0 if failure.
 *
 * Pseudocode:
 *
 * retval = 0
 * if Test Unit Ready command fails, even after SCSI reset and retry
 *   print "Test Unit Ready fails"
 * else if Request Sense command fails
 *   print "Request Sense fails"
 * else if Read Capacity command succeeds
 *   print "Read Capacity fails"
 * else if partition table can't be read
 *   print "can't get partition table"
 * else
 *   print "SCSI id #n initialized"
 *   retval = 1
 * return retval
 */
static int ssinit(s_id)
int s_id;
{
	int retval = 0;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

	if (testready(s_id))
		retval = 1;
	else {
		scsireset();
		bus_dev_reset(s_id);
		if (testready(s_id))
			retval = 1;
		else
			devmsg(dev, "Test Unit Ready Failed");
	}

	if (retval)
		if (req_sense(s_id)) {
			retval = 1;
		} else
			devmsg(dev, "Request Sense Failed");

	if (retval)
		if (inquiry(s_id)) {
			ss[s_id]->in_buf[INQUIRYLEN] = 0;
			devmsg(dev, ss[s_id]->in_buf + 8);
			if (ss[s_id]->in_buf[0] == 0) {
				retval = 1;
			} else
				devmsg(dev, "Not Direct Access Device");
		} else
			devmsg(dev, "Inquiry Failed");

	if (retval)
		if (read_cap(s_id)) {
			retval = 1;
		} else
			devmsg(dev, "Read Capacity Failed");

#if 0
	if (retval) {
		retval = fdisk(dev, ss[s_id]->parmp);
		if (retval) {
			printf("fdisk scsi id #%d succeeded\n", s_id);
			ss[s_id]->ptab_read = 1;
		} else
			printf("fdisk scsi id #%d failed\n", s_id);
	}
#else
	/*
	 * For test purposes only, try to read the partition table.
	 */
	if (retval) {
int foo,fof;
for (foo=0,fof=0;foo<100;){
	rpt_irpt=0;
	busted=0;
	drvl[SCSI_MAJOR].d_time=1;
		if (read_pt(s_id)) {
			retval = 1;
		} else {
			devmsg(dev, "Read Partition Table Failed");
			break;
		}
foo++;
	if (!rpt_irpt){
		fof++;
		if (fof>=3) {
			printf("3 irq's lost\n");
			break;
		}
	}
} /*endfor*/
printf("%d read_pt's\n",foo);
	}
#endif

	return retval;
}

/*
 * Send Test Unit Ready command.
 * Retry after bus reset if necessary.
 *
 * Return 1 if unit is ready, 0 if not.
 */
static int testready(s_id)
int s_id;
{
	int retval;
	struct ss * ssp = ss[s_id];

	ssp->cmdbuf[0] = ScmdTESTREADY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] =
		ssp->cmdbuf[5] = 0;
	ssp->cmdlen = G0CMDLEN;
	retval = scsicmd(s_id);

	return retval;
}

/*
 * scsicmd()
 *
 * Send command packet to target device.
 * Start a new SCSI bus cycle when this routine is called.
 * If command status after sending is Device Check (CS_CHECK), do a
 * Request Sense to find out what happened and clear check status.
 *
 * Return 1 if command was send and status was good, else 0.
 */
static int scsicmd(s_id)
int s_id;
{
	int retval;
	struct ss *ssp = ss[s_id];
	int tries;

	tries = 0;
	do {
		if (tries > 0)
			ssdelay(100);

		if (retval = bus_pre_xfer(s_id)) {
			bus_info_xfer(ssp);
			retval = (ssp->cmdlen == ssp->cmd_bytes_out
				&& ssp->cmdstat == CS_GOOD);
		}

		if (ssp->cmdstat == CS_CHECK) {
			if (req_sense(s_id))
				retval = (ssp->cmdlen == ssp->cmd_bytes_out);
		}

		tries++;
	} while (ssp->cmdstat == CS_BUSY && tries < LOPRI_RETRIES);

	if (ssp->msg_in == MSG_DISCONNECT) {
		int connected = 0;
		uchar dat, csr;

printf("Disconnected ");
{
	int s;
	s=sphi();
	while(!rpt_irpt && !busted)
		sleep(&rpt_irpt, CVBLKIO,IVBLKIO,SVBLKIO);
	spl(s);
}
		for (tries = 0; tries < 10; tries++) {
			csr = ffbyte(ss_csr);
			if (csr & RS_SELECT) {
				dat = ffbyte(ss_dat);
				if (dat & HOST_ID) {
printf("%d tries Reconnected\n",tries);
					connected = 1;
					break;
				} else {
					int t;
printf("Host not selected\n");
					for (t = 0; t < 10; t++) {
						if (ffbyte(ss_csr) & RS_SELECT == 0) {
printf("Select dropped by target\n");
							break;
						}
						ssdelay(10);
					}
				}
			}
			ssdelay(10);
		}
		if (connected) {
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
			if (bus_wait(RS_SELECT << 8 | 0)) {
printf("Select deasserted by target\n");
				sfbyte(ss_csr, WC_ENABLE_SCSI);
				bus_info_xfer(ssp);
				retval = (ssp->cmdstat == CS_GOOD);
			}
		}
	}

	return retval;
}

/*
 * scsireset()
 *
 * Reset the SCSI bus.
 * Allow settling time when turning reset on/off.
 * Settling times were determined empirically.
 * Each tick is 10 msec.
 */
#define RESET_TICKS	40
int RESET_ON_TICKS = 40;
int RESET_OFF_TICKS = 40;
static void scsireset()
{
printf("scsireset\n");
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
	ssdelay(RESET_ON_TICKS);
	sfbyte(ss_csr, 0);
	ssdelay(RESET_OFF_TICKS);
}

/*
 * ssdelay()
 *
 * Delay for some number of clock ticks.
 * 286/386 kernel ticks are at 100Hz
 */
static void ssdelay(ticks)
int ticks;
{
	timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
}

/*
 * ss_start_timing()
 *
 * Start a timeout for some number of ticks.
 * Caller knows timer has expired when "ss_expired" goes to 1.
 *
 * Sample invocation:
 *	ss_start_timing(n);
 *	while (check for desired event fails) {
 *		if (ss_expired) {
 *			...failure stuff..
 *			break;
 *		}
 *		ssdelay(m); <= needed to allow kernel to update timers
 *	}
 */
static void ss_start_timing(ticks)
int ticks;
{
	ss_expired = 0;
	timeout(&timeout_tim, ticks, ss_stop_timing, 1);
}

/*
 * ss_stop_timing()
 *
 * Stub function called only by ss_start_timing()
 */
static void ss_stop_timing(flagval)
int flagval;
{
	ss_expired = flagval;
}

/*
 * bus_pre_xfer()
 *
 * Do bus cycle phases prior to the information transfer phases.
 * This includes arbitration and selection.
 */
static int bus_pre_xfer(s_id)
int s_id;
{
	int tries;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));
	int ret;

	for (ret = 0, tries = 0; !ret && tries < LOPRI_RETRIES; tries++) {
		/*
		 * Do ST0x arbitration.
		 */
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

		/*
		 * SCSI spec says there is "no maximum" to the wait for arbitration
		 * complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			scsireset();
			continue;
		}

		/*
		 * Arbitration complete.  Now select, with ATN to allow messages.
		 */
		sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			continue;

		/*
		 * Send "Identify" Message with Disconnect allowed.
		 */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			continue;

		sfbyte(ss_dat, MSG_IDENT_DC);
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ENABLE_IRPT);
		ret = 1;
	}

	return ret;
}

/*
 * bus_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * This includes message in/out, command in/out, and data in/out.
 *
 * If cmdlen is nonzero, cmdbuf is an array of bytes of that length,
 * to be sent to the target.
 *
 * Return 1 if bus timeout did not occur, else 0.
 *
 * pseudocode:
 *
 * while (wait for REQ true or BUSY false on SCSI bus)
 *   if (BUSY false)
 *     break from while loop
 *   else
 *     switch (xfer phase = RS_CTRL_DATA|RS_I_O|RS_MESSAGE)
 *       case XP_MSG_IN/XP_MSG_OUT/...
 *         handle the indicated information transfer phase
 *     endswitch
 *   endif
 * endwhile
 */
static int bus_info_xfer(ssp)
struct ss *ssp;
{
	int bus_timeout;
	uchar phase_type;
	uchar msg_in;
	int no_msg_rcvd = 1;
	int s;
	int bytes_to_send;

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->cmd_bytes_out = 0;
	ssp->msg_in = -1;
	s = sphi();
	while(req_wait(&bus_timeout)) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		switch (phase_type) {
		case XP_MSG_IN:
			/*
			 * Only pay attention to first msg byte in.
			 * Don't care about extended messages.
			 */
			msg_in = ffbyte(ss_dat);
printf("msg_in = %x\n", msg_in);
			switch(msg_in){
			case MSG_CMD_CMPLT:
				ssp->msg_in = msg_in;
				break;
			case MSG_SAVE_DPTR:
				break;
			case MSG_RSTOR_DPTR:
				break;
			case MSG_DISCONNECT:
				ssp->msg_in = msg_in;
				break;
			case MSG_ABORT:
				break;
			case MSG_DEV_RESET:
				break;
			case MSG_IDENT_DC:
				break;
			}
			break;
		case XP_MSG_OUT:
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.  Abort the bus cycle.
			 */
			sfbyte(ss_csr, WC_ENABLE_SCSI);
			sfbyte(ss_dat, MSG_ABORT); 
			break;
		case XP_STAT_IN:
			ssp->cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 * Reset SCSI bus if too many command bytes are wanted.
			 */
			bytes_to_send = ssp->cmdlen - ssp->cmd_bytes_out;
			if(bytes_to_send > 0) {
				sfbyte(ss_dat, ssp->cmdbuf[ssp->cmd_bytes_out++]);
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (bytes_to_send == 1) {
					spl(s);
					s = sphi();
				}
			} else {	/* This case should not happen. */
SSDUMP(ssp, "Command overrun");
				scsireset();
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.  Else toss it.
			 */
			if (ssp->data_bytes_in < ssp->in_buf_len)
				ssp->in_buf[ssp->data_bytes_in]
				= ffbyte(ss_dat);
			else
				ffbyte(ss_dat);
			ssp->data_bytes_in++;
			break;
		case XP_DATA_OUT:
			/*
			 * Temporary filler.
			 */
			sfbyte(ss_dat, 0xAA);
			break;
		default:
			break;
		} /* endswitch */
	}
	spl(s);
	return (bus_timeout) ? 0 : 1 ;
}
/*
 * req_wait()
 *
 * This routine is called at the start of each information transfer
 * phase and after the last such phase.
 *
 * It returns 1 if REQ is asserted on the SCSI bus, meaning another phase
 * may begin, and 0 otherwise.  A REQ signal will not be seen if the function
 * times out or if BUSY drops.  A value of 1 is written to the pointer argument
 * if timeout occurred, else 0 is written.
 */
static int req_wait(to_ptr)
int *to_ptr;
{
	int req_found, i;
	unsigned char status;

	*to_ptr = 1;
	req_found = 0;
	for ( i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if (status & RS_REQUEST) {
			req_found = 1;
			*to_ptr = 0;
			break;
		} else if ((status & RS_BUSY) == 0) {
			*to_ptr = 0;
			break;
		}
	}

	if (*to_ptr)
		printf("ST0x info xfer timeout;  status=%x\n", status);

	return req_found;
}

/*
 * req_sense()
 *
 * Request Sense for a device.  The main reason for doing this is to
 * clear a standing Command Status of Device Check.
 *
 * Full results are discarded.  Return 1 if Device returns No Sense or
 * or Unit Attention.  Else return 0.
 *
 */
static int req_sense(s_id)
int s_id;
{
	int ret = 0;

	rqs.cmdbuf[0] = ScmdREQUESTSENSE;
	rqs.cmdbuf[1] = rqs.cmdbuf[2] = rqs.cmdbuf[3] =
		rqs.cmdbuf[5] = 0;
		rqs.cmdbuf[4] = SENSELEN;
	rqs.cmdlen = G0CMDLEN;
	rqs.in_buf_len = SENSELEN;

	if (bus_pre_xfer(s_id)) {
		bus_info_xfer(&rqs);
		if (rqs.data_bytes_in == SENSELEN) {
			if (rqs.in_buf[2] == 0x00)	/* No Sense.  AOK */
				ret = 1;
			else if (rqs.in_buf[2] == 0x06 && rqs.in_buf[12] == 0x29)
				ret = 1;
		}
	}

	return ret;
}

/*
 * inquiry()
 *
 * Inquiry command for a device.
 * Find out if device is direct access, removable, etc.
 *
 * Return 1 if command succeeds, else 0.
 */
static int inquiry(s_id)
int s_id;
{
	int ret = 0;
	struct ss * ssp = ss[s_id];

	ssp->cmdbuf[0] = ScmdINQUIRY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] =
		ssp->cmdbuf[5] = 0;
		ssp->cmdbuf[4] = INQUIRYLEN;
	ssp->cmdlen = G0CMDLEN;
	ssp->in_buf_len = INQUIRYLEN;

	ret = scsicmd(s_id);

	return ret;
}

/*
 * read_cap()
 *
 * Read Capacity command for a device.
 *
 * Return 1 if command succeeds, else 0.
 */
static int read_cap(s_id)
int s_id;
{
	int ret = 0;
	struct ss * ssp = ss[s_id];

	ssp->cmdbuf[0] = ScmdREADCAPACITY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] = 0;
	ssp->cmdbuf[5] = ssp->cmdbuf[6] = ssp->cmdbuf[7] = ssp->cmdbuf[8] = 0;
	ssp->cmdbuf[9] = 0;
	ssp->cmdlen = G1CMDLEN;
	ssp->in_buf_len = 8;

	ret = scsicmd(s_id);
	if (ret) {
		ssp->capacity = ssp->in_buf[3] | (ssp->in_buf[2] << 8)
		| (((long)(ssp->in_buf[1])) << 16)
		| (((long)(ssp->in_buf[0])) << 24);
		ssp->blocklen = ssp->in_buf[7] | (ssp->in_buf[6] << 8)
		| (((long)(ssp->in_buf[5])) << 16)
		| (((long)(ssp->in_buf[4])) << 24);
printf("capacity=%ld   block length=%ld\n", ssp->capacity, ssp->blocklen);
	}

	return ret;
}

/*
 * ss_start()
 *
 * Invoked whenever there is I/O to do.  Pull first request, if any,
 * off the queue, send it to the drive, and delete it from the queue.
 *
 * Disallow re-entrancy in this routine (variable "locked").
 */
static void ss_start()
{
	int s;
	scsi_work_t *sw;
	static char locked;

	s = sphi();
	if(locked) {
		spl(s);
		return;
	}
	++locked;
	spl(s);

	if((sw = ssq_rm_head()) != NULL) {
		if (sw->sw_bp->b_req == BWRITE)
			ss_state = SWRITE;
		else if (sw->sw_bp->b_req == BREAD)
			ss_state = SREAD;
		else
			printf("Error:  b_req=%d\n", sw->sw_bp->b_req);
		do_ss(sw);
	}
	--locked;
}

/*
 * do_ss()
 *
 * Begin a block read or write command as found in an "sw" queue entry.
 */
static void do_ss(sw)
struct scsi_work_t * sw;
{
	BUF * bp;

printf("do_ss\n");
	bp = sw->sw_bp;
	switch(ss_state) {
	case SREAD:
		bp->b_resid -= BSIZE;
		ss_done(sw);
		break;
	case SWRITE:
		bp->b_resid -= BSIZE;
		ss_done(sw);
		break;
	}
}

/*
 * ss_done
 *
 * Release current i/o buffer to the O/S.
 */
static void ss_done(sw)
struct scsi_work_t * sw;
{
	BUF * bp;

printf("ss_done\n");
	bp = sw->sw_bp;

	ss_state = SIDLE;
	bdone(bp);
	kfree(sw);

	if (ssq_rd_head())
		ss_start();
}

/*
 * read_pt()
 *
 * Read partition table for a device.
 *
 * Return 1 if command succeeds, else 0.
 */
static int read_pt(s_id)
int s_id;
{
	int ret = 0;
	struct ss * ssp = ss[s_id];

	ssp->cmdbuf[0] = ScmdREADEXTENDED;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] = 0;
	ssp->cmdbuf[5] = ssp->cmdbuf[6] = ssp->cmdbuf[7] = ssp->cmdbuf[9] = 0;
	ssp->cmdbuf[8] = 1;	/* transfer 1 block */
	ssp->cmdlen = G1CMDLEN;
	ssp->in_buf_len = BSIZE;

	ret = scsicmd(s_id);
	if (ret) {
printf("signature low:%x high:%x\n", ssp->in_buf[510], ssp->in_buf[511]);
	}

	return ret;
}

/*
 * BDR_CHECK_INTERVAL is the number of ticks to wait between checks for
 * SCSI Bus Free after sending Bus Device Reset.
 * BDR_CHECK_COUNT is the number of times to check for SCSI Bus Free
 * before giving up.
 */
#define BDR_CHECK_INTERVAL	10
#define BDR_CHECK_COUNT		100

/*
 * bus_dev_reset()
 *
 * Send Bus Device Reset message to the given SCSI id.
 */
static void	bus_dev_reset(s_id)
{
	int tries;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));
printf("bus_dev_reset\n");
	for (tries = 0; tries < LOPRI_RETRIES; tries++) {
		/*
		 * Do ST0x arbitration.
		 */
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

		/*
		 * SCSI spec says there is "no maximum" to the wait for arbitration
		 * complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			scsireset();
			continue;
		}

		/*
		 * Arbitration complete.  Now select, with ATN to allow messages.
		 */
		sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			continue;

		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			continue;

		sfbyte(ss_csr, WC_ENABLE_SCSI);
		sfbyte(ss_dat, MSG_DEV_RESET);
		break;
	}
	for (tries = 0; tries < BDR_CHECK_COUNT; tries++) {
		if (ffbyte(ss_csr) == 0) {
			printf("bus device reset done\n");
			break;
		}
		ssdelay(BDR_CHECK_INTERVAL);
	}
}
@


1.19
log
@Reads partition table in prototype code
@
text
@d1 2
d12 3
d626 2
d635 5
a639 1
	static int calls;
a640 7
	if (calls == 0)
		printf("*");
	calls++;
	if (calls >= 60)
		calls = 0;
}

d752 5
d759 1
a759 1
		} else
d761 9
d771 3
d840 8
a847 1
printf("Disconnected\n");
d853 1
a853 1
printf("Reconnected\n");
a998 1
		sfbyte(ss_csr, WC_ENABLE_SCSI);
d1000 1
a1128 1
SSDUMP(ssp, "cmd");
@


1.18
log
@first raw read - disconnects
@
text
@d10 3
d106 6
a112 1
#define MSG_ABORT	0x06	/* End the current SCSI bus cycle */
d144 1
a144 1
#define SSTATUS		printf("status=%x\n", (int)(unsigned char)status)
d228 1
d666 1
a666 1
PUSHI;
d681 1
a681 1
 * if Test Unit Ready command fails
d700 1
a700 1
	if (testready(s_id)) {
d702 8
a709 2
	} else
		devmsg(dev, "Test Unit Ready Failed");
d794 1
d796 55
a850 4
	if (retval = bus_pre_xfer(s_id)) {
		bus_info_xfer(ssp);
		retval = (ssp->cmdlen == ssp->cmd_bytes_out
			&& ssp->cmdstat == CS_GOOD);
a852 5
	if (ssp->cmdstat == CS_CHECK) {
		if (req_sense(s_id))
			retval = (ssp->cmdlen == ssp->cmd_bytes_out);
	}

d865 2
d869 1
d871 1
a871 1
	ssdelay(RESET_TICKS);
d873 1
a873 1
	ssdelay(RESET_TICKS);
a1002 2
int zzzz;

d1007 2
a1008 1
	unsigned char phase_type;
a1011 1
int zzgo=0;
d1016 1
a1018 4
if(zzgo) {
	zzgo = 0;
	printf("zzzz=%d\n", zzzz);
}
d1026 20
a1045 5
			if (no_msg_rcvd) {
				no_msg_rcvd = 0;
				ssp->msg_in = ffbyte(ss_dat);
			} else
				ffbyte(ss_dat);
a1070 1
zzgo=1;
d1101 1
a1101 1
POPI;
d1137 1
a1137 2
PUSHI;
zzzz=i;
d1342 64
@


1.17
log
@calls ssqueue functions - need real i/o
@
text
@d10 3
d263 1
a263 1
#define IN_BUF_SIZE	100
d283 1
a284 3
 * void
 * ssload()	- load routine.
 *
d288 1
a288 2
static void
ssload()
a361 1
 * void
d364 1
a364 2
static void
ssunload()
d384 1
a384 3
 * ssopen( dev, mode )
 * dev_t dev;
 * int mode;
d392 1
a392 2
static void
ssopen( dev, mode )
d453 1
a454 5
 * void
 * ssread( dev, iop )	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
d460 1
a460 2
static void
ssread( dev, iop )
d468 1
a469 5
 * void
 * sswrite( dev, iop )	- write a block to the raw disk
 * dev_t dev;
 * IO * iop;
 *
d475 1
a475 2
static void
sswrite( dev, iop )
d483 1
a484 6
 * int
 * ssioctl( dev, cmd, arg )
 * dev_t dev;
 * int cmd;
 * char * vec;
 *
d492 1
a492 2
static int
ssioctl( dev, cmd, vec )
d509 1
a509 1
 * ssblock( bp )	- queue a block to the disk
d516 1
a516 2
static void
ssblock(bp)
d609 1
a609 2
static void
ssintr()
d617 1
a617 1
static void	sswatch()
d719 1
d728 11
d1241 28
@


1.16
log
@Need to do more with ss_start()
@
text
@d10 3
d92 1
d108 6
d182 3
a184 3
int	nulldev();
int	nonedev();
unsigned char ffbyte();
d186 4
d215 2
d231 2
d235 2
a237 3
static int	ss_expired;	/* 1 after local timeout */
static scsi_work_t	*scsi_work_queue;

d276 1
d454 1
a454 1
	--drvl[SDMAJOR].d_time;	
d522 1
a522 1
		u.uerror = EINVAL;
d530 1
a531 3
 * void
 * ssblock( bp )	- queue a block to the disk
 *
d548 3
d579 13
a591 1
	} else if ( (bp->b_bno + (bp->b_count/BSIZE))
d600 1
a600 1
	if (sw == (scsi_work_t *)0) {
d615 1
a615 1
	drv, (long)sw->sw_bno, bp, bp->b_flag);
d617 4
a620 7
	s = sphi();
	if (sd.sw_actf == NULL)
		sd.sw_actf = sw;
	else
		sd.sw_actl->sw_actf = sw;
	sd.sw_actl = sw;
	spl(s);
a621 3
	ss_start();
}

a622 2
 *
 * void
a623 1
 *
d685 2
d744 5
a748 4
		if (retval)
			printf("fdisk succeeded\n");
		else
			printf("fdisk failed\n");
d836 2
d859 2
d1178 1
a1178 2
 * off the queue and try to send it to the drive.
 * If request is sent, delete it from the queue.
d1189 1
a1189 1
	if( locked ) {
d1196 8
a1203 8
	if( (sw = scsi_work_queue->sw_actf) != NULL ) {
		if (do_ss(sw)) {
			s = sphi();
			sw = scsi_work_queue->sw_actf = sw->sw_actf;
			if( sw == NULL )
				scsi_work_queue->sw_actl = NULL;
			spl(s);
		}
d1207 45
@


1.15
log
@getting ready to call fdisk - finish ss_start next
@
text
@d10 3
a532 1

d538 1
a538 1
	if (dev & SDEV )
d577 2
a578 3
	sw->sw_type = 0;
	if ( partition != WHOLE_DRIVE )
		sw->sw_bno   = fdp[partition].p_base + bp->b_bno;
d580 1
a580 1
		sw->sw_bno   = bp->b_bno;
d583 2
a584 2
printf( "ssblock: drv %x bno %x:%x  bp=%x, flag = %o\n",
	drv, (long)sw->sw_bno, bp, bp->b_flag );
a591 1
	++drvl[SDMAJOR].d_time;	
d1147 6
d1156 1
a1156 1
	int i, s, n = 0;
d1168 8
a1175 19
	while( (sw = scsi_work_queue->sw_actf) != NULL ) {
		for( i = MIN_MAILBOX; i < MAX_MAILBOX; ++i )
			if( mailbox_out[i].cmd == MBO_IS_FREE ) {
				register ccb_t *ccb;
				int s;

				++n;
SEND SCSI COMMAND
				s = sphi();
				sw = scsi_work_queue->sw_actf = sw->sw_actf;
				if( sw == NULL )
					scsi_work_queue->sw_actl = NULL;
				spl(s);

				if( sw == NULL )
					break;
			}
		if( i == MAX_MAILBOX )
			break;
a1177 1
	return n;
@


1.14
log
@Inquiry and Read Capacity working
@
text
@a4 1
 *	run scsicmd() at hi priority
a5 1
 *	put retry logic into arbitrate, etc.
d10 3
d53 1
d179 1
d197 1
d216 1
d225 1
a225 1
	nulldev,			/* Close */
d254 2
a364 2
 *
 * void
d401 7
a407 4
#if 0
	if ( minor(dev) & SDEV ) {
		d = minor(dev) % NDRIVE;
		p += NDRIVE * NPARTN;
a408 2
	else
		d = minor(dev) / NPARTN;
a409 7
	if ( (d >= NDRIVE) || (at.at_dtype[d] == 0) ) {
		return;
	}

	if ( minor(dev) & SDEV )
		return;

d411 1
a411 1
	 * If partition not defined read partition characteristics.
d413 4
a416 3
	if ( pparm[p].p_size == 0 )
		fdisk( makedev( major(dev), SDEV + d), &pparm[ d * NPARTN ] );

d428 9
d497 9
d522 73
d615 3
d620 7
a696 1
			devmsg(dev, "Sense Requested");
a705 1
				devmsg(dev, "Inquiry Complete");
a713 1
			devmsg(dev, "Read Capacity Done");
d718 8
d755 2
d758 1
a758 1
 * Return 1 if command succeeds, else 0.
d771 1
a771 1
SSDUMP(ssp, "command sent");
d920 2
d928 3
d935 1
d937 4
d966 6
a971 2
#if 0
			if (ssp->cmd_bytes_out < ssp->cmdlen)
d973 9
a981 1
			else {	/* This case should not happen. */
a984 9
#else
{int diff = ssp->cmdlen - ssp->cmd_bytes_out;
	if(diff > 0) {
		sfbyte(ss_dat, ssp->cmdbuf[ssp->cmd_bytes_out++]);
		if (diff == 1)
			ssdelay(1);
	}
}
#endif
d1008 1
d1046 1
d1081 1
a1081 1
SSDUMP((&rqs), "sense req");
d1107 1
a1107 1
SSDUMP(ssp, "inquiry");
d1141 1
a1141 1
SSDUMP(ssp, "read_cap");
d1144 41
@


1.13
log
@add retry logic to scsicmd(); general cleanup
@
text
@d12 3
d82 1
a82 1
#define HIPRI_RETRIES	100	/* # of times to retry while hogging CPU */
d88 1
d190 4
a194 2
static void	ssintr();

d235 1
a235 1
#define IN_BUF_SIZE	22
d240 1
d557 1
a557 1

d589 1
a589 4
	if (!testready(s_id))
		devmsg(dev, "Test Unit Ready failed");
	else {
		devmsg(dev, "Unit initialized");
d591 29
a619 2
	}
POPI;
d665 2
a666 14
		if (bus_pre_xfer(s_id)) {
			rqs.cmdbuf[0] = ScmdREQUESTSENSE;
			rqs.cmdbuf[1] = rqs.cmdbuf[2] = rqs.cmdbuf[3] =
				rqs.cmdbuf[5] = 0;
				rqs.cmdbuf[4] = SENSELEN;
			rqs.cmdlen = G0CMDLEN;
			rqs.in_buf_len = SENSELEN;
			bus_info_xfer(&rqs);
			if (rqs.data_bytes_in == SENSELEN
			&& (rqs.in_buf[2] & 0x0F) == 0x06
			&& rqs.in_buf[12] == 0x29)
				retval = (ssp->cmdlen == ssp->cmd_bytes_out);
		}
SSDUMP((&rqs), "sense req");
d668 1
d677 1
d848 1
d855 9
d887 1
d926 95
@


1.12
log
@Test Ready now works, including Req Sense
@
text
@d4 7
d12 3
d79 2
a80 1
#define BUS_RETRIES	1000
d109 2
a110 2
int stats[40], statsptr;
#define PUSHI		{ stats[statsptr++] = i; }
d118 1
a118 1
	printf(" %x", ssp->cmdbuf[i]);printf(" cmd_bytes_out=%d\n",\
d184 2
d203 1
d205 2
d505 6
d514 1
a514 1
	printf("ss IRPT\n");
d540 1
a540 1
	for ( i = 0; i < BUS_RETRIES; i++) {
d581 1
a581 3
#if DEBUG
devmsg(dev, "ssinit invoked");
#endif
d585 1
a585 1
		devmsg(dev, "Unit successfully initialized");
d588 1
d608 2
a609 6
#define XXXX
	if (1 || !(retval = scsicmd(s_id))) {
printf("First Test Unit Ready failed.  Will reset SCSI bus.\n");
		scsireset();
		retval = scsicmd(s_id);
	}
d626 1
a626 1
SSTELL("enter scsicmd\n");
d646 1
a647 1
		}
d655 3
a657 1
 * Assert reset for 1 clock tick.
d659 1
d663 1
a663 1
	ssdelay(50);
d665 1
a665 1
	ssdelay(50);
d682 30
d720 3
a722 6
	/*
	 * Do ST0x arbitration.
	 */
	sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
	sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
	sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */
d724 7
a730 2
	if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL))
		return 0;
d732 8
a739 5
	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);
d741 5
a745 2
	if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
		return 0;
d747 2
a748 4
	/*
	 * Send "Identify" Message with Disconnect allowed.
	 */
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);
d750 4
a753 3
	if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
	| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
		return 0;
d755 3
a757 2
	sfbyte(ss_csr, WC_ENABLE_SCSI);
	sfbyte(ss_dat, MSG_IDENT_DC);
d759 6
a764 1
	return 1;
d812 2
a813 1
			}
d829 4
d877 1
a877 1
	for ( i = 0; i < BUS_RETRIES; i++) {
d891 1
a891 1

a893 95

#define STUFF 0
/* pieces of code temporarily without a home */
#if STUFF
	for (i = 0; i < CMDLEN; i++) {
		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA));
		sfbyte(ss_dat, cmd[i]);
	}

	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_I_O));
	data1 = ffbyte(ss_dat);
	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE));
	data2 = ffbyte(ss_dat);
bus_wait(RS_BUSY << 8 | 0);
status = ffbyte(ss_csr);
SSTATUS;
printf("data1=%x data2=%x\n",data1,data2);
POPI;
	/*
	 * If there was a check condition on the previous commmand,
	 * do a Request Sense command.
	 */
	if (data1 & CS_CHECK) {
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

		bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL);

		/*
		 * Arbitration complete.  Now select, with ATN to allow messages.
		 */
		sfbyte(ss_dat, HOST_ID | 1);	/* Write two SCSI id's to port */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		bus_wait(RS_BUSY << 8 | RS_BUSY);

		/*
		 * Send "Identify" Message with Disconnect allowed.
		 */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE));

		sfbyte(ss_csr, WC_ENABLE_SCSI);
		sfbyte(ss_dat, MSG_IDENT_DC);

for (i = 0; i < CMDLEN; i++) cmd[i] = 0; /* send Request Sense command */
cmd[0] = 3;  cmd[4] = SENSELEN;

		for (i = 0; i < CMDLEN; i++) {
			bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
				(RS_REQUEST|RS_CTRL_DATA));
			sfbyte(ss_dat, cmd[i]);
		}

		for (inbytes = 0; inbytes < SENSELEN;  inbytes++) {
			if (bus_wait(
			((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_I_O)))
				sense[inbytes] = ffbyte(ss_dat);
			else
				break;
		}
		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA|RS_I_O));
		data1 = ffbyte(ss_dat);
		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE));
		data2 = ffbyte(ss_dat);
bus_wait(RS_BUSY << 8 | 0);
status = ffbyte(ss_csr);
SSTATUS;
printf("data1=%x data2=%x\n",data1,data2);
printf("%d:", inbytes);
for (i = 0; i < inbytes; i++) printf(" %x",sense[i]);
printf("\n");
POPI;
	}

#if 0
bus_wait(RS_REQUEST << 8 | RS_REQUEST);
#endif
	/*
	 * Initialize Drive Size.
	 */

	/*
	 * Initialize Drive Controller.
	 */
#endif
@


1.11
log
@has trouble with Test Ready using bus_info_xfer fsa
@
text
@d5 3
d73 1
d104 2
a105 2
#define SSDUMP(s_id, text) {int i;struct ss*ssp=ss[s_id];\
	printf("%s: s_id=%d msg_in=%x cmdstat=%x\n", text, s_id, ssp->msg_in,\
d117 1
a117 1
#define SSDUMP(s_id, text)
d226 1
a226 1
} *ss[MAX_SCSI_ID-1];
d289 1
a289 1
		} else {
a290 3
			printf("kalloc'ed %d bytes at offset %x\n",
				num_drives*sizeof(struct ss), ss_block);
		}
d587 2
a588 1
	if (!(retval = scsicmd(s_id))) {
d609 1
a609 1
SSDUMP(s_id, "enter scsicmd");
d611 1
a611 1
		bus_info_xfer(s_id);
d615 17
a631 1
SSDUMP(s_id, "leave scsicmd");
d643 1
a643 1
	ssdelay(1);
d645 1
d728 2
a729 2
static int bus_info_xfer(s_id)
int s_id;
a733 1
	struct ss * ssp = ss[s_id];
a741 1
SSTELL("MSG_IN\n");
a751 1
SSTELL("MSG_OUT\n");
d760 1
a760 3
SSTELL("STAT_IN\n");
			ssp->cmdstat = ffbyte(ss_csr);
goto foo;
a762 1
SSTELL("CMD_OUT\n");
a766 1
SSTELL("DATA_IN\n");
a778 1
SSTELL("DATA_OUT\n");
a787 1
foo:;
d821 1
a821 1
	if (!req_found)
@


1.10
log
@still more to do on bus_info_xfer
@
text
@d5 3
d68 3
a70 1
#define CMDLEN		6
d87 1
a87 1
#define XP_CMD_IN	(             RS_I_O | RS_CTRL_DATA)
d100 8
d113 1
d150 1
d164 1
d166 1
a166 1
static void	scsidelay();
d209 3
d213 9
a221 2
	long capacity;
	unsigned char do_xfer;	/* bitmapped flags;  1=xfer needed */
d224 1
a224 1
/**
d558 3
a560 1

a578 1
	unsigned char cmd[CMDLEN];
d580 1
d582 5
a586 3
	cmd[0] = ScmdTESTREADY;
	cmd[1] = cmd[2] = cmd[3] = cmd[4] = cmd[5] = 0;
	if (!(retval = scsicmd(s_id, cmd))) {
d589 1
a589 1
		retval = scsicmd(s_id, cmd);
d597 2
a598 1
 * Send 6-byte command packet to target device.
d602 1
a602 1
static int scsicmd(s_id, cmd)
a603 1
unsigned char *cmd;
d606 8
a613 3

	if (retval = bus_pre_xfer(s_id))
		retval = bus_info_xfer(cmd);
d625 1
a625 1
	scsidelay(1);
d630 1
a630 1
 * scsidelay()
d694 1
a694 1
 * Return 1 if command executed successfully, else 0.
d709 2
a710 3
static int bus_info_xfer(cmdbuf, cmdlen)
char * cmdbuf;
int cmdlen;
a711 1
	int ret;
d714 2
d717 3
d723 52
a774 14
			case XP_MSG_IN:
				break;
			case XP_MSG_OUT:
				break;
			case XP_CMD_IN:
				break;
			case XP_CMD_OUT:
				break;
			case XP_DATA_IN:
				break;
			case XP_DATA_OUT:
				break;
			default:
				break;
d777 2
a778 1
	return (cmdlen == 0);
@


1.9
log
@need to finish bus_info_xfer()
@
text
@d5 3
d75 12
d151 2
a152 2
static int	bus_pre_xfer(s_id);
static int	bus_info_xfer(s_id);
d664 8
a671 7
 *  if (BUSY false)
 *    break from while loop
 *  else
 *    switch (xfer phase = RS_CTRL_DATA|RS_I_O|RS_MESSAGE)
 *      case XP_MSG_IN/XP_MSG_OUT/...
 *        handle the indicated information transfer phase
 *    endswitch
d680 1
d683 17
a699 1
		
@


1.8
log
@started ssopen()/wrote stub for ssinit()
@
text
@d5 3
d62 1
d133 5
a137 1
static void	ssinit();
d152 3
a154 2
static int num_drives;
static struct ss *ss_block;		/* points to block of "ss" structs */
d180 1
a180 1
	char scsi_id;
d237 5
a241 1
		if ((ss_block = kalloc(num_drives*sizeof(struct ss))) == NULL) {
d244 5
a248 2
		} else
			kclear(ssblock, num_drives * sizeof(struct ss));
d251 1
a251 1
		struct ss *foo = ssblock;
d278 2
a279 1
	kfree(ssblock);
d382 1
a382 1
/**
d402 1
a402 1
/**
d425 1
a425 1
/**
d441 1
a441 1
/**
d458 2
a486 1
PUSHI;
d493 18
d512 1
a512 1
static void ssinit(s_id)
d515 10
d527 47
a573 8
#define STUFF 0
/* pieces of code temporarily without a home */
#if STUFF
#if 0
{ long x;
	/*
	 * Reset the SCSI bus.
	 */
d575 1
a575 1
	for (x=0; x<100000L; x++);
a576 1
	for (x=0; x<100000L; x++);
a577 1
#endif
d579 22
d608 2
a609 1
	bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL);
d614 1
a614 1
	sfbyte(ss_dat, HOST_ID | 1);	/* Write two SCSI id's to port */
d617 2
a618 1
	bus_wait(RS_BUSY << 8 | RS_BUSY);
d625 3
a627 2
	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE));
d629 1
a629 2
#ifdef SEND_ABORT_MESSAGE
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);
d632 2
a633 7
	/*
	 * Second message is Abort.
	 */
	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE));
	sfbyte(ss_csr, WC_ENABLE_SCSI);
	sfbyte(ss_dat, MSG_ABORT);
d635 29
a663 4
	bus_wait(RS_BUSY << 8 | RS_BUSY);
#else
	sfbyte(ss_csr, WC_ENABLE_SCSI);
	sfbyte(ss_dat, MSG_IDENT_DC);
d665 21
a685 1
for (i = 0; i < CMDLEN; i++) cmd[i] = 0; /* send Test Unit Ready command */
d687 23
a714 1
#endif
@


1.7
log
@Does Test Read and Request Sense properly.
@
text
@d5 3
d25 5
d68 2
a69 1
#if 1
d108 3
a110 2
int	SS_INT = 5;		/* ST01/ST02 use either IRQ3 or IRQ5 */
int	SS_BASE_SEG = 0xDE00;	/* Start of memory-mapped communication area */
d129 1
a130 1
static void	ssreset();
d144 3
d166 8
d185 1
a186 8
	char status;
	int await_bus;
	int data1, data2;
	int inbytes;
#define CMDLEN		6
#define SENSELEN	22
	unsigned char cmd[CMDLEN];
	unsigned char sense[SENSELEN];
d196 1
a196 1
	ss_base = (paddr_t)((long)(unsigned)SS_BASE_SEG << 4);
d215 2
a216 3
		return;
	} else
		printf("ST0x passed memory test\n");
a217 2
#if 0
{ long x;
d219 4
a222 1
	 * Reset the SCSI bus.
d224 12
a235 6
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
	for (x=0; x<100000L; x++);
	sfbyte(ss_csr, 0);
	for (x=0; x<100000L; x++);
}
#endif
d237 5
d243 1
a243 1
	 * Do ST0x arbitration.
d245 6
a250 3
	sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
	sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
	sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */
a251 130
	bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL);

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	sfbyte(ss_dat, HOST_ID | 1);	/* Write two SCSI id's to port */
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

	bus_wait(RS_BUSY << 8 | RS_BUSY);

	/*
	 * Send "Identify" Message with Disconnect allowed.
	 */
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE));

#ifdef SEND_ABORT_MESSAGE
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);
	sfbyte(ss_dat, MSG_IDENT_DC);

	/*
	 * Second message is Abort.
	 */
	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE));
	sfbyte(ss_csr, WC_ENABLE_SCSI);
	sfbyte(ss_dat, MSG_ABORT);

	bus_wait(RS_BUSY << 8 | RS_BUSY);
#else
	sfbyte(ss_csr, WC_ENABLE_SCSI);
	sfbyte(ss_dat, MSG_IDENT_DC);

for (i = 0; i < CMDLEN; i++) cmd[i] = 0; /* send Test Unit Ready command */

	for (i = 0; i < CMDLEN; i++) {
		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA));
		sfbyte(ss_dat, cmd[i]);
	}
#endif

	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_I_O));
	data1 = ffbyte(ss_dat);
	bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
		(RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE));
	data2 = ffbyte(ss_dat);
bus_wait(RS_BUSY << 8 | 0);
status = ffbyte(ss_csr);
SSTATUS;
printf("data1=%x data2=%x\n",data1,data2);
POPI;
	/*
	 * If there was a check condition on the previous commmand,
	 * do a Request Sense command.
	 */
	if (data1 & CS_CHECK) {
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

		bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL);

		/*
		 * Arbitration complete.  Now select, with ATN to allow messages.
		 */
		sfbyte(ss_dat, HOST_ID | 1);	/* Write two SCSI id's to port */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		bus_wait(RS_BUSY << 8 | RS_BUSY);

		/*
		 * Send "Identify" Message with Disconnect allowed.
		 */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE));

		sfbyte(ss_csr, WC_ENABLE_SCSI);
		sfbyte(ss_dat, MSG_IDENT_DC);

for (i = 0; i < CMDLEN; i++) cmd[i] = 0; /* send Request Sense command */
cmd[0] = 3;  cmd[4] = SENSELEN;

		for (i = 0; i < CMDLEN; i++) {
			bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
				(RS_REQUEST|RS_CTRL_DATA));
			sfbyte(ss_dat, cmd[i]);
		}

		for (inbytes = 0; inbytes < SENSELEN;  inbytes++) {
			if (bus_wait(
			((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_I_O)))
				sense[inbytes] = ffbyte(ss_dat);
			else
				break;
		}
		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA|RS_I_O));
		data1 = ffbyte(ss_dat);
		bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8) |
			(RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE));
		data2 = ffbyte(ss_dat);
bus_wait(RS_BUSY << 8 | 0);
status = ffbyte(ss_csr);
SSTATUS;
printf("data1=%x data2=%x\n",data1,data2);
printf("%d:", inbytes);
for (i = 0; i < inbytes; i++) printf(" %x",sense[i]);
printf("\n");
POPI;
	}

#if 0
bus_wait(RS_REQUEST << 8 | RS_REQUEST);
#endif
	/*
	 * Initialize Drive Size.
	 */

	/*
	 * Initialize Drive Controller.
	 */
}

d260 1
a260 1
	 * Release IRQ vector.
d262 1
a262 1
	clrivec(SS_INT);
d268 5
d275 1
a275 1
/**
a277 10
 * ssreset()	-- reset hard disk controller, define drive characteristics.
 */
static void
ssreset()
{
}

/**
 *
 * void
d292 51
d345 1
a345 1
/**
d471 161
@


1.6
log
@sends Test Ready, Starts to Request Sense
@
text
@d5 3
d168 3
a170 1
#define CMDLEN 6
d172 1
d205 1
a205 1
#if 1
d274 1
a274 1
bus_wait(RS_BUSY, 0);
d309 2
a310 2
for (i = 0; i < CMDLEN; i++) cmd[i] = 0; /* send Test Unit Ready command */
cmd[0] = 3;
d318 8
d332 1
a332 1
bus_wait(RS_BUSY, 0);
d336 3
@


1.5
log
@Now sends Identify and Abort messages & completes a SCSI bus cycle
@
text
@d5 3
d10 1
a10 1
 * 
d13 1
a13 1
 * 
d15 1
a15 1
 
d35 1
a35 1
 
d46 3
a48 1
#define BUS_RETRIES	10000
d50 7
a56 2
#define MSG_ABORT	0x06	/* Identify, with Disconnect allowed */
 
d58 4
d65 2
d73 1
a73 1
 */ 
d92 1
a92 1
 
d164 3
d171 2
a172 2
	setivec(SS_INT, ssintr); 
	
d198 1
a198 1
		
d208 1
a208 1
}	
d210 1
a210 1
	 
d213 1
a213 1
	 */	
d218 1
a218 10
	for ( i = 0, await_bus = 1; await_bus && i < BUS_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if (status & RS_ARBIT_COMPL) {
			await_bus = 0;
		}
	}
	if (await_bus) {
		printf("Error - ST0x doesn't complete arbitration\n");
		return;
	}
a224 11
	
	for ( i = 0, await_bus = 1; await_bus && i < BUS_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if (status & RS_BUSY) {
			await_bus = 0;
		}
	}
	if (await_bus) {
		printf("Error - ST0x drive doesn't assert BUSY\n");
		return;
	}
d226 2
d230 1
a230 1
	 */	
a231 11
	for ( i = 0, await_bus = 1; await_bus && i < BUS_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & (RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE)) ==
			(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)) {
			await_bus = 0;
		}
	}
	if (await_bus) {
		printf("Error - ST0x didn't enter MSG out\n");
		return;
	}
d233 4
d239 1
a239 1
	
d243 2
a244 11
	for ( i = 0, await_bus = 1; await_bus && i < BUS_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & (RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE)) ==
			(RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)) {
			await_bus = 0;
		}
	}
	if (await_bus) {
		printf("Error - ST0x didn't enter MSG out 2nd time\n");
		return;
	}
d248 62
a309 4
	for ( i = 0, await_bus = 1; await_bus && i < BUS_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & RS_BUSY) == 0) {
			await_bus = 0;
d311 12
d324 1
a324 4
	if (await_bus) {
		printf("Error - ST0x didn't go to Bus Free state\n");
		return;
	}
d326 2
a327 14
	for ( i = 0, await_bus = 1; await_bus && i < BUS_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if (status & RS_REQUEST) {
			await_bus = 0;
		}
	}
	if (await_bus) {
		printf("Error - ST0x didn't REQ after Identify msg\n");
		return;
	}
#endif	
SSTATUS;
printf("i=%d\n", i);
	
d347 2
a348 2
	clrivec(SS_INT); 
	 
d352 1
a352 1
	vrelse(ss_fp); 
d478 32
@


1.4
log
@tried to send Identify message - get status 0x40 & fail
@
text
@d5 3
d45 1
d49 1
d52 1
d186 1
a186 1
	for (x=0; x<1000000L; x++);
d188 3
a190 3
	for (x=0; x<1000000L; x++);
}
#endif	
d195 1
a195 1
	sfbyte(ss_csr, WC_ENABLE_PRTY);	/* De-assert SCSI enable bit */
d197 1
a197 1
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ARBITRATE);	/* Start arbitration */
d199 1
a199 1
	for ( i = 0, await_bus = 1; i < BUS_RETRIES; i++) {
a208 1
SSTELL("Arbitration complete\n");
d214 1
a214 1
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SELECT | WC_ENABLE_PRTY);
d216 1
a216 1
	for ( i = 0, await_bus = 1; i < BUS_RETRIES; i++) {
d230 2
a231 2
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);
	for ( i = 0, await_bus = 1; i < BUS_RETRIES; i++) {
d233 1
a233 1
		if (status & (RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) ==
a236 2
		if (status & (RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE))
			break;
a237 1
SSTELL("status=%x\n");	
a241 1
SSTELL("MSG out phase entered.\n");
d243 1
a243 1
	sfbyte(ss_csr, WC_ENABLE_PRTY | WC_ENABLE_SCSI);
d245 17
a261 1
SSTELL("Identify MSG sent\n");
d263 1
a263 1
	for ( i = 0, await_bus = 1; i < BUS_RETRIES; i++) {
d265 11
a279 1
SSTELL("status=%x\n");	
d284 3
a286 1
SSTELL("REQ hanging\n");
@


1.3
log
@Goes thru arbitration (sans IRQ) successfully
@
text
@d4 4
a7 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d40 2
a41 1
#define BUS_RETRIES	100
d43 6
d173 3
d177 11
a187 3
	 * Check out Bus Stuff.
	 *
	 * First, do ST0x arbitration.
d189 1
a189 1
	sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
d191 1
a191 1
	sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */
d203 7
a210 3
	sfbyte(ss_dat, HOST_ID | 1);	/* Write two SCSI id's to port */
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SELECT);
	
d220 1
a220 2
	} else
		printf("Arbitration phase succeeded.\n");
d223 37
@


1.2
log
@Loads ok, tests Parameter RAM ok.
@
text
@d4 1
d17 9
d27 12
d55 1
d129 4
d163 8
d172 26
d342 1
@


1.1
log
@Skeleton - just allocates selector and grabs IRQ
@
text
@d21 4
a24 3
#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
d27 1
a27 1
#include	<sys/uproc.h>
a28 1
#include	<devices.h>		/* SCSI_MAJOR */
d30 4
d42 1
a42 1
int	SS_BASE_SEG = 0xDC00	/* Start of memory-mapped communication area */
d91 2
a92 1
	ssunload			/* Unload */
d114 1
a114 1
	ss_base = (paddr_t)SS_BASE_SEG << 4;
d122 16
d282 4
@
0707070064030104141004440000030000030000011777770507310660100006100000205103/newbits/kernel/USRSRC/i8086/drv/RCS/ss21_35.c,vhead     1.35;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.35
date     91.04.20.01.35.52;  author root;  state Exp;
branches ;
next	1.34;

1.34
date     91.04.19.09.41.40;  author root;  state Exp;
branches ;
next	1.33;

1.33
date     91.04.17.14.15.48;  author root;  state Exp;
branches ;
next	1.32;

1.32
date     91.04.17.04.07.21;  author root;  state Exp;
branches ;
next	1.31;

1.31
date     91.04.17.03.16.33;  author root;  state Exp;
branches ;
next	1.30;

1.30
date     91.04.17.02.17.43;  author root;  state Exp;
branches ;
next	1.29;

1.29
date     91.04.16.22.40.19;  author root;  state Exp;
branches ;
next	1.28;

1.28
date     91.04.16.20.48.47;  author root;  state Exp;
branches ;
next	1.27;

1.27
date     91.04.16.16.38.47;  author root;  state Exp;
branches ;
next	1.26;

1.26
date     91.04.16.16.13.10;  author root;  state Exp;
branches ;
next	1.25;

1.25
date     91.04.16.01.45.35;  author root;  state Exp;
branches ;
next	1.24;

1.24
date     91.04.12.17.19.25;  author root;  state Exp;
branches ;
next	1.23;

1.23
date     91.04.11.12.51.50;  author root;  state Exp;
branches ;
next	1.22;

1.22
date     91.04.10.16.55.59;  author root;  state Exp;
branches ;
next	1.21;

1.21
date     91.04.10.15.21.41;  author root;  state Exp;
branches ;
next	1.20;

1.20
date     91.04.09.14.23.49;  author root;  state Exp;
branches ;
next	;


desc
@Seagate ST01/ST02 hard disk SCSI device driver.
@


1.35
log
@ssinit() - improved error recovery.
@
text
@#define MAXSSERR 3
static int sserrct;
/*
 * This is a driver for Seagate ST01/ST02 scsi host adapters.
 *
 * To do:
 * 1.	fix ss_rw() error recovery
 * 2.	reduce number of ss_rw() write errors
 * 3.	figure out what to do about drive parameters (HDGETA)
 * 4.	bootable driver, without/with "at" device(s)
 * 5.	rewrite data_in/data_out transfer phases in assembler
 * 6.	investigate queueing - see if sorting requests will help
 * 7.	use different queues for different SCSI id's
 * 8.	look into kernel for mystery of lost EOI's on IRQ 5.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.34	91/04/19  09:41:40	root
 * Better error recovery, but needs work.
 * 
 * Revision 1.33	91/04/17  14:15:48	root
 * Starting to fix retry mechanism on ss_rw().
 * 
 * Revision 1.32	91/04/17  04:07:21	root
 * Accesses file system but has frequent BFERR 5's.
 * 
 * Revision 1.31	91/04/17  03:16:33	root
 * Now fdisk command works but mkfs fails.
 * 
 * Revision 1.30	91/04/17  02:17:43	root
 * Trying to figure out disconnect after write.
 * 
 * Revision 1.29	91/04/16  22:40:19	root
 * Whole disk devices working - need to implement HDGETA.
 * 
 * Revision 1.28	91/04/16  20:48:47	root
 * Kernel fdisk works, fdisk command gets garbage.
 * 
 * Revision 1.27	91/04/16  16:38:47	root
 * Typos fixed.  Locks up CPU on first open
 * 
 * Revision 1.26	91/04/16  16:13:10	root
 * First clean compile with block routine.
 * 
 * Revision 1.25	91/04/16  01:45:35	root
 * lots of strategy code added - but not ready to compile
 * 
 * Revision 1.24	91/04/12  17:19:25	root
 * Some rearrangements - still working on block & related routines
 * 
 * Revision 1.23	91/04/11  12:51:50	root
 * ssopen compiles - not tested
 * 
 * Revision 1.22	91/04/10  16:55:59	root
 * Starting to get block operations working.
 * 
 * Revision 1.21	91/04/10  15:21:41	root
 * Move define's to ss.h and scsiwork.h.  Other cleanup
 * 
 * Revision 1.20	91/04/09  14:23:49	root
 * Reads boot sector 100 times using IRQ on reconnect
 */

/*
 * Includes.
 */
#include	<coherent.h>
#include	<sys/io.h>
#include	<sys/sched.h>
#include	<sys/uproc.h>
#include	<sys/proc.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/devices.h>		/* SCSI_MAJOR */
#include	<errno.h>

#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<scsiwork.h>
#include	<ss.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */
#define DEV_SCSI_ID(dev)	((dev >> 4) & 0x0007)
#define DEV_LUN(dev)		((dev >> 2) & 0x0003)
#define DEV_DRIVE(dev)		((dev >> 2) & 0x001F)
#define DEV_PARTN(dev)		(dev & 0x0003)
#define DEV_SPECIAL(dev)	(dev & 0x0080)

#define HOST_ID		0x80	/* Host adapter is SCSI ID #7 */
#define HIPRI_RETRIES	400	/* # of times to retry while hogging CPU */
#define LOPRI_RETRIES	5	/* # of retries with sleep between tries */
#define WHOLE_DRIVE	NPARTN
#define WATCHDOG_SECONDS  4

#define IN_BUF_SIZE	512	/* buffer size in "ss" structs */

#define DEBUG	1
#if DEBUG
int stats[100], statsptr;
#define PUSHI		{ if(statsptr<100)stats[statsptr++] = i; }
#define POPI		{ if(sserrct<=MAXSSERR)printf("%d:",statsptr);while(statsptr)\
				if(sserrct<=MAXSSERR)printf("%d ",stats[--statsptr]);if(sserrct<=MAXSSERR)printf("\n");}
#define SSTELL(foo)	if(sserrct<=MAXSSERR)printf(foo)
#define SSTATUS		{uchar status = ffbyte(ss_csr);if(sserrct<=MAXSSERR)printf("status=%x\n", status);}
#define SSDUMP(ssp, text) {int i;\
	if(sserrct<=MAXSSERR)printf("%s: msg_in=%x cmdstat=%x\n", text, ssp->msg_in,\
	ssp->cmdstat);if(ssp->cmdlen)for(i=0;i<ssp->cmdlen;i++)\
	if(sserrct<=MAXSSERR)printf(" %x", ssp->cmdbuf[i]);if(sserrct<=MAXSSERR)printf(" cmd_bytes_out=%d",\
	ssp->cmd_bytes_out);\
	if(ssp->data_bytes_in)for(i=0;i<ssp->data_bytes_in;i++)\
	if(sserrct<=MAXSSERR)printf(" %x", ffbyte(ssp->in_buf+i));if(sserrct<=MAXSSERR)printf(" data_bytes_in=%d\n",\
	ssp->data_bytes_in);}
#else
#define PUSHI
#define POPI
#define SSTELL(foo)
#define SSTATUS
#define SSDUMP(ssp, text)
#endif

typedef unsigned char	uchar;
typedef unsigned long	ulong;
typedef struct ss {
	ulong	capacity;
	ulong	blocklen;
	ulong	bno;
	int	msg_in;
	int	dr_watch;	/* number of seconds for pending timeout */
	uchar	cmdbuf[G1CMDLEN];
	int	cmdlen;
	int	cmd_bytes_out;
	int	cmdstat;
	faddr_t	in_buf;
	int	in_buf_len;
	int	data_bytes_in;
	faddr_t	out_buf;
	int	out_buf_len;
	int	data_bytes_out;
	BUF	*bp;		/* current I/O request node, or NULL */
	struct	fdisk_s parmp[NPARTN+1];
	unsigned int	ptab_read:1;  /* 1 if partition table has been read */
	unsigned int	id_busy:1;  /* 1 if device with this SCSI id busy */
}	ss_type;

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
extern int	nulldev();
extern int	nonedev();
extern unsigned char ffbyte();

static void	ssopen();		/* CON functions */
static void	ssclose();
static void	ssblock();
static void	ssread();
static void	sswrite();
static int	ssioctl();
static void	sswatch();
static void	ssload();
static void	ssunload();

static int	bus_dev_reset();	/* additional support functions */
static int	bus_info_xfer();
static int	bus_pre_xfer();
static int	chk_reconn();
static int	inquiry();
static int	mode_sense();
static int	read_cap();
static void	reconnect();
static int	req_sense();
static int	rezero();
static int	scsicmd();
static void	scsireset();
static void	ss_done();
static int	ss_rw();
static void	ss_start();
static void	ss_start_timing();
static void	ss_stop_timing();
static void	ssdelay();
static int	ssinit();
static void	ssintr();
static int	testready();

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
CON	sscon	= {
	DFBLK|DFCHR,			/* Flags */
	SCSI_MAJOR,			/* Major index */
	ssopen,				/* Open */
	ssclose,			/* Close */
	ssblock,			/* Block */
	ssread,				/* Read */
	sswrite,			/* Write */
	ssioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	sswatch,			/* Timeout */
	ssload,				/* Load */
	ssunload,			/* Unload */
	nulldev				/* Poll */
};

	/* Patch these Export Variables to configure the driver. */
int	NSDRIVE = 1;		/* Bitmap of attached SCSI drives. */
int	SS_INT = 5;		/* ST0[12] use either IRQ3 or IRQ5 */
int	SS_BASE = 0xDE00;	/* Segment addr of ST0x communication area */

static int	loading;	/* 1 ssload() is executing */
static BUF	dbuf;		/* For raw I/O */
static paddr_t	ss_base;	/* physical address of ST0x comm area */
static faddr_t	ss_fp;		/* (far *) to ST0x comm area */

static faddr_t	ss_ram;		/* (far *) to parameter RAM */
static faddr_t	ss_csr;		/* (far *) to control/status */
static faddr_t	ss_dat;		/* (far *) to data port */

static int	num_drives;	/* number of controller SCSI id's */
static ss_type *ss_tbl;		/* points to block of "ss" structs */
static int	st0x_busy;	/* 1 if SCSI host adapter busy */

static TIM	delay_tim;	/* needed for calls to ssdelay() */
static TIM	reset_tim;	/* needed for calls to scsireset() */
static TIM	timeout_tim;	/* needed for calls to timeout() */
static TIM	sst_tim;	/* for timeout() call from ss_start() */
static int	ss_expired;	/* 1 after local timeout */
static ss_type  *ss[MAX_SCSI_ID-1], rqs;

/*
 * ssload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void ssload()
{
	int erf = 0;  /* 1 if error occurs */
	int i;
	loading = 1;

	/*
	 * Claim IRQ vector.
	 */
	setivec(SS_INT, ssintr);

	/*
	 * Allocate a selector to map into ST0x memory-mapped comm area.
	 */
	ss_base = (paddr_t)((long)(unsigned)SS_BASE << 4);
	ss_fp = ptov(ss_base, (fsize_t)SS_SEL_LEN);

	ss_ram = ss_fp + SS_RAM;
	ss_csr = ss_fp + SS_CSR;
	ss_dat = ss_fp + SS_DAT;

	/*
	 * Primitive test of ST0x RAM.
	 */
	sfword(ss_ram, 0xA55A);
	sfword(ss_ram + 2, 0x3CC3);
	sfword(ss_ram + SS_RAM_LEN - 4, 0xA55A);
	sfword(ss_ram + SS_RAM_LEN - 2, 0x3CC3);
	if (ffword(ss_ram) != 0xA55A		/* fetch a "far" word */
	||  ffword(ss_ram + 2) != 0x3CC3
	||  ffword(ss_ram + SS_RAM_LEN - 4) != 0xA55A
	||  ffword(ss_ram + SS_RAM_LEN - 2) != 0x3CC3) {
		printf("Error - ST0x failed memory test\n");
		erf = 1;
	}

	/*
	 * Allocate drive structs.
	 *
	 * Do a single call to kalloc() then put allocated pieces into
	 * array ss.
	 */
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				num_drives++;
		if (num_drives == 0) {
			printf("Error - ss has no valid target id's\n");
			erf = 1;
		} else if ((ss_tbl = kalloc(num_drives*sizeof(ss_type)))
		== NULL) {
			printf("Error - ss can't allocate structs\n");
			erf = 1;
		} else
			kclear(ss_tbl, num_drives * sizeof(ss_type));
	}
	if (!erf) {
		ss_type *foo = ss_tbl;

		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				ss[i] = foo++;
	}

	/*
	 * Initialize drives we know about (i.e. in NSDRIVE bitmap).
	 */
	st0x_busy++;
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				ssinit(i);
	}
	st0x_busy--;
	loading = 0;
}

/*
 * ssunload()	- unload routine.
 */
static void ssunload()
{
	/*
	 * Deallocate driver heap space.
	 */
	if (ss_tbl)
		kfree(ss_tbl);

	/*
	 * Free the ST0x selector.
	 */
	vrelse(ss_fp);

	/*
	 * Release IRQ vector.
	 */
	clrivec(SS_INT);
}

/*
 * ssopen()
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void ssopen(dev, mode)
register dev_t	dev;
{
	int drive, partn;
	int valid_open;
	struct	fdisk_s	*fdp;
	ss_type * ssp;
	int s_id;

	/*
	 * Set up local variables.
	 */
	valid_open = 1;
	drive = DEV_SCSI_ID(dev);
	partn = DEV_PARTN(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;
devmsg(dev, "ssopen");
	/*
	 * LUN must be zero.
	 * SCSI id must have corresponding 1 in NSDRIVE bitmapped variable.
	 */
	if (DEV_LUN(dev) != 0 || ((1 << drive) & NSDRIVE) == 0) {
		u.u_error = ENXIO;
		valid_open = 0;
	}

	/*
	 * If "special" bit is set, partition field must be zero.
	 */
	if (valid_open && DEV_SPECIAL(dev) && partn != 0) {
		u.u_error = ENXIO;
		valid_open = 0;
	}

	/*
	 * Subscripting gimmick for partition table.
	 */
	if (valid_open && dev & SDEV)
		partn = WHOLE_DRIVE;
	/*
	 * If not accessing whole drive and the partition table has not
	 * been read yet, try to read it now.
	 * Do this by calling fdisk() with partition table device on the drive
	 * that is being accessed.
	 */
	if (valid_open && partn != WHOLE_DRIVE && !(ssp->ptab_read)) {
		int fdisk_dev;

		fdisk_dev = (dev | SDEV) & 0xfff0;
devmsg(fdisk_dev, "calling fdisk");
		if (fdisk(fdisk_dev, fdp)) {
int p;
			fdp[WHOLE_DRIVE].p_size = ssp->capacity;
			fdp[WHOLE_DRIVE].p_base = 0;
printf("fdisk() succeeded\n");
for (p=0; p<=WHOLE_DRIVE; p++)
	printf("p=%d base=%ld size=%ld\n", p, fdp[p].p_base, fdp[p].p_size);
			ssp->ptab_read = 1;
		} else {
printf("fdisk() failed\n");
			u.u_error = ENXIO;
			valid_open = 0;
		}
	}

	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	if (valid_open && partn != WHOLE_DRIVE
	&& (fdp[partn].p_base+fdp[partn].p_size) > fdp[WHOLE_DRIVE].p_size) {
		u.u_error = EBADFMT;
		valid_open = 0;
	}

	if (valid_open && partn != WHOLE_DRIVE && fdp[partn].p_size == 0) {
		u.u_error = ENODEV;
		valid_open = 0;
	}

	/*
	 * OK to open the device.
	 * Start watchdog timer (if not already started) for the host adapter.
	 */
	if (valid_open) {
		++drvl[SCSI_MAJOR].d_time;
	}
}

/*
 * ssclose()
 */
static void ssclose(dev)
dev_t dev;
{
	/*
	 * Decrement the number of watchdog timer requests open for host board.
	 */
	--drvl[SCSI_MAJOR].d_time;	
devmsg(dev, "ssclose");
}

/*
 * ssread()	- read a block from the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void ssread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
}

/*
 * sswrite()	- write a block to the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void sswrite(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
}

/*
 * ssioctl()
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
#define NHEAD	4
#define NSEC	52
#define NCYL	1004

static int ssioctl(dev, cmd, vec)
register dev_t	dev;
int cmd;
char * vec;
{
	int ret = 0;
	hdparm_t hdparm;
	struct	fdisk_s	*fdp;
	int s_id;
	ss_type * ssp;

	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;

	switch(cmd) {
	case HDGETA:
printf("HDGETA ");
		fdp = ssp->parmp;
		*(short *)&hdparm.landc[0] =
		*(short *)&hdparm.ncyl[0] = NCYL;
		hdparm.nhead = NHEAD;
		hdparm.nspt = NSEC;
printf("ncyl=%d nhead=%d nspt=%d\n",
  hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt);
		kucopy( &hdparm, vec, sizeof hdparm );
		ret = 0;
		break;
	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * ssblock()	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void ssblock(bp)
register BUF	*bp;
{
	register int s;
	struct	fdisk_s	*fdp;
	int partition, drive, s_id;
	dev_t dev;
	ss_type * ssp;
	int valid_op = 1;

	bp->b_resid = bp->b_count;

	/*
	 * Set up local variables.
	 */
	dev = bp->b_dev;
	partition = DEV_PARTN(dev);
	drive = DEV_DRIVE(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	if (dev & SDEV)
		partition = WHOLE_DRIVE;
	fdp = ssp->parmp;

	/*
	 * Range check disk region.
	 */
	if (!(ssp->ptab_read)) {
		if ( partition == WHOLE_DRIVE ) {
			if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
{if(sserrct<=MAXSSERR)printf("BF1 ");}
				bp->b_flag |= BFERR;
				valid_op = 0;
			}
		} else {
{if(sserrct<=MAXSSERR)printf("BF2 ");}
			devmsg(dev, "no partition table");
			bp->b_flag |= BFERR;
			valid_op = 0;
		}
	}
	/*
	 * Check for read at end of partition.
	 * (Need to return with b_resid = BSIZE to signal end of volume.)
	 */
	else if ((bp->b_req == BREAD) && (bp->b_bno == fdp[partition].p_size)) {
		valid_op = 0;
	}
	/*
	 * Check for read past end of partition.
	 */
	else if ( (bp->b_bno + (bp->b_count/BSIZE))
	> fdp[partition].p_size ) {
{if(sserrct<=MAXSSERR)printf("BF3 ");}
		bp->b_flag |= BFERR;
		valid_op = 0;
	}

	/*
	 * Operation appears valid.
	 * Fill fields in the node and queue the request.
	 */
	if (valid_op) {

/* if(sserrct<=MAXSSERR)printf("ssblock: drv=%x bno=%lx bp=%x flag=%x\n",
	drive, bp->b_bno, bp, bp->b_flag); */

		ssq_wr_tail(bp);
		ss_start();
	/*
	 * Operation cannot be done.  Release the kernel buffer structure.
	 * Value of "bp->b_flag" tells caller if error occurred.
	 */
	} else { 	/* "valid_op" is FALSE */
		bdone(bp);
	}
}

/*
 * ssintr()	- Interrupt routine.
 *
 * If we have been reselected by a recognized target device
 *	let kernel get out of interrupt mode (defer) and do SCSI
 *	reconnect stuff.
 */
static void ssintr()
{
	int s_id;

	s_id = chk_reconn();
	if (s_id != -1)
		reconnect(s_id);
/*		defer(reconnect, s_id); */
}

/*
 * sswatch()
 *
 * Invoked once per second if any devices going through this driver are open.
 * Poll for any reselect, in case interrupt got lost.
 */
static void sswatch()
{
	int s_id, rs_id;
	ss_type * ssp;

	for (s_id = 0; s_id < MAX_SCSI_ID-1; s_id++) {
		ssp = ss[s_id];
		if (ssp && ssp->dr_watch) {
			ssp->dr_watch--;
			if (ssp->dr_watch == 0) {
{if(sserrct<=MAXSSERR)printf("BF4 ");}
				bus_dev_reset(s_id);
				ssp->bp->b_flag |= BFERR;
{if(sserrct<=MAXSSERR)printf("SCSI id #%d: bno=%lu <Watchdog Timeout>\n", s_id, ss[s_id]->bp->b_bno);}
				ss_done(s_id);
			} else {
				while (1) {
					rs_id = chk_reconn();
					if (rs_id == -1)
						break;
					else
						reconnect(rs_id);
				} /* endwhile */
			}
		}
	} /* endfor */
}

/*
 * bus_wait()
 *
 * Wait for specified bit values to appear in Status Register.
 * This uses a tight loop and does not expect to be interrupted.
 *
 * Argument "flags" is a double-byte value;  the high byte is ANDed with
 * status register contents, and the result is tested for equality with
 * the low byte.
 *
 * Return 1 if values wanted appeared, 0 if timeout occurred.
 */
static int bus_wait(flags)
unsigned short flags;
{
	int found, i;
	unsigned char status;

	found = 0;
	for ( i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & (flags >> 8)) == (flags & 0xff)) {
			found = 1;
			break;
		}
	}

	if (!found)
		{if(sserrct<=MAXSSERR)printf("TO:f=%x s=%x ", flags, status);}

	return found;
}

/*
 * ssinit()
 *
 * Attempt to initialize the (unique) drive with a given SCSI id.
 * Assume only one drive per SCSI id, having LUN = 0.
 * 
 * Return 1 if success, 0 if failure.
 */
static int ssinit(s_id)
int s_id;
{
	int try;
	int retval = 0;
	uchar query_buf[MODESENSELEN];
	ss_type * ssp = ss[s_id];
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

/*FOO*/
bus_dev_reset(s_id);
	/*
	 * Try Test Unit Ready command.
	 * If it fails, reset SCSI bus and target device, and try again.
	 */
printf("T");
	for (try = 0; !retval && try < LOPRI_RETRIES; try++) {
		if (testready(s_id))
			retval = 1;
		else {
printf("X");
			if (ssp->cmdstat == CS_BUSY)
				ssdelay(50);
			else if (ssp->cmdstat == CS_CHECK)
				req_sense(s_id);
			else if (s_id == chk_reconn())
			{
printf("-r-");
				ssdelay(50);
			}
			else
				scsireset();
		}
#if 0
		scsireset();
		bus_dev_reset(s_id);
#endif
	} /* endfor */
	if (!retval)
		devmsg(dev, "Test Unit Ready Failed");

printf("R");
	if (retval)
		if (req_sense(s_id)) {
			retval = 1;
		} else
			devmsg(dev, "Request Sense Failed");

	if (retval)
		if (inquiry(s_id, query_buf)) {
			query_buf[INQUIRYLEN] = 0;
			devmsg(dev, query_buf + 8);
			if (query_buf[0] == 0) {
				retval = 1;
			} else
				devmsg(dev, "Not Direct Access Device");
		} else
			devmsg(dev, "Inquiry Failed");

	if (retval)
		if (read_cap(s_id, query_buf)) {
			retval = 1;
			ssp->capacity = query_buf[3] | (query_buf[2] << 8)
			| (((long)(query_buf[1])) << 16)
			| (((long)(query_buf[0])) << 24);
			ssp->blocklen = query_buf[7] | (query_buf[6] << 8)
			| (((long)(query_buf[5])) << 16)
			| (((long)(query_buf[4])) << 24);
printf("capacity=%ld   block length=%ld\n", ssp->capacity, ssp->blocklen);
		} else
			devmsg(dev, "Read Capacity Failed");

	if (retval)
		if (mode_sense(s_id, query_buf)) {
#define FMT_PG	(4+8+8+12)
#define DDG_PG	(4+8+8+12+24)
			uchar heads;
			unsigned short spt;
			ulong cyls;
spt=((int)query_buf[FMT_PG+10]<<8) + query_buf[FMT_PG+11];
cyls=((int)query_buf[DDG_PG+2]<<16) + ((int)query_buf[DDG_PG+3]<<8) + query_buf[DDG_PG+4];
heads=query_buf[DDG_PG+5];
printf("%d sectors per track\n", spt);
printf("%ld cylinders\n", cyls);
printf("%d heads\n", heads);
		} else
			devmsg(dev, "Mode Sense Failed");

ssp->id_busy=0;
	return retval;
}

/*
 * testready()
 *
 * Send Test Unit Ready command.
 * Retry after bus reset if necessary.
 *
 * Return 1 if unit is ready, 0 if not.
 */
static int testready(s_id)
int s_id;
{
	int retval;
	ss_type * ssp = ss[s_id];

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->cmdbuf[0] = ScmdTESTREADY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] =
		ssp->cmdbuf[5] = 0;
	ssp->cmdlen = G0CMDLEN;
	retval = scsicmd(s_id);

	return retval;
}

/*
 * scsicmd()
 *
 * Send command packet to target device.
 * Start a new SCSI bus cycle when this routine is called.
 * If command status after sending is Device Check (CS_CHECK), do a
 * Request Sense to find out what happened and clear check status.
 *
 * Return 1 if command was send and status was good, else 0.
 */
static int scsicmd(s_id)
int s_id;
{
	int retval;
	ss_type *ssp = ss[s_id];

	if (retval = bus_pre_xfer(s_id)) {
		bus_info_xfer(ssp);
		retval = (ssp->cmdlen == ssp->cmd_bytes_out
			&& ssp->cmdstat == CS_GOOD);
	}

	if (ssp->cmdstat == CS_CHECK) {
		if (req_sense(s_id))
			retval = (ssp->cmdlen == ssp->cmd_bytes_out);
	}

	return retval;
}

/*
 * scsireset()
 *
 * Reset the SCSI bus.
 *
 * Allow settling time when turning reset on/off.
 * Settling times were determined empirically.
 * Each tick is 10 msec.
 *
 * If called while ssload() is running, don't return until reset is complete.
 * If called after ssload(), start up state machine and return.
 *
 * Either way, mark host adapter busy until reset completes.
 */
#define RESET_TICKS	40
static void scsireset()
{
	static int reset_state;

printf("!");
	/*
	 * During load, it's ok to do sleep() calls for reset settling.
	 * After load is finished, use timeout() to accomplish this.
	 */
	if (loading) {
		st0x_busy++;
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
		ssdelay(RESET_TICKS);
		sfbyte(ss_csr, 0);
		ssdelay(RESET_TICKS);
		st0x_busy--;
	} else {
		switch(reset_state) {
		case 0:
			st0x_busy++;
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
			timeout(&reset_tim, RESET_TICKS, scsireset, 0);
			reset_state = 1;
			break;
		case 1:
			sfbyte(ss_csr, 0);
			timeout(&reset_tim, RESET_TICKS, scsireset, 0);
			reset_state = 2;
			break;
		case 2:
			st0x_busy--;
			reset_state = 0;
			break;
		}
	}
}

/*
 * ssdelay()
 *
 * Delay for some number of clock ticks.
 * 286/386 kernel ticks are at 100Hz
 */
static void ssdelay(ticks)
int ticks;
{
	timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
}

/*
 * ss_start_timing()
 *
 * Start a timeout for some number of ticks.
 * Caller knows timer has expired when "ss_expired" goes to 1.
 *
 * Sample invocation:
 *	ss_start_timing(n);
 *	while (check for desired event fails) {
 *		if (ss_expired) {
 *			...failure stuff..
 *			break;
 *		}
 *		ssdelay(m); <= needed to allow kernel to update timers
 *	}
 */
static void ss_start_timing(ticks)
int ticks;
{
	ss_expired = 0;
	timeout(&timeout_tim, ticks, ss_stop_timing, 1);
}

/*
 * ss_stop_timing()
 *
 * Stub function called only by ss_start_timing()
 */
static void ss_stop_timing(flagval)
int flagval;
{
	ss_expired = flagval;
}

/*
 * bus_pre_xfer()
 *
 * Do bus cycle phases prior to the information transfer phases.
 * This includes arbitration and selection.
 */
static int bus_pre_xfer(s_id)
int s_id;
{
	int tries;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));
	int ret = 0;

	for (tries = 0; !ret && tries < LOPRI_RETRIES; tries++) {
if (tries>0)break;
		/*
		 * Do ST0x arbitration.
		 */
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

		/*
		 * SCSI spec says there is "no maximum" to the wait for arbitration
		 * complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			if (ffbyte(ss_csr) & (RS_REQUEST|RS_BUSY))
				ret = 1;
			continue;
		}

		/*
		 * Arbitration complete.  Now select, with ATN to allow messages.
		 */
		sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			continue;

		/*
		 * Send "Identify" Message with Disconnect allowed.
		 */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			continue;

		/*
		 * During ssload(), diagnostics are running and we don't
		 * want disconnects.  At other times, disconnect is ok.
		 */
		if (loading)
			sfbyte(ss_dat, MSG_IDENTIFY);
		else
			sfbyte(ss_dat, MSG_IDENT_DC);
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ENABLE_IRPT);
		ret = 1;
	}

	return ret;
}

/*
 * bus_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * This includes message in/out, command in/out, and data in/out.
 *
 * If cmdlen is nonzero, cmdbuf is an array of bytes of that length,
 * to be sent to the target.
 *
 * Return 1 if bus timeout did not occur, else 0.
 *
 * pseudocode:
 *
 * while (wait for REQ true or BUSY false on SCSI bus)
 *   if (BUSY false)
 *     break from while loop
 *   else
 *     switch (xfer phase = RS_CTRL_DATA|RS_I_O|RS_MESSAGE)
 *       case XP_MSG_IN/XP_MSG_OUT/...
 *         handle the indicated information transfer phase
 *     endswitch
 *   endif
 * endwhile
 */
static int bus_info_xfer(ssp)
ss_type *ssp;
{
	int bus_timeout;
	uchar phase_type;
	uchar msg_in;
	int no_msg_rcvd = 1;
	int s;
	int bytes_to_send;
int we_wrote=0;

	ssp->cmd_bytes_out = 0;
	ssp->msg_in = -1;
	s = sphi();
	while(req_wait(&bus_timeout)) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		switch (phase_type) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_IRPT);
				break;
			case MSG_SAVE_DPTR:
				break;
			case MSG_RSTOR_DPTR:
				break;
			case MSG_DISCONNECT:
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_IRPT);
				break;
			case MSG_ABORT:
				break;
			case MSG_DEV_RESET:
				break;
			case MSG_IDENTIFY:
				break;
			case MSG_IDENT_DC:
				break;
			}
			break;
		case XP_MSG_OUT:
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.  Abort the bus cycle.
			 */
			sfbyte(ss_csr, WC_ENABLE_SCSI);
			sfbyte(ss_dat, MSG_ABORT); 
			break;
		case XP_STAT_IN:
			ssp->cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 * Reset SCSI bus if too many command bytes are wanted.
			 */
			bytes_to_send = ssp->cmdlen - ssp->cmd_bytes_out;
			if(bytes_to_send > 0) {
				sfbyte(ss_dat, ssp->cmdbuf[ssp->cmd_bytes_out++]);
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (bytes_to_send == 1) {
					spl(s);
					s = sphi();
				}
			} else {	/* This case should not happen. */
SSDUMP(ssp, "Command overrun");
				scsireset();
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.  Else toss it.
			 */
			if (ssp->data_bytes_in < ssp->in_buf_len && ssp->in_buf) {
				uchar dat;

				dat = ffbyte(ss_dat);
				sfbyte(ssp->in_buf + ssp->data_bytes_in, dat);
				ssp->data_bytes_in++;
			} else
				ffbyte(ss_dat);
			break;
		case XP_DATA_OUT:
#if 0
if (!we_wrote) {
	we_wrote=1;
	{if(sserrct<=MAXSSERR)printf("W");}
}
#endif
			/*
			 * Copy output buffer bytes to data register.
			 */
			if (ssp->data_bytes_out < ssp->out_buf_len && ssp->out_buf) {
				uchar dat;

				dat = ffbyte(ssp->out_buf + ssp->data_bytes_out);
				sfbyte(ss_dat, dat);
				ssp->data_bytes_out++;
			} else { /* This case should not happen. */
SSDUMP(ssp, "Data out overrun");
				scsireset();
			}
			break;
		default:
			break;
		} /* endswitch */
	}
	spl(s);
switch(ssp->cmdstat) {
case -1:
	break;
case CS_GOOD:
	break;
case CS_CHECK:
	{if(sserrct<=MAXSSERR)printf("CSK",ssp->cmdstat);}
	break;
case CS_BUSY:
	{if(sserrct<=MAXSSERR)printf("CSY",ssp->cmdstat);}
	break;
case CS_RESERVED:
default:
	{if(sserrct<=MAXSSERR)printf("CS%x",ssp->cmdstat);}
}
	return (bus_timeout) ? 0 : 1 ;
}
/*
 * req_wait()
 *
 * This routine is called at the start of each information transfer
 * phase and after the last such phase.
 *
 * It returns 1 if REQ is asserted on the SCSI bus, meaning another phase
 * may begin, and 0 otherwise.  A REQ signal will not be seen if the function
 * times out or if BUSY drops.  A value of 1 is written to the pointer argument
 * if timeout occurred, else 0 is written.
 */
static int req_wait(to_ptr)
int *to_ptr;
{
	int req_found, i;
	unsigned char status;

	*to_ptr = 1;
	req_found = 0;
	for (i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if (status & RS_REQUEST) {
			req_found = 1;
			*to_ptr = 0;
			break;
		} else if ((status & RS_BUSY) == 0) {
			*to_ptr = 0;
			break;
		}
	}

	if (*to_ptr)
		{if(sserrct<=MAXSSERR)printf("TX: s=%x ", status);}

	return req_found;
}

/*
 * req_sense()
 *
 * Request Sense for a device.  The main reason for doing this is to
 * clear a standing Command Status of Device Check.
 *
 * Full results are discarded.  Return 1 if Device returns No Sense or
 * or Unit Attention.  Else return 0.
 *
 */
static int req_sense(s_id)
int s_id;
{
	uchar sense_buf[SENSELEN];
	int ret = 0;

	rqs.cmdstat = -1;
	rqs.data_bytes_in = 0;
	rqs.data_bytes_out = 0;
	rqs.cmdbuf[0] = ScmdREQUESTSENSE;
	rqs.cmdbuf[1] = rqs.cmdbuf[2] = rqs.cmdbuf[3] =
		rqs.cmdbuf[5] = 0;
		rqs.cmdbuf[4] = SENSELEN;
	rqs.cmdlen = G0CMDLEN;
	rqs.in_buf_len = SENSELEN;
	rqs.out_buf_len = 0;
	FP_OFF(rqs.in_buf) = sense_buf;
	FP_SEL(rqs.in_buf) = sds;

	if (bus_pre_xfer(s_id)) {
		bus_info_xfer(&rqs);
		if (rqs.data_bytes_in == SENSELEN) {
			if (sense_buf[2] == 0x00)	/* No Sense.  AOK */
				ret = 1;
			else if (sense_buf[2] == 0x06 && sense_buf[12] == 0x29)
				ret = 1;
		}
	}

	return ret;
}

/*
 * inquiry()
 *
 * Inquiry command for a device.
 * Find out if device is direct access, removable, etc.
 *
 * Put result of inquiry into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int inquiry(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	ss_type * ssp = ss[s_id];

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->id_busy = 1;
	ssp->cmdbuf[0] = ScmdINQUIRY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] =
		ssp->cmdbuf[5] = 0;
		ssp->cmdbuf[4] = INQUIRYLEN;
	ssp->cmdlen = G0CMDLEN;
	FP_OFF(ssp->in_buf) = buf;
	FP_SEL(ssp->in_buf) = sds;
	ssp->in_buf_len = INQUIRYLEN;
	ssp->out_buf_len = 0;

	ret = scsicmd(s_id);
	ssp->id_busy = 0;

	return ret;
}

/*
 * mode_sense()
 *
 * Mode Sense command for a device.
 * Use this to get disk parameters:
 *	number of cylinders
 *	number of heads
 *	number of sectors per track.
 *
 * Put result of mode sense into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int mode_sense(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	ss_type * ssp = ss[s_id];

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->id_busy = 1;
	ssp->cmdbuf[0] = ScmdMODESENSE;
	ssp->cmdbuf[1] = 0;
	ssp->cmdbuf[2] = 0x3F;
	ssp->cmdbuf[3] = 0;
	ssp->cmdbuf[4] = MODESENSELEN;
	ssp->cmdbuf[5] = 0;
	ssp->cmdlen = G0CMDLEN;
	FP_OFF(ssp->in_buf) = buf;
	FP_SEL(ssp->in_buf) = sds;
	ssp->in_buf_len = MODESENSELEN;
	ssp->out_buf_len = 0;

	ret = scsicmd(s_id);
	ssp->id_busy = 0;

	return ret;
}

/*
 * read_cap()
 *
 * Read Capacity command for a device.
 *
 * Return 1 if command succeeds, else 0.
 */
static int read_cap(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	ss_type * ssp = ss[s_id];

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->id_busy = 1;
	ssp->cmdbuf[0] = ScmdREADCAPACITY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] = 0;
	ssp->cmdbuf[5] = ssp->cmdbuf[6] = ssp->cmdbuf[7] = ssp->cmdbuf[8] = 0;
	ssp->cmdbuf[9] = 0;
	ssp->cmdlen = G1CMDLEN;
	FP_OFF(ssp->in_buf) = buf;
	FP_SEL(ssp->in_buf) = sds;
	ssp->in_buf_len = 8;
	ssp->out_buf_len = 0;

	ret = scsicmd(s_id);
	ssp->id_busy = 0;

	return ret;
}

/*
 * ss_start()
 *
 * Invoked whenever there might be I/O to do.
 *
 * Disallow re-entrancy in this routine (variable "locked").
 * If there is a next I/O request queued (peek at head of queue)
 *   get the target SCSI ID.
 *   If target is not busy
 *     remove request from queue
 *     mark target device busy
 *     start watchdog timer
 *     send command to host adapter
 *     if command succeeded
 *       cleanup after command
 *       adjust b_resid field
 *     else if command failed
 *       set error flag
 *       cleanup after command
 *     else (disconnected)
 *       do nothing
 */
static void ss_start()
{
#define RW_TRIES	5
	int s;
	BUF * bp;
	static char locked;
	int s_id;
	ss_type * ssp;
	struct	fdisk_s	*fdp;
	int partition;
	dev_t dev;
	static int retry[MAX_SCSI_ID-1];

	s = sphi();
	if(locked) {
		spl(s);
		return;
	}
	++locked;
	spl(s);

	if (st0x_busy) {
		timeout(&sst_tim, 50, ss_start, 0);
		return;
	}

	if((bp = ssq_rd_head()) != NULL) {
		s_id = DEV_SCSI_ID(bp->b_dev);
		ssp = ss[s_id];
		dev = bp->b_dev;
		partition = DEV_PARTN(dev);
		if (dev & SDEV)
			partition = WHOLE_DRIVE;
		fdp = ssp->parmp;
		if (!(ssp->id_busy)) {
			if (partition != WHOLE_DRIVE)
				ssp->bno = fdp[partition].p_base + bp->b_bno;
			else
				ssp->bno = bp->b_bno;
			ssp->bp = bp;
			ssp->id_busy = 1;
			ssp->dr_watch = WATCHDOG_SECONDS;
			if (ss_rw(s_id)) {
				retry[s_id] = 0;
				ssq_rm_head();
				if (bp->b_req == BREAD)
					bp->b_resid -= ssp->data_bytes_in;
				else
					bp->b_resid -= ssp->data_bytes_out;
				if (ssp->msg_in != MSG_DISCONNECT)
					ss_done(s_id);
/* if(sserrct<=MAXSSERR)printf("%d in  %d out\n",ssp->data_bytes_in,ssp->data_bytes_out); */
			} else {
				if (++retry[s_id] > RW_TRIES) {
{if(sserrct<=MAXSSERR)printf("BF5 ");}
					retry[s_id] = 0;
					ssq_rm_head();
					bp->b_flag |= BFERR;
					ss_done(s_id);
				} else {
					ssp->id_busy = 0;
					timeout(&sst_tim, 10, ss_start, 0);
{if(sserrct<=MAXSSERR)printf("R%d ",retry[s_id]);}
				}
			}
		}
	}
	--locked;
}

/*
 * ss_done
 *
 * Release current i/o buffer to the O/S.
 */
static void ss_done(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int s;

	s = sphi();
	ssp->id_busy = 0;
	ssp->dr_watch = 0;
	ssp->in_buf = ssp->out_buf = NULL;
	if (bp) {
		bdone(bp);
		ssp->bp = NULL;
	}
	spl(s);

	ss_start();
}

/*
 * bus_dev_reset()
 *
 * Send Bus Device Reset message to the given SCSI id.
 * Return 1 if host adapter was not busy and no obvious timeouts occurred,
 * else 0.
 */
static int bus_dev_reset(s_id)
{
	int bdr_ok = 1;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

{if(sserrct<=MAXSSERR)printf("bdr");}

	if (!loading && st0x_busy)
		bdr_ok = 0;

	if (bdr_ok) {
		/*
		 * Do ST0x arbitration.
		 */
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

		/*
		 * SCSI spec says there is "no maximum" to the wait for
		 * arbitration complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			bdr_ok = 0;
		}
	}

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	if (bdr_ok) {
		sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_SCSI);
		sfbyte(ss_dat, MSG_DEV_RESET);
		if (!bus_wait((0xFF << 8) | 0))
			bdr_ok = 0;
	}

{if(sserrct<=MAXSSERR)printf("%d",bdr_ok);}
	return bdr_ok;
}

/*
 * chk_reconn()
 *
 * Check SELECT to see if any SCSI device has tried to reconnect to the host
 * adapter.  Called if there is an interrupt, and by the timer in case
 * we somehow lose an interrupt.
 *
 * Return -1 if no reselect detected, or the SCSI ID of the reselecting
 * target if there is one.
 *
 * Call reconnect() after this if reselect has occurred.
 */
static int chk_reconn()
{
	uchar csr, dat;
	int s_id = -1;

	csr = ffbyte(ss_csr);
	if (csr & (RS_SELECT | RS_I_O)) {
		dat = ffbyte(ss_dat);
		if ((dat & HOST_ID) && (dat & NSDRIVE)) {
			dat &= ~HOST_ID;
			s_id = 0;
			while (dat >>=1)
				s_id++;
		}
	}

	return s_id;
}

/*
 * reconnect()
 *
 * Given SCSI ID of target device that is issuing reselect, do reconnect
 * SCSI bus stuff.
 */
static void reconnect(s_id)
int s_id;
{
	uchar dat;
	int cmd_ok = 0;
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

	dat = ffbyte(ss_dat);
	if ((dat & HOST_ID) && (dat & (1 << s_id)) && ssp) {
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
		if (bus_wait(RS_SELECT << 8 | 0)) {
			sfbyte(ss_csr, WC_ENABLE_SCSI);
			cmd_ok = bus_info_xfer(ssp);
			if (bp) {
				if (bp->b_req == BREAD)
					bp->b_resid -= ssp->data_bytes_in;
				else
					bp->b_resid -= ssp->data_bytes_out;
				if (cmd_ok && ssp->cmdstat == CS_GOOD) {
					if (ssp->msg_in == MSG_DISCONNECT) {
						ssp->dr_watch = WATCHDOG_SECONDS;
					} else
						ss_done(s_id);
				} else {
{if(sserrct<=MAXSSERR)printf("BF6 ");}
					bp->b_flag |= BFERR;
					ss_done(s_id);
				}
			}
		}
	}
}

/*
 * ss_rw()
 *
 * Send read or write command to the host adapter.
 */
static int ss_rw(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int rw_ok = 0;
uchar rwc;

	ssp->cmdstat = -1;
	if (bp->b_req == BREAD) {
		ssp->cmdbuf[0] = ScmdREADEXTENDED;
		ssp->in_buf_len = bp->b_count;
		ssp->in_buf = bp->b_faddr;
		ssp->out_buf_len = 0;
		ssp->out_buf = NULL;
rwc='R';
	} else {
		ssp->cmdbuf[0] = ScmdWRITEXTENDED;
		ssp->in_buf_len = 0;
		ssp->in_buf = NULL;
		ssp->out_buf_len = bp->b_count;
		ssp->out_buf = bp->b_faddr;
rwc='W';
	}
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->cmdbuf[1] = 0;
	ssp->cmdbuf[2] = ssp->bno >> 24;
	ssp->cmdbuf[3] = ssp->bno >> 16;
	ssp->cmdbuf[4] = ssp->bno >>  8;
	ssp->cmdbuf[5] = ssp->bno;
	ssp->cmdbuf[6] = 0;
	ssp->cmdbuf[7] = bp->b_count / (BSIZE * 256L);
	ssp->cmdbuf[8] = bp->b_count / BSIZE;
	ssp->cmdbuf[9] = 0;
	ssp->cmdlen = G1CMDLEN;

{ int s = sphi();
	rw_ok = bus_pre_xfer(s_id);
	if (rw_ok) {
		bus_info_xfer(ssp);
spl(s);
		rw_ok = (ssp->cmdlen == ssp->cmd_bytes_out);
if(!rw_ok) {
  uchar csr=ffbyte(ss_csr), dat=ffbyte(ss_dat);
  sserrct++; if (sserrct <=MAXSSERR) {
    {if(sserrct<=MAXSSERR)printf("F2 cmdlen=%d cmd_bytes_out=%d cmdstat=%d\n", ssp->cmdlen,
  	ssp->cmd_bytes_out, ssp->cmdstat);}
    {if(sserrct<=MAXSSERR)printf("%c msg_in=%x inl=%d ", rwc, ssp->msg_in, ssp->in_buf_len);}
    {if(sserrct<=MAXSSERR)printf("inb=%d otl=%d otb=%d\n", ssp->data_bytes_in, ssp->out_buf_len,
    ssp->data_bytes_out);}
    {if(sserrct<=MAXSSERR)printf("csr=%x dat=%x bno=%ld ",csr,dat,bp->b_bno);}
  }
}
	}
else {{if(sserrct<=MAXSSERR)printf("F1");}spl(s);}
}

	if (ssp->cmdstat == CS_CHECK) {
{if(sserrct<=MAXSSERR)printf("ss_rw(): requesting sense\n");}
		if (req_sense(s_id)) {
			rw_ok = (ssp->cmdlen == ssp->cmd_bytes_out);
if(!rw_ok) {if(sserrct<=MAXSSERR)printf("F3");}
		}
	}

	if (rw_ok) {
		rw_ok =
		(ssp->cmdstat == CS_GOOD || ssp->msg_in == MSG_DISCONNECT);
if(!rw_ok) {if(sserrct<=MAXSSERR)printf("F4");}
	}

	return rw_ok;

}

/*
 * rezero()
 *
 * Send Rezero Unit command.
 *
 * Return 1 if no timeouts occurred, 0 if not.
 */
static int rezero(s_id)
int s_id;
{
	int retval;
	ss_type * ssp = ss[s_id];

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->cmdbuf[0] = ScmdREZERO;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] =
		ssp->cmdbuf[5] = 0;
	ssp->cmdlen = G0CMDLEN;
	retval = scsicmd(s_id);

	return retval;
}
@


1.34
log
@Better error recovery, but needs work.
@
text
@d1 1
d17 3
d96 1
a96 1
#define HIPRI_RETRIES	800	/* # of times to retry while hogging CPU */
d107 4
a110 4
#define POPI		{ printf("%d:",statsptr);while(statsptr)\
				printf("%d ",stats[--statsptr]);printf("\n");}
#define SSTELL(foo)	printf(foo)
#define SSTATUS		{uchar status = ffbyte(ss_csr);printf("status=%x\n", status);}
d112 1
a112 1
	printf("%s: msg_in=%x cmdstat=%x\n", text, ssp->msg_in,\
d114 1
a114 1
	printf(" %x", ssp->cmdbuf[i]);printf(" cmd_bytes_out=%d",\
d117 1
a117 1
	printf(" %x", ffbyte(ssp->in_buf+i));printf(" data_bytes_in=%d\n",\
d180 1
d191 1
d220 1
a220 1
static int	allow_dc;	/* 1 if we allow SCSI targets to disconnect */
d234 1
d250 1
d313 1
d319 2
a320 1
	allow_dc = 1;
d518 1
a518 1
printf("HDGETA\n");
d575 1
a575 1
printf("BFERR 1\n");
d580 1
a580 1
printf("BFERR 2\n");
d598 1
a598 1
printf("BFERR 3\n");
d609 1
a609 1
/* printf("ssblock: drv=%x bno=%lx bp=%x flag=%x\n",
d636 2
a637 1
		defer(reconnect, s_id);
d656 1
a656 1
printf("BFERR 4\n");
d659 1
a659 1
printf("SCSI id #%d: bno=%lu <Watchdog Timeout>\n", s_id, ss[s_id]->bp->b_bno);
d702 1
a702 1
		printf("ST0x timeout;  flags=%x status=%x\n", flags, status);
d736 11
a746 2
			if (ssp->cmdstat != CS_BUSY)
				;
a747 1
		ssdelay(100);
a750 2
		if (testready(s_id))
			retval = 1;
d821 1
d867 1
d871 5
d880 33
a912 5
printf("scsireset\n");
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
	ssdelay(RESET_TICKS);
	sfbyte(ss_csr, 0);
	ssdelay(RESET_TICKS);
d1012 7
a1018 1
		if (allow_dc)
a1019 2
		else
			sfbyte(ss_dat, MSG_IDENTIFY);
a1061 1
	ssp->cmdstat = -1;
d1142 1
a1142 1
	printf("W");
d1170 1
a1170 1
	printf("CSK",ssp->cmdstat);
d1173 1
a1173 1
	printf("CSY",ssp->cmdstat);
d1177 1
a1177 1
	printf("CS%x",ssp->cmdstat);
d1213 1
a1213 1
		printf("ST0x info xfer timeout;  status=%x\n", status);
d1234 1
d1276 1
d1315 1
d1351 1
d1444 1
a1444 1
/* printf("%d in  %d out\n",ssp->data_bytes_in,ssp->data_bytes_out); */
d1447 1
a1447 1
printf("BFERR 5\n");
d1455 1
a1455 2
if(sserrct<=5)printf("R%d\n",retry[s_id]);
else printf("%d",retry[s_id]);
d1500 1
a1500 1
printf("bdr");
d1502 1
a1502 1
	if (st0x_busy)
d1548 1
a1548 1
printf("%d",bdr_ok);
d1570 1
a1570 1
	if (csr & RS_SELECT) {
d1598 1
a1598 1
	if ((dat & HOST_ID) && (dat & (1 << s_id)) && ssp && ssp->id_busy) {
d1614 1
a1614 1
printf("BFERR 6\n");
d1636 1
d1673 7
a1679 7
  sserrct++; if (sserrct <=5) {
    printf("F2 cmdlen=%d cmd_bytes_out=%d cmdstat=%d\n", ssp->cmdlen,
  	ssp->cmd_bytes_out, ssp->cmdstat);
    printf("%c msg_in=%x inl=%d ", rwc, ssp->msg_in, ssp->in_buf_len);
    printf("inb=%d otl=%d otb=%d\n", ssp->data_bytes_in, ssp->out_buf_len,
    ssp->data_bytes_out);
    printf("csr=%x dat=%x bno=%ld ",csr,dat,bp->b_bno);
d1683 1
a1683 1
else {printf("F1");spl(s);}
d1687 1
a1687 1
printf("ss_rw(): requesting sense\n");
d1690 1
a1690 1
if(!rw_ok) printf("F3");
d1697 1
a1697 1
if(!rw_ok) printf("F4");
d1703 25
@


1.33
log
@Starting to fix retry mechanism on ss_rw().
@
text
@d1 1
d6 8
a13 2
 *	figure out a better storage class for rqs
 *      make input buffer for commands dynamic (?)
d16 3
d167 1
a167 1
static void	bus_dev_reset();	/* additional support functions */
d214 1
d229 1
d310 1
a623 1
printf("@@");
d707 1
d713 2
d719 11
a729 3
	if (testready(s_id))
		retval = 1;
	else {
d734 4
a737 3
		else
			devmsg(dev, "Test Unit Ready Failed");
	}
d739 1
d786 1
d921 1
a921 1
	int ret;
d923 2
a924 1
	for (ret = 0, tries = 0; !ret && tries < LOPRI_RETRIES; tries++) {
d937 2
a938 1
			scsireset();
d960 4
a963 1
		sfbyte(ss_dat, MSG_IDENT_DC);
d1018 1
d1026 1
a1026 1
sfbyte(ss_csr, WC_ENABLE_IRPT); /* FOO */
d1032 2
d1109 15
d1145 1
a1145 1
	for ( i = 0; i < HIPRI_RETRIES; i++) {
d1187 1
d1231 1
d1271 1
d1304 1
d1355 5
d1393 6
a1398 2
				} else
printf("R%d\n",retry[s_id]);
a1430 9
 * BDR_CHECK_INTERVAL is the number of ticks to wait between checks for
 * SCSI Bus Free after sending Bus Device Reset.
 * BDR_CHECK_COUNT is the number of times to check for SCSI Bus Free
 * before giving up.
 */
#define BDR_CHECK_INTERVAL	10
#define BDR_CHECK_COUNT		100

/*
d1434 2
d1437 1
a1437 1
static void	bus_dev_reset(s_id)
d1439 1
a1439 1
	int tries;
d1441 7
a1447 2
printf("bus_dev_reset\n");
	for (tries = 0; tries < LOPRI_RETRIES; tries++) {
d1456 2
a1457 2
		 * SCSI spec says there is "no maximum" to the wait for arbitration
		 * complete.
d1460 1
a1460 2
			scsireset();
			continue;
d1462 1
d1464 4
a1467 3
		/*
		 * Arbitration complete.  Now select, with ATN to allow messages.
		 */
d1472 2
a1473 1
			continue;
d1475 1
d1480 2
a1481 1
			continue;
d1483 1
d1486 2
a1487 1
		break;
d1489 3
a1491 7
	for (tries = 0; tries < BDR_CHECK_COUNT; tries++) {
		if (ffbyte(ss_csr) == 0) {
	printf("bus device reset done\n");
			break;
		}
		ssdelay(BDR_CHECK_INTERVAL);
	}
d1545 13
a1557 8
			if (bp->b_req == BREAD)
				bp->b_resid -= ssp->data_bytes_in;
			else
				bp->b_resid -= ssp->data_bytes_out;
			if (cmd_ok && ssp->cmdstat == CS_GOOD) {
				if (ssp->msg_in == MSG_DISCONNECT) {
					ssp->dr_watch = WATCHDOG_SECONDS;
				} else
d1559 1
a1559 4
			} else {
printf("BFERR 6\n");
				bp->b_flag |= BFERR;
				ss_done(s_id);
d1575 2
a1576 1
	int retval;
d1582 3
d1587 2
d1591 1
d1605 4
a1608 1
	if (retval = bus_pre_xfer(s_id)) {
d1610 13
a1622 3
/* printf("cmdlen=%d cmd_bytes_out=%d cmdstat=%d\n", ssp->cmdlen,
	ssp->cmd_bytes_out, ssp->cmdstat); */
		retval = (ssp->cmdlen == ssp->cmd_bytes_out);
d1624 2
d1629 4
a1632 2
		if (req_sense(s_id))
			retval = (ssp->cmdlen == ssp->cmd_bytes_out);
d1635 8
a1642 3
	retval = (retval &&
		(ssp->cmdstat == CS_GOOD || ssp->msg_in == MSG_DISCONNECT));
	return retval;
@


1.32
log
@Accesses file system but has frequent BFERR 5's.
@
text
@d9 3
d1050 1
d1055 1
d1283 1
d1292 1
a1315 1
			ssq_rm_head();
d1319 2
a1326 2
				else
					printf("D");
d1329 1
d1331 6
a1336 2
				bp->b_flag |= BFERR;
				ss_done(s_id);
a1456 2
printf("R%d", s_id);
if(s_id!=0)s_id=-1;
@


1.31
log
@Now fdisk command works but mkfs fails.
@
text
@d9 3
d79 1
a79 1
#define HIPRI_RETRIES	400	/* # of times to retry while hogging CPU */
d583 2
a584 2
printf("ssblock: drv=%x bno=%lx bp=%x flag=%x\n",
	drive, bp->b_bno, bp, bp->b_flag);
a624 1
printf("*");
d1321 1
a1321 1
printf("%d in  %d out\n",ssp->data_bytes_in,ssp->data_bytes_out);
d1503 1
a1503 1
printf("ss_rw(%d)\n", s_id);
d1527 2
a1528 2
printf("cmdlen=%d cmd_bytes_out=%d cmdstat=%d\n", ssp->cmdlen,
	ssp->cmd_bytes_out, ssp->cmdstat);
@


1.30
log
@Trying to figure out disconnect after write.
@
text
@d9 3
a398 1
printf("BARF\n");
d619 1
a619 1
	int s_id;
a626 1
printf("1 s_id=%d dr_w=%d\n",s_id,ssp->dr_watch);
d635 2
a636 2
					s_id = chk_reconn();
					if (s_id == -1)
d639 1
a639 1
						reconnect(s_id);
d989 1
a1309 1
printf("2 s_id=%d dr_w=%d\n",s_id,ssp->dr_watch);
d1340 1
d1342 1
a1344 1
printf("3 s_id=%d dr_w=%d\n",s_id,ssp->dr_watch);
d1350 2
a1438 1
printf("chk_reconn: csr=%x dat=%x\n",csr,dat);
a1478 1
printf("4 s_id=%d dr_w=%d\n",s_id,ssp->dr_watch);
a1523 1
printf("ss_rw(): bus_pre_xfer ok\n");
d1528 1
a1528 2
	} else
printf("ss_rw(): bus_pre_xfer not ok\n");
a1537 1
printf("ss_rw(): retval=%d\n", retval);
@


1.29
log
@Whole disk devices working - need to implement HDGETA.
@
text
@d9 3
d153 1
a210 1
static int	dr_watch[MAX_SCSI_ID-1];
a362 1
printf("adj partn=%d\n", partn);
d466 3
a468 3
#define NHEAD	7
#define NSEC	28
#define NCYL	1066
d494 1
a494 1
  hdparm.ncyl[0] + hdparm.ncyl[1]<<8, (int)hdparm.nhead, (int)hdparm.nspt);
d625 1
d630 1
a631 1
printf("SCSI id #%d: bno=%lu <Watchdog Timeout>\n", s_id, ss[s_id]->bp->b_bno);
d690 1
a690 1
	uchar query_buf[INQUIRYLEN + 1];
d739 16
d772 2
d967 1
a969 2
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
d1043 4
d1121 2
d1161 2
d1180 39
d1232 2
a1293 1
		ssp->bp = bp;
a1298 4
		if (partition != WHOLE_DRIVE)
			ssp->bno = fdp[partition].p_base + bp->b_bno;
		else
			ssp->bno = bp->b_bno;
d1300 5
d1308 1
d1316 3
d1342 1
a1344 2
if (bp->b_flag & BFERR)
  printf("BFERR\n");
d1429 1
a1429 1
	uchar dat;
d1432 2
a1433 1
	if (ffbyte(ss_csr) && RS_SELECT) {
d1435 1
d1442 1
d1464 1
a1464 1
	if ((dat & HOST_ID) && (dat & (1 << s_id))) {
d1474 1
a1474 1
				if (ssp->msg_in == MSG_DISCONNECT)
d1476 2
a1477 1
				else
d1509 2
@


1.28
log
@Kernel fdisk works, fdisk command gets garbage.
@
text
@d9 3
d91 1
a91 1
	printf(" %x", ssp->in_buf[i]);printf(" data_bytes_in=%d\n",\
d113 1
a113 1
	uchar	*in_buf;
d116 1
a116 1
	uchar	*out_buf;
d375 1
d1014 4
a1017 2
				ssp->in_buf[ssp->data_bytes_in]
				= ffbyte(ss_dat);
d1027 4
a1030 1
				sfbyte(ss_dat, ssp->out_buf[ssp->data_bytes_out]);
d1103 2
a1104 1
	rqs.in_buf = sense_buf;
d1109 1
a1109 1
			if (rqs.in_buf[2] == 0x00)	/* No Sense.  AOK */
d1111 1
a1111 1
			else if (rqs.in_buf[2] == 0x06 && rqs.in_buf[12] == 0x29)
d1141 2
a1142 1
	ssp->in_buf = buf;
d1171 2
a1172 1
	ssp->in_buf = buf;
d1228 2
d1427 1
a1427 1
		ssp->in_buf = FP_OFF(bp->b_faddr);
d1431 1
a1431 1
		ssp->out_buf = FP_OFF(bp->b_faddr);
@


1.27
log
@Typos fixed.  Locks up CPU on first open
@
text
@d9 3
d334 1
a334 1

d357 1
a357 1

d361 2
d364 6
a369 2
	if (valid_open && partn != WHOLE_DRIVE && !(ssp->ptab_read))
		if (fdisk(dev, fdp)) {
d371 1
d373 1
a373 1
for (p=0; p<WHOLE_DRIVE; p++)
d381 1
d386 1
a386 1
	if (valid_open
d390 1
d393 1
a393 1
	if (valid_open && fdp[partn].p_size == 0) {
d417 1
d460 4
d470 4
d475 4
d480 12
a510 1
	register scsi_work_t *sw;
d538 1
d543 1
d561 1
d572 2
a573 2
printf("ssblock: drv %x bno %x:%x  bp=%x, flag = %o\n",
	drive, (long)sw->sw_bno, bp, bp->b_flag);
d575 1
a575 1
		ssq_wr_tail(sw);
d620 1
d1233 1
d1257 2
d1390 1
d1409 1
a1409 1

d1430 1
d1432 5
a1436 3
		retval = (ssp->cmdlen == ssp->cmd_bytes_out
			&& ssp->cmdstat == CS_GOOD);
	}
d1439 1
d1444 3
@


1.26
log
@First clean compile with block routine.
@
text
@d9 3
d194 1
a194 1
static ss_type *ss_block;	/* points to block of "ss" structs */
d257 1
a257 1
		} else if ((ss_block = kalloc(num_drives*sizeof(ss_type)))
d262 1
a262 1
			kclear(ss_block, num_drives * sizeof(ss_type));
d265 1
a265 1
		ss_type *foo = ss_block;
d290 2
a291 2
	if (ss_block)
		kfree(ss_block);
d669 1
a669 1
		if (inquiry(s_id), query_buf) {
d680 1
a680 1
		if (read_cap(s_id), query_buf) {
d1045 1
d1054 1
@


1.25
log
@lots of strategy code added - but not ready to compile
@
text
@d9 3
d97 1
a528 6
#ifdef BNO_CALC
		if (partition != WHOLE_DRIVE)
			sw->sw_bno = fdp[partition].p_base + bp->b_bno;
		else
			sw->sw_bno = bp->b_bno;
#endif
d555 1
a558 1
printf("@@");
d563 3
d579 2
d583 7
a589 3
				s_id = chk_reconn();
				if (s_id != -1)
					reconnect(s_id);
d640 2
d666 4
a669 4
		if (inquiry(s_id)) {
			ss[s_id]->in_buf[INQUIRYLEN] = 0;
			devmsg(dev, ss[s_id]->in_buf + 8);
			if (ss[s_id]->in_buf[0] == 0) {
d677 1
a677 1
		if (read_cap(s_id)) {
d679 7
a688 29
#if 0
	/*
	 * For test purposes only, try to read the partition table.
	 */
	if (retval) {
#define READ_PTS	1
int foo,fof;
for (foo=0,fof=0;foo<READ_PTS;){
	busted=0;
	drvl[SCSI_MAJOR].d_time++;
		if (read_pt(s_id)) {
			retval = 1;
		} else {
			devmsg(dev, "Read Partition Table Failed");
			break;
		}
foo++;
	if (!rpt_irpt){
		fof++;
		if (fof>=3) {
			printf("3 irq's lost\n");
			break;
		}
	}
} /*endfor*/
printf("%d read_pt's\n",foo);
	}
#endif

a729 1
	int tries;
d731 5
a735 4
	tries = 0;
	do {
		if (tries > 0)
			ssdelay(100);
d737 4
a740 5
		if (retval = bus_pre_xfer(s_id)) {
			bus_info_xfer(ssp);
			retval = (ssp->cmdlen == ssp->cmd_bytes_out
				&& ssp->cmdstat == CS_GOOD);
		}
a741 52
		if (ssp->cmdstat == CS_CHECK) {
			if (req_sense(s_id))
				retval = (ssp->cmdlen == ssp->cmd_bytes_out);
		}

		tries++;
	} while (ssp->cmdstat == CS_BUSY && tries < LOPRI_RETRIES);

	if (ssp->msg_in == MSG_DISCONNECT) {
		int connected = 0;
		uchar dat, csr;

printf("Disconnected ");
{
	int s;
	s=sphi();
	while(!rpt_irpt && !busted)
		sleep(&rpt_irpt, CVBLKIO,IVBLKIO,SVBLKIO);
	spl(s);
}
		for (tries = 0; tries < 10; tries++) {
			csr = ffbyte(ss_csr);
			if (csr & RS_SELECT) {
				dat = ffbyte(ss_dat);
				if (dat & HOST_ID) {
printf("%d tries Reconnected\n",tries);
					connected = 1;
					break;
				} else {
					int t;
printf("Host not selected\n");
					for (t = 0; t < 10; t++) {
						if (ffbyte(ss_csr) & RS_SELECT == 0) {
printf("Select dropped by target\n");
							break;
						}
						ssdelay(10);
					}
				}
			}
			ssdelay(10);
		}
		if (connected) {
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
			if (bus_wait(RS_SELECT << 8 | 0)) {
				sfbyte(ss_csr, WC_ENABLE_SCSI);
				bus_info_xfer(ssp);
				retval = (ssp->cmdstat == CS_GOOD);
			}
		}
	}

d977 1
a977 1
			if (ssp->data_bytes_out < ssp->out_buf_len && ssp->out_buf)
d980 1
a980 1
			else {	/* This case should not happen. */
d1070 1
d1073 1
a1073 1
static int inquiry(s_id)
d1075 1
d1080 1
d1086 1
d1090 1
d1102 1
a1102 1
static int read_cap(s_id)
d1104 1
d1109 1
d1115 1
d1119 1
a1119 9
	if (ret) {
		ssp->capacity = ssp->in_buf[3] | (ssp->in_buf[2] << 8)
		| (((long)(ssp->in_buf[1])) << 16)
		| (((long)(ssp->in_buf[0])) << 24);
		ssp->blocklen = ssp->in_buf[7] | (ssp->in_buf[6] << 8)
		| (((long)(ssp->in_buf[5])) << 16)
		| (((long)(ssp->in_buf[4])) << 24);
printf("capacity=%ld   block length=%ld\n", ssp->capacity, ssp->blocklen);
	}
d1153 3
d1169 7
a1217 28
 * read_pt()
 *
 * Read partition table for a device.
 *
 * Return 1 if command succeeds, else 0.
 */
static int read_pt(s_id)
int s_id;
{
	int ret = 0;
	ss_type * ssp = ss[s_id];

	ssp->cmdbuf[0] = ScmdREADEXTENDED;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] = 0;
	ssp->cmdbuf[5] = ssp->cmdbuf[6] = ssp->cmdbuf[7] = ssp->cmdbuf[9] = 0;
	ssp->cmdbuf[8] = 1;	/* transfer 1 block */
	ssp->cmdlen = G1CMDLEN;
	ssp->in_buf_len = BSIZE;

	ret = scsicmd(s_id);
	if (ret) {
printf("signature low:%x high:%x\n", ssp->in_buf[510], ssp->in_buf[511]);
	}

	return ret;
}

/*
d1321 1
d1324 1
d1326 20
a1345 5
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
	if (bus_wait(RS_SELECT << 8 | 0)) {
		sfbyte(ss_csr, WC_ENABLE_SCSI);
		if (bus_info_xfer(ssp) && ssp->cmdstat == CS_GOOD)
			cmd_ok = 1;
d1347 1
a1347 7
/* This is not finished: dr_watch, bdone, id_busy, etc. 
and what of another disconnect??? */
/* no disconnect allowed for inquiry, test ready, read capacity, etc. */
		bp->b_resid -= BSIZE;
	if (cmd_ok)
	if (ssp->msg_in != MSG_DISCONNECT)
		ssp->dr_watch = WATCHDOG_SECONDS;
a1348 2
}

d1370 6
a1375 2
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] = 0;
	ssp->cmdbuf[5] = ssp->cmdbuf[6] = ssp->cmdbuf[9] = 0;
d1378 1
@


1.24
log
@Some rearrangements - still working on block & related routines
@
text
@a0 2
int rpt_irpt;
int busted;
d2 1
a2 1
 * This is a driver for Seagate ST01/ST02 scsi hard disk controllers.
d9 3
d61 1
a64 6
				/* Device States */
#define	SIDLE		0	/* controller idle */
#define	SRETRY		1	/* seeking */
#define	SREAD		2	/* reading */
#define	SWRITE		3	/* writing */

d90 1
d92 2
a93 2
	long	capacity;
	long	blocklen;
d95 1
d100 1
a100 1
	uchar	in_buf[IN_BUF_SIZE];
d103 4
a106 1
	BUF	*bp;
d135 1
a135 2
static void	chk_reconn();
static void	do_ss();
d138 1
d143 1
a192 1
static int	ss_state;	/* starts at SIDLE */
d380 2
a381 1
	 * OK - open the device.
d394 3
d521 2
a522 1
	 * See if we can allocate a request node for this operation.
d525 1
a525 16
		bp->b_actf = NULL;
		sw = (scsi_work_t *)kalloc( sizeof(*sw) );
		if (sw == NULL) {
			devmsg(dev, "out of kernel memory");
			bp->b_flag |= BFERR;
			valid_op = 0;
		}
	}

	/*
	 * Operation appears valid and we have a node for it.
	 * Fill fields in the node and queue the request.
	 */
	if (valid_op) {
		sw->sw_bp = bp;
		sw->sw_drv = drive;
d530 1
a530 1
		sw->sw_retry = 1;
d536 1
a536 2
		if (ss_state == SIDLE)
			ss_start();
d548 4
d555 6
a560 3
	printf("@@");
	rpt_irpt=1;
	wakeup(&rpt_irpt);
d568 2
a569 1
	int	s_id;
d571 6
a576 5
	for (s_id = 0; s_id < MAX_SCSI_ID-1; s_id++)
		if (dr_watch[s_id]) {
			dr_watch[s_id]--;
			chk_reconn();
			if (dr_watch[s_id] == 0) {
d579 4
d585 1
a585 4
	printf("*");
	busted = 1;
	drvl[SCSI_MAJOR].d_time--;
	wakeup(&rpt_irpt);
d673 1
a673 1
#if 1
a680 1
	rpt_irpt=0;
d968 1
d1032 1
a1032 1
			if (ssp->data_bytes_in < ssp->in_buf_len)
d1035 2
a1036 1
			else
a1037 1
			ssp->data_bytes_in++;
d1041 1
a1041 1
			 * Temporary filler.
d1043 7
a1049 1
			sfbyte(ss_dat, 0xAA);
d1193 1
a1193 2
 * Invoked whenever there is I/O to do.  Pull first request, if any,
 * off the queue, send it to the drive, and delete it from the queue.
d1196 15
d1215 1
a1215 1
	scsi_work_t *sw;
d1217 2
d1228 20
a1247 8
	if((sw = ssq_rm_head()) != NULL) {
		if (sw->sw_bp->b_req == BWRITE)
			ss_state = SWRITE;
		else if (sw->sw_bp->b_req == BREAD)
			ss_state = SREAD;
		else
			printf("Error:  b_req=%d\n", sw->sw_bp->b_req);
		do_ss(sw);
d1253 1
a1253 1
 * do_ss()
a1254 24
 * Begin a block read or write command as found in an "sw" queue entry.
 */
static void do_ss(sw)
struct scsi_work_t * sw;
{
	BUF * bp;

printf("do_ss\n");
	bp = sw->sw_bp;
	switch(ss_state) {
	case SREAD:
		bp->b_resid -= BSIZE;
		ss_done(sw);
		break;
	case SWRITE:
		bp->b_resid -= BSIZE;
		ss_done(sw);
		break;
	}
}

/*
 * ss_done
 *
d1257 2
a1258 2
static void ss_done(sw)
struct scsi_work_t * sw;
d1260 2
a1261 1
	BUF * bp;
d1263 4
a1266 5
printf("ss_done\n");
	if (sw) {
		bp = sw->sw_bp;

		ss_state = SIDLE;
d1268 1
a1268 1
		kfree(sw);
d1270 2
a1272 4
	if (ssq_rd_head())
		ss_start();
}

d1358 1
a1358 1
			printf("bus device reset done\n");
d1368 1
a1368 1
 * Poll to see if any SCSI device has tried to reconnect to the host
d1371 5
d1377 1
a1377 1
static void chk_reconn()
d1379 15
d1395 68
@


1.23
log
@ssopen compiles - not tested
@
text
@d11 3
d25 19
d45 4
d61 2
d93 18
d112 4
a115 1
 * Includes.
a116 30
#include	<coherent.h>
#include	<sys/io.h>
#include	<sys/sched.h>
#include	<sys/uproc.h>
#include	<sys/proc.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/devices.h>		/* SCSI_MAJOR */
#include	<errno.h>

#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<scsiwork.h>
#include	<ss.h>

/*
 * Export Functions.
 */

/*
 * Export Variables - patch these to configure the driver.
 */
int	NSDRIVE = 1;		/* Bitmap of attached SCSI drives. */
int	SS_INT = 5;		/* ST0[12] use either IRQ3 or IRQ5 */
int	SS_BASE = 0xDE00;	/* Segment addr of ST0x communication area */

/*
 * Import Functions.
 */
a120 3
/*
 * Local Functions.
 */
d134 1
d150 4
a153 1
 * Local Variables.
a154 20
static BUF	dbuf;		/* For raw I/O */
static paddr_t	ss_base;	/* physical address of ST0x comm area */
static faddr_t	ss_fp;		/* (far *) to ST0x comm area */

static faddr_t	ss_ram;		/* (far *) to parameter RAM */
static faddr_t	ss_csr;		/* (far *) to control/status */
static faddr_t	ss_dat;		/* (far *) to data port */

static int	num_drives;	/* number of controller SCSI id's */
static struct ss *ss_block;	/* points to block of "ss" structs */
static int	st0x_busy;	/* 1 if SCSI host adapter busy */

static TIM	delay_tim;	/* needed for calls to ssdelay() */
static TIM	timeout_tim;	/* needed for calls to timeout() */
static int	ss_expired;	/* 1 after local timeout */
static int	ss_state;	/* starts at SIDLE */

/*
 * Driver CON entry - an export variable.
 */
d171 4
a174 5
/*
 * A per-drive structure - ss
 */
#define IN_BUF_SIZE	512
typedef unsigned char	uchar;
d176 3
a178 15
static struct ss	{
	long	capacity;
	long	blocklen;
	int	msg_in;
	uchar	cmdbuf[G1CMDLEN];
	int	cmdlen;
	int	cmd_bytes_out;
	int	cmdstat;
	uchar	in_buf[IN_BUF_SIZE];
	int	in_buf_len;
	int	data_bytes_in;
	struct	fdisk_s parmp[NPARTN+1];
	unsigned int	ptab_read:1;  /* 1 if partition table has been read */
	unsigned int	id_busy:1;  /* 1 if device with this SCSI id busy */
} *ss[MAX_SCSI_ID-1], rqs;
d180 15
d249 1
a249 1
		} else if ((ss_block = kalloc(num_drives*sizeof(struct ss)))
d254 1
a254 1
			kclear(ss_block, num_drives * sizeof(struct ss));
d257 1
a257 1
		struct ss *foo = ss_block;
d311 1
a311 1
	struct ss * ssp;
d467 1
a467 1
	struct ss * ssp;
d571 11
d584 1
a584 1
	drvl[SCSI_MAJOR].d_time=0;
d683 1
a683 1
	drvl[SCSI_MAJOR].d_time=1;
d718 1
a718 1
	struct ss * ssp = ss[s_id];
d743 1
a743 1
	struct ss *ssp = ss[s_id];
d958 1
a958 1
struct ss *ssp;
d1136 1
a1136 1
	struct ss * ssp = ss[s_id];
d1161 1
a1161 1
	struct ss * ssp = ss[s_id];
d1253 2
a1254 1
	bp = sw->sw_bp;
d1256 4
a1259 3
	ss_state = SIDLE;
	bdone(bp);
	kfree(sw);
d1276 1
a1276 1
	struct ss * ssp = ss[s_id];
d1356 11
@


1.22
log
@Starting to get block operations working.
@
text
@d11 3
a76 1
#include	<ss.h>
d82 1
a101 4
extern void ssq_wr_tail();
extern scsi_work_t * ssq_rd_head();
extern scsi_work_t * ssq_rm_head();

d303 1
a303 1
static void ssopen( dev, mode )
d307 4
a310 1
	int erf = 0;
d312 4
d318 3
d328 1
a328 1
		erf = 1;
d332 1
a332 1
	 * If "special" bit is set, partition must be zero.
d334 1
a334 1
	if (!erf && DEV_SPECIAL(dev) && partn != 0) {
d336 1
a336 1
		erf = 1;
d340 1
a340 1
	 * If "special" bit is NOT set, error return for now.
d342 2
a343 4
	if (!erf && !DEV_SPECIAL(dev)) {
		u.u_error = ENXIO;
		erf = 1;
	}
d346 2
a347 1
	 * OK - open the device.
d349 13
a361 4
	if (!erf) {
		++drvl[SCSI_MAJOR].d_time;
	}
#if 0
d365 2
a366 1
	if ((pparm[p].p_base+pparm[p].p_size) > pparm[d+NDRIVE*NPARTN].p_size)
d368 4
a371 1
	else if ( pparm[p].p_size == 0 )
d373 9
a381 1
#endif
d387 1
a387 1
static void ssclose( dev )
d394 1
a394 1
 * ssread()	- write a block to the raw disk
d401 1
a401 1
static void ssread( dev, iop )
d416 1
a416 1
static void sswrite( dev, iop )
d433 1
a433 1
static int ssioctl( dev, cmd, vec )
d660 1
a660 10
#if 0
	if (retval) {
		retval = fdisk(dev, ss[s_id]->parmp);
		if (retval) {
			printf("fdisk scsi id #%d succeeded\n", s_id);
			ss[s_id]->ptab_read = 1;
		} else
			printf("fdisk scsi id #%d failed\n", s_id);
	}
#else
a788 1
printf("Select deasserted by target\n");
@


1.21
log
@Move define's to ss.h and scsiwork.h.  Other cleanup
@
text
@a6 1
 *	turn on interrupts
d11 3
d645 1
d647 1
a647 1
for (foo=0,fof=0;foo<100;){
@


1.20
log
@Reads boot sector 100 times using IRQ on reconnect
@
text
@d12 2
a13 51
 * Revision 1.19	91/03/26  23:15:47	root
 * Reads partition table in prototype code
 * 
 * Revision 1.18	91/03/25  20:11:30	root
 * first raw read - disconnects
 * 
 * Revision 1.17	91/03/25  19:06:36	root
 * calls ssqueue functions - need real i/o
 * 
 * Revision 1.16	91/03/22  17:40:03	root
 * Need to do more with ss_start()
 * 
 * Revision 1.15	91/03/21  16:44:03	root
 * getting ready to call fdisk - finish ss_start next
 * 
 * Revision 1.14	91/03/20  17:25:14	root
 * Inquiry and Read Capacity working
 * 
 * Revision 1.13	91/03/18  17:43:18	root
 * add retry logic to scsicmd(); general cleanup
 * 
 * Revision 1.12	91/03/14  17:22:28	root
 * Test Ready now works, including Req Sense
 * 
 * Revision 1.11	91/03/14  15:45:12	root
 * has trouble with Test Ready using bus_info_xfer fsa
 * 
 * Revision 1.10	91/03/13  17:08:03	root
 * still more to do on bus_info_xfer
 * 
 * Revision 1.9	91/03/12  16:08:23	root
 * need to finish bus_info_xfer()
 * 
 * Revision 1.8	91/03/11  17:41:10	root
 * started ssopen()/wrote stub for ssinit()
 * 
 * Revision 1.7	91/03/08  17:07:28	root
 * Does Test Read and Request Sense properly.
 * 
 * Revision 1.6	91/03/07  16:41:31	root
 * sends Test Ready, Starts to Request Sense
 * 
 * Revision 1.5	91/03/07  11:48:39	root
 * Now sends Identify and Abort messages & completes a SCSI bus cycle
 *
 * Revision 1.4	91/03/06  16:31:45	root
 * tried to send Identify message - get status 0x40 & fail
 *
 * Revision 1.3	91/03/05  17:03:43	root
 * Goes thru arbitration (sans IRQ) successfully
 *
a24 26
#define SS_RAM		0x1800	/* Offset of parameter RAM */
#define SS_CSR		0x1A00	/* Offset of control/status register */
#define SS_DAT		0x1C00	/* Offset of data port */

#define SS_RAM_LEN	128	/* ST0x has 128 bytes of RAM */
#define SS_DAT_LEN	0x400	/* Byte range mapped to data port */
#define SS_SEL_LEN	0x2000	/* Total size of memory-mapped area */

#define WC_ENABLE_SCSI	0x80	/* Write Control (WC) register bits */
#define WC_ENABLE_IRPT	0x40
#define WC_ENABLE_PRTY	0x20
#define WC_ARBITRATE	0x10
#define WC_ATTENTION	0x08
#define WC_BUSY  	0x04
#define WC_SELECT  	0x02
#define WC_SCSI_RESET  	0x01

#define RS_ARBIT_COMPL	0x80	/* Read STATUS (RS) register bits */
#define RS_PRTY_ERROR	0x40
#define RS_SELECT	0x20
#define RS_REQUEST	0x10
#define RS_CTRL_DATA	0x08
#define RS_I_O  	0x04
#define RS_MESSAGE  	0x02
#define RS_BUSY  	0x01

a29 19
#define G0CMDLEN	6	/* Group 0 commands are 6 bytes long  */
#define G1CMDLEN	10	/* Group 1 commands are 10 bytes long */
#define SENSELEN	22	/* number of bytes returned w/ req sense */
#define INQUIRYLEN	54	/* number of bytes returned w/ inquiry */

				/* Message types */
#define MSG_CMD_CMPLT	0x00	/* Command Complete */
#define MSG_SAVE_DPTR	0x02	/* Save SCSI data pointer */
#define MSG_RSTOR_DPTR	0x03	/* Restore SCSI pointers */
#define MSG_DISCONNECT	0x04	/* Target is about to disconnect */
#define MSG_ABORT	0x06	/* End the current SCSI bus cycle */
#define MSG_DEV_RESET	0x0C	/* Bus Device Reset */
#define MSG_IDENT_DC	0xC0	/* Identify, with Disconnect allowed */

#define CS_GOOD		0x00	/* Command Status from the drive */
#define CS_CHECK	0x02
#define CS_BUSY		0x08
#define CS_RESERVED	0x18

a35 12
/*
 * Information Transfer Phase masks -
 * setting of RS_MESSAGE, RS_I_O, and RS_CTRL_DATA determines which of six
 * possible info transfer phases is occurring.
 */
#define XP_MSG_IN	(RS_MESSAGE | RS_I_O | RS_CTRL_DATA)
#define XP_MSG_OUT	(RS_MESSAGE          | RS_CTRL_DATA)
#define XP_STAT_IN	(             RS_I_O | RS_CTRL_DATA)
#define XP_CMD_OUT	(                      RS_CTRL_DATA)
#define XP_DATA_IN	(             RS_I_O               )
#define XP_DATA_OUT	(                                 0)

d70 1
a70 1
#include	<devices.h>		/* SCSI_MAJOR */
d72 1
d104 1
a104 3
static void	ssload();
static void	ssunload();
static void	ssopen();
d106 1
d111 10
a120 2
static void	ssblock();
static int	ssinit();
d123 2
a124 3
static void	ssdelay();
static int	bus_pre_xfer();
static int	bus_info_xfer();
d127 2
a128 3
static int	req_sense();
static int	inquiry();
static int	read_cap();
a129 4
static void	ss_start();
static void	ss_done();
static void	do_ss();
static void	bus_dev_reset();
d435 1
d437 2
a446 1

a448 2
	bp->b_resid = bp->b_count;
	
d458 1
a458 2
				bdone(bp);
				return;
d463 1
a463 2
			bdone(bp);
			return;
d471 1
a471 2
		bdone(bp);
		return;
d479 1
a479 2
		bdone(bp);
		return;
d482 11
a492 7
	bp->b_actf = NULL;
	sw = (scsi_work_t *)kalloc( sizeof(*sw) );
	if (sw == NULL) {
		devmsg(dev, "out of kernel memory");
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
a493 7
	sw->sw_bp = bp;
	sw->sw_drv = drive;
	if (partition != WHOLE_DRIVE)
		sw->sw_bno = fdp[partition].p_base + bp->b_bno;
	else
		sw->sw_bno = bp->b_bno;
	sw->sw_retry = 1;
d495 13
d511 10
a520 3
	ssq_wr_tail(sw);
	if (ss_state == SIDLE)
		ss_start();
a525 6
#if 0
static int irpted;
static long x;
for (x = 0, irpted = 0; x < 100000L; x++)  if (irpted) break;
#endif

a583 16
 *
 * Pseudocode:
 *
 * retval = 0
 * if Test Unit Ready command fails, even after SCSI reset and retry
 *   print "Test Unit Ready fails"
 * else if Request Sense command fails
 *   print "Request Sense fails"
 * else if Read Capacity command succeeds
 *   print "Read Capacity fails"
 * else if partition table can't be read
 *   print "can't get partition table"
 * else
 *   print "SCSI id #n initialized"
 *   retval = 1
 * return retval
d591 4
d671 2
a785 2
int RESET_ON_TICKS = 40;
int RESET_OFF_TICKS = 40;
d790 1
a790 1
	ssdelay(RESET_ON_TICKS);
d792 1
a792 1
	ssdelay(RESET_OFF_TICKS);
a940 4
			/*
			 * Only pay attention to first msg byte in.
			 * Don't care about extended messages.
			 */
a941 1
printf("msg_in = %x\n", msg_in);
@
0707070064030104131004440000030000030000011777770507310661700006100000210603/newbits/kernel/USRSRC/i8086/drv/RCS/ss36_46.c,vhead     1.46;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.46
date     91.05.16.21.54.10;  author root;  state Exp;
branches ;
next	1.45;

1.45
date     91.05.16.17.47.26;  author root;  state Exp;
branches ;
next	1.44;

1.44
date     91.05.16.14.17.20;  author root;  state Exp;
branches ;
next	1.43;

1.43
date     91.05.16.01.08.22;  author root;  state Exp;
branches ;
next	1.42;

1.42
date     91.05.15.23.58.22;  author root;  state Exp;
branches ;
next	1.41;

1.41
date     91.05.15.21.57.55;  author root;  state Exp;
branches 1.41.1.1;
next	1.40;

1.40
date     91.05.15.15.19.52;  author root;  state Exp;
branches 1.40.1.1;
next	1.39;

1.39
date     91.05.15.09.35.58;  author root;  state Exp;
branches ;
next	1.38;

1.38
date     91.05.14.10.05.37;  author root;  state Exp;
branches ;
next	1.37;

1.37
date     91.05.13.15.02.21;  author root;  state Exp;
branches ;
next	1.36;

1.36
date     91.05.13.11.08.25;  author root;  state Exp;
branches ;
next	;

1.40.1.1
date     91.05.15.23.21.27;  author root;  state Exp;
branches ;
next	;

1.41.1.1
date     91.05.15.23.47.43;  author root;  state Exp;
branches ;
next	;


desc
@Seagate ST01/ST02 device driver - state machine version.
@


1.46
log
@Hang bug fixed.  Raw i/o > 1 block reads 0.
@
text
@/*
 * Device driver for Seagate ST01/ST02 scsi host adapters.
 *
 * To do:
 *	set host_claimed conscientiously
 *	works but hogs CPU during big dd to /dev/null
 *
 *	bufq_rd_head()
 *	bufq_rm_head()
 *	bufq_wr_tail()
 *
 *	backoff & retry when bdr or req sense needed
 *	nonzero LUN's
 *	assembler I/O
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.45	91/05/16  17:47:26	root
 * Still trying to test ss_get.  Always hangs.
 * 
 * Revision 1.44	91/05/16  14:17:20	root
 * Drop unneeded fields from ss struct.  Try ss_get().
 * 
 * Revision 1.43	91/05/16  01:08:22	root
 * Needs assembler I/O most.
 * 
 * Revision 1.42	91/05/15  23:58:22	root
 * COH fdisk command gives junk when DEBUG=1, ok if DEBUG=3
 * 
 * Revision 1.41	91/05/15  21:57:55	root
 * First working version.
 * 
 * Revision 1.40	91/05/15  15:19:52	root
 * First clean compile of state machine version.
 * 
 * Revision 1.39	91/05/15  09:35:58	root
 * Code recover, do_connect, etc..
 * 
 * Revision 1.38	91/05/14  10:05:37	root
 * Code ss_mach().
 * 
 * Revision 1.37	91/05/13  15:02:21	root
 * Initial state machine hacks.
 * 
 * Revision 1.36	91/05/13  11:08:25	root
 * Last version before using state machine logic.
 * 
 */

/*
 * Debug levels.
 * DEBUG = 0	No debug output.
 * DEBUG = 1	Debug output on error only.
 * DEBUG = 2	Debug output on error only and at other selected places.
 * DEBUG = 3	Maximum debug output.
 */
#if (DEBUG >= 1)
#define PR1(str)		printf(str)
#else
#define PR1(str)
#endif
#if (DEBUG >= 2)
#define PR2(str)		printf(str)
#else
#define PR2(str)
#endif
#if (DEBUG >= 3)
#define PR3(str)		printf(str)
#else
#define PR3(str)
#endif

/* TEMPORARY S**T */
#define bufq_rd_head(s_id)	ssq_rd_head()
#define bufq_rm_head(s_id)	ssq_rm_head()
#define bufq_wr_tail(s_id, foo)	ssq_wr_tail(foo)

/*
 * Includes.
 */
#include	<coherent.h>
#include	<sys/io.h>
#include	<sys/sched.h>
#include	<sys/uproc.h>
#include	<sys/proc.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/devices.h>		/* SCSI_MAJOR */
#include	<errno.h>

#include 	<sys/fdisk.h>
#include	<sys/hdioctl.h>
#include	<sys/buf.h>
#include	<scsiwork.h>
#include	<ss.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */
#define DEV_SCSI_ID(dev)	((dev >> 4) & 0x0007)
#define DEV_LUN(dev)		((dev >> 2) & 0x0003)
#define DEV_DRIVE(dev)		((dev >> 2) & 0x001F)
#define DEV_PARTN(dev)		(dev & 0x0003)
#define DEV_SPECIAL(dev)	(dev & 0x0080)

#define HOST_ID		0x80	/* Host adapter is SCSI ID #7 */
#define HIPRI_RETRIES	400	/* # of times to retry while hogging CPU */
#define LOPRI_RETRIES	5	/* # of retries with sleep between tries */
#define WHOLE_DRIVE	NPARTN

#define BUS_FREE	((ffbyte(ss_csr) & (RS_BUSY | RS_SELECT)) == 0)
#define TGT_RSEL	\
	(  (ffbyte(ss_csr) & (RS_SELECT |  RS_I_O   )) \
	&& (ffbyte(ss_dat) & (HOST_ID   | (1<<s_id) )) )

#define DELAY_ARB	10	/* delays units are 10 msec (clock ticks) */
#define DELAY_BDR	30
#define DELAY_BSY	10
#define DELAY_RES	40
#define DELAY_RST	40

#define MAX_AVL_COUNT	10
#define MAX_BDR_COUNT	2
#define MAX_BSY_COUNT	2
#define MAX_TRY_COUNT	7

typedef unsigned char	uchar;
typedef unsigned int	uint;
typedef unsigned long	ulong;

typedef enum {			/* values for current driver state */
	SST_DEQUEUE =0,
	SST_BUS_DEV_RESET,
	SST_HIPRI_RESET,
	SST_LOPRI_RESET,
	SST_POLL_ARBITN,
	SST_POLL_BEGIN_IO,
	SST_POLL_RESELECT,
	SST_REQ_SENSE,
	SST_RESET_DONE,
	SST_RESET_OFF
} SST_TYPE;

typedef enum {			/* values for input to recovery routine */
	RV_A_TIMEOUT,
	RV_P_TIMEOUT,
	RV_R_TIMEOUT,
	RV_BF_TIMEOUT,
	RV_CS_BUSY,
	RV_CS_CHECK
} RV_TYPE;

typedef struct ss {
	ulong	capacity;
	ulong	blocklen;
	ulong	bno;
	int	msg_in;
	int	dr_watch;
	uchar	cmdbuf[G1CMDLEN];
	int	cmdlen;
	int	cmd_bytes_out;
	int	cmdstat;
	BUF	*bp;		/* current I/O request node, or NULL */
	struct	fdisk_s parmp[NPARTN+1];
	SST_TYPE state;
	TIM	tim;		/* for target-specific timers */
	uchar	avl_count;
	uchar	bdr_count;
	uchar	bsy_count;
	uchar	try_count;
	uint	busy:1;		/* 1 if command uses local buffer */
	uint	expired:1;	/* 1 if target's timer has expired */
	uint	ptab_read:1;	/* 1 if partition table has been read */
	uint	waiting:1;	/* 1 if target timer is running */
}	ss_type;

typedef struct {
	uint	ncyl;
	uchar	nhead;
	uchar	nspt;
}	drv_parm_type;

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
extern int	nulldev();
extern int	nonedev();
extern unsigned char ffbyte();

static void	ssopen();		/* CON functions */
static void	ssclose();
static void	ssblock();
static void	ssread();
static void	sswrite();
static int	ssioctl();
static void	sswatch();
static void	ssload();
static void	ssunload();

static int	bus_dev_reset();	/* additional support functions */
static int	chk_reconn();
static void	do_connect();
static int	far_info_xfer();
static int	host_ident();
static void	init_pointers();
static int	inquiry();
static int	local_info_xfer();
static int	mode_sense();
static void	nonpolled();
static int	read_cap();
static void	recover();
static int	req_sense();
static int	rsel_handshake();
static void	ss_finished();
static void	ss_mach();
static void	set_timeout();
static int	ssinit();
static void	ssintr();
static int	start_arb();
static void	stop_timeout();

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
CON	sscon	= {
	DFBLK|DFCHR,			/* Flags */
	SCSI_MAJOR,			/* Major index */
	ssopen,				/* Open */
	ssclose,			/* Close */
	ssblock,			/* Block */
	ssread,				/* Read */
	sswrite,			/* Write */
	ssioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	sswatch,			/* Timeout */
	ssload,				/* Load */
	ssunload,			/* Unload */
	nulldev				/* Poll */
};

	/* Patch these Export Variables to configure the driver. */
int	NSDRIVE = 1;		/* Bitmap of attached SCSI drives. */
int	SS_INT = 5;		/* ST0[12] use either IRQ3 or IRQ5 */
int	SS_BASE = 0xDE00;	/* Segment addr of ST0x communication area */

#define NCYL	1004
#define NHEAD	4
#define NSPT	52

drv_parm_type drv_parm[MAX_SCSI_ID-1] = {
	{ NCYL, NHEAD, NSPT},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0},
	{ 0, 0, 0}
};

static BUF	dbuf;		/* For raw I/O */
static paddr_t	ss_base;	/* physical address of ST0x comm area */
static faddr_t	ss_fp;		/* (far *) to ST0x comm area */

static faddr_t	ss_ram;		/* (far *) to parameter RAM */
static faddr_t	ss_csr;		/* (far *) to control/status */
static faddr_t	ss_dat;		/* (far *) to data port */

static int	num_drives;	/* number of controller SCSI id's */

static int	do_sst_op;	/* 1 when state machine iteration continues */
static int	host_claimed;	/* -1 or SCSI id of target using the host */
static int	ss_expired;	/* 1 after local timeout */

static ss_type	*ss_tbl;	/* points to block of "ss" structs */
static ss_type  *ss[MAX_SCSI_ID-1];

/*
 * ssload()	- load routine.
 *
 *	Action:	The controller is reset and the interrupt vector is grabbed.
 *		The drive characteristics are set up at this time.
 */
static void ssload()
{
	int erf = 0;  /* 1 if error occurs */
	int i;

	/*
	 * Claim IRQ vector.
	 */
	setivec(SS_INT, ssintr);

	/*
	 * Allocate a selector to map into ST0x memory-mapped comm area.
	 */
	ss_base = (paddr_t)((long)(unsigned)SS_BASE << 4);
	ss_fp = ptov(ss_base, (fsize_t)SS_SEL_LEN);

	ss_ram = ss_fp + SS_RAM;
	ss_csr = ss_fp + SS_CSR;
	ss_dat = ss_fp + SS_DAT;
printf("ss_dat=%lx ", ss_dat);
	/*
	 * Primitive test of ST0x RAM.
	 */
	sfword(ss_ram, 0xA55A);
	sfword(ss_ram + 2, 0x3CC3);
	sfword(ss_ram + SS_RAM_LEN - 4, 0xA55A);
	sfword(ss_ram + SS_RAM_LEN - 2, 0x3CC3);
	if (ffword(ss_ram) != 0xA55A		/* fetch a "far" word */
	||  ffword(ss_ram + 2) != 0x3CC3
	||  ffword(ss_ram + SS_RAM_LEN - 4) != 0xA55A
	||  ffword(ss_ram + SS_RAM_LEN - 2) != 0x3CC3) {
		printf("Error - ST0x failed memory test\n");
		erf = 1;
	}

	/*
	 * Allocate drive structs.
	 *
	 * Do a single call to kalloc() then put allocated pieces into
	 * array ss.
	 *
	 * First allocate and clear storage.  Then hook up the pointers.
	 */
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				num_drives++;
		if (num_drives == 0) {
			printf("Error - ss has no valid target id's\n");
			erf = 1;
		} else if ((ss_tbl = kalloc(num_drives*sizeof(ss_type)))
		== NULL) {
			printf("Error - ss can't allocate structs\n");
			erf = 1;
		} else
			kclear(ss_tbl, num_drives * sizeof(ss_type));
	}
	if (!erf) {
		ss_type *foo = ss_tbl;

		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				ss[i] = foo++;
	}

	/*
	 * Initialize drives we know about (i.e. in NSDRIVE bitmap).
	 */
	host_claimed = -1;
	if (!erf) {
		for (i = 0; i < MAX_SCSI_ID -1; i++)
			if ((NSDRIVE >> i) & 1)
				ssinit(i);
	}
}

/*
 * ssunload()	- unload routine.
 */
static void ssunload()
{
	/*
	 * Deallocate driver heap space.
	 */
	if (ss_tbl)
		kfree(ss_tbl);

	/*
	 * Free the ST0x selector.
	 */
	vrelse(ss_fp);

	/*
	 * Release IRQ vector.
	 */
	clrivec(SS_INT);
}

/*
 * ssopen()
 *
 *	Input:	dev = disk device to be opened.
 *		mode = access mode [IPR,IPW, IPR+IPW].
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */
static void ssopen(dev, mode)
register dev_t	dev;
{
	int drive, partn;
	int valid_open;
	struct	fdisk_s	*fdp;
	ss_type * ssp;
	int s_id;

	/*
	 * Set up local variables.
	 */
	valid_open = 1;
	drive = DEV_SCSI_ID(dev);
	partn = DEV_PARTN(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;

#if (DEBUG >= 3)
devmsg(dev, "ssopen");
#endif

	/*
	 * LUN must be zero.
	 * SCSI id must have corresponding 1 in NSDRIVE bitmapped variable.
	 */
	if (DEV_LUN(dev) != 0 || ((1 << drive) & NSDRIVE) == 0) {
		u.u_error = ENXIO;
		valid_open = 0;
	}

	/*
	 * If "special" bit is set, partition field must be zero.
	 */
	if (valid_open && DEV_SPECIAL(dev) && partn != 0) {
		u.u_error = ENXIO;
		valid_open = 0;
	}

	/*
	 * Subscripting gimmick for partition table.
	 */
	if (valid_open && dev & SDEV)
		partn = WHOLE_DRIVE;
	/*
	 * If not accessing whole drive and the partition table has not
	 * been read yet, try to read it now.
	 * Do this by calling fdisk() with partition table device on the drive
	 * that is being accessed.
	 */
	if (valid_open && partn != WHOLE_DRIVE && !(ssp->ptab_read)) {
		int fdisk_dev;

		fdisk_dev = (dev | SDEV) & 0xfff0;

#if (DEBUG >=3)
		devmsg(fdisk_dev, "calling fdisk");
		if (fdisk(fdisk_dev, fdp)) {
			int p;

			fdp[WHOLE_DRIVE].p_size = ssp->capacity;
			fdp[WHOLE_DRIVE].p_base = 0;
			printf("fdisk() succeeded\n");
			for (p=0; p<=WHOLE_DRIVE; p++)
	printf("p=%d base=%ld size=%ld\n", p, fdp[p].p_base, fdp[p].p_size);
			ssp->ptab_read = 1;
		} else {
			printf("fdisk() failed\n");
			u.u_error = ENXIO;
			valid_open = 0;
		}
#else
		if (fdisk(fdisk_dev, fdp)) {
			fdp[WHOLE_DRIVE].p_size = ssp->capacity;
			fdp[WHOLE_DRIVE].p_base = 0;
			ssp->ptab_read = 1;
		} else {
			u.u_error = ENXIO;
			valid_open = 0;
		}
#endif

	}

	/*
	 * Ensure partition lies within drive boundaries and is non-zero size.
	 */
	if (valid_open && partn != WHOLE_DRIVE
	&& (fdp[partn].p_base+fdp[partn].p_size) > fdp[WHOLE_DRIVE].p_size) {
		u.u_error = EBADFMT;
		valid_open = 0;
	}

	if (valid_open && partn != WHOLE_DRIVE && fdp[partn].p_size == 0) {
		u.u_error = ENODEV;
		valid_open = 0;
	}

	/*
	 * OK to open the device.
	 * Start watchdog timer (if not already started) for the host adapter.
	 */
	if (valid_open) {
		++drvl[SCSI_MAJOR].d_time;
		++ssp->dr_watch;
	}
}

/*
 * ssclose()
 */
static void ssclose(dev)
dev_t dev;
{
	ss_type * ssp;
	int s_id;

	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];

	/*
	 * Decrement the number of watchdog timer requests open for host
	 * adapter and for target.
	 */
	--drvl[SCSI_MAJOR].d_time;	
	--ssp->dr_watch;

#if (DEBUG >= 3)
devmsg(dev, "ssclose");
#endif

}

/*
 * ssread()	- read a block from the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void ssread(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BREAD, BFRAW|BFBLK|BFIOC );
}

/*
 * sswrite()	- write a block to the raw disk
 *
 *	Input:	dev = disk device to be written to.
 *		iop = pointer to source I/O structure.
 *
 *	Action:	Invoke the common raw I/O processing code.
 */
static void sswrite(dev, iop)
dev_t	dev;
IO	*iop;
{
	ioreq( &dbuf, iop, dev, BWRITE, BFRAW|BFBLK|BFIOC );
}

/*
 * ssioctl()
 *
 *	Input:	dev = disk device to be operated on.
 *		cmd = input/output request to be performed.
 *		vec = (pointer to) optional argument.
 *
 *	Action:	Validate the minor device.
 *		Update the paritition table if necessary.
 */

static int ssioctl(dev, cmd, vec)
register dev_t	dev;
int cmd;
char * vec;
{
	int ret = 0;
	hdparm_t hdparm;
	struct	fdisk_s	*fdp;
	int s_id;
	ss_type * ssp;

	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	fdp = ssp->parmp;

	switch(cmd) {
	case HDGETA:
PR3("HDGETA ");
		fdp = ssp->parmp;
		*(short *)&hdparm.landc[0] =
		*(short *)&hdparm.ncyl[0] = drv_parm[s_id].ncyl;
		hdparm.nhead = drv_parm[s_id].nhead;
		hdparm.nspt = drv_parm[s_id].nspt;
#if (DEBUG >= 3)
printf("ncyl=%d nhead=%d nspt=%d\n",
  hdparm.ncyl[0]+((int)hdparm.ncyl[1]<<8), (int)hdparm.nhead, (int)hdparm.nspt);
#endif
		kucopy( &hdparm, vec, sizeof hdparm );
		ret = 0;
		break;
	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * ssblock()	- queue a block to the disk
 *
 *	Input:	bp = pointer to block to be queued.
 *
 *	Action:	Queue a block to the disk.
 *		Make sure that the transfer is within the disk partition.
 */
static void ssblock(bp)
register BUF	*bp;
{
	struct	fdisk_s	*fdp;
	int partition, drive, s_id;
	dev_t dev;
	ss_type * ssp;

	/*
	 * Set up local variables.
	 */
	dev = bp->b_dev;
	partition = DEV_PARTN(dev);
	drive = DEV_DRIVE(dev);
	s_id = DEV_SCSI_ID(dev);
	ssp = ss[s_id];
	if (dev & SDEV)
		partition = WHOLE_DRIVE;
	fdp = ssp->parmp;

	bp->b_resid = bp->b_count;

	/*
	 * Range check disk region.
	 */
	if (!(ssp->ptab_read)) {
		if ( partition == WHOLE_DRIVE ) {
			if ((bp->b_bno != 0) || (bp->b_count != BSIZE)) {
PR1("BF1 ");
				bp->b_flag |= BFERR;
				goto bad_open;
			}
		} else {
PR2("BF2 ");
			devmsg(dev, "no partition table");
			bp->b_flag |= BFERR;
			goto bad_open;
		}
	}

	/*
	 * Check for read at end of partition.
	 * (Need to return with b_resid = BSIZE to signal end of volume.)
	 */
	else if ((bp->b_req == BREAD) && (bp->b_bno == fdp[partition].p_size)) {
		goto bad_open;
	}

	/*
	 * Check for read past end of partition.
	 */
	else if ( (bp->b_bno + (bp->b_count/BSIZE))
	> fdp[partition].p_size ) {
PR3("BF3 ");
		bp->b_flag |= BFERR;
		goto bad_open;
	}

	/*
	 * Fail if request is for zero bytes or is not even # of blocks.
	 */
	if ((bp->b_count % BSIZE) || bp->b_count == 0) {
		bp->b_flag |= BFERR;
		goto bad_open;
	}

	/*
	 * Operation appears valid.
	 * Fill fields in the node and queue the request.
	 */
	bufq_wr_tail(s_id, bp);
	ss_mach(s_id);
	goto end_open;

	/*
	 * Operation cannot be done.  Release the kernel buffer structure.
	 * Value of "bp->b_flag" tells caller if error occurred.
	 */
bad_open:
		bdone(bp);

end_open:
	return;
}

/*
 * ssintr()	- Interrupt routine.
 *
 * If we have been reselected by a recognized target device
 *	let kernel get out of interrupt mode (defer) and do SCSI
 *	reconnect stuff.
 */
static void ssintr()
{
	int s_id;

	s_id = chk_reconn();
	if (s_id != -1) {
		defer(ss_mach, s_id);
PR3("!");
	}
}

/*
 * sswatch()
 *
 * Invoked once per second if any devices going through this driver are open.
 * Poll for any reselect, in case interrupt got lost.
 */
static void sswatch()
{
	int s_id;
	ss_type * ssp;

	for (s_id = 0; s_id < MAX_SCSI_ID-1; s_id++) {
		ssp = ss[s_id];
		if (ssp && ssp->dr_watch)
			defer(ss_mach, s_id);
	} /* endfor */
}

/*
 * bus_wait()
 *
 * Wait for specified bit values to appear in Status Register.
 * This uses a tight loop and does not expect to be interrupted.
 *
 * Argument "flags" is a double-byte value;  the high byte is ANDed with
 * status register contents, and the result is tested for equality with
 * the low byte.
 *
 * Return 1 if values wanted appeared, 0 if timeout occurred.
 */
static int bus_wait(flags)
unsigned short flags;
{
	int found, i;
	unsigned char status;

	found = 0;
	for ( i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if ((status & (flags >> 8)) == (flags & 0xff)) {
			found = 1;
			break;
		}
	}

#if (DEBUG >= 1)
	if (!found)
		printf("TO:f=%x s=%x ", flags, status);
#endif

	return found;
}

/*
 * ssinit()
 *
 * Attempt to initialize the (unique) drive with a given SCSI id.
 * Assume only one drive per SCSI id, having LUN = 0.
 * 
 * Return 1 if success, 0 if failure.
 */
static int ssinit(s_id)
int s_id;
{
	int retval = 1;
	uchar query_buf[MODESENSELEN];
	ss_type * ssp = ss[s_id];
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

	if (retval)
		if (inquiry(s_id, query_buf)) {
			query_buf[INQUIRYLEN] = 0;
#if (debug >= 2)
			devmsg(dev, query_buf + 8);
#endif
			if (query_buf[0] == 0) {
				retval = 1;
			} else
				devmsg(dev, "Not Direct Access Device");
		} else
			devmsg(dev, "Inquiry Failed");

	if (retval)
		if (read_cap(s_id, query_buf)) {
			retval = 1;
			ssp->capacity = query_buf[3] | (query_buf[2] << 8)
			| (((long)(query_buf[1])) << 16)
			| (((long)(query_buf[0])) << 24);
			ssp->blocklen = query_buf[7] | (query_buf[6] << 8)
			| (((long)(query_buf[5])) << 16)
			| (((long)(query_buf[4])) << 24);
#if (DEBUG >= 3)
printf("capacity=%ld   block length=%ld\n", ssp->capacity, ssp->blocklen);
#endif
		} else
			devmsg(dev, "Read Capacity Failed");

	if (retval)
		if (mode_sense(s_id, query_buf)) {
#if (DEBUG >= 3)
#define FMT_PG	(4+8+8+12)
#define DDG_PG	(4+8+8+12+24)

uchar heads;
unsigned short spt;
ulong cyls;

spt=((int)query_buf[FMT_PG+10]<<8) + query_buf[FMT_PG+11];
cyls=((int)query_buf[DDG_PG+2]<<16) + ((int)query_buf[DDG_PG+3]<<8) + query_buf[DDG_PG+4];
heads=query_buf[DDG_PG+5];
printf("%d sectors per track\n", spt);
printf("%ld cylinders\n", cyls);
printf("%d heads\n", heads);
#endif
		} else
			devmsg(dev, "Mode Sense Failed");

	return retval;
}

/*
 * far_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * This includes message in/out, command in/out, and data in/out.
 *
 * If cmdlen is nonzero, cmdbuf is an array of bytes of that length,
 * to be sent to the target.
 *
 * Return 1 if bus timeout did not occur, else 0.
 *
 * pseudocode:
 *
 * while (wait for REQ true or BUSY false on SCSI bus)
 *   if (BUSY false)
 *     break from while loop
 *   else
 *     switch (xfer phase = RS_CTRL_DATA|RS_I_O|RS_MESSAGE)
 *       case XP_MSG_IN/XP_MSG_OUT/...
 *         handle the indicated information transfer phase
 *     endswitch
 *   endif
 * endwhile
 */
static int far_info_xfer(s_id)
int s_id;
{
	int bus_timeout;
	uchar phase_type;
	uchar msg_in;
	int s;
	int bytes_to_send;
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int xfer_good = 1;
	int xfer_count = bp->b_count - bp->b_resid;
	int i = 0;

	ssp->cmd_bytes_out = 0;
	ssp->msg_in = -1;
	s = sphi();
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		switch (phase_type) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_IRPT);
				break;
			case MSG_SAVE_DPTR:
				break;
			case MSG_RSTOR_DPTR:
				break;
			case MSG_DISCONNECT:
				ssp->msg_in = msg_in;
				sfbyte(ss_csr, WC_ENABLE_IRPT);
				break;
			case MSG_ABORT:
				break;
			case MSG_DEV_RESET:
				break;
			case MSG_IDENTIFY:
				break;
			case MSG_IDENT_DC:
				break;
			}
			break;
		case XP_MSG_OUT:
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.  Abort the bus cycle.
			 */
			sfbyte(ss_csr, WC_ENABLE_SCSI);
			sfbyte(ss_dat, MSG_ABORT); 
			break;
		case XP_STAT_IN:
			ssp->cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 * Reset SCSI bus if too many command bytes are wanted.
			 */
			bytes_to_send = ssp->cmdlen - ssp->cmd_bytes_out;
			if(bytes_to_send > 0) {
				sfbyte(ss_dat, ssp->cmdbuf[ssp->cmd_bytes_out++]);
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (bytes_to_send == 1) {
					spl(s);
					s = sphi();
				}
			} else {	/* This case should not happen. */
				xfer_good = 0;
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.  Else toss it.
			 */
			if (bp->b_req == BREAD)
				ss_get(ss_fp, bp->b_faddr + xfer_count, BSIZE);
			else
				xfer_good = 0;
			break;
		case XP_DATA_OUT:
			/*
			 * Copy output buffer bytes to data register.
			 */
			if (bp->b_req == BWRITE) {
				uchar dat;

				dat = ffbyte(bp->b_faddr + xfer_count + i);
				sfbyte(ss_dat, dat);
				i++;
			} else /* This case should not happen. */
				xfer_good = 0;
			break;
		default:
			break;
		} /* endswitch */
	}
	spl(s);
#if (DEBUG >= 1)
switch(ssp->cmdstat) {
case -1:
	if (msg_in != MSG_DISCONNECT)
		printf("CS-",ssp->cmdstat);
	break;
case CS_GOOD:
	break;
case CS_CHECK:
	printf("CSK",ssp->cmdstat);
	break;
case CS_BUSY:
	printf("CSY",ssp->cmdstat);
	break;
case CS_RESERVED:
default:
	printf("CS%x",ssp->cmdstat);
#endif
}
	return (bus_timeout) ? 0 : 1 ;
}

/*
 * req_wait()
 *
 * This routine is called at the start of each information transfer
 * phase and after the last such phase.
 *
 * It returns 1 if REQ is asserted on the SCSI bus, meaning another phase
 * may begin, and 0 otherwise.  A REQ signal will not be seen if the function
 * times out or if BUSY drops.  A value of 1 is written to the pointer argument
 * if timeout occurred, else 0 is written.
 */
static int req_wait(to_ptr)
int *to_ptr;
{
	int req_found, i;
	unsigned char status;

	*to_ptr = 1;
	req_found = 0;
	for (i = 0; i < HIPRI_RETRIES; i++) {
		status = ffbyte(ss_csr);
		if (status & RS_REQUEST) {
			req_found = 1;
			*to_ptr = 0;
			break;
		} else if ((status & RS_BUSY) == 0) {
			*to_ptr = 0;
			break;
		}
	}

#if (DEBUG >= 1)
	if (*to_ptr) {
		printf("TX: s=%x ", status);
	}
#endif

	return req_found;
}

/*
 * req_sense()
 *
 * Request Sense for a device.  The main reason for doing this is to
 * clear a standing Command Status of Device Check.
 *
 * Full results are discarded.  Return 1 if Device returns No Sense or
 * or Unit Attention.  Else return 0.
 *
 */
static int req_sense(s_id)
int s_id;
{
	uchar sense_buf[SENSELEN];
	uchar cmdbuf[G0CMDLEN];
	int ret = 0;

	cmdbuf[0] = ScmdREQUESTSENSE;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = SENSELEN;
	cmdbuf[5] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, sense_buf, SENSELEN, NULL, 0)) {
		if (sense_buf[2] == 0x00)	/* No Sense.  AOK */
			ret = 1;
		else if (sense_buf[2] == 0x06 && sense_buf[12] == 0x29)
			ret = 1;
	}

	return ret;
}

/*
 * inquiry()
 *
 * Inquiry command for a device.
 * Find out if device is direct access, removable, etc.
 *
 * Put result of inquiry into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int inquiry(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G0CMDLEN];

	cmdbuf[0] = ScmdINQUIRY;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = INQUIRYLEN;
	cmdbuf[5] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, buf, INQUIRYLEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * mode_sense()
 *
 * Mode Sense command for a device.
 * Use this to get disk parameters:
 *	number of cylinders
 *	number of heads
 *	number of sectors per track.
 *
 * Put result of mode sense into supplied buffer.
 * Return 1 if command succeeds, else 0.
 */
static int mode_sense(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G0CMDLEN];

	cmdbuf[0] = ScmdMODESENSE;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0x3F;
	cmdbuf[3] = 0;
	cmdbuf[4] = MODESENSELEN;
	cmdbuf[5] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G0CMDLEN, buf, MODESENSELEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * read_cap()
 *
 * Read Capacity command for a device.
 *
 * Return 1 if command succeeds, else 0.
 */
static int read_cap(s_id, buf)
int s_id;
uchar * buf;
{
	int ret = 0;
	uchar cmdbuf[G1CMDLEN];

	cmdbuf[0] = ScmdREADCAPACITY;
	cmdbuf[1] = 0;
	cmdbuf[2] = 0;
	cmdbuf[3] = 0;
	cmdbuf[4] = 0;
	cmdbuf[5] = 0;
	cmdbuf[6] = 0;
	cmdbuf[7] = 0;
	cmdbuf[8] = 0;
	cmdbuf[9] = 0;

	if (start_arb() && host_ident(s_id, 0) &&
	local_info_xfer(cmdbuf, G1CMDLEN, buf, READCAPLEN, NULL, 0))
		ret = 1;

	return ret;
}

/*
 * bus_dev_reset()
 *
 * Send Bus Device Reset message to the given SCSI id.
 * Return 1 if host adapter was not busy and no obvious timeouts occurred,
 * else 0.
 */
static int bus_dev_reset(s_id)
{
	int bdr_ok = 1;
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));

PR1("bdr");

	if (bdr_ok) {
		/*
		 * Do ST0x arbitration.
		 */
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

		/*
		 * SCSI spec says there is "no maximum" to the wait for
		 * arbitration complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			bdr_ok = 0;
		}
	}

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	if (bdr_ok) {
		sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			bdr_ok = 0;
	}

	if (bdr_ok) {
		sfbyte(ss_csr, WC_ENABLE_SCSI);
		sfbyte(ss_dat, MSG_DEV_RESET);
		if (!bus_wait((0xFF << 8) | 0))
			bdr_ok = 0;
	}

	return bdr_ok;
}

/*
 * chk_reconn()
 *
 * Check SELECT to see if any SCSI device has tried to reconnect to the host
 * adapter.  Called if there is an interrupt, and by the timer in case
 * we somehow lose an interrupt.
 *
 * Return -1 if no reselect detected, or the SCSI ID of the reselecting
 * target if there is one.
 */
static int chk_reconn()
{
	uchar csr, dat;
	int s_id = -1;

	csr = ffbyte(ss_csr);
	if (csr & (RS_SELECT | RS_I_O)) {
		dat = ffbyte(ss_dat);
		if ((dat & HOST_ID) && (dat & NSDRIVE)) {
			dat &= ~HOST_ID;
			s_id = 0;
			while (dat >>=1)
				s_id++;
		}
	}

	return s_id;
}

/*
 * ss_mach()
 *
 *	Gives a distinct state machine for each target device.
 */
void	ss_mach(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp;
	int s;

	do_sst_op = 1; /* plan to run this routine again in most cases */
	while (do_sst_op) {
		bp = ssp->bp;  /* nonpolled() below can change ssp->bp */
		switch (ssp->state) {
		/*
		 * Polling states execute whether ssp->waiting or not.
		 */
		case SST_POLL_ARBITN:
PR3("PA ");
			if (ffbyte(ss_csr) & RS_ARBIT_COMPL) {
				ssp->waiting = 0;
				if (host_ident(s_id, 1))
					do_connect(s_id);
				else
					recover(s_id, RV_P_TIMEOUT);
			} else {
				if (ssp->expired) {
					ssp->expired = 0;
					recover(s_id, RV_A_TIMEOUT);
				} else
					do_sst_op = 0;
			}
			break;
		case SST_POLL_BEGIN_IO:
PR3("PBI ");
			if (bp == NULL)
				ssp->state = SST_DEQUEUE;
			else {
				/*
				 * At this point a SCSI command is about to
				 * be initiated.  It may be a retry.
				 */
				if (host_claimed == -1 && BUS_FREE && BUS_FREE) {
					host_claimed = s_id;
					ssp->waiting = 0;
					init_pointers(s_id);
					s=sphi();
					if (start_arb()) {
						if (host_ident(s_id, 1)) {
							do_connect(s_id);
							spl(s);
						} else {
							spl(s);
							recover(s_id, RV_P_TIMEOUT);
						}
					} else {
						spl(s);
						ssp->state = SST_POLL_ARBITN;
						set_timeout(s_id, DELAY_ARB);
					}
				} else { /* host busy or bus not free */
					++ssp->avl_count;
					if (ssp->avl_count >= MAX_AVL_COUNT)
						recover(s_id, RV_BF_TIMEOUT);
					else
						set_timeout(s_id, DELAY_BSY);
				}
			}
			break;
		case SST_POLL_RESELECT:
PR3("PR ");
			if (TGT_RSEL) {
				ssp->waiting = 0;
				s=sphi();
				if (rsel_handshake()) {
					do_connect(s_id);
					spl(s);
				} else {
					spl(s);
					recover(s_id, RV_P_TIMEOUT);
				}
			} else  { /* Reselect poll is negative */
				if (ssp->expired) {
					ssp->expired = 0;
					recover(s_id, RV_R_TIMEOUT);
				} else
					do_sst_op = 0;
			}
			break;
		default:
			if (ssp->waiting)
				do_sst_op = 0;
			else {
				/*
				 * Nonpolling states execute only if no
				 * target timer is running.
				 */
				nonpolled(s_id);
			}
		} /* endswitch */
	} /* endwhile */
}

/*
 * nonpolled()
 *
 * Part of ss_mach() - handling of nonpolling states is taken out simply
 * for readability.
 */
static void nonpolled(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	struct	fdisk_s	*fdp;
	int partition;
	dev_t dev;

	switch (ssp->state) {
	case SST_BUS_DEV_RESET:
PR3("BDR ");
		if (bus_dev_reset(s_id)) {
			do_sst_op = 0;
			set_timeout(s_id, DELAY_BDR);
			ssp->state = SST_REQ_SENSE;
		} else
			recover(s_id, RV_P_TIMEOUT);
		break;
	case SST_DEQUEUE:
		if(bufq_rd_head(s_id) != NULL && !ssp->busy) {
PR3("DQ ");
			ssp->busy = 1;
			bp = bufq_rm_head(s_id);
			ssp->bp = bp;
			dev = bp->b_dev;
			partition = DEV_PARTN(dev);
			if (dev & SDEV)
				partition = WHOLE_DRIVE;
			fdp = ssp->parmp;
			if (partition != WHOLE_DRIVE)
				ssp->bno = fdp[partition].p_base + bp->b_bno;
			else
				ssp->bno = bp->b_bno;
			if (bp->b_req == BREAD)
				ssp->cmdbuf[0] = ScmdREADEXTENDED;
			else
				ssp->cmdbuf[0] = ScmdWRITEXTENDED;
			ssp->cmdbuf[1] = 0;
			ssp->cmdbuf[2] = ssp->bno >> 24;
			ssp->cmdbuf[3] = ssp->bno >> 16;
			ssp->cmdbuf[4] = ssp->bno >>  8;
			ssp->cmdbuf[5] = ssp->bno;
			ssp->cmdbuf[6] = 0;
			ssp->cmdbuf[7] = 0;
			ssp->cmdbuf[8] = 1;
			ssp->cmdbuf[9] = 0;
			ssp->cmdlen = G1CMDLEN;
			init_pointers(s_id);
			ssp->bdr_count = 0;
			ssp->bsy_count = 0;
			ssp->try_count = 0;
			ssp->state = SST_POLL_BEGIN_IO;
		} else /* queue is empty or ssp->busy */
			do_sst_op = 0;
		break;
	case SST_HIPRI_RESET:
	case SST_LOPRI_RESET:
PR1("rst");
if ((ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA)) == XP_MSG_OUT) {
	printf("honk");
	sfbyte(ss_csr, WC_ENABLE_SCSI);
	sfbyte(ss_dat, MSG_ABORT); 
}
		/*
		 * SST_LOPRI_RESET is same as SST_HIPRI_RESET for now.
		 * Later, can implement a delay to allow other targets to
		 * finish pending operations.
		 */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET); /* reset ON */
		ssp->state = SST_RESET_OFF;
		set_timeout(s_id, DELAY_RST);
		break;
	case SST_REQ_SENSE:
PR1("RQS ");
		if (req_sense(s_id))
			ssp->state = SST_POLL_BEGIN_IO;
		else
			recover(s_id, RV_P_TIMEOUT);
		break;
	case SST_RESET_DONE:
PR3("RDN ");
		ssp->state = SST_POLL_BEGIN_IO;
		break;
	case SST_RESET_OFF:
PR3("RFF ");
		sfbyte(ss_csr, 0); /* reset OFF */
		ssp->state = SST_RESET_DONE;
		set_timeout(s_id, DELAY_RST);
	} /* endswitch */
}

/*
 * start_arb()
 *
 * return 1 if host adapter returned Arbitration Complete within allotted
 * number of tries, else 0
 */
static int start_arb()
{
	sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
	sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
	sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

	/*
	 * SCSI spec says there is "no maximum" to the wait for arbitration
	 * complete.
	 */
	return bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL);
}

/*
 * host_ident()
 *
 * This routine is the bridge in a SCSI bus cycle between Abitration
 * Complete and the Information Transfer phases.
 *
 * return 1 if everything went ok, 0 in case of timeout
 */
static int host_ident(s_id, disconnect)
int s_id;
int disconnect;
{
	int ret = 0;

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

	if (bus_wait(RS_BUSY << 8 | RS_BUSY)) {
		/*
		 * Assert ATTN so target expects incoming message byte.
		 */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

		if (bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE))) {
			if (disconnect)
				sfbyte(ss_dat, MSG_IDENT_DC);
			else
				sfbyte(ss_dat, MSG_IDENTIFY);
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ENABLE_IRPT);
			ret = 1;
		}
	}
	return ret;
}

/*
 * rsel_handshake()
 *
 * After Reselect is detected, a couple steps are needed before entering
 * Information Transfer phases.  This routine does those steps.
 *
 * return 1 if ok, 0 in case of timeout.
 */
static int rsel_handshake()
{
	int ret = 0;

	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
	if (bus_wait(RS_SELECT << 8 | 0)) {
		sfbyte(ss_csr, WC_ENABLE_SCSI);
		ret = 1;
	}
	return ret;
}

/*
 * set_timeout()
 *
 * Start a timer so as not to wait forever in case something goes wrong while
 * waiting for an event.  Available delays are:
 *
 * 	DELAY_ARB -	wait for arbitration complete
 * 	DELAY_BDR -	allow settling time after Bus Device Reset
 * 	DELAY_BSY -	wait for not HOST_BUSY and bus free
 * 	DELAY_RES -	wait for reselect by target
 * 	DELAY_RST -	allow settling times when doing SCSI Bus Reset
 *
 * Second argument is number of clock ticks to wait until timer expiration.
 */
static void set_timeout(s_id, delay)
int s_id, delay;
{
	ss_type * ssp = ss[s_id];

	ssp->expired = 0;
	ssp->waiting = 1;
	do_sst_op =  0;
	timeout(&(ssp->tim), delay, stop_timeout, s_id);
}

/*
 * stop_timeout()
 *
 * Called on expiration of the timer for a given target.
 * Don't expire a timer if it's no longer active.
 */
static void stop_timeout(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];

	if (ssp->waiting) {
		ssp->expired = 1;
		ssp->waiting = 0;
	}
	ss_mach(s_id);
}

/*
 * init_pointers()
 *
 * Initialize command and data pointers when starting (or restarting)
 * a block i/o command.
 */
static void init_pointers(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

	ssp->cmdstat = -1;
	ssp->cmd_bytes_out = 0;
	ssp->avl_count = 0;
}

/*
 * recover()
 *
 * This routine is called directly or indirectly from ss_mach().  It
 * determines what to do when the interface fails to behave as desired.
 *
 * Arguments are the SCSI id of the target HDC and an error type.
 * Error types are:
 *
 * RV_A_TIMEOUT (arbitration timeout)
 * Host adapter takes too long to respond with arbitration complete.
 * 
 * RV_P_TIMEOUT (protocol timeout)
 * Timeout waiting for desired SCSI bus status while connected to a target.
 * 
 * RV_R_TIMEOUT (reconnect timeout)
 * Timeout after target disconnects, waiting for reconnect.
 * 
 * RV_BF_TIMEOUT (bus free timeout)
 * Waited too long for host not busy and BUS_FREE.
 * 
 * RV_CS_BUSY (target device busy)
 * Command status returned was Busy.
 * 
 * RV_CS_CHECK (target device check)
 * Command status returned was CHECK.
 * 
 * Whenever an error occurs, one of the above inputs, together with the SCSI id
 * of the target, is sent to the recovery process.  The recovery process in turn
 * programs the next state for the machine.
 */
static void recover(s_id, errtype)
int s_id;
RV_TYPE errtype;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

	++ssp->try_count;
	if (ssp->try_count < MAX_TRY_COUNT) {

		switch (errtype) {

		case RV_CS_BUSY:
			++ssp->bsy_count;
			if (ssp->bsy_count < MAX_BSY_COUNT) {
				ssp->state = SST_POLL_BEGIN_IO;
				set_timeout(s_id, DELAY_BSY);
			} else
				ssp->state = SST_BUS_DEV_RESET;
			break;

		case RV_CS_CHECK:
			ssp->state = SST_REQ_SENSE;
			break;

		case RV_P_TIMEOUT:
			/* fall thru */
		case RV_R_TIMEOUT:
			++ssp->bdr_count;
			if (ssp->bdr_count < MAX_BDR_COUNT)
				ssp->state = SST_BUS_DEV_RESET;
			else
				ssp->state = SST_LOPRI_RESET;
			break;

		case RV_BF_TIMEOUT:
			host_claimed = -1;
			/* fall thru */
		case RV_A_TIMEOUT:
			ssp->state = SST_HIPRI_RESET;
		}
	} else { /* try_count >= MAX_TRY_COUNT */
		if (bp) {
			bp->b_flag |= BFERR;
PR3("BF4 ");
		}
		ss_finished(s_id);
	}
}

/*
 * ss_finished
 *
 * Release current i/o buffer to the O/S.
 */
static void ss_finished(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int go_again = 1;

	if (host_claimed == s_id)
		host_claimed = -1;
	ssp->busy = 0;
	if (bp) {
		if (!(bp->b_flag & BFERR))
			bp->b_resid -= BSIZE;
		if ((bp->b_flag & BFERR) || bp->b_resid == 0) {
			ssp->bp = NULL;
			bdone(bp);
			go_again = 0;
		}
	}
	if (go_again) {
		ssp->state = SST_POLL_BEGIN_IO;
		ssp->bdr_count = 0;
		ssp->bsy_count = 0;
		ssp->try_count = 0;
	} else
		ssp->state = SST_DEQUEUE;
}

/*
 * do_connect()
 *
 * This function is called when the host is successfully connected to
 * the target.
 */
static void do_connect(s_id)
int s_id;
{
	int result;
	ss_type * ssp = ss[s_id];

	result = far_info_xfer(s_id);
	if (host_claimed == s_id)
		host_claimed = -1;
	if (!result)
		recover(s_id, RV_P_TIMEOUT);
	else if (ssp->msg_in == MSG_DISCONNECT) {
		ssp->state = SST_POLL_RESELECT;
		set_timeout(s_id, DELAY_RES);
	} else if (ssp->msg_in == MSG_CMD_CMPLT && ssp->cmdstat == CS_GOOD)
		ss_finished(s_id);
	else if (ssp->cmdstat == CS_BUSY)
		recover(s_id, RV_CS_BUSY);
	else if (ssp->cmdstat == CS_CHECK)
		recover(s_id, RV_CS_CHECK);
	else  /* something else went wrong */
		recover(s_id, RV_P_TIMEOUT);
}

/*
 * local_info_xfer()
 *
 * Do bus cycle information transfer phases.
 * Transfer is for a command which will produce local results in the driver.
 * Other ...info_xfer routine handles kernel block i/o commands.
 *
 * Return 1 if transfer succeeded, else 0.
 *
 */
static int local_info_xfer(cmdbuf, cmdlen, inbuf, inlen, outbuf, outlen)
uchar * cmdbuf, * inbuf, * outbuf;
uint cmdlen, inlen, outlen;
{
	int bus_timeout;
	uchar phase_type;
	int s;
	int cmd_bytes_out = 0;
	int data_bytes_in = 0;
	int data_bytes_out = 0;
	int ret = 0;
	int xfer_good = 1;
	int cmdstat = -1;
	int msg_in = -1;

	s = sphi();
	while (req_wait(&bus_timeout) && xfer_good) {
		phase_type = ffbyte(ss_csr) & (RS_MESSAGE|RS_I_O|RS_CTRL_DATA);
		switch (phase_type) {
		case XP_MSG_IN:
			msg_in = ffbyte(ss_dat);
			switch(msg_in){
			case MSG_CMD_CMPLT:
			case MSG_DISCONNECT:
				sfbyte(ss_csr, WC_ENABLE_IRPT);
				break;
			}
			break;
		case XP_MSG_OUT:
			/*
			 * This case shouldn't happen.  We weren't
			 * asserting ATTENTION.  Abort the bus cycle.
			 */
			sfbyte(ss_csr, WC_ENABLE_SCSI);
			sfbyte(ss_dat, MSG_ABORT); 
			break;
		case XP_STAT_IN:
			cmdstat = ffbyte(ss_dat);
			break;
		case XP_CMD_OUT:
			/*
			 * Ship out command bytes.
			 */
			if (cmd_bytes_out < cmdlen) {
				sfbyte(ss_dat, cmdbuf[cmd_bytes_out++]);
				/*
				 * If just sent last byte, allow interrupts.
				 */
				if (cmd_bytes_out == cmdlen) {
					spl(s);
					s = sphi();
				}
			} else {	/* This case should not happen. */
				xfer_good = 0;
			}
			break;
		case XP_DATA_IN:
			/*
			 * If caller's buffer has room, keep incoming
			 * data byte.  Else toss it.
			 */
			if (data_bytes_in < inlen) {
				inbuf[data_bytes_in++] = ffbyte(ss_dat);
			} else
				ffbyte(ss_dat);
			break;
		case XP_DATA_OUT:
			/*
			 * Copy output buffer bytes to data register.
			 */
			if (data_bytes_out < outlen) {
				sfbyte(outbuf[data_bytes_out++], ss_dat);
			} else { /* This case should not happen. */
				xfer_good = 0;
			}
			break;
		default:
			break;
		} /* endswitch */
	}
	spl(s);

	if (!bus_timeout && xfer_good && cmdstat == CS_GOOD)
		ret = 1;

	host_claimed = -1;
	return ret;
}
@


1.45
log
@Still trying to test ss_get.  Always hangs.
@
text
@a11 1
 *	mask interrupts on finishing arbitration, etc.
d17 3
a165 2
	int	data_bytes_in;
	int	data_bytes_out;
a626 1
	int valid_op = 1;
d640 2
d650 1
a650 1
				valid_op = 0;
d656 1
a656 1
			valid_op = 0;
d659 1
d665 1
a665 1
		valid_op = 0;
d667 1
d675 1
a675 1
		valid_op = 0;
d679 8
d690 4
a693 4
	if (valid_op) {
		bufq_wr_tail(s_id, bp);
		ss_mach(s_id);
	}
d698 1
a698 1
	else { 	/* "valid_op" is FALSE */
d700 3
a702 1
	}
d878 2
a879 1
int first=1;
d947 4
a950 23
if (bp->b_req == BREAD) {
	if (first) {
		first=0;
		printf("ss_fp=%lx ", ss_fp);
		printf("buf_f=%lx resid=%d ", bp->b_faddr, bp->b_resid);
	}
#if 0
	if (bp->b_resid <= SS_DAT_LEN) {
		ss_get(ss_fp, bp->b_faddr, (uint)bp->b_resid);
printf("word 1FC = %x\n", ffword(bp->b_faddr+0x1fc));
ssp->data_bytes_in += bp->b_resid;
	} else
#endif
			if (ssp->data_bytes_in < bp->b_count) {
				uchar dat;

				dat = ffbyte(ss_dat);
				sfbyte(bp->b_faddr + ssp->data_bytes_in, dat);
				ssp->data_bytes_in++;
			} else
				ffbyte(ss_dat);
} else
	xfer_good = 0;
d956 1
a956 2
if (bp->b_req == BWRITE) {
			if (ssp->data_bytes_out < bp->b_count) {
d959 1
a959 1
				dat = ffbyte(bp->b_faddr + ssp->data_bytes_out);
d961 2
a962 2
				ssp->data_bytes_out++;
			} else { /* This case should not happen. */
a963 3
			}
} else
	xfer_good = 0;
d1406 2
a1407 2
			ssp->cmdbuf[7] = bp->b_count / (BSIZE * 256L);
			ssp->cmdbuf[8] = bp->b_count / BSIZE;
a1587 2
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
a1589 3
	if (bp) {
		bp->b_resid = bp->b_count;
	}
d1683 1
d1689 7
a1695 6
		ssp->bp = NULL;
		if (bp->b_req == BREAD)
			bp->b_resid -= ssp->data_bytes_in;
		else
			bp->b_resid -= ssp->data_bytes_out;
		bdone(bp);
d1697 7
a1703 3
	ssp->state = SST_DEQUEUE;
	do_sst_op = 0;
	set_timeout(2);
@


1.44
log
@Drop unneeded fields from ss struct.  Try ss_get().
@
text
@d18 3
d311 1
a311 1

d865 1
d934 7
a940 1
	if (bp->b_resid <= SS_DAT_LEN)
d942 4
a945 1
	else {
a953 1
	}
d1430 5
d1679 1
a1679 1
		if (bp)
d1681 2
@


1.43
log
@Needs assembler I/O most.
@
text
@d18 3
a160 2
	faddr_t	in_buf;
	int	in_buf_len;
a161 2
	faddr_t	out_buf;
	int	out_buf_len;
d860 1
d929 5
a933 1
			if (ssp->data_bytes_in < ssp->in_buf_len && ssp->in_buf) {
d937 1
a937 1
				sfbyte(ssp->in_buf + ssp->data_bytes_in, dat);
d941 3
d949 2
a950 1
			if (ssp->data_bytes_out < ssp->out_buf_len && ssp->out_buf) {
d953 1
a953 1
				dat = ffbyte(ssp->out_buf + ssp->data_bytes_out);
d959 2
a1585 11
		if (bp->b_req == BREAD) {
			ssp->in_buf_len = bp->b_count;
			ssp->in_buf = bp->b_faddr;
			ssp->out_buf_len = 0;
			ssp->out_buf = NULL;
		} else {
			ssp->in_buf_len = 0;
			ssp->in_buf = NULL;
			ssp->out_buf_len = bp->b_count;
			ssp->out_buf = bp->b_faddr;
		}
a1681 1
	ssp->in_buf = ssp->out_buf = NULL;
d1691 2
@


1.42
log
@COH fdisk command gives junk when DEBUG=1, ok if DEBUG=3
@
text
@d18 3
d598 1
a599 1
#endif
d1608 1
a1608 1
 * RV_BF_TIMEOUT (reconnect timeout)
a1685 1
		ssp->state = SST_DEQUEUE;
d1692 1
@


1.41
log
@First working version.
@
text
@a11 1
 *	bus_pre_xfer() -> start_arb() + host_ident()
d18 3
a201 1
static int	bus_pre_xfer();
d826 1
a826 1
 * bus_pre_xfer()
a827 55
 * Do bus cycle phases prior to the information transfer phases.
 * This includes arbitration and selection.
 */
static int bus_pre_xfer(s_id)
int s_id;
{
	int dev = ((sscon.c_mind << 8) | 0x80 | (s_id << 4));
	int ret = 0;

	/*
	 * Do ST0x arbitration.
	 */
	sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
	sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
	sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */

	/*
	 * SCSI spec says there is "no maximum" to the wait for arbitration
	 * complete.
	 */
	if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
		if (ffbyte(ss_csr) & (RS_REQUEST|RS_BUSY))
			ret = 1;
		goto frotz;
	}

	/*
	 * Arbitration complete.  Now select, with ATN to allow messages.
	 */
	sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);

	if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
		goto frotz;

	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);

	if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
	| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
		goto frotz;

	/*
	 * Disallow Disconnect.
	 */
	sfbyte(ss_dat, MSG_IDENTIFY);
	sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ENABLE_IRPT);
	ret = 1;

frotz:
	return ret;
}

/*
 * far_info_xfer()
 *
d863 1
a863 1
	while(req_wait(&bus_timeout) && xfer_good) {
d1040 1
a1040 1
	if (bus_pre_xfer(s_id) &&
d1074 1
a1074 1
	if (bus_pre_xfer(s_id) &&
d1107 1
a1107 1
	if (bus_pre_xfer(s_id) &&
d1139 1
a1139 1
	if (bus_pre_xfer(s_id) &&
d1258 1
a1258 1
				if (host_ident(s_id))
d1285 1
a1285 1
						if (host_ident(s_id)) {
d1453 1
a1453 1
 * host_ident(s_id)
d1460 1
a1460 1
static int host_ident(s_id)
d1462 1
d1480 4
a1483 1
			sfbyte(ss_dat, MSG_IDENT_DC); /* allow Disconnect */
d1748 1
a1748 1
	while(req_wait(&bus_timeout) && xfer_good) {
@


1.41.1.1
log
@Comment out spl stuff in ss_mach().
@
text
@a18 3
 * Revision 1.41	91/05/15  21:57:55	root
 * First working version.
 * 
d1337 1
a1337 1
/* ZZ					s=sphi(); */
d1341 1
a1341 1
/* ZZ							spl(s); */
d1343 1
a1343 1
/* ZZ							spl(s); */
d1347 1
a1347 1
/* ZZ						spl(s); */
d1364 1
a1364 1
/* ZZ				s=sphi(); */
d1367 1
a1367 1
/* ZZ					spl(s); */
d1369 1
a1369 1
/* ZZ					spl(s); */
@


1.40
log
@First clean compile of state machine version.
@
text
@d5 2
a6 4
 *	local commands: (right now there aren't any!)
 *		local_buf = 0
 *		local_done = 0
 *		local_failed = 0
a7 5
 * Cleanup:
 *	set host_claimed conscientiously
 *	get rid of declarations for deleted functions
 *
 * To try after initial working version:
d15 2
d19 3
d36 23
d62 1
a62 1
#define bufq_wr_tail(s_id, foo)	ssq_wr_head(foo)
a99 1
#define WATCHDOG_SECONDS  4
a100 2
#define IN_BUF_SIZE	512	/* buffer size in "ss" structs */

d120 1
a168 3
	uint	local_buf:1;	/* 1 if command uses local buffer */
	uint	local_done:1;	/* 1 if local command is finished */
	uint	local_fail:1;	/* 1 if local command ended in error */
a212 1
static int	rezero();
a213 3
static int	scsicmd();
static void	scsireset();
static void	ss_done();
a272 3
static TIM	reset_tim;	/* needed for calls to scsireset() */
static TIM	timeout_tim;	/* needed for calls to timeout() */

d411 2
d414 2
d448 3
a450 1
devmsg(fdisk_dev, "calling fdisk");
d452 2
a453 1
int p;
d456 2
a457 2
printf("fdisk() succeeded\n");
for (p=0; p<=WHOLE_DRIVE; p++)
d461 1
a461 1
printf("fdisk() failed\n");
d465 11
d520 2
d523 2
d585 1
a585 1
printf("HDGETA ");
d591 1
d595 1
d641 1
a641 1
printf("BF1 ");
d646 1
a646 1
printf("BF2 ");
d664 1
a664 1
printf("BF3 ");
d698 1
a698 1
	if (s_id != -1)
d700 2
d749 1
d752 1
d776 1
d778 1
d795 1
d797 1
d803 1
d806 5
a810 3
			uchar heads;
			unsigned short spt;
			ulong cyls;
d817 1
d1008 1
d1025 1
d1029 1
d1061 2
a1062 1
	if (*to_ptr)
d1064 2
d1212 1
a1212 1
printf("bdr");
d1298 2
a1299 1
	BUF * bp = ssp->bp;
d1303 1
d1309 1
d1325 2
a1326 1
			if (bp == NULL && ssp->local_buf == 0)
d1337 1
d1339 1
a1339 1
						if (host_ident(s_id))
d1341 3
a1343 1
						else
d1345 1
d1347 1
d1361 1
d1364 2
a1365 1
				if (rsel_handshake())
d1367 3
a1369 1
				else
d1371 1
d1411 1
d1421 1
d1458 1
d1469 1
d1476 1
d1480 1
d1533 1
a1533 8
			/*
			 * If using a local buffer rather than doing a kernel
			 * block i/o request, inhibit Disconnect.
			 */
			if (ss[s_id]->local_buf)
				sfbyte(ss_dat, MSG_IDENTIFY);
			else
				sfbyte(ss_dat, MSG_IDENT_DC);
a1711 3
		if (ssp->local_buf) {
			ssp->local_fail = 1;
		}
a1739 5
	if (ssp->local_buf) {
		ssp->local_buf = 0;
		ssp->local_done = 1;
		ssp->state = SST_POLL_BEGIN_IO;
	}
@


1.40.1.1
log
@Fix 2 bugs in version 1.40
@
text
@a23 3
 * Revision 1.40	91/05/15  15:19:52	root
 * First clean compile of state machine version.
 * 
d41 1
a41 1
#define bufq_wr_tail(s_id, foo)	ssq_wr_tail(foo)
d1247 1
a1247 1
	BUF * bp;
a1250 1
		bp = ssp->bp;
@


1.39
log
@Code recover, do_connect, etc..
@
text
@d2 1
a2 1
 * This is a driver for Seagate ST01/ST02 scsi host adapters.
d5 7
a12 8
 *	if (bp->b_req == BREAD) {...
 *	set host_claimed conscientiously
 *	ss_start() code moved elsewhere
 *	initialize and maintain retry counters
 *	inquiry()
 *	read_cap()
 *	mode_sense()
 *	req_sense() <- called from dblock!!!
d21 1
d24 3
d38 5
a183 1
static int	bus_info_xfer();
d187 1
d191 1
d202 1
a203 3
static void	ss_start();
static void	ss_start_timing();
static void	ss_stop_timing();
a204 1
static void	ssdelay();
a260 1
static TIM	delay_tim;	/* needed for calls to ssdelay() */
a261 1
static TIM	sst_tim;	/* for timeout() call from ss_start() */
a583 1
	register int s;
d641 1
a641 1
		bufq_wr_tail(bp, s_id);
d643 1
d648 1
a648 1
	} else { 	/* "valid_op" is FALSE */
a730 1
	int try;
d780 1
a780 1
 * ssdelay()
a781 16
 * Delay for some number of clock ticks.
 * 286/386 kernel ticks are at 100Hz
 *
 * This routine is of limited use as it can only be called via
 * ssload()/ssunload()/ssopen()/ssclose().
 */
static void ssdelay(ticks)
int ticks;
{
	timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
}

/*
 * bus_pre_xfer()
 *
a787 1
	int tries;
d791 6
a796 8
	for (tries = 0; !ret && tries < LOPRI_RETRIES; tries++) {
if (tries>0)break;
		/*
		 * Do ST0x arbitration.
		 */
		sfbyte(ss_csr, 0);		/* De-assert SCSI enable bit */
		sfbyte(ss_dat, HOST_ID);	/* Write my SCSI id to port */
		sfbyte(ss_csr, WC_ARBITRATE);	/* Start arbitration */
d798 9
a806 9
		/*
		 * SCSI spec says there is "no maximum" to the wait for arbitration
		 * complete.
		 */
		if (!bus_wait(RS_ARBIT_COMPL << 8 | RS_ARBIT_COMPL)) {
			if (ffbyte(ss_csr) & (RS_REQUEST|RS_BUSY))
				ret = 1;
			continue;
		}
d808 5
a812 5
		/*
		 * Arbitration complete.  Now select, with ATN to allow messages.
		 */
		sfbyte(ss_dat, HOST_ID | (1 << s_id));	/* Write both SCSI id's */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION | WC_SELECT);
d814 2
a815 2
		if (!bus_wait(RS_BUSY << 8 | RS_BUSY))
			continue;
d817 1
a817 4
		/*
		 * Send "Identify" Message with Disconnect allowed.
		 */
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ATTENTION);
d819 3
a821 3
		if (!bus_wait(((RS_REQUEST|RS_CTRL_DATA|RS_I_O|RS_MESSAGE) << 8)
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
			continue;
d823 6
a828 11
		/*
		 * During ssload(), diagnostics are running and we don't
		 * want disconnects.  At other times, disconnect is ok.
		 */
		if (loading)
			sfbyte(ss_dat, MSG_IDENTIFY);
		else
			sfbyte(ss_dat, MSG_IDENT_DC);
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_ENABLE_IRPT);
		ret = 1;
	}
d830 1
d835 1
a835 1
 * bus_info_xfer()
d858 2
a859 2
static int bus_info_xfer(ssp)
ss_type *ssp;
a863 1
	int no_msg_rcvd = 1;
d866 2
a867 1
int we_wrote=0;
d872 1
a872 1
	while(req_wait(&bus_timeout)) {
d927 1
a927 1
				scsireset();
a944 6
#if 0
if (!we_wrote) {
	we_wrote=1;
	printf("W");
}
#endif
d955 1
a955 1
				scsireset();
d965 2
d1033 1
d1036 6
a1041 12
	rqs.cmdstat = -1;
	rqs.data_bytes_in = 0;
	rqs.data_bytes_out = 0;
	rqs.cmdbuf[0] = ScmdREQUESTSENSE;
	rqs.cmdbuf[1] = rqs.cmdbuf[2] = rqs.cmdbuf[3] =
		rqs.cmdbuf[5] = 0;
		rqs.cmdbuf[4] = SENSELEN;
	rqs.cmdlen = G0CMDLEN;
	rqs.in_buf_len = SENSELEN;
	rqs.out_buf_len = 0;
	FP_OFF(rqs.in_buf) = sense_buf;
	FP_SEL(rqs.in_buf) = sds;
d1043 6
a1048 8
	if (bus_pre_xfer(s_id)) {
		bus_info_xfer(&rqs);
		if (rqs.data_bytes_in == SENSELEN) {
			if (sense_buf[2] == 0x00)	/* No Sense.  AOK */
				ret = 1;
			else if (sense_buf[2] == 0x06 && sense_buf[12] == 0x29)
				ret = 1;
		}
d1068 1
a1068 1
	ss_type * ssp = ss[s_id];
d1070 6
a1075 13
	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->id_busy = 1;
	ssp->cmdbuf[0] = ScmdINQUIRY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] =
		ssp->cmdbuf[5] = 0;
		ssp->cmdbuf[4] = INQUIRYLEN;
	ssp->cmdlen = G0CMDLEN;
	FP_OFF(ssp->in_buf) = buf;
	FP_SEL(ssp->in_buf) = sds;
	ssp->in_buf_len = INQUIRYLEN;
	ssp->out_buf_len = 0;
d1077 3
a1079 2
	ret = scsicmd(s_id);
	ssp->id_busy = 0;
d1101 1
a1101 1
	ss_type * ssp = ss[s_id];
d1103 6
a1108 15
	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->id_busy = 1;
	ssp->cmdbuf[0] = ScmdMODESENSE;
	ssp->cmdbuf[1] = 0;
	ssp->cmdbuf[2] = 0x3F;
	ssp->cmdbuf[3] = 0;
	ssp->cmdbuf[4] = MODESENSELEN;
	ssp->cmdbuf[5] = 0;
	ssp->cmdlen = G0CMDLEN;
	FP_OFF(ssp->in_buf) = buf;
	FP_SEL(ssp->in_buf) = sds;
	ssp->in_buf_len = MODESENSELEN;
	ssp->out_buf_len = 0;
d1110 3
a1112 2
	ret = scsicmd(s_id);
	ssp->id_busy = 0;
d1129 1
a1129 1
	ss_type * ssp = ss[s_id];
d1131 10
a1140 13
	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->id_busy = 1;
	ssp->cmdbuf[0] = ScmdREADCAPACITY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] = 0;
	ssp->cmdbuf[5] = ssp->cmdbuf[6] = ssp->cmdbuf[7] = ssp->cmdbuf[8] = 0;
	ssp->cmdbuf[9] = 0;
	ssp->cmdlen = G1CMDLEN;
	FP_OFF(ssp->in_buf) = buf;
	FP_SEL(ssp->in_buf) = sds;
	ssp->in_buf_len = 8;
	ssp->out_buf_len = 0;
d1142 3
a1144 2
	ret = scsicmd(s_id);
	ssp->id_busy = 0;
d1150 1
a1150 1
 * ss_start()
a1151 91
 * Invoked whenever there might be I/O to do.
 *
 * Disallow re-entrancy in this routine (variable "locked").
 * If there is a next I/O request queued (peek at head of queue)
 *   get the target SCSI ID.
 *   If target is not busy
 *     remove request from queue
 *     mark target device busy
 *     start watchdog timer
 *     send command to host adapter
 *     if command succeeded
 *       cleanup after command
 *       adjust b_resid field
 *     else if command failed
 *       set error flag
 *       cleanup after command
 *     else (disconnected)
 *       do nothing
 */
static void ss_start()
{
#define RW_TRIES	5
	int s;
	BUF * bp;
	static char locked;
	int s_id;
	ss_type * ssp;
	struct	fdisk_s	*fdp;
	int partition;
	dev_t dev;
	static int retry[MAX_SCSI_ID-1];

	s = sphi();
	if(locked) {
		spl(s);
		return;
	}
	++locked;
	spl(s);

	if (st0x_busy) {
		timeout(&sst_tim, 50, ss_start, 0);
		return;
	}

	if((bp = ssq_rd_head()) != NULL) {
		s_id = DEV_SCSI_ID(bp->b_dev);
		ssp = ss[s_id];
		dev = bp->b_dev;
		partition = DEV_PARTN(dev);
		if (dev & SDEV)
			partition = WHOLE_DRIVE;
		fdp = ssp->parmp;
		if (!(ssp->id_busy)) {
			if (partition != WHOLE_DRIVE)
				ssp->bno = fdp[partition].p_base + bp->b_bno;
			else
				ssp->bno = bp->b_bno;
			ssp->bp = bp;
			ssp->id_busy = 1;
			ssp->dr_watch = WATCHDOG_SECONDS;
			if (ss_rw(s_id)) {
				retry[s_id] = 0;
				ssq_rm_head();
				if (bp->b_req == BREAD)
					bp->b_resid -= ssp->data_bytes_in;
				else
					bp->b_resid -= ssp->data_bytes_out;
				if (ssp->msg_in != MSG_DISCONNECT)
					ss_done(s_id);
			} else {
				if (++retry[s_id] > RW_TRIES) {
printf("BF5 ");
					retry[s_id] = 0;
					ssq_rm_head();
					bp->b_flag |= BFERR;
					ss_done(s_id);
				} else {
					ssp->id_busy = 0;
					timeout(&sst_tim, 10, ss_start, 0);
printf("R%d ",retry[s_id]);
				}
			}
		}
	}
	--locked;
}

/*
 * bus_dev_reset()
 *
a1267 1
				endif
d1278 1
a1278 1
				if (host_claimed == -1 && BUS_FREE) {
d1291 1
a1291 1
				} else  /* host busy or bus not free */
d1340 3
d1357 14
a1370 1
			init_pointers(s_id);
d1381 4
d1461 1
a1461 1
		| (RS_REQUEST|RS_CTRL_DATA|RS_MESSAGE)))
d1466 1
a1466 1
			if (ss[s_id]->local_buf))
d1517 1
a1517 1
	ssp->timing = 1;
d1528 1
a1528 1
static void stop_timeout(s_id);
a1559 1
			ssp->cmdbuf[0] = ScmdREADEXTENDED;
a1564 1
			ssp->cmdbuf[0] = ScmdWRITEXTENDED;
d1622 1
a1622 2
				ssp->state = SST_BUS_DEV_RST;
			}
d1634 1
a1634 1
				ssp->state = SST_BUS_DEV_RST;
a1636 1
			}
d1642 1
a1642 1
		case RV_A_TIMEOUT
d1645 1
a1645 1
	else { /* try_count >= MAX_TRY_COUNT */
a1670 1
		bdone(bp);
d1673 5
d1682 1
d1696 1
d1698 1
a1698 1
	result = info_xfer(s_id);
d1704 1
a1704 1
		target_state = SST_POLL_RESELECT;
d1708 1
a1708 1
	} else if (ssp->cmdstat == CS_BUSY)
d1710 1
a1710 1
	} else if (ssp->cmdstat == CS_CHECK)
d1715 99
@


1.38
log
@Code ss_mach().
@
text
@d5 16
a20 4
 *	bufq_wr_tail
 *	recover()
 *	do_connect()
 *	set_timeout()
d24 3
d80 11
d94 1
a94 1
typedef enum {
d106 10
d121 1
a121 1
	int	dr_watch;	/* number of seconds for pending timeout */
d136 11
a146 5
	unsigned int	busy:1;		/* 1 if command uses local buffer */
	unsigned int	expired:1;	/* 1 if target's timer has expired */
	unsigned int	local_buf:1;	/* 1 if command uses local buffer */
	unsigned int	ptab_read:1;	/* 1 if partition table has been read */
	unsigned int	waiting:1;	/* 1 if target timer is running */
d179 1
d181 1
d186 1
a186 1
static void	reconnect();
a193 1
static int	ss_rw();
d197 1
d202 1
d261 1
a261 1
static int	host_busy;	/* 1 when host is arbitrating or connected */
d341 1
d662 1
a662 1
		defer(ss_mach, s_id); */
d679 1
a679 1
			ss_mach(s_id);
d777 1
a777 1
 * scsireset()
a778 48
 * Reset the SCSI bus.
 *
 * Allow settling time when turning reset on/off.
 * Settling times were determined empirically.
 * Each tick is 10 msec.
 *
 * If called while ssload() is running, don't return until reset is complete.
 * If called after ssload(), start up state machine and return.
 *
 * Either way, mark host adapter busy until reset completes.
 */
#define RESET_TICKS	40
static void scsireset()
{
	static int reset_state;

printf("!");
	/*
	 * During load, it's ok to do sleep() calls for reset settling.
	 * After load is finished, use timeout() to accomplish this.
	 */
	if (loading) {
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
		ssdelay(RESET_TICKS);
		sfbyte(ss_csr, 0);
		ssdelay(RESET_TICKS);
	} else {
		switch(reset_state) {
		case 0:
			sfbyte(ss_csr, WC_ENABLE_SCSI | WC_SCSI_RESET);
			timeout(&reset_tim, RESET_TICKS, scsireset, 0);
			reset_state = 1;
			break;
		case 1:
			sfbyte(ss_csr, 0);
			timeout(&reset_tim, RESET_TICKS, scsireset, 0);
			reset_state = 2;
			break;
		case 2:
			reset_state = 0;
			break;
		}
	}
}

/*
 * ssdelay()
 *
d781 3
d793 1
a793 1
 * ss_start_timing()
a794 34
 * Start a timeout for some number of ticks.
 * Caller knows timer has expired when "ss_expired" goes to 1.
 *
 * Sample invocation:
 *	ss_start_timing(n);
 *	while (check for desired event fails) {
 *		if (ss_expired) {
 *			...failure stuff..
 *			break;
 *		}
 *		ssdelay(m); <= needed to allow kernel to update timers
 *	}
 */
static void ss_start_timing(ticks)
int ticks;
{
	ss_expired = 0;
	timeout(&timeout_tim, ticks, ss_stop_timing, 1);
}

/*
 * ss_stop_timing()
 *
 * Stub function called only by ss_start_timing()
 */
static void ss_stop_timing(flagval)
int flagval;
{
	ss_expired = flagval;
}

/*
 * bus_pre_xfer()
 *
d1291 1
a1291 1
 * ss_done
a1292 25
 * Release current i/o buffer to the O/S.
 */
static void ss_done(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int s;

	s = sphi();
	ssp->id_busy = 0;
	ssp->dr_watch = 0;
	ssp->in_buf = ssp->out_buf = NULL;
	if (bp) {
		bdone(bp);
		ssp->bp = NULL;
	}
	spl(s);

	ss_start();
}

/*
 * bus_dev_reset()
 *
a1358 2
 *
 * Call reconnect() after this if reselect has occurred.
d1380 1
a1380 1
 * reconnect()
a1381 135
 * Given SCSI ID of target device that is issuing reselect, do reconnect
 * SCSI bus stuff.
 */
static void reconnect(s_id)
int s_id;
{
	uchar dat;
	int cmd_ok = 0;
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;

	dat = ffbyte(ss_dat);
	if ((dat & HOST_ID) && (dat & (1 << s_id)) && ssp) {
		sfbyte(ss_csr, WC_ENABLE_SCSI | WC_BUSY);
		if (bus_wait(RS_SELECT << 8 | 0)) {
			sfbyte(ss_csr, WC_ENABLE_SCSI);
			cmd_ok = bus_info_xfer(ssp);
			if (bp) {
				if (bp->b_req == BREAD)
					bp->b_resid -= ssp->data_bytes_in;
				else
					bp->b_resid -= ssp->data_bytes_out;
				if (cmd_ok && ssp->cmdstat == CS_GOOD) {
					if (ssp->msg_in == MSG_DISCONNECT) {
						ssp->dr_watch = WATCHDOG_SECONDS;
					} else
						ss_done(s_id);
				} else {
printf("BF6 ");
					bp->b_flag |= BFERR;
					ss_done(s_id);
				}
			}
		}
	}
}

/*
 * ss_rw()
 *
 * Send read or write command to the host adapter.
 */
static int ss_rw(s_id)
int s_id;
{
	ss_type * ssp = ss[s_id];
	BUF * bp = ssp->bp;
	int rw_ok = 0;
uchar rwc;

	ssp->cmdstat = -1;
	if (bp->b_req == BREAD) {
		ssp->cmdbuf[0] = ScmdREADEXTENDED;
		ssp->in_buf_len = bp->b_count;
		ssp->in_buf = bp->b_faddr;
		ssp->out_buf_len = 0;
		ssp->out_buf = NULL;
rwc='R';
	} else {
		ssp->cmdbuf[0] = ScmdWRITEXTENDED;
		ssp->in_buf_len = 0;
		ssp->in_buf = NULL;
		ssp->out_buf_len = bp->b_count;
		ssp->out_buf = bp->b_faddr;
rwc='W';
	}
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->cmdbuf[1] = 0;
	ssp->cmdbuf[2] = ssp->bno >> 24;
	ssp->cmdbuf[3] = ssp->bno >> 16;
	ssp->cmdbuf[4] = ssp->bno >>  8;
	ssp->cmdbuf[5] = ssp->bno;
	ssp->cmdbuf[6] = 0;
	ssp->cmdbuf[7] = bp->b_count / (BSIZE * 256L);
	ssp->cmdbuf[8] = bp->b_count / BSIZE;
	ssp->cmdbuf[9] = 0;
	ssp->cmdlen = G1CMDLEN;

{ int s = sphi();
	rw_ok = bus_pre_xfer(s_id);
	if (rw_ok) {
		bus_info_xfer(ssp);
spl(s);
		rw_ok = (ssp->cmdlen == ssp->cmd_bytes_out);
	}
else {{if(sserrct<=MAXSSERR)printf("F1");}spl(s);}
}

	if (ssp->cmdstat == CS_CHECK) {
{if(sserrct<=MAXSSERR)printf("ss_rw(): requesting sense\n");}
		if (req_sense(s_id)) {
			rw_ok = (ssp->cmdlen == ssp->cmd_bytes_out);
if(!rw_ok) {if(sserrct<=MAXSSERR)printf("F3");}
		}
	}

	if (rw_ok) {
		rw_ok =
		(ssp->cmdstat == CS_GOOD || ssp->msg_in == MSG_DISCONNECT);
if(!rw_ok) {if(sserrct<=MAXSSERR)printf("F4");}
	}

	return rw_ok;

}

/*
 * rezero()
 *
 * Send Rezero Unit command.
 *
 * Return 1 if no timeouts occurred, 0 if not.
 */
static int rezero(s_id)
int s_id;
{
	int retval;
	ss_type * ssp = ss[s_id];

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->cmdbuf[0] = ScmdREZERO;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] =
		ssp->cmdbuf[5] = 0;
	ssp->cmdlen = G0CMDLEN;
	retval = scsicmd(s_id);

	return retval;
}

/*
 * ss_mach()
 *
d1404 2
a1405 1
				if (ssp->expired)
d1407 1
a1407 1
				else
d1412 1
a1412 1
		case SST_POLL_BEGIN_IO
d1420 2
a1421 2
				if (!host_busy && BUS_FREE) {
					host_busy = 1;
d1423 1
a1423 5
					ssp->cmd_bytes_out = 0;
					ssp->data_bytes_in = 0;
					ssp->data_bytes_out = 0;
					if (bp)
						bp->b_resid = bp->b_count;
d1431 1
a1431 1
						set_timeout(DELAY_ARB);
d1433 6
a1438 2
				} else  /* host_busy or bus not free */
					set_timeout(DELAY_BSY);
a1444 1
				if reconnect handshake succeeds
d1450 2
a1451 1
				if (ssp->expired)
d1453 1
a1453 1
				else
d1487 1
a1487 1
			set_timeout(DELAY_BDR);
d1493 1
a1493 1
		if(ssq_rd_head() != NULL && !ssp->busy) {
d1495 12
a1506 2
			bp = ssq_rm_head();
			form current block request - initialize try counts, etc.
d1520 1
a1520 1
		set_timeout(DELAY_RST);
d1534 1
a1534 1
		set_timeout(DELAY_RST);
d1618 217
@


1.37
log
@Initial state machine hacks.
@
text
@d5 5
d12 3
d60 4
a63 23
#define DEBUG	1
#if DEBUG
int stats[100], statsptr;
#define PUSHI		{ if(statsptr<100)stats[statsptr++] = i; }
#define POPI		{ if(sserrct<=MAXSSERR)printf("%d:",statsptr);while(statsptr)\
				if(sserrct<=MAXSSERR)printf("%d ",stats[--statsptr]);if(sserrct<=MAXSSERR)printf("\n");}
#define SSTELL(foo)	if(sserrct<=MAXSSERR)printf(foo)
#define SSTATUS		{uchar status = ffbyte(ss_csr);if(sserrct<=MAXSSERR)printf("status=%x\n", status);}
#define SSDUMP(ssp, text) {int i;\
	if(sserrct<=MAXSSERR)printf("%s: msg_in=%x cmdstat=%x\n", text, ssp->msg_in,\
	ssp->cmdstat);if(ssp->cmdlen)for(i=0;i<ssp->cmdlen;i++)\
	if(sserrct<=MAXSSERR)printf(" %x", ssp->cmdbuf[i]);if(sserrct<=MAXSSERR)printf(" cmd_bytes_out=%d",\
	ssp->cmd_bytes_out);\
	if(ssp->data_bytes_in)for(i=0;i<ssp->data_bytes_in;i++)\
	if(sserrct<=MAXSSERR)printf(" %x", ffbyte(ssp->in_buf+i));if(sserrct<=MAXSSERR)printf(" data_bytes_in=%d\n",\
	ssp->data_bytes_in);}
#else
#define PUSHI
#define POPI
#define SSTELL(foo)
#define SSTATUS
#define SSDUMP(ssp, text)
#endif
d68 12
d98 7
a104 1
	unsigned int	ptab_read:1;  /* 1 if partition table has been read */
a121 1
extern void	ss_mach();
d137 1
d140 1
d145 1
d149 1
d157 1
a157 1
static int	testready();
a208 1
static ss_type *ss_tbl;		/* points to block of "ss" structs */
d212 1
d214 3
a216 1
static TIM	sst_tim;	/* for timeout() call from ss_start() */
d218 2
a540 2
	bp->b_resid = bp->b_count;

d731 1
a731 1
 * testready()
a732 56
 * Send Test Unit Ready command.
 * Retry after bus reset if necessary.
 *
 * Return 1 if unit is ready, 0 if not.
 */
static int testready(s_id)
int s_id;
{
	int retval;
	ss_type * ssp = ss[s_id];

	ssp->cmdstat = -1;
	ssp->data_bytes_in = 0;
	ssp->data_bytes_out = 0;
	ssp->cmdbuf[0] = ScmdTESTREADY;
	ssp->cmdbuf[1] = ssp->cmdbuf[2] = ssp->cmdbuf[3] = ssp->cmdbuf[4] =
		ssp->cmdbuf[5] = 0;
	ssp->cmdlen = G0CMDLEN;
	retval = scsicmd(s_id);

	return retval;
}

/*
 * scsicmd()
 *
 * Send command packet to target device.
 * Start a new SCSI bus cycle when this routine is called.
 * If command status after sending is Device Check (CS_CHECK), do a
 * Request Sense to find out what happened and clear check status.
 *
 * Return 1 if command was send and status was good, else 0.
 */
static int scsicmd(s_id)
int s_id;
{
	int retval;
	ss_type *ssp = ss[s_id];

	if (retval = bus_pre_xfer(s_id)) {
		bus_info_xfer(ssp);
		retval = (ssp->cmdlen == ssp->cmd_bytes_out
			&& ssp->cmdstat == CS_GOOD);
	}

	if (ssp->cmdstat == CS_CHECK) {
		if (req_sense(s_id))
			retval = (ssp->cmdlen == ssp->cmd_bytes_out);
	}

	return retval;
}

/*
 * scsireset()
 *
a982 1
SSDUMP(ssp, "Command overrun");
a1016 1
SSDUMP(ssp, "Data out overrun");
a1361 3
	if (!loading && st0x_busy)
		bdr_ok = 0;

a1404 1
printf("%d",bdr_ok);
d1573 229
@


1.36
log
@Last version before using state machine logic.
@
text
@d7 3
d77 1
a97 1
	unsigned int	id_busy:1;  /* 1 if device with this SCSI id busy */
d100 6
d115 1
d176 14
a189 1
static int	loading;	/* 1 ssload() is executing */
a199 1
static int	st0x_busy;	/* 1 if SCSI host adapter busy */
d206 1
a206 1
static ss_type  *ss[MAX_SCSI_ID-1], rqs;
a217 1
	loading = 1;
d254 2
a281 1
	st0x_busy++;
a286 2
	st0x_busy--;
	loading = 0;
d407 1
d417 6
d424 2
a425 1
	 * Decrement the number of watchdog timer requests open for host board.
d428 1
a471 3
#define NHEAD	4
#define NSEC	52
#define NCYL	1004
d493 3
a495 3
		*(short *)&hdparm.ncyl[0] = NCYL;
		hdparm.nhead = NHEAD;
		hdparm.nspt = NSEC;
d547 1
a547 1
{if(sserrct<=MAXSSERR)printf("BF1 ");}
d552 1
a552 1
{if(sserrct<=MAXSSERR)printf("BF2 ");}
d570 1
a570 1
{if(sserrct<=MAXSSERR)printf("BF3 ");}
d580 2
a581 6

/* if(sserrct<=MAXSSERR)printf("ssblock: drv=%x bno=%lx bp=%x flag=%x\n",
	drive, bp->b_bno, bp, bp->b_flag); */

		ssq_wr_tail(bp);
		ss_start();
d604 1
a604 2
		reconnect(s_id);
/*		defer(reconnect, s_id); */
d615 1
a615 1
	int s_id, rs_id;
d620 2
a621 18
		if (ssp && ssp->dr_watch) {
			ssp->dr_watch--;
			if (ssp->dr_watch == 0) {
{if(sserrct<=MAXSSERR)printf("BF4 ");}
				bus_dev_reset(s_id);
				ssp->bp->b_flag |= BFERR;
{if(sserrct<=MAXSSERR)printf("SCSI id #%d: bno=%lu <Watchdog Timeout>\n", s_id, ss[s_id]->bp->b_bno);}
				ss_done(s_id);
			} else {
				while (1) {
					rs_id = chk_reconn();
					if (rs_id == -1)
						break;
					else
						reconnect(rs_id);
				} /* endwhile */
			}
		}
d653 1
a653 1
		{if(sserrct<=MAXSSERR)printf("TO:f=%x s=%x ", flags, status);}
d670 1
a670 1
	int retval = 0;
a674 33
/*FOO*/
bus_dev_reset(s_id);
	/*
	 * Try Test Unit Ready command.
	 * If it fails, reset SCSI bus and target device, and try again.
	 */
printf("T");
	for (try = 0; !retval && try < LOPRI_RETRIES; try++) {
		if (testready(s_id))
			retval = 1;
		else {
printf("X");
			if (ssp->cmdstat == CS_BUSY)
				ssdelay(50);
			else if (ssp->cmdstat == CS_CHECK)
				req_sense(s_id);
			else if (s_id == chk_reconn())
			{
printf("-r-");
				ssdelay(50);
			}
			else
				scsireset();
		}
#if 0
		scsireset();
		bus_dev_reset(s_id);
#endif
	} /* endfor */
	if (!retval)
		devmsg(dev, "Test Unit Ready Failed");

printf("R");
a675 6
		if (req_sense(s_id)) {
			retval = 1;
		} else
			devmsg(dev, "Request Sense Failed");

	if (retval)
a714 1
ssp->id_busy=0;
a798 1
		st0x_busy++;
a802 1
		st0x_busy--;
a805 1
			st0x_busy++;
a815 1
			st0x_busy--;
d1049 1
a1049 1
	{if(sserrct<=MAXSSERR)printf("W");}
d1077 1
a1077 1
	{if(sserrct<=MAXSSERR)printf("CSK",ssp->cmdstat);}
d1080 1
a1080 1
	{if(sserrct<=MAXSSERR)printf("CSY",ssp->cmdstat);}
d1084 1
a1084 1
	{if(sserrct<=MAXSSERR)printf("CS%x",ssp->cmdstat);}
d1120 1
a1120 1
		{if(sserrct<=MAXSSERR)printf("TX: s=%x ", status);}
a1350 1
/* if(sserrct<=MAXSSERR)printf("%d in  %d out\n",ssp->data_bytes_in,ssp->data_bytes_out); */
d1353 1
a1353 1
{if(sserrct<=MAXSSERR)printf("BF5 ");}
d1361 1
a1361 1
{if(sserrct<=MAXSSERR)printf("R%d ",retry[s_id]);}
d1406 1
a1406 1
{if(sserrct<=MAXSSERR)printf("bdr");}
d1454 1
a1454 1
{if(sserrct<=MAXSSERR)printf("%d",bdr_ok);}
d1520 1
a1520 1
{if(sserrct<=MAXSSERR)printf("BF6 ");}
a1576 11
if(!rw_ok) {
  uchar csr=ffbyte(ss_csr), dat=ffbyte(ss_dat);
  sserrct++; if (sserrct <=MAXSSERR) {
    {if(sserrct<=MAXSSERR)printf("F2 cmdlen=%d cmd_bytes_out=%d cmdstat=%d\n", ssp->cmdlen,
  	ssp->cmd_bytes_out, ssp->cmdstat);}
    {if(sserrct<=MAXSSERR)printf("%c msg_in=%x inl=%d ", rwc, ssp->msg_in, ssp->in_buf_len);}
    {if(sserrct<=MAXSSERR)printf("inb=%d otl=%d otb=%d\n", ssp->data_bytes_in, ssp->out_buf_len,
    ssp->data_bytes_out);}
    {if(sserrct<=MAXSSERR)printf("csr=%x dat=%x bno=%ld ",csr,dat,bp->b_bno);}
  }
}
@
0707070064030104121004440000030000030000011777770507310663600005600000022502/newbits/kernel/USRSRC/i8086/drv/RCS/ssas.s,vhead     1.7;
branch   ;
access   ;
symbols  ;
locks    ;
comment  @/ @;


1.7
date     91.06.01.10.51.00;  author hal;  state Exp;
branches ;
next     1.6;

1.6
date     91.06.01.10.32.51;  author hal;  state Exp;
branches ;
next     1.5;

1.5
date     91.05.20.17.22.03;  author root;  state Exp;
branches ;
next     1.4;

1.4
date     91.05.20.16.21.35;  author root;  state Exp;
branches ;
next     1.3;

1.3
date     91.05.20.10.23.13;  author root;  state Exp;
branches ;
next     1.2;

1.2
date     91.05.17.00.24.17;  author root;  state Exp;
branches ;
next     1.1;

1.1
date     91.05.16.14.16.21;  author root;  state Exp;
branches ;
next     ;


desc
@Assembler I/O for Seagate SCSI.
@


1.7
log
@Add ffcopy().
@
text
@////////
/
/ I/O for Seagate ST01/ST02 SCSI Host Adapters.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.6  91/06/01  10:32:51  hal
/ Do handshaking both ways.  Now names are ss_getb()/ss_putb().
/ 
/ Revision 1.5	91/05/20  17:22:03	root
/ Not using ss_put() any more.
/ 
/ Revision 1.4	91/05/20  16:21:35	root
/ Call to ss_putc() now works.
/ 
/ Revision 1.3	91/05/20  10:23:13	root
/ Drop 3rd arg.  Same code for Seagate & Future Domain.
/ 
/ Revision 1.2	91/05/17  00:24:17	root
/ Code ss_put - use REQ handshake.
/ 
/ Revision 1.1	91/05/16  14:16:21	root
/ Initial version - no code yet for ss_put().
/ 
/
/	Since these functions are called from the midst of C code in
/	the "ss" driver, they need to preserve the following registers:
/		SI  DI  SP  BP    SS  DS  ES
/	Additionally, surrounding C code is expected to leave the "D"
/	CPU flag clear (string op's increment index registers).
/
////////

////////
/
/	Export functions.
/
////////
	.globl	ss_getb_
	.globl	ss_putb_
	.globl	ffcopy_

////////
/
/ Constants
/
/	Relative to the RAM base address of the host adapter, offsets
/	for Control/Status Register (CSR) and Data Port (DAT) differ
/	between Seagate and Future Domain as follows:
/			Seagate		Future Domain
/		SS_CSR	0x1A00		0x1C00
/		SS_DAT	0x1C00		0x1E00
/	The difference between these (CSR_OFF) is 0x200 in either case.
/
////////

	BSIZE	= 0x200		/ Disk block size in bytes
	CSR_OFF	= 0x200

	REQ_LIM = 500
	RS_REQUEST = 0x10

////////
/
/ ss_getb(ss_dat_fp, buf_fp)
/ faddr_t ss_dat_fp, buf_fp;
/
/ Fetch input bytes from host adapter and store at buffer address.
/
/ Do REQ handshaking and return the number of bytes remaining to transfer.
/ (So return value of 0 means no error.)
/
/ Here is the stack after initial "push bp":
/
/	10(bp)	FP_SEL(buf_fp)
/	8(bp)	FP_OFF(buf_fp)
/	6(bp)	FP_SEL(ss_dat_fp)
/	4(bp)	FP_OFF(ss_dat_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ss_getb_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si

	lds	si, 4(bp)	/ ss_dat_fp to DS:SI
	mov	bx, si		/ .. and to DS:BX
	sub	bx, $CSR_OFF	/ ss_csr to DS:BX
	les	di, 8(bp)	/ buf_fp to ES:DI
	mov	cx, $BSIZE	/ rep count to CX

G01:				/ start outer loop - reading bytes from SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
G02:				/ start inner loop - polling for REQ
	movb	dl, (bx)
	testb	dl, $RS_REQUEST
	jne	G03		/ got REQ
	dec	ax
	jnz	G02		/ no REQ - look again
	jmp	G04		/ no REQ - give up

G03:				/ got REQ - ok to read a byte
	movsb
	loop	G01
G04:				/ all done
	mov	ax, cx		/ normal exit returns 0

	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

////////
/
/ int ss_putb(ss_dat_fp, buf_fp)
/ faddr_t ss_dat_fp, buf_fp;
/
/ Write output bytes to host adapter from buffer address.
/
/ Return the number of bytes remaining to be sent (should be 0).
/
/ Here is the stack after initial "push bp":
/
/	10(bp)	FP_SEL(buf_fp)
/	8(bp)	FP_OFF(buf_fp)
/	6(bp)	FP_SEL(ss_dat_fp)
/	4(bp)	FP_OFF(ss_dat_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ss_putb_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si 
	lds	si, 8(bp)	/ buf_fp to DS:SI
	les	di, 4(bp)	/ ss_dat_fp  to ES:DI
	mov	bx, di		/ .. and to ES:BX
	sub	bx, $CSR_OFF	/ ss_csr to ES:BX
	mov	cx, $BSIZE	/ count to CX

P01:				/ start outer loop - writing bytes to SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
P02:				/ start inner loop - polling for REQ
	movb	dl, es:(bx)
	testb	dl, $RS_REQUEST
	jne	P03		/ got REQ
	dec	ax
	jnz	P02		/ no REQ - look again
	jmp	P04		/ no REQ - give up

P03:				/ got REQ - ok to write a byte
	movsb
	loop	P01
P04:				/ all done - now restore registers
	mov	ax, cx
	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

////////
/
/ void ffcopy(from_fp, to_fp, count)
/ faddr_t from_fp, to_fp;
/ int count;
/
/ Copy count bytes from from_fp to to_fp.
/
/ Here is the stack after initial "push bp":
/
/	12(bp)	count
/	10(bp)	FP_SEL(to_fp)
/	8(bp)	FP_OFF(to_fp)
/	6(bp)	FP_SEL(from_fp)
/	4(bp)	FP_OFF(from_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

ffcopy_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si

	lds	si, 4(bp)	/ from_fp  to DS:SI
	les	di, 8(bp)	/ to_fp to ES:DI
	mov	cx, 12(bp)	/ rep count to CX
	rep
	movsb

	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret
@


1.6
log
@Do handshaking both ways.  Now names are ss_getb()/ss_putb().
@
text
@d5 4
a8 1
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
d40 1
d174 41
@


1.5
log
@Not using ss_put() any more.
@
text
@d6 3
d35 2
a36 2
	.globl	ss_get_
/	.globl	ss_put_
d60 1
a60 1
/ ss_get(ss_dat_fp, buf_fp)
a63 2
/ (Also used conversely - this routine should be called "ff_bcopy()"
/ for "far-to-far block copy".)
d65 3
d79 1
a79 1
ss_get_:
d87 3
a89 1
	lds	si, 4(bp)	/ ss_dat_fp  to DS:SI
d92 12
a103 1
	rep
d105 3
a115 2
/ THE FOLLOWING ROUTINE APPEARS TO BE UNNECESSARY, SO IS COMMENTED OUT.

d118 1
a118 1
/ int ss_put(ss_dat_fp, buf_fp)
d136 34
a169 34
/ss_put_:
/	push	bp
/	mov	bp, sp
/	push	es
/	push	di
/	push	ds
/	push	si 
/	lds	si, 8(bp)	/ buf_fp to DS:SI
/	les	di, 4(bp)	/ ss_dat_fp  to ES:DI
/	mov	bx, di		/ .. and to ES:BX
/	sub	bx, $CSR_OFF	/ ss_csr to ES:BX
/	mov	cx, $BSIZE	/ count to CX
/
/P01:				/ start outer loop - writing bytes to SCSI
/	mov	ax, $REQ_LIM	/ max # of times to look for REQ
/P02:				/ start inner loop - polling for REQ
/	movb	dl, es:(bx)
/	testb	dl, $RS_REQUEST
/	jne	P03
/	dec	ax
/	jnz	P02
/	jmp	P04
/
/P03:				/ got REQ - ok to write a byte
/	movsb
/	loop	P01
/P04:				/ all done - now restore registers
/	mov	ax, cx
/	pop	si
/	pop	ds
/	pop	di
/	pop	es
/	pop	bp
/	ret
@


1.4
log
@Call to ss_putc() now works.
@
text
@d6 3
d33 1
a33 2
	.globl	ss_put_
	.globl	req_waitA_	/ temporary!
d61 2
d96 2
d118 12
a129 36
ss_put_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si 
	lds	si, 8(bp)	/ buf_fp to DS:SI
	les	di, 4(bp)	/ ss_dat_fp  to ES:DI
	mov	bx, di		/ .. and to ES:BX
	sub	bx, $CSR_OFF	/ ss_csr to ES:BX
	mov	cx, $BSIZE	/ count to CX

P01:				/ start outer loop - writing bytes to SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
P02:				/ start inner loop - polling for REQ
	movb	dl, es:(bx)
	testb	dl, $RS_REQUEST
	jne	P03
	dec	ax
	jnz	P02
	jmp	P04

P03:				/ got REQ - ok to write a byte
	movsb
	loop	P01
P04:				/ all done - now restore registers
	mov	ax, cx
	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret

////////
d131 9
a139 2
/ int req_waitA(ss_dat_fp, buf_fp)
/ faddr_t ss_dat_fp, buf_fp;
d141 11
a151 49
/ Return when REQ is true or timeout.
/
/ Return 1 if REQ received, 0 if timeout.
/
/ Here is the stack after initial "push bp":
/
/	10(bp)	FP_SEL(buf_fp)
/	8(bp)	FP_OFF(buf_fp)
/	6(bp)	FP_SEL(ss_dat_fp)
/	4(bp)	FP_OFF(ss_dat_fp)
/	2(bp)	return IP
/	0(bp)	old bp
/
////////

req_waitA_:
	push	bp
	mov	bp, sp
	push	es
	push	di
	push	ds
	push	si 
	lds	si, 8(bp)	/ buf_fp to DS:SI
	les	di, 4(bp)	/ ss_dat_fp  to ES:DI
	mov	bx, di		/ .. and to ES:BX
	sub	bx, $CSR_OFF	/ ss_csr to ES:BX
	mov	cx, $BSIZE	/ count to CX

Q01:				/ start outer loop - writing bytes to SCSI
	mov	ax, $REQ_LIM	/ max # of times to look for REQ
Q02:				/ start inner loop - polling for REQ
	movb	dl, es:(bx)
	testb	dl, $RS_REQUEST
	jne	Q03
	dec	ax
	jnz	Q02
	xor	ax, ax		/ timeout - return 0
	jmp	Q04

Q03:				/ got REQ
	mov	ax, $1		/ return 1
Q04:				/ all done - now restore registers
	movb	dh, $0xEE
	pop	si
	pop	ds
	pop	di
	pop	es
	pop	bp
	ret
@


1.3
log
@Drop 3rd arg.  Same code for Seagate & Future Domain.
@
text
@d6 3
d31 1
d50 1
a50 1
	REQ_LIM = 200
d122 1
a122 1
	sub	bx, CSR_OFF	/ ss_csr to ES:BX
d146 55
@


1.2
log
@Code ss_put - use REQ handshake.
@
text
@d6 3
a31 2
/	Also defined in /usr/src/sys/i8086/sys/ss.h:
/		SS_CSR  SS_DAT  RS_REQUEST
d33 8
d43 2
a44 2
	SS_CSR	= 0x1A00
	SS_DAT	= 0x1C00
d51 2
a52 3
/ ss_get(ss_fp, buf_fp, count)
/ faddr_t ss_fp, buf_fp;
/ int count;
a54 1
/ Count must be <= SS_RAM_LEN (0x400).
a57 1
/	12(bp)	count
d60 2
a61 2
/	6(bp)	FP_SEL(ss_fp)
/	4(bp)	FP_OFF(ss_fp)
d75 1
a75 2
	lds	si, 4(bp)	/ ss_fp  to DS:SI
	add	si, $SS_DAT	/ ss_dat to DS:SI
d77 1
a77 1
	mov	cx, 12(bp)	/ count to CX
d90 2
a91 3
/ int ss_put(ss_fp, buf_fp, count)
/ faddr_t ss_fp, buf_fp;
/ int count;
a93 1
/ Count must be <= SS_RAM_LEN (0x400).
d95 1
a95 1
/ Return 0 if timeout occurred, otherwise nonzero.
a98 1
/	12(bp)	count
d101 2
a102 2
/	6(bp)	FP_SEL(ss_fp)
/	4(bp)	FP_OFF(ss_fp)
d116 1
a116 1
	les	di, 4(bp)	/ ss_fp  to ES:DI
d118 2
a119 3
	add	di, $SS_DAT	/ ss_dat to ES:DI
	add	bx, $SS_CSR	/ ss_csr to ES:BX
	mov	cx, 12(bp)	/ count to CX
d121 1
a121 1
P01:				/ start of 2 loops
d123 4
a126 2
	testb	es:(bx), $RS_REQUEST
	jne	P02
d128 2
a129 2
	jnz	P01
	jmp	P03
d131 1
a131 1
P02:				/ got REQ - ok to write a byte
d134 2
a135 1
P03:				/ all done - now restore registers
@


1.1
log
@Initial version - no code yet for ss_put().
@
text
@d5 4
a8 1
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
d24 1
a24 1
/	.globl	ss_put_
d29 2
a30 1
/	These are also defined in /usr/src/sys/i8086/sys/ss.h
d37 3
d82 56
@
0707070064030104111004440000030000030000011777770507310664000006100000010712/newbits/kernel/USRSRC/i8086/drv/RCS/ssqueue.c,vhead     1.5;
access   ;
symbols  ;
locks    ;
comment  @ * @;


1.5
date     91.04.17.03.49.56;  author root;  state Exp;
branches ;
next	1.4;

1.4
date     91.04.16.01.47.29;  author root;  state Exp;
branches ;
next	1.3;

1.3
date     91.03.25.19.05.25;  author root;  state Exp;
branches 1.3.1.1;
next	1.2;

1.2
date     91.03.25.13.04.04;  author root;  state Exp;
branches ;
next	1.1;

1.1
date     91.03.22.17.39.06;  author root;  state Exp;
branches ;
next	;

1.3.1.1
date     91.04.11.15.59.53;  author root;  state Exp;
branches ;
next	;


desc
@Queueing routines for HD device driver.
@


1.5
log
@Turn off debug printing.
@
text
@/*
 * File:	ssqueue.c
 *
 * Purpose:
 *	Queueing routines for Seagate SCSI driver.
 *	Should be generalizable for other hard drives.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4	91/04/16  01:47:29	root
 * Use BUF rather than scsi_work_t as queue element type.
 * 
 * Revision 1.3.1.1	91/04/11  15:59:53	root
 * debug printing added
 * 
 * Revision 1.3	91/03/25  19:05:25	root
 * run at high priority
 * 
 * Revision 1.2	91/03/25  13:04:04	root
 * Minor code fixes.  Now passes unit test.
 * 
 * Revision 1.1	91/03/22  17:39:06	root
 * Initial code - not tested yet
 * 
 */

/*
 * Includes.
 */
#include <coherent.h>
#include <sys/buf.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
static BUF	* ssq_head;	/* point to first node */
static BUF	* ssq_tail;	/* point to last node */
static int		ssq_count;	/* number of nodes in the queue */

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
void ssq_wr_tail();
BUF * ssq_rd_head();
BUF * ssq_rm_head();

/*
 * Debug macros.
 */
#if 0
#define QSIZE	printf("Q%d:", ssq_count)
#else
#define QSIZE
#endif

/*
 * ssq_wr_tail()
 *
 * Append a BUF object to the doubly-linked queue.
 * Object to be inserted has been allocated by the caller.
 * Run at high priority.
 */
void ssq_wr_tail(bp)
BUF * bp;
{
	int s;

	s = sphi();
	if (ssq_count == 0) {
		ssq_head = ssq_tail = bp;
		bp->b_actf = bp->b_actl = NULL;
	} else {
		ssq_tail->b_actf = bp;
		bp->b_actf = NULL;
		bp->b_actl = ssq_tail;
		ssq_tail = bp;
	}
	ssq_count++;
QSIZE;
	spl(s);
}

/*
 * ssq_rd_head()
 *
 * Nondestructively fetch the head entry in the queue - i.e., this routine
 * does not remove an entry from the queue (see ss_rm_head() for that).
 * Return NULL if queue is empty, else return pointer to head item.
 */
BUF * ssq_rd_head()
{
	return ssq_head;
}

/*
 * ssq_rm_head()
 *
 * Delete head item from the queue.  Return a pointer to the node deleted,
 * or NULL if the queue was already empty.
 * Run at high priority.
 *
 * This routine does NOT deallocate the node.  That must be done by the
 * calling function after this routine runs.
 */
BUF * ssq_rm_head()
{
	BUF * ret;
	int s;

	s = sphi();
	if (ssq_count > 0) {
		ret = ssq_head;
		if (ssq_count == 1) {
			ssq_head = ssq_tail = NULL;
		} else {
			ssq_head = ssq_head->b_actf;
			ssq_head->b_actl = NULL;
		}
		ssq_count--;
QSIZE;
	} else
		ret = NULL;
	spl(s);

	return ret;
}
@


1.4
log
@Use BUF rather than scsi_work_t as queue element type.
@
text
@d9 3
d63 1
a63 1
#if 1
@


1.3
log
@run at high priority
@
text
@d9 6
a27 1
#include <scsiwork.h>
d43 2
a44 2
static scsi_work_t	* ssq_head;	/* point to first node */
static scsi_work_t	* ssq_tail;	/* point to last node */
d54 2
a55 2
scsi_work_t * ssq_rd_head();
scsi_work_t * ssq_rm_head();
d58 9
d69 1
a69 1
 * Append a scsi_work_t object to the doubly-linked queue.
d73 2
a74 2
void ssq_wr_tail(sw)
scsi_work_t * sw;
d80 2
a81 2
		ssq_head = ssq_tail = sw;
		sw->sw_actf = sw->sw_actl = NULL;
d83 4
a86 4
		ssq_tail->sw_actf = sw;
		sw->sw_actf = NULL;
		sw->sw_actl = ssq_tail;
		ssq_tail = sw;
d89 1
d100 1
a100 1
scsi_work_t * ssq_rd_head()
d115 1
a115 1
scsi_work_t * ssq_rm_head()
d117 1
a117 1
	scsi_work_t * ret;
d126 2
a127 2
			ssq_head = ssq_head->sw_actf;
			ssq_head->sw_actl = NULL;
d130 1
@


1.3.1.1
log
@debug printing added
@
text
@a8 3
 * Revision 1.3	91/03/25  19:05:25	root
 * run at high priority
 * 
a52 9
 * Debug macros.
 */
#if 1
#define QSIZE	printf("Q%d:", ssq_count)
#else
#define QSIZE
#endif

/*
a74 1
QSIZE;
a114 1
QSIZE;
@


1.2
log
@Minor code fixes.  Now passes unit test.
@
text
@d9 3
d57 1
d62 3
d75 1
d95 1
d103 1
d105 1
d117 1
@


1.1
log
@Initial code - not tested yet
@
text
@d8 4
a11 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d18 1
d101 1
a101 1
			ssq_head->sw_actl = NULL
@
0707070064030104101005550000030000030000011777770507310664100006000000010616/newbits/kernel/USRSRC/i8086/drv/RCS/310.diff,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.42.07;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@*** alx310.c	Sat Feb  2 16:44:45 1991
--- alx.c	Sat Feb 16 01:27:53 1991
***************
*** 25,34 ****
--- 25,42 ----
  
  #define DTRTMOUT  3	/* DTR timeout interval in seconds for close */
  #define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)
+ #define IE_ALL	(IE_RxI|IE_TxI|IE_LSI|IE_MSI)
  
+ #define RTS_ON()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) | MC_RTS); }
+ #define RTS_OFF()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) & ~MC_RTS); }
+ 
  int	al_sg_set = 0;
  int	al_sg_clr = 0;
  static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
+ static int drlsd;	/* delta carrier detect - set by alxintr(), read
+ 			   by alxcycle() */
+ static int rawin_ct;	/* number of characters in input silo */			   
+ static int want_rts;
  
  /*
   * functions herein
***************
*** 135,141 ****
  
  	b = ALPORT;
  
! 	if ( inb(b+IER) & ~IENABLE ) { /* chip not found */
  		u.u_error = ENXIO;
  		return;
  	}
--- 143,149 ----
  
  	b = ALPORT;
  
! 	if ( inb(b+IER) & ~IE_ALL ) { /* chip not found */
  		u.u_error = ENXIO;
  		return;
  	}
***************
*** 190,195 ****
--- 198,205 ----
  			*irqtty = tp_table[AL_NUM];
  			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
  		}
+ 		RTS_ON();
+ 		want_rts = 0;
  	
  		outb(b+IER, IENABLE);        /* enable interrupts */
  	
***************
*** 316,322 ****
  		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
  			state--;
  	}
! 	outb(b+MCR, 0);
  	com_usage[AL_NUM] = COM_UNUSED;
  	set_poll_rate();
  	CDUMP("closed")
--- 326,335 ----
  		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
  			state--;
  	}
! 	/*
! 	 * Turn off MC_OUT2 so IRQ can be used by other port.
! 	 */
! 	outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
  	com_usage[AL_NUM] = COM_UNUSED;
  	set_poll_rate();
  	CDUMP("closed")
***************
*** 343,350 ****
--- 356,365 ----
  {
  	register int	s, b;
  	int stat1, stat2;
+ 	char ier_save;
  
  	s = sphi();
+ 	ier_save=inb(b+IER);	/* some chips need this */
  	b = ALPORT;
  	stat1 = inb(b+MCR);		/* get current MCR register status */
  	stat2 = inb(b+LCR);		/* get current LCR register status */
***************
*** 384,389 ****
--- 399,405 ----
  	default:
  		ttioctl(tp, com, vec);
  	}
+ 	outb(b+IER, ier_save);
  	spl(s);
  }
  
***************
*** 466,472 ****
  		/*
  		 * Carrier changed.
  		 */
! 		if ( b & MS_DRLSD ) {
  			/*
  			 * wakeup open
  			 */
--- 482,489 ----
  		/*
  		 * Carrier changed.
  		 */
! 		if ((b & MS_DRLSD) || drlsd) {
! 			drlsd = 0;
  			/*
  			 * wakeup open
  			 */
***************
*** 482,487 ****
--- 499,505 ----
  				 * clear carrier flag; send hangup signal
  				 */
  				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
+ 				rawin_ct = 0;
  				tthup( tp );
  			}
  		}
***************
*** 497,502 ****
--- 515,521 ----
  		else
  			tp->t_rawin.si_ox++;
  	}
+ 	rawin_ct = 0;
  
  	/*
  	 * Calculate free output slot count.
***************
*** 520,530 ****
  	 * (Re)start output, wake sleeping processes, etc.
  	 */
  	ttstart( tp );
  
  	/*
  	 * Schedule next cycle.
  	 */
! 	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
  }
  
  /*
--- 539,554 ----
  	 * (Re)start output, wake sleeping processes, etc.
  	 */
  	ttstart( tp );
+ 	
+ 	if (want_rts) {
+ 		RTS_ON();
+ 		want_rts = 0;
+ 	}
  
  	/*
  	 * Schedule next cycle.
  	 */
! 	timeout( &tp->t_rawtim, HZ/20, alxcycle, tp );
  }
  
  /*
***************
*** 619,624 ****
--- 643,659 ----
  		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
  		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
  			tp->t_rawin.si_ix = 0;
+ 			
+ 		/*
+ 		 * Preliminary code!
+ 		 * De-assert RTS if we are close to filling the input silo.
+ 		 */	
+ 		rawin_ct++;
+ 		if (!want_rts && rawin_ct > SI_BUFSIZ / 4) {
+ 			RTS_OFF();
+ 			want_rts = 1;
+ 		}
+ 		
  		goto rescan;
  
  	case Tx_INTR:
***************
*** 650,655 ****
--- 685,707 ----
  			defer( alxcycle, tp );
  		}
  		goto rescan;
+ 		
+ 	case MS_INTR:
+ 		/*
+ 		 * This is preliminary code - use delta of CTS from
+ 		 * modem to implement flow control.
+ 		 *
+ 		 * Sense delta of RLSD for use by alxcycle().
+ 		 */
+ 		b = inb(ALPORT+MSR);
+ 		if (b & MS_DCTS)
+ 			if (b & MS_CTS)
+ 				tp->t_flags &= ~T_STOP;
+ 			else
+ 				tp->t_flags |= T_STOP;
+ 		if (b & MS_DRLSD)
+ 			drlsd = 1;		
+ 		goto rescan;
  	}
  }
  
@
0707070064030104071005550000030000030000011777770507310664200006000000006664/newbits/kernel/USRSRC/i8086/drv/RCS/311.diff,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.42.15;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@*** alx311.c	Sat Feb  2 16:45:12 1991
--- alx.c	Sat Feb 16 01:27:53 1991
***************
*** 27,32 ****
--- 27,35 ----
  #define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)
  #define IE_ALL	(IE_RxI|IE_TxI|IE_LSI|IE_MSI)
  
+ #define RTS_ON()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) | MC_RTS); }
+ #define RTS_OFF()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) & ~MC_RTS); }
+ 
  int	al_sg_set = 0;
  int	al_sg_clr = 0;
  static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
***************
*** 195,201 ****
  			*irqtty = tp_table[AL_NUM];
  			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
  		}
! 		want_rts = 1;
  	
  		outb(b+IER, IENABLE);        /* enable interrupts */
  	
--- 198,205 ----
  			*irqtty = tp_table[AL_NUM];
  			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
  		}
! 		RTS_ON();
! 		want_rts = 0;
  	
  		outb(b+IER, IENABLE);        /* enable interrupts */
  	
***************
*** 206,212 ****
  					SVTTOUT);	/* wait for carrier */
  		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
  					outb(b+MCR, inb(b+MCR)&MC_OUT2);
- 					want_rts = 0;
  	                    		/*
  					 * make sure port is hungup
  					 * disable all ints except for TxI
--- 210,215 ----
***************
*** 300,306 ****
  		 * Hangup port
  		 */
  		outb(b+MCR, inb(b+MCR)&MC_OUT2);
- 		want_rts = 0;
  		/*
  		 * Hold dtr low for timeout
  		 */
--- 303,308 ----
***************
*** 422,428 ****
  		if (tp->t_flags & T_MODC) {  /* modem control? */
  			tp->t_flags &= ~T_CARR;  /* indicate no carrier */
  			outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
- 			want_rts = 0;
  		}
  	}
  
--- 424,429 ----
***************
*** 515,522 ****
  			tp->t_rawin.si_ox++;
  	}
  	rawin_ct = 0;
- 	if (want_rts)
- 		outb(b+MCR, inb(b+MCR) | MC_RTS);
  
  	/*
  	 * Calculate free output slot count.
--- 516,521 ----
***************
*** 540,550 ****
  	 * (Re)start output, wake sleeping processes, etc.
  	 */
  	ttstart( tp );
  
  	/*
  	 * Schedule next cycle.
  	 */
! 	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
  }
  
  /*
--- 539,554 ----
  	 * (Re)start output, wake sleeping processes, etc.
  	 */
  	ttstart( tp );
+ 	
+ 	if (want_rts) {
+ 		RTS_ON();
+ 		want_rts = 0;
+ 	}
  
  	/*
  	 * Schedule next cycle.
  	 */
! 	timeout( &tp->t_rawtim, HZ/20, alxcycle, tp );
  }
  
  /*
***************
*** 639,652 ****
  		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
  		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
  			tp->t_rawin.si_ix = 0;
! 			rawin_ct++;
  		/*
  		 * Preliminary code!
  		 * De-assert RTS if we are close to filling the input silo.
  		 */	
! 		if (want_rts && (sizeof(tp->t_rawin.si_buf) - rawin_ct < 4))
! 			outb(b+MCR, inb(b+MCR) & ~MC_RTS);
! 			goto rescan;
  
  	case Tx_INTR:
  		/*
--- 643,660 ----
  		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
  		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
  			tp->t_rawin.si_ix = 0;
! 			
  		/*
  		 * Preliminary code!
  		 * De-assert RTS if we are close to filling the input silo.
  		 */	
! 		rawin_ct++;
! 		if (!want_rts && rawin_ct > SI_BUFSIZ / 4) {
! 			RTS_OFF();
! 			want_rts = 1;
! 		}
! 		
! 		goto rescan;
  
  	case Tx_INTR:
  		/*
***************
*** 693,698 ****
--- 701,707 ----
  				tp->t_flags |= T_STOP;
  		if (b & MS_DRLSD)
  			drlsd = 1;		
+ 		goto rescan;
  	}
  }
  
@
0707070064030104061004440000030000030000011777770507310664300005700000041621/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.norm,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.42.19;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@# $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
#
# Makefile for ibm specific coherent sources and coherent images.
#
# Revision 2.1	88/09/03  13:02:03	src
# *** empty log message ***
# 
# Revision 1.1	88/03/24  16:50:12	src
# Initial revision
# 

AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
#CFLAGS=	-VCNEST -VSINU -I.. -I../sys -I../.. -I../../sys 
CFLAGS=-I.. -I../sys -I../.. -I../../sys \
	-I/usr/include/sys
AFLAGS=-gx

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

HERE=	objects/pccon.o \
	objects/console.o \
	objects/dmareq.o

# The following don't compile due to missing header files
#	objects/jr.o objects/jras.o
DRVOBJ=	objects/alx.o \
	objects/ms.o \
	objects/ati.o \
	objects/com1.o objects/com2.o \
	objects/eye.o objects/eyeas.o \
	objects/fdisk.o \
	objects/fl.o \
	objects/fontw.o \
	objects/gr.o objects/gras.o objects/gmas.o objects/hgas.o \
	objects/hs.o objects/clocked.o \
	objects/ipc.o objects/ipcas.o \
	objects/kb.o objects/mm.o \
	objects/lp.o \
	objects/me.o objects/meas.o \
	objects/mmas.o \
	objects/msg.o objects/msgcon.o objects/msgstub.o \
	objects/rm.o \
	objects/rp.o objects/rpas.o \
	objects/rs0.o objects/rs1.o objects/rsas.o \
	objects/sem.o objects/semcon.o objects/semstub.o \
	objects/shm.o objects/shmcon.o objects/shmstub.o \
        objects/sham.o \
	objects/sl.o \
	objects/st.o \
	objects/tn.o objects/tnas.o \
	objects/tty.o \

all: $(HERE) $(DRVOBJ)
	@@exec /bin/sync

shrink:
	exec /bin/rm -f objects/*

#	rm -f $(USRSYS)/lib/jr.a
#	ar rc $(USRSYS)/lib/jr.a objects/jr.o objects/jras.o
install: all
	rm -f $(USRSYS)/lib/eye.a
	ar rc $(USRSYS)/lib/eye.a objects/eye.o objects/eyeas.o
	rm -f $(USRSYS)/lib/ms.a
	ar rc $(USRSYS)/lib/ms.a objects/ms.o
	rm -f $(USRSYS)/lib/al.a
	ar rc $(USRSYS)/lib/al.a objects/com1.o objects/com2.o objects/alx.o \
				objects/tty.o objects/clocked.o
	rm -f $(USRSYS)/lib/ati.a
	ar rc $(USRSYS)/lib/ati.a objects/mm.o objects/ati.o objects/kb.o \
				objects/tty.o
	rm -f $(USRSYS)/lib/fl.a
	ar rc $(USRSYS)/lib/fl.a objects/fl.o
	rm -f $(USRSYS)/lib/gm.a
	ar rc $(USRSYS)/lib/gm.a objects/mm.o objects/gr.o objects/gmas.o \
				objects/fontw.o objects/kb.o objects/tty.o
	ranlib $(USRSYS)/lib/gm.a
	rm -f $(USRSYS)/lib/gr.a
	ar rc $(USRSYS)/lib/gr.a objects/mm.o objects/gr.o objects/gras.o \
				objects/fontw.o objects/kb.o objects/tty.o
	ranlib $(USRSYS)/lib/gr.a
	rm -f $(USRSYS)/lib/hs.a
	ar rc $(USRSYS)/lib/hs.a objects/hs.o objects/clocked.o
	rm -f $(USRSYS)/lib/lp.a
	ar rc $(USRSYS)/lib/lp.a objects/lp.o
	rm -f $(USRSYS)/lib/mm.a
	ar rc $(USRSYS)/lib/mm.a objects/mm.o objects/mmas.o objects/kb.o \
				objects/tty.o
	rm -f $(USRSYS)/lib/me.a
	ar rc $(USRSYS)/lib/me.a objects/me.o objects/meas.o objects/fdisk.o
	rm -f $(USRSYS)/lib/msg.a
	ar rc $(USRSYS)/lib/msg.a objects/msgcon.o objects/msg.o \
				objects/ipc.o objects/ipcas.o
	rm -f $(USRSYS)/lib/rm.a
	ar rc $(USRSYS)/lib/rm.a objects/rm.o
	rm -f $(USRSYS)/lib/rp.a
	ar rc $(USRSYS)/lib/rp.a objects/rp.o objects/rpas.o
	rm -f $(USRSYS)/lib/rs.a
	ar rc $(USRSYS)/lib/rs.a objects/rs0.o objects/rs1.o objects/rsas.o
	rm -f $(USRSYS)/lib/sem.a
	ar rc $(USRSYS)/lib/sem.a objects/semcon.o objects/sem.o \
				objects/ipc.o objects/ipcas.o
	rm -f $(USRSYS)/lib/sham.a
	ar rc $(USRSYS)/lib/sham.a objects/shmcon.o objects/sham.o \
				objects/ipc.o objects/ipcas.o
	rm -f $(USRSYS)/lib/shm.a
	ar rc $(USRSYS)/lib/shm.a objects/shmcon.o objects/shm.o \
				objects/ipc.o objects/ipcas.o
	rm -f $(USRSYS)/lib/sl.a
	ar rc $(USRSYS)/lib/sl.a objects/sl.o objects/tty.o
	rm -f $(USRSYS)/lib/st.a
	ar rc $(USRSYS)/lib/st.a objects/st.o
	rm -f $(USRSYS)/lib/stubs.a
	ar rc $(USRSYS)/lib/stubs.a objects/*stub.o
	rm -f $(USRSYS)/lib/tn.a
	ar rc $(USRSYS)/lib/tn.a objects/tn.o objects/tnas.o

objects/alx.o:				\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		alx.c
	$(CC) $(CFLAGS) -c -o $@@ alx.c

objects/ati.o: ati.s
	exec /lib/cpp -E -DATI_132=1 ati.s > ati.i
	exec /bin/as -gxo $@@ ati.i
	exec /bin/rm -f ati.i

objects/clocked.o: clocked.c
	$(CC) $(CFLAGS) -c -o $@@ clocked.c

objects/com1.o: 			\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM1=1 -c -o $@@ al.c

objects/com2.o: 			\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM2=1 -c -o $@@ al.c

objects/com3.o:				\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM3=1 -c -o $@@ al.c

objects/console.o:			\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/inode.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/stat.h	\
		console.c
	$(CC) $(CFLAGS) -c -o $@@ console.c

objects/dmareq.o:			\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(DRVINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		dmareq.c
	$(CC) $(CFLAGS) -c -o $@@ dmareq.c

objects/eye.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/eye.h		\
		$(SYSINC)/inode.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		eye.c
	$(CC) $(CFLAGS) -c -o $@@ eye.c

objects/eyeas.o: eyeas.s		\
		$(SYSINC)/eye.h
	exec /lib/cpp -E eyeas.s > eyeas.i
	exec /bin/as -gxo $@@ eyeas.i
	exec /bin/rm -f eyeas.i

objects/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@@ fdisk.c

objects/fl.o:				\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(DRVINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdioctl.h	\
		$(DRVINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		fl.c
	$(CC) $(CFLAGS) -c -o $@@ fl.c

objects/fontw.o: fontgen.c
	$(CC) -i fontgen.c
	exec ./l.out > $*.s
	exec /bin/rm l.out
	$(AS) -gxo $@@ $*.s

objects/gmas.o: gras.s
	exec /lib/cpp -E -DTECMAR gras.s > gmas.i
	exec /bin/as -gxo $@@ gmas.i
	exec /bin/rm -f gmas.i

objects/gr.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		gr.c
	$(CC) $(CFLAGS) -c -o $@@ gr.c

objects/gras.o: gras.s
	exec /lib/cpp -E gras.s > gras.i
	exec /bin/as -gxo $@@ gras.i
	exec /bin/rm -f gras.i

objects/hgas.o: gras.s
	exec /lib/cpp -E -DHERCULES gras.s > hgas.i
	exec /bin/as -gxo $@@ hgas.i
	exec /bin/rm -f hgas.i

objects/hd.o: hd.c
	$(CC) $(CFLAGS) -c -o $@@ $<

objects/hs.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		hs.c
	$(CC) $(CFLAGS) -c -o $@@ hs.c

objects/ipc.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/ipc.h		\
		$(SYSINC)/uproc.h	\
		ipc.c
	$(CC) $(CFLAGS) -c -o $@@ ipc.c

objects/ipcas.o: ipcas.s
	$(AS) -gxo $@@ $<

objects/jr.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h	\
		jr.c
	$(CC) $(CFLAGS) -c -o $@@ jr.c

objects/jras.o: jras.s
	$(AS) -gxo $@@ $<

objects/kb.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		kb.c
	$(CC) $(CFLAGS) -c -o $@@ kb.c

objects/lp.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		lp.c
	$(CC) $(CFLAGS) -c -o $@@ lp.c

objects/me.o:				\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(DRVINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/inode.h	\
		$(DRVINC)/me.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		me.c
	$(CC) $(CFLAGS) -c -o $@@ me.c

objects/meas.o: meas.s
	$(AS) -gxo $@@ meas.s

objects/mm.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/sched.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/timeout.h	\
		mm.c
	$(CC) $(CFLAGS) -c -o $@@ mm.c

objects/mmas.o: mmas.s
	-/lib/cpp -E mmas.s > mmas.i
	exec /bin/as -gxo $@@ mmas.i
	exec /bin/rm -f mmas.i

objects/ms.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/ms.h		\
		$(USRINC)/errno.h	\
		ms.c
	$(CC) $(CFLAGS) -c -o $@@ ms.c

objects/msg.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/msg.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		msg.c
	$(CC) $(CFLAGS) -c -o $@@ msg.c

objects/msgcon.o:			\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/msg.h		\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		msgcon.c
	$(CC) $(CFLAGS) -c -o $@@ msgcon.c

objects/msgstub.o:			\
		msgstub.c
	$(CC) $(CFLAGS) -c -o $@@ msgstub.c

objects/pccon.o:			\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/mtype.h	\
		$(SYSINC)/stat.h	\
		pccon.c
	$(CC) $(CFLAGS) -c -o $@@ pccon.c

objects/rm.o: rm.c
	$(CC) $(CFLAGS) -c -o $@@ $<

objects/rp.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/v7sgtty.h	\
		rp.c
	$(CC) $(CFLAGS) -c -o $@@ rp.c

objects/rpas.o: rpas.s
	$(AS) -gxo $@@ $<

objects/rs0.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS0 -c -o $@@ rs.c

objects/rs1.o: 				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS1 -c -o $@@ rs.c

objects/rsas.o: rsas.s
	$(AS) -gxo $@@ $<

objects/sem.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/sem.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		sem.c
	$(CC) $(CFLAGS) -c -o $@@ sem.c

objects/semcon.o:			\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sem.h		\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		semcon.c
	$(CC) $(CFLAGS) -c -o $@@ semcon.c

objects/semstub.o:			\
		semstub.c
	$(CC) $(CFLAGS) -c -o $@@ semstub.c

objects/shm.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/shm.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		shm.c
	$(CC) $(CFLAGS) -c -o $@@ shm.c

objects/sham.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/shm.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		sham.c
	$(CC) $(CFLAGS) -c -o $@@ sham.c

objects/shmcon.o:			\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/shm.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		shmcon.c
	$(CC) $(CFLAGS) -c -o $@@ shmcon.c

objects/shmstub.o:			\
		shmstub.c
	$(CC) $(CFLAGS) -c -o $@@ shmstub.c

objects/sl.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		sl.c
	$(CC) $(CFLAGS) -c -o $@@ sl.c

objects/st.o:				\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/const.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/mtioctl.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		st.c
	$(CC) $(CFLAGS) -c -o $@@ st.c

objects/tn.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		tn.c
	$(CC) $(CFLAGS) -c -o $@@ tn.c

objects/tnas.o: tnas.s
	$(AS) -gxo $@@ $<

objects/tty.o: ../../ttydrv/tty.c
	$(CC) $(CFLAGS) -c -o $@@ $<
@
0707070064030104051004440000030000030000011777770507310664700005500000001662/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.qq,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.42.34;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@# Make file for a loadable driver

AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys \
	-I/usr/include/sys
AFLAGS=-gx

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

DRVOBJ=	objects/qq.o

qq: objects/qq.o
	rm -f $(USRSYS)/lib/qq.a
	ar rc $(USRSYS)/lib/qq.a objects/qq.o

objects/qq.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		qq.c
	$(CC) $(CFLAGS) -c -o $@@ qq.c
@
0707070064030104041004440000030000030000011777770507310664700006100000001662/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.qq.foo,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.42.37;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@# Make file for a loadable driver

AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys \
	-I/usr/include/sys
AFLAGS=-gx

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

DRVOBJ=	objects/qq.o

qq: objects/qq.o
	rm -f $(USRSYS)/lib/qq.a
	ar rc $(USRSYS)/lib/qq.a objects/qq.o

objects/qq.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		qq.c
	$(CC) $(CFLAGS) -c -o $@@ qq.c
@
0707070064030104031004440000030000030000011777770507310665000005500000003661/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.sd,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.42.39;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@# (lgl-
# 	COHERENT Driver Kit Version 1.1.0
# 	Copyright (c) 1982, 1990 by Mark Williams Company.
# 	All rights reserved. May not be copied without permisdion.
# -lgl)
#
# Makefile for Adaptec AHA154x SCSI driver "sd"
#
AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/icpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys -I/usr/include/sys
AFLAGS=-gx
OBJECTS=objects/scsi.o objects/aha.o objects/fdisk.o

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

sd: $(USRSYS)/lib/aha154x.a
	:

$(USRSYS)/lib/aha154x.a: $(OBJECTS)
	rm -f $(USRSYS)/lib/aha154x.a
	ar rc $(USRSYS)/lib/aha154x.a $(OBJECTS)

objects/scsi.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/sdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h	\
		$(DRVINC)/scsiwork.h	\
		scsi.c
	$(CC) $(CFLAGS) -c -o objects/scsi.o scsi.c

objects/aha.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
		$(SYSINC)/buf.h		\
		$(SYSINC)/sched.h		\
		$(DRVINC)/scsiwork.h	\
		$(DRVINC)/aha154x.h	\
		aha.c
	$(CC) $(CFLAGS) -c -o $@@ aha.c

objects/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
		$(SYSINC)/con.h \
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@@ fdisk.c
@
0707070064030104021004440000030000030000011777770507310665000006100000041315/newbits/kernel/USRSRC/i8086/drv/RCS/alx.c.1.6,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.45.25;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.6	91/04/03  18:55:07	root
 * alxclose():  do closing state machine BEFORE dropping control lines.
 * alxioctl():  save and restore interrupt enable register.
 * alxopen():   wait for pending last close (fixes SLOW port bug).
 * This version needs al.h 1.3 or later.
 * 
 * Revision 1.5	91/04/02  17:53:37	root
 * save MSR delta status; add MS_INTR handling; use al.h 1.2
 * 
 * Revision 1.4	91/02/22  09:21:17	root
 * alxintr():  replace repeated use of ALPORT macro by local variable
 * 
 * Revision 1.3	91/02/21  14:58:16	root
 * Fix unconditional "hupcl" bug in 3.1.0 version.
 * 
 * Revision 1.2	91/02/21  11:21:40	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 * 
 * Revision 1.1	91/02/21  11:08:31	hal
 * Used in COH Release 3.0.0 - no COM3/COM4
 *
 -lgl) */
/*
 * Shared parts of IBM async port drivers.
 */
#include <coherent.h>
#include <i8086.h>
#include <al.h>
#include <con.h>
#include <errno.h>
#include <stat.h>
#include <tty.h>
#include <uproc.h>
#include <sys/timeout.h>
#include <clist.h>
#include <ins8250.h>
#include <sched.h>

#define ALPORT	(((COM_DDP *)(tp->t_ddp))->port)
#define AL_TIM	(((COM_DDP *)(tp->t_ddp))->tim)
#define AL_NUM	(((COM_DDP *)(tp->t_ddp))->com_num)
#define AL_MSR_DELTAS	(((COM_DDP *)(tp->t_ddp))->msr_deltas)
#define AL_H_CLOSE	(((COM_DDP *)(tp->t_ddp))->h_close)

#define DTRTMOUT  3	/* DTR timeout interval in seconds for close */
#define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)

int	al_sg_set = 0;
int	al_sg_clr = 0;
static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */

/*
 * functions herein
 */
int	alxopen();
int	alxclose();
int	alxtimer();
int	alxioctl();
int	alxparam();
int	alxcycle();
int	alxstart();
int	alxbreak();
int	alxintr();
static	int	alxclk();
static	set_poll_rate();

/*
 * Baud rate table and polling rate table.
 * Indexed by ioctl bit rates.
 */
int albaud[] ={
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	alp_rate[] is tied to albaud[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int alp_rate[] ={			/* baud/6 or zero */
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	the following is for debug only
 */
#if 0
#define CDUMP(text)	cdump(text);

cdump(message)
char *message;
{
	int i, b;

	for (i = 0; i < NUM_AL_PORTS; i++) {
		b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
		printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
	}
	printf("poll=%d ", poll_rate);
	printf("%s\n", message);
}
#else
#define CDUMP(text)
#endif

/*
 * alxopen()
 */
alxopen(dev, mode, tp, irqtty)
dev_t	dev;
int	mode;
register TTY	*tp, **irqtty;
{
	register int	s;
	register int	b;
	register int	minor_h;  /* minor device number including high bit */
	unsigned char	msr;

	minor_h = minor(dev);     /* complete minor number */

	b = ALPORT;

	if ( inb(b+IER) & ~IENABLE ) { /* chip not found */
		u.u_error = ENXIO;
		return;
	}

	if ((tp->t_flags & T_EXCL) && !super()) {
		u.u_error = ENODEV;
		return;
	}

	if (drvl[major(dev)].d_time != 0) {	/* Modem settling */
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Can't open a polled port if another driver is using polling.
	 */
	if (dev & CPOLL && poll_owner & ~ POLL_AL) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * exclusion conditions:
	 *	can't have same port polled and IRQ at once
	 *	can't have both com[13] or both com[24] IRQ at once 
	 */
	if (dev & CPOLL) {
		if (com_usage[AL_NUM] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	} else {
		if (com_usage[AL_NUM] == COM_POLLED
		   || com_usage[AL_NUM ^ 2] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	}

	if (tp->t_open == 0) {        /* not already open */
		/*
		 * Wait for pending last close (if any) to finish.
		 */
		while (AL_H_CLOSE) {
   	  		sleep((char *)(&AL_H_CLOSE), CVTTOUT, IVTTOUT,
				SVTTOUT);
		}
		s = sphi();
		/*
		 * Raise basic modem control lines even if modem
		 * control hasn't been specified.
		 * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
		 * since we can't have two UART's on same IRQ with MC_OUT2 on
		 */
		if (dev & CPOLL) {
			outb(b+MCR, MC_RTS|MC_DTR);
		} else {
			*irqtty = tp_table[AL_NUM];
			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
		}
	
		outb(b+IER, IENABLE);        /* enable interrupts */
	
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
			tp->t_flags |= T_MODC | T_HOPEN; /* yes, set flags */
			while (1) {	/* wait for carrier */
				msr = inb(b+MSR);
				AL_MSR_DELTAS |= msr;
				if (msr & MS_RLSD)
					break;
	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
					SVTTOUT);	/* wait for carrier */
		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
					outb(b+MCR, inb(b+MCR)&MC_OUT2);
	                    		/*
					 * make sure port is hungup
					 * disable all ints except for TxI
					 */
			    		outb(b+IER, IE_TxI);
					u.u_error = EINTR;
					spl(s);
					return;
				}
			}
			tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
		} else {
			tp->t_flags &= ~T_MODC;		/* no modem control */ 
		}
	        tp->t_flags |= T_CARR;			/* carrier on */
		ttopen(tp);				/* stty inits */

		/*
		 * Allow custom modification of defaults.
		 */
		tp->t_sgttyb.sg_flags |=  al_sg_set;
		tp->t_sgttyb.sg_flags &= ~al_sg_clr;
		alxparam(tp);
		spl(s);
	} else {			        /* already open */
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
	   	    if ((tp->t_flags & T_MODC)==0) { /* already not modem control? */
			u.u_error = ENODEV;     /* yes, don't allow open */	
			return;
		    }
		} else {		         /* don't want modem control */
			if (tp->t_flags & T_MODC) { /* already modem control? */
				u.u_error = ENODEV; /* yes, don't allow open */
				return;
			}
		}
	}
	tp->t_open++;
	ttsetgrp(tp, dev);

	/*
	 * now that we've successfully opened, designate port as
	 * polled or interrupt driven to avoid future conflicts
	 */
	if (dev & CPOLL) {
		com_usage[AL_NUM] = COM_POLLED;
		set_poll_rate();
	} else {				/* irq-driven port */
		com_usage[AL_NUM] = COM_IRQ;
	}

	CDUMP((dev&CPOLL)?"open polled":"open irq")
}

/*
 * alxclose()
 */
alxclose(dev, mode, tp)
dev_t	dev;
int	mode;
TTY	*tp;
{
	register unsigned holdflags;
	register int b;
	int state, maj;

	/*
	 * Called at high priority by alclose after al_buff is drained
	 */
	holdflags = tp->t_flags;	/* save flags */
	AL_H_CLOSE = 1;			/* disallow reopen til done closing */
	ttclose(tp);			/* clear flags */
	b = ALPORT;
	/*
	 * ttclose() only emptied the output queue tp->t_oq;
	 * now wait for the silo tp->rawout to empty
	 * and allow a delay for the UART on-chip xmit buffer to empty
	 * state 2: waiting for silo to empty
	 * state 1: stalling so UART can empty xmit buffer
	 * state 0: done!  ok to shut off IRQ for this chip by clearing MC_OUT2
	 */
	state = 2;
	while (state) {
		timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
		sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
			state--;
	}

	/*
	 * If not hanging in open
	 */
	if ( (holdflags & T_HOPEN) == 0 ) {
		/*
		 * Disable all ints except TxI
		 */
		outb(b+IER, IE_TxI);
	} else {
		/*
		 * Flags for first open
		 */
		tp->t_flags = T_MODC | T_HOPEN;
	}

	/*
	 * If hupcls
	 */
	if (holdflags & T_HPCL) {
		/*
		 * Hangup port
		 */
		outb(b+MCR, inb(b+MCR)&MC_OUT2);

		/*
		 * Hold dtr low for timeout
		 */
		maj = major(dev);
		drvl[maj].d_time = 1;
		sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
		drvl[maj].d_time = 0;
	}
	outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
	com_usage[AL_NUM] = COM_UNUSED;
	set_poll_rate();
	AL_H_CLOSE = 0;		/* allow reopen - done closing */
	wakeup((char *)&AL_H_CLOSE);
	CDUMP("closed")
}

/*
 * Common c_timer routine for async ports.
 */
alxtimer(dev)
dev_t dev;
{
	if ( ++drvl[major(dev)].d_time > DTRTMOUT )
		wakeup((char *)&drvl[major(dev)].d_time);
}


/*
 * Common c_ioctl routine for async ports.
 */
alxioctl(dev, com, vec, tp)
dev_t	dev;
struct sgttyb *vec;
register TTY 	*tp;
{
	register int	s, b;
	int stat1, stat2;
	unsigned char	msr;
	unsigned char ier_save;

	s = sphi();
	b = ALPORT;
	ier_save=inb(b+IER);
	stat1 = inb(b+MCR);		/* get current MCR register status */
	stat2 = inb(b+LCR);		/* get current LCR register status */

	switch(com) {
	case TIOCSBRK:			/* set BREAK */		
		outb(b+LCR, stat2|LC_SBRK);
		break;
	case TIOCCBRK:			/* clear BREAK */
		outb(b+LCR, stat2 & ~LC_SBRK);
		break;
	case TIOCSDTR:			/* set DTR */
		outb(b+MCR, stat1|MC_DTR);
		break;	
	case TIOCCDTR:			/* clear DTR */
		outb(b+MCR, stat1 & ~MC_DTR);	
		break;
	case TIOCSRTS:			/* set RTS */
		outb(b+MCR, stat1|MC_RTS);	
		break;
	case TIOCCRTS:			/* clear RTS */
		outb(b+MCR, stat1 & ~MC_RTS);	
		break;	
	case TIOCRSPEED:		/* set "raw" I/O speed divisor */
		outb(b+LCR, stat2|LC_DLAB);  /* set speed latch bit */
		outb(b+DLL, (unsigned) vec);
		outb(b+DLH, (unsigned) vec >> 8);
		outb(b+LCR, stat2);       /* reset latch bit */
		break;
	case TIOCWORDL:		/* set word length and stop bits */
		outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
		break;
	case TIOCRMSR:		/* get CTS/DSR/RI/RLSD (MSR) */
		msr = inb(b+MSR);
		AL_MSR_DELTAS |= msr;
		stat1 = msr >> 4;
		kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
		break;	
	default:
		ttioctl(tp, com, vec);
	}
	outb(b+IER, ier_save);
	spl(s);
}

alxparam(tp)
TTY	*tp;
{
	register int	b;
	register int	baud;
	int s;

	b = ALPORT;

	/*
	 * error if input speed not the same as output speed
	 */
	if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
		u.u_error = ENODEV;	  
		return;
 	}

	if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
		if (tp->t_flags & T_MODC) {  /* modem control? */
			tp->t_flags &= ~T_CARR;  /* indicate no carrier */
			outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
		}
	}

	if (baud) {
		unsigned char ier_save;

		s=sphi();
		ier_save=inb(b+IER);	/* some chips need this */
		outb(b+LCR, LC_DLAB);
		outb(b+DLL, baud);
		outb(b+DLH, baud >> 8);
		switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
		case EVENP:
			outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN );
			break;

		case ODDP:
			outb(b+LCR, LC_CS7 + LC_PARENB );
			break;

		default:
			outb(b+LCR, LC_CS8 );
			break;
		}
		outb(b+IER, ier_save);
		spl(s);
	}
	set_poll_rate();
}

/*
 * Middle level processor.
 *
 *	Invoked 10 times per second.
 *	Checks modem status for loss of carrier.
 *	Tranfers rawin buffer [from intr level] to canonical input queue.
 *	Transfers output queue to rawout buffer [for intr level].
 */
alxcycle( tp )
register TTY * tp;
{
	register int b;
	register int n;
	unsigned char	msr;
	int s;

	/*
	 * Check modem status every clock tick.
	 * Modem status interrupts are not enabled due to 8250 hardware bug.
	 * Enabling modem status and receive interrupts may cause lockup.
	 */
	if ( tp->t_flags & T_MODC ) {

		/*
		 * Get status
		 */
		s = sphi();
		msr = inb(ALPORT+MSR);
		AL_MSR_DELTAS |= msr;
		spl(s);

		/*
		 * Carrier changed.
		 */
		if ( AL_MSR_DELTAS & MS_DRLSD ) {
			AL_MSR_DELTAS & ~MS_DRLSD;
			/*
			 * wakeup open
			 */
			if ( tp->t_open == 0 ) {
				wakeup((char *)(&tp->t_open));
			}

			/*
			 * carrier off?
			 */
			else if ( (msr & MS_RLSD) == 0 ) {
				/*
				 * clear carrier flag; send hangup signal
				 */
				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
				tthup( tp );
			}
		}
	}

	/*
	 * Empty raw input buffer.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );
		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}

	/*
	 * Calculate free output slot count.
	 */
	n  = sizeof(tp->t_rawout.si_buf) - 1;
	n += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	n %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--n >= 0) && ((b = ttout(tp)) >= 0) ) {
		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = b;
		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, wake sleeping processes, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
}

/*
 * Serial Transmit Start Routine.
 */
alxstart( tp )
register TTY * tp;
{
	register int b;
	register int s;
	extern alxbreak();

	/*
	 * Read line status register AFTER disabling interrupts.
	 */
	s = sphi();
	b = inb(ALPORT+LSR);

	/*
	 * Process break indication.
	 * NOTE: Break indication cleared when line status register was read.
	 */
	if ( b & LS_BREAK )
		defer( alxbreak, tp );

	/*
	 * Transmitter is empty, output data is pending.
	 */
	if ( (b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
		outb(	ALPORT+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}

/*
 * Serial Received Break Handler.
 */
alxbreak( tp )
register TTY * tp;
{
	ttsignal( tp, SIGINT );
}

/*
 * Serial Interrupt Handler.
 */
alxintr( tp )
register TTY * tp;
{
	register int	b;
	int port = ALPORT;

rescan:
	switch ( inb(port+IIR) ) {

	case LS_INTR:
		if ( inb(port+LSR) & LS_BREAK )
			defer( alxbreak, tp );
		goto rescan;

	case Rx_INTR:
		b = inb(port+DREG);
		if ( tp->t_open == 0 )
			goto rescan;
		/*
		 * Must recognize XOFF quickly to avoid transmit overrun.
		 * Recognize XON here as well to avoid race conditions.
		 */
		if ( (tp->t_sgttyb.sg_flags & RAWIN) == 0 ) {
			/*
			 * XOFF.
			 */
			if ( tp->t_tchars.t_stopc == (b & 0177) ) {
				tp->t_flags |= T_STOP;
				goto rescan;
			}

			/*
			 * XON.
			 */
			if ( tp->t_tchars.t_startc == (b & 0177) ) {
				tp->t_flags &= ~T_STOP;
				goto rescan;
			}
		}

		/*
		 * Save char in raw input buffer.
		 */
		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
			tp->t_rawin.si_ix = 0;
		goto rescan;

	case Tx_INTR:
		/*
		 * Do nothing if no raw output data or output is stopped.
		 */
		if ( tp->t_rawout.si_ix == tp->t_rawout.si_ox ) {
			goto rescan;
		}
		if ( tp->t_flags & T_STOP )
			goto rescan;

		/*
		 * Transmit next char in raw output buffer.
		 */
		outb(	port+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		/*
		 * Adjust raw output buffer output index.
		 */
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;

		/*
		 * Try to fill buffer if now empty.
		 */
		if ( tp->t_rawout.si_ox == tp->t_rawout.si_ix ) {
			defer( alxcycle, tp );
		}
		goto rescan;
		
	case MS_INTR:
		AL_MSR_DELTAS |= inb(port+MSR);
		goto rescan;
	}
}

/*
 * alxclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int alxclk()
{
	static int count;
	int i;

	for (i = 0; i < NUM_AL_PORTS;  i++)
		if (com_usage[i] == COM_POLLED)
			alxintr(tp_table[i]);
	count++;
	if (count >= poll_divisor)
		count = 0;
	return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_AL)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
		if (com_usage[port_num] == COM_POLLED) {
			port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
			if (max_rate < port_rate)
				max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in alxclk() */
		altclk_out();		/* stop previous polling */
		poll_owner &= ~ POLL_AL;
		if (max_rate) {	/* resume polling at new rate if needed */
			poll_owner |= POLL_AL;
			altclk_in(poll_rate, alxclk);
		}
		CDUMP("new rate")
	}
}
@
0707070064030104011004440000030000030000011777770507310665500006100000036361/newbits/kernel/USRSRC/i8086/drv/RCS/alx.c.310,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.45.42;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	91/02/21  11:21:40	hal
 * Used in COH Release 3.1.0 - add COM3/COM4 and polling
 * 
 * Revision 1.1	91/02/21  11:08:31	hal
 * Used in COH Release 3.0.0 - no COM3/COM4
 *
 -lgl) */
/*
 * Shared parts of IBM async port drivers.
 */
#include <coherent.h>
#include <i8086.h>
#include <al.h>
#include <con.h>
#include <errno.h>
#include <stat.h>
#include <tty.h>
#include <uproc.h>
#include <sys/timeout.h>
#include <clist.h>
#include <ins8250.h>
#include <sched.h>

#define ALPORT	(((COM_DDP *)(tp->t_ddp))->port)
#define AL_TIM	(((COM_DDP *)(tp->t_ddp))->tim)
#define AL_NUM	(((COM_DDP *)(tp->t_ddp))->com_num)

#define DTRTMOUT  3	/* DTR timeout interval in seconds for close */
#define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)

int	al_sg_set = 0;
int	al_sg_clr = 0;
static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */

/*
 * functions herein
 */
int	alxopen();
int	alxclose();
int	alxtimer();
int	alxioctl();
int	alxparam();
int	alxcycle();
int	alxstart();
int	alxbreak();
int	alxintr();
static	int	alxclk();
static	set_poll_rate();

/*
 * Baud rate table and polling rate table.
 * Indexed by ioctl bit rates.
 */
int albaud[] ={
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	alp_rate[] is tied to albaud[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int alp_rate[] ={			/* baud/6 or zero */
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	the following is for debug only
 */
#if 0
#define CDUMP(text)	cdump(text);

cdump(message)
char *message;
{
	int i, b;

	for (i = 0; i < NUM_AL_PORTS; i++) {
		b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
		printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
	}
	printf("poll=%d ", poll_rate);
	printf("%s\n", message);
}
#else
#define CDUMP(text)
#endif

alxopen(dev, mode, tp, irqtty)
dev_t	dev;
int	mode;
register TTY	*tp, **irqtty;
{
	register int	s;
	register int	b;
	register int	minor_h;  /* minor device number including high bit */

	minor_h = minor(dev);     /* complete minor number */

	b = ALPORT;

	if ( inb(b+IER) & ~IENABLE ) { /* chip not found */
		u.u_error = ENXIO;
		return;
	}

	if ((tp->t_flags & T_EXCL) && !super()) {
		u.u_error = ENODEV;
		return;
	}

	if (drvl[major(dev)].d_time != 0) {	/* Modem settling */
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Can't open a polled port if another driver is using polling.
	 */
	if (dev & CPOLL && poll_owner & ~ POLL_AL) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * exclusion conditions:
	 *	can't have same port polled and IRQ at once
	 *	can't have both com[13] or both com[24] IRQ at once 
	 */
	if (dev & CPOLL) {
		if (com_usage[AL_NUM] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	} else {
		if (com_usage[AL_NUM] == COM_POLLED
		   || com_usage[AL_NUM ^ 2] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	}

	if (tp->t_open == 0) {        /* not already open */
		s = sphi();
		/*
		 * Raise basic modem control lines even if modem
		 * control hasn't been specified.
		 * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
		 * since we can't have two UART's on same IRQ with MC_OUT2 on
		 */
		if (dev & CPOLL)
			outb(b+MCR, MC_RTS|MC_DTR);
		else {
			*irqtty = tp_table[AL_NUM];
			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
		}
	
		outb(b+IER, IENABLE);        /* enable interrupts */
	
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
			tp->t_flags |= T_MODC | T_HOPEN; /* yes, set flags */
			while ((inb(b+MSR) & MS_RLSD) == 0) { /* no carrier? */
	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
					SVTTOUT);	/* wait for carrier */
		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
					outb(b+MCR, inb(b+MCR)&MC_OUT2);
	                    		/*
					 * make sure port is hungup
					 * disable all ints except for TxI
					 */
			    		outb(b+IER, IE_TxI);
					u.u_error = EINTR;
					spl(s);
					return;
				}
			}
			tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
		} else {
			tp->t_flags &= ~T_MODC;		/* no modem control */ 
		}
	        tp->t_flags |= T_CARR;			/* carrier on */
		ttopen(tp);				/* stty inits */

		/*
		 * Allow custom modification of defaults.
		 */
		tp->t_sgttyb.sg_flags |=  al_sg_set;
		tp->t_sgttyb.sg_flags &= ~al_sg_clr;
		alxparam(tp);
		spl(s);
	} else {			        /* already open */
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
	   	    if ((tp->t_flags & T_MODC)==0) { /* already not modem control? */
			u.u_error = ENODEV;     /* yes, don't allow open */	
			return;
		    }
		} else {		         /* don't want modem control */
			if (tp->t_flags & T_MODC) { /* already modem control? */
				u.u_error = ENODEV; /* yes, don't allow open */
				return;
			}
		}
	}
	tp->t_open++;
	ttsetgrp(tp, dev);

	/*
	 * now that we've successfully opened, designate port as
	 * polled or interrupt driven to avoid future conflicts
	 */
	if (dev & CPOLL) {
		com_usage[AL_NUM] = COM_POLLED;
		set_poll_rate();
	} else {				/* irq-driven port */
		com_usage[AL_NUM] = COM_IRQ;
	}

	CDUMP((dev&CPOLL)?"open polled":"open irq")
}

alxclose(dev, mode, tp)
dev_t	dev;
int	mode;
TTY	*tp;
{
	register unsigned holdflags;
	register int b;
	int state, maj;

	/*
	 * Called at high priority by alclose after al_buff is drained
	 */
	holdflags = tp->t_flags;       /* save flags */
	ttclose(tp);		       /* clear flags */
	b = ALPORT;

	/*
	 * If not hanging in open
	 */
	if ( (holdflags & T_HOPEN) == 0 ) {
		/*
		 * Disable all ints except TxI
		 */
		outb(b+IER, IE_TxI);
	} else {
		/*
		 * Flags for first open
		 */
		tp->t_flags = T_MODC | T_HOPEN;
	}

	/*
	 * If hupcls
	 */
	if (holdflags & T_HPCL) {
		/*
		 * Hangup port
		 */
		outb(b+MCR, inb(b+MCR)&MC_OUT2);
		/*
		 * Hold dtr low for timeout
		 */
		maj = major(dev);
		drvl[maj].d_time = 1;
		sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
		drvl[maj].d_time = 0;
	}
	/*
	 * ttclose() only emptied the output queue tp->t_oq;
	 * now wait for the silo tp->rawout to empty
	 * and allow a delay for the UART on-chip xmit buffer to empty
	 * state 2: waiting for silo to empty
	 * state 1: stalling so UART can empty xmit buffer
	 * state 0: done!  ok to shut off IRQ for this chip by clearing MC_OUT2
	 */
	state = 2;
	while (state) {
		timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
		sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
			state--;
	}
	outb(b+MCR, 0);
	com_usage[AL_NUM] = COM_UNUSED;
	set_poll_rate();
	CDUMP("closed")
}

/*
 * Common c_timer routine for async ports.
 */
alxtimer(dev)
dev_t dev;
{
	if ( ++drvl[major(dev)].d_time > DTRTMOUT )
		wakeup((char *)&drvl[major(dev)].d_time);
}


/*
 * Common c_ioctl routine for async ports.
 */
alxioctl(dev, com, vec, tp)
dev_t	dev;
struct sgttyb *vec;
register TTY 	*tp;
{
	register int	s, b;
	int stat1, stat2;

	s = sphi();
	b = ALPORT;
	stat1 = inb(b+MCR);		/* get current MCR register status */
	stat2 = inb(b+LCR);		/* get current LCR register status */

	switch(com) {
	case TIOCSBRK:			/* set BREAK */		
		outb(b+LCR, stat2|LC_SBRK);
		break;
	case TIOCCBRK:			/* clear BREAK */
		outb(b+LCR, stat2 & ~LC_SBRK);
		break;
	case TIOCSDTR:			/* set DTR */
		outb(b+MCR, stat1|MC_DTR);
		break;	
	case TIOCCDTR:			/* clear DTR */
		outb(b+MCR, stat1 & ~MC_DTR);	
		break;
	case TIOCSRTS:			/* set RTS */
		outb(b+MCR, stat1|MC_RTS);	
		break;
	case TIOCCRTS:			/* clear RTS */
		outb(b+MCR, stat1 & ~MC_RTS);	
		break;	
	case TIOCRSPEED:		/* set "raw" I/O speed divisor */
		outb(b+LCR, stat2|LC_DLAB);  /* set speed latch bit */
		outb(b+DLL, (unsigned) vec);
		outb(b+DLH, (unsigned) vec >> 8);
		outb(b+LCR, stat2);       /* reset latch bit */
		break;
	case TIOCWORDL:		/* set word length and stop bits */
		outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
		break;
	case TIOCRMSR:		/* get CTS/DSR/RI/RLSD (MSR) */
		stat1 = inb(b+MSR) >> 4;
		kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
		break;	
	default:
		ttioctl(tp, com, vec);
	}
	spl(s);
}

alxparam(tp)
TTY	*tp;
{
	register int	b;
	register int	baud;
	int s;

	b = ALPORT;

	/*
	 * error if input speed not the same as output speed
	 */
	if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
		u.u_error = ENODEV;	  
		return;
 	}

	if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
		if (tp->t_flags & T_MODC) {  /* modem control? */
			tp->t_flags &= ~T_CARR;  /* indicate no carrier */
			outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
		}
	}

	if (baud) {
		char ier_save=inb(b+IER);	/* some chips need this */

		s=sphi();
		outb(b+LCR, LC_DLAB);
		outb(b+DLL, baud);
		outb(b+DLH, baud >> 8);
		switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
		case EVENP:
			outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN );
			break;

		case ODDP:
			outb(b+LCR, LC_CS7 + LC_PARENB );
			break;

		default:
			outb(b+LCR, LC_CS8 );
			break;
		}
		outb(b+IER, ier_save);
		spl(s);
	}
	set_poll_rate();
}

/*
 * Middle level processor.
 *
 *	Invoked 10 times per second.
 *	Checks modem status for loss of carrier.
 *	Tranfers rawin buffer [from intr level] to canonical input queue.
 *	Transfers output queue to rawout buffer [for intr level].
 */
alxcycle( tp )
register TTY * tp;
{
	register int b;
	register int n;

	/*
	 * Check modem status every clock tick.
	 * Modem status interrupts are not enabled due to 8250 hardware bug.
	 * Enabling modem status and receive interrupts may cause lockup.
	 */
	if ( tp->t_flags & T_MODC ) {

		/*
		 * Get status
		 */
		b = inb(ALPORT+MSR);

		/*
		 * Carrier changed.
		 */
		if ( b & MS_DRLSD ) {
			/*
			 * wakeup open
			 */
			if ( tp->t_open == 0 ) {
				wakeup((char *)(&tp->t_open));
			}

			/*
			 * carrier off?
			 */
			else if ( (b & MS_RLSD) == 0 ) {
				/*
				 * clear carrier flag; send hangup signal
				 */
				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
				tthup( tp );
			}
		}
	}

	/*
	 * Empty raw input buffer.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );
		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}

	/*
	 * Calculate free output slot count.
	 */
	n  = sizeof(tp->t_rawout.si_buf) - 1;
	n += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	n %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--n >= 0) && ((b = ttout(tp)) >= 0) ) {
		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = b;
		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, wake sleeping processes, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
}

/*
 * Serial Transmit Start Routine.
 */
alxstart( tp )
register TTY * tp;
{
	register int b;
	register int s;
	extern alxbreak();

	/*
	 * Read line status register AFTER disabling interrupts.
	 */
	s = sphi();
	b = inb(ALPORT+LSR);

	/*
	 * Process break indication.
	 * NOTE: Break indication cleared when line status register was read.
	 */
	if ( b & LS_BREAK )
		defer( alxbreak, tp );

	/*
	 * Transmitter is empty, output data is pending.
	 */
	if ( (b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
		outb(	ALPORT+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}

/*
 * Serial Received Break Handler.
 */
alxbreak( tp )
register TTY * tp;
{
	ttsignal( tp, SIGINT );
}

/*
 * Serial Interrupt Handler.
 */
alxintr( tp )
register TTY * tp;
{
	register int	b;

rescan:
	switch ( inb(ALPORT+IIR) ) {

	case LS_INTR:
		if ( inb(ALPORT+LSR) & LS_BREAK )
			defer( alxbreak, tp );
		goto rescan;

	case Rx_INTR:
		b = inb(ALPORT+DREG);
		if ( tp->t_open == 0 )
			goto rescan;
		/*
		 * Must recognize XOFF quickly to avoid transmit overrun.
		 * Recognize XON here as well to avoid race conditions.
		 */
		if ( (tp->t_sgttyb.sg_flags & RAWIN) == 0 ) {
			/*
			 * XOFF.
			 */
			if ( tp->t_tchars.t_stopc == (b & 0177) ) {
				tp->t_flags |= T_STOP;
				goto rescan;
			}

			/*
			 * XON.
			 */
			if ( tp->t_tchars.t_startc == (b & 0177) ) {
				tp->t_flags &= ~T_STOP;
				goto rescan;
			}
		}

		/*
		 * Save char in raw input buffer.
		 */
		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
			tp->t_rawin.si_ix = 0;
		goto rescan;

	case Tx_INTR:
		/*
		 * Do nothing if no raw output data or output is stopped.
		 */
		if ( tp->t_rawout.si_ix == tp->t_rawout.si_ox ) {
			goto rescan;
		}
		if ( tp->t_flags & T_STOP )
			goto rescan;

		/*
		 * Transmit next char in raw output buffer.
		 */
		outb(	ALPORT+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		/*
		 * Adjust raw output buffer output index.
		 */
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;

		/*
		 * Try to fill buffer if now empty.
		 */
		if ( tp->t_rawout.si_ox == tp->t_rawout.si_ix ) {
			defer( alxcycle, tp );
		}
		goto rescan;
	}
}

/*
 * alxclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int alxclk()
{
	static int count;
	int i;

	for (i = 0; i < NUM_AL_PORTS;  i++)
		if (com_usage[i] == COM_POLLED)
			alxintr(tp_table[i]);
	count++;
	if (count >= poll_divisor)
		count = 0;
	return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_AL)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
		if (com_usage[port_num] == COM_POLLED) {
			port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
			if (max_rate < port_rate)
				max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in alxclk() */
		altclk_out();		/* stop previous polling */
		poll_owner &= ~ POLL_AL;
		if (max_rate) {	/* resume polling at new rate if needed */
			poll_owner |= POLL_AL;
			altclk_in(poll_rate, alxclk);
		}
		CDUMP("new rate")
	}
}
@
0707070064030104001004440000030000030000011777770507310666100006100000040615/newbits/kernel/USRSRC/i8086/drv/RCS/alx.c.esa,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.46.06;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 * Add IE_ALL bit mask and use it when checking for UART existence.
 * Save delta status of CD - but not on per port basis.
 * Fix unconditional "hupcl" bug in 3.1.0 version.
 * Add RTS handshaking.
 * Add CTS handshaking.
 * Save and restore IER during alxioctl() call as well as alxparam().
 -lgl) */
/*
 * Shared parts of IBM async port drivers.
 */
#include <coherent.h>
#include <i8086.h>
#include <al.h>
#include <con.h>
#include <errno.h>
#include <stat.h>
#include <tty.h>
#include <uproc.h>
#include <sys/timeout.h>
#include <clist.h>
#include <ins8250.h>
#include <sched.h>

#define ALPORT	(((COM_DDP *)(tp->t_ddp))->port)
#define AL_TIM	(((COM_DDP *)(tp->t_ddp))->tim)
#define AL_NUM	(((COM_DDP *)(tp->t_ddp))->com_num)

#define DTRTMOUT  3	/* DTR timeout interval in seconds for close */
#define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)
#define IE_ALL	(IE_RxI|IE_TxI|IE_LSI|IE_MSI)

int	al_sg_set = 0;
int	al_sg_clr = 0;
static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
static int drlsd;	/* delta carrier detect - set by alxintr(), read
			   by alxcycle() */
static int rawin_ct;	/* number of characters in input silo */			   
static int want_rts;

/*
 * functions herein
 */
int	alxopen();
int	alxclose();
int	alxtimer();
int	alxioctl();
int	alxparam();
int	alxcycle();
int	alxstart();
int	alxbreak();
int	alxintr();
static	int	alxclk();
static	set_poll_rate();

/*
 * Baud rate table and polling rate table.
 * Indexed by ioctl bit rates.
 */
int albaud[] ={
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	alp_rate[] is tied to albaud[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int alp_rate[] ={			/* baud/6 or zero */
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 *	the following is for debug only
 */
#if 0
#define CDUMP(text)	cdump(text);

cdump(message)
char *message;
{
	int i, b;

	for (i = 0; i < NUM_AL_PORTS; i++) {
		b = ((COM_DDP *)(tp_table[i]->t_ddp))->port;
		printf("%x:%x:%x:%x ", i+1, b, inb(b+MCR), inb(b+IER));
	}
	printf("poll=%d ", poll_rate);
	printf("%s\n", message);
}
#else
#define CDUMP(text)
#endif

alxopen(dev, mode, tp, irqtty)
dev_t	dev;
int	mode;
register TTY	*tp, **irqtty;
{
	register int	s;
	register int	b;
	register int	minor_h;  /* minor device number including high bit */

	minor_h = minor(dev);     /* complete minor number */

	b = ALPORT;

	if ( inb(b+IER) & ~IE_ALL ) { /* chip not found */
		u.u_error = ENXIO;
		return;
	}

	if ((tp->t_flags & T_EXCL) && !super()) {
		u.u_error = ENODEV;
		return;
	}

	if (drvl[major(dev)].d_time != 0) {	/* Modem settling */
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Can't open a polled port if another driver is using polling.
	 */
	if (dev & CPOLL && poll_owner & ~ POLL_AL) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * exclusion conditions:
	 *	can't have same port polled and IRQ at once
	 *	can't have both com[13] or both com[24] IRQ at once 
	 */
	if (dev & CPOLL) {
		if (com_usage[AL_NUM] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	} else {
		if (com_usage[AL_NUM] == COM_POLLED
		   || com_usage[AL_NUM ^ 2] == COM_IRQ) {
			u.u_error = EDBUSY;
			return;
		}
	}

	if (tp->t_open == 0) {        /* not already open */
		s = sphi();
		/*
		 * Raise basic modem control lines even if modem
		 * control hasn't been specified.
		 * MC_OUT2 turns on NON-open-collector IRQ line from the UART.
		 * since we can't have two UART's on same IRQ with MC_OUT2 on
		 */
		if (dev & CPOLL)
			outb(b+MCR, MC_RTS|MC_DTR);
		else {
			*irqtty = tp_table[AL_NUM];
			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
		}
		want_rts = 1;
	
		outb(b+IER, IENABLE);        /* enable interrupts */
	
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
			tp->t_flags |= T_MODC | T_HOPEN; /* yes, set flags */
			while ((inb(b+MSR) & MS_RLSD) == 0) { /* no carrier? */
	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
					SVTTOUT);	/* wait for carrier */
		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
					outb(b+MCR, inb(b+MCR)&MC_OUT2);
					want_rts = 0;
	                    		/*
					 * make sure port is hungup
					 * disable all ints except for TxI
					 */
			    		outb(b+IER, IE_TxI);
					u.u_error = EINTR;
					spl(s);
					return;
				}
			}
			tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
		} else {
			tp->t_flags &= ~T_MODC;		/* no modem control */ 
		}
	        tp->t_flags |= T_CARR;			/* carrier on */
		ttopen(tp);				/* stty inits */

		/*
		 * Allow custom modification of defaults.
		 */
		tp->t_sgttyb.sg_flags |=  al_sg_set;
		tp->t_sgttyb.sg_flags &= ~al_sg_clr;
		alxparam(tp);
		spl(s);
	} else {			        /* already open */
		if ((minor_h & NMODC) == 0) {	/* want modem control? */
	   	    if ((tp->t_flags & T_MODC)==0) { /* already not modem control? */
			u.u_error = ENODEV;     /* yes, don't allow open */	
			return;
		    }
		} else {		         /* don't want modem control */
			if (tp->t_flags & T_MODC) { /* already modem control? */
				u.u_error = ENODEV; /* yes, don't allow open */
				return;
			}
		}
	}
	tp->t_open++;
	ttsetgrp(tp, dev);

	/*
	 * now that we've successfully opened, designate port as
	 * polled or interrupt driven to avoid future conflicts
	 */
	if (dev & CPOLL) {
		com_usage[AL_NUM] = COM_POLLED;
		set_poll_rate();
	} else {				/* irq-driven port */
		com_usage[AL_NUM] = COM_IRQ;
	}

	CDUMP((dev&CPOLL)?"open polled":"open irq")
}

alxclose(dev, mode, tp)
dev_t	dev;
int	mode;
TTY	*tp;
{
	register unsigned holdflags;
	register int b;
	int state, maj;

	/*
	 * Called at high priority by alclose after al_buff is drained
	 */
	holdflags = tp->t_flags;       /* save flags */
	ttclose(tp);		       /* clear flags */
	b = ALPORT;

	/*
	 * If not hanging in open
	 */
	if ( (holdflags & T_HOPEN) == 0 ) {
		/*
		 * Disable all ints except TxI
		 */
		outb(b+IER, IE_TxI);
	} else {
		/*
		 * Flags for first open
		 */
		tp->t_flags = T_MODC | T_HOPEN;
	}

	/*
	 * If hupcls
	 */
	if (holdflags & T_HPCL) {
		/*
		 * Hangup port
		 */
		outb(b+MCR, inb(b+MCR)&MC_OUT2);
		want_rts = 0;
		/*
		 * Hold dtr low for timeout
		 */
		maj = major(dev);
		drvl[maj].d_time = 1;
		sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
		drvl[maj].d_time = 0;
	}
	/*
	 * ttclose() only emptied the output queue tp->t_oq;
	 * now wait for the silo tp->rawout to empty
	 * and allow a delay for the UART on-chip xmit buffer to empty
	 * state 2: waiting for silo to empty
	 * state 1: stalling so UART can empty xmit buffer
	 * state 0: done!  ok to shut off IRQ for this chip by clearing MC_OUT2
	 */
	state = 2;
	while (state) {
		timeout(&AL_TIM, 10, wakeup, (int)&AL_TIM);
		sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
			state--;
	}
	/*
	 * Turn off MC_OUT2 so IRQ can be used by other port.
	 */
	outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
	com_usage[AL_NUM] = COM_UNUSED;
	set_poll_rate();
	CDUMP("closed")
}

/*
 * Common c_timer routine for async ports.
 */
alxtimer(dev)
dev_t dev;
{
	if ( ++drvl[major(dev)].d_time > DTRTMOUT )
		wakeup((char *)&drvl[major(dev)].d_time);
}


/*
 * Common c_ioctl routine for async ports.
 */
alxioctl(dev, com, vec, tp)
dev_t	dev;
struct sgttyb *vec;
register TTY 	*tp;
{
	register int	s, b;
	int stat1, stat2;
	char ier_save;

	s = sphi();
	ier_save=inb(b+IER);	/* some chips need this */
	b = ALPORT;
	stat1 = inb(b+MCR);		/* get current MCR register status */
	stat2 = inb(b+LCR);		/* get current LCR register status */

	switch(com) {
	case TIOCSBRK:			/* set BREAK */		
		outb(b+LCR, stat2|LC_SBRK);
		break;
	case TIOCCBRK:			/* clear BREAK */
		outb(b+LCR, stat2 & ~LC_SBRK);
		break;
	case TIOCSDTR:			/* set DTR */
		outb(b+MCR, stat1|MC_DTR);
		break;	
	case TIOCCDTR:			/* clear DTR */
		outb(b+MCR, stat1 & ~MC_DTR);	
		break;
	case TIOCSRTS:			/* set RTS */
		outb(b+MCR, stat1|MC_RTS);	
		break;
	case TIOCCRTS:			/* clear RTS */
		outb(b+MCR, stat1 & ~MC_RTS);	
		break;	
	case TIOCRSPEED:		/* set "raw" I/O speed divisor */
		outb(b+LCR, stat2|LC_DLAB);  /* set speed latch bit */
		outb(b+DLL, (unsigned) vec);
		outb(b+DLH, (unsigned) vec >> 8);
		outb(b+LCR, stat2);       /* reset latch bit */
		break;
	case TIOCWORDL:		/* set word length and stop bits */
		outb(b+LCR, ((stat2&~0x7) | ((unsigned) vec & 0x7)));
		break;
	case TIOCRMSR:		/* get CTS/DSR/RI/RLSD (MSR) */
		stat1 = inb(b+MSR) >> 4;
		kucopy(&stat1, (unsigned *) vec, sizeof(unsigned));
		break;	
	default:
		ttioctl(tp, com, vec);
	}
	outb(b+IER, ier_save);
	spl(s);
}

alxparam(tp)
TTY	*tp;
{
	register int	b;
	register int	baud;
	int s;

	b = ALPORT;

	/*
	 * error if input speed not the same as output speed
	 */
	if (tp->t_sgttyb.sg_ispeed!=tp->t_sgttyb.sg_ospeed) {
		u.u_error = ENODEV;	  
		return;
 	}

	if ((baud = albaud[tp->t_sgttyb.sg_ispeed]) == 0) {
		if (tp->t_flags & T_MODC) {  /* modem control? */
			tp->t_flags &= ~T_CARR;  /* indicate no carrier */
			outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
			want_rts = 0;
		}
	}

	if (baud) {
		char ier_save=inb(b+IER);	/* some chips need this */

		s=sphi();
		outb(b+LCR, LC_DLAB);
		outb(b+DLL, baud);
		outb(b+DLH, baud >> 8);
		switch (tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW)) {
		case EVENP:
			outb(b+LCR, LC_CS7 + LC_PARENB + LC_PAREVEN );
			break;

		case ODDP:
			outb(b+LCR, LC_CS7 + LC_PARENB );
			break;

		default:
			outb(b+LCR, LC_CS8 );
			break;
		}
		outb(b+IER, ier_save);
		spl(s);
	}
	set_poll_rate();
}

/*
 * Middle level processor.
 *
 *	Invoked 10 times per second.
 *	Checks modem status for loss of carrier.
 *	Tranfers rawin buffer [from intr level] to canonical input queue.
 *	Transfers output queue to rawout buffer [for intr level].
 */
alxcycle( tp )
register TTY * tp;
{
	register int b;
	register int n;

	/*
	 * Check modem status every clock tick.
	 * Modem status interrupts are not enabled due to 8250 hardware bug.
	 * Enabling modem status and receive interrupts may cause lockup.
	 */
	if ( tp->t_flags & T_MODC ) {

		/*
		 * Get status
		 */
		b = inb(ALPORT+MSR);

		/*
		 * Carrier changed.
		 */
		if ((b & MS_DRLSD) || drlsd) {
			drlsd = 0;
			/*
			 * wakeup open
			 */
			if ( tp->t_open == 0 ) {
				wakeup((char *)(&tp->t_open));
			}

			/*
			 * carrier off?
			 */
			else if ( (b & MS_RLSD) == 0 ) {
				/*
				 * clear carrier flag; send hangup signal
				 */
				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
				rawin_ct = 0;
				tthup( tp );
			}
		}
	}

	/*
	 * Empty raw input buffer.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );
		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}
	rawin_ct = 0;
	if (want_rts)
		outb(b+MCR, inb(b+MCR) | MC_RTS);

	/*
	 * Calculate free output slot count.
	 */
	n  = sizeof(tp->t_rawout.si_buf) - 1;
	n += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	n %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--n >= 0) && ((b = ttout(tp)) >= 0) ) {
		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = b;
		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, wake sleeping processes, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
}

/*
 * Serial Transmit Start Routine.
 */
alxstart( tp )
register TTY * tp;
{
	register int b;
	register int s;
	extern alxbreak();

	/*
	 * Read line status register AFTER disabling interrupts.
	 */
	s = sphi();
	b = inb(ALPORT+LSR);

	/*
	 * Process break indication.
	 * NOTE: Break indication cleared when line status register was read.
	 */
	if ( b & LS_BREAK )
		defer( alxbreak, tp );

	/*
	 * Transmitter is empty, output data is pending.
	 */
	if ( (b & LS_TxRDY) && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {
		outb(	ALPORT+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}

/*
 * Serial Received Break Handler.
 */
alxbreak( tp )
register TTY * tp;
{
	ttsignal( tp, SIGINT );
}

/*
 * Serial Interrupt Handler.
 */
alxintr( tp )
register TTY * tp;
{
	register int	b;

rescan:
	switch ( inb(ALPORT+IIR) ) {

	case LS_INTR:
		if ( inb(ALPORT+LSR) & LS_BREAK )
			defer( alxbreak, tp );
		goto rescan;

	case Rx_INTR:
		b = inb(ALPORT+DREG);
		if ( tp->t_open == 0 )
			goto rescan;
		/*
		 * Must recognize XOFF quickly to avoid transmit overrun.
		 * Recognize XON here as well to avoid race conditions.
		 */
		if ( (tp->t_sgttyb.sg_flags & RAWIN) == 0 ) {
			/*
			 * XOFF.
			 */
			if ( tp->t_tchars.t_stopc == (b & 0177) ) {
				tp->t_flags |= T_STOP;
				goto rescan;
			}

			/*
			 * XON.
			 */
			if ( tp->t_tchars.t_startc == (b & 0177) ) {
				tp->t_flags &= ~T_STOP;
				goto rescan;
			}
		}

		/*
		 * Save char in raw input buffer.
		 */
		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
			tp->t_rawin.si_ix = 0;
			rawin_ct++;
		/*
		 * Preliminary code!
		 * De-assert RTS if we are close to filling the input silo.
		 */	
		if (want_rts && (sizeof(tp->t_rawin.si_buf) - rawin_ct < 4))
			outb(b+MCR, inb(b+MCR) & ~MC_RTS);
			goto rescan;

	case Tx_INTR:
		/*
		 * Do nothing if no raw output data or output is stopped.
		 */
		if ( tp->t_rawout.si_ix == tp->t_rawout.si_ox ) {
			goto rescan;
		}
		if ( tp->t_flags & T_STOP )
			goto rescan;

		/*
		 * Transmit next char in raw output buffer.
		 */
		outb(	ALPORT+DREG,
			tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		/*
		 * Adjust raw output buffer output index.
		 */
		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;

		/*
		 * Try to fill buffer if now empty.
		 */
		if ( tp->t_rawout.si_ox == tp->t_rawout.si_ix ) {
			defer( alxcycle, tp );
		}
		goto rescan;
		
	case MS_INTR:
		/*
		 * This is preliminary code - use delta of CTS from
		 * modem to implement flow control.
		 *
		 * Sense delta of RLSD for use by alxcycle().
		 */
		b = inb(ALPORT+MSR);
		if (b & MS_DCTS)
			if (b & MS_CTS)
				tp->t_flags &= ~T_STOP;
			else
				tp->t_flags |= T_STOP;
		if (b & MS_DRLSD)
			drlsd = 1;		
	}
}

/*
 * alxclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int alxclk()
{
	static int count;
	int i;

	for (i = 0; i < NUM_AL_PORTS;  i++)
		if (com_usage[i] == COM_POLLED)
			alxintr(tp_table[i]);
	count++;
	if (count >= poll_divisor)
		count = 0;
	return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_AL)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < NUM_AL_PORTS; port_num++) {
		if (com_usage[port_num] == COM_POLLED) {
			port_rate = alp_rate[(tp_table[port_num])->t_sgttyb.sg_ispeed];
			if (max_rate < port_rate)
				max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in alxclk() */
		altclk_out();		/* stop previous polling */
		poll_owner &= ~ POLL_AL;
		if (max_rate) {	/* resume polling at new rate if needed */
			poll_owner |= POLL_AL;
			altclk_in(poll_rate, alxclk);
		}
		CDUMP("new rate")
	}
}
@
0707070064030103771004440000030000030000011777770507310666500006200000001725/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.ssqtest,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.19.54;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@#
# Makefile for test of ss queueing
#
AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/icpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys -I/usr/include/sys
AFLAGS=-gx
OBJECTS=ssqtest.o objects/ssqueue.o

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

ssqtest: $(OBJECTS)
	$(CC) $(CFLAGS) -o ssqtest $(OBJECTS)

ssqtest.o: ssqtest.c
	$(CC) $(CFLAGS) -DVERBOSE=1 -c -o ssqtest.o ssqtest.c

objects/ssqueue.o:			\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(DRVINC)/mmu.h \
		$(SYSINC)/buf.h		\
		$(DRVINC)/scsiwork.h	\
		ssqueue.c
	$(CC) $(CFLAGS) -c -o $@@ ssqueue.c
@
0707070064030103761004440000030000030000011777770507310666500005300000025247/newbits/kernel/USRSRC/i8086/drv/RCS/Mf2,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.20.00;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@#
# Makefile for AT specific Coherent drivers
#
AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys -I/usr/include/sys
AFLAGS=-gx

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

ARCHIVES=$(USRSYS)/lib/al.a \
	$(USRSYS)/lib/ati.a \
	$(USRSYS)/lib/fl.a \
	$(USRSYS)/lib/gm.a \
	$(USRSYS)/lib/gr.a \
	$(USRSYS)/lib/hs.a \
	$(USRSYS)/lib/lp.a \
	$(USRSYS)/lib/mm.a \
	$(USRSYS)/lib/ms.a \
	$(USRSYS)/lib/rm.a \
	$(USRSYS)/lib/rp.a \
	$(USRSYS)/lib/rs.a \
	$(USRSYS)/lib/st.a \
	$(USRSYS)/lib/tn.a \

DRVOBJ=	objects/alx.o \
	objects/ms.o \
	objects/ati.o \
	objects/com1.o objects/com2.o \
	objects/fdisk.o \
	objects/fl.o \
	objects/fontw.o \
	objects/gr.o objects/gras.o objects/gmas.o \
	objects/hs.o objects/clocked.o \
	objects/kb.o objects/mm.o \
	objects/lp.o \
	objects/mmas.o \
	objects/rm.o \
	objects/rp.o objects/rpas.o \
	objects/rs0.o objects/rs1.o objects/rsas.o \
	objects/st.o \
	objects/tn.o objects/tnas.o \

install: $(ARCHIVES)
	@@exec /bin/sync

all:	$(DRVOBJ)
	@@exec /bin/sync

$(USRSYS)/lib/al.a: objects/com1.o objects/com2.o objects/alx.o
	rm -f $(USRSYS)/lib/al.a
	ar rc $(USRSYS)/lib/al.a objects/com1.o objects/com2.o objects/alx.o
$(USRSYS)/lib/ati.a: objects/mm.o objects/ati.o objects/kb.o
	rm -f $(USRSYS)/lib/ati.a
	ar rc $(USRSYS)/lib/ati.a objects/mm.o objects/ati.o objects/kb.o
$(USRSYS)/lib/fl.a: objects/fl.o
	rm -f $(USRSYS)/lib/fl.a
	ar rc $(USRSYS)/lib/fl.a objects/fl.o
$(USRSYS)/lib/gm.a: objects/mm.o objects/gr.o objects/gmas.o \
				objects/fontw.o objects/kb.o
	rm -f $(USRSYS)/lib/gm.a
	ar rc $(USRSYS)/lib/gm.a objects/mm.o objects/gr.o objects/gmas.o \
				objects/fontw.o objects/kb.o
$(USRSYS)/lib/gr.a: objects/mm.o objects/gr.o objects/gras.o \
				objects/fontw.o objects/kb.o
	rm -f $(USRSYS)/lib/gr.a
	ar rc $(USRSYS)/lib/gr.a objects/mm.o objects/gr.o objects/gras.o \
				objects/fontw.o objects/kb.o
$(USRSYS)/lib/hs.a: objects/hs.o objects/clocked.o
	rm -f $(USRSYS)/lib/hs.a
	ar rc $(USRSYS)/lib/hs.a objects/hs.o objects/clocked.o
$(USRSYS)/lib/lp.a: objects/lp.o
	rm -f $(USRSYS)/lib/lp.a
	ar rc $(USRSYS)/lib/lp.a objects/lp.o
$(USRSYS)/lib/mm.a: objects/mm.o objects/mmas.o objects/kb.o
		rm -f $(USRSYS)/lib/mm.a
	ar rc $(USRSYS)/lib/mm.a objects/mm.o objects/mmas.o objects/kb.o
$(USRSYS)/lib/ms.a: objects/ms.o
	rm -f $(USRSYS)/lib/ms.a
	ar rc $(USRSYS)/lib/ms.a objects/ms.o
$(USRSYS)/lib/rm.a: objects/rm.o
	rm -f $(USRSYS)/lib/rm.a
	ar rc $(USRSYS)/lib/rm.a objects/rm.o
$(USRSYS)/lib/rp.a: objects/rp.o objects/rpas.o
	rm -f $(USRSYS)/lib/rp.a
	ar rc $(USRSYS)/lib/rp.a objects/rp.o objects/rpas.o
$(USRSYS)/lib/rs.a: objects/rs0.o objects/rs1.o objects/rsas.o
	rm -f $(USRSYS)/lib/rs.a
	ar rc $(USRSYS)/lib/rs.a objects/rs0.o objects/rs1.o objects/rsas.o
$(USRSYS)/lib/st.a: objects/st.o
	rm -f $(USRSYS)/lib/st.a
	ar rc $(USRSYS)/lib/st.a objects/st.o
$(USRSYS)/lib/tn.a: objects/tn.o objects/tnas.o
	rm -f $(USRSYS)/lib/tn.a
	ar rc $(USRSYS)/lib/tn.a objects/tn.o objects/tnas.o

objects/alx.o:				\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		alx.c
	$(CC) $(CFLAGS) -c -o $@@ alx.c

objects/ati.o: ati.s
	exec /lib/cpp -E -DATI_132=1 ati.s > ati.i
	exec /bin/as -gxo $@@ ati.i
	exec /bin/rm -f ati.i

#objects/clocked.o: clocked.s
#	$(AS) -go $@@ $<
objects/clocked.o: clocked.c

objects/com1.o: 			\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM1=1 -c -o $@@ al.c

objects/com2.o: 			\
		$(KERINC)/clist.h	\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM2=1 -c -o $@@ al.c

objects/dmareq.o:			\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(DRVINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		dmareq.c
	$(CC) $(CFLAGS) -c -o $@@ dmareq.c

objects/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@@ fdisk.c

objects/fl.o:				\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(DRVINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdioctl.h	\
		$(DRVINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		fl.c
	$(CC) $(CFLAGS) -c -o $@@ fl.c

objects/fontw.o: fontgen.c
	$(CC) -i fontgen.c
	exec ./fontgen > $*.s
	exec /bin/rm fontgen
	$(AS) -gxo $@@ $*.s
	exec /bin/rm $*.s

objects/gmas.o: gras.s
	exec /lib/cpp -E -DTECMAR gras.s > gmas.i
	exec /bin/as -gxo $@@ gmas.i
	exec /bin/rm -f gmas.i

objects/gr.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		gr.c
	$(CC) $(CFLAGS) -c -o $@@ gr.c

objects/gras.o: gras.s
	exec /lib/cpp -E gras.s > gras.i
	exec /bin/as -gxo $@@ gras.i
	exec /bin/rm -f gras.i

objects/hgas.o: gras.s
	exec /lib/cpp -E -DHERCULES gras.s > hgas.i
	exec /bin/as -gxo $@@ hgas.i
	exec /bin/rm -f hgas.i

objects/hd.o: hd.c
	$(CC) $(CFLAGS) -c -o $@@ $<

objects/hs.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		hs.c
	$(CC) $(CFLAGS) -c -o $@@ hs.c

objects/kb.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		kb.c
	$(CC) $(CFLAGS) -c -o $@@ kb.c

objects/lp.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/i8086.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		lp.c
	$(CC) $(CFLAGS) -c -o $@@ lp.c

objects/mm.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/sched.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/tty.h		$(KERINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/timeout.h	\
		mm.c
	$(CC) $(CFLAGS) -c -o $@@ mm.c

objects/mmas.o: mmas.s
	-/lib/cpp -E mmas.s > mmas.i
	exec /bin/as -gxo $@@ mmas.i
	exec /bin/rm -f mmas.i

objects/ms.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/ms.h		\
		$(USRINC)/errno.h	\
		ms.c
	$(CC) $(CFLAGS) -c -o $@@ ms.c

objects/rm.o: rm.c
	$(CC) $(CFLAGS) -c -o $@@ $<

objects/rp.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/v7sgtty.h	\
		rp.c
	$(CC) $(CFLAGS) -c -o $@@ rp.c

objects/rpas.o: rpas.s
	$(AS) -gxo $@@ $<

objects/rs0.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS0 -c -o $@@ rs.c

objects/rs1.o: 				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(DRVINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS1 -c -o $@@ rs.c

objects/rsas.o: rsas.s
	$(AS) -gxo $@@ $<

objects/st.o:				\
		$(SYSINC)/buf.h		\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/const.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/mtioctl.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		st.c
	$(CC) $(CFLAGS) -c -o $@@ st.c

objects/tn.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		tn.c
	$(CC) $(CFLAGS) -c -o $@@ tn.c

objects/tnas.o: tnas.s
	$(AS) -gxo $@@ $<
@
0707070064030103751004440000030000030000011777770507310667000005600000003726/newbits/kernel/USRSRC/i8086/drv/RCS/README,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.20.05;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@Here are two sets of diffs against the alx.c that I'm currently running.
It was derived from your RTS/CTS-enhanced version (that I dubbed "3.11").

The two sets of diffs are:

- version 3.10 alx.c against my current version
- your enhanced "version 3.11" alx.c against mine.

Important note:  I'm out of my league here.  I'm a reasonably competent
C programmer, but completely ignorant of asynch communications programming
and issues.  Don't look for deep insight in the changes that you see; in
many cases I merely removed code from your enhanced version that I didn't
understand, attempting to narrow down the number of changes involved.

I *have* tested and demonstrated that the code DOES toggle RTS correctly;
the persistent packet errors must be caused by delays in the chain well 
past the driver.

As I mentioned earlier, this version does cure the SSS (Sudden Sluggishness
Syndrome ;-) -- but introduces the following new anomalies:

- My version of ckermit does not get any response from the modem.  The modem
  lights indicate that the modem is sending stuff (e.g. after an ATN?), but
  nothing comes out.  The native plain old kermit does work.

- Recall that I use a fixed-at-9600 line speed, and let the Telebit cope
  with slower modems.  This has worked without incident in the past, but
  no longer.  While uucicos work  (with reduced speed), interactive 
  dial-ups at 2400 hang up the modem as soon as a "large" amount of 
  characters is sent (e.g. "ls -l").  The symptom is that the characters
  come across VERY slowly, and after the output is complete, further 
  keystrokes aren't echoed or responded to by the system.  It's almost as
  if the line speed gets changed from 9600 !?

I look forward to further testing material from you.

@
0707070064030103741004440000030000030000011777770507310667100005500000104725/newbits/kernel/USRSRC/i8086/drv/RCS/ati.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.20.27;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ Array Technologies Inc - Graphics Solution - Device Driver
/
/	 Supports 40/80/132 column color text
/		     80/132 column monochrome text
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal information
/		CX    - input count
/		BP    - references terminal information
/		AH    - character attributes
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
/ 
////////

	NCB	= 2		/ number of horizontal bytes per char
	NCR	= 1		/ number of horizontal lines per char
	NHB	= 160		/ number of horizontal bytes per line
	NRB	= NCR*NHB	/ number of bytes per character row

	ATTR	= ah		/ attribute byte
	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	INTENSE	= 0x08		/ high intensity attribute bit
	BLINK	= 0x80		/ blinking attribute bit
	REVERSE	= 0x70		/ reverse video

////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_BASE	= 8

	IOSYS	= 0
	IOUSR	= 1

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_INVIS	= 20		/ cursor invisible mask
MM_NCOL		= 22		/ number of columns
MM_DATA		= 24		/ pointer to crt data
MM_MODE		= 26		/ mode register [0x21=col80/132,0x20=col40]

	.prvd
mmdata:	.word	mminit
	.word	0x03D4
	.word	0xB800
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, 23, 24, 0, 0, 0, 23
	.word	0
	.word	80
	.word	creg80
	.byte	0x21, 0x00
	.shri

////////
/
/ creg40, creg80, creg132 - crt register values for 40/80/132 column color
/         mreg80, mreg132 - crt register values for 80/132 column monochrome
/
////////

creg40:	.byte	0x38, 0x28, 0x2D, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

creg80:	.byte	0x71, 0x50, 0x5A, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

mreg80:	.byte	0x61, 0x50, 0x52, 0x0F, 0x19, 0x06, 0x19, 0x19
	.byte	0x02, 0x0D, 0x0B, 0x0C, 0x00, 0x00, 0x00, 0x00

#ifdef ATI_132
	.globl	creg132
creg132:.byte	0xB5, 0x84, 0x97, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

	.globl	mreg132
mreg132:.byte	0x9F, 0x84, 0x89, 0x0F, 0x19, 0x06, 0x19, 0x19
	.byte	0x02, 0x0D, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00
#endif

////////
/
/ mmgo( iop )
/ IO *iop;
/
////////

	.globl	mmgo_

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc
	cmp	IO_SEG(bx), $IOSYS
	je	0f
	mov	ds, uds_
0:	mov	bp, $mmdata

	mov	dx, MM_PORT(bp)		/ turn video off if color board
	cmp	dx, $0x3B4
	je	0f
	add	dx, $4
	movb	al, MM_MODE(bp)
	outb	dx, al
0:
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	sub	bx, bx
	movb	ATTR, MM_ATTR(bp)
	ijmp	MM_FUNC(bp)

exit:	pop	bx
	pop	es
	pop	ds
	movb	MM_ATTR(bp), ATTR
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, MM_PORT(bp)		/ adjust cursor location
	mov	bx, POS
	or	bx, MM_INVIS(bp)
	shr	bx, $1

	movb	al, $14
	outb	dx, al
	inc	dx
	movb	al, bh
	outb	dx, al
	dec	dx
	movb	al, $15
	outb	dx, al
	inc	dx
	movb	al, bl
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ turn video on
	add	dx, $4
	movb	al, MM_MODE(bp)
	orb	al, $0x08
	outb	dx, al
	mov	mmvcnt_, $300		/ 300 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $'c		/ schedule keyboard initialization
	mov	MM_NCOL(bp), $80	/ set 80 column mode
	movb	MM_MODE(bp), $0x21
	mov	MM_DATA(bp), $creg80

#ifdef	ATI_132
	mov	dx, $0x3DF		/ clear 132 column color
	movb	al, $0x00		/ in mode select register
	outb	dx, al

	mov	dx, $0x3BA		/ clear 132 column monochrome
	movb	al, $0x00		/ in mode select register
	outb	dx, al
#endif

	call	int11_			/ read equipment status
	andb	al, $0x30		/ isolate video bits
	cmpb	al, $0x30		/ if monochrome
	jne	0f
	mov	MM_DATA(bp), $mreg80	/	set monochrome register info
	mov	MM_PORT(bp), $0x3B4	/	set monochrome port
	mov	MM_BASE(bp), $0xB000	/	set monochrome base
	mov	es, MM_BASE(bp)		/		and extra segment.

0:	call	newcrt			/ reprogram crt registers

reinit:	sub	ax, ax			/ regenerate row table
	mov	bx, $rowtab
1:	mov	ss:(bx), ax
	add	ax, MM_NCOL(bp)
	add	ax, MM_NCOL(bp)
	add	bx, $2
	cmp	bx, $rowend
	jb	1b

	mov	dx, MM_PORT(bp)		/ zero display offset
	movb	al, $12
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al
	dec	dx
	movb	al, $13
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ reset border to black
	add	dx, $5
	subb	al, al
	outb	dx, al

	mov	MM_INVIS(bp), $0
	movb	ATTR, $0x07
	movb	MM_ATTR(bp), ATTR
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ newcrt -- reload crt registers
/
/	Action:	Program crt registers with values defined in code space
/		at offset given by MM_DATA(bp).
/
/	Note:	AX, BX, DX, DI trashed on exit.
/
////////

newcrt:	mov	dx, MM_PORT(bp)		/ turn video off
	add	dx, $4
	movb	al, MM_MODE(bp)
	outb	dx, al

	mov	di, MM_DATA(bp)		/ program crt registers, last to first
	mov	bx, $15			/ [delay between i/o]
	mov	dx, MM_PORT(bp)		/ [NOTE:DI=obsolete screen offset]
0:	movb	al, bl
	outb	dx, al
	movb	al, cs:(bx,di)
	inc	dx
	outb	dx, al
	dec	dx
	dec	bx
	jge	0b
	ret

////////
/
/ mm_so - stand out - define 40 column attributes
/
////////

mm_so:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	mm_si

	mov	MM_NCOL(bp), $40	/	setup for 40 column color
	movb	MM_MODE(bp), $0x20
	mov	MM_DATA(bp), $creg40

#ifdef	ATI_132
	mov	dx, $0x3DF		/	clear 132 column color
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/ program crt registers
	jmp	reinit

////////
/
/ mm_si - define 80 column attributes
/
////////

mm_si:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	0f

	mov	MM_NCOL(bp), $80
	movb	MM_MODE(bp), $0x21
	mov	MM_DATA(bp), $creg80

#ifdef	ATI_132
	mov	dx, $0x3DF		/	clear 132 column color
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/	reprogram crt registers.
	jmp	reinit

0:	mov	MM_NCOL(bp), $80
	mov	MM_DATA(bp), $mreg80
	movb	MM_MODE(bp), $0x21

#ifdef	ATI_132
	mov	dx, $0x3BA		/	clear 132 column monochrome
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/	reprogram crt registers
	jmp	reinit

////////
/
/ mm_132 - define 132 column attributes
/
////////

mm_132:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	0f

#ifdef	ATI_132
	mov	MM_DATA(bp), $creg132	/	set color crt values
	mov	MM_NCOL(bp), $132	/	set columns to 132
	movb	MM_MODE(bp), $0x21

	call	newcrt			/	set 132 column crt values
					/	BEFORE setting mode select reg

	mov	dx, $0x3DF		/	set 132 columns
	movb	al, $0x10		/		in mode select register
	outb	dx, al
#endif
	jmp	reinit

0:
#ifdef	ATI_132
	mov	MM_NCOL(bp), $132	/	set columns to 132
	movb	MM_MODE(bp), $0x21	/	set 80/132 column display mode
	mov	MM_DATA(bp), $mreg132	/	set monochrome crt values

	call	newcrt			/	set 132 column crt values
					/	BEFORE setting mode select reg

	mov	dx, $0x3BA		/	set 132 columns monochrome
	movb	al, $0x08		/		in mode select register
	outb	dx, al
#endif
	jmp	reinit

////////
/
/ mmspec - schedule special keyboard function
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
	mov	si, ss:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, ss:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	cld
	rep
	movsw
	movb	al, $' 
	pop	di
	mov	cx, MM_NCOL(bp)
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, ss:rowtab(bx)
	call	exit
	jmp	eval

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, COL			/ reposition to ROW and COL
	shl	bx, $1			/ [trash BH]
	mov	POS, cs:coltab(bx)
	subb	bh, bh			/ [clear BH]
	movb	bl, ROW
	shlb	bl, $1
	add	POS, ss:rowtab(bx)
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	stosw
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jnb	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	sub	POS, $2
	subb	COL, $1
	jnb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
0:	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $';
	je	csi_n2
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	1f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

1:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csgtab(bx)

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jnb	0f
	subb	COL, COL		/ can't step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process 'ESC [ > N1 h' escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process 'ESC [ > N1 l' escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	push	cx
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl
	movb	al, $' 
	rep
	stosw
	pop	cx
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	eval

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The 1st parameter (mm_n1) specifies the vertical   position MM_ROW(bp).
/	The 2nd parameter (mm_n2) specifies the horizontal position MM_COL(bp).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	orb	ROW, ROW
	je	0f
	decb	ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
	mov	si, ss:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, ss:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	rep
	movsw
	mov	di, ss:rowtab(bx)
	mov	cx, MM_NCOL(bp)
	movb	al, $' 
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input, and causing cursor to vanish.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2


////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

mm_e2:	push	cx
	movb	al, $' 
0:	mov	cx, MM_NCOL(bp)
	rep
	stosw
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

mm_e1:	push	cx
	mov	cx, POS
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	sub	cx, POS
	jl	0f
	movb	al, $' 
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

mm_e0:	push	cx
	shlb	bl, $1
	mov	cx, ss:rowtab+2(bx)
	sub	cx, POS
	jl	0f
	movb	al, $' 
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, ss:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, ss:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, ss:rowtab(bx)
	jle	0f
	shr	cx, $1
	std
	rep
	movsw
	mov	di, ss:rowtab(bx)
	mov	cx, MM_NCOL(bp)
	movb	al, $' 
	cld
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	orb	ROW, ROW
	je	0f
	decb	ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	 MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_INVIS(bp), $0
	jmp	eval

0:	mov	MM_INVIS(bp), $-1
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					5 - slow blink
/					7 - reverse video
/					30-37 - foreground color
/					40-47 - background color
/					50-57 - border color
/
////////

mm_sgr:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	ATTR, $0x07
1:	jmp	eval
0:	cmpb	al, $1		/ bold
	jne	0f
	orb	ATTR, $INTENSE
	jmp	1b
0:	cmpb	al, $4		/ underline
	jne	0f
	cmp	MM_PORT(bp), $0x03D4	/ color card?
	je	1b			/ yes, ignore underline
	andb	ATTR, $~0x77
	orb	ATTR, $0x01
	jmp	1b
0:	cmpb	al, $5		/ blinking
	jne	0f
	orb	ATTR, $BLINK
	jmp	1b
0:	cmpb	al, $7		/ reverse video
	jne	0f
	movb	al, $0x70
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f
	movb	al, ah			/ yes, exchange foreground/background
	andb	al, $0x77
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
2:	andb	ATTR, $~0x77
	orb	ATTR, al
	jmp	1b
0:	cmp	MM_PORT(bp), $0x03D4	/ color card?
	jne	1b			/ no, ignore remaining options
0:	subb	al, $30		/ foreground color
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x07
	orb	ATTR, cs:fcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x70
	orb	ATTR, cs:bcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	movb	al, cs:fcolor(bx)
	push	dx
	mov	dx, MM_PORT(bp)
	add	dx, $5
	outb	dx, al
	pop	dx
/	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	mmbell	/	EOT  ENQ  ACK  BEL
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/	BS   HT   LF   VT
	.word	eval,	mm_cr,	mm_so,	mm_si	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
/ DEBUG: mm_132 is only inserted temporarily, for testing - 86/05/26
	.word	eval,	eval,	eval,	mm_132	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	mm_esc	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	  ! " # \040 - \043
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	$ % & ' \044 - \047
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	( ) * + \050 - \053
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	, - . / \054 - \057
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	0 1 2 3 \060 - \063
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	4 5 6 7 \064 - \067
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	8 9 : ; \070 - \073
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	< = > ? \074 - \077
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	@@ A B C \100 - \103
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	D E F G \104 - \107
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	H I J K \110 - \113
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	L M N O \114 - \117
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	P Q R S \120 - \123
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	T U V W \124 - \127
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	X Y Z [ \130 - \133
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	\ ] ^ _ \134 - \137
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	` a b c \140 - \143
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	d e f g \144 - \147
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	h i j k \150 - \153
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	l m n o \154 - \157
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	p q r s \160 - \163
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	t u v w \164 - \167
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	x y z { \170 - \173
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	| } ~ ? \174 - \177

////////
/
/ esctab - table of functions indexed by escape characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/	NUL  SOH  STX  ETX
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	EOT  ENQ  ACK  BEL
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	BS   HT   LF   VT
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	FF   CR   SO   SI
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	DLE  DC1  DC2  DC3
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	DC4  NAK  SYN  ETB
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	CAN  EM   SUB  ESC
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! " # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & ' \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	mm_new	/	4 5 6 7 \064 - \067
	.word	mm_old,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	mmspec,	mmspec,	eval	/	< = > ? \074 - \077
	.word	eval,	eval,	eval,	eval	/	@@ A B C \100 - \103
	.word	mm_ind,	mm_cnl,	eval,	eval	/	D E F G \104 - \107
	.word	eval,	eval,	eval,	eval	/	H I J K \110 - \113
	.word	eval,	mm_ri,	eval,	eval	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	eval	/	P Q R S \120 - \123
	.word	eval,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	eval,	csi_n1	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	mm_dmi,	eval,	mm_emi,	mminit	/	` a b c \140 - \143
	.word	eval,	eval,	eval,	eval	/	d e f g \144 - \147
	.word	eval,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	eval,	eval,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	eval,	eval	/	p q r s \160 - \163
	.word	mmspec,	mmspec,	eval,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	eval	/	EOT  ENQ  ACK  BEL
	.word	eval,	eval,	eval,	eval	/	BS   HT   LF   VT
	.word	eval,	eval,	eval,	eval	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
	.word	eval,	eval,	eval,	eval	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	eval	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! " # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & ' \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	eval	/	4 5 6 7 \064 - \067
	.word	eval,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	eval,	csi_gt,	eval	/	< = > ? \074 - \077
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/	@@ A B C \100 - \103
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/	D E F G \104 - \107
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/	H I J K \110 - \113
	.word	mm_il,	mm_dl,	eval,	mm_ea	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	mm_ind	/	P Q R S \120 - \123
	.word	mm_ri,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	mm_cbt,	eval	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	mm_hpa,	mm_hpr,	eval,	eval	/	` a b c \140 - \143
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/	d e f g \144 - \147
	.word	eval,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	eval,	mm_sgr,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	mm_ssr,	eval	/	p q r s \160 - \163
	.word	eval,	eval,	mm_scr,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ csgtab - table of functions indexed by ESC [ > characters.
/
////////

csgtab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	eval	/	EOT  ENQ  ACK  BEL
	.word	eval,	eval,	eval,	eval	/	BS   HT   LF   VT
	.word	eval,	eval,	eval,	eval	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
	.word	eval,	eval,	eval,	eval	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	eval	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! " # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & ' \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	eval	/	4 5 6 7 \064 - \067
	.word	eval,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	eval,	eval,	eval	/	< = > ? \074 - \077
	.word	eval,	eval,	eval,	eval	/	@@ A B C \100 - \103
	.word	eval,	eval,	eval,	eval	/	D E F G \104 - \107
	.word	eval,	eval,	eval,	eval	/	H I J K \110 - \113
	.word	eval,	eval,	eval,	eval	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	eval	/	P Q R S \120 - \123
	.word	eval,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	eval,	eval	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	eval,	eval,	eval,	eval	/	` a b c \140 - \143
	.word	eval,	eval,	eval,	eval	/	d e f g \144 - \147
	.word	mm_cgh,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	mm_cgl,	eval,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	eval,	eval	/	p q r s \160 - \163
	.word	eval,	eval,	eval,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ coltab - integer array of offsets to each column - up to 132 columns
/
////////

coltab:	.word	  0*NCB,   1*NCB,   2*NCB,   3*NCB
	.word	  4*NCB,   5*NCB,   6*NCB,   7*NCB
	.word	  8*NCB,   9*NCB,  10*NCB,  11*NCB
	.word	 12*NCB,  13*NCB,  14*NCB,  15*NCB
	.word	 16*NCB,  17*NCB,  18*NCB,  19*NCB
	.word	 20*NCB,  21*NCB,  22*NCB,  23*NCB
	.word	 24*NCB,  25*NCB,  26*NCB,  27*NCB
	.word	 28*NCB,  29*NCB,  30*NCB,  31*NCB
	.word	 32*NCB,  33*NCB,  34*NCB,  35*NCB
	.word	 36*NCB,  37*NCB,  38*NCB,  39*NCB
	.word	 40*NCB,  41*NCB,  42*NCB,  43*NCB
	.word	 44*NCB,  45*NCB,  46*NCB,  47*NCB
	.word	 48*NCB,  49*NCB,  50*NCB,  51*NCB
	.word	 52*NCB,  53*NCB,  54*NCB,  55*NCB
	.word	 56*NCB,  57*NCB,  58*NCB,  59*NCB
	.word	 60*NCB,  61*NCB,  62*NCB,  63*NCB
	.word	 64*NCB,  65*NCB,  66*NCB,  67*NCB
	.word	 68*NCB,  69*NCB,  70*NCB,  71*NCB
	.word	 72*NCB,  73*NCB,  74*NCB,  75*NCB
	.word	 76*NCB,  77*NCB,  78*NCB,  79*NCB
	.word	 80*NCB,  81*NCB,  82*NCB,  83*NCB
	.word	 84*NCB,  85*NCB,  86*NCB,  87*NCB
	.word	 88*NCB,  89*NCB,  90*NCB,  91*NCB
	.word	 92*NCB,  93*NCB,  94*NCB,  95*NCB
	.word	 96*NCB,  97*NCB,  98*NCB,  99*NCB
	.word	100*NCB, 101*NCB, 102*NCB, 103*NCB
	.word	104*NCB, 105*NCB, 106*NCB, 107*NCB
	.word	108*NCB, 109*NCB, 110*NCB, 111*NCB
	.word	112*NCB, 113*NCB, 114*NCB, 115*NCB
	.word	116*NCB, 117*NCB, 118*NCB, 119*NCB
	.word	120*NCB, 121*NCB, 122*NCB, 123*NCB
	.word	124*NCB, 125*NCB, 126*NCB, 127*NCB
	.word	128*NCB, 129*NCB, 130*NCB, 131*NCB

////////
/
/ rowtab - array of offsets to each row - up to 44 rows
/	   automatically regenerated by reinit().
/
/	NOTE: In kernel data space to allow modification in protected mode.
/
////////

	.shrd
rowtab:	.word	 0*NRB,	 1*NRB,	 2*NRB,	 3*NRB
	.word	 4*NRB,	 5*NRB,	 6*NRB,	 7*NRB
	.word	 8*NRB,	 9*NRB,	10*NRB,	11*NRB
	.word	12*NRB,	13*NRB,	14*NRB,	15*NRB
	.word	16*NRB,	17*NRB,	18*NRB,	19*NRB
	.word	20*NRB,	21*NRB,	22*NRB,	23*NRB
	.word	24*NRB,	25*NRB,	26*NRB,	27*NRB
	.word	28*NRB,	29*NRB,	30*NRB,	31*NRB
	.word	32*NRB,	33*NRB,	34*NRB,	35*NRB
	.word	36*NRB,	37*NRB,	38*NRB,	39*NRB
	.word	40*NRB,	41*NRB,	42*NRB,	43*NRB
rowend:
	.shri

////////
/
/ fcolor - foreground color
/ bcolor - background color
/
/	indexed by ansi color (black,red,green,brown,blue,magenta,cyan,white)
/	yields graphics color (black,blue,green,cyan,red,magenta,brown,white)
/		which is properly shifted for installation in attribute byte.
/
////////

fcolor:	.byte	0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
bcolor:	.byte	0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70

////////
/
/ mm_voff()	-- Disable video display.
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, mmdata+MM_PORT
	add	dx, $4
	movb	al, mmdata+MM_MODE
	outb	dx, al
	ret

////////
/
/ mm_von()	-- Enable video display
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, mmdata+MM_PORT	/ enable video display
	add	dx, $4
	movb	al, mmdata+MM_MODE
	orb	al, $0x08
	outb	dx, al
	mov	mmvcnt_, $300		/ 300 seconds before video disabled
	ret
@
0707070064030103731004440000030000030000011777770507310670000006100000006335/newbits/kernel/USRSRC/i8086/drv/RCS/clocked.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.20.56;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@////////
/
/ Clocked Functions - schedule function 'f' to be periodically invoked.
/		    - invocation is at clock interrupt level
/		    - only one function can be clocked
/
/	clocked( f, hz )
/	void (*f)();
/	int hz;
/
////////

	.globl	clocked_

////////
/
/ Hardware Dependant Constants
/
////////

	EOI	= 0x20		/ Non-specific End of Interrupt command
	PIC	= 0x20		/ 8259 pic   base address
	PIT	= 0x40		/ 8253 timer base address

////////
/
/ Private Data Declarations
/
////////

	.bssd
stack:	.blkb	256		/ Run time stack for the clocked function.
stktop:

	.shri	/ CODE SPACE!
uss:	.word	0		/ User stack segment
usp:	.word	0		/ User stack pointer
kds:	.word	0		/ Kernel data segment
oldclk:	.word	0		/ Previous clock interrupt entry point.
reload:	.word	0		/ Number of polls per logical clock tick.
resid:	.word	0		/ Number of polls left in logical clock tick.
cfunc:	.word	0		/ Clocked function
	.shri

////////
/
/ clocked( f, hz )
/ void (*f)();
/ int hz;
/
/	Input:	f  = function to be clocked.
/		hz = desired clock rate in invocations/second.
/
/	Action:	Calculate the number of polls per logical clock tick.
/		Seize the clock hardware interrupt.
/		Preserve the previous clock interrupt handler.
/		Reprogram the hardware clock to the desired rate.
/
/	Return:	 0 = clock interrupt seized.
/		-1 = clock interrupt previously seized.
/
/	Notes:	The logical clock rate to the OS will be unchanged.
/
////////

clocked_:
	pop	ax		/ Convert IP into PSW,CS,IP so can use iret.
	pushf
	push	cs
	push	ax

	mov	cs:kds, ds	/ Remember the kernel data segment

	cli			/ Disable interrupts

	push	es		/ Seize clock interrupt vector
	sub	ax, ax
	mov	es, ax
	mov 	ax, es:0x0020
	cmp	ax, $clocker
	jne	0f
	mov	ax, $-1
	pop	es
	iret

0:	mov	cs:oldclk, ax
	mov	es:0x0020, $clocker
	pop	es

	mov	bx, sp		/ Remember the function to be clocked.
	mov	ax, ss:6(bx)
	mov	cs:cfunc, ax

	mov	ax, ss:8(bx)	/ Compute polling rate relative to 20 hz.
	sub	dx, dx
	mov	cx, $20
	div	cx
	mov	cs:reload, ax
	mov	cs:resid, ax

	movb	al, $0x36	/ Timer 0, LSB, MSB, mode 3
	outb	PIT+3, al
	mov	ax, $59659
	sub	dx, dx
	div	cs:reload
	outb	PIT, al		/ LSB of 59659/reload
	jmp	0f
0:	movb	al, ah
	outb	PIT, al		/ MSB of 59659/reload

	sub	ax, ax
	iret

////////
/
/	clocker()	- initiate clocked function.
/
/	Action:	Every hardware clock tick, invoke the clocked function.
/		Every 'reload' hardware clock ticks,
/			simulate a logical clock interrupt to the OS.
/
////////

clocker:
	push	ax		/ Save registers.
	push	bx
	push	cx
	push	dx
	push	ds
	push	es

	mov	cs:uss, ss	/ Save current stack.
	mov	cs:usp, sp

	mov	ax, cs:kds	/ Remap Data/Extra/Stack Segments into Kernel.
	mov	ds, ax
	mov	es, ax
	mov	ss, ax
	mov	sp, $stktop	/ Remap stack pointer onto private intr stack.

	icall	cs:cfunc	/ Call the clocked function.

	mov	ss, cs:uss	/ Restore previous stack.
	mov	sp, cs:usp
	
	pop	es		/ Restore registers.
	pop	ds
	pop	dx
	pop	cx
	pop	bx

	dec	cs:resid
	je	0f
	movb	al, $EOI
	outb	PIC, al
	pop	ax
	iret

0:	mov	ax, cs:reload
	mov	cs:resid, ax
	pop	ax
	ijmp	cs:oldclk
@
0707070064030104321004440000030000030000011777770507310670100006100000002767/newbits/kernel/USRSRC/i8086/drv/RCS/console.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.48.41;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.11.19;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.30.06;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.20.59;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 * Tiny console driver.
 * 8086/8088 Coherent, IBM PC.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:03:39	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:04:25	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/i8086/drv/console.c
 * putchar() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <sys/inode.h>
#include <sys/stat.h>
#include <sys/con.h>
#include <sys/io.h>

dev_t condev = makedev(2,0);

putchar(c)
int c;
{
	static coninit;
	IO iob;

	if (coninit == 0) {
		++coninit;
		dopen( condev, IPW, DFCHR );
	}

	if (c == '\n')
		putchar('\r');

	iob.io_seg  = IOSYS;
	iob.io_ioc  = 1;
	iob.io_base = &c;
	iob.io_flag = 0;
	dwrite( condev, &iob );
}
@


1.3
log
@update provided by hal
@
text
@d16 1
a16 1
#include <coherent.h>
@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030103721004440000030000030000011777770507310670100006000000011334/newbits/kernel/USRSRC/i8086/drv/RCS/dmareq.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.48.52;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.11.32;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.30.25;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.22.13;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */

/*
 * Like ioreq, but guarantee that no DMA straddle occurs.
 * And assume we are called by fl.c, xt.c, dv.c or someone
 * else who obeys the parameter rules that they do.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:03:47	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:04:28	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/i8086/drv/dmareq.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/i8086/drv/dmareq.c
 * dmareq() now wakes &stimer only if the swap timer is active.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/dmac.h>

dmareq(bp, iop, dev, req)
register BUF *bp;
register IO *iop;
dev_t dev;
{
	register int n;
	register SEG *sp;
	register CON *cp;
	dold_t dold;
	long l;
	BUF *tbp;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	lock(bp->b_gate);
	n = cp->c_flag;
	drest(dold);
	if (blocko(iop->io_seek) != 0) {
		u.u_error = EIO;
		goto out;
	}
	if ((sp=iomapvp(iop, bp)) == NULL) {
		u.u_error = EIO;
		goto out;
	}
	bp->b_dev = dev;
	bp->b_flag = 0;
	sp->s_lrefc++;
	bp->b_faddr = ptov( bp->b_paddr, (fsize_t) bp->b_count );
	/*
	 * The dma address is 20 bits; 16 bit offset counter from a 4 bit
	 * base segment.  Since io_ioc is limited to 32Kb positive, we
	 * have at most two raw transfers separated by a block which
	 * straddles the segment boundary.
	 * Life would be simpler if we assumed io_ioc % BSIZE, but
	 * flioctl comes through here with it's short format buffer.
	 */
	while (iop->io_ioc > 0 && (bp->b_flag&BFERR) == 0) {
		l = dmaseg(bp->b_paddr+iop->io_ioc-1) - bp->b_paddr;
		if (l < 0)
			n = iop->io_ioc;
		else
			n = l & ~((long)BSIZE-1);
		l = blockn(iop->io_seek);
		if (n == 0) {
			/* Straddle block */
			tbp = bp;		/* Save the raw buffer */
			n = BSIZE;
			if (n > iop->io_ioc)
				n = iop->io_ioc;
			bp = bclaim(dev, l);
			bp->b_count = n;
			bp->b_req = req;
			if (req != BREAD)
				ioread(iop, FP_OFF(bp->b_faddr), n);
			dmabuf(bp, dev);
			if ((bp->b_flag&BFERR) == 0) {
				if (req == BREAD)
					iowrite(iop, FP_OFF(bp->b_faddr), n);
			} else {
				tbp->b_flag = bp->b_flag;
				tbp->b_err = bp->b_err;
				if (req != BREAD)
					iop->io_ioc += bp->b_resid;
			}
			bp->b_flag |= BFERR;
			brelease(bp);
			bp = tbp;		/* Reclaim raw buffer */
		} else {
			/* Raw transfer */
			bp->b_count = n;
			bp->b_req = req;
			bp->b_bno = l;
			dmabuf(bp, dev);
			if ((bp->b_flag&BFERR) != 0)
				n -= bp->b_resid;
			iop->io_ioc -= n;	/* cookedio do these */
			iop->io_base += n;	/* for everyone */
		}
		FP_OFF(bp->b_faddr) += n;
		bp->b_paddr  += n;
		iop->io_seek += n;
		/* And continue for the next chunk */
	}
	vrelse( bp->b_faddr );
	sp->s_lrefc--;
	if ( stimer.t_last != 0 )
		wakeup((char *)&stimer);
	if ((bp->b_flag&BFERR) != 0 && (u.u_error = bp->b_err) == 0)
		u.u_error = EIO;
out:
	unlock(bp->b_gate);
}

static
dmabuf(bp, dev)
register BUF *bp;
dev_t dev;
{
	register int s;
	bp->b_flag = BFRAW|BFBLK|BFIOC|BFNTP;
	s = sphi();
	dblock(dev, bp);
	while ((bp->b_flag&BFNTP) != 0)
		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
	spl(s);
}
@


1.3
log
@update provided by hal
@
text
@d34 3
a36 3
#include <coherent.h>
#include <buf.h>
#include <con.h>
d38 7
a44 7
#include <io.h>
#include <proc.h>
#include <sched.h>
#include <seg.h>
#include <stat.h>
#include <uproc.h>
#include <dmac.h>
@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030107001004440000030000030000011777770507310670300005700000001074/newbits/kernel/USRSRC/i8086/drv/RCS/errlist,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.22.15;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@make: 	exited with status 256
./.. -I../../sys -I/usr/include/sys -c -o objects/scsi.o scsi.c
306: scsi.c: identifier "w" is not defined
306: scsi.c: missing ';'
306: scsi.c: Strict: variable "mode" (line 263) is not used
306: scsi.c: Strict: label "xxx" is not used
312: scsi.c: Strict: variable "dev" (line 308) is not used
@
0707070064030106771004440000030000030000011777770507310670300006100000030116/newbits/kernel/USRSRC/i8086/drv/RCS/esa.diffs,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.22.16;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@From emory.mathcs.emory.edu!cyclone!esa  Mon Feb 18 13:14:39 1991 remote from uunet
Received: by mwc.UUCP (smail2.5)
	id AA17103; 18 Feb 91 13:14:39 
Received: from emory.mathcs.emory.edu by uunet.UU.NET (5.61/1.14) with UUCP 
	id AA04365; Mon, 18 Feb 91 04:16:30 -0500
Received: from emory.UUCP by rutgers.edu (5.59/SMI4.0/RU1.4/3.08) with UUCP 
	id AA27253; Mon, 18 Feb 91 00:22:09 EST
Received: from cyclone.UUCP by
	emory.mathcs.emory.edu (5.59/2.17.EUCC-MathCS) via UUCP
	id AA07538 ; Sun, 17 Feb 91 23:42:17 EST
Received: by cyclone.UUCP (smail2.5)
	id AA04284; 17 Feb 91 23:40:45 
X-Mailer: W-MAIL 3.63/Coherent (11/12/90)
To: mwc!hal
Subject: diffs
Message-Id: <9102172340.AA04282@@cyclone.UUCP>
Date: 17 Feb 91 23:40:43 
From: uunet!emory.mathcs.emory.edu!cyclone!esa (Esa Ahola)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README 310.diff 311.diff
# Wrapped by root@@cyclone on Sun Feb 17 23:39:49 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1760 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XHere are two sets of diffs against the alx.c that I'm currently running.
XIt was derived from your RTS/CTS-enhanced version (that I dubbed "3.11").
X
XThe two sets of diffs are:
X
X- version 3.10 alx.c against my current version
X- your enhanced "version 3.11" alx.c against mine.
X
XImportant note:  I'm out of my league here.  I'm a reasonably competent
XC programmer, but completely ignorant of asynch communications programming
Xand issues.  Don't look for deep insight in the changes that you see; in
Xmany cases I merely removed code from your enhanced version that I didn't
Xunderstand, attempting to narrow down the number of changes involved.
X
XI *have* tested and demonstrated that the code DOES toggle RTS correctly;
Xthe persistent packet errors must be caused by delays in the chain well 
Xpast the driver.
X
XAs I mentioned earlier, this version does cure the SSS (Sudden Sluggishness
XSyndrome ;-) -- but introduces the following new anomalies:
X
X- My version of ckermit does not get any response from the modem.  The modem
X  lights indicate that the modem is sending stuff (e.g. after an ATN?), but
X  nothing comes out.  The native plain old kermit does work.
X
X- Recall that I use a fixed-at-9600 line speed, and let the Telebit cope
X  with slower modems.  This has worked without incident in the past, but
X  no longer.  While uucicos work  (with reduced speed), interactive 
X  dial-ups at 2400 hang up the modem as soon as a "large" amount of 
X  characters is sent (e.g. "ls -l").  The symptom is that the characters
X  come across VERY slowly, and after the output is complete, further 
X  keystrokes aren't echoed or responded to by the system.  It's almost as
X  if the line speed gets changed from 9600 !?
X
XI look forward to further testing material from you.
X
END_OF_FILE
if test 1760 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f '310.diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'310.diff'\"
else
echo shar: Extracting \"'310.diff'\" \(4270 characters\)
sed "s/^X//" >'310.diff' <<'END_OF_FILE'
X*** alx310.c	Sat Feb  2 16:44:45 1991
X--- alx.c	Sat Feb 16 01:27:53 1991
X***************
X*** 25,34 ****
X--- 25,42 ----
X  
X  #define DTRTMOUT  3	/* DTR timeout interval in seconds for close */
X  #define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)
X+ #define IE_ALL	(IE_RxI|IE_TxI|IE_LSI|IE_MSI)
X  
X+ #define RTS_ON()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) | MC_RTS); }
X+ #define RTS_OFF()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) & ~MC_RTS); }
X+ 
X  int	al_sg_set = 0;
X  int	al_sg_clr = 0;
X  static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
X+ static int drlsd;	/* delta carrier detect - set by alxintr(), read
X+ 			   by alxcycle() */
X+ static int rawin_ct;	/* number of characters in input silo */			   
X+ static int want_rts;
X  
X  /*
X   * functions herein
X***************
X*** 135,141 ****
X  
X  	b = ALPORT;
X  
X! 	if ( inb(b+IER) & ~IENABLE ) { /* chip not found */
X  		u.u_error = ENXIO;
X  		return;
X  	}
X--- 143,149 ----
X  
X  	b = ALPORT;
X  
X! 	if ( inb(b+IER) & ~IE_ALL ) { /* chip not found */
X  		u.u_error = ENXIO;
X  		return;
X  	}
X***************
X*** 190,195 ****
X--- 198,205 ----
X  			*irqtty = tp_table[AL_NUM];
X  			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
X  		}
X+ 		RTS_ON();
X+ 		want_rts = 0;
X  	
X  		outb(b+IER, IENABLE);        /* enable interrupts */
X  	
X***************
X*** 316,322 ****
X  		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
X  			state--;
X  	}
X! 	outb(b+MCR, 0);
X  	com_usage[AL_NUM] = COM_UNUSED;
X  	set_poll_rate();
X  	CDUMP("closed")
X--- 326,335 ----
X  		if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
X  			state--;
X  	}
X! 	/*
X! 	 * Turn off MC_OUT2 so IRQ can be used by other port.
X! 	 */
X! 	outb(b+MCR, inb(b+MCR)&(~MC_OUT2));
X  	com_usage[AL_NUM] = COM_UNUSED;
X  	set_poll_rate();
X  	CDUMP("closed")
X***************
X*** 343,350 ****
X--- 356,365 ----
X  {
X  	register int	s, b;
X  	int stat1, stat2;
X+ 	char ier_save;
X  
X  	s = sphi();
X+ 	ier_save=inb(b+IER);	/* some chips need this */
X  	b = ALPORT;
X  	stat1 = inb(b+MCR);		/* get current MCR register status */
X  	stat2 = inb(b+LCR);		/* get current LCR register status */
X***************
X*** 384,389 ****
X--- 399,405 ----
X  	default:
X  		ttioctl(tp, com, vec);
X  	}
X+ 	outb(b+IER, ier_save);
X  	spl(s);
X  }
X  
X***************
X*** 466,472 ****
X  		/*
X  		 * Carrier changed.
X  		 */
X! 		if ( b & MS_DRLSD ) {
X  			/*
X  			 * wakeup open
X  			 */
X--- 482,489 ----
X  		/*
X  		 * Carrier changed.
X  		 */
X! 		if ((b & MS_DRLSD) || drlsd) {
X! 			drlsd = 0;
X  			/*
X  			 * wakeup open
X  			 */
X***************
X*** 482,487 ****
X--- 499,505 ----
X  				 * clear carrier flag; send hangup signal
X  				 */
X  				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
X+ 				rawin_ct = 0;
X  				tthup( tp );
X  			}
X  		}
X***************
X*** 497,502 ****
X--- 515,521 ----
X  		else
X  			tp->t_rawin.si_ox++;
X  	}
X+ 	rawin_ct = 0;
X  
X  	/*
X  	 * Calculate free output slot count.
X***************
X*** 520,530 ****
X  	 * (Re)start output, wake sleeping processes, etc.
X  	 */
X  	ttstart( tp );
X  
X  	/*
X  	 * Schedule next cycle.
X  	 */
X! 	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
X  }
X  
X  /*
X--- 539,554 ----
X  	 * (Re)start output, wake sleeping processes, etc.
X  	 */
X  	ttstart( tp );
X+ 	
X+ 	if (want_rts) {
X+ 		RTS_ON();
X+ 		want_rts = 0;
X+ 	}
X  
X  	/*
X  	 * Schedule next cycle.
X  	 */
X! 	timeout( &tp->t_rawtim, HZ/20, alxcycle, tp );
X  }
X  
X  /*
X***************
X*** 619,624 ****
X--- 643,659 ----
X  		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
X  		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
X  			tp->t_rawin.si_ix = 0;
X+ 			
X+ 		/*
X+ 		 * Preliminary code!
X+ 		 * De-assert RTS if we are close to filling the input silo.
X+ 		 */	
X+ 		rawin_ct++;
X+ 		if (!want_rts && rawin_ct > SI_BUFSIZ / 4) {
X+ 			RTS_OFF();
X+ 			want_rts = 1;
X+ 		}
X+ 		
X  		goto rescan;
X  
X  	case Tx_INTR:
X***************
X*** 650,655 ****
X--- 685,707 ----
X  			defer( alxcycle, tp );
X  		}
X  		goto rescan;
X+ 		
X+ 	case MS_INTR:
X+ 		/*
X+ 		 * This is preliminary code - use delta of CTS from
X+ 		 * modem to implement flow control.
X+ 		 *
X+ 		 * Sense delta of RLSD for use by alxcycle().
X+ 		 */
X+ 		b = inb(ALPORT+MSR);
X+ 		if (b & MS_DCTS)
X+ 			if (b & MS_CTS)
X+ 				tp->t_flags &= ~T_STOP;
X+ 			else
X+ 				tp->t_flags |= T_STOP;
X+ 		if (b & MS_DRLSD)
X+ 			drlsd = 1;		
X+ 		goto rescan;
X  	}
X  }
X  
END_OF_FILE
if test 4270 -ne `wc -c <'310.diff'`; then
    echo shar: \"'310.diff'\" unpacked with wrong size!
fi
chmod +x '310.diff'
# end of '310.diff'
fi
if test -f '311.diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'311.diff'\"
else
echo shar: Extracting \"'311.diff'\" \(3284 characters\)
sed "s/^X//" >'311.diff' <<'END_OF_FILE'
X*** alx311.c	Sat Feb  2 16:45:12 1991
X--- alx.c	Sat Feb 16 01:27:53 1991
X***************
X*** 27,32 ****
X--- 27,35 ----
X  #define	IENABLE	(IE_RxI+IE_TxI+IE_LSI)
X  #define IE_ALL	(IE_RxI|IE_TxI|IE_LSI|IE_MSI)
X  
X+ #define RTS_ON()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) | MC_RTS); }
X+ #define RTS_OFF()	{ outb(ALPORT+MCR, inb(ALPORT+MCR) & ~MC_RTS); }
X+ 
X  int	al_sg_set = 0;
X  int	al_sg_clr = 0;
X  static int poll_divisor;  /* set by set_poll_rate(), read by alxclk() */
X***************
X*** 195,201 ****
X  			*irqtty = tp_table[AL_NUM];
X  			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
X  		}
X! 		want_rts = 1;
X  	
X  		outb(b+IER, IENABLE);        /* enable interrupts */
X  	
X--- 198,205 ----
X  			*irqtty = tp_table[AL_NUM];
X  			outb(b+MCR, MC_RTS|MC_DTR|MC_OUT2);
X  		}
X! 		RTS_ON();
X! 		want_rts = 0;
X  	
X  		outb(b+IER, IENABLE);        /* enable interrupts */
X  	
X***************
X*** 206,212 ****
X  					SVTTOUT);	/* wait for carrier */
X  		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
X  					outb(b+MCR, inb(b+MCR)&MC_OUT2);
X- 					want_rts = 0;
X  	                    		/*
X  					 * make sure port is hungup
X  					 * disable all ints except for TxI
X--- 210,215 ----
X***************
X*** 300,306 ****
X  		 * Hangup port
X  		 */
X  		outb(b+MCR, inb(b+MCR)&MC_OUT2);
X- 		want_rts = 0;
X  		/*
X  		 * Hold dtr low for timeout
X  		 */
X--- 303,308 ----
X***************
X*** 422,428 ****
X  		if (tp->t_flags & T_MODC) {  /* modem control? */
X  			tp->t_flags &= ~T_CARR;  /* indicate no carrier */
X  			outb(b+MCR, inb(b+MCR) & MC_OUT2); /* hangup */
X- 			want_rts = 0;
X  		}
X  	}
X  
X--- 424,429 ----
X***************
X*** 515,522 ****
X  			tp->t_rawin.si_ox++;
X  	}
X  	rawin_ct = 0;
X- 	if (want_rts)
X- 		outb(b+MCR, inb(b+MCR) | MC_RTS);
X  
X  	/*
X  	 * Calculate free output slot count.
X--- 516,521 ----
X***************
X*** 540,550 ****
X  	 * (Re)start output, wake sleeping processes, etc.
X  	 */
X  	ttstart( tp );
X  
X  	/*
X  	 * Schedule next cycle.
X  	 */
X! 	timeout( &tp->t_rawtim, HZ/10, alxcycle, tp );
X  }
X  
X  /*
X--- 539,554 ----
X  	 * (Re)start output, wake sleeping processes, etc.
X  	 */
X  	ttstart( tp );
X+ 	
X+ 	if (want_rts) {
X+ 		RTS_ON();
X+ 		want_rts = 0;
X+ 	}
X  
X  	/*
X  	 * Schedule next cycle.
X  	 */
X! 	timeout( &tp->t_rawtim, HZ/20, alxcycle, tp );
X  }
X  
X  /*
X***************
X*** 639,652 ****
X  		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
X  		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
X  			tp->t_rawin.si_ix = 0;
X! 			rawin_ct++;
X  		/*
X  		 * Preliminary code!
X  		 * De-assert RTS if we are close to filling the input silo.
X  		 */	
X! 		if (want_rts && (sizeof(tp->t_rawin.si_buf) - rawin_ct < 4))
X! 			outb(b+MCR, inb(b+MCR) & ~MC_RTS);
X! 			goto rescan;
X  
X  	case Tx_INTR:
X  		/*
X--- 643,660 ----
X  		tp->t_rawin.si_buf[ tp->t_rawin.si_ix ] = b;
X  		if ( ++tp->t_rawin.si_ix >= sizeof(tp->t_rawin.si_buf) )
X  			tp->t_rawin.si_ix = 0;
X! 			
X  		/*
X  		 * Preliminary code!
X  		 * De-assert RTS if we are close to filling the input silo.
X  		 */	
X! 		rawin_ct++;
X! 		if (!want_rts && rawin_ct > SI_BUFSIZ / 4) {
X! 			RTS_OFF();
X! 			want_rts = 1;
X! 		}
X! 		
X! 		goto rescan;
X  
X  	case Tx_INTR:
X  		/*
X***************
X*** 693,698 ****
X--- 701,707 ----
X  				tp->t_flags |= T_STOP;
X  		if (b & MS_DRLSD)
X  			drlsd = 1;		
X+ 		goto rescan;
X  	}
X  }
X  
END_OF_FILE
if test 3284 -ne `wc -c <'311.diff'`; then
    echo shar: \"'311.diff'\" unpacked with wrong size!
fi
chmod +x '311.diff'
# end of '311.diff'
fi
echo shar: End of shell archive.
exit 0

@
0707070064030104301004440000030000030000011777770507310670600005400000060162/newbits/kernel/USRSRC/i8086/drv/RCS/fl.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.49.02;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.22.22;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * This is a driver for the IBM AT or PC/XT
 * floppy, using interrupts and DMA on
 * the NEC 756 floppy chip. Ugh.
 * Handles single, double and quad
 * density drives, 8, 9, 15 or 18 sectors per track.
 * 15 and 18 sectors per track only available on the IBM_AT.
 *
 * Minor device assignments: xxuuhkkk
 *	uu - unit = 0/1/2/3
 *	kkk - kind, struct fdata infra.
 *	h - alternating head rather than side by side
 *
 */

#include	<sys/coherent.h>
#include	<sys/i8086.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<errno.h>
#include	<sys/uproc.h>
#include	<sys/fdioctl.h>
#include	<sys/sched.h>
#include	<sys/dmac.h>

#define		BIT(n)		(1 << (n))

/*
 * Patchable parameters (default to IBM PC/XT values).
 */

int	fl_srt = 0xC;	/* Floppy seek step rate, in unit 2 millisec */
			/* NOT DIRECTLY ENCODED */
			/* COMPAQ wants 0xD */
int	fl_hlt = 1;	/* Floppy head load time, in unit 4 millisec */
int	fl_hut = 0xF;	/* Floppy head unload time, in unit 32 millisec */

int	flload();
int	flunload();
int	flopen();
int	flblock();
int	flread();
int	flwrite();
int	flioctl();
int	fldelay();
int	flintr();
int	fltimeout();
int	nulldev();
int	nonedev();

#define	FDCMAJ	4			/* Major # */

CON	flcon	= {
	DFBLK|DFCHR,			/* Flags */
	FDCMAJ,				/* Major index */
	flopen,				/* Open */
	nulldev,			/* Close */
	flblock,			/* Block */
	flread,				/* Read */
	flwrite,			/* Write */
	flioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	fltimeout,			/* Timeout */
	flload,				/* Load */
	flunload			/* Unload */
};

#define	MTIMER	5			/* Motor timeout */
#define	FDCDOR	0x3F2			/* Digital output */
#define	FDCDAT	0x3F5			/* Data register */
#define	FDCMSR	0x3F4			/* Main status register */
#define	FDCRATE	0x3F7			/* Transfer rate (500,300,250 Kbps) */

#define	DORDS	0x03			/* Drive select bits */
#define	DORNMR	0x04			/* Not master reset */
#define	DORIEN	0x08			/* Interrupt, DMA enable */
#define	DORMS	0xF0			/* Motor enables */

#define	MSRDB	0x0F			/* Drive busy */
#define	MSRCB	0x10			/* Control busy */
#define	MSRNDMA	0x20			/* Not DMA */
#define	MSRDIO	0x40			/* Data direction */
#define	MSRRQM	0x80			/* Request for master */

/*
 * Status Register 0 - Bit Definitions.
 */
#define	ST0_US0	0x01			/* Unit Select 0 */
#define	ST0_US1	0x02			/* Unit Select 1 */
#define	ST0_HD	0x04			/* Head Address */
#define	ST0_NR	0x08			/* Not Ready */
#define	ST0_EC	0x10			/* Equipment Check */
#define	ST0_SE	0x20			/* Seek End */
#define	ST0_IC	0xC0			/* Interrupt code */
#define	ST0_NT	0x00			/* Normal Termination */

/*
 * Status Register 1 - Bit Definitions.
 */
#define	ST1_MA	0x01			/* Missing Address Mark */
#define	ST1_NW	0x02			/* Not writeable */
#define	ST1_ND	0x04			/* No Data */
	/*	0x08 */			/* Not used - always 0 */
#define	ST1_OR	0x10			/* Overrun */
#define	ST1_DE	0x20			/* Data Error */
	/*	0x40 */			/* Not used - always 0 */
#define	ST1_EN	0x80			/* End of Cylinder */

/*
 * Status Register 2 - Bit Definitions.
 */
#define	ST2_MD	0x01			/* Missing Address Mark in Data Field */
#define	ST2_BC	0x02			/* Bad Cylinder */
#define	ST2_SN	0x04			/* Scan Not Satisfied */
#define	ST2_SH	0x08			/* Scan Equal Hit */
#define	ST2_WC	0x10			/* Wrong Cylinder */
#define	ST2_DD	0x20			/* Data Error in Data Field */
#define	ST2_CM	0x40			/* Control Mark */
	/*	0x80 */			/* Not used - always 0 */

/*
 * Status Register 3 - Bit Definitions.
 */
#define	ST3_US0	0x01			/* Unit Select 0 */
#define	ST3_US1	0x02			/* Unit Select 1 */
#define	ST3_HD	0x04			/* Head Address */
#define	ST3_TS	0x08			/* Two Sides */
#define	ST3_T0	0x10			/* Track 0 */
#define	ST3_RDY	0x20			/* Ready */
#define	ST3_WP	0x40			/* Write Protected */
#define	ST3_FT	0x80			/* Fault */

/*
 * Controller Commands.
 */
#define	CMDSPEC	0x03			/* Specify */
#define	CMDRCAL	0x07			/* Recal */
#define	CMDSEEK	0x0F			/* Seek */
#define	CMDRDAT	0x66			/* Read data */
#define	CMDWDAT	0x45			/* Write data */
#define	CMDSINT	0x08			/* Sense status */
#define	CMDFMT	0x4D			/* Format track */

/*
 * Driver States.
 */
#define	SIDLE	0			/* Idle */
#define	SSEEK	1			/* Need seek */
#define	SRDWR	2			/* Need read/write command */
#define	SENDIO	3			/* Need end I/O processing */
#define	SDELAY	4			/* Delay before next disk operation */
#define	SHDLY	5			/* Head settling delay before r/w */
#define SLOCK	6			/* Got DMA controller lock */

#define funit(x)	(minor(x)>>4)	/* Unit/drive number */
#define fkind(x)	(minor(x)&0x7)	/* Kind of format */
#define	fhbyh(x)	(minor(x)&0x8)	/* 0=Side by side, 1=Head by head */

static
struct	fdata {
	int	fd_size;	/* Blocks per diskette */
	int	fd_nhds;	/* Heads per drive */
	int	fd_trks;	/* Tracks per side */
	int	fd_offs;	/* Sector base */
	int	fd_nspt;	/* Sectors per track */
	char	fd_GPL[4];	/* Controller gap param (indexed by rate) */
	char	fd_N;		/* Controller size param */
	char	fd_FGPL;	/* Format gap length */
} fdata[] = {
/* 8 sectors per track, surface by surface seek. */
	{  320,1,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */
	{  640,2,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */
	{ 1280,2,80,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */
/* 9 sectors per track, surface by surface seek. */
	{  360,1,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */
	{  720,2,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */
	{ 1440,2,80,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */
/* 15 sectors per track, surface by surface seek. */
	{ 2400,2,80,0,15, { 0x1B,0x00,0x00 }, 2,0x54 }, /* High capacity */
/* 18 sectors per track, surface by surface seek. */
	{ 2880,2,80,0,18, { 0x1B,0x00,0x00 }, 2,0x54 }	/* 1.44 3.5" */
};


static
struct	fl	{
	BUF	*fl_actf;		/* Queue, forward */
	BUF	*fl_actl;		/* Queue, backward */
	paddr_t	fl_addr;		/* Address */
	int	fl_nsec;		/* # of sectors */
	int	fl_secn;		/* Current sector */
	struct	fdata fl_fd;		/* Disk kind data */
	int	fl_fcyl;		/* Floppy cylinder # */
	char	fl_incal[4];		/* Disk in cal flags */
	char	fl_ndsk;		/* # of 5 1/4" drives */
	char	fl_unit;		/* Unit # */
	char	fl_mask;		/* Handy unit mask */
	char	fl_hbyh;		/* 0/1 = Side by side/Head by head */
	char	fl_nerr;		/* Error count */
	int	fl_ncmdstat;		/* Number of cmd status bytes recvd */
	char	fl_cmdstat[8];		/* Command Status buffer */
	int	fl_nintstat;		/* Number of intr status bytes recvd */
	char	fl_intstat[4];		/* Interrupt Status buffer */
	int	fl_fsec;		/* Floppy sector # */
	int	fl_head;		/* Floppy head */
	char	fl_init;		/* FDC init done flag */
	char	fl_state;		/* Processing state */
	char	fl_mstatus;		/* Motor status */
	char	fl_time[4];		/* Motor timeout */
	char	fl_rate;		/* Data rate: 500,300,250,?? kbps */
	char	fl_type[4];		/* Type of drive: 2 = HiCap */
	int	fl_wflag;		/* Write operation  */
	int	fl_recov;		/* Recovery initiated */
}	fl;

static	BUF	flbuf;
static	TIM	fltim;
static	TIM	fldmalck;	/* DMA lock deferred function structure.     */

/*
 * The load routine asks the
 * switches how many drives are present
 * in the machine, and sets up the field
 * in the floppy database. It also grabs
 * the level 6 interrupt vector.
 */
static
flload()
{
	register int	eflag;
	register int	s;

	/*
	 * Ensure DMA channel 2 is turned off.
	 * The Computerland ROM does not disable DMA channel after autoboot
	 * from hard disk.  The Western Digital controller board appears to
	 * send a dma burst when the floppy controller chip is reset.
	 */
	dmaoff( 2 );

	/*
	 * Read floppy equipment byte from CMOS ram
	 *	drive 0 is in high nibble, drive 1 is in low nibble.
	 */
	outb( 0x70, 0x10 );
	/* delay */
	eflag = inb( 0x71 );

	/*
	 * Flag hardware as an IBM AT if neither equipment byte nibble is
	 * greater than 4 (since 5 through 15 are reserved nibble values - see
	 * IBM AT Technical Reference manual, page 1-50).  Note that this
	 * relies on the fact that in the XT, this byte will "float" high.
	 * NOTE: 1.44 Mbyte 3.5 inch drives are type 4
	 */
	if ( (eflag & 0x88) == 0 ) {

		/*
		 * Reinitialize patchable parameters for IBM AT.
		 */
		fl_srt = 0xD;	/* Floppy seek step rate, in unit 2 ms */
				/* NOT DIRECTLY ENCODED */
		fl_hlt = 25;	/* Floppy head load time, in unit 4 ms */

		/*
		 * Define AT drive information.
		 */
		fl.fl_type[0]	= eflag >> 4;
		fl.fl_type[1]	= eflag & 15;
		fl.fl_rate	= 1; /* Must not be 2 */

		/*
		 * Determine number of AT floppy drives.
		 */
		if ( eflag & 0xF0 ) {
			fl.fl_ndsk++;
			if ( eflag & 0x0F )
				fl.fl_ndsk++;
		}
	} else {
		/*
		 * Define XT drive information.
		 */
		eflag		= int11();
		fl.fl_rate	= 2;
		if ( eflag & 1 )
			fl.fl_ndsk = ((eflag >> 6) & 0x03) + 1;
	}

	if ( fl.fl_ndsk ) {

		s = sphi();
		outb(FDCDOR, 0);
		setivec(6, &flintr);

		outb(FDCDOR, 0);
		outb(FDCDOR, DORNMR);

		if ( fl.fl_rate != 2 )
			outb(FDCRATE, fl.fl_rate );

		flput(CMDSPEC);
		flput((fl_srt<<4)|fl_hut);
		flput(fl_hlt<<1);
		spl( s );
	}
}

/*
 * Release resources.
 */
flunload()
{
	/*
	 * Clear interrupt vector.
	 */
	if ( fl.fl_ndsk )
		clrivec(6);

	/*
	 * Cancel timed function.
	 */
	timeout( &fltim, 0, NULL, NULL );

	/*
	 * Cancel periodic [1 second] invocation.
	 */
	drvl[FDCMAJ].d_time = 0;

	/*
	 * Turn motors off.
	 */
	outb(FDCDOR, DORNMR | DORIEN );
}

/*
 * The open routine screens out
 * opens of illegal minor devices and
 * performs the NEC specify command if
 * this is the very first floppy disk
 * open call.
 */

static
flopen( dev, mode )

dev_t	dev;
int	mode;

{
	/*
	 * Validate existence and data rate [Gap length != 0].
	 */
	if ( ( funit(dev) >= fl.fl_ndsk )
	  || ( fdata[ fkind(dev) ].fd_GPL[ flrate(dev) ] == 0 ) ) {

		u.u_error = ENXIO;
		return;
	}
}

/*
 * The read routine just calls
 * off to the common raw I/O processing
 * code, using a static buffer header in
 * the driver.
 */

static
flread( dev, iop )

dev_t	dev;
IO	*iop;

{
	dmareq(&flbuf, iop, dev, BREAD);
}

/*
 * The write routine is just like the
 * read routine, except that the function code
 * is write instead of read.
 */

static
flwrite( dev, iop )

dev_t	dev;
IO	*iop;

{
	dmareq(&flbuf, iop, dev, BWRITE);
}

/*
 * The ioctl routine simply queues a format request
 * using flbuf.
 * The only valid command is to format a track.
 * The parameter block contains the header records supplied to the controller.
 */

static
flioctl( dev, com, par )

dev_t	dev;
int	com;
char	*par;

{
	register unsigned s;
	register struct fdata *fdp;
	unsigned hd, cyl;

	if (com != FDFORMAT) {
		u.u_error = EINVAL;
		return;
	}

	fdp = &fdata[ fkind(dev) ];
	cyl = getubd(par);
	hd  = getubd(par+1);

	if (hd > 1 || cyl >= fdp->fd_trks) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * The following may need some explanation.
	 * dmareq will:
	 *	claim the buffer,
	 *	bounds check the parameter buffer,
	 *	lock the parameter buffer in memory,
	 *	convert io_seek to b_bno,
	 *	dispatch the request,
	 *	wait for completion,
	 *	and unlock the parameter buffer.
	 * The b_bno is reconverted to hd, cyl in flfsm.
	 */

	s = fhbyh(dev) ? (cyl * fdp->fd_nhds + hd) : (hd * fdp->fd_trks + cyl);
	s *= fdp->fd_nspt;
	u.u_io.io_seek = ((long)s) * BSIZE;
	u.u_io.io_base = par;
	u.u_io.io_ioc = fdp->fd_nspt * 4;
	dmareq(&flbuf, &u.u_io, dev, FDFORMAT);
}

/*
 * Start up block I/O on a
 * buffer. Check that the block number
 * is not out of range, given the style of
 * the disk. Put the buffer header into the
 * device queue. Start up the disk if the
 * device is idle.
 */

static
flblock( bp )

register BUF	*bp;

{
	register int	s;
	register unsigned bno;

	bno = bp->b_bno + (bp->b_count >> 9) - 1;
	if ((unsigned)bp->b_bno > fdata[ fkind(bp->b_dev) ].fd_size) {
		bp->b_flag |= BFERR;
		bdone(bp);
		return;
	}
	if (bp->b_req != FDFORMAT && bno >= fdata[ fkind(bp->b_dev) ].fd_size) {
		bp->b_resid = bp->b_count;
		if (bp->b_flag & BFRAW)
			bp->b_flag |= BFERR;
		bdone(bp);		/* return w/ b_resid != 0 */
		return;
	}

	if ((bp->b_count&0x1FF) != 0) {
		if (bp->b_req != FDFORMAT) {
			bp->b_flag |= BFERR;
			bdone(bp);
			return;
		}
	}

	bp->b_actf = NULL;
	s = sphi();	/* s was already == sphi() on at least PC/XT. */

	if (fl.fl_actf == NULL)
		fl.fl_actf = bp;
	else
		fl.fl_actl->b_actf = bp;

	fl.fl_actl = bp;

	if (fl.fl_state == SIDLE)
		flfsm();

	spl( s );
}

/*
 * This finite state machine is
 * responsible for all sequencing on the disk.
 * It builds the commands, does the seeks, spins up
 * the drive motor for 1 second on the first call,
 * and so on.
 * Note that the format command is rather obscurely shoehorned into this.
 */

static
flfsm()
{
	register BUF	*bp;
	register int	flcmd;
	register int	i;

again:
	bp = fl.fl_actf;

	switch (fl.fl_state) {

	case SIDLE:
		drvl[FDCMAJ].d_time = 1;

		if ( bp == NULL )
			break;

		fl.fl_fd   = fdata[ fkind(bp->b_dev) ];
		fl.fl_unit = funit( bp->b_dev );
		fl.fl_hbyh = fhbyh( bp->b_dev );

		fl.fl_mask = 0x10 << fl.fl_unit;

		fl.fl_addr = bp->b_paddr;
		fl.fl_secn = bp->b_bno;
		fl.fl_time[fl.fl_unit] = 0;

		if ((fl.fl_nsec = bp->b_count>>9) == 0)
			fl.fl_nsec = 1;

		fl.fl_nerr = 0;

		/*
		 * Set data rate if changed.
		 * NOTE: XT never changes data rate.
		 */
		if ( (i = flrate(bp->b_dev)) != fl.fl_rate )
			outb(FDCRATE, fl.fl_rate = i );

		/*
		 * Motor is turned off - turn it on, wait 1 second.
		 */
		if ((fl.fl_mstatus&fl.fl_mask) == 0) {

			fl.fl_mstatus |= fl.fl_mask;
			outb(FDCDOR, DORNMR|DORIEN|fl.fl_mstatus|fl.fl_unit);
			flsense();

			timeout( &fltim, HZ, fldelay, SSEEK );
			fl.fl_time[fl.fl_unit] = 0;
			fl.fl_state = SDELAY;
			break;
		}
		/* no break */

	case SSEEK:
		fl.fl_time[fl.fl_unit] = 0;
		outb(FDCDOR, DORNMR|DORIEN|fl.fl_mstatus|fl.fl_unit);
		flsense();

		/*
		 * Drive is not calibrated - seek to track 0.
		 */
		if (fl.fl_incal[fl.fl_unit] == 0) {
			++fl.fl_incal[fl.fl_unit];
			flput(CMDRCAL);
			flput(fl.fl_unit);
			fl.fl_state = SSEEK;
			break;
		}

		fl.fl_fsec = (fl.fl_secn % fl.fl_fd.fd_nspt) + 1;

		/*
		 * Seek cylinder by cylinder (XENIX/DOS compatible).
		 */
		if (fl.fl_hbyh) {
	                fl.fl_head = fl.fl_secn / fl.fl_fd.fd_nspt;
			fl.fl_fcyl = fl.fl_head / fl.fl_fd.fd_nhds;
			fl.fl_head = fl.fl_head % fl.fl_fd.fd_nhds;
		}
		
		/*
		 * Seek surface by surface.
		 */
		else {
			fl.fl_fcyl = fl.fl_secn / fl.fl_fd.fd_nspt;
			fl.fl_head = fl.fl_fcyl / fl.fl_fd.fd_trks;
			fl.fl_fcyl = fl.fl_fcyl % fl.fl_fd.fd_trks;
		}

		flput(CMDSEEK);
		flput((fl.fl_head<<2) | fl.fl_unit);

		if ( fl.fl_fd.fd_trks == 80 )
			flput(fl.fl_fcyl);
		else if ( fl.fl_type[fl.fl_unit] == 2 )
			flput(fl.fl_fcyl << 1);		/* double step */
		else if ( fl.fl_type[fl.fl_unit] == 4 )
			flput(fl.fl_fcyl << 1);		/* double step */
		else
			flput(fl.fl_fcyl);

		fl.fl_state = SHDLY;
		break;

	case SHDLY:
		/*
		 * Delay for minimum 15 milliseconds after seek before w/fmt.
		 * 2 clock ticks would give 10-20 millisecond [100 Hz clock].
		 * 3 clock ticks gives      20-30 millisecond [100 Hz clock].
		 */
		if ( bp->b_req != BREAD ) {
			timeout( &fltim, 3, fldelay, SRDWR );
			fl.fl_state = SDELAY;
			break;
		}
		/* no break */

	case SRDWR:
		/*
		 * Disable watchdog timer while waiting to lock DMA controller.
		 */
		fl.fl_time[fl.fl_unit] = -1;

		/*
		 * Next state will be DMA locked state.
		 */
		fl.fl_state = SLOCK;

		/*
		 * If DMA controller locked by someone else, exit for now.
		 */
		if ( dmalock( &fldmalck, flfsm, 0 ) != 0 )
			return;

	case SLOCK:
		/*
		 * Reset watchdog timer to restart timeout sequence.
		 */
		fl.fl_time[fl.fl_unit] = 0;

		flcmd = CMDRDAT;
		fl.fl_wflag = 0;

		if (bp->b_req == BREAD)
			;

		else if (bp->b_req == BWRITE) {
			fl.fl_wflag = 1;
			flcmd = CMDWDAT;
		}
		
		else {
			fl.fl_wflag = 1;
			flcmd = CMDFMT;

			if(dmaon(2, fl.fl_addr, bp->b_count, fl.fl_wflag) == 0)
				goto straddle;

			else
				goto command;
		}

		if (dmaon(2, fl.fl_addr, 512, fl.fl_wflag) == 0) {
straddle:
			devmsg(bp->b_dev, "fd: DMA page straddle at %x:%x",
				fl.fl_addr);
			dmaunlock( &fldmalck );
			bp->b_flag |= BFERR;
			fldone( bp );
			goto again;
		}
command:
		dmago(2);
		flput(flcmd);
		flput((fl.fl_head<<2) | fl.fl_unit);

		if (bp->b_req == FDFORMAT) {
			flput(fl.fl_fd.fd_N);		/* N */
			flput(fl.fl_fd.fd_nspt);	/* SC */
			flput(fl.fl_fd.fd_FGPL);	/* GPL */
			flput(0xF6);			/* D */
		}
		
		else {
			flput(fl.fl_fcyl);
			flput(fl.fl_head);
			flput(fl.fl_fsec);
			flput(fl.fl_fd.fd_N);		/* N */
			flput(fl.fl_fd.fd_nspt);	/* EOT */
			flput(fl.fl_fd.fd_GPL[fl.fl_rate]); /* GPL */
			flput(0xFF);			/* DTL */
		}

		fl.fl_state = SENDIO;
		break;

	case SENDIO:
		fl.fl_time[fl.fl_unit] = 0;
		dmaoff(2);
		dmaunlock( &fldmalck );

		if ((fl.fl_cmdstat[0]&ST0_IC) != ST0_NT) {
			if (++fl.fl_nerr < 5) {
				fl.fl_incal[fl.fl_unit] = 0;
				fl.fl_state = SSEEK;
			}
			
			else {
				flstatus();
				bp->b_flag |= BFERR;
				fldone(bp);
			}
		}

		else if (--fl.fl_nsec == 0) {
			bp->b_resid = 0;
			fldone(bp);
		}
		
		else {
			++fl.fl_secn;
			fl.fl_addr += 512;	/* 512 == fl.fl_fd.fd_nbps */
			fl.fl_state = SSEEK;
		}

		/*
		 * Delay for minimum 1.5 msecs after writing before seek.
		 */
		if ( fl.fl_wflag ) {
			timeout( &fltim, 2, fldelay, fl.fl_state );
			fl.fl_state = SDELAY;
			break;
		}

		goto again;

	case SDELAY:
		/*
		 * Ignore interrupts until timeout occurs.
		 */
		break;

	default:
		panic("fds");
	}
}

/*
 * Delay before initiating next operation.
 * This allows the floppy motor to turn on,
 * the head to settle before writing,
 * the erase head to turn off after writing, etc.
 */
static
fldelay( state )
int state;
{
	int s;

	s = sphi();
	if ( fl.fl_state == SDELAY ) {
		fl.fl_state = state;
		flfsm();
	}
	spl( s );
}

/*
 * The flrate function returns the data rate for the flopen and flfsm routines.
 */
static int
flrate( dev )
register dev_t dev;
{
	register int rate;

	/*
	 * Default is 250 Kbps.
	 */
	rate = 2;

	/*
	 * Check for high capacity drive.
	 */
	if ( fl.fl_type[ funit(dev) ] == 2 ) {

		/*
		 * 300 Kbps.
		 */
		rate--;

		/*			       
		 * Check for high capacity media.
		 */
		if ( fdata[ fkind(dev) ].fd_nspt == 15 ) {

			/*
			 * 500 Kbps.
			 */
			rate--;
		}
	} else if (fl.fl_type[funit(dev)] == 4 && fkind(dev) == 7)
		rate = 0;

	return( rate );
}

/*
 * This routine is called by the
 * clock handler every second. If the drive
 * has been idle for a long time it turns off
 * the motor and shuts off the timeouts.
 */

static
fltimeout()
{
	register int	unit;
	register int	mask;
	register int	s;

	s = sphi();

	/*
	 * Scan all drives, looking for motor timeouts.
	 */
	for ( unit=0, mask=0x10; unit < 4; unit++, mask <<= 1 ) {

		/*
		 * Ignore drives which aren't spinning.
		 */
		if ( (fl.fl_mstatus & mask) == 0 )
			continue;

		/*
		 * If timer is disabled (i.e. we are waiting for the DMA
		 * controller), go on to the next drive.
		 */
		if ( fl.fl_time[unit] < 0 )
			continue;

		/*
		 * Leave recently accessed (in last 4 seconds) drives spinning.
		 */
		if ( ++fl.fl_time[unit] < MTIMER )
			continue;

		/*
		 * Timeout drives which have been inactive for 5 seconds.
		 */
		fl.fl_mstatus &= ~mask;

		/*
		 * Not selected drive, or selected drive is idle.
		 */
		if ( (unit != fl.fl_unit) || (fl.fl_state == SIDLE) )
			continue;

		/*
		 * Active drive did not complete operation within 5 seconds.
		 * Attempt recovery.
		 */
		flrecov();

		/*
		 * Initiate next block request.
		 */
		if ( fl.fl_state == SIDLE )
			flfsm();
	}

	/*
	 * Physically turn off drives which timed out.
	 */
	outb(FDCDOR, DORNMR | DORIEN | fl.fl_mstatus | fl.fl_unit);

	/*
	 * Stop checking once all drives have been stopped.
	 */
	if ( fl.fl_mstatus == 0 )
		drvl[FDCMAJ].d_time = 0;

	spl(s);
}

/*
 * The recovery routine resets and reprograms the floppy controller,
 * and discards any queued requests on the current drive.
 * This is required if the floppy door is open, or diskette is missing.
 */

flrecov()
{
	register BUF * bp;
	register dev_t dev;

	/*
	 * Disable DMA transfer.
	 * Reset floppy controller.
	 */
	dmaoff( 2 );

	/*
	 * Unlock the controller if locked by us.
	 */
	dmaunlock( &fldmalck );

	outb(FDCDOR, 0);
	outb(FDCDOR, DORNMR);

	/*
	 * Program transfer bps.
	 */
	if ( fl.fl_rate != 2 )
		outb( FDCRATE, fl.fl_rate );

	/*
	 * Program floppy controller.
	 */
	flput( CMDSPEC );
	flput( (fl_srt << 4) | fl_hut );
	flput( fl_hlt << 1 );

	/*
	 * Drives are no longer in calibration.
	 */
	fl.fl_incal[0] =
	fl.fl_incal[1] =
	fl.fl_incal[2] =
	fl.fl_incal[3] = 0;

	/*
	 * Abort all block requests on current drive after 1st recov attempt.
	 */
	if ( bp = fl.fl_actf ) {
		printf("fd%d: <Door Open>\n", fl.fl_unit );
		dev = bp->b_dev;
		do {
			bp->b_flag |= BFERR;
			fldone( bp );
		} while ( (bp = fl.fl_actf) && (bp->b_dev == dev) );
	}

	/*
	 * Delay before setting controller state to idle.
	 * This gives time for spurious floppy interrupts to occur.
	 * NOTE: Can't call flfsm(), since it may call us [future revision].
	 */
	timeout( &fltim, HZ/4, fldelay, SIDLE );
	fl.fl_state = SDELAY;
}

/*
 * The interrupt routine gets all
 * the status bytes the controller chip
 * will give it, then issues a sense interrupt
 * status command (which is necessary for a seek
 * to complete!) and throws all of the status
 * bytes away.
 */

static
flintr()
{
	register int s;

	s = sphi();
	flsense();

	if (fl.fl_state != SIDLE)
		flfsm();

	spl(s);
}

/*
 * Fldone() returns current request to operating system.
 */
fldone( bp )
register BUF * bp;
{
	fl.fl_actf  = bp->b_actf;
	fl.fl_state = SIDLE;
	bdone( bp );
}

/*
 * Flsense() issues a sense interrupt status command
 * to restore the controller to a quiescent state.
 */

static
flsense()
{
	register int	b;
	register int	n;
	register int	i = 0;
	register int	s;

	s = sphi();

	/*
	 * Read all the status bytes the controller will give us.
	 */
	n = 0;

	for (;;) {
		while (((b=inb(FDCMSR))&MSRRQM) == 0) {
			if ( --i == 0 ) {
				printf("flintr: timeout\n");
				break;
			}
		}

		if ((b&MSRDIO) == 0)
			break;

		b = inb(FDCDAT);
		if ( n < sizeof(fl.fl_cmdstat) )
			fl.fl_cmdstat[n++] = b;
	}

	fl.fl_ncmdstat = n;

	/*
	 * Issue a sense interrupt command and discard result.
	 */
	outb(FDCDAT, CMDSINT);

	n = 0;
	for (;;) {
		while (((b=inb(FDCMSR))&MSRRQM) == 0) {
			if ( --i == 0 ) {
				printf("flsense: timeout\n");
				break;
			}
		}

		if ((b&MSRDIO) == 0)
			break;

		b = inb(FDCDAT);
		if ( n < sizeof(fl.fl_intstat) )
			fl.fl_intstat[n++] = b;
	}
	fl.fl_nintstat = n;

	spl( s );
}

/*
 * Send a command byte to the
 * NEC chip, first waiting until the chip
 * says that it is ready. No timeout is
 * performed; if the chip dies, we do too!
 */

static
flput( b )

int	b;

{
	register int i = 0;

	while ( (inb(FDCMSR) & (MSRRQM|MSRDIO)) != MSRRQM ) {
		if ( --i == 0 ) {
			printf("flput: timeout\n");
			return;
		}
	}

	outb(FDCDAT, b);
}

/*
 * Dissassemble the floppy error status for user reference.
 */

static
flstatus()
{
	printf("fd%d: head=%u cyl=%u",
		fl.fl_cmdstat[0] & 3,
		fl.fl_head, fl.fl_fcyl );

	/*
	 * Report on ST0 bits.
	 */
	if ( fl.fl_ncmdstat >= 1 ) {
		if ( fl.fl_cmdstat[0] & ST0_NR )
			printf(" <Not Ready>");

		if ( fl.fl_cmdstat[0] & ST0_EC )
			printf(" <Equipment Check>");
	}

	/*
	 * Report on ST1 bits.
	 */
	if ( fl.fl_ncmdstat >= 2 ) {
		if ( fl.fl_cmdstat[1] & ST1_MA )
			printf(" <Missing Address Mark>");

		if ( fl.fl_cmdstat[1] & ST1_NW )
			printf(" <Write Protected>");

		if ( fl.fl_cmdstat[1] & ST1_ND )
			printf(" <No Data>");

		if ( fl.fl_cmdstat[1] & ST1_OR )
			printf(" <Overrun>");

		if ( fl.fl_cmdstat[1] & ST1_DE )
			printf(" <Data Error>");

		if ( fl.fl_cmdstat[1] & ST1_EN )
			printf(" <End of Cyl>");
	}

	/*
	 * Report on ST2 bits.
	 */
	if ( fl.fl_ncmdstat >= 3 ) {
		if ( fl.fl_cmdstat[2] & ST2_MD )
			printf(" <Missing Data Address Mark>");

		if ( fl.fl_cmdstat[2] & ST2_BC )
			printf(" <Bad Cylinder>");

		if ( fl.fl_cmdstat[2] & ST2_WC )
			printf(" <Wrong Cylinder>");

		if ( fl.fl_cmdstat[2] & ST2_DD )
			printf(" <Bad Data CRC>");

		if ( fl.fl_cmdstat[2] & ST2_CM )
			printf(" <Data Deleted>");
	}

	printf("\n");
}
@


1.1
log
@Initial revision
@
text
@d21 2
a22 2
#include	"coherent.h"
#include	"i8086.h"
a27 1
#include	<sys/timeout.h>
d30 1
a30 1
#include	"dmac.h"
@
0707070064030106751004440000030000030000011777770507310671400005300000013273/newbits/kernel/USRSRC/i8086/drv/RCS/fo2,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.22.29;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/usr/src/sys/coh/bio.c: 			sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
/usr/src/sys/coh/bio.c: 			sleep((char *)&bufneed, CVBLKIO, IVBLKIO, SVBLKIO);
/usr/src/sys/coh/bio.c: 		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
/usr/src/sys/coh/bio.c: 		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
/usr/src/sys/coh/clist.c: 		sleep((char *)&cltwant, CVCLIST, IVCLIST, SVCLIST);
/usr/src/sys/coh/pipe.c: 		sleep((char *)&ip->i_prx, CVPIPE, IVPIPE, SVPIPE);
/usr/src/sys/coh/pipe.c: 			sleep((char *)&ip->i_pwx, CVPIPE, IVPIPE, SVPIPE);
/usr/src/sys/coh/poll.c: 			 * Wake process if it is sleeping.
/usr/src/sys/coh/proc.c:  * wakes us up.  Since it is possible for many people to sleep on the
/usr/src/sys/coh/proc.c:  * was waiting for has completed and if not, go to sleep again.  `cl'
/usr/src/sys/coh/proc.c:  * of the sleep.  `sr' is the swap value that allows us to get swapped
/usr/src/sys/coh/proc.c: sleep(e, cl, sl, sr)
/usr/src/sys/coh/proc.c: 	 * Get ready to go to sleep and do so.
/usr/src/sys/coh/proc.c:  * Defer function to wake up all processes sleeping on the event `e'.
/usr/src/sys/coh/proc.c:  * Wake up all processes sleeping on the event `e'.
/usr/src/sys/coh/proc.c: 		sleep((char *)g, CVGATE, IVGATE, SVGATE);
/usr/src/sys/coh/seg.c: 			sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
/usr/src/sys/coh/sig.c: 		sleep((char *)&pts.pt_busy, CVPTSET, IVPTSET, SVPTSET);
/usr/src/sys/coh/sig.c: 			sleep((char *)&pts.pt_req, CVPTRET, IVPTRET, SVPTRET);
/usr/src/sys/coh/sys1.c:  * Pause.  Go to sleep on a channel that nobody will wakeup so that only
/usr/src/sys/coh/sys1.c: 		sleep((char *)&u, CVPAUSE, IVPAUSE, SVPAUSE);
/usr/src/sys/coh/sys1.c: 		sleep((char *)ppp, CVWAIT, IVWAIT, SVWAIT);
/usr/src/sys/coh/sys2.c: 		sleep( &cprocp->p_polls, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/aha.c: 		sleep( ccb, CVBLKIO, IVBLKIO, SVBLKIO );
/usr/src/sys/i8086/drv/alx.c:    	  		sleep((char *)(&AL_H_CLOSE), CVTTOUT, IVTTOUT,
/usr/src/sys/i8086/drv/alx.c: 	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
/usr/src/sys/i8086/drv/alx.c: 		sleep((char *)&AL_TIM, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/i8086/drv/alx.c: 		sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/i8086/drv/alx.c: 	 * (Re)start output, wake sleeping processes, etc.
/usr/src/sys/i8086/drv/dg.c:  * Use kernel function sleep(), which is NOT the system call by that name.
/usr/src/sys/i8086/drv/dg.c: 	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
/usr/src/sys/i8086/drv/dmareq.c: 		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
/usr/src/sys/i8086/drv/gc.c: 			sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/i8086/drv/hs.c: 			sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/i8086/drv/lp.c:  * sleep for a while.
/usr/src/sys/i8086/drv/lp.c: 			sleep((char *)p, 0, 0, 0);
/usr/src/sys/i8086/drv/lp.c: 		 * Check for sleeping process on ready printer.
/usr/src/sys/i8086/drv/mm.c: 				sleep((char*) &istty.t_oq,
/usr/src/sys/i8086/drv/ms.c: 		sleep(&u_stts, 0x7fff, 0x7fff, 0);
/usr/src/sys/i8086/drv/msg.c:  * Msgsnd() now checks for queue removal after waking from sleep.
/usr/src/sys/i8086/drv/msg.c:  * since system calls are synchronous unless they sleep or are interrupted.
/usr/src/sys/i8086/drv/msg.c: 		 * Wakeup processes sleeping on the removed message queue.
/usr/src/sys/i8086/drv/msg.c: 			sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/msg.c: 			sleep( msqs, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/msg.c: 		sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/rp.c: 		sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/rp.c: 			sleep( rp->q_ogate, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/rp.c: 		sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/rs.c: 			sleep( &rstty.rt_crefc,
/usr/src/sys/i8086/drv/rs.c: 			sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/rs.c: 		sleep( &rstty.rt_irefc, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/rs.c: 		sleep( &rstty.rt_orefc, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/rs.c: 			sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/i8086/drv/sem.c: 	sleep( ep, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/ss.c: #define LOPRI_RETRIES	5	/* # of retries with sleep between tries */
/usr/src/sys/i8086/drv/ss.c: 	sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
/usr/src/sys/i8086/drv/st.c: 		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/st.c: 		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/st.c: 		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/st.c:  *		Wake sleeping processes if appropriate.
/usr/src/sys/i8086/drv/st.c: 		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/drv/tn.c: 		sleep( &tp->RxReq[code], CVTTIN, IVTTIN, SVTTIN );
/usr/src/sys/i8086/drv/tn.c: 		sleep( &tp->TxReq, CVTTOUT, IVTTOUT, SVTTOUT );
/usr/src/sys/i8086/src/clist.s: 	call	sleep_
/usr/src/sys/ker/swap.c: 		sleep((char *)&stimer, CVSWAP, IVSWAP, SVSWAP);
/usr/src/sys/ttydrv/tty.c: 			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/ttydrv/tty.c: 			sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN);
/usr/src/sys/ttydrv/tty.c: 			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/ttydrv/tty.c: 			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
/usr/src/sys/ldrv/ldmain.c: 		sleep( (char *)&nopen, CVSWAP, IVSWAP, SVSWAP );
/usr/src/sys/ldrv/ldswap.c: 		sleep( (char *)&stimer, CVSWAP, IVSWAP, SVSWAP );
@
0707070064030106741004440000030000030000011777770507310671500006100000004016/newbits/kernel/USRSRC/i8086/drv/RCS/fontgen.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.22.32;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/*
 * fontgen - generate 16x8 font assembler source on stdout.
 */

#define	BIT(n)	(1 << (n))
#define	BITS(n)	(((n) >= 4) ? (3 << (((n) - 4) * 2)) : (3 << (((n) + 4) * 2)))

unsigned char ibuf[1024];
unsigned char odef[] = "\tB________ = 0000000\n";
unsigned char obuf[] = "\t.word\tB________\n";

main()
{
	register unsigned s;
	register unsigned j;
	register unsigned i;
	extern long lseek();

	/*
	 * Read fonts from /dev/mem at offset 0xFFA6E.
	 */
	close(0);
	if (open("/dev/mem", 0) != 0)
		fatal("/dev/mem: can't open\n");
	if (lseek( 0, 0xFFA6EL, 0) != 0xFFA6EL)
		fatal("/dev/mem: can't seek to fonts");
	if (read( 0, ibuf, sizeof ibuf ) != sizeof ibuf)
		fatal("/dev/mem: can't read fonts");

	/*
	 * Define symbolic constants.
	 */
	for (i=0; i < 256; ++i) {
		/* Generate constant's name. */
		s = i;
		for (j=10; --j >= 2; s>>=1)
			odef[j] = (s&1) ? 'X' : '_';

		/* Convert 8 pixel width to 16 pixels */
		s = 0;
		for (j=0; j < 8; ++j)
			if (i & BIT(j))
				s |= BITS(j);

		/* Generate constant's value */
		for (j=19; j >= 14; --j) {
			odef[j] = (s & 7) + '0';
			s >>= 3;
		}

		/* Print constant's name and value */
		send( odef );
	}
	send( "\n\t.globl\tfontw_\nfontw_:" );

	/*
	 * Define fonts for 128 characters.
	 */
	for (i=0; i < sizeof ibuf; ++i) {

		/* Format and print one pixel line */
		j = 16;
		s = ibuf[i];
		while ( --j >= 8 ) {
			obuf[j] = (s&1) ? 'X' : '_' ;
			s >>= 1;
		}
		send( obuf );

		/* Insert blank line between characters for readability */
		if ( (i & 7) == 7 )
			send( "\n" );
	}
	exit( 0 );
}

/*
 * Fatal( msg ) - report error, and abort.
 */

fatal( msg )
register char *msg;
{
	write( 2, msg, strlen(msg) );
	exit( 1 );
}

/*
 * send( s ) - write null-terminated string to standard output.
 */

send( s )
register char *s;
{
	write( 1, s, strlen(s) );
}
@
0707070064030106731004440000030000030000011777770507310671600005400000022700/newbits/kernel/USRSRC/i8086/drv/RCS/gc.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.22.36;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/*
 * Interrupt Driver Multi-Port Device Driver.
 * - supports version 7 compatible ioctl
 */

#include "coherent.h"
#include "ins8250.h"
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/proc.h>
#include <sys/tty.h>		/* indirectly includes sgtty.h */
#include <sys/con.h>
#include <errno.h>
#include <sys/timeout.h>	/* TIM */
#include <sched.h>		/* CVTTOUT, IVTTOUT, SVTTOUT */
#include <poll_clk.h>

/*
 * Definitions.
 *
 * MAX_GCNUM is the maximum number of devices that can be polled
 *   using this driver and can be revised up or down
 * PORT is a convenience macro for the base address of a port
 * port_config is the structure of the initial configuration for each
 *   polled port;  note that "speed" is NOT the actual baud rate, but
 *   the value of the symbol for that baud rate as defined in
 *   /usr/include/sgtty.h
 * GCINT is the IRQ number for the interrupt belonging to the board.
 *   On the AT, IRQ2 is mapped to the same vector as IRQ9.
 */
#define MAX_GCNUM	8
#define	PORT	((int)(tp->t_ddp))
struct port_config {
	int	addr;	/* base address of the 8250-family UART */
	int	speed;	/* B0..B19200 */
};
#define GCINT		2

/*
 * Export Variables - these can be patched without recompiling and linking
 *
 * GCNUM is the actual number of polled serial ports, and should be
 *   less than or equal to MAX_GCNUM
 * GCIRPT is the I/O address of the multiport interrupt register;
 *   a value of 0 in bit 0..3 means a pending interrupt for port 0..3
 * GC_PORTS is an array of address/speed pairs, one for each port
 */
int	GCNUM = 4;
int	GCIRPT = 0x2BF;
/*
 * Defaults are for PC COM4, Enhanced Mode, High Address.
 */
struct port_config GC_PORTS[MAX_GCNUM] = {
	{ 0x2A0, B9600 },
	{ 0x2A8, B9600 },
	{ 0x2B0, B9600 },
	{ 0x2B8, B9600 }
};

/*
 * Export Functions.
 */
int	gcload();
int	gcopen();
int	gcclose();
int	gcread();
int	gcwrite();
int	gcioctl();
int	gcunload();
int	gcpoll();

int	gccycle();
int	gcintr();
int	gcparam();
int	gcstart();

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON gccon ={
	DFCHR|DFPOL,			/* Flags */
	GCINT,				/* Major index */
	gcopen,				/* Open */
	gcclose,			/* Close */
	nulldev,			/* Block */
	gcread,				/* Read */
	gcwrite,			/* Write */
	gcioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	gcload,				/* Load */
	gcunload,			/* Unload */
	gcpoll				/* Poll */
};

/*
 * Local variables.
 */
static TTY *hstty;
static TTY *hslimtty;
static TIM hstim;

/*
 * Time constant table.
 * Indexed by ioctl baud rate.
 */
static
int timeconst[] = {
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	6,				/* EXTA */
	6				/* EXTB */
};

/*
 * Load Routine.
 */
static gcload()
{
	register TTY * tp;
	register int port;
	int i, b, s;

	if ((hstty = (TTY *)kalloc(GCNUM*sizeof(TTY))) == 0) {
		printf("gcload: can't allocate tty's\n");
		return;
	}
	kclear(hstty, GCNUM*sizeof(TTY));

	s = sphi();
	for (i = 0; i < GCNUM; i++) {
		port = GC_PORTS[i].addr;
		tp = hstty + i;

		outb( port+MCR, 0 );
		outb( port+IER, 0 );

		if ( inb( port+IER ) )
			break;

		tp->t_cs_sel  = cs_sel();
		tp->t_start   = gcstart;
		tp->t_param   = gcparam;
		tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
		tp->t_dispeed = tp->t_dospeed = GC_PORTS[i].speed;
		tp->t_ddp     = port;

		b = timeconst[ tp->t_sgttyb.sg_ospeed ];
		outb( port+LCR, LC_DLAB );
		outb( port+DLL, b );
		outb( port+DLH, b >> 8);
		outb( port+LCR, LC_CS8);

		hslimtty = tp;
	}
	setivec(GCINT, gcintr);
	spl(s);
}

static gcunload()
{
	clrivec(GCINT);
	kfree(hstty);
}

/*
 * Open Routine.
 */
gcopen( dev, mode )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];
	register int b;
	int s;

	/*
	 * Verify hardware exists.
	 */
	if ( (PORT == 0) || (inb(PORT+IER) & ~IE_TxI) ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Initialize if not already open.
	 */
	if ( ++tp->t_open == 1 ) {
		ttopen( tp );

		if ( dev & 0x80 ) {
			s = sphi();
			b = inb(PORT+MSR);
			tp->t_flags |= T_MODC + T_STOP;
			if ( b & MS_CTS )
				tp->t_flags &= ~T_STOP;
			if ( b & MS_DSR )
				tp->t_flags |=  T_CARR;
			spl( s );
		} else  {
			tp->t_flags &= ~T_MODC;
			tp->t_flags |=  T_CARR;
		}
		gccycle( tp );
	}
	ttsetgrp( tp, dev );
}

/*
 * Close Routine.
 */
gcclose( dev )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];

	/*
	 * Reset if last close.
	 */
	if ( tp->t_open == 1 ) {
		int state;

		ttclose( tp );
		/*
		 * ttclose() only emptied the output queue tp->t_oq;
		 * now wait 0.1 sec for the silo tp->rawout to empty
		 * and allow a delay for the UART on-chip xmit buffer to empty
		 *
		 * state 2: waiting for silo to empty
		 * state 1: stalling so UART can empty xmit buffer
		 * state 0: done!
		 */
		state = 2;
		while (state) {
			timeout(&hstim, 10, wakeup, (int)&hstim);
			sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
			if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
				state--;
		}
	}

	--tp->t_open;
}

/*
 * Read Routine.
 */
gcread( dev, iop )
dev_t dev;
register IO * iop;
{
	ttread( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Write Routine.
 */
gcwrite( dev, iop )
dev_t dev;
register IO * iop;
{
	ttwrite( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Ioctl Routine.
 */
gcioctl( dev, com, vec )
dev_t dev;
int com;
struct sgttyb * vec;
{
	ttioctl( &hstty[ dev & 15 ], com, vec );
}

/*
 * Polling Routine.
 */
gcpoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	return ttpoll( &hstty[ dev & 15 ], ev, msec );
}

/*
 * Cyclic routine - invoked every clock tick to perform raw input/output.
 *
 *	Notes:	Invoked 10 times per second.
 */
gccycle( tp )
register TTY * tp;
{
	register int resid;
	register int c;

	/*
	 * Process rawin buf.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}

	/*
	 * Calculate free output slot count.
	 */
	resid  = sizeof(tp->t_rawout.si_buf) - 1;
	resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	resid %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--resid >= 0) && ((c = ttout(tp)) >= 0) ) {

		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;

		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, waking processes waiting to output, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	if ( tp->t_open != 0 )
		timeout( &tp->t_rawtim, HZ/10, gccycle, tp );
}

/*
 * Interrupt driven Polling routine.
 */
gcintr()
{
	register TTY * tp = &hstty[0];
	register int b;

	do {
		if ( tp->t_open == 0 )
			continue;

		/*
		 * Check modem status if modem control is enabled.
		 */
		if ( tp->t_flags & T_MODC ) {

			b = inb( PORT+MSR );

			if ( b & (MS_DCTS|MS_DDSR) ) {

				if ( b & MS_DCTS ) {
					if ( b & MS_CTS )
						tp->t_flags &= ~T_STOP;
					else
						tp->t_flags |=  T_STOP;
				}
				if ( b & MS_DDSR ) {
					if ( b & MS_DSR )
						tp->t_flags |=  T_CARR;
					else {
						tp->t_flags &= ~T_CARR;
						tthup( tp );
					}
				}
			}
		}

		b = inb( PORT+LSR );

		if ( (b & LS_BREAK) && (tp->t_flags & T_CARR) )
			ttsignal( tp, SIGINT );

		/*
		 * Receive ready.
		 */
		if ( b & LS_RxRDY ) {

			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(PORT+DREG);

			if ( tp->t_flags & T_CARR ) {

				if ( ++(tp->t_rawin.si_ix) >=
						sizeof(tp->t_rawin.si_buf) )
					tp->t_rawin.si_ix = 0;
			}
		}

		/*
		 * Transmit ready and raw output data exists.
		 */
		if ( (b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
		  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

			outb(	PORT+DREG,
				tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

			if ( ++(tp->t_rawout.si_ox) >=
					sizeof(tp->t_rawout.si_buf) )
				tp->t_rawout.si_ox = 0;
		}

	} while ( ++tp <= hslimtty );
}

/*
 * Set hardware parameters.
 */
gcparam( tp )
register TTY * tp;
{
	register int b;
	int s;

	s = sphi();
	/*
	 * Assert required modem control lines (DTR, RTS).
	 */
	b = 0;
	if ( tp->t_sgttyb.sg_ospeed != B0 )
		b |=  MC_DTR | MC_RTS;
	outb( PORT+MCR, b );

	/*
	 * Program baud rate.
	 */
	if (b = timeconst[ tp->t_sgttyb.sg_ospeed ]) {
		outb( PORT+LCR, LC_DLAB );
		outb( PORT+DLL, b );
		outb( PORT+DLH, b >> 8 );
	}

	/*
	 * Program character size, parity.
	 */
	switch ( tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW) ) {
	case ODDP:		b = LC_CS7|LC_PARENB;		 break;
	case EVENP:		b = LC_CS7|LC_PARENB|LC_PAREVEN; break;
	default:		b = LC_CS8;			 break;
	}
	outb( PORT+LCR, b );

	/*
	 * Enable Transmit Buffer Empty Interrupts.
	 */
	outb( PORT+IER, IE_TxI );

	spl(s);
}

/*
 * Start Routine.
 */
gcstart( tp )
register TTY * tp;
{
	register int s;

	/*
	 * Transmit buffer is empty, and raw output buffer is not.
	 */
	s = sphi();
	if ( (inb( PORT+LSR ) & LS_TxRDY)
	  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

		/*
		 * Send next char from raw output buffer.
		 */
		outb( PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}
@
0707070064030106761004440000030000030000011777770507310672000005400000002745/newbits/kernel/USRSRC/i8086/drv/RCS/gr.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3; strict;
comment  @ * @;


1.3
date     91.06.20.14.49.36;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.31.06;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.22.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.3
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Graphics Display Driver for PC Color Card
 */

#include <sys/coherent.h>
#include <sys/sched.h>
#include <sys/types.h>
#include <sys/uproc.h>
#include <errno.h>
#include <sys/con.h>

int grread();
int grwrite();
int nonedev();
int nulldev();

/*
 * Driver Configuration.
 */
#define	MAJOR	30

CON
grcon = {
	DFCHR,				/* Flags			  */
	MAJOR,				/* Major Index			  */
	nulldev,			/* Open				  */
	nulldev,			/* Close			  */
	nonedev,			/* Block			  */
	grread,				/* Read				  */
	grwrite,			/* Write			  */
	nonedev,			/* Ioctl			  */
	nulldev,			/* Power fail			  */
	nulldev,			/* Timeout			  */
	nulldev,			/* Load				  */
	nulldev				/* Unload			  */
};
@


1.2
log
@new version provided y hal for v321
@
text
@d10 1
a10 2
#include <coherent.h>
#include <sys/timeout.h>
@


1.1
log
@Initial revision
@
text
@d12 3
a14 3
#include <sched.h>
#include <types.h>
#include <uproc.h>
d16 1
a16 1
#include <con.h>
@
0707070064030106711004440000030000030000011777770507310672100005600000113750/newbits/kernel/USRSRC/i8086/drv/RCS/gras.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.22.42;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
	.globl	grread_
	.globl	grwrite_
	.globl	mmgo_

////////
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal attributes
/		CX    - input count
/		BP    - references terminal information
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
////////

#ifdef	HERCULES
	VSEG	= 0xB000	/ Video Display Segment
	BANKSZ	= 8192		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 8		/ number of horizontal lines per char
	NCR2	= 4		/ number of horizontal lines per char / 2
	NCR4	= 2		/ number of horizontal lines per char / 4
	NHB	= 90		/ number of horizontal bytes per line
#else
#ifdef TECMAR
	VSEG	= 0xA000	/ Video Display Segment
	BANKSZ	= 32768		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 16		/ number of horizontal lines per char
	NCR2	= 8		/ number of horizontal lines per char / 2
	NCR4	= 4		/ number of horizontal lines per char / 4
	NHB	= 80		/ number of horizontal bytes per line
#else
	VSEG    = 0xB800	/ Video Display Segment
	BANKSZ	= 8192		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 8		/ number of horizontal lines per char
	NCR2	= 4		/ number of horizontal lines per char / 2
	NCR4	= 2		/ number of horizontal lines per char / 4
	NHB	= 80		/ number of horizontal bytes per line
#endif
#endif

	NRB	= NHB*NCR	/ number of bytes per character row
	NRB2	= NHB*NCR2	/ number of bytes per character row / 2
	NRB4	= NHB*NCR4	/ number of bytes per character row / 4

	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	CSR	= 0x3D9		/ Color Select Register
	MSR	= 0x3D8		/ Mode Select Register
	XMSR	= 0x3DA		/ Extended Mode Select Register


////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_SEEK	= 4
	IO_BASE	= 8

	IOSYS	= 0

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_FLIP		= 20
MM_MASK		= 22
MM_ULINE	= 24
MM_CURSE	= 26
MM_VIS		= 28		/ set to -1 to make cursor visible
MM_NCOL		= 30
MM_WRAP		= 31

	.prvd
mmdata:	.word	mminit, 0x03D4, VSEG
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, LROW-1, LROW, 0, 0, 0, LROW-1
	.word	0, -1, 0, 0xff
	.word	0
	.byte	80
	.byte	1

	.shri
#ifdef	HERCULES
crtdata:.byte	 54,  45,  45,   8,  91,   1,  86,  88
	.byte	  2,   3,  32,   0,   0,   0,   0,   0
#else
#ifdef TECMAR
crtdata:.byte	 56,  40,  43,   8, 127,   6, 100, 112
	.byte	  3,   1,  32,   0,   0,   0,   0,   0
#else
crtdata:.byte	 56,  40,  43,   8, 127,   6, 100, 112
	.byte	  2,   1,  32,   0,   0,   0,   0,   0
#endif
#endif
	.shri

////////
/
/ mmgo( iop )		- Entry point for text stream output
/ IO *iop;
/
////////

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc
	cmp	IO_SEG(bx), $IOSYS
	je	0f
	mov	bx, uds_
	mov	ds, bx
0:	mov	bp, $mmdata
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	mov	ax, MM_CURSE(bp)
	and	ax, MM_VIS(bp)
#ifdef TECMAR
	xor	es:[NHB*6](POS), ax
	xor	es:[NHB*6]+BANKSZ(POS), ax
	xor	es:[NHB*7](POS), ax
	xor	es:[NHB*7]+BANKSZ(POS), ax
#else
	xor	es:[NHB*3](POS), ax	/ turn cursor off
	xor	es:[NHB*3]+BANKSZ(POS), ax
#endif
	sub	bx, bx
	ijmp	MM_FUNC(bp)

exit:	movb	bl, ROW			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	bl, $1
0:	add	POS, bx
	mov	ax, MM_CURSE(bp)
	and	ax, MM_VIS(bp)
#ifdef TECMAR
	xor	es:[NHB*6](POS), ax	/ turn cursor on
	xor	es:[NHB*6]+BANKSZ(POS), ax
	xor	es:[NHB*7](POS), ax
	xor	es:[NHB*7]+BANKSZ(POS), ax
#else
	xor	es:[NHB*3](POS), ax	/ turn cursor on
	xor	es:[NHB*3]+BANKSZ(POS), ax
#endif
	pop	bx
	pop	es
	pop	ds
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, $MSR		/ enable video display
	movb	al, $0x1A
	outb	dx, al
	mov	mmvcnt_, $480		/ 480 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx			/ Return the residual count.
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $'c		/ schedule keyboard initialization
	mov	dx, $MSR		/ disable video display
	movb	al, $0x12
	outb	dx, al

	push	cx			/ program registers, last to first
	mov	bx, $15
	mov	dx, MM_PORT(bp)
0:	movb	al, bl
	outb	dx, al
	inc	dx
	movb	al, cs:crtdata(bx)
	outb	dx, al
	dec	dx
	dec	bx
	jge	0b
	pop	cx

	mov	dx, $CSR
	movb	al, $0x0F
	outb	dx, al

	mov	dx, $XMSR
#ifdef TECMAR
	movb	al, $31
#else
	movb	al, $0
#endif
	outb	dx, al

/	mov	dx, $XMSR
0:	inb	al, dx		/ wait for vertical retrace
	andb	al, $8
	je	0b

	mov	dx, $MSR
	movb	al, $0x1A	/ video display on
	outb	dx, al

	mov	MM_VIS(bp), $-1
	mov	MM_MASK(bp), $0xAAAA
	mov	MM_FLIP(bp), $0
	mov	MM_ULINE(bp), $0
	mov	MM_CURSE(bp), $0x00ff
	movb	MM_WRAP(bp), $1
	movb	MM_NCOL(bp), $80
	subb	COL, COL
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mmspec - pass special characters on to keyboard routine(s).
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/	Returns to mmwrite() to allow flow control on each output line.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jle	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	push	si
	push	di
	push	cx
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	pop	di
	push	di
	mov	cx, $NRB4
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	jmp	ewait

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, ROW			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	bl, $1
0:	add	POS, bx
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait0
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

ewait0:	call	exit
	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	cmpb	MM_NCOL(bp), $40
	jne	putc8


putc16:	push	ds
	push	si
	subb	ah, ah
	shlb	al, $1
	shl	ax, $1
	shl	ax, $1
	shl	ax, $1
	add	ax, $fontw_
	mov	si, ax
	mov	ax, cs
	mov	ds, ax
	mov	bx, $BANKSZ-2

	lodsw				/ row 0
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
	push	di			/ save position for next char
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif
	lodsw				/ row 1
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 2
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif

	lodsw				/ row 3
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 4
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif

	lodsw				/ row 5
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 6
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif
	lodsw				/ row 7
	or	ax, MM_ULINE(bp)
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax


	pop	di			/ restore position for next char
	pop	si
	pop	ds

	sub	bx, bx
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jge	0f
	jcxz	ewait1
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

ewait1:	jmp	ewait

putc8:	push	ds
	push	si
	subb	ah, ah
	shlb	al, $1
	shl	ax, $1
	shl	ax, $1
	add	ax, $0xFA6E
	mov	si, ax
	mov	ax, $0xF000
	mov	ds, ax
	mov	bx, $BANKSZ-1

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 0
	push	di			/ save position for next char
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah		/ row 1
	movb	es:80(bx,di), ah
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 1
	add	di, $79
#endif

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 2
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah
	movb	es:80(bx,di), ah	/ row 3
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 3
	add	di, $79
#endif

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 4
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah		/ row 5
	movb	es:80(bx,di), ah
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 5
	add	di, $79
#endif

	lodsw
	orb	ah, MM_ULINE(bp)
	xor	ax, MM_FLIP(bp)
	stosb				/ row 6
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah
	movb	es:80(bx,di), ah
#else
	movb	es:(bx,di), ah		/ row 7
#endif

	pop	di			/ restore position for next char
	pop	si
	pop	ds

	sub	bx, bx
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jge	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	decb	COL
	jge	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
0:	jmp	repos

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $';
	je	csi_n2
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

0:	cmpb	al, $'h
	je	mm_cgh
	cmpb	al, $'l
	je	mm_cgl
	jmp	eval

////////
/
/ Csi_q state - entered after input sequence ESC [ ?
/	
////////

0:	call	exit
csi_q:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_q

0:	cmpb	al, $'h
	je	mm_cqh
	cmpb	al, $'l
	je	mm_cql
	jmp	eval

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jg	0f
	subb	COL, COL		/ can't step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process 'ESC [ > N1 h' escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process 'ESC [ > N1 l' escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	decb	COL
	jge	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	mov	bx, $BANKSZ
	push	cx
	push	si
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl

	mov	si, MM_MASK(bp)
	cmpb	MM_NCOL(bp), $80
	jne	0f
	mov	si, $-1
	inc	cx
	shr	cx, $1

0:	mov	ax, MM_FLIP(bp)
	and	ax, si
#ifdef TECMAR
	stosw				/ row 0
	mov	es:[NHB*0]-2(di,bx), ax
	mov	es:[NHB*1]-2(di), ax	/ row 1
	mov	es:[NHB*1]-2(di,bx), ax
	mov	es:[NHB*2]-2(di), ax	/ row 2
	mov	es:[NHB*2]-2(di,bx), ax
	mov	es:[NHB*3]-2(di), ax	/ row 3
	mov	es:[NHB*3]-2(di,bx), ax
	mov	es:[NHB*4]-2(di), ax	/ row 4
	mov	es:[NHB*4]-2(di,bx), ax
	mov	es:[NHB*5]-2(di), ax	/ row 5
	mov	es:[NHB*5]-2(di,bx), ax
	mov	es:[NHB*6]-2(di), ax	/ row 6
	mov	es:[NHB*6]-2(di,bx), ax
	or	ax, MM_ULINE(bp)
	and	ax, si
	mov	es:[NHB*7]-2(di), ax	/ row 7
	mov	es:[NHB*7]-2(di,bx), ax
#else
	stosw				/ row 0
	mov	es:[NHB*0]-2(di,bx), ax	/ row 1
	mov	es:[NHB*1]-2(di), ax	/ row 2
	mov	es:[NHB*1]-2(di,bx), ax	/ row 3
	mov	es:[NHB*2]-2(di), ax	/ row 4
	mov	es:[NHB*2]-2(di,bx), ax	/ row 5
	mov	es:[NHB*3]-2(di), ax	/ row 6
	or	ax, MM_ULINE(bp)
	and	ax, si
	mov	es:[NHB*3]-2(di,bx), ax	/ row 7
#endif
	loop	0b
	sub	bx, bx
	pop	si
	pop	cx
	cmpb	COL, MM_NCOL(bp)
	jl	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jle	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	repos

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cqh - process 'ESC [ ? N1 h' escape sequence
/
/	Recognized sequences:	ESC [ ? 7 h	-- Set wraparound.
/
////////

mm_cqh:
	cmpb	MM_N1(bp), $7		/ Wraparound.
	jne	0f
	movb	MM_WRAP(bp), $1
0:	jmp	eval

////////
/
/ mm_cql - process 'ESC [ ? N1 l' escape sequence
/
/	Recognized sequences:	ESC [ ? 7 l	-- Reset wraparound.
/
////////

mm_cql:
	cmpb	MM_N1(bp), $7		/ No wraparound.
	jne	0f
	movb	MM_WRAP(bp), $0
0:	jmp	eval

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter (mm_n1) specifies the vertical position (MM_ROW(bp)).
/	The second parameter (mm_n2) specifies the horizontal position (MM_COL(bp)).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	si
	push	di
	push	cx
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	di, cs:rowtab(bx)
	push	di
	mov	cx, $NRB4
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	subb	COL, COL
0:	pop	cx
	pop	si
	pop	ds
	jmp	repos

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2

////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

////////
/
/ mm_e2 - erase from POS for BL rows (minimum 1 row)
/
////////

mm_e2:	push	cx
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
0:	mov	cx, $NRB4
	rep
	stosw
	add	di, $BANKSZ-NRB2
	mov	cx, $NRB4
	rep
	stosw
	sub	di, $BANKSZ
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

////////
/
/ mm_e1 - erase from row BL to current cursor position.
/
////////

mm_e1:	push	dx
	push	cx
	push	di
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	di
	push	cx
	rep
	stosw
	pop	cx
	pop	di
	add	di, $BANKSZ
	rep
	stosw
0:	pop	cx
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	sub	cx, di
	jle	0f

	mov	dx, di
	mov	bx, cx
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 6
	stosb
#ifdef TECMAR
	add	dx, $80
	mov	di, dx
	mov	cx, bx
	rep			/ erase row 7
	stosb
	add	dx, $BANKSZ-560
#else
	add	dx, $BANKSZ-240
#endif
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 6
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 7
	stosb
1:	sub	bx, bx
	pop	cx
	pop	dx
	jmp	repos

////////
/
/ mm_e0 - erase from current cursor position to row BL inclusive.
/
////////

mm_e0:	push	dx
	push	cx
	push	di
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab+2(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	di
	push	cx
	rep
	stosw
	pop	cx
	pop	di
	add	di, $BANKSZ
	rep
	stosw
0:	pop	di
	sub	cx, cx
	movb	cl, MM_NCOL(bp)
	subb	cl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	cl, $1
0:	mov	dx, di
	mov	bx, cx
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 6
	stosb
#ifdef TECMAR
	add	dx, $80
	mov	di, dx
	mov	cx, bx
	rep			/ erase row 7
	stosb
	add	dx, $BANKSZ-560
#else
	add	dx, $BANKSZ-240
#endif
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 6
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 7
	stosb
1:	sub	bx, bx
	pop	cx
	pop	dx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, cs:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, cs:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, cs:rowtab(bx)
	jle	0f
	shr	cx, $1
	push	si
	push	di
	push	cx
	std
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	di, cs:rowtab(bx)
	push	di
	mov	cx, $NRB4
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	cld
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	subb	COL, COL
0:	pop	cx
	pop	si
	pop	ds
	jmp	repos

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_VIS(bp), $-1
	jmp	eval

0:	mov	MM_VIS(bp), $0
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					7 - reverse video
/
////////

mm_sgr:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	mov	MM_MASK(bp), $0xAAAA
	mov	MM_FLIP(bp), $0
	mov	MM_ULINE(bp), $0
	jmp	1f
0:	cmpb	al, $1		/ bold
	jne	0f
	mov	MM_MASK(bp), $-1
	jmp	1f
0:	cmpb	al, $4		/ underline
	jne	0f
	mov	MM_ULINE(bp), $0xFFFF
	jmp	1f
0:	cmpb	al, $7		/ reverse video
	jne	0f
	mov	MM_FLIP(bp), $-1
	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_so - stand out - enter 40 column mode
/
////////

mm_so:	cmpb	MM_NCOL(bp), $80
	jne	0f
	movb	MM_NCOL(bp), $40
	incb	COL
	shrb	COL, $1
0:	mov	MM_CURSE(bp), $0xffff
	jmp	repos

////////
/
/ mm_si - stand in - enter 80 column mode
/
////////

mm_si:	cmpb	MM_NCOL(bp), $40
	jne	0f
	movb	MM_NCOL(bp), $80
	shlb	COL, $1
0:	mov	MM_CURSE(bp), $0x00ff
	jmp	repos

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	mmbell	/* EOT  ENQ  ACK  BEL  */
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/* BS   HT   LF   VT  */
	.word	eval,	mm_cr,	mm_so,	mm_si	/* FF   CR   SO   SI  */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3 */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	mm_esc	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/*   ! " # \040 - \043 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* $ % & ' \044 - \047 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ( ) * + \050 - \053 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* , - . / \054 - \057 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 0 1 2 3 \060 - \063 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 4 5 6 7 \064 - \067 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 8 9 : ; \070 - \073 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* < = > ? \074 - \077 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* @@ A B C \100 - \103 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* D E F G \104 - \107 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* H I J K \110 - \113 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* L M N O \114 - \117 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* P Q R S \120 - \123 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* T U V W \124 - \127 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* X Y Z [ \130 - \133 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* \ ] ^ _ \134 - \137 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ` a b c \140 - \143 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* d e f g \144 - \147 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* h i j k \150 - \153 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* l m n o \154 - \157 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* p q r s \160 - \163 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* t u v w \164 - \167 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* x y z { \170 - \173 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* | } ~ ? \174 - \177 */

////////
/
/ esctab - table of functions indexed by escape characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/* NUL  SOH  STX  ETX  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* EOT  ENQ  ACK  BEL  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* BS   HT   LF   VT  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FF   CR   SO   SI  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DLE  DC1  DC2  DC3 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DC4  NAK  SYN  ETB  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* CAN  EM   SUB  ESC  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & ' \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	mm_new	/* 4 5 6 7 \064 - \067 */
	.word	mm_old,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	mmspec,	mmspec,	eval	/* < = > ? \074 - \077 */
	.word	eval,	eval,	eval,	eval	/* @@ A B C \100 - \103 */
	.word	mm_ind,	mm_cnl,	eval,	eval	/* D E F G \104 - \107 */
	.word	eval,	eval,	eval,	eval	/* H I J K \110 - \113 */
	.word	eval,	mm_ri,	eval,	eval	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	eval	/* P Q R S \120 - \123 */
	.word	eval,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	eval,	csi_n1	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_dmi,	eval,	mm_emi,	mminit	/* ` a b c \140 - \143 */
	.word	eval,	eval,	eval,	eval	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	eval,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	eval,	eval	/* p q r s \160 - \163 */
	.word	mmspec,	mmspec,	eval,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	eval	/* EOT  ENQ  ACK  BEL  */
	.word	eval,	eval,	eval,	eval	/* BS   HT   LF   VT  */
	.word	eval,	eval,	eval,	eval	/* FF   CR   SO   SI  */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3 */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	eval	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & ' \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	eval	/* 4 5 6 7 \064 - \067 */
	.word	eval,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	eval,	csi_gt,	eval	/* < = > ? \074 - \077 */
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/* @@ A B C \100 - \103 */
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/* D E F G \104 - \107 */
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/* H I J K \110 - \113 */
	.word	mm_il,	mm_dl,	eval,	mm_ea	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	mm_ind	/* P Q R S \120 - \123 */
	.word	mm_ri,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	mm_cbt,	eval	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_hpa,	mm_hpr,	eval,	eval	/* ` a b c \140 - \143 */
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	mm_sgr,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	mm_ssr,	eval	/* p q r s \160 - \163 */
	.word	eval,	eval,	mm_scr,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ rowtab - array of offsets to each row
/
////////

rowtab:	.word	 0*NRB2,	 1*NRB2,	 2*NRB2,	 3*NRB2
	.word	 4*NRB2,	 5*NRB2,	 6*NRB2,	 7*NRB2
	.word	 8*NRB2,	 9*NRB2,	10*NRB2,	11*NRB2
	.word	12*NRB2,	13*NRB2,	14*NRB2,	15*NRB2
	.word	16*NRB2,	17*NRB2,	18*NRB2,	19*NRB2
	.word	20*NRB2,	21*NRB2,	22*NRB2,	23*NRB2
	.word	24*NRB2,	25*NRB2,	26*NRB2,	27*NRB2
	.word	28*NRB2,	29*NRB2,	30*NRB2,	31*NRB2
	.word	32*NRB2,	33*NRB2,	34*NRB2,	35*NRB2
	.word	36*NRB2,	37*NRB2,	38*NRB2,	39*NRB2
	.word	40*NRB2,	41*NRB2,	42*NRB2,	43*NRB2
	.word	44*NRB2,	45*NRB2,	46*NRB2,	47*NRB2
	.word	48*NRB2,	49*NRB2,	50*NRB2,	51*NRB2

////////
/
/ grread( dev, iop ) - read graphics display memory
/
////////

grread_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	mov	bp, 10(bp)
	push	ds
	push	es
	cmp	IO_SEG(bp), $IOSYS
	je	0f
	mov	ax, uds_
	mov	es, ax
0:	mov	di, IO_BASE(bp)
	mov	ax, $VSEG
	mov	ds, ax

#ifndef TECMAR
	mov	ax, IO_SEEK(bp)
	add	ax, IO_IOC(bp)
	cmp	ax, $BANKSZ*2
	ja	done
#endif

	mov	ax, IO_SEEK(bp)
	sub	dx, dx
	mov	cx, $NHB
	div	cx
	mov	si, dx
	mov	bx, ax
	shr	ax, $1
	mul	cx
	mov	dx, si
	add	si, ax
	testb	bl, $1
	jne	read2

read1:	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	push	si
	rep
	movsb
	pop	si
read2:	add	si, $BANKSZ
	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	rep
	movsb
	sub	si, $BANKSZ
	sub	dx, dx
	jmp	read1

done:	pop	es
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ grwrite( dev, iop ) - write graphics display memory
/
////////

grwrite_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	mov	bp, 10(bp)
	push	ds
	push	es
	cmp	IO_SEG(bp), $IOSYS
	je	0f
	mov	ax, uds_
	mov	ds, ax
0:	mov	si, IO_BASE(bp)
	mov	ax, $VSEG
	mov	es, ax

#ifndef TECMAR
	mov	ax, IO_SEEK(bp)
	add	ax, IO_IOC(bp)
	cmp	ax, $BANKSZ*2
	ja	done
#endif

	mov	ax, IO_SEEK(bp)
	sub	dx, dx
	mov	cx, $NHB
	div	cx
	mov	di, dx
	mov	bx, ax
	shr	ax, $1
	mul	cx
	mov	dx, di
	add	di, ax
	testb	bl, $1
	jne	page2

page1:	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	push	di
	rep
	movsb
	pop	di
page2:	add	di, $BANKSZ
	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	rep
	movsb
	sub	di, $BANKSZ
	sub	dx, dx
	jmp	page1

////////
/
/ mm_voff()	-- Disable video display
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, $MSR
	movb	al, $0x12
	outb	dx, al
	ret

////////
/
/ mm_von()	-- Enable video display
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, $MSR		/ enable video display
	movb	al, $0x1A
	outb	dx, al
	mov	ss:mmvcnt_, $480	/ 480 seconds before video disabled
	ret
@
0707070064030106701004440000030000030000011777770507310673100006200000035253/newbits/kernel/USRSRC/i8086/drv/RCS/hs.c.debug,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.23.00;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 *
 *	$Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 -lgl) */
/*
 * Polled Serial Port Device Driver.
 * - supports version 7 compatible ioctl
 */

#include "coherent.h"
#include "ins8250.h"
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/proc.h>
#include <sys/tty.h>		/* indirectly includes sgtty.h */
#include <sys/con.h>
#include <errno.h>
#include <sys/timeout.h>	/* TIM */
#include <sched.h>		/* CVTTOUT, IVTTOUT, SVTTOUT */
#include <poll_clk.h>

/*
 * Definitions.
 *
 * HSBAUD is the highest baud rate supported by this driver
 * HS_HZ is the polling rate, i.e. the number of times per second
 *   at which all open ports are checked for input, output, and
 *   line status changes
 * MAX_HSNUM is the maximum number of devices that can be polled
 *   using this driver and can be revised up or down
 * PORT is a convenience macro for the base address of a port
 * port_config is the structure of the initial configuration for each
 *   polled port;  note that "speed" is NOT the actual baud rate, but
 *   the value of the symbol for that baud rate as defined in
 *   /usr/include/sgtty.h
 *
 * "PORT" is a macro yielding the 8250 base address, given the "tp" pointer.
 * "PORT_NUM" is a macro yielding the port index (0..MAX_HSNUM-1) given "tp".
 */
#define	HSBAUD	9600
#define	HS_HZ	(HSBAUD/6)
#define MAX_HSNUM	8
#define	PORT		(HS_PORTS[(int)(tp->t_ddp)].addr)
#define	PORT_NUM	((int)(tp->t_ddp))
#define MSR_DELTAS	(MS_DCTS | MS_DDSR | MS_TERI | MS_DRLSD)
struct port_config {
	int	addr;	/* base address of the 8250-family UART */
	int	speed;	/* B0..B19200 */
};

/*
 * Export Variables - these can be patched without recompiling and linking
 *
 * HSNUM is the actual number of polled serial ports, and should be
 *   less than or equal to MAX_HSNUM
 * HS_PORTS is an array of address/speed pairs, one for each port
 */
int	HSNUM = 4;
struct port_config HS_PORTS[MAX_HSNUM] = {
	{ 0x3F8, B9600 },
	{ 0x2F8, B9600 },
	{ 0x3E8, B9600 },
	{ 0x2E8, B9600 }
};

/*
 * 8250's MSR delta bits are cleared each time the MSR is read.
 * But different parts of the driver look for deltas of different bits.
 * Array msr[] saves delta bits until they are needed.
 */
static char msr[MAX_HSNUM];
/*
 * Export Functions.
 */
int	hsload();
int	hsopen();
int	hsclose();
int	hsread();
int	hswrite();
int	hsioctl();
int	hsunload();
int	hspoll();

int	hscycle();
int	hsintr();
int	hsparam();
int	hsstart();
int	hsclk();
int	set_poll_rate();

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON hscon ={
	DFCHR|DFPOL,			/* Flags */
	7,				/* Major index */
	hsopen,				/* Open */
	hsclose,			/* Close */
	nulldev,			/* Block */
	hsread,				/* Read */
	hswrite,			/* Write */
	hsioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	hsload,				/* Load */
	hsunload,			/* Unload */
	hspoll				/* Poll */
};

/*
 * Local variables.
 */
static TTY *hstty;
static TTY *hslimtty;
static TIM hstim;
static int poll_divisor;	/* used in hsclk() and set_poll_rate() */

/*
 * Time constant table.
 * Indexed by ioctl baud rate.
 */
static
int timeconst[] = {
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	58,				/* 2000 */
	48,				/* 2400 */
	32,				/* 3600 */
	24,				/* 4800 */
	16,				/* 7200 */
	12,				/* 9600 */
	6,				/* 19200 */
	6,				/* EXTA */
	6				/* EXTB */
};

/*
 * poll_hz[] is tied to timeconst[] - it gives the minimum polling
 *	rate for the corresponding port speed; it must be a multiple
 *	of 100 (system clock Hz) and >= baud/6
 */
int poll_hz[] ={
	0,				/* 0 */
	1*HZ,				/* 50 */
	1*HZ,				/* 75 */
	1*HZ,				/* 110 */
	1*HZ,				/* 134.5 */
	1*HZ,				/* 150 */
	1*HZ,				/* 200 */
	1*HZ,				/* 300 */
	1*HZ,				/* 600 */
	2*HZ,				/* 1200 */
	3*HZ,				/* 1800 */
	4*HZ,				/* 2000 */
	4*HZ,				/* 2400 */
	6*HZ,				/* 3600 */
	8*HZ,				/* 4800 */
	12*HZ,				/* 7200 */
	16*HZ,				/* 9600 */
	0,				/* 19200 */
	0,				/* EXTA */
	0				/* EXTB */
};

/*
 * Load Routine.
 */
static hsload()
{
	register TTY * tp;
	register int port;
	int i, b;

	if ((hstty = (TTY *)kalloc(HSNUM*sizeof(TTY))) == 0) {
		printf("hsload: can't allocate tty's\n");
		return;
	}
	kclear(hstty, HSNUM*sizeof(TTY));

	for (i = 0; i < HSNUM; i++) {
		port = HS_PORTS[i].addr;
		tp = hstty + i;

		outb( port+MCR, 0 );
		outb( port+IER, 0 );

		if ( inb( port+IER ) )
			break;

		tp->t_cs_sel  = cs_sel();
		tp->t_start   = hsstart;
		tp->t_param   = hsparam;
		tp->t_sgttyb.sg_ospeed = tp->t_sgttyb.sg_ispeed = 
		tp->t_dispeed = tp->t_dospeed = HS_PORTS[i].speed;
		tp->t_ddp     = i;

		b = timeconst[ tp->t_sgttyb.sg_ospeed ];
		outb( port+LCR, LC_DLAB );
		outb( port+DLL, b );
		outb( port+DLH, b >> 8);
		outb( port+LCR, LC_CS8);

		hslimtty = tp;
	}
}

static hsunload()
{
	if (hstty != (TTY *)0)
		kfree(hstty);
}

/*
 * Open Routine.
 */
hsopen( dev, mode )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];
	int port = PORT;
	int s;
	char msr_ch;
printf("hsopen #%d: enter, count=%d\n", PORT_NUM, tp->t_open);
	/*
	 * Verify hardware exists.
	 */
	if ( (port == 0) || (inb(port+IER) & ~IE_TxI) ) {
		u.u_error = ENXIO;
		return;
	}
	
	/*
	 * Don't allow open if flagged for exclusive use and not super-user.
	 */
	if ((tp->t_flags & T_EXCL) && !super()) {
		u.u_error = ENODEV;
		return;
	}

	/*
	 * Don't open if modem is settling from previous close.
	 */
	if (drvl[major(dev)].d_time != 0) {	/* Modem settling */
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Can't open if another driver is using polling
	 */
	if (poll_owner & ~ POLL_HS) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Initialize if not already open.
	 */
	if ( tp->t_open++ == 0 ) {
		hscycle( tp );
		/*
		 * ttopen() will call hsparam()
		 * hsparam() asserts DTR and RTS and sets polling rate
		 */
		ttopen( tp );

		if (dev & 0x80) { /* if modem control... */
			s = sphi();
			tp->t_flags |= T_MODC + T_STOP + T_HOPEN;
			/*
			 * Sleep while waiting for carrier.
			 */
			while(1) {
				msr_ch = inb(port + MSR);
				msr[PORT_NUM] |= msr_ch & MSR_DELTAS; 
				if (msr_ch & MS_RLSD)
					break;
	   	  		sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
					SVTTOUT);	/* wait for carrier */
		 		if (SELF->p_ssig && nondsig()) {  /* signal? */
					outb(port+MCR, 0);  /* kill RTS/DTR */
					u.u_error = EINTR;
					spl(s);
					tp->t_open = 0;
					return;
				}
			}
			tp->t_flags &= ~T_HOPEN; /* no longer hanging in open */
			msr_ch = inb(port + MSR);
			msr[PORT_NUM] |= msr_ch & MSR_DELTAS; 
			if (msr_ch & MS_CTS)
				tp->t_flags &= ~T_STOP;
			spl( s );
		} else  {
			tp->t_flags &= ~T_MODC;
			tp->t_flags |=  T_CARR;
		}
	}
	ttsetgrp( tp, dev );
printf("hsopen #%d: leave, count=%d\n", PORT_NUM, tp->t_open);
}

/*
 * Close Routine.
 */
hsclose( dev )
dev_t dev;
{
	register TTY * tp = &hstty[ dev & 15 ];
printf("hsclose #%d: enter, count=%d\n", PORT_NUM, tp->t_open);
	/*
	 * Reset if last close.
	 */
	if ( tp->t_open == 1 ) {
		int state;
		int holdflags = tp->t_flags;	/* save flags */
		int port = PORT;

		ttclose( tp );			/* clears flags */

		if (holdflags & T_HOPEN) {  /* if waiting for RLSD... */
			/*
			 * Flags for first open
			 * (clear T_HPCL)
			 */
			tp->t_flags = T_MODC | T_HOPEN;
		}

		/*
		 * If hupcls
		 */
		if (holdflags & T_HPCL) {
			int maj;
			/*
			 * Hangup port
			 */
			outb(port+MCR, 0);
			/*
			 * Hold dtr low for timeout
			 */
			maj = major(dev);
			drvl[maj].d_time = 1;
			sleep((char *)&drvl[maj].d_time, CVTTOUT, IVTTOUT, SVTTOUT);
			drvl[maj].d_time = 0;
		}
		
		/*
		 * ttclose() only emptied the output queue tp->t_oq;
		 * now wait 0.1 sec for the silo tp->rawout to empty
		 * and allow a delay for the UART on-chip xmit buffer to empty
		 *
		 * state 2: waiting for silo to empty
		 * state 1: stalling so UART can empty xmit buffer
		 * state 0: done!
		 */
		state = 2;
		while (state) {
			timeout(&hstim, 10, wakeup, (int)&hstim);
			sleep((char *)&hstim, CVTTOUT, IVTTOUT, SVTTOUT);
			if (tp->t_rawout.si_ix == tp->t_rawout.si_ox  && state)
				state--;
		}
	}

	--tp->t_open;
	set_poll_rate();
printf("hsclose #%d: leave, count=%d\n", PORT_NUM, tp->t_open);
}

/*
 * Read Routine.
 */
hsread( dev, iop )
dev_t dev;
register IO * iop;
{
	ttread( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Write Routine.
 */
hswrite( dev, iop )
dev_t dev;
register IO * iop;
{
	ttwrite( &hstty[ dev & 15 ], iop, 0 );
}

/*
 * Ioctl Routine.
 */
hsioctl( dev, com, vec )
dev_t dev;
int com;
struct sgttyb * vec;
{
	ttioctl( &hstty[ dev & 15 ], com, vec );
}

/*
 * Polling Routine.
 */
hspoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	return ttpoll( &hstty[ dev & 15 ], ev, msec );
}

/*
 * Cyclic routine - invoked every clock tick to perform raw input/output.
 *
 *	Notes:	Invoked 10 times per second.
 */
hscycle( tp )
register TTY * tp;
{
	register int resid;
	register int c;
	int msr_ch;

	/*
	 * Check modem status every clock tick.
	 */
	if ( tp->t_flags & T_MODC ) {
		/*
		 * Get status
		 */
		msr_ch = inb(PORT + MSR);
		msr[PORT_NUM] |= msr_ch & MSR_DELTAS; 

		/*
		 * Carrier changed.
		 */
		if ( msr[PORT_NUM] & MS_DRLSD ) {
			if (msr_ch & MS_RLSD)
				tp->t_flags |= T_CARR;  /* carrier on */
			else
				tp->t_flags &= ~T_CARR; /* no carrier */

			msr[PORT_NUM] &= ~MS_DRLSD;
			/*
			 * wakeup open
			 */
			if ( tp->t_open == 0 ) {
				wakeup((char *)(&tp->t_open));
			}

			/*
			 * carrier off?
			 */
			else if ( (msr_ch & MS_RLSD) == 0 ) {
				/*
				 * clear carrier flag; send hangup signal
				 */
				tp->t_rawin.si_ox = tp->t_rawin.si_ix;
				tthup( tp );
			}
		}
	}

	/*
	 * Process rawin buf.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		ttin( tp, tp->t_rawin.si_buf[ tp->t_rawin.si_ox ] );

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;
	}

	/*
	 * Calculate free output slot count.
	 */
	resid  = sizeof(tp->t_rawout.si_buf) - 1;
	resid += tp->t_rawout.si_ox - tp->t_rawout.si_ix;
	resid %= sizeof(tp->t_rawout.si_buf);

	/*
	 * Fill raw output buffer.
	 */
	while ( (--resid >= 0) && ((c = ttout(tp)) >= 0) ) {

		tp->t_rawout.si_buf[ tp->t_rawout.si_ix ] = c;

		if ( tp->t_rawout.si_ix >= sizeof(tp->t_rawout.si_buf) - 1 )
			tp->t_rawout.si_ix = 0;
		else
			tp->t_rawout.si_ix++;
	}

	/*
	 * (Re)start output, waking processes waiting to output, etc.
	 */
	ttstart( tp );

	/*
	 * Schedule next cycle.
	 */
	if ( tp->t_open != 0 )
		timeout( &tp->t_rawtim, HZ/10, hscycle, tp );
}

/*
 * Clock Interrupt driven Polling routine.
 */
hsintr()
{
	register TTY * tp = &hstty[0];
	register int b;
	char msr_ch;

	do {
		int port = PORT, port_num = PORT_NUM;	/* for speed */

		if ( tp->t_open == 0 )
			continue;

		/*
		 * Check modem status if modem control is enabled.
		 */
		if ( tp->t_flags & T_MODC ) {

			msr_ch = inb(port + MSR);
			msr[port_num] |= msr_ch & MSR_DELTAS; 

			if ( msr[port_num] & MS_DCTS ) {
				msr[port_num] &= ~MS_DCTS;
				if ( msr_ch & MS_CTS )
					tp->t_flags &= ~T_STOP;
				else
					tp->t_flags |=  T_STOP;
			}
		}

		b = inb( port+LSR );

		if ( (b & LS_BREAK) && (tp->t_flags & T_CARR) )
			ttsignal( tp, SIGINT );

		/*
		 * Receive ready.
		 */
		if ( b & LS_RxRDY ) {

			tp->t_rawin.si_buf[tp->t_rawin.si_ix] = inb(port+DREG);

			if ( tp->t_flags & T_CARR ) {

				if ( ++(tp->t_rawin.si_ix) >=
						sizeof(tp->t_rawin.si_buf) )
					tp->t_rawin.si_ix = 0;
			}
		}

		/*
		 * Transmit ready and raw output data exists.
		 */
		if ( (b & LS_TxRDY) && ((tp->t_flags & T_STOP) == 0)
		  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

			outb(port+DREG,
				tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

			if ( ++(tp->t_rawout.si_ox) >=
					sizeof(tp->t_rawout.si_buf) )
				tp->t_rawout.si_ox = 0;
		}

	} while ( ++tp <= hslimtty );
}

/*
 * Set hardware parameters.
 */
hsparam( tp )
register TTY * tp;
{
	register int b;
	int s;

	s = sphi();
	/*
	 * Assert required modem control lines (DTR, RTS).
	 */
	b = 0;
	if ( tp->t_sgttyb.sg_ospeed != B0 )
		b |=  MC_DTR | MC_RTS;
	outb( PORT+MCR, b );

	/*
	 * Program baud rate.
	 */
	if (b = timeconst[ tp->t_sgttyb.sg_ospeed ]) {
		outb( PORT+LCR, LC_DLAB );
		outb( PORT+DLL, b );
		outb( PORT+DLH, b >> 8 );
	}

	/*
	 * Program character size, parity.
	 */
	switch ( tp->t_sgttyb.sg_flags & (EVENP|ODDP|RAW) ) {
	case ODDP:		b = LC_CS7|LC_PARENB;		 break;
	case EVENP:		b = LC_CS7|LC_PARENB|LC_PAREVEN; break;
	default:		b = LC_CS8;			 break;
	}
	outb( PORT+LCR, b );

	/*
	 * Enable Transmit Buffer Empty Interrupts.
	 */
	outb( PORT+IER, IE_TxI );

	spl(s);
	set_poll_rate();
}

/*
 * Start Routine.
 */
hsstart( tp )
register TTY * tp;
{
	register int s;

	/*
	 * Transmit buffer is empty, and raw output buffer is not.
	 */
	s = sphi();
	if ( (inb( PORT+LSR ) & LS_TxRDY)
	  && (tp->t_rawout.si_ix != tp->t_rawout.si_ox) ) {

		/*
		 * Send next char from raw output buffer.
		 */
		outb( PORT+DREG, tp->t_rawout.si_buf[ tp->t_rawout.si_ox ] );

		if ( ++tp->t_rawout.si_ox >= sizeof(tp->t_rawout.si_buf) )
			tp->t_rawout.si_ox = 0;
	}
	spl( s );
}

/*
 * hsclk will be called every time T0 interrupts - if it returns 0,
 * the usual system timer interrupt stuff is done
 */
static int hsclk()
{
  static int count;

  hsintr();
  count++;
  if (count >= poll_divisor)
    count = 0;
  return count;
}

/*
 * set_poll_rate is called when a port is opened or closed or changes speed
 * it sets the polling rate only as fast as needed, and shuts off polling
 * whenever possible
 */
static set_poll_rate()
{
	int port_num, max_rate, port_rate;
printf("set_poll_rate()\n");

	/*
	 * If another driver has the polling clock, do nothing.
	 */
	if (poll_owner & ~ POLL_HS)
		return;

	/*
	 * find highest valid polling rate in units of HZ/10
	 */
	max_rate = 0;
	for (port_num = 0; port_num < HSNUM; port_num++) {
		if (hstty[port_num].t_open) {
		  port_rate = poll_hz[hstty[port_num].t_sgttyb.sg_ispeed];
printf("port %d  rate=%d\n", port_num, port_rate);		  
		  if (max_rate < port_rate)
			max_rate = port_rate;
		}
	}
	/*
	 * if max_rate is not current rate, adjust the system clock
	 */
	if (max_rate != poll_rate) {
		poll_rate = max_rate;
		poll_divisor = poll_rate/HZ;  /* used in hsclk() */
		altclk_out();		/* stop previous polling */
printf("altclk_out()\n");		
		poll_owner &= ~POLL_HS;
		if (max_rate) {	/* resume polling at new rate if needed */
			altclk_in(poll_rate, hsclk);
printf("altclk_in(%d, hsclk)\n", poll_rate);			
			poll_owner |= POLL_HS;
		}
	}
}
@
0707070064030104271004440000030000030000011777770507310673500005500000004443/newbits/kernel/USRSRC/i8086/drv/RCS/ipc.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.50.14;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.12.14;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.31.52;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.12;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Inter-Process Communication.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:06:15	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:05:02	src
 * Initial revision
 * 
 */
#include <coherent.h>
#include <sys/ipc.h>
#include <sys/uproc.h>

/*
 * Determine Inter-Process Communication Access Permissions.
 *
 *	Input:	p = pointer to inter-process communication permission struct.
 *
 *	Action:	If super user, permissions are 0600.
 *		If uid is that of the creator or owner of the message id,
 *			use user permissions.
 *		If gid is that of the creator or owner of the message id,
 *			use group permissions.
 *		Otherwise, use others permissions.
 *
 *	Output:	0600 = Read/Alter permission.
 *		0400 = Read permission.
 *		0200 = Alter permission.
 *		   0 = No permission.
 */

ipcaccess( p )

register struct ipc_perm * p;

{
	if ( u.u_uid == 0 )
		return 0600;

	if ((u.u_uid == p->uid) || (u.u_uid == p->cuid))
		return p->mode & 0600;

	if ((u.u_gid == p->gid) || (u.u_gid == p->cgid))
		return (p->mode << 3) & 0600;

	return (p->mode << 6) & 0600;
}
@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106671004440000030000030000011777770507310673500005700000010524/newbits/kernel/USRSRC/i8086/drv/RCS/ipcas.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.50.17;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.14;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1985, 1984
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/

////////
/
/ System V Compatible Inter-Process Communication - Assembler Support
/
/ ufcopy( base, off, sel, n ) -- copy n bytes from user base to sel:off.
/ fucopy( off, sel, base, n ) -- copy n bytes from sel:off to user base.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 2.1	88/09/03  13:06:24	src
/ *** empty log message ***
/ 
/ Revision 1.1	88/03/24  17:05:05	src
/ Initial revision
/ 
/
/ 85/07/19	Allan Cornish
/ Inserted code to check user address for validity.
/ Functions ufcopy and fucopy now return 0 if user address is invalid.
/ Replaced 'jnc .+2;movsb' with 'rcl cx,$1;rep movsb' to improve pipelining.
/
/ 85/07/03	Allan Cornish
/ Functions renamed: uoscopy --> ufcopy, osucopy --> fucopy (f = far).
/ Module moved from msgas.s to ipcas.s, to reflect its shared use.
/
////////

	.globl	ufcopy_
	.globl	fucopy_

////////
/
/ ufcopy( base, off, sel, n )	-- copy n bytes from user base to sel:off.
/
/	Input:	base = offset in user memory to copy from
/		off  = offset in the destination segment
/		sel  = selector to access the destination segment
/		n    = number of bytes to copy
/
/	Action:	Copy 'n' bytes of data from offset 'base' in user memory
/		to offset 'off' in the segment accessed by selector 'sel'.
/
/	Return:	Number of bytes copied, or 0 if invalid user address.
/
////////

ufcopy_:			/ ufcopy( base, off, sel, n )
	push	si		/
	push	di		/ unsigned base;
	push	bp		/ unsigned off;
	mov	bp, sp		/ saddr_t sel;
	push	ds		/ unsigned n;
	push	es		/
				/ {
	mov	ax, 8(bp)	/	Validate user address.
	dec	ax		/
	add	ax, 14(bp)	/	Wrap-around error?
	jc	fuerr		/
	cmp	ax, udl_	/	Address out of bounds error?
	ja	fuerr		/
				/
	mov	bx, uds_	/	Map DS:SI into user (source) addr
	mov	ds, bx		/
	mov	si, 8(bp)	/
	les	di, 10(bp)	/	Map ES:DI into segment (dest) addr
	mov	cx, 14(bp)	/	Transfer count
				/
	cld			/	Auto Increment
	clc			/
	rcr	cx, $1		/	Change byte count into word count
	rep			/	Transfer data words
	movsw			/
	rcl	cx, $1		/	If residual byte count
	rep			/		Transfer last data byte.
	movsb			/
				/
	mov	ax, 14(bp)	/	Return transfer count.
	pop	es		/ }
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret

fuerr:	sub	ax, ax
	pop	es
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ fucopy( off, sel, base, n )	-- copy n bytes from sel:off to user base.
/
/	Input:	off  = offset is the source segment
/		sel  = selector to access the source segment
/		base = offset in user memory to copy to
/		n    = number of bytes to copy
/
/	Action:	Copy 'n' bytes of data from offset 'off' in the segment
/		accessed by selector 'sel' to offset 'base' in user memory.
/
/	Return:	Number of bytes copied, or 0 if invalid user address.
/
////////

fucopy_:			/ fucopy( off, sel, base, n )
	push	si		/
	push	di		/ unsigned off;
	push	bp		/ saddr_t  sel;
	mov	bp, sp		/ unsigned base;
	push	ds		/ unsigned n;
	push	es		/
				/ {
	mov	ax, 12(bp)	/	Validate user address.
	dec	ax		/
	add	ax, 14(bp)	/	Wrap-around error?
	jc	fuerr		/
	cmp	ax, udl_	/	Address out of bounds error?
	ja	fuerr		/
				/
	mov	es, uds_	/	Map ES:DI into user (dest) address
	mov	di, 12(bp)	/
	lds	si, 8(bp)	/	Map DS:SI into segment (source) addr
	mov	cx, 14(bp)	/	Transfer count
				/
	cld			/	Auto Increment
	clc			/
	rcr	cx, $1		/	Change byte count into word count
	rep			/
	movsw			/	Transfer data words
	rcl	cx, $1		/	If residual byte count
	rep			/		Transfer last data byte.
	movsb			/
				/
	mov	ax, 14(bp)	/	Return transfer count.
	pop	es		/ }
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030054731004440000000000000000011777770507310673700005400000044213/newbits/kernel/USRSRC/i8086/drv/RCS/kb.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.07.03.13.18.48;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.18;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Keyboard/display driver.
 * Coherent, IBM PC/XT/AT.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <signal.h>
#include <sys/sched.h>

#define	ISMAJ	2			/* Keyboard major device */

#define	SPC	0376			/* Special encoding */
#define XXX	0377			/* Non-character */
#define	KBDATA	0x60			/* Keyboard data */
#define	KBCTRL	0x61			/* Keyboard control */
#define	KBFLAG	0x80			/* Keyboard reset flag */
#define	LEDCMD	0xED			/* status indicator command */
#define	KBACK	0xFA			/* status indicator acknowledge */
#define	EXTENDED1 0xE1			/* extended key seq initiator */

#define	KEYUP	0x80			/* Key up change */
#define	KEYSC	0x7F			/* Key scan code mask */
#define	LSHIFT	0x2A-1			/* Left shift key */
#define LSHIFTA 0x2B-1			/* Alternate left-shift key */
#define	RSHIFT	0x36-1			/* Right shift key */
#define	CTRL	0x1D-1			/* Control key */
/*-- #define	CAPLOCK	0x1D-1	--*/		/* Control key */
#define	ALT	0x38-1			/* Alt key */
#define	CAPLOCK	0x3A-1			/* Caps lock key */
/*-- #define	CTRL	0x3A-1	--*/		/* Caps lock key */
#define	NUMLOCK	0x45-1			/* Numeric lock key */
#define	DELETE	0x53-1			/* Del, as in CTRL-ALT-DEL */
#define BACKSP	0x0E-1			/* Back space */
#define SCRLOCK	0x46-1			/* Scroll lock */

/* Shift flags */
#define	SRS	0x01			/* Right shift key on */
#define	SLS	0x02			/* Left shift key on */
#define CTS	0x04			/* Ctrl key on */
#define ALS	0x08			/* Alt key on */
#define CPLS	0x10			/* Caps lock on */
#define NMLS	0x20			/* Num lock on */
#define AKPS	0x40			/* Alternate keypad shift */
#define SHFT	0x80			/* Shift key flag */

/* Function key information */
#define	NFKEY	20			/* Number of settable functions */
#define	NFCHAR	150			/* Number of characters settable */
#define	NFBUF	(NFKEY*2+NFCHAR+1)	/* Size of buffer */

/*
 * Functions.
 */
int	isrint();
int	istime();
void	isbatch();
int	mmstart();
int	isopen();
int	isclose();
int	isread();
int	mmwrite();
int	isioctl();
void	mmwatch();
int	isload();
int	isuload();
int	ispoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON iscon ={
	DFCHR|DFPOL,			/* Flags */
	ISMAJ,				/* Major index */
	isopen,				/* Open */
	isclose,			/* Close */
	nulldev,			/* Block */
	isread,				/* Read */
	mmwrite,			/* Write */
	isioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	mmwatch,			/* Timeout */
	isload,				/* Load */
	isuload,			/* Unload */
	ispoll				/* Poll */
};

/*
 * Flag indicating turbo machine.
 */
int isturbo = 0;

/*
 * Terminal structure.
 */
TTY	istty = {
	{0}, {0}, 0, mmstart, NULL, 0, 0
};

/*
 * State variables.
 */
int		islock;			/* Keyboard locked flag */
int		isbusy;			/* Raw input conversion busy */
static	char	shift;			/* Overall shift state */
static	char	scroll;			/* Scroll lock state */
static  char	lshift = LSHIFT;	/* Left shift alternate state */
static	char	isfbuf[NFBUF];		/* Function key values */
static	char	*isfval[NFKEY];		/* Function key string pointers */
static	int	ledcmd;			/* LED update command flag */
static	int	extended;		/* extended key scan count */

/*
 * Tables for converting key code to ASCII.
 * lmaptab specifies unshifted conversion,
 * umaptab specifies shifted conversion,
 * smaptab specifies the shift states which are active.
 * An entry of XXX says the key is dead.
 * An entry of SPC requires further processing.
 *
 * Key codes:
 *	ESC .. <- == 1 .. 14
 *	-> .. \n == 15 .. 28
 *	CTRL .. ` == 29 .. 41
 *	^Shift .. PrtSc == 42 .. 55
 * 	ALT .. CapsLock == 56 .. 58
 *	F1 .. F10 == 59 .. 68
 *	NumLock .. Del == 69 .. 83
 */
static unsigned char lmaptab[] ={
	     '\33',  '1',  '2',  '3',  '4',  '5',  '6',		/* 1 - 7 */
	 '7',  '8',  '9',  '0',  '-',  '=', '\b', '\t',		/* 8 - 15 */
	 'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',		/* 16 - 23 */
	 'o',  'p',  '[',  ']', '\r',  XXX,  'a',  's',		/* 24 - 31 */
	 'd',  'f',  'g',  'h',  'j',  'k',  'l',  ';',		/* 32 - 39 */
	 '\'', '`',  XXX,  '\\',  'z',  'x',  'c',  'v',	/* 40 - 47 */
	 'b',  'n',  'm',  ',',  '.',  '/',  XXX,  '*',		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC					/* 80 - 83 */
};

static unsigned char umaptab[] ={
	     '\33',  '!',  '@@',  '#',  '$',  '%',  '^',		/* 1 - 7 */
	 '&',  '*',  '(',  ')',  '_',  '+', '\b', SPC,		/* 8 - 15 */
	 'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',		/* 16 - 23 */
	 'O',  'P',  '{',  '}', '\r',  XXX,  'A',  'S',		/* 24 - 31 */
	 'D',  'F',  'G',  'H',  'J',  'K',  'L',  ':',		/* 32 - 39 */
	 '"',  '~',  XXX,  '|',  'Z',  'X',  'C',  'V',		/* 40 - 47 */
	 'B',  'N',  'M',  '<',  '>',  '?',  XXX,  '*',		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC					/* 80 - 83 */
};

#define SS0	0			/* No shift */
#define SS1	(SLS|SRS|CTS)		/* Shift, Ctrl */
#define SES	(SLS|SRS)		/* Shift */
#define LET	(SLS|SRS|CPLS|CTS)	/* Shift, Caps, Ctrl */
#define KEY	(SLS|SRS|NMLS|AKPS)	/* Shift, Num, Alt keypad */

static unsigned char smaptab[] ={
	       SS0,  SES,  SS1,  SES,  SES,  SES,  SS1,		/* 1 - 7 */
	 SES,  SES,  SES,  SES,  SS1,  SES,  CTS,  SES,		/* 8 - 15 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  LET,		/* 16 - 23 */
	 LET,  LET,  SS1,  SS1,  CTS, SHFT,  LET,  LET,		/* 24 - 31 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  SES,		/* 32 - 39 */
	 SES,  SS1, SHFT,  SS1,  LET,  LET,  LET,  LET,		/* 40 - 47 */
	 LET,  LET,  LET,  SES,  SES,  SES, SHFT,  SES,		/* 48 - 55 */
	SHFT,  SS1, SHFT,  SS0,  SS0,  SS0,  SS0,  SS0,		/* 56 - 63 */
	 SS0,  SS0,  SS0,  SS0,  SS0, SHFT,  KEY,  KEY,		/* 64 - 71 */
	 KEY,  KEY,  SS0,  KEY,  KEY,  KEY,  SS0,  KEY,		/* 72 - 79 */
	 KEY,  KEY,  KEY,  KEY					/* 80 - 83 */
};

/*
 * Load entry point.
 *  Do reset the keyboard because it gets terribly munged
 *  if you type during the boot.
 */
isload()
{
	register int i;

	/*
	 * Reset keyboard if NOT an XT turbo.
	 */
	if ( ! isturbo ) {
		outb(KBCTRL, 0x0C);		/* Clock low */
		for (i = 10582; --i >= 0; );	/* For 20ms */
		outb(KBCTRL, 0xCC);		/* Clock high */
		for (i = 0; --i != 0; )
			;
		i = inb(KBDATA);
		outb(KBCTRL, 0xCC);			/* Clear keyboard */
		outb(KBCTRL, 0x4D);			/* Enable keyboard */
	}

	/*
	 * Enable mmwatch() invocation every second.
	 */
	drvl[ISMAJ].d_time = 1;

	/*
	 * Seize keyboard interrupt.
	 */
	setivec(1, isrint);

	/*
	 * Initiailize video display.
	 */
	mmstart( &istty );
}

/*
 * Unload entry point.
 */
isuload()
{
	clrivec(1);
}

/*
 * Default function key strings (terminated by -1 [\377])
 */
static char *deffuncs[] = {
	"\33[1x\377",	/* F1 */
	"\33[2x\377",	/* F2 */
	"\33[3x\377",	/* F3 */
	"\33[4x\377", 	/* F4 */
	"\33[5x\377",	/* F5 */
	"\33[6x\377",	/* F6 */
	"\33[7x\377",	/* F7 */
	"\33[8x\377",	/* F8 */
	"\33[9x\377",	/* F9 */
	"\33[0x\377",	/* F10 - historical value */
	"\33[1y\377",	/* F11 */
	"\33[2y\377",	/* F12 */
	"\33[3y\377",	/* F13 */
	"\33[4y\377", 	/* F14 */
	"\33[5y\377",	/* F15 */
	"\33[6y\377",	/* F16 */
	"\33[7y\377",	/* F17 */
	"\33[8y\377",	/* F18 */
	"\33[9y\377",	/* F19 */
	"\33[0y\377"	/* F20 */
};

/*
 * Open routine.
 */
isopen(dev)
dev_t dev;
{
	register int s;

	if (minor(dev) != 0) {
		u.u_error = ENXIO;
		return;
	}
	if ((istty.t_flags&T_EXCL)!=0 && super()==0) {
		u.u_error = ENODEV;
		return;
	}
	ttsetgrp(&istty, dev);

	s = sphi();
	if (istty.t_open++ == 0)
	{  initkeys();	 /* init function keys */
	   istty.t_flags = T_CARR;  /* indicate "carrier" */
	   ttopen(&istty);
	}
	spl(s);
	updleds();			/* update keyboard status LEDS */
}

/* Init function keys */
initkeys()
{	register int i;
	register char *cp1, *cp2;

	for (i=0; i<NFKEY; i++)
	    isfval[i] = 0;	    /* clear function key buffer */
	cp2 = isfbuf;	      	    /* pointer to key buffer */   
	for (i=0; i<NFKEY; i++)
	{  isfval[i] = cp2;	    /* save pointer to key string */
	   cp1 = deffuncs[i];       /* get init string pointer */
	   while ((*cp2++ = *cp1++) != -1)  /* copy key data */
	     if (cp2 >= &isfbuf[NFBUF-3])   /* overflow? */
	        return;
	}
}

/*
 * Close a tty.
 */
isclose(dev)
{
	register int s;

	s = sphi();
	if (--istty.t_open == 0)
	{  	s = sphi();
		ttclose(&istty);
		spl(s);
	}
}

/*
 * Read routine.
 */
isread(dev, iop)
dev_t dev;
IO *iop;
{
	ttread(&istty, iop, 0);
	if (istty.t_oq.cq_cc)
		mmtime(&istty);
}

/*
 * Ioctl routine.
 */
isioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	register int s;

	switch(com) {
	case TIOCSETF:
	case TIOCGETF:
		isfunction(com, (char *)vec);
		return;
	case TIOCSHIFT:   /* switch left-SHIFT and "\" */
		lshift = LSHIFTA;    /* alternate values */
		lmaptab[41] = '\\';
		lmaptab[42] = XXX;
		umaptab[41] = '|';
		umaptab[42] = XXX;
		smaptab[41] = SS1;
		smaptab[42] = SHFT;
		return;
	case TIOCCSHIFT:  /* normal (default) left-SHIFT and "\" */
		lshift = LSHIFT;     /* normal values */
		lmaptab[41] = XXX;
		lmaptab[42] = '\\';
		umaptab[41] = XXX;
		umaptab[42] = '|';
		smaptab[41] = SHFT;
		smaptab[42] = SS1;
		return;
	}
	s = sphi();
	ttioctl(&istty, com, vec);
	spl(s);
}

/*
 * Set and receive the function keys.
 */
isfunction(c, v)
int c;
char *v;
{
	register char *cp;
	register int i;

	if (c == TIOCGETF) {
		for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++)
		    putubd(v++, *cp);
	} else {
		for (i=0; i<NFKEY; i++)		/* zap current settings */
			isfval[i] = 0;
		cp = isfbuf;			/* pointer to key buffer */
		for (i=0; i<NFKEY; i++) {
			isfval[i] = cp;	        /* save pointer to key string */
			while ((*cp++ = getubd(v++)) != -1)  /* copy key data */
				if (cp >= &isfbuf[NFBUF-3])  /* overflow? */
					return;
		}
	}
}


/*
 * Poll routine.
 */
ispoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll failure.
	 */
	if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) {

		if ( msec != 0 )
			pollopen( &istty.t_ipolls );

		/*
		 * Second look AFTER enabling monitor, avoiding interrupt race.
		 */
		if ( istty.t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}

	return ev;
}

/*
 * Receive interrupt.
 */
isrint()
{
	register int	c;
	register int	s;
	register int	r;
	int	savests;
	int	update_leds = 0;

	/*
	 * Schedule raw input handler if not already active.
	 */
	if ( isbusy == 0 ) {
		defer( isbatch, &istty );
		isbusy = 1;
	}

	/*
	 * Pull character from the data
	 * port. Pulse the KBFLAG in the control
	 * port to reset the data buffer.
	 */
	r = inb(KBDATA) & 0xFF;
	c = inb(KBCTRL);
	outb(KBCTRL, c|KBFLAG);
	outb(KBCTRL, c);
#if	KBDEBUG
	printf("kbd: %d\n", r);			/* print scan code/direction */
#endif
	if (ledcmd) {
		ledcmd = 0;
		if (r == KBACK) {		/* output to status LEDS */
			c = scroll & 1;
			if (shift & NMLS)
				c |= 2;
			if (shift & CPLS)
				c |= 4;
			outb(KBDATA, c);
		}
		return;
	}
	if (extended > 0) {			/* if multi-character seq, */
		--extended;			/* ... ignore this char */
		return;
	}
	if (r == EXTENDED1) {			/* ignore extended sequences */
		extended = 5;
		return;
	}
	if (r == 0xFF)
		return;	/* Overrun */
	c = (r & KEYSC) - 1;
	/*
	 * Check for reset.
	 */
	if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS))
		boot();

	/*
	 * Track "shift" keys.
	 */
	s = smaptab[c];
	if (s&SHFT) {
		if (r&KEYUP) {			/* "shift" released */
			if (c == RSHIFT)
				shift &= ~SRS;
			else if (c == lshift)
				shift &= ~SLS;
			else if (c == CTRL)
				shift &= ~CTS;
			else if (c == ALT)
				shift &= ~ALS;
		} else {			/* "shift" pressed */
			if (c == lshift)
				shift |= SLS;
			else if (c == RSHIFT)
				shift |= SRS;
			else if (c == CTRL)
				shift |= CTS;
			else if (c == ALT)
				shift |= ALS;
			else if (c == CAPLOCK) {
				shift ^= CPLS;	/* toggle cap lock */
				updleds();
			} else if (c == NUMLOCK) {
				shift ^= NMLS;	/* toggle num lock */
				updleds();
			}
		}
		return;
	}

	/*
	 * No other key up codes of interest.
	 */
	if (r&KEYUP)
		return;

	/*
	 * If the tty is not open the character is
	 * just tossed away.
	 */
	if (istty.t_open == 0)
		return;

	/*
	 * Map character, based on the
	 * current state of the shift, control,
	 * meta and lock flags.
	 */
	if (shift & CTS) {
		if (s == CTS)			/* Map Ctrl (BS | NL) */
			c = (c == BACKSP) ? 0x7F : 0x0A;  
		else if (s==SS1 || s==LET)	/* Normal Ctrl map */
			c = umaptab[c]&0x1F;	/* Clear bits 5-6 */
		else				
			return;			/* Ignore this char */
	} else if (s &= shift) {
		if (shift & SES) {		 /* if shift on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = lmaptab[c];  /* use unshifted */
			else
				c = umaptab[c];	 /* use shifted */
		} else {			 /* if shift not on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = umaptab[c];	 /* use shifted */
			else
				c = lmaptab[c];	 /* use unshifted */
		}
	} else					 
		c = lmaptab[c];			 /* use unshifted */

	/*
	 * Act on character.
	 */
	if (c == XXX)				
		return;				 /* char to ignore */

	if (c != SPC) {			 /* not special char? */
		if (shift & ALS)	 /* ALT (meta bit)? */
			c |= 0x80;	 /* set meta */
		isin(c);		 /* send the char */
	} else
		update_leds += isspecial(r);	 /* special chars */
	if (update_leds) {
		savests = sphi();
		outb(KBDATA, LEDCMD);
		ledcmd = 1;
		spl(savests);
	}
}

/*
 * Handle special input sequences.
 * The character passed is the key number.
 *
 * The keypad is translated by the following table,
 * the first entry is the normal sequence, the second the shifted,
 * and the third the alternate keypad sequence.
 */
static char *keypad[][3] = {
	{ "\33[H",  "7", "\33?w" },	/* 71 */
	{ "\33[A",  "8", "\33?x" },	/* 72 */
	{ "\33[V",  "9", "\33?y" },	/* 73 */
	{ "\33[D",  "4", "\33?t" },	/* 75 */
	{ "\0337",  "5", "\33?u" },	/* 76 */
	{ "\33[C",  "6", "\33?v" },	/* 77 */
	{ "\33[24H","1", "\33?q" },	/* 79 */
	{ "\33[B",  "2", "\33?r" },	/* 80 */
	{ "\33[U",  "3", "\33?s" },	/* 81 */
	{ "\33[@@",  "0", "\33?p" },	/* 82 */
	{ "\33[P", ".",  "\33?n" }	/* 83 */
};

isspecial(c)
int c;
{
	register char *cp;
	register int s;
	int	update_leds = 0;

	cp = 0;

	switch (c) {
	case 15:					/* cursor back tab */
		cp = "\033[Z";
		break;
	case 59: case 60: case 61: case 62: case 63:	/* Function keys */
	case 64: case 65: case 66: case 67: case 68:
		/* offset to function string */
		if ( shift & ALS )
			cp = isfval[c-49];
		else
			cp = isfval[c-59];
		break;

	case 70:		/* Scroll Lock -- stop/start output */
	{
		static char cbuf[2];

		cp = &cbuf[0];  /* working buffer */
		if (!(istty.t_sgttyb.sg_flags&RAWIN)) {	/* not if in RAW mode */
			++update_leds;
			if (istty.t_flags & T_STOP) {	/* output stopped? */
			   cbuf[0] = istty.t_tchars.t_startc;  /* start it */
			   scroll = 0;
			} else {
			   cbuf[0] = istty.t_tchars.t_stopc;   /* stop output */
			   scroll = 1;
			}
		}
		break;
	}

	case 79:		/* 1/End */
	case 80:		/* 2/DOWN */
	case 81:		/* 3/PgDn */
	case 82:		/* 0/Ins */
	case 83:		/* ./Del */
		--c;		/* adjust code */
	case 75:		/* 4/LEFT */
	case 76:		/* 5 */
	case 77:		/* 6/RIGHT */
		--c;		/* adjust code */
	case 71:		/* 7/Home/Clear */
	case 72:		/* 8/UP */
	case 73:		/* 9/PgUp */
		s = 0;			/* start off with normal keypad */
		if (shift&NMLS)		/* num lock? */
			s = 1;		/* set shift pad */
		if (shift&SES)		/* shift? */
			s ^= 1;		/* toggle shift pad */
		if (shift&AKPS)		/* alternate pad? */
			s = 2;		/* set alternate pad */		
		cp = keypad[c-71][s];   /* get keypad value */
		break;
	}
	if (cp)					/* send string */
		while ((*cp != 0) && (*cp != -1))
			isin( *cp++ & 0377 );
	return update_leds;
}

/**
 *
 * void
 * ismmfunc( c )	-- process keyboard related output escape sequences
 * char c;
 */
void
ismmfunc(c)
register int c;
{
	switch (c) {
	case 't':	/* Enter numlock */
		shift |= NMLS;
		updleds();			/* update LED status */
		break;
	case 'u':	/* Leave numlock */
		shift &= ~NMLS;
		updleds();			/* update LED status */
		break;
	case '=':	/* Enter alternate keypad */
		shift |= AKPS;
		break;
	case '>':	/* Exit alternate keypad */
		shift &= ~AKPS;
		break;
	case 'c':	/* Reset terminal */
		islock = 0;
		shift  = 0;
		initkeys();
		updleds();			/* update LED status */
		break;
	}
}

/**
 *
 * void
 * isin( c )	-- append character to raw input silo
 * char c;
 */
static
isin( c )
register int c;
{
	/*
	 * Cache received character.
	 */
	istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c;

	if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) )
		istty.t_rawin.si_ix = 0;
}

/**
 *
 * void
 * isbatch()	-- raw input conversion routine
 *
 *	Action:	Enable the video display.
 *		Canonize the raw input silo.
 *
 *	Notes:	isbatch() was scheduled as a deferred process by isrint().
 */
static void
isbatch( tp )
register TTY * tp;
{
	register int c;
	static int lastc;

	/*
	 * Ensure video display is enabled.
	 */
	mm_von();

	isbusy = 0;

	/*
	 * Process all cached characters.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		/*
		 * Get next cached char.
		 */
		c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ];

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;

		if ( (islock == 0) || ISINTR || ISQUIT ) {
			ttin( tp, c );
		}

		else if ( (c == 'b') && (lastc == '\033') ) {
			islock = 0;
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else if ( (c == 'c') && (lastc == '\033') ) {
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else
			putchar('\007');

		lastc = c;
	}
}

/*
 * update the keyboard status LEDS
 */
updleds()
{
	int	s;

	s = sphi();
	outb(KBDATA, LEDCMD);
	ledcmd = 1;
	spl(s);
}

/*
 * unlock the scroll in case an interrupt character is received
 */
kbunscroll()
{
	scroll = 0;
	updleds();
}
@


1.1
log
@Initial revision
@
text
@d10 3
a12 3
#include <coherent.h>
#include <i8086.h>
#include <con.h>
d14 3
a16 3
#include <stat.h>
#include <tty.h>
#include <uproc.h>
d18 1
a18 2
#include <sys/timeout.h>
#include <sched.h>
@
0707070064030106641004440000030000030000011777770507310674400005500000000647/newbits/kernel/USRSRC/i8086/drv/RCS/lgl.h,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.23.24;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version (Beta)
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
@
0707070064030104261004440000030000030000011777770507310674400005400000006622/newbits/kernel/USRSRC/i8086/drv/RCS/mm.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.50.47;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.33;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Memory Mapped Video
 * High level output routines.
 */
#include <sys/coherent.h>
#include <sys/sched.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/io.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <sys/timeout.h>

/* For beeper */
#define	TIMCTL	0x43			/* Timer control port */
#define	TIMCNT	0x42			/* Counter timer port */
#define	PORTB	0x61			/* Port containing speaker enable */
#define	FREQ	((int)(1193181L/440))	/* Counter for 440 Hz. tone */

int mmtime();

char mmbeeps;		/* number of ticks remaining on bell */
char mmesc;		/* last unserviced escape character */
int  mmcrtsav = 1;	/* crt saver enabled */
int  mmvcnt   = 900;	/* seconds remaining before crt saver is activated */

extern TTY istty;

/*
 * Start the output stream.
 * Called from `ttwrite' and `isrint' routines.
 */
TIM mmtim;

mmstart(tp)
register TTY *tp;
{
	int c;
	IO iob;
	static int mmbegun;

	while ((tp->t_flags&T_STOP) == 0) {
		if ((c = ttout(tp)) < 0)
			break;
		iob.io_seg  = IOSYS;
		iob.io_ioc  = 1;
		iob.io_base = &c;
		iob.io_flag = 0;
		mmwrite( makedev(2,0), &iob );
	}

	if (mmbegun == 0) {
		++mmbegun;
		timeout(&mmtim, HZ/10, mmtime, (char *)tp);
	}
}

mmtime(xp)
char *xp;
{
	register int s;

	s = sphi();
	if (mmbeeps < 0) {
		mmbeeps = 2;
		outb(TIMCTL, 0xB6);	/* Timer 2, lsb, msb, binary */
		outb(TIMCNT, FREQ&0xFF);
	        outb(TIMCNT, FREQ>>8);
		outb(PORTB, inb(PORTB) | 03);	/* Turn speaker on */
	}
	else if ((mmbeeps > 0) && (--mmbeeps == 0))
		outb( PORTB, inb(PORTB) & ~03 );

	if (mmesc) {
		ismmfunc(mmesc);
		mmesc = 0;
	}
	spl(s);

	ttstart( (TTY *) xp );

	timeout(&mmtim, HZ/10, mmtime, xp);
}

/**
 *
 * void
 * mmwatch()	-- turn video display off after 15 minutes inactivity.
 */
void
mmwatch()
{
	if ( (mmcrtsav > 0) && (mmvcnt > 0) && (--mmvcnt == 0) )
		mm_voff();
}

mmwrite( dev, iop )
dev_t dev;
register IO *iop;
{
	int ioc;
	int s;

	ioc = iop->io_ioc;

	/*
	 * Kernel writes.
	 */
	if (iop->io_seg == IOSYS) {
		while (mmgo(iop))
			;
	}

	/*
	 * Blocking user writes.
	 */
	else if ( (iop->io_flag & IONDLY) == 0 ) {
		do {
			while (istty.t_flags & T_STOP) {
				s = sphi();
				istty.t_flags |= T_HILIM;
				sleep((char*) &istty.t_oq,
					CVTTOUT, IVTTOUT, SVTTOUT);
				spl( s );
			}
			/*
			 * Signal received.
			 */
			if ( SELF->p_ssig && nondsig() ) {
				kbunscroll();	/* update kbd LEDS */
				/*
				 * No data transferred yet.
				 */
				if ( ioc == iop->io_ioc )
					u.u_error = EINTR;
				/*
				 * Transfer remaining data
				 * without pausing after scrolling.
				 */
				else while ( mmgo(iop) )
					;

				return;
			}
			mmgo(iop);
		} while ( iop->io_ioc );
	}

	/*
	 * Non-blocking user writes with output stopped.
	 */
	else if ( istty.t_flags & T_STOP ) {
		u.u_error = EAGAIN;
		return;
	}

	/*
	 * Non-blocking user writes do not pause after scrolling.
	 */
	else {
		while ( mmgo(iop) )
			;
	}
}
@


1.1
log
@Initial revision
@
text
@d10 1
a10 1
#include <coherent.h>
@
0707070064030106621004440000030000030000011777770507310674500005600000075145/newbits/kernel/USRSRC/i8086/drv/RCS/mmas.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.10.14.33.03;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.35;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update prov by hal
@
text
@////////
/
/	Memory mapped video driver assembler assist.
/
////////
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal information
/		CX    - input count
/		BP    - references terminal information
/		AH    - character attributes
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
////////

	NCOL	= 80		/ number of columns
	NCB	= 2		/ number of horizontal bytes per char
	NCR	= 1		/ number of horizontal lines per char
	NHB	= 160		/ number of horizontal bytes per line
	NRB	= NCR*NHB	/ number of bytes per character row

	ATTR	= ah		/ attribute byte
	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	INTENSE	= 0x08		/ high intensity attribute bit
	BLINK	= 0x80		/ blinking attribute bit
	REVERSE	= 0x70		/ reverse video

////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_BASE	= 8

	IOSYS	= 0
	IOUSR	= 1

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_INVIS	= 20		/ cursor invisible mask
MM_SLOW		= 22		/ slow [no flicker] video update
MM_WRAP		= 23		/ wrap to start of next line

	.globl	VIDSLOW_	/ Patchable kernel variable.
	.prvd
mmdata:	.word	mminit
	.word	0x03B4
	.word	0xB000
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, 23, 24, 0, 0, 0, 23
	.word	0
VIDSLOW_:.byte	0
	.byte	1
	.shri

////////
/
/ mmgo( iop )
/ IO *iop;
/
////////

	.globl	mmgo_

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc

	cmp	IO_SEG(bx), $IOSYS	/ user address space
	je	0f
	mov	bx, uds_
	mov	ds, bx
0:
	mov	bp, $mmdata
	mov	dx, MM_PORT(bp)		/ turn video off if color board
	cmp	dx, $0x3B4
	je	3f
	cmpb	MM_SLOW(bp), $0		/ check for slow [flicker-free]
	je	2f

	mov	dx, $0x3DA
1:	inb	al, dx			/ wait for vertical retrace
	testb	al, $8
	je	1b
2:
	mov	dx, $0x3D8		/ disable video
	movb	al, $0x25
	outb	dx, al
3:
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	sub	bx, bx
	movb	ATTR, MM_ATTR(bp)
	ijmp	MM_FUNC(bp)

exit:	pop	bx
	pop	es
	pop	ds
	movb	MM_ATTR(bp), ATTR
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, MM_PORT(bp)		/ adjust cursor location
	mov	bx, POS
	or	bx, MM_INVIS(bp)
	shr	bx, $1

	movb	al, $14
	outb	dx, al
	inc	dx
	movb	al, bh
	outb	dx, al
	dec	dx
	movb	al, $15
	outb	dx, al
	inc	dx
	movb	al, bl
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ turn video on
	add	dx, $4
	movb	al, $0x29
	outb	dx, al
	mov	mmvcnt_, $600		/ 600 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret


////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $'c		/ schedule keyboard initialization
	call	int11_			/ read equipment status
	and	ax, $0x30		/ isolate video bits
	cmp	ax, $0x30		/ if not monochrome
	je	0f
	mov	MM_PORT(bp), $0x3D4	/	set color port
	mov	MM_BASE(bp), $0xB800	/	set color base
	mov	es, MM_BASE(bp)		/
0:					/
	mov	dx, MM_PORT(bp)		/ turn video off
	add	dx, $4
	movb	al, $0x21
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ zero display offset
	movb	al, $12
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al
	dec	dx
	movb	al, $13
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ reset border to black
	add	dx, $5
	subb	al, al
	outb	dx, al

	inc	dx			/ reset TECMAR XMSR register
	outb	dx, al

	mov	MM_INVIS(bp), $0
	movb	ATTR, $0x07
	movb	MM_ATTR(bp), ATTR
	movb	MM_WRAP(bp), $1
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ mmspec - schedule special keyboard function
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	cld
	rep
	movsw
	movb	al, $' 
	pop	di
	mov	cx, $NCOL
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, cs:rowtab(bx)
	call	exit
	jmp	eval

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, cs:rowtab(bx)
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	stosw				/ Update display memory.
	incb	COL
	cmpb	COL, $NCOL		/ Past end of line?
	jge	0f
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	cmpb	MM_WRAP(bp), $0		/ Yes past, Wrap around?
	jne	0f
	sub	di, $2			/ No wrap, adjust back to end of line.
	decb	COL
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	subb	COL, COL		/ Wrap to next line.
	incb	ROW
	cmpb	ROW, MM_EROW(bp)	/ Past scrolling region?
	jg	0f
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	movb	ROW, MM_EROW(bp)	/ Yes past, scroll up 1 line.
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	sub	POS, $2
	decb	COL
	jge	0f
	movb	COL, $NCOL-1
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
0:	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $';
	je	csi_n2
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

0:	cmpb	al, $'h
	je	mm_cgh
	cmpb	al, $'l
	je	mm_cgl
	jmp	eval

////////
/
/ Csi_q state - entered after input sequence ESC [ ?
/	
////////

0:	call	exit
csi_q:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $'0
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_q

0:	cmpb	al, $'h
	je	mm_cqh
	cmpb	al, $'l
	je	mm_cql
	jmp	eval

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jg	0f
	subb	COL, COL		/ can't step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process 'ESC [ > N1 h' escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process 'ESC [ > N1 l' escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	decb	COL
	jge	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	push	cx
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl
	movb	al, $' 
	rep
	stosw
	pop	cx
	cmpb	COL, $NCOL
	jb	0f
	subb	COL, $NCOL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	eval

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cqh - process 'ESC [ ? N1 h' escape sequence
/
/	Recognized sequences:	ESC [ ? 4 h	-- Set smooth scroll.
/				ESC [ ? 7 h	-- Set wraparound.
/
////////

mm_cqh:	cmpb	MM_N1(bp), $4		/ Smooth scroll.
	jne	0f
	movb	MM_SLOW(bp), $1
0:	cmpb	MM_N1(bp), $7		/ Wraparound.
	jne	0f
	movb	MM_WRAP(bp), $1
0:	jmp	eval

////////
/
/ mm_cql - process 'ESC [ ? N1 l' escape sequence
/
/	Recognized sequences:	ESC [ ? 4 l	-- Set jump scroll.
/				ESC [ ? 7 l	-- Reset wraparound.
/
////////

mm_cql:	cmpb	MM_N1(bp), $4		/ Jump scroll.
	jne	0f
	movb	MM_SLOW(bp), $0
0:	cmpb	MM_N1(bp), $7		/ No wraparound.
	jne	0f
	movb	MM_WRAP(bp), $0
0:	jmp	eval

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, $NCOL
	jb	0f
	subb	COL, $NCOL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, $NCOL-1
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter (mm_n1) specifies the vertical position (MM_ROW(bp)).
/	The second parameter (mm_n2) specifies the horizontal position (MM_COL(bp)).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	rep
	movsw
	mov	di, cs:rowtab(bx)
	mov	cx, $NCOL
	movb	al, $' 
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input, and causing cursor to vanish.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2


////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

mm_e2:	push	cx
	movb	al, $' 
0:	mov	cx, $NCOL
	rep
	stosw
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

mm_e1:	push	cx
	mov	cx, POS
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	sub	cx, POS
	jl	0f
	movb	al, $' 
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

mm_e0:	push	cx
	shlb	bl, $1
	mov	cx, cs:rowtab+2(bx)
	sub	cx, POS
	jl	0f
	movb	al, $' 
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, cs:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, cs:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, cs:rowtab(bx)
	jle	0f
	shr	cx, $1
	std
	rep
	movsw
	mov	di, cs:rowtab(bx)
	mov	cx, $NCOL
	movb	al, $' 
	cld
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	 MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_INVIS(bp), $0
	jmp	eval

0:	mov	MM_INVIS(bp), $-1
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					5 - slow blink
/					7 - reverse video
/					8 - concealed on
/					30-37 - foreground color
/					40-47 - background color
/					50-57 - border color
/
////////

mm_sgr:	movb	al, MM_N1(bp)

	cmpb	al, $0			/ reset all = 0
	jne	0f
	movb	ATTR, $0x07
1:	jmp	eval

0:	cmpb	al, $1			/ bold = 1
	jne	0f
	orb	ATTR, $INTENSE
	jmp	1b

0:	cmpb	al, $4			/ underline = 4
	jne	0f
	cmp	MM_PORT(bp), $0x03D4	/ color card?
	je	1b			/ yes, ignore underline
	andb	ATTR, $~0x77
	orb	ATTR, $0x01
	jmp	1b

0:	cmpb	al, $5			/ blinking = 5
	jne	0f
	orb	ATTR, $BLINK
	jmp	1b

0:	cmpb	al, $7			/ reverse video = 7
	jne	0f
	movb	al, $0x70
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f
	movb	al, ATTR		/ yes, exchange foreground/background
	andb	al, $0x77
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
2:	andb	ATTR, $~0x77
	orb	ATTR, al
	jmp	1b

0:	cmpb	al, $8			/ concealed on = 8
	jne	0f
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f

	andb	ATTR, $0x70		/ Yes,	Set foreground color
	movb	al, ATTR		/	to background color.
	rorb	al, $1
	rorb	al, $1
	rorb	al, $1
	rorb	al, $1
	orb	ATTR, al
	jmp	1b

2:	andb	ATTR, $0x80		/ No, set attributes to non-display.
	jmp	1b			/	retain blink attribute.

0:	cmp	MM_PORT(bp), $0x03D4	/ color card?
	jne	1b			/ no, ignore remaining options
0:	subb	al, $30			/ foreground color
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x07
	orb	ATTR, cs:fcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x70
	orb	ATTR, cs:bcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	movb	al, cs:fcolor(bx)
	push	dx
	mov	dx, MM_PORT(bp)
	add	dx, $5
	outb	dx, al
	pop	dx
/	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	mmbell	/* EOT  ENQ  ACK  BEL  */
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/* BS   HT   LF   VT   */
	.word	eval,	mm_cr,	eval,	eval	/* FF   CR   SO   SI   */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3  */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	mm_esc	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/*   ! " # \040 - \043 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* $ % & ' \044 - \047 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ( ) * + \050 - \053 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* , - . / \054 - \057 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 0 1 2 3 \060 - \063 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 4 5 6 7 \064 - \067 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 8 9 : ; \070 - \073 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* < = > ? \074 - \077 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* @@ A B C \100 - \103 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* D E F G \104 - \107 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* H I J K \110 - \113 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* L M N O \114 - \117 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* P Q R S \120 - \123 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* T U V W \124 - \127 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* X Y Z [ \130 - \133 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* \ ] ^ _ \134 - \137 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ` a b c \140 - \143 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* d e f g \144 - \147 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* h i j k \150 - \153 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* l m n o \154 - \157 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* p q r s \160 - \163 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* t u v w \164 - \167 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* x y z { \170 - \173 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* | } ~ ? \174 - \177 */

////////
/
/ esctab - table of functions indexed by ESC characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/* NUL  SOH  STX  ETX  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* EOT  ENQ  ACK  BEL  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* BS   HT   LF   VT   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FF   CR   SO   SI   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DLE  DC1  DC2  DC3  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DC4  NAK  SYN  ETB  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* CAN  EM   SUB  ESC  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & ' \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	mm_new	/* 4 5 6 7 \064 - \067 */
	.word	mm_old,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	mmspec,	mmspec,	eval	/* < = > ? \074 - \077 */
	.word	eval,	eval,	eval,	eval	/* @@ A B C \100 - \103 */
	.word	mm_ind,	mm_cnl,	eval,	eval	/* D E F G \104 - \107 */
	.word	eval,	eval,	eval,	eval	/* H I J K \110 - \113 */
	.word	eval,	mm_ri,	eval,	eval	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	eval	/* P Q R S \120 - \123 */
	.word	eval,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	eval,	csi_n1	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_dmi,	eval,	mm_emi,	mminit	/* ` a b c \140 - \143 */
	.word	eval,	eval,	eval,	eval	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	eval,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	eval,	eval	/* p q r s \160 - \163 */
	.word	mmspec,	mmspec,	eval,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */


////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	eval	/* EOT  ENQ  ACK  BEL  */
	.word	eval,	eval,	eval,	eval	/* BS   HT   LF   VT   */
	.word	eval,	eval,	eval,	eval	/* FF   CR   SO   SI   */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3  */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	eval	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & ' \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	eval	/* 4 5 6 7 \064 - \067 */
	.word	eval,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	eval,	csi_gt,	csi_q	/* < = > ? \074 - \077 */
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/* @@ A B C \100 - \103 */
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/* D E F G \104 - \107 */
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/* H I J K \110 - \113 */
	.word	mm_il,	mm_dl,	eval,	mm_ea	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	mm_ind	/* P Q R S \120 - \123 */
	.word	mm_ri,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	mm_cbt,	eval	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_hpa,	mm_hpr,	eval,	eval	/* ` a b c \140 - \143 */
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	mm_sgr,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	mm_ssr,	eval	/* p q r s \160 - \163 */
	.word	eval,	eval,	mm_scr,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ coltab - integer array of offsets to each column
/
////////

coltab:	.word	 0*NCB,	 1*NCB,	 2*NCB,	 3*NCB
	.word	 4*NCB,	 5*NCB,	 6*NCB,	 7*NCB
	.word	 8*NCB,	 9*NCB,	10*NCB,	11*NCB
	.word	12*NCB,	13*NCB,	14*NCB,	15*NCB
	.word	16*NCB,	17*NCB,	18*NCB,	19*NCB
	.word	20*NCB,	21*NCB,	22*NCB,	23*NCB
	.word	24*NCB,	25*NCB,	26*NCB,	27*NCB
	.word	28*NCB,	29*NCB,	30*NCB,	31*NCB
	.word	32*NCB,	33*NCB,	34*NCB,	35*NCB
	.word	36*NCB,	37*NCB,	38*NCB,	39*NCB
	.word	40*NCB,	41*NCB,	42*NCB,	43*NCB
	.word	44*NCB,	45*NCB,	46*NCB,	47*NCB
	.word	48*NCB,	49*NCB,	50*NCB,	51*NCB
	.word	52*NCB,	53*NCB,	54*NCB,	55*NCB
	.word	56*NCB,	57*NCB,	58*NCB,	59*NCB
	.word	60*NCB,	61*NCB,	62*NCB,	63*NCB
	.word	64*NCB,	65*NCB,	66*NCB,	67*NCB
	.word	68*NCB,	69*NCB,	70*NCB,	71*NCB
	.word	72*NCB,	73*NCB,	74*NCB,	75*NCB
	.word	76*NCB,	77*NCB,	78*NCB,	79*NCB

////////
/
/ rowtab - array of offsets to each row
/
////////

rowtab:	.word	 0*NRB,	 1*NRB,	 2*NRB,	 3*NRB
	.word	 4*NRB,	 5*NRB,	 6*NRB,	 7*NRB
	.word	 8*NRB,	 9*NRB,	10*NRB,	11*NRB
	.word	12*NRB,	13*NRB,	14*NRB,	15*NRB
	.word	16*NRB,	17*NRB,	18*NRB,	19*NRB
	.word	20*NRB,	21*NRB,	22*NRB,	23*NRB
	.word	24*NRB,	25*NRB,	26*NRB,	27*NRB
	.word	28*NRB,	29*NRB,	30*NRB,	31*NRB

////////
/
/ fcolor - foreground color
/ bcolor - background color
/
/	indexed by ansi color (black,red,green,brown,blue,magenta,cyan,white)
/	yields graphics color (black,blue,green,cyan,red,magenta,brown,white)
/		which is properly shifted for installation in attribute byte.
/
////////

fcolor:	.byte	0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
bcolor:	.byte	0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70

////////
/
/ mm_voff()	-- turn video display off
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, mmdata+MM_PORT
	add	dx, $4
	movb	al, $0x21
	outb	dx, al
	ret

////////
/
/ mm_von()	-- turn video display on
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, mmdata+MM_PORT	/ enable video display
	add	dx, $4
	movb	al, $0x29
	outb	dx, al
	mov	mmvcnt_, $900		/ 900 seconds before video disabled
	ret
@


1.1
log
@Initial revision
@
text
@a0 5
/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
d337 1
d355 1
d367 1
d379 1
d397 1
d417 1
d443 1
d515 1
@
0707070064030106631004440000030000030000011777770507310675400005400000021265/newbits/kernel/USRSRC/i8086/drv/RCS/ms.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3; strict;
comment  @ * @;


1.3
date     91.06.20.14.51.08;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.33.02;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.45;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.3
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 *	Microsoft bus mouse (rodent) driver.
 */

#include <sys/coherent.h>
#include <sys/uproc.h>
#include <sys/con.h>
#include <sys/ms.h>
#include <errno.h>

#define Help(fmt, p)		printf(fmt, p)
#define Help2(fmt, p, q)	printf(fmt, p, q)
#define Diag(fmt, p)		/* Help(fmt, p) */
#define Diag2(fmt, p, q)	/* Help2(fmt, p, q) */
#define	MSMAJOR		10	/* major device # */

/*
 *	global patchable definitions
 */
unsigned MSPORT  = 0x23C;	/* mouse 8255A registers: */
				/* modified mouse is 0x23C */
				/* Geac modified mouse is 0x230 */
unsigned MSIRQ   = 2;		/* mouse interrupt # */

/*
 *	driver function definitions
 */
int	msload();
int	msunload();
int	msopen();
int	msclose();
int	msioctl();
int	mspoll();
int	msintr();
int	nulldev();
int	nonedev();

/*
 *	configuration table
 */
CON mscon = {
	DFCHR|DFPOL,			/* flags	*/
	MSMAJOR,			/* major index	*/
	msopen,				/* open		*/
	msclose,			/* close	*/
	nonedev,			/* block	*/
	nonedev,			/* read		*/
	nonedev,			/* write	*/
	msioctl,			/* ioctl	*/
	nulldev,			/* power fail	*/
	nulldev,			/* timeout	*/
	msload,				/* load		*/
	msunload,			/* unload	*/
	mspoll				/* poll		*/
};

/*
 *	ioctl function definitions
 */

int	ms_setup();
int	ms_setcrs();
int	ms_readcrs();
int	ms_setmick();
int	ms_readmick();
int	ms_readbtns();
int	ms_readstat();
int	ms_wait();

int (*ioctls[])() = {
  /*	   0	     1		 2	     3		  4		*/
	ms_setup, ms_setcrs, ms_readcrs, ms_setmick, ms_readmick,

  /*	     5		 6	   7					*/
	ms_readbtns, ms_readstat, ms_wait
};

/*
 *	hardware constants
 */
static	int	porta;			/* 	port A (read/write) */
static	int	portb;			/*	port B (read/write) */
static	int	portc;			/*	port C (read/write) */
static	int	portcm;			/*	control port (write only) */

static	int	u_stts	=  0;		/* changed-status flags */
static	int	u_mask	=  0;		/* user condition mask */

static	event_t	ipolls;

static struct msparms parms, initparm = {
	2, -16, 655, -16, 215, 8, 16
};

static struct mspos crsr, csav, initcrsr = { 320, 100 };

static struct msmick mick, initmick = { 0, 0 };

static struct msbuts buttons, initbuttons = {
	0,
	{	{0, {320, 100}},
		{0, {320, 100}},
		{0, {320, 100}},
		{0, {320, 100}}
	}
};

static	int	ms_inuse = 0;		/* is mouse in use ? */

msload()
{
	int s;

	porta  = MSPORT;
	portb  = MSPORT + 1;
	portc  = MSPORT + 2;
	portcm = MSPORT + 3;

	s = sphi();
	outb( portcm, 0x91 );		/* set 8255A mode 9 */
	outb( portc,  0x10 );		/* disable interrupt */
	setivec( MSIRQ, msintr );	/* set up irq vector */
	spl(s);

	return 0;
}

/*
 * Unload function.
 */
msunload()
{
	clrivec( MSIRQ );		/* release irq vector */
	outb( portcm, 0x91 );		/* set 8255A mode 9 */
	outb( portc,  0x10 );		/* disable interrupt */
}

msopen(dev, mode)
dev_t	dev;
{
	int	s;

	s = sphi(s);
	if (ms_inuse) {
		u.u_error = EDBUSY;
		spl(s);
		return( -1 );
	}

	outb( portcm, 0x91 );			/* set 8255A mode 9 */
	outb( portb,  0x5a );

	if( inb( portb ) != 0x5a) {		/* hardware installed? */
		u.u_error = ENXIO;
		spl(s);
		return( -1 );
	}

	outb( portc, 0x90 );
	inb( porta );
	outb( portc, 0xb0 );
	inb( porta );
	outb( portc, 0xd0 );
	inb( porta );
	outb( portc, 0xf0 );
	inb( porta );
	outb( portc, 0 );		/* clear all mouse registers */

/* set things */
	parms = initparm;
	crsr = csav = initcrsr;
	mick = initmick;
	buttons = initbuttons;
	u_stts = u.u_error = 0;
	ms_inuse = 1;
	spl(s);

	return( 0 );
}

msclose()
{
	int s;

	s = sphi();
	outb( portc, 0x10 );			/* disable interrupt */
	ms_inuse = u.u_error = 0;
	spl(s);
	return( 0 );
}

msioctl( dev, com, vec )
dev_t	dev;
int	com;
char	*vec;
{
	int s;

	s = sphi();
	if (com >= 0 && com < sizeof(ioctls)/sizeof(ioctls[0])) {
		(*ioctls[com])(vec);	/* indirect func call */
		u.u_error = 0;
	} else
		u.u_error = EINVAL;
	spl(s);
	if (u.u_error)
		return( -1 );

	return( 0 );
}

/*
 * Polling routine.
 * [System V.3 Compatible].
 */
mspoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	ev &= ~POLLPRI;
	ev &= ~POLLOUT;

	/*
	 * No input.
	 */
	if ( (u_stts & u_mask) == 0 ) {
		/*
		 * Enable monitor if blocking poll.
		 */
		if ( msec != 0 ) 
			pollopen( &ipolls );
		/*
		 * Look again to avoid interrupt race.
		 */
		if ( (u_stts & u_mask) == 0 )
			ev &= ~POLLIN;
	}

	return ev;
}

/*
 *	write setup structure
 */
ms_setup( newparm )
struct msparms *newparm;
{
	ukcopy(newparm, &parms, sizeof(struct msparms));
	if (parms.h_mpr == 0)
		parms.h_mpr = 1;
	if (parms.v_mpr == 0)
		parms.v_mpr = 1;
}

/*
 *	write cursor position
 */
ms_setcrs( pos )
struct mspos *pos;
{
	ukcopy(pos, &crsr, sizeof(struct mspos));
	u_stts &= ~MS_S_MOVE;		/* clear u_stts pos bit */
}

/*
 *	read cursor postion
 */
ms_readcrs( pos )
struct mspos *pos;
{
	kucopy(&crsr, pos, sizeof(struct mspos));
	u_stts &= ~MS_S_MOVE;		/* clear u_stts pos bit */
}

/*
 *	write mickey postion
 */
ms_setmick( pos )
struct msmick *pos;
{
	ukcopy(pos, &mick, sizeof(struct msmick));
}

/*
 *	read mickey postion
 */
ms_readmick( pos )
struct msmick *pos;
{
	kucopy(&mick, pos, sizeof(struct msmick));
}

/*
 *	read button status
 */
ms_readbtns( btns )
struct msbuts *btns;
{
	kucopy(&buttons, btns, sizeof(struct msbuts));
	u_stts &= ~MS_S_BUTTONS;		/* clear u_stts button bits */
}

/*
 *	read "changed status" mask
 */
ms_readstat( stat )
int *stat;
{
	kucopy(&u_stts, stat, sizeof(int));
}

/*
 *	wait on "changed status" mask
 */
ms_wait( flag )
int *flag;
{
	ukcopy(flag, &u_mask, sizeof(int));
	while ((u_mask & u_stts) == 0)	/* wait until any bit is on */
		sleep(&u_stts, 0x7fff, 0x7fff, 0);
	u_mask = 0;
}

/*
 *	mouse interrupt service routine
 */
msintr()
{
	static	int h_fpix =  0;			/* fractional pixel */
	static	int v_fpix = 0;				/* ditto */
	int	s, n_l, n_h, h_diff, v_diff, tmp, left, right;

	if (!ms_inuse)			/* dev not open - ignore interrupts */
		return;
	
	s = sphi();
	outb( portc, 0x90 );		/* get horizontal change */
	n_l = inb( porta );
	outb( portc, 0xb0 );
	n_h = inb( porta );
	h_diff = (char) ((n_l & 0x0f) | (n_h << 4));

	outb( portc, 0xd0 );		/* get vertical change */
	n_l = inb( porta );
	outb( portc, 0xf0 );
	n_h = inb( porta );
	v_diff = (char) ((n_l & 0x0f) | (n_h << 4));

	outb( portc, 0 );
	left = right = 0;				/* set button status */
	if (!(n_h & 0x80)) left = MS_L_DOWN;		/* left button.. */
	if ((buttons.bbstat & MS_L_DOWN) ^ left) {
		if (left)
			button(MS_B_L_PRESS,   MS_S_L_PRESS);
		else
			button(MS_B_L_RELEASE, MS_S_L_RELEASE);
	}
	if (!(n_h & 0x20))				/* right button.. */
		right = MS_R_DOWN;
	if ((buttons.bbstat & MS_R_DOWN) ^ right) {
		if (right)
			button(MS_B_R_PRESS,   MS_S_R_PRESS);
		else
			button(MS_B_R_RELEASE, MS_S_R_RELEASE);
	}

	buttons.bbstat = left | right;		/* set new button status */

	if (h_diff || v_diff) {			/* any motion? */
		mick.h_mick += h_diff;		/* yes - update positions */
		mick.v_mick += v_diff;
		if ((abs(h_diff) > parms.accel_t) || (abs(v_diff) > parms.accel_t)) {
			h_diff *= 2;
			v_diff *= 2;
		}

		if (h_diff) {			/* horizontal change */
			tmp   = h_fpix + 8 * h_diff;
			h_fpix = tmp % parms.h_mpr;
			tmp    = crsr.h_crsr + tmp / parms.h_mpr;
			crsr.h_crsr = c_range(tmp, parms.h_cmin, parms.h_cmax);
		}

		if (v_diff) {			/* vertical change */                                                                                                                                                                                           
			tmp   = v_fpix + 8 * v_diff;
			v_fpix = tmp % parms.v_mpr;
			tmp    = crsr.v_crsr + tmp / parms.v_mpr;
			crsr.v_crsr = c_range(tmp, parms.v_cmin, parms.v_cmax);
		}

		if ((crsr.h_crsr != csav.h_crsr) || (crsr.v_crsr != csav.v_crsr)) {
			u_stts |= MS_S_MOVE;
			csav = crsr;
		}
	}

	if (u_stts & u_mask) {
		wakeup(&u_stts);
		if ( ipolls.e_procp )
			pollwake( &ipolls );
	}

	spl(s);
}

/*
 *	update button-press/release data
 */
button( bp, sbit )
int bp;
unsigned sbit;
{
	++buttons.buts[bp].cnt;
	buttons.buts[bp].bpos = crsr;
	u_stts |= sbit;
}

/*
 *	force return value to be within specified range
 */
c_range(c, cmin, cmax)
int	c, cmin, cmax;
{
	if( c < cmin )
		c = cmin;
	else if( c > cmax )
		c = cmax;
	return( c );
}

abs(i)
int i;
{
	if (i < 0)
		return (-i);
	return i;
}
@


1.2
log
@new version provided y hal for v321
@
text
@d10 1
a10 1
#include <coherent.h>
@


1.1
log
@Initial revision
@
text
@d10 1
a10 1
#include <sys/coherent.h>
@
0707070064030106611004440000030000030000011777770507310675600005500000045247/newbits/kernel/USRSRC/i8086/drv/RCS/msg.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.51.17;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.12.53;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.33.12;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.53;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1986, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Messaging
 *
 *	This module provides System V compatible messaging operations.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Oct 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:09:07	src
 * *** empty log message ***
 * 
 * Revision 1.2	88/08/02  16:49:52	src
 * Bug:	msgget with IPC_CREAT could fail if message queue already
 * 	existed, and queue permissions were not an exact match
 * 	for requested permissions.
 * Fix:	Permission checking made more rigorous.
 * 
 * Revision 1.1	88/03/24  17:05:44	src
 * Initial revision
 * 
 * 87/04/24	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgctl() IPC_STAT check of polled devices modified.
 *
 * 87/04/01	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgctl() now correctly reports polling events on an IPC_STAT operation.
 *
 * 87/03/20	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgpoll() now correctly reports POLLOUT events.
 *
 * 87/01/20	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * msginit() is now more paranoid about validating NMSC, NMSG, NMSQID.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * msginit() now allocates message buffers in high memory.
 *
 * 86/12/12	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Added 3rd argument to msgpoll() to support non-blocking polls.
 *
 * 86/11/21	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Added support for System V.3 compatible polls.
 * Added msgpoll() routine and xmsqid_ds structure.
 *
 * 85/08/06	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msg.c split into configuration (msgcon.c) and implementation (msg.c).
 *
 * 85/07/22	Allan Cornish		/usr/src/sys/i8086/drv/msg.c
 * Msgget, msgctl, msgsnd, msgrcv now return immediately if u.u_error is set.
 *
 * 85/07/19	Allan Cornish
 * Msgrcv() now reports E2BIG if message is larger than size requested.
 * Msgfree() integrated into msginit() and msgrcv() functions.
 * Msgsnd() now checks for queue removal after waking from sleep.
 * Msgsnd() and msgrcv() now detect address faults and report EFAULT.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Replaced msgaccess() by calls to ipcaccess(), increasing shared ipc code.
 * Eliminated many calls to sphi() and spl().  They are not really required,
 * since system calls are synchronous unless they sleep or are interrupted.
 * Sleeps cause no problem, and interrupts do not affect messaging state.
 *
 * 85/06/19	Allan Cornish
 * Added code to msgctl to allow the owner of a queue to reduce msg_qbytes.
 * Previously only the super-user could modify msg_qbytes.
 *
 * 85/06/18	Allan Cornish
 * Added code to msgsnd to check for full queue (msg_cbytes >= msg_qbytes).
 * Integrated msgalloc function into msgsnd, since only called from there.
 * Fixed bug in msgrcv when msgtyp < 0, to treat msg_type as mesg priority.
 *
 * 85/05/10	Allan Cornish
 * C compiler bug in msginit caused 'mp->msg_spot = (wanted -= NMSC)' to fail.
 * For NMSG=10, NMSC=640, msg_spot always set to 0x1900 or 0xE980.
 * Code changed to 'wanted -= NMSC; mp->msg_spot = wanted'.
 *
 * 85/04/01	Allan Cornish
 * fixed qp->msg_last bug in msgrcv().
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <seg.h>
#include <msg.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif

/*
 * Extended message queue id data structure.
 *	- extended to support System V.3 compatible polls.
 */
struct xmsqid_ds {
	struct msqid_ds	msq;
	struct event	ipolls;
	struct event	opolls;
};

/*
 *	Message Information
 */

struct xmsqid_ds *msqs = 0;	/* Pointer to array of message queues */
				/* (first queue contains free message list) */

struct msg * msgs = 0;		/* Pointer to array of message headers */

static SEG * msgsp;		/* Segment containing messages */
#define	msgsel FP_SEL(msgsp->s_faddr)

/*
 *	Global Message Parameters
 */

unsigned NMSQID = 9;	/* allocated number of message queues */
unsigned NMSQB  = 2048;	/* default maximum queue size in bytes */
unsigned NMSG = 10;	/* allocated messages: (NMSG * NMSC) < 2^16 */
unsigned NMSC = 640;	/* maximum message text size */

/*
 * Message Device Initialization.
 *
 *	Initialize message ids.
 */

msginit()
{
	register struct xmsqid_ds *qp;
	register struct msg *mp;
	long wanted;
	int i;

	if ( NMSG == 0 )
		NMSQID = 0;
	if ( NMSC == 0 )
		NMSQID = 0;
	if ( NMSQID == 0 )
		return 0;

	if ( NMSQID > 128 )
		NMSQID = 128;

	/*
	 * Allocate message queues and message headers.
	 */
	wanted = (NMSQID * (long) sizeof(struct xmsqid_ds)) +
		(NMSG * (long) sizeof(struct msg));
	if (wanted > 16384) {
		printf("invalid NMSQID or NMSG kernel variable\n");
		NMSQID=0;
		return;
	}

	if ( msqs = kalloc( (unsigned) wanted) ) {

		/*
		 * Ensure allocated space is cleared.
		 */
		memset( msqs, 0, (unsigned) wanted );

		/*
		 * Message headers are contiguous to message queues.
		 */
		msgs = (struct msg *) (&msqs[NMSQID]);

		/*
		 * Allocate message buffers.
		 */
		wanted = (long) NMSG * NMSC;
		if ( wanted > 0xFFFFL ) {
			printf("invalid NMSG or NMSC kernel variable\n");
			kfree( msqs );
			NMSQID = 0;
			msqs   = 0;
			return;
		}

		msgsp = salloc( (size_t) wanted, SFHIGH|SFNSWP|SFNCLR );

		if ( msgsp == 0 ) {
			printf("could not salloc %u messages\n", NMSG);
			kfree( msqs );
			NMSQID = 0;
			msqs   = 0;
			return;
		}

		/*
		 * Initialize message queues.
		 */
		for ( qp = msqs, i = 0; i < NMSQID; i++, qp++ ) {

			qp->msq.msg_perm.seq  = i * 256;

			qp->ipolls.e_dnext =
			qp->ipolls.e_dlast = &qp->ipolls;

			qp->opolls.e_dnext =
			qp->opolls.e_dlast = &qp->opolls;
		}

		/*
		 * Initialize message headers, place on free queue.
		 */
		for ( qp = msqs, mp = &msgs[NMSG]; --mp >= msgs; ) {
			wanted -= NMSC;
			mp->msg_spot  = wanted;
			mp->msg_next  = qp->msq.msg_first;
			qp->msq.msg_first = mp;
		}
	}
	else {
		printf("could not kalloc %u message ids\n", NMSQID);
		NMSQID = 0;
	}
}


/*
 * Msgctl - Message Control Operations.
 */

umsgctl( qid, cmd, buf )

int qid;
int cmd;
struct msqid_ds *buf;

{
	register struct xmsqid_ds *qp;
	register struct msg *mp;
	unsigned n;

	/*
	 * Validate queue identifier.
	 */
	if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( (qp == 0) || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	/*
	 * Validate qid for all commands except for IPC_STAT.
	 */
	if ( (cmd != IPC_STAT) && (qp->msq.msg_perm.seq != qid) ) {
		u.u_error = EINVAL;
		return -1;
	}

	switch ( cmd ) {

	case IPC_STAT:
		/*
		 * Validate access authority.
		 */
		if ( (ipcaccess(&qp->msq.msg_perm) & MSG_R) == 0 ) {
			u.u_error = EACCES;
			break;
		}

		/*
		 * Copy queue info to user.
		 */
		kucopy( qp, buf, sizeof(struct msqid_ds) );

		/*
		 * Include input polls in receive waiting.
		 */
		if ( (qp->ipolls.e_dnext != NULL)
		  && (qp->ipolls.e_dnext != &qp->ipolls) ) {
			putuwd( &buf->msg_perm.mode,
				getuwd( &buf->msg_perm.mode ) | MSG_RWAIT );
		}

		/*
		 * Include output polls in write waiting.
		 */
		if ( (qp->opolls.e_dnext != NULL)
		  && (qp->opolls.e_dnext != &qp->opolls) ) {
			putuwd( &buf->msg_perm.mode,
				getuwd( &buf->msg_perm.mode ) | MSG_WWAIT );
		}

		/*
		 * Validate qid.
		 * Doing it now lets user get info on message queue.
		 */
		if ( qp->msq.msg_perm.seq != qid )
			u.u_error = EINVAL;
		break;

	case IPC_SET:
		/*
		 * Validate modify authority.
		 */
		if ( (u.u_uid != 0) && (u.u_uid != qp->msq.msg_perm.uid) ) {
			u.u_error = EPERM;
			break;
		}

		/*
		 * Get desired queue size.
		 */
		n = getuwd( &(buf->msg_qbytes) );
		if (u.u_error)
			break;

		/*
		 * Only super-user can increase queue size.
		 */
		if ( (u.u_uid != 0) && (n > qp->msq.msg_qbytes) ) {
			u.u_error = EPERM;
			break;
		}

		/*
		 * Set queue parameters.
		 */
		qp->msq.msg_perm.uid   = getuwd( &(buf->msg_perm.uid ) );
		qp->msq.msg_perm.gid   = getuwd( &(buf->msg_perm.gid ) );
		qp->msq.msg_perm.mode &= ~0777;
		qp->msq.msg_perm.mode |= getuwd( &(buf->msg_perm.mode) ) & 0777;
		qp->msq.msg_qbytes     = n;
		break;

	case IPC_RMID:
		/*
		 * Validate removal authority.
		 */
		if ( (u.u_uid != 0) && (u.u_uid != qp->msq.msg_perm.uid) ) {
			u.u_error = EPERM;
			break;
		}

		/*
		 * Free all messages on the queue being removed.
		 */
		while ( mp = qp->msq.msg_first ) {
			qp->msq.msg_first   = mp->msg_next;
			mp->msg_next        = msqs->msq.msg_first;
			msqs->msq.msg_first = mp;
		}

		/*
		 * Wakeup processes waiting for free message buffers.
		 */
		if ( msqs->msq.msg_perm.mode & MSG_RWAIT ) {
			msqs->msq.msg_perm.mode &= ~MSG_RWAIT;
			wakeup( msqs );
		}
		if ( msqs->ipolls.e_procp )
			pollwake( &msqs->ipolls );

		/*
		 * Initialize queue parameters.
		 */
		qp->msq.msg_last   = 0;
		qp->msq.msg_qnum   = 0;
		qp->msq.msg_cbytes = 0;
		if ( (qp->msq.msg_perm.seq & 0x00FF) == 0x00FF )
			qp->msq.msg_perm.seq &= 0x7F00;
		qp->msq.msg_perm.seq++;

		/*
		 * Wakeup processes sleeping on the removed message queue.
		 */
		if ( qp->msq.msg_perm.mode & (MSG_RWAIT|MSG_WWAIT) )
			wakeup( qp );
		if ( qp->ipolls.e_procp )
			pollwake( &qp->ipolls );
		if ( qp->opolls.e_procp )
			pollwake( &qp->opolls );

		qp->msq.msg_perm.mode = 0;
		break;

	default:
		u.u_error = EINVAL;
	}

	if ( u.u_error )
		return -1;

	return 0;
}

/*
 * Msgget - Get set of messages
 */

umsgget( mykey, msgflg )

key_t mykey;
int msgflg;

{
	register struct xmsqid_ds *qp;
	register struct xmsqid_ds *freeidp = 0;
	int rwmode;
	
	if ( msqs == 0 ) {

		msginit();

		if ( msqs == 0 ) {
			u.u_error = ENOMEM;
			return;
		}
	}

	/*
	 * Extract desired access mode from flags.
	 */
	rwmode = msgflg & 0777;

	/*
	 * Search for desired message queue [also for first free queue].
	 */
	for ( qp = &msqs[NMSQID]; --qp > msqs; ) {

		if ( (qp->msq.msg_perm.mode & IPC_ALLOC) == 0 ) {

			if ((freeidp == 0) ||
			    (freeidp->msq.msg_ctime > qp->msq.msg_ctime))
				freeidp = qp;
			continue;
		}

		if (mykey == IPC_PRIVATE)
			continue;

		if ( mykey == qp->msq.msg_perm.key ) {		/* found! */

			if ( (msgflg & IPC_CREAT) && (msgflg & IPC_EXCL) ) {
				u.u_error = EEXIST;
				return -1;
			}

			if ( (qp->msq.msg_perm.mode & rwmode) != rwmode ) {
				u.u_error = EACCES;
				return -1;
			}

			return qp->msq.msg_perm.seq;
		}
	}

	if ( ! (msgflg & IPC_CREAT) ) {
		u.u_error = ENOENT;
		return -1;
	}

	if ( (qp = freeidp) == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	qp->msq.msg_first  = 0;
	qp->msq.msg_last   = 0;
	qp->msq.msg_cbytes = 0;
	qp->msq.msg_qnum   = 0;
	qp->msq.msg_qbytes = NMSQB;
	qp->msq.msg_lspid  = 0;
	qp->msq.msg_lrpid  = 0;
	qp->msq.msg_stime  = 0;
	qp->msq.msg_rtime  = 0;
	qp->msq.msg_ctime  = timer.t_time;

	qp->msq.msg_perm.cuid = qp->msq.msg_perm.uid = u.u_uid;
	qp->msq.msg_perm.cgid = qp->msq.msg_perm.gid = u.u_gid;
	qp->msq.msg_perm.mode = rwmode | IPC_ALLOC;
	qp->msq.msg_perm.key  = mykey;

	return qp->msq.msg_perm.seq;
}

/*
 * Send a Message
 */

umsgsnd( qid, bufp, msgsz, msgflg )

int qid;
struct msgbuf *bufp;
unsigned msgsz, msgflg;

{
	register struct xmsqid_ds * qp;
	register struct msg      * mp;

	/*
	 * Validate queue identifier.
	 */
	if ((qid <= 0) || (qid/256 >= NMSQID) || (msgsz > NMSC) || (msqs==0)) {
		u.u_error = EINVAL;
		return -1;
	}

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( (qp->msq.msg_perm.seq != qid)
	  || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ((ipcaccess(&qp->msq.msg_perm) & MSG_W) == 0){ /* can't send mesg */
		u.u_error = EACCES;
		return -1;
	}

	/*
	 * Wait for a free message buffer
	 */
	while ( (msqs->msq.msg_first == 0)
	     || (qp->msq.msg_qbytes <= qp->msq.msg_cbytes)) {

		if ( msgflg & IPC_NOWAIT ) {
			u.u_error = EAGAIN;
			return -1;
		}

		if (qp->msq.msg_qbytes <= qp->msq.msg_cbytes) {
			qp->msq.msg_perm.mode |= MSG_WWAIT;
			sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );
		}
		else {
			msqs->msq.msg_perm.mode |= MSG_RWAIT;
			sleep( msqs, CVTTOUT, IVTTOUT, SVTTOUT );
		}

		/*
		 * Abort if a signal was received
		 */
		if (SELF->p_ssig && nondsig() ) {
			u.u_error = EINTR;
			return -1;
		}

		/*
		 * Abort if the message queue was removed.
		 */
		if ( qid != qp->msq.msg_perm.seq ) {
			u.u_error = EIDRM;
			return -1;
		}
	}

	/*
	 * Use first message on free message queue
	 */
	mp = msqs->msq.msg_first;
	mp->msg_ts = msgsz;

	/*
	 * Transfer the message type and text.
	 */
	ukcopy( &(bufp->mtype), &(mp->msg_type), sizeof(mp->msg_type) );
	if ( ufcopy( &bufp->mtext[0], mp->msg_spot, msgsel, msgsz ) != msgsz )
			u.u_error = EFAULT;

	/*
	 * Abort if address fault occured during transfer.
	 */
	if ( u.u_error )
		return -1;

	/*
	 * Move the message to the desired queue.
	 */
	msqs->msq.msg_first = mp->msg_next;
	mp->msg_next = 0;

	if ( qp->msq.msg_last )
		qp->msq.msg_last->msg_next = mp;
	else
		qp->msq.msg_first = mp;
	qp->msq.msg_last = mp;

	/*
	 * Update queue statistics.
	 */
	qp->msq.msg_cbytes += msgsz;
	qp->msq.msg_qnum++;
	qp->msq.msg_lspid = SELF->p_pid;
	qp->msq.msg_stime = timer.t_time;

	/*
	 * Wake processes waiting to receive.
	 */
	if ( qp->msq.msg_perm.mode & MSG_RWAIT ) {
		qp->msq.msg_perm.mode &= ~MSG_RWAIT;
		wakeup( qp );
	}
	if ( qp->ipolls.e_procp )
		pollwake( &qp->ipolls );

	return 0;
}

/*
 * Receive A Message
 */

umsgrcv( qid, bufp, msgsz, msgtyp, msgflg )

int qid;
struct msgbuf *bufp;
unsigned msgsz;
long msgtyp;
unsigned msgflg;

{
	register struct xmsqid_ds *qp;
	register struct msg *mp;
	register struct msg *prev;

	/*
	 * Validate queue identifier.
	 */
	if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( (qp->msq.msg_perm.seq != qid)
	  || ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0) ) {
		u.u_error = EINVAL;
		return -1;
	}

	/*
	 * Permission denied
	 */
	if ( (ipcaccess(&qp->msq.msg_perm) & MSG_R) == 0 ) {
		u.u_error = EACCES;
		return -1;
	}

	/*
	 * Wait for message
	 */
	for (;;) {

		mp   = qp->msq.msg_first;
		prev = 0;

		/*
		 * Find mesg of type <= abs(msgtyp)
		 */
		if ( msgtyp < 0 ) {

			struct msg *xp, *xprev;
			
			xp     = 0;
			xprev  = 0;
			msgtyp = -msgtyp;

			for ( ; mp != 0 ; prev = mp, mp = mp->msg_next ) {

				if (mp->msg_type > msgtyp)
					continue;

				if ((xp==0) || (mp->msg_type < xp->msg_type)) {
					xp    = mp;
					xprev = prev;
				}
			}
			mp     = xp;
			prev   = xprev;
			msgtyp = -msgtyp;
		}

		/*
		 * Find message of type == msgtyp
		 */
		else if ( msgtyp > 0 ) {

			while ( (mp != 0) && (mp->msg_type != msgtyp) ) {
				prev = mp;
				mp = mp->msg_next;
			}
		}

		/*
		 * Else take first message
		 */

		if ( mp )
			break;

		/*
		 * Can't wait to receive mesg
		 */
		if ( msgflg & IPC_NOWAIT ) {
			u.u_error = EAGAIN;
			return -1;
		}

		qp->msq.msg_perm.mode |= MSG_RWAIT;
		sleep( qp, CVTTOUT, IVTTOUT, SVTTOUT );

		/*
		 * Signal received
		 */
		if ( SELF->p_ssig && nondsig() ) {
			u.u_error = EINTR;
			return -1;
		}

		/*
		 * Not same q anymore
		 */
		if ( qid != qp->msq.msg_perm.seq ) {
			u.u_error = EIDRM;
			return -1;
		}
	}

	/*
	 * Ensure entire message can be transferred, or MSG_NOERROR asserted.
	 */
	if ( (msgsz < mp->msg_ts) && ((msgflg & MSG_NOERROR) == 0) ) {
		u.u_error = E2BIG;
		return -1;
	}

	/*
	 * Transfer message data
	 */
	if ( msgsz > mp->msg_ts )
		msgsz = mp->msg_ts;

	kucopy( &(mp->msg_type), &(bufp->mtype), sizeof(mp->msg_type) );
	if (fucopy( mp->msg_spot, msgsel, &(bufp->mtext[0]), msgsz ) != msgsz)
		u.u_error = EFAULT;

	/*
	 * Abort if address fault occurred during transfer.
	 */
	if ( u.u_error )
		return -1;

	/*
	 * Remove message from queue
	 */
	if ( prev )
		prev->msg_next = mp->msg_next;
	else
		qp->msq.msg_first = mp->msg_next;

	if ( qp->msq.msg_last == mp )
		qp->msq.msg_last = prev;

	/*
	 * Update queue statistics
	 */
	qp->msq.msg_cbytes -= mp->msg_ts;
	qp->msq.msg_qnum--;
	qp->msq.msg_lrpid = SELF->p_pid;
	qp->msq.msg_rtime = timer.t_time;

	/*
	 * Wakeup processes waiting to send.
	 */
	if (qp->msq.msg_perm.mode & MSG_WWAIT) {
		qp->msq.msg_perm.mode &= ~MSG_WWAIT;
		wakeup( qp );
	}
	if ( qp->opolls.e_procp )
		pollwake( &qp->opolls );

	/*
	 * Place message buffer on free message queue
	 */
	qp = msqs;
	mp->msg_next = qp->msq.msg_first;
	qp->msq.msg_first = mp;

	/*
	 * Wakeup processes waiting for empty message buffer
	 */
	if ( qp->msq.msg_perm.mode & MSG_RWAIT ) {
		qp->msq.msg_perm.mode &= ~MSG_RWAIT;
		wakeup( qp );
	}
	if ( msqs->ipolls.e_procp )
		pollwake( &msqs->ipolls );

	return msgsz;
}

/*
 * Msgpoll - Message Queue Polling.
 */
msgpoll( qid, ev, msec )
int qid;
int ev;
int msec;
{
	register struct xmsqid_ds * qp;

	/*
	 * Validate queue identifier.
	 */
	if ( (qid <= 0) || (qid/256 >= NMSQID) || (msqs == 0) )
		return POLLNVAL;

	qp = &msqs[ qid / 256 ];

	/*
	 * Validate queue existence.
	 */
	if ( ((qp->msq.msg_perm.mode & IPC_ALLOC) == 0)
	  || (qp->msq.msg_perm.seq != qid) )
		return POLLHUP;

	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll.
	 */
	if ( ev & POLLIN ) {

		/*
		 * No messages on queue.
		 */
		if ( qp->msq.msg_qnum == 0 ) {
			/*
			 * Enable input monitor.
			 */
			if ( msec != 0 )
				pollopen( &qp->ipolls );
			ev &= ~POLLIN;
		}

		/*
		 * Prevent output monitor.
		 */
		else
			msec = 0;
	}

	/*
	 * Output poll.
	 */
	if ( ev & POLLOUT ) {

		/*
		 * Queue full.
		 */
		if ( qp->msq.msg_cbytes >= qp->msq.msg_qbytes ) {
			if ( msec != 0 )
				pollopen( &qp->opolls );
			ev &= ~POLLOUT;
		}

		/*
		 * No free message buffers.
		 */
		else if ( msqs->msq.msg_first == NULL ) {
			if ( msec != 0 )
				pollopen( &msqs->ipolls );
			ev &= ~POLLOUT;
		}
	}

	return ev;
}
@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106601004440000030000030000011777770507310676200006000000007307/newbits/kernel/USRSRC/i8086/drv/RCS/msgcon.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.51.35;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.13.14;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.33.34;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.23.59;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Message Device Driver
 *
 *	This device driver provides System V compatible messaging operations.
 *	Operations are performed through the message device (/dev/msg).
 *	and are implemented as ioctl calls from msgctl, msgget, msgsnd, msgrcv
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Oct 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:09:32	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:05:49	src
 * Initial revision
 * 
 * 87/03/02	Allan Cornish		/usr/src/sys/i8086/drv/msgcon.c
 * Msgioctl() now supports long key [was short] on MSGGET operations.
 * This allows compatability with System V.
 *
 * 85/08/06	Allan Cornish
 * Msg.c split into configuration (msgcon.c) and implementation (msg.c).
 *
 * 85/07/03	Allan Cornish
 * Simplified msgopen by ignoring minor device, which previously had to be 0.
 *
 * 84/01/30	Allan Cornish
 * Initial revision.
 */

#include <coherent.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <con.h>
#include <msg.h>

/*
 * Functions.
 */

int msgopen();
int msgioctl();
int nulldev();
int nonedev();

/*
 * Device Configuration.
 */

CON msgcon = {
	DFCHR,			/* Flags			*/
	25,			/* Major Index			*/
	msgopen,		/* Open				*/
	nulldev,		/* Close			*/
	nonedev,		/* Block			*/
	nonedev,		/* Read				*/
	nonedev,		/* Write			*/
	msgioctl,		/* Ioctl			*/
	nulldev,		/* Power fail			*/
	nulldev,		/* Timeout			*/
	nulldev,		/* Load				*/
	nulldev			/* Unload			*/
};

/*
 * Message Device Open.
 */

static
msgopen( dev, mode )

dev_t dev;
int mode;

{
	extern struct msqid_ds * msqs; /* Pointer to array of message queues */

	if ( ! msqs )			/* message queues not initialized */
		msginit();

	if ( ! msqs )			/* no message queues */
		u.u_error = ENODEV;
}

/*
 * Message Device Ioctl.
 */

static
msgioctl( dev, com, vec )

dev_t dev;
int com;
register int *vec;

{
	switch ( com ) {

	case MSGCTL:
		putuwd( vec+0,
			umsgctl(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ) ));
		return;

	case MSGGET:
		putuwd( vec+0,
			umsgget(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ) ));
		return;

	case MSGSND:
		putuwd( vec+0,
			umsgsnd(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ) ));
		return;

	case MSGRCV:
		putuwd( vec+0,
			umsgrcv(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ),
				getuwd( vec+5 ),
				getuwd( vec+6 ) ));
		return;

	default:
		u.u_error = EINVAL;
		return;
	}
}
@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106561004440000030000030000011777770507310676300006100000003343/newbits/kernel/USRSRC/i8086/drv/RCS/msgstub.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.24.23;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Message Device Driver Stub.
 *
 *	This module provides stubs for messaging routines accessed by the
 *	operating system, and is linked in when messaging is not specified.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Nov 1986.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:09:42	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:05:52	src
 * Initial revision
 * 
 * 86/12/12	Allan Cornish		/usr/src/sys/i8086/drv/msgstub.c
 * Added 3rd argument to msgpoll() to support non-blocking polls.
 *
 * 85/11/21	Allan Cornish		/usr/src/sys/i8086/drv/msgstub.c
 * Initial Revision.
 */

#include <coherent.h>
#include <errno.h>
#include <sys/uproc.h>

msgpoll( qid, ev, msec )
int qid;
int ev;
int msec;
{
	return POLLNVAL;
}

umsgget()
{
	u.u_error = ENXIO;
}

umsgrcv()
{
	u.u_error = ENXIO;
}

umsgsnd()
{
	u.u_error = ENXIO;
}

umsgctl()
{
	u.u_error = ENXIO;
}
@
0707070064030106551005550000030000030000011777770507310676300005500000016405/newbits/kernel/USRSRC/i8086/drv/RCS/parms,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.24.26;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@� ������F� �P�́�VWU���U�;v}=����^
�?�=t,��=-t=ct�DG��F��;F|�6����^
��"��F��5+�P�X��]_^�VWU���"j� t]_^�VWU��~P���]_^�VWU��P�BP�6"�*���>Ru�6"��P����+�P�6 �����}�6 ��P���� P�"P�T+�RP�e����P�:���F��~�}G�~���犅**�P�~���犅0*�P�~���犅$*�P�~������"�v���P�����F�볋�]_^�VWU��+�P�v
�v�6�����v�v�6����;Ft
�"P���]_^�VWU��zP�|���FP�;P��P����>P��P����P��
��]_^�VWU���J+��v
����<t+��D�DG���@@P�v�����F��u�'P�P�,P�F�P����F��~�t���~�t���F���F��~�4�F������ȋ���F��F������ȋ���w��w�����^��GډW��ËFڋV�F�V�F�V�F�V�F�V�,���F��V�+�PR�v��v��5���F��V��F��V���n��^��~�x[u�~�tS�tO�v��P�P�F�P�J���ȋ�=u1�v
����<t��P�F�PV����u�FΉD�FЉDOu���v��	����]_^�VWU��FP�zP�j��]_^�VWU��F
P�v�T��]_^�VWU����F�P��P�v�����F
P�F�P�)���N�}�F��F�P+�P�V����	�~��F����]_^�VWU���^�F
�F��^���F�F��^��F����=%t/�u���^�O}
�GSW�W
���ԋ^���F��^��Lj���F� �F����F����^��F������-u�F��^��F������F���0u�F�0�^��F������*u'�^��F���F��}
�F��؉F�^��F�����0�F���0|&��9!�F�.�.	�ȋ��-0�F�^��F�����Ճ�.uY�^��F������*u�^��F���F�^��F�����0�F���0|&��9!�F�.�.	�ȋ��-0�F�^��F�����Ճ�lu&�^��F������dt��ot
��ut��xu��%�����F��F����F��ǻl�CC.;��t��.�gDOUXcdefgorsux�I-N��SSS��i���^��F���F�~�}�؉F��F�-�
P�v�V� �������
P�^��F��7������^���W�F�V�F��~�y���؃��F�V��F�-�
P�v��v�V�?��뤸
P�^��w�7V�*�����F�������V�v��v�W�p	�����F��j�F��^���F��u�F��F��F��F�����F�?t�~�|��+F�;F�~�N�-�F���F�F��^��F���^����^��7�v������F��F�F�+ƉF��}�F��~�uz�~�tG�~�0uA�^��?-u9�^�O}�GS�^��F���P�^�W
����^���F��^��F����^���F��N��t#�^�O}	�GS�v��ŋ^���F��^��F���;v�v;�^�O}�GS�^��F���P�^�W
���ڋ^���F��^��F����^�����~�u�*��F��N��u���^�O}�GS�v��W
���܋^���F��^��F���ȋ�]_^�VWU����v
�F��F��N��^����+��v���t �N��F��F��+��v�ڊ���^������N��^������^��?t�F�F�F��F����^���F��]_^�VWU����v�~�n��N�^���ǙRP�v�v
�
���F�V��t4�N�F�F�ǙRP�v�v
�*
���؊���^��F�V�F
�V��N�F�F�F
�؊���^��^�?t
��F�F��F���Ƌ�]_^�
VWU��B��js(�<t�<�Eu���P�4�v
�v�4��������+�]_^�VWU����v�~�F�f
�F��Et��F�F�W�U���^���N��}u�Eu1�~�tV�E~�MW�U������*�F�=��t5��F��N����v�V�E
�P����F��~)F���~�u�M��M�F�f
+F�+��v
��]_^�VWU��v�~u�Dt�n
�^V���=��u����B�v�v�v
�D
�P�@@���؋ʉ^
�N���u���tӃ|t�F
%�D��D�d�+�]_^�VWU����v�~�F��F��F��^
�F
��F��F�r�~�rt���F��F�w�^
���F�
�t�~�bt�~�+t�F��:F�t���F��}�~�u�v��v������}:�~�u�~�t.��P�v�h�����|�~�tW�Q���v��v�U�����|p�~�t�P+�PPW�6���u�P������u	W����>�D+��D��D�D�Dp�D
��LjD
����~�wu�F����~�au�F���+���]_^�VWU��v�|u:�Du(�D
�P������t��zu�P�����D�u�D�D
��A�Du�t��zu�D�
�D
�D��D�
�D
~�D
�P���D��D�D]_^�VWU����P+�PP�v�-���؋ʉ^��N����u	���u+���F�+�.�6��‹�]_^�VWU��vV�$���V�T��]_^�VWU��v�~
W����WV�U
��]_^�VWU��h��Br�<t�4�$������]_^�VWU������v�A��]_^�VWU��v�Du����/V�/�����D
�P�\���|t�Du	�t����D��]_^�VWU��v�D��D�uI�+D���~W�t�D
�P�"����;�t�>u�|�D;u�D����D+���L����]_^�VWU��vV�����t����i�>�u
�zP�o�����D+DP�t�D
�P����؉D=u�>t�L��D믃|u�L@@룋D�D)D�<��*�]_^�VWU��P�v�>�u
�zP������D��P�F�P�D
�P�(��=��t�t�F�*���>t
�L���L@@�����]_^�VWU��v�~
W����t�����E+EH�E����*�*�]_^�VWU��P�v�~
�ƈF��E��Eu4W�:���u)�P�F�P�E
�P���=u��*���>t�M�����]_^�VWU��v�DtV�T���D;w	V������8�P�<+|�ǙRP�D
�P����؋ʃ��u
���u������D�D+�]_^�VWU����F�P�AP�v�����|��+���]_^�VWU���N�t�v
�~���u
����wB�J��]_^�VWU�츚P��P�����P��P�q���P�����]_^�VWU����>�t+���F%��F�;Fs�F�F������v�������=��u���~�v}�n��~�s��F��҃>�u���ƉF������/;6�u���F��D�F������-���E�F��u���F�-
���F���-����F��E���]_^�VWU����~u+����F%���F�;Fr�+��6����F��F��N��t$��N���uC+��~�t
�F�%�����D����;6�t�P��P�P�8�����v������u���t���F�%����F����F�;F�s��뜋F�)F��F�=s�%���F����F�����F����F����F�������D��]_^�VWU��~tE�FHH���<��s�P�P�P����'��ρ������;�t
���u�6�]_^�VWU��̀��]_^�VWU��+�P�[�����~t$��F��;�v�����V�6���>u��]_^�͆��͈��Ͷ��͓��ͅ��̓��̈́�̋܋W�G�͑�̋Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@@��[��]_^��Ë܋_��Ë܍_VWU��P�v
�~+�+�� ��������;Wrw;r+W��[��]_^�VWU��v�~
�E�E;uW������u���ƈ*�=
uW������t������*�]_^�VWU��v�F��D�D��F
�؉D�|�}�D��D
���D
���]_^�VWU��v
�D���]_^�VWU��v
�D��<��F�*�]_^�VWU��v�D���]_^�{NULL}0123456789ABCDEFatparm_/coherent/dev/kmemUsage: parms [-][c kernel_file]Bad namelist file %sCannot open %sHard drive parameters as stored in "at" driver:
drive %d  cyl=%4d  hd=%2d  spt=%2d  ctrl=%02x
Kernel memory read error%r
rjz�p�p�p�You must compile with the -f flag to include printf() floating point.
Bad pointer in malloc.
Bad pointer in free.
ahigh	
ahigh	
free_�bhigh	bhigh	main_ __a_first_�errno___a_count_�_fgetb_�
_fgetc__fpinit_�_dtefg_�Count	_stropen_dnlist_�write_|initialise_}sbrk_$open_texecute_�_stderr_�_fp_Bkfd__fopen_f
malloc_�fprintf_]exit_�fclose_�_canl_�_fgeteof_�brk_�_fputb_~_fputc_�_stdin_jenviron_ fread_D	_stdout_zatparm_"vldiv�sprintf_svlrem�strncmp_�kread_gfflush_*
String1	String2	
kfile_ panic_�vrdiv�vrrem�fseek_�	nfile_"creat_h_fputt___a_scanp_�printf_Falow	alow	lseek_pblow	blow	usage_�close_dabort_fopen_	_exit_finit_�nl_Bioctl_lread_x_fpseek_isatty_x_finish_�_fginit_p@
0707070064030106541004440000030000030000011777770507310676500005700000005110/newbits/kernel/USRSRC/i8086/drv/RCS/parms.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.24.29;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* parms.c - display hard drive parameters per "atparm" in kernel */

#include <stdio.h>
#include <l.out.h>

/*
 * For easy referencing.
 */
#define	at_table		nl[0].n_value
#define	plowner		nl[1].n_value
#define NDRIVE		2

struct dparm_s {
	unsigned short	d_ncyl;		/* number of cylinders */
	unsigned char	d_nhead;	/* number of heads */
	unsigned short	d_rwcc;		/* reduced write current cyl */
	unsigned short	d_wpcc;		/* write pre-compensation cyl */
	unsigned char	d_eccl;		/* max ecc data length */
	unsigned char	d_ctrl;		/* control byte */
	unsigned char	d_fill2[3];
	unsigned short	d_landc;	/* landing zone cylinder */
	unsigned char	d_nspt;		/* number of sectors per track */
	unsigned char	d_fill3;

}	atparm[ NDRIVE ] = {
	0				/* Initialized to allow patching */
};

/*
 * Table for namelist.
 */
struct nlist nl[] ={
	"atparm_",		0,	0,
	""
};

/*
 * Symbols.
 */
char	 *kfile;			/* Kernel data memory file */
char	 *nfile;			/* Namelist file */
int	 kfd;				/* Kernel memory file descriptor */

main(argc, argv)
char *argv[];
{
	register int i;
	register char *cp;

	initialise();
	for (i=1; i<argc; i++) {
		for (cp=&argv[i][0]; *cp; cp++) {
			switch (*cp) {
			case '-':
				continue;
			case 'c':
				if (++i >= argc)
					usage();
				nfile = argv[i];
				continue;
			default:
				usage();
			}
		}
	}
	execute();
	exit(0);
}

/*
 * Initialise.
 */
initialise()
{
	nfile = "/coherent";
	kfile = "/dev/kmem";
}

/*
 * Print out usage.
 */
usage()
{
	panic("Usage: parms [-][c kernel_file]");
}

/*
 * Display parameters
 */
execute()
{
	int dr;

	nlist(nfile, nl);
	if (nl[0].n_type == 0)
		panic("Bad namelist file %s", nfile);
	if ((kfd = open(kfile, 0)) < 0)
		panic("Cannot open %s", kfile);

	kread((long)at_table, atparm, sizeof(atparm));
	printf("Hard drive parameters as stored in \"at\" driver:\n");
	for (dr = 0;  dr < NDRIVE;  dr++) {
		printf("drive %d  cyl=%4d  hd=%2d  spt=%2d  ctrl=%02x\n",
			dr, atparm[dr].d_ncyl, atparm[dr].d_nhead,
			atparm[dr].d_nspt, atparm[dr].d_ctrl);
	}
}

/*
 * Read `n' bytes into the buffer `bp' from kernel memory
 * starting at seek position `s'.
 */
kread(s, bp, n)
long s;
{
	lseek(kfd, (long)s, 0);
	if (read(kfd, bp, n) != n)
		panic("Kernel memory read error");
}

/*
 * Print out an error message and exit.
 */
panic(a1)
char *a1;
{
	fflush(stdout);
	fprintf(stderr, "%r", &a1);
	fprintf(stderr, "\n");
	exit(1);
}
@
0707070064030106261004440000030000030000011777770507310676600005700000005737/newbits/kernel/USRSRC/i8086/drv/RCS/pccon.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.52.01;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.13.40;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.34.31;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.24.31;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Configuration table.
 * 8088 Coherent, IBM PC.
 * Minimal system.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:09:51	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:05:55	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <mtype.h>
#include <sys/stat.h>

extern	CON	nlcon[];		/* Null device */
extern	CON	ctcon[];		/* Console terminal */

/*
 * Device table.
 */
DRV	drvl[NDRV] = {
	{nlcon},	{ctcon},	{NULL },	{NULL },  /*  0 -  3 */
	{NULL },	{NULL },	{NULL },	{NULL },  /*  4 -  7 */
	{NULL },	{NULL },	{NULL },	{NULL },  /*  8 - 11 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 12 - 15 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 16 - 19 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 20 - 23 */
	{NULL },	{NULL },	{NULL },	{NULL },  /* 24 - 27 */
	{NULL },	{NULL },	{NULL },	{NULL }   /* 28 - 31 */
};

/*
 * Time.
 */
TIME timer ={
	0,				/* Initial time */
	0,				/* Ticks */
	8*60,				/* Pacific */
	1				/* Daylight saving time */
};

/*
 * Devices and sizes.
 */
dev_t	rootdev = makedev(4, 4);	/* Root device */
dev_t	pipedev = makedev(4, 4);	/* Pipe device */
dev_t	swapdev = makedev(0, 0);	/* Swap device */
daddr_t	swapbot = 0;			/* Swap base */
daddr_t	swaptop = 0;			/* Swap end */
int	ronflag	= 0;			/* Not read only root device */
int	drvn	= NDRV;			/* Maximum number of devices */
int	mactype	= M_8086;		/* Machine type */

/*
 * Flexible param's
 */
int	NCLIST	= 8;		/* 8 clists per installed tty, never run out */
int	ALLSIZE = 7*1024;	/* 7K has been reasonable */
int	NINODE	= 64;		/* More than enough so far */
int	NBUF	= 16;		/* Stingy */
@


1.3
log
@update provided by hal
@
text
@d28 2
a29 2
#include <coherent.h>
#include <con.h>
d31 1
a31 1
#include <stat.h>
@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106521004440000030000030000011777770507310676700005700000004047/newbits/kernel/USRSRC/i8086/drv/RCS/prate.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.24.36;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* prate.c - display polling rate of com[1-4] drivers */

#include <stdio.h>
#include <l.out.h>
#include <poll_clk.h>

/*
 * For easy referencing.
 */
#define	plrate		nl[0].n_value
#define	plowner		nl[1].n_value

/*
 * Table for namelist.
 */
struct nlist nl[] ={
	"poll_rate_",		0,	0,
	"poll_owner_",		0,	0,
	""
};

/*
 * Symbols.
 */
char	 *kfile;			/* Kernel data memory file */
char	 *nfile;			/* Namelist file */
int	 kfd;				/* Kernel memory file descriptor */

main(argc, argv)
char *argv[];
{
	register int i;
	register char *cp;

	initialise();
	for (i=1; i<argc; i++) {
		for (cp=&argv[i][0]; *cp; cp++) {
			switch (*cp) {
			case '-':
				continue;
			case 'c':
				if (++i >= argc)
					usage();
				nfile = argv[i];
				continue;
			default:
				usage();
			}
		}
	}
	execute();
	exit(0);
}

/*
 * Initialise.
 */
initialise()
{
	nfile = "/coherent";
	kfile = "/dev/kmem";
}

/*
 * Print out usage.
 */
usage()
{
	panic("Usage: prate [-][c kernel_file]");
}

/*
 * Display polling rate
 */
execute()
{
	int rate, owner;

	nlist(nfile, nl);
	if (nl[0].n_type == 0)
		panic("Bad namelist file %s", nfile);
	if ((kfd = open(kfile, 0)) < 0)
		panic("Cannot open %s", kfile);

	kread((long)plrate, &rate, sizeof(int));
	kread((long)plowner, &owner, sizeof(int));
	if (rate) {
		if (owner & POLL_AL)
			printf("al driver is ");
		else if (owner & POLL_HS)
			printf("hs driver is ");
		printf("polling at %d Hz\n", rate);
	} else
		printf("polling is OFF\n");
}

/*
 * Read `n' bytes into the buffer `bp' from kernel memory
 * starting at seek position `s'.
 */
kread(s, bp, n)
long s;
{
	lseek(kfd, (long)s, 0);
	if (read(kfd, bp, n) != n)
		panic("Kernel memory read error");
}

/*
 * Print out an error message and exit.
 */
panic(a1)
char *a1;
{
	fflush(stdout);
	fprintf(stderr, "%r", &a1);
	fprintf(stderr, "\n");
	exit(1);
}
@
0707070064030106511004440000030000030000011777770507310676700005400000012610/newbits/kernel/USRSRC/i8086/drv/RCS/qq.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.24.41;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/*
 * qq - sample device driver using absolute memory addressing
 *
 * All this device does is read/write video ram.
 * It assumes that there is a monochrome adapter in use, so that video
 * ram starts at segment B000;  if color, this should be changed to B800.
 *
 * This driver does not do anything useful;  it is intended to serve as
 * an example.
 *
 * Here is how to make the driver and test it (you will need a COHERENT
 * Driver Kit installed on your system):
 * 1.	put this file, "qq.c", in /usr/src/sys/i8086/drv/qq.c
 * 2.	cut out the make file and store it in /usr/src/sys/i8086/drv/Mf.qq
 * 3.	cut out the config file and store it at /usr/sys/confdrv/qq
 * 4.	execute the following commands
 *		cd /usr/src/sys/i8086/drv
 *		make -f Mf.qq
 *		cd /usr/sys
 *		ldconfig qq
 *		drvld ldrv/qq
 * 5.	the driver should now be loaded - try "date > /dev/qq" or
 *	"cat < /dev/qq" (you will have to use Ctrl-C to stop the "cat"
 *	command)
 * 6.	to unload the driver, do "ps -d" to get the PID number for the driver;
 *	then do "kill kill nnn" where nnn is the process number for "<qq>"
 */
/****
Here is the makefile for the "qq" driver (cut it out of this file):
--------------- cut here -----------------
# Make file for a loadable driver

AS=exec /bin/as
CC=exec /bin/cc
CPP=exec /lib/cpp
CFLAGS=-I.. -I../sys -I../.. -I../../sys \
	-I/usr/include/sys
AFLAGS=-gx

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USRSYS=/usr/sys

DRVOBJ=	objects/qq.o

qq: objects/qq.o
	rm -f $(USRSYS)/lib/qq.a
	ar rc $(USRSYS)/lib/qq.a objects/qq.o

objects/qq.o:				\
		$(KERINC)/coherent.h	$(SYSINC)/types.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		qq.c
	$(CC) $(CFLAGS) -c -o $@@ qq.c
--------------- cut here -----------------

Here is the configuration file for the "qq" driver.
Cut it out of this file and copy it to "/usr/sys/confdrv/qq".
When "ldconfig" is run, it will create a node for /dev/qq.
--------------- cut here -----------------
:
: 'Dummy driver for write to absolute RAM area'
:
UNDEF="${UNDEF} -u qqcon_ lib/qq.a"
PATCH="${PATCH} drvl_+70=qqcon_"
:
: devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/qq c 7  0 || exit 1
--------------- cut here -----------------
****/
#include "coherent.h"
#include "ins8250.h"
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/proc.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mmu.h>

/*
 * Definitions.
 *
 */
#define	MONOVIDEO	0xB000		/* monochrome text RAM segment */
#define	VIDLENGTH	(2048*2)	/* screen locations (2 bytes each) */

/*
 * Export Functions.
 */
int	qqload();
int	qqopen();
int	qqclose();
int	qqread();
int	qqwrite();
int	qqunload();

/*
 * Import Functions
 */
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON qqcon ={
	DFCHR,				/* Flags */
	7,				/* Major index */
	qqopen,				/* Open */
	qqclose,			/* Close */
	nulldev,			/* Block */
	qqread,				/* Read */
	qqwrite,			/* Write */
	nulldev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	qqload,				/* Load */
	qqunload,			/* Unload */
	nulldev				/* Poll */
};

/*
 * Local variables.
 */
static faddr_t	screen_fp;		/* (far *) to access screen */
static paddr_t	screen_base;		/* physical address of screen base */

/*
 * Load Routine.
 */
static qqload()
{
	/*
	 * Allocate a selector to map onto the video RAM.  ptov() will
	 * return the first available selector of the 8,192 possible.
	 * This is time consuming, so we only want to do this as part
	 * of our initialization code and not on every access.
	 *
	 * Since we are operating in 286 protected mode (ugh), the
	 * second argument to ptov() must not exceed 0x10000L.
	 */
	screen_base = (paddr_t)((long)(unsigned)MONOVIDEO << 4);
	screen_fp = ptov(screen_base, (fsize_t)VIDLENGTH);
}

static qqunload()
{
	/*
	 * We have to free up the selector now that we're done using it.
	 */
	vrelse(screen_fp);
}

/*
 * Open Routine.
 */
qqopen( dev, mode )
dev_t dev;
{
}

/*
 * Close Routine.
 */
qqclose( dev )
dev_t dev;
{
}

/*
 * Read Routine.
 */
qqread( dev, iop )
dev_t dev;
register IO * iop;
{
	static int offset;
	int c;
	/*
	 * Read a character code from video RAM
	 * Start reading RAM just after where previous read ended
	 *
	 * Note that "offset" is the value of the displacement into
	 * the screen RAM. Any expression which results in a value
	 * which is less than VIDLENGTH is OK here.
	 */
	while(iop->io_ioc) {
		c = ffbyte(screen_fp + offset); /* fetch a "far" byte */
		if(ioputc(c, iop) == -1)
			break;
		offset += 2;
		offset %= VIDLENGTH;
	}
}

/*
 * Write Routine.
 */
qqwrite( dev, iop )
dev_t dev;
register IO * iop;
{
	int offset = 0;
	int c;

	/*
	 * Write a character into the screen RAM
	 * Note that "offset" is the value of the displacement into
	 * the screen RAM. Any expression which results in a value
	 * which is less than VIDLENGTH is OK here.
	 */
	while ((c = iogetc(iop)) >= 0 && offset < VIDLENGTH) {
		sfbyte(screen_fp + offset, c);	   /* store a "far" byte */
		offset += 2;	/* skip attribute byte */
	}
}
@
0707070064030106501004440000030000030000011777770507310677100005400000015475/newbits/kernel/USRSRC/i8086/drv/RCS/rp.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.24.49;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/*
 *	Ram Pipe Device Driver
 */

#include <coherent.h>
#include <con.h>
#include <seg.h>
#include <stat.h>
#include <sched.h>
#include <termio.h>
#include <v7sgtty.h>
#include <uproc.h>
#include <errno.h>

#define	MAXNRP	30		/* Maximum number of ram pipes (must be < 32) */
#define	NCPQ	2048		/* Size of pipe in bytes */
#define	RPMAJOR 22		/* Major device for ram pipes  */

/*
 *	function definitions
 */
int	rpopen();
int	rpread();
int	rpwrite();
int	rpioctl();
int	rppoll();
void	rpuload();
int	nulldev();
int	nonedev();


/*
 *	configuration table
 */
CON rpcon = {
	DFCHR|DFPOL,			/* flags	*/
	RPMAJOR,			/* major index	*/
	rpopen,				/* open		*/
	nulldev,			/* close	*/
	nonedev,			/* block	*/
	rpread,				/* read		*/
	rpwrite,			/* write	*/
	rpioctl,			/* ioctl	*/
	nulldev,			/* power fail	*/
	nulldev,			/* timeout	*/
	nulldev,			/* load		*/
	rpuload,			/* unload	*/
	rppoll				/* poll		*/
};

/*
 *	Ram Pipe Headers
 */
static
struct ring {
	unsigned short	q_size;		/* Number of characters in queue    */
	unsigned short	q_mask;		/* Ring buffer Mask: NCPQ-1	    */
	faddr_t		q_ifaddr;	/* Input virtual address	    */
	faddr_t		q_ofaddr;	/* Output virtual address	    */
	GATE		q_igate;	/* Read lock			    */
	GATE		q_ogate;	/* Write lock			    */
	event_t		q_ipoll;	/* Input polls			    */
	event_t		q_opoll;	/* Output polls			    */

} rpq[MAXNRP];

static SEG * rpsegp;
unsigned NRP = MAXNRP;

/*
 * Initialization Routine
 */
static
rpinit()
{
	register struct ring *rp;
	faddr_t faddr;
	paddr_t paddr;

	/*
	 * Ensure valid number of ram pipes
	 */
	if ( NRP > MAXNRP )
		NRP = MAXNRP;
		
	/*
	 * Allocate ram pipe segment, initialize ram pipe queues
	 */
	 if ( NRP != 0 ) {
		rpsegp = salloc((fsize_t)NRP*NCPQ, SFSYST|SFHIGH|SFNSWP|SFNCLR);

		if ( rpsegp == NULL )
			return -1;

		paddr = rpsegp->s_paddr;

		for ( rp = &rpq[0]; rp < &rpq[NRP]; rp++, paddr += NCPQ ) {

			faddr = ptov( paddr, (fsize_t)NCPQ );
			rp->q_size = 0;
			rp->q_mask = NCPQ - 1;

			rp->q_ifaddr = faddr;
			rp->q_ofaddr = faddr;
		}
	}
	return 0;
}

/*
 * Unload Routine.
 */
static void
rpuload()
{
	register struct ring *rp;

	/*
	 * Release virtual address mappers.
	 */
	for ( rp = &rpq[0]; rp < &rpq[NRP]; rp++ ) {
		if ( rp->q_ifaddr )
			vrelse( rp->q_ifaddr );
	}

	/*
	 * Release ring buffer storage.
	 */
	if ( rpsegp != NULL ) {
		sfree( rpsegp );
		rpsegp = NULL;
	}

	/*
	 * Erase private data.
	 */
	memset( &rpq[0], 0, sizeof(rpq) );
}

/*
 * Open Routine
 */
static
rpopen( dev, mode )
dev_t dev;
{
	int s;

	s = sphi();
	if ( rpq[0].q_mask == 0 )
		if ( rpinit() < 0 )
			u.u_error = ENOSPC;
	spl( s );
	if ( minor(dev) >= NRP )
		u.u_error = ENXIO;
}

/*
 * Ioctl Routine
 */
static
rpioctl( dev, com, vec )
dev_t dev;
{
	switch ( com ) {

	case TIOCQUERY:
		putuwd( vec, rpq[ minor(dev) ].q_size );
		return;

	case TIOCOUTQ:
		putuwd( vec, rpq[ minor(dev) ].q_size );
		return;

	case TIOCFLUSH:
	case TCFLSH:
		rpflush( &rpq[minor(dev)] );
		return;

	default:
		u.u_error = EINVAL;
		return;
	}
}

/*
 * Read Routine
 */
static
rpread( dev, iop )
dev_t dev;
register IO *iop;
{
	register struct ring *rp;
	unsigned n;
	int s;

	rp = &rpq[ minor(dev) ];
	s  = sphi();

	/*
	 * Wait until read is unlocked, and there is data to read
	 */
	while ( (rp->q_igate[0] != 0) || ((n = rp->q_size) == 0) ) {

		/*
		 * Non-blocking reads.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			return;
		}

		++rp->q_igate[1];
		sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT );
		--rp->q_igate[1];

		if ( SELF->p_ssig && nondsig() ) {	/* signal received */

			spl( s );
			u.u_error = EINTR;
			return;
		}
	}
	rp->q_igate[0] = 1;			/* lock read gate	    */
	spl( s );

	if ( n > iop->io_ioc )			/* more data than requested */
		n = iop->io_ioc;

	rucopy( rp, iop->io_base, n );		/* copy data to user space  */
	iop->io_base += n;
	iop->io_ioc  -= n;

	if ( rp->q_ogate[1] != 0 )		/* someone waiting to write */
		wakeup( rp->q_ogate );
	if ( rp->q_opoll.e_procp )		/* someone polling to write */
		pollwake( &rp->q_opoll );

	rp->q_igate[0] = 0;			/* unlock read gate	    */

	if ( rp->q_igate[1] != 0 )		/* others waiting to read   */
		wakeup( rp->q_igate );
}

/*
 * Write Routine
 */
static
rpwrite( dev, iop )
dev_t dev;
register IO *iop;
{
	register struct ring *rp;
	unsigned n;
	int s;

	rp = &rpq[ minor(dev) ];

	do {
		s  = sphi();
		/*
		 * Wait until write is unlocked and 512 free slots exist
		 */

		while ((rp->q_ogate[0] != 0) || ((n = NCPQ-rp->q_size) < 512)) {

			/*
			 * Non-blocking writes.
			 */
			if ( iop->io_flag & IONDLY ) {
				u.u_error = EAGAIN;
				return;
			}

			++rp->q_ogate[1];
			sleep( rp->q_ogate, CVTTOUT, IVTTOUT, SVTTOUT );
			--rp->q_ogate[1];

			if (SELF->p_ssig && nondsig()) { /* received signal */

				spl( s );
				u.u_error = EINTR;
				return;
			}
		}
		rp->q_ogate[0] = 1;		/* lock write gate	     */
		spl( s );

		if ( n > iop->io_ioc )
			n = iop->io_ioc;

		urcopy( iop->io_base, rp, n );	/* copy data from user space */
		iop->io_base += n;
		iop->io_ioc  -= n;

		rp->q_ogate[0] = 0;		/* unlock write gate	     */

		if ( rp->q_igate[1] != 0 )	/* someone waiting to read   */
			wakeup( rp->q_igate );

		if ( rp->q_ipoll.e_procp )	/* someone polling to read */
			pollwake( &rp->q_ipoll );

	} while ( iop->io_ioc != 0 );		/* until all data copied     */

	if (rp->q_ogate[1] != 0)		/* someone waiting to write  */
		wakeup( rp->q_ogate );
}

/*
 * Poll.
 */
rppoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	register struct ring *rp = &rpq[ minor(dev) ];

	ev &= ~POLLPRI;

	/*
	 * Input poll.
	 */
	if ( ev & POLLIN ) {

		/*
		 * Pipe empty.
		 */
		if ( FP_OFF(rp->q_ifaddr) == FP_OFF(rp->q_ofaddr) ) {
			if ( msec != 0 )
				pollopen( &rp->q_ipoll );
			ev &= ~POLLIN;
		}
	}

	/*
	 * Output poll.
	 */
	if ( ev & POLLOUT ) {

		/*
		 * Pipe not empty.
		 */
		if ( FP_OFF(rp->q_ifaddr) != FP_OFF(rp->q_ofaddr) ) {
			if ( msec != 0 )
				pollopen( &rp->q_opoll );
			ev &= ~POLLOUT;
		}
	}

	return ev;
}

/*
 * Flush queue
 */
static
rpflush( rp )
register struct ring *rp;
{
	register int s;

	s = sphi();

	/*
	 * Wait until read is unlocked, or nothing in queue
	 */

	while ((rp->q_size != 0) && (rp->q_igate[0] != 0) ) {

		++rp->q_igate[1];
		sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT );
		--rp->q_igate[1];

		if (SELF->p_ssig && nondsig()) { /* received signal	   */

			spl( s );
			u.u_error = EINTR;
			return;
		}
	}

	if (rp->q_size != 0) {			/* flush ram pipe	   */

		rp->q_ofaddr = rp->q_ifaddr;
		rp->q_size = 0;
	}
	spl( s );

	if (rp->q_ogate[1] != 0)		/* someone waiting to write */
		wakeup( rp->q_ogate );

	if ( rp->q_opoll.e_procp )		/* someone polling to write */
		pollwake( &rp->q_opoll );
}
@
0707070064030106471004440000030000030000011777770507310677300005600000005556/newbits/kernel/USRSRC/i8086/drv/RCS/rpas.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.24.52;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@////////
/
/ Ram Pipe Device Driver Assembler Support
/
/	urcopy( up, np, n )	-- copy user data to pipe
/	rucopy( np, up, n )	-- copy pipe data to user
/
////////

	.globl	urcopy_
	.globl	rucopy_

////////
/
/ Offsets of fields within the ram pipe structure
/
////////

	Q_SIZE	= 0
	Q_MASK	= 2
	Q_IX	= 4
	Q_ISEG	= 6
	Q_OX	= 8
	Q_OSEG	= 10
	Q_IGATE	= 12
	Q_OGATE	= 14

////////
/
/ Urcopy ( up, rp, cnt )
/ char * up;
/ struct ring * rp;
/ unsigned cnt;
/
/	Input:	up  = pointer to user data to copy.
/		rp  = pointer to ring structure to copy data to.
/		cnt = number of data bytes to copy.
/
/	Action:	Copy CNT bytes from UP to RP->Q_IX.
/
/	Return:	Number of bytes transferred.
/
////////

urcopy_:				/ urcopy ( up, rp, cnt )
	push	si			/ register char *up;		/* SI */
	push	di			/ register struct ring *rp;	/* BX */
	push	bp			/ unsigned cnt;
	mov	bp, sp			/ {
	pushf				/	register char *cp;	/* DI */
	push	ds			/	register unsigned ret;	/* AX */
	push	es			/	register unsigned n;	/* CX */
					/	register unsigned m;	/* DX */
	mov	si, 8(bp)		/
	mov	bx, 10(bp)		/
	mov	cx, 12(bp)		/	n  = cnt;
	mov	dx, Q_MASK(bx)		/	m  = rp->q_mask;
	les	di, Q_IX(bx)		/	cp = rp->q_ix;
	mov	ds, uds_		/
					/
	cld				/
0:	movsb				/	do {	*cp++ = *up++;
	and	di, dx			/		wrap(cp);
	loop	0b			/	} while (--n != 0);
					/
	pop	es			/
	pop	ds			/
	mov	ax, 12(bp)		/	ret = cnt;
	cli				/	s   = sphi();
	mov	Q_IX(bx), di		/	rp->q_ix = cp;
	add	Q_SIZE(bx), ax		/	rp->q_size += ret;
	popf				/	spl( s );
	pop	bp			/
	pop	di			/	return ret;
	pop	si			/
	ret				/ }

////////
/
/ Rucopy ( rp, up, cnt )
/ struct ring * rp;
/ char * up;
/ unsigned cnt;
/
/	Input:	rp  = pointer to ring structure to copy data from.
/		up  = pointer to user data.
/		cnt = number of data bytes to copy.
/
/	Action:	Copy CNT bytes from RP->Q_OX to UP.
/
/	Return:	None.
/
////////

rucopy_:				/ rucopy ( rp, up, cnt )
	push	si			/ register struct ring *rp;	/* BX */
	push	di			/ register char * up;		/* DI */
	push	bp			/ unsigned cnt;
	mov	bp, sp			/ {
	pushf				/	register char *cp;	/* SI */
	push	ds			/	register unsigned ret;	/* AX */
	push	es			/	register unsigned n;	/* CX */
					/	register unsigned m;	/* DX */
	mov	bx, 8(bp)		/
	mov	di, 10(bp)		/
	mov	cx, 12(bp)		/
	mov	dx, Q_MASK(bx)		/	m = rp->q_mask;
	mov	es, uds_		/
	lds	si, Q_OX(bx)		/	cp = rp->q_ox;
					/
	cld				/
0:	movsb				/	do {	*up++ = *cp++;
	and	si, dx			/		wrap(cp);
	loop	0b			/	} while (--cnt != 0);
					/
	pop	es			/
	pop	ds			/
	mov	ax, 12(bp)		/	ret = cnt;
	cli				/	s   = sphi();
	mov	Q_OX(bx), si		/	rp->q_ox = cp;
	sub	Q_SIZE(bx), ax		/	rp->q_size -= ret;
	popf				/	spl( s );
	pop	bp			/
	pop	di			/	return ret;
	pop	si			/
	ret				/ }
@
0707070064030104241004440000030000030000011777770507310677300005400000051350/newbits/kernel/USRSRC/i8086/drv/RCS/rs.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.52.27;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.24.54;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Raw Serial Device Driver.
 *
 *	Provides fast, efficiently buffered serial i/o to COM1 & COM2.
 *	Supports an extreme subset of System V (termio) parameters.
 *		c_iflag: ISTRIP, IXON, IXANY, IGNBRK, INPCK, PARMRK, IGNPAR.
 * 		c_oflag: OPOST, ONLCR, ONLRET, TAB3.
 *		c_cflag: *.
 *
 */

#include <sys/coherent.h>
#include <sys/ins8250.h>
#include <sys/proc.h>
#include <sys/uproc.h>
#include <sys/con.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <termio.h>
#include <errno.h>

#define	COM1VEC		4		/* interrupt vector for COM1	*/
#define	COM2VEC		3		/* interrupt vector for COM2	*/

#define	COM1PORT	0x3F8		/* i/o port address for COM1	*/
#define	COM2PORT	0x2F8		/* i/o port address for COM2	*/

#ifdef	RS1
#	define	CFLAG	RS1CFLAG
#	define	MAJ	6		/* major device for /dev/rs1	*/
#	define	rscon	rs1con		/* configuration table for "	*/
#	define	rstty	rs1tty
#	define	IVEC	COM2VEC		/* interrupt vector for rs1	*/
#	define	PORT	COM2PORT	/* i/o port address for rs1	*/
#else
#	define	CFLAG	RS0CFLAG
#	define	MAJ	5		/* major device for /dev/rs0	*/
#	define	rscon	rs0con		/* configuration table for "	*/
#	define	rstty	rs0tty
#	define	IVEC	COM1VEC		/* interrupt vector for rs0	*/
#	define	PORT	COM1PORT	/* i/o port address for rs0	*/
#endif

#define	CTRLS	'\023'
#define	CTRLQ	'\021'

/*
 * Functions.
 */

int	rsload();
int	rsunload();
int	rsopen();
int	rsclose();
int	rsread();
int	rswrite();
int	rsioctl();
int	rspoll();
int	nulldev();
int	nonedev();

int	rsintr();
int	rsparam();

/*
 * Configuration table.
 */

CON rscon ={
	DFCHR|DFPOL,			/* Flags */
	MAJ,				/* Major index */
	rsopen,				/* Open */
	rsclose,			/* Close */
	nulldev,			/* Block */
	rsread,				/* Read */
	rswrite,			/* Write */
	rsioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	rsload,				/* Load */
	rsunload,			/* Unload */
	rspoll				/* Poll */
};

/*
 * Terminal structure.
 */

#define	RAWSZ	(2048-1)
#define	OUTSZ	(2048-1)

#define	NRAWC	((rsrawq.rq_ix - rsrawq.rq_ox) & RAWSZ)
#define	NOUTC	((rsoutq.rq_ix - rsoutq.rq_ox) & OUTSZ)

#define	TTSTOP	00001
#define	TTSBRK	00002
#define	CARRIER	00004

typedef
struct rawtty_s {
	unsigned	rt_state;	/* terminal state		*/
	int		rt_group;	/* controlling process group	*/
	unsigned	rt_ticks;	/* send break 1/10 sec counter	*/
	unsigned	rt_iflag;	/* termio input   flags		*/
	unsigned	rt_oflag;	/* termio output  flags		*/
	unsigned	rt_cflag;	/* termio control flags		*/
	unsigned char	rt_col;		/* current output column	*/
	unsigned char	rt_refc;	/* # procs accessing the port	*/
	unsigned char	rt_irefc;	/* # procs waiting for input	*/
	unsigned char	rt_orefc;	/* # procs waitint for output	*/
	unsigned char	rt_crefc;	/* # procs waiting for carrier	*/
	unsigned char	rt_drefc;	/* # procs waiting for drain	*/
	event_t		rt_ipolls;	/* Procs polling on input queue	*/
	event_t		rt_opolls;	/* Procs polling on output que  */
} RAWTTY;

typedef
struct iring_s {
	unsigned short	rq_mask;
	unsigned short	rq_ix;
	unsigned short	rq_ox;
	unsigned char	rq_cc[RAWSZ+1];
} IRING;

typedef
struct oring_s {
	unsigned short	rq_mask;
	unsigned short	rq_ix;
	unsigned short	rq_ox;
	unsigned char	rq_cc[OUTSZ+1];
} ORING;

/*
 * Local variables.
 */
unsigned CFLAG  = CLOCAL | CREAD | B1200 | CS8 | HUPCL;
RAWTTY	rstty;
static ORING	rsoutq;
static IRING	rsrawq;
static TIM	rstim;

/*
 * Time constant table.
 * Indexed by ioctl baud rate.
 */
static
int timeconst[] = {
	0,				/* 0 */
	2304,				/* 50 */
	1536,				/* 75 */
	1047,				/* 110 */
	857,				/* 134.5 */
	768,				/* 150 */
	576,				/* 200 */
	384,				/* 300 */
	192,				/* 600 */
	96,				/* 1200 */
	64,				/* 1800 */
	48,				/* 2400 */
	24,				/* 4800 */
	12,				/* 9600 */
	6,				/* 19200/EXTA */
	6				/* 19200/EXTB */
};

/*
 * Rsload() -- Raw Serial Load Routine.
 *
 *	Action:	Define terminal parameters.
 *		Initialize terminal hardware.
 *		If serial port exists, seize its interrupt vector.
 *
 *	Return:	None.
 */

static
rsload()
{
	/*
	 * Initialize terminal parameters.
	 */
	rsoutq.rq_mask = OUTSZ;
	rsrawq.rq_mask = RAWSZ;

	/*
	 * Initialize terminal hardware.
	 */
	rsparam();

	/*
	 * If serial port exists, initialize interrupt vector.
	 */
	if ( inb(PORT+IER) == 0 ) {
		setivec( IVEC, rsintr);
		rscycle();
	}
}

/*
 * Rsunload() -- Raw Serial unload Routine.
 */

static
rsunload()
{
	timeout( &rstim, 0, NULL, 0 );	/* cancel timed function */
	clrivec( IVEC );		/* release interrupt vector */
	outb(PORT+IER, 0);		/* disable port interrupts */
	outb(PORT+MCR, MC_OUT2);	/* hangup port */
}

/*
 * Rsopen -- Open Routine.
 *
 *	Input:	dev = device to open.
 *		If high bit (0x80) set in minor, modem control is requested.
 *
 *	Action:	Validate minor device.
 *		Increment reference count.
 *		If first reference and parameters are not initialized,
 *			set default parameters and initialize hardware.
 *
 *	Return:	None.
 */

static
rsopen( dev, mode )

dev_t dev;

{
	register PROC *pp = SELF;

	/*
	 * Validate minor device.
	 */
	if (minor(dev) & ~0x80) {
		u.u_error = ENODEV;
		return;
	}

	/*
	 * Validate hardware.
	 */
	if (inb(PORT+IER) & ~(IE_RxI|IE_TxI|IE_LSI)) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Ensure controlling terminal and group fields initialized.
	 */
	if (pp->p_ttdev == NODEV)
		pp->p_ttdev = dev;
	if (pp->p_group == 0)
		pp->p_group = pp->p_pid;

	/*
	 * Check for first open.
	 */
	if (++rstty.rt_refc == 1) {

		if (pp->p_group == pp->p_pid)
			rstty.rt_group = pp->p_group;

		if ((rstty.rt_cflag & CBAUD) == B0) {

			/*
			 * Define terminal parameters.
			 */
			rstty.rt_state = 0;
			rstty.rt_col   = 0;
			rstty.rt_iflag = ISTRIP | IXON;
			rstty.rt_oflag = OPOST  | ONLCR | TAB3;
			rstty.rt_cflag = CFLAG;
			if ( minor(dev) & 0x80 )
				rstty.rt_cflag &= ~CLOCAL;

			/*
			 * Initialize terminal hardware.
			 */
			rsparam();
		}

		/*
		 * Discard input data.
		 */
		rsrawq.rq_ox = rsrawq.rq_ix;
	}

	/*
	 * If modem control is requested, check carrier.
	 */
	if ( minor(dev) & 0x80 ) {

		/*
		 * Delay until carrier is present.
		 */
		while ( (rstty.rt_state & CARRIER) == 0 ) {

			/*
			 * Sleep on carrier.
			 */
			++rstty.rt_crefc;
			sleep( &rstty.rt_crefc,
				CVTTOUT, IVTTOUT, SVTTOUT);
			--rstty.rt_crefc;

			/*
			 * Abort if non-ignored signal is received.
			 */
			if (SELF->p_ssig && nondsig()) {

				if (--rstty.rt_refc == 0) {
					rstty.rt_group = 0;
					rstty.rt_cflag = 0;
					rsparam();
				}
				u.u_error = EINTR;
				return;
			}
		}
	}
}

/*
 * Rsclose -- Close Routine.
 *
 *	Action:	Decrement reference count.
 *		If serial port is no longer referenced,
 *		and the hangup on last close bit is set in rt_cflag,
 *		clear terminal parameters, and initialize hardware.
 *
 *	Return:	None.
 *
 *	Note:	This routine does not wait for the output queue to empty.
 */

static
rsclose( dev )

dev_t dev;

{
	/*
	 * Check for last close and hangup on close.
	 */
	if ((rstty.rt_refc == 1) && (rstty.rt_cflag & HUPCL)) {

		/*
		 * Wait for output to drain.
		 */
		while ( rsoutq.rq_ox != rsoutq.rq_ix ) {

			++rstty.rt_drefc;
			sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT );
			--rstty.rt_drefc;

			if (rstty.rt_refc != 1) {
				rstty.rt_refc--;
				return;
			}

			if (SELF->p_ssig && nondsig())
				break;
		}

		/*
		 * Initialize terminal hardware.
		 */
		rstty.rt_group = 0;
		rstty.rt_cflag = 0;
		rsparam();

		/*
		 * Flush input and output queues.
		 */
		rsrawq.rq_ix =
		rsrawq.rq_ox =
		rsoutq.rq_ox =
		rsoutq.rq_ix = 0;
	}
	--rstty.rt_refc;
}

/*
 * Rsread -- Read Routine.
 *
 *	Input:	iop = pointer to structure containing i/o parameters.
 *
 *	Action:	Attempt to read data from input buffer until at least
 *		one character has been read, or a signal is received
 *		by the current process.
 *		Update the parameters in the io structure.
 *		If a signal is received, set errno to EINTR.
 *
 *	Return:	None.
 */

static
rsread( dev, iop )

dev_t dev;
register IO *iop;

{
	register int sioc;

	/*
	 * Remember original char count.
	 */
	sioc = iop->io_ioc;

	do {
		/*
		 * Transfer data until done or input buffer empty.
		 */
		rsin( &rsrawq, iop );

		/*
		 * Return if some data was transferred.
		 */
		if (sioc != iop->io_ioc)
			return;

		/*
		 * Non-blocking reads.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			return;
		}

		/*
		 * Sleep waiting for a signal or input data.
		 */
		++rstty.rt_irefc;
		sleep( &rstty.rt_irefc, CVTTOUT, IVTTOUT, SVTTOUT );
		--rstty.rt_irefc;

		/*
		 * Abort if a non-ignored signal was received.
		 */
		if (SELF->p_ssig && nondsig()) {
			u.u_error = EINTR;
			return;
		}

	} while (1);
}

/*
 * Rswrite -- Write Routine.
 */

static
rswrite( dev, iop )

dev_t dev;
register IO *iop;

{
	register int n;

	/*
	 * Non-blocking write.
	 */
	if ( iop->io_flag & IONDLY ) {

		/*
		 * Calculate free slots.
		 */
		n  = rsoutq.rq_mask - rsoutq.rq_ix + rsoutq.rq_ox;
		n &= rsoutq.rq_mask;

		/*
		 * Insufficient space.
		 */
		if ( n <= iop->io_ioc ) {
			u.u_error = EAGAIN;
			return;
		}
	}

	do {
		/*
		 * Transfer data until done or output queue full.
		 */
		rsout( &rsoutq, iop );

		/*
		 * Make sure the transmitter is operating.
		 */
		rsstart();

		/*
		 * Return if all data was transferred.
		 */
		if ( iop->io_ioc == 0 )
			return;

		/*
		 * Sleep waiting for a signal or room in the output queue.
		 */
		++rstty.rt_orefc;
		sleep( &rstty.rt_orefc, CVTTOUT, IVTTOUT, SVTTOUT );
		--rstty.rt_orefc;

		/*
		 * Abort if a non-ignored signal was received.
		 */
		if ( SELF->p_ssig && nondsig() ) {
			u.u_error = EINTR;
			return;
		}

	} while (1);
}

/*
 * Rspoll -- Polling Routine.
 */
static int
rspoll( dev, ev, msec )
dev_t dev;
register int ev;
int msec;
{
	/*
	 * No priority reports.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll with empty input ring.
	 */
	if ( (ev & POLLIN) && (rsrawq.rq_ix == rsrawq.rq_ox) ) {

		/*
		 * Blocking input poll.
		 */
		if ( msec != 0 )
			pollopen( &rstty.rt_ipolls );

		/*
		 * Second look and clear input report.
		 */
		if ( rsrawq.rq_ix == rsrawq.rq_ox )
			ev &= ~POLLIN;
	}

	/*
	 * Output poll with non-empty output ring.
	 */
	if ( (ev & POLLOUT) && (rsoutq.rq_ix != rsrawq.rq_ox) ) {

		/*
		 * Blocking output poll.
		 */
		if ( msec != 0 )
			pollopen( &rstty.rt_opolls );

		/*
		 * Second look and clear output report.
		 */
		if ( rsoutq.rq_ix != rsoutq.rq_ox )
			ev &= ~POLLOUT;
	}

	return ev;
}

/*
 * Cyclic [1 sec] Routine.
 */
static
rscycle()
{
	register PROC *pp;
	register int b;

	/*
	 * Check for carrier transitions.
	 */
	if ( inb( PORT + MSR ) & MS_RLSD ) {

		/*
		 * Have carrier.  Wake processes waiting for carrier.
		 */
		rstty.rt_state |= CARRIER;

		if ( rstty.rt_crefc )
			wakeup( &rstty.rt_crefc );
	}
	else if ((rstty.rt_state & CARRIER) && (rstty.rt_cflag&CLOCAL) == 0) {

		/*
		 * Lost carrier. Signal attached processes.
		 */
		rstty.rt_state &= ~CARRIER;

		if (rstty.rt_refc && (b = rstty.rt_group))
			for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw)
				if ( pp->p_group == b )
					sendsig( SIGHUP, pp );
	}

	/*
	 * Wakeup processes waiting to read if input data present.
	 */
	if ( rsrawq.rq_ix != rsrawq.rq_ox ) {
		if ( rstty.rt_irefc )
			wakeup( &rstty.rt_irefc );
		if ( rstty.rt_ipolls.e_procp )
			pollwake( &rstty.rt_ipolls );
	}

	/*
	 * Check for break being sent.
	 */
	if ( rstty.rt_ticks != 0 ) {

		if ( --rstty.rt_ticks == 0 ) {

			b = inb( PORT + LCR );
			outb( PORT + LCR, b & ~LC_SBRK );
			rstty.rt_state &= ~TTSBRK;
		}
	}

	/*
	 * Can check output if not sending break.
	 */
	if ( rstty.rt_ticks == 0 ) {

		/*
		 * Restart output if necessary.
		 */
		if ( rsoutq.rq_ox != rsoutq.rq_ix )
			rsstart();

		/*
		 * Wakeup processes waiting for drain if output queue empty.
		 */
		if ( rstty.rt_drefc ) {
			if ( rsoutq.rq_ix == rsoutq.rq_ox )
				wakeup( &rstty.rt_drefc );
		}

		/*
		 * Wakeup processes waiting to write if 512 slots are free.
		 */
		else if ( NOUTC < OUTSZ-512 ) {
			if ( rstty.rt_orefc )
				wakeup( &rstty.rt_orefc );
			if ( rstty.rt_opolls.e_procp )
				pollwake( &rstty.rt_opolls );
		}
	}

	timeout( &rstim, HZ/10, rscycle, 0 );
}

/*
 * Rsintr -- Serial Interrupt Handler.
 *
 *	Action:	Process all pending interrupt service requests
 *		on the serial port.
 *
 *	Return:	None.
 *
 *	Notes:	This routine must loop until all requests are serviced
 *		because of the edge sensitive nature of the programmable
 *		interrupt controller.
 */

static
rsintr()
{
	register int b;

	/*
	 * Service serial port interrupt requests, highest to lowest priority.
	 */
rescan:
	b = inb( PORT + IIR );

	switch ( b ) {

	case LS_INTR:
		/*
		 * Get line status (clear interrupt).
		 */
		b = inb( PORT + LSR );

		/*
		 * Check for received break.
		 */
		if (b & LS_BREAK) {

			/*
			 * Read the break char ('\0').
			 */
			rsrawq.rq_cc[ rsrawq.rq_ix ] = inb( PORT + DREG );

			/*
			 * Clear output stops.
			 */
			rstty.rt_state &= ~TTSTOP;

			/*
			 * Update input index if not ignoring break.
			 */
			if ((rstty.rt_iflag & IGNBRK) == 0) {
				rsrawq.rq_ix ++;
				rsrawq.rq_ix &= RAWSZ;
			}
		}

		/*
		 * Special handling if frame/parity error and checking enabled.
		 */
		if ((b & (LS_FRAME|LS_PARITY)) && (rstty.rt_iflag & INPCK)) {

			/*
			 * Ignore next input char if IGNPAR set.
			 */
			if (rstty.rt_iflag & IGNPAR)
				inb( PORT + DREG );
			/*
			 * Change next input char into 0377,0,ch if PARMRK set.
			 */
			else if (rstty.rt_iflag & PARMRK) {

				b = rsrawq.rq_ix;
				rsrawq.rq_cc[ b++ ] = 0377;
				b &= RAWSZ;
				rsrawq.rq_cc[ b++ ] = '\0';
				b &= RAWSZ;
				rsrawq.rq_cc[ b++ ] = inb( PORT + DREG );
				b &= RAWSZ;
				rsrawq.rq_ix = b;
			}

			/*
			 * Otherwise change next input char into null.
			 */
			else {
				inb( PORT + DREG );
				rsrawq.rq_cc[ rsrawq.rq_ix++ ] = '\0';
				rsrawq.rq_ix &= RAWSZ;
			}
		}
		goto rescan;

	case Rx_INTR:
		/*
		 * Read character from receive buffer.
		 */
		b = inb( PORT + DREG );

		/*
		 * Discard high bit if ISTRIP set.
		 */
		if ( rstty.rt_iflag & ISTRIP )
			b &= 0177;

		/*
		 * Check for output flow control if IXON set.
		 */
		if ( rstty.rt_iflag & IXON ) {

			/*
			 * Stop output if Ctl-S.
			 */
			if ( b == CTRLS ) {
				rstty.rt_state |= TTSTOP;
				goto rescan;
			}

			/*
			 * Resume output if Ctl-Q.
			 */
			if ( b == CTRLQ ) {
				rstty.rt_state &= ~TTSTOP;
				goto rescan;
			}

			/*
			 * Enable output if IXANY set.
			 */
			if ( rstty.rt_iflag & IXANY )
				rstty.rt_state &= ~TTSTOP;
		}

		/*
		 * Save the character in the input queue.
		 */
		rsrawq.rq_cc[ rsrawq.rq_ix++ ] = b;
		rsrawq.rq_ix &= RAWSZ;

		/*
		 * Save again if 0377 and parity marking enabled.
		 */
		if ((b == 0377)
		&&  ((rstty.rt_iflag & (INPCK|PARMRK)) == (INPCK|PARMRK))) {

			rsrawq.rq_cc[ rsrawq.rq_ix++ ] = b;
			rsrawq.rq_ix &= RAWSZ;
		}

		goto rescan;

	case Tx_INTR:
		rsstart();
		goto rescan;
	}
}

/*
 * Rsstart()
 *
 *	Action:	While output data is available, and the transmitter buffer
 *		is empty, transfer one character from the output queue to the
 *		transmit buffer.
 *
 *	Return:	None.
 */

static
rsstart()
{
	register int b;
	register int s;

	/*
	 * Can't transmit if output stopped or sending break.
	 */
	if ( rstty.rt_state & (TTSTOP|TTSBRK) )
		return;

	/*
	 * Can't transmit if modem control enabled without CTS present.
	 */
	if ( (rstty.rt_cflag & CLOCAL) == 0 )
		if ( (inb(PORT+MSR) & MS_CTS) == 0 )
			return;

	/*
	 * Disable interrupts to avoid critical race.
	 */
	s = sphi();

	/*
	 * Can transmit if output data available and transmit buffer empty.
	 */
	if ( (rsoutq.rq_ix != rsoutq.rq_ox)
	&&   (inb(PORT+LSR) & LS_TxRDY)	) {

		/*
		 * Get next char from output queue.
		 */
		b = rsoutq.rq_cc [ rsoutq.rq_ox ];

		if (rstty.rt_oflag & OPOST) {

			/*
			 * Printable characters increment the column.
			 */
			if (b >= ' ') {
				rstty.rt_col++;
			}
			/*
			 * Carriage return resets the column.
			 */
			else if (b == '\r') {
				rstty.rt_col = 0;
				if (rstty.rt_oflag & OCRNL)
					b = '\n';
			}
			/*
			 * New-line may also generate a carriage return.
			 */
			else if (b == '\n') {
				if (rstty.rt_oflag & ONLCR) {
					if (rstty.rt_col) {
						rstty.rt_col = 0;
						rsoutq.rq_ox--;
						b = '\r';
					}
				}
				else if (rstty.rt_oflag & ONLRET)
					rstty.rt_col = 0;
			}
			/*
			 * Backspace decrements the column.
			 */
			else if (b == '\b') {
				if (rstty.rt_col)
					--rstty.rt_col;
			}
			/*
			 * Tabs may generate spaces, always move to tab stop.
			 */
			else if (b == '\t') {
				if ((rstty.rt_oflag & TABDLY) == TAB3) {
					b = ' ';
					if (++rstty.rt_col & 7)
						rsoutq.rq_ox--;
				}
				else {
					rstty.rt_col |= 7;
					rstty.rt_col++;
				}
			}
		}
		rsoutq.rq_ox++;
		rsoutq.rq_ox &= OUTSZ;

		/*
		 * Transmit next char.
		 */
		outb( PORT+DREG, b );
	}

	spl(s);
}

/*
 * Ioctl Routine.
 */

static
rsioctl( dev, com, vec )

dev_t dev;
int com;
struct termio *vec;

{
	register int b;
	struct termio tb;

	switch (com) {

	case TCSETAW:	/* Set attributes after waiting for output to clear */
	case TCSETAF:	/* ditto, but also flush input queue */
	case TCSBRK:	/* wait for output to clear, send break */

		/*
		 * Delay until output queue is empty.
		 */
		while ( rsoutq.rq_ox != rsoutq.rq_ix ) {

			/*
			 * Sleep waiting for empty output queue.
			 */
			++rstty.rt_drefc;
			sleep( &rstty.rt_drefc, CVTTOUT, IVTTOUT, SVTTOUT);
			--rstty.rt_drefc;

			/*
			 * Abort if a non-ignored signal was received.
			 */
			if ( SELF->p_ssig && nondsig() ) {
				u.u_error = EINTR;
				return;
			}
		}

		if ( com == TCSBRK ) {

			b = inb( PORT + LCR );

			if ( vec == 0 ) {
				rstty.rt_ticks  = 3;	/* 0.2 to 0.3 sec */
				rstty.rt_state |= TTSBRK;
				b |= LC_SBRK;
			}
			else {
				rstty.rt_ticks  = 0;
				rstty.rt_state &= ~TTSBRK;
				b &= ~LC_SBRK;
			}

			outb( PORT + LCR, b );
			return;
		}
		/* no break */

	case TCSETA:
		/*
		 * Get new terminal attributes.
		 */
		ukcopy( vec, &tb, sizeof(tb) );
		if ( u.u_error )
			return;

		/*
		 * Set terminal attributes and hardware.
		 */
		rstty.rt_iflag = tb.c_iflag;
		rstty.rt_oflag = tb.c_oflag;
		if (rstty.rt_cflag != tb.c_cflag) {
			rstty.rt_cflag = tb.c_cflag;
			rsparam();
		}

		if ((rstty.rt_iflag & IXON) == 0)
			rstty.rt_state &= ~TTSTOP;

		/*
		 * Flush input queue if command was TCSETAF.
		 */
		if ( com == TCSETAF )
			rsrawq.rq_ox = rsrawq.rq_ix;
		break;

	case TCGETA:	/* Get terminal attributes */
		
		memset( &tb, 0, sizeof(tb) );
		tb.c_cflag = rstty.rt_cflag;
		tb.c_iflag = rstty.rt_iflag;
		tb.c_oflag = rstty.rt_oflag;

		/*
		 * Transfer terminal attributes to user space.
		 */
		kucopy( &tb, vec, sizeof(tb) );
		break;

	case TCFLSH:
		switch ((int) vec) {
		case 0:
			/* flush input queue */
			rsrawq.rq_ox = rsrawq.rq_ix;
			break;
		case 1:
			/* flush output queue */
			rsoutq.rq_ox = rsoutq.rq_ix;
			break;
		case 2:
			/* flush both input and output queues */
			rsrawq.rq_ox = rsrawq.rq_ix;
			rsoutq.rq_ox = rsoutq.rq_ix;
			break;
		default:
			u.u_error = EINVAL;
		}
		break;

	case TCXONC:
		switch ( (int) vec ) {
		case 0:
			/* stop output */
			rstty.rt_state |= TTSTOP;
			break;
		case 1:
			/* restart output */
			rstty.rt_state &= ~TTSTOP;
			rsstart();
			break;
		default:
			u.u_error = EINVAL;
		}
		break;

	default:
		u.u_error = EINVAL;
	}
}

/*
 * Rsparam -- Setup hardware parameters.
 */

static
rsparam()
{
	register int b;
	register int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Assert required modem control lines (DTR, RTS).
	 */
	if ((rstty.rt_cflag & CBAUD) == B0)
		outb( PORT+MCR, MC_OUT2 );
	else if ((rstty.rt_refc == 0) && (rstty.rt_cflag & HUPCL))
		outb( PORT+MCR, MC_OUT2 );
	else
		outb( PORT+MCR, MC_OUT2+MC_DTR+MC_RTS );

	/*
	 * Program baud rate.
	 */
	if (b = timeconst[ rstty.rt_cflag & CBAUD ]) {
		outb( PORT+LCR, LC_DLAB );
		outb( PORT+DLL, b );
		outb( PORT+DLH, b >> 8 );
	}

	/*
	 * Program character size, parity, and stop bits.
	 */
	switch (rstty.rt_cflag & CSIZE) {
	case CS5:		b = LC_CS5;			break;
	case CS6:		b = LC_CS6;			break;
	case CS7:		b = LC_CS7;			break;
	case CS8:		b = LC_CS8;			break;
	}

	switch (rstty.rt_cflag & (PARENB|PARODD)) {
	case PARENB:		b |= LC_PARENB|LC_PAREVEN;	break;
	case PARENB|PARODD:	b |= LC_PARENB;			break;
	}

	if (rstty.rt_cflag & CSTOPB)
		b |= LC_STOPB;

	if (rstty.rt_state & TTSBRK)
		b |= LC_SBRK;

	outb( PORT+LCR, b );

	/*
	 * Enable desired interrupts.
	 */
	b = 0;
	if (rstty.rt_cflag & CBAUD) {
		b = IE_TxI | IE_LSI;
		if (rstty.rt_cflag & CREAD)
			b |= IE_RxI;
	}
	outb( PORT+IER, b );

	/*
	 * Enable interrupts.
	 */
	spl( s );
}
@


1.1
log
@Initial revision
@
text
@d17 2
a18 2
#include "coherent.h"
#include "ins8250.h"
@
0707070064030106451004440000030000030000011777770507310700000005600000004600/newbits/kernel/USRSRC/i8086/drv/RCS/rsas.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.25.00;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ Raw Serial Device Driver - Assembler Support
/
////////

////////
/
/ Locally defined global symbols
/
////////

	.globl	rsin_
	.globl	rsout_

////////
/
/ Offsets to fields in the IRING and ORING data structures.
/
////////

	Q_MASK	= 0
	Q_IX	= 2
	Q_OX	= 4
	Q_CC	= 6

////////
/
/ Offsets to fields in the IO data structure.
/
////////

	IO_IOC	= 2
	IO_BASE	= 8

////////
/
/ Rsin ( rawqp, iop )	-- transfer data from input ring to user
/ IRING *rawqp;
/ IO *iop;
/
////////

rsin_:
	push	si				/ Save SI, DI, BP, ES
	push	di
	push	bp
	mov	bp, sp
	push	es

	mov	bx, 10(bp)			/ User destination --> ES:DI
	mov	di, IO_BASE(bx)
	mov	es, uds_

	cld					/ Auto Increment
	mov	cx, IO_IOC(bx)			/ Byte count --> CX
	jcxz	1f

	mov	bx, 8(bp)			/ rawqp --> BX

	mov	si, Q_OX(bx)
	cmp	si, Q_IX(bx)			/ Input data available?
	je	1f

0:	movb	al, Q_CC(bx,si)			/ Yes,	read one character
	inc	si				/	update index
	and	si, Q_MASK(bx)			/	(wrap if necessary)
	stosb					/	write to user space
	cmp	si, Q_IX(bx)			/	More input data?
	loopne	0b				/

	mov	Q_OX(bx), si			/ Save revised index
	mov	bx, 10(bp)			/ Update io parameters
	mov	IO_BASE(bx), di
	mov	IO_IOC(bx), cx

1:	pop	es				/ Restore ES, BP, DI, SI.
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ Rsout( outqp, iop )	-- transfer data from user to output ring
/ ORING *outqp;
/ IO *iop;
/
////////

rsout_:
	push	si				/ Save SI, DI, BP, ES
	push	di
	push	bp
	mov	bp, sp
	push	es

	mov	bx, 10(bp)			/ User source --> ES:DI
	mov	di, IO_BASE(bx)
	mov	es, uds_

	mov	cx, IO_IOC(bx)			/ Byte count --> CX
	jcxz	2f

	mov	bx, 8(bp)			/ outqp --> BX
	mov	si, Q_IX(bx)

0:	movb	al, es:(di)
	inc	di
	movb	Q_CC(bx,si), al
	inc	si
	and	si, Q_MASK(bx)
	cmp	si, Q_OX(bx)
	loopne	0b

	jne	1f				/ If can't save last char
	dec	di				/	Undo changes.
	dec	si
	and	si, Q_MASK(bx)
	inc	cx

1:	mov	Q_IX(bx), si			/ Save revised index
	mov	bx, 10(bp)
	mov	IO_BASE(bx), di			/ Update io parameters
	mov	IO_IOC(bx), cx

2:	pop	es				/ Restore ES, BP, DI, SI.
	pop	bp
	pop	di
	pop	si
	ret
@
0707070064030106441004440000030000030000011777770507310700100005400000000711/newbits/kernel/USRSRC/i8086/drv/RCS/scsi,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.25.02;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: SCSI Hard Disk Version 0.0
:
MAJOR=13

HD_TYPE=sd0
:
:	needed by config
:
UNDEF="${UNDEF} -u sdcon_ lib/scsi.a"
PATCH="${PATCH} drvl_+130=sdcon_"

umask 077
/etc/mknod -f ${DEV-/dev}/sd0a  b 13 0		|| exit 1
@
0707070064030106431004440000030000030000011777770507310700100005600000001223/newbits/kernel/USRSRC/i8086/drv/RCS/sd.toc,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.25.13;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@-rw-r--r--  1 root       daemon       15118 Fri Oct  5  1990 aha.c
-rw-r--r--  1 root       daemon        4557 Fri Oct  5  1990 aha154x.h
-rw-r--r--  1 root       daemon         211 Wed Sep 19  1990 scsi
-rw-r--r--  1 root       daemon       10198 Fri Oct  5  1990 scsi.c
-rw-r--r--  1 root       daemon        1205 Fri Oct  5  1990 scsiwork.h
-rw-r--r--  1 root       daemon          87 Wed Sep 19  1990 sdioctl.h
@
0707070064030104231004440000030000030000011777770507310700100005500000026472/newbits/kernel/USRSRC/i8086/drv/RCS/sem.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.53.04;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.14.27;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.35.34;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.25.14;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Semaphores
 *
 *	This module provides System V compatible semaphore operations.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:11:37	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:22	src
 * Initial revision
 * 
 * 85/08/06	Allan Cornish
 * Sem.c split into configuration (semcon.c) and implementation (sem.c).
 * Semload() renamed to seminit().
 *
 * 85/07/22	Allan Cornish
 * Semctl, semget, semop now return immediately if u.u_error is set.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Eliminated semlock() and semunlock() functions.
 * Replaced semaccess() by calls to ipcaccess(), increasing shared ipc code.
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <sem.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif

/*
 *	Semaphore Information
 */

#define	NSEMVAL	32767

static
struct semid_ds *semids = 0;

unsigned NSEMID = 16;
unsigned NSEM   = 16;
		    
/*
 * Semaphore Initialization.
 *
 *	Initialize semaphore ids.
 */

seminit()
{
	register struct semid_ds *semidp;

	if ( semids = kalloc( NSEMID * sizeof(struct semid_ds) ) ) {

		for ( semidp = &semids[NSEMID]; --semidp >= semids; )
			semidp->sem_perm.mode = 0;
	}
	else {
		printf("could not allocate %u semaphore ids\n", NSEMID);
		NSEMID = 0;
	}
}

/*
 * Semctl - Semaphore Control Operations.
 */

usemctl( semid, semnum, cmd, arg )

unsigned semid;
unsigned semnum;
int cmd;
union semun {
	int val;
	struct semid_ds *buf;
	unsigned short *array;
} arg;

{
	register struct semid_ds *semidp;
	register struct sem *semp;
	int nsems, val;

	if ( u.u_error )
		return -1;

	if ( semid >= NSEMID ) {
		u.u_error = EINVAL;
		return -1;
	}

	semidp = &semids[semid];

	if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ((ipcaccess( &semidp->sem_perm ) & SEM_R) == 0) { /* can't read */
		u.u_error = EACCES;
		return -1;
	}

	if ( semnum >= semidp->sem_nsems ) {
		u.u_error = EFBIG;
		return -1;
	}

	semp = &semidp->sem_base[semnum];

	switch ( cmd ) {

	case GETVAL:		/* Return value of semval */
		return semp->semval;

	case SETVAL:						/* Set semval */
		if ((ipcaccess( &semidp->sem_perm ) & SEM_A) == 0) {
			u.u_error = EACCES;	/* can't alter */
			return -1;
		}

		if ( arg.val < 0 ) {			/* illegal value */
			u.u_error = ERANGE;
			return -1;
		}

		if ( semp->semval = arg.val ) {

			if ( semp->semncnt )
				wakeup( &semp->semncnt );
		}
		else {
			if ( semp->semzcnt )
				wakeup( &semp->semzcnt );
		}

		return 0;

	case GETPID:		/* Return value of sempid */
		return semp->sempid;

	case GETNCNT:		/* Return value of semncnt */
		return semp->semncnt;

	case GETZCNT:		/* Return value of semzcnt */
		return semp->semzcnt;

	case GETALL:		/* Return semvals array */
		nsems = semidp->sem_nsems;
		semp  = semidp->sem_base;

		while ( --nsems >= 0 ) {

			putuwd( (arg.array)++, (semp++)->semval );

			if ( u.u_error )
				return -1;
		}
		return 0;

	case SETALL:		/* Set semvals array */
		if ( (ipcaccess( &semidp->sem_perm ) & SEM_A) == 0 ) {
			u.u_error = EACCES;
			return -1;
		}
		nsems = semidp->sem_nsems;
		semp  = semidp->sem_base;

		while ( --nsems >= 0 ) {

			if ( (val = getuwd( arg.array )) < 0 ) {

				if ( u.u_error == 0 )
					u.u_error = ERANGE;
			}
			else
				semp->semval = val;
			arg.array++;
			semp++;
		}
		if ( u.u_error )
			return -1;
		return 0;

	case IPC_STAT:
		kucopy( semidp, arg.buf, sizeof(struct semid_ds) );
		return 0;

	case IPC_SET:
		if ( (u.u_uid != 0) && (u.u_uid != semidp->sem_perm.uid) ) {
			u.u_error = EPERM;
			return -1;
		}
		semidp->sem_perm.uid   = getuwd( &((arg.buf)->sem_perm.uid ) );
		semidp->sem_perm.gid   = getuwd( &((arg.buf)->sem_perm.gid ) );
		semidp->sem_perm.mode  =
			(getuwd(&((arg.buf)->sem_perm.mode))&0777) | IPC_ALLOC;
		return 0;

	case IPC_RMID:
		if ( (u.u_uid != 0) && (u.u_uid != semidp->sem_perm.uid) ) {
			u.u_error = EPERM;
			return -1;
		}
		semidp->sem_perm.seq++;
		semp = &semidp->sem_base[ semidp->sem_nsems ];

		while ( --semp >= semidp->sem_base ) {

			if ( semp->semncnt )
				wakeup( &semp->semncnt );
			if ( semp->semzcnt )
				wakeup( &semp->semzcnt );
		}

		kfree( semidp->sem_base );
		semidp->sem_perm.mode = 0;
		return 0;

	default:
		u.u_error = EINVAL;
		return -1;
	}
}

/*
 * Semget - Get set of semaphores
 */

usemget( skey, nsems, semflg )

key_t skey;
unsigned nsems;
int semflg;

{
	register struct semid_ds *semidp;
	register struct sem *semp;
	struct semid_ds *freeidp = 0;

	if ( u.u_error )
		return -1;

	if ( nsems >= NSEM ) {
		u.u_error = EINVAL;
		return -1;
	}

	for ( semidp = &semids[NSEMID]; --semidp >= semids; ) {

		if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {

			if ((freeidp == 0) ||
			    (freeidp->sem_ctime > semidp->sem_ctime))
				freeidp = semidp;
			continue;
		}

#ifdef	IPC_PRIVATE
		if (skey == IPC_PRIVATE)
			continue;
#endif

		if (skey == semidp->sem_perm.key) {		/* found! */

			if ( (semflg & IPC_CREAT) && (semflg & IPC_EXCL) ) {
				u.u_error = EEXIST;
				return -1;
			}

			if ((semidp->sem_perm.mode & semflg) != (semflg&0777)) {
				u.u_error = EACCES;
				return -1;
			}

			if ( semidp->sem_nsems < nsems ) {
				u.u_error = EINVAL;
				return -1;
			}

			return semidp - semids;
		}
	}

	if ( !(semflg & IPC_CREAT) ) {
		u.u_error = ENOENT;
		return -1;
	}

	if ( freeidp == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	semidp = freeidp;
	semidp->sem_base = kalloc( nsems * sizeof(struct sem) );

	if (semidp->sem_base == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	semidp->sem_nsems = nsems;
	semidp->sem_otime = 0;
	semidp->sem_ctime = timer.t_time;

	for ( semp = &semidp->sem_base[nsems]; --semp >= semidp->sem_base; )
		semp->semval = semp->sempid = semp->semncnt = semp->semzcnt = 0;

	semidp->sem_perm.cuid = semidp->sem_perm.uid = u.u_uid;
	semidp->sem_perm.cgid = semidp->sem_perm.gid = u.u_gid;
	semidp->sem_perm.mode = (semflg & 0777) | IPC_ALLOC;
	semidp->sem_perm.key  = skey;

	return semidp - semids;
}

/*
 * Semop - Semaphore Operations.
 */

usemop( semid, sops, nsops )

unsigned semid;
struct sembuf *sops;
unsigned nsops;

{
	register struct semid_ds *semidp;
	register struct sem *semp;
	struct sembuf *sp;
	unsigned n, semnum, semflg;
	int semop, oval;

	if ( u.u_error )
		return -1;

	if ( semid >= NSEMID ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ( nsops >= NSEM ) {
		u.u_error = E2BIG;
		return -1;
	}

	semidp = &semids[semid];

	if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EINVAL;
		return -1;
	}

	if ( (ipcaccess( &semidp->sem_perm ) & SEM_A) == 0 ) {
		u.u_error = EACCES;
		return -1;
	}

	sp = sops;
	n  = nsops;

	while ( n > 0 ) {				/* do semaphore ops  */

		semnum = getuwd( & (sp->sem_num) );
		semop  = getuwd( & (sp->sem_op ) );
		semflg = getuwd( & (sp->sem_flg) );

		if ( (u.u_error != 0) || (semnum >= semidp->sem_nsems) ) {

			while ( --sp >= sops ) {	/* undo prev semops  */

				semnum = getuwd( &sp->sem_num );
				semop  = getuwd( &sp->sem_op  );
				semp   = &semidp->sem_base[ semnum ];
				semundo( semp, semop );
			}

			if ( u.u_error == 0 )
				u.u_error = EFBIG;
			return -1;
		}

		semp = &semidp->sem_base[semnum];

		if ( (oval = semdo( semp, semop )) < 0 ) { /* can't do semop */

			while ( --sp >= sops ) {	/* undo prev semops  */

				unsigned unnum = getuwd( &sp->sem_num );
				int	 unop  = getuwd( &sp->sem_op  );
				semundo( &semidp->sem_base[ unnum ], unop);
			}

			if ( u.u_error )
				return -1;

			if ( semflg & IPC_NOWAIT ) {
				u.u_error = EAGAIN;
				return -1;
			}

			if ( semop < 0 ) {	/* wait for non-zero */

				if (semwait( semidp, &semp->semncnt ) < 0 )
					return -1;
			}
			else {			/* wait for zero */

				if ( semwait( semidp, &semp->semzcnt ) < 0 )
					return -1;
			}

			sp = sops;	/* retry set of semaphore operations */
			n = nsops;
			continue;
		}

		++sp;
		--n;
	}

	for (sp=sops,n=nsops; n > 0; --n,++sp) {/* save pid in each semaphore */

		semnum = getuwd( &sp->sem_num );
		semidp->sem_base[ semnum ].sempid = SELF->p_pid;
	}

	semidp->sem_otime = timer.t_time;	/* ajust operation time */
	return oval;				/* return last prev semval */
}

/*
 * Do a Semaphore Operation.
 *
 *	Input:	semp  = pointer to semaphore
 *		semop = semaphore operation
 *
 *	Action:	If semop < 0 and semval > semop then add semop to semval.
 *		If semop > 0 then add semop to semval.
 *
 *	Return:	Previous semval.
 */

static
semdo( semp, semop )

register struct sem * semp;
register int semop;

{
	int ret;

	ret = semp->semval;

	if ( semop < 0 ) {			/* want to decrement semval */

		semop = -semop;

		if ( semp->semval < semop )	/* can't decrement semval */
			return -1;

		semp->semval -= semop;

		if ( (semp->semval == 0)  && (semp->semzcnt != 0) )
			wakeup( &semp->semzcnt );
	}
	else if ( semop > 0 ) {			/* want to increment semval */

		if ( (semp->semval + semop) > NSEMVAL) {
		
			u.u_error = ERANGE;
			return -1;
		}

		semp->semval += semop;

		if ( semp->semncnt )
			wakeup( &semp->semncnt );
	}
	else /* if ( semop == 0 ) */ {

		if ( semp->semval != 0 )
			return -1;
	}
	return ret;
}

/*
 * Undo a Semaphore Operation.
 */

static
semundo( semp, semop )

register struct sem * semp;
register int semop;

{
	if ( semp->semval -= semop ) {

		if ( semp->semncnt )
			wakeup( &semp->semncnt );
	}
	else {
		if ( semp->semzcnt )
			wakeup( &semp->semzcnt );
	}
}

/*
 * Wait on Semaphore Event
 *
 *	Input:	semidp = pointer to semaphore id structure.
 *		ep     = pointer to semncnt or semzcnt event to wait for.
 *
 *	Action:	Sleep on a semaphore event.
 *		If semaphore id has been deleted, error return.
 *		If signal has been received, error return.
 *
 *	Output:	 0 = Status ok.
 *		-1 = Error occurred, errno is set.
 */

static
semwait( semidp, ep )

register struct semid_ds * semidp;
register unsigned short *ep;
{
	unsigned seqn;

	seqn = semidp->sem_perm.seq;
	++(*ep);
	sleep( ep, CVTTOUT, IVTTOUT, SVTTOUT );

	if (semidp->sem_perm.seq != seqn ) {	/* semaphore id gone */
		u.u_error = EIDRM;
		return -1;
	}

	--(*ep);

	if ( SELF->p_ssig && nondsig() ) {	/* signal received */
		u.u_error = EINTR;
		return -1;
	}
	return 0;
}
@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106421004440000030000030000011777770507310700400006000000006410/newbits/kernel/USRSRC/i8086/drv/RCS/semcon.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.53.18;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.14.41;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.35.53;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.25.18;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Semaphore Device Driver
 *
 *	This device driver provides System V compatible semaphore operations.
 *	Operations are performed through the semaphore device (/dev/sem).
 *	and are implemented as ioctl calls from semctl, semget, semop
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:11:55	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:26	src
 * Initial revision
 * 
 * 87/03/02	Allan Cornish		/usr/src/sys/i8086/drv/semcon.c
 * Semioctl() now supports long key [was short] on SEMGET operations.
 * This allows compatability with System V.
 *
 * 85/08/06	Allan Cornish
 * Sem.c split into configuration (semcon.c) and implementation (sem.c).
 * Semload() renamed to seminit().
 *
 * 85/07/03	Allan Cornish
 * Eliminated semopen() and semclose() functions.
 *
 * 84/09/30	Allan Cornish
 * Initial Revision.
 */

#include <coherent.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <con.h>
#include <sem.h>

/*
 * Functions.
 */

int seminit();
int semioctl();
int nulldev();
int nonedev();

/*
 * Device Configuration.
 */

CON semcon = {
	DFCHR,			/* Flags			*/
	23,			/* Major Index			*/
	nulldev,		/* Open				*/
	nulldev,		/* Close			*/
	nonedev,		/* Block			*/
	nonedev,		/* Read				*/
	nonedev,		/* Write			*/
	semioctl,		/* Ioctl			*/
	nulldev,		/* Power fail			*/
	nulldev,		/* Timeout			*/
	seminit,		/* Load				*/
	nulldev			/* Unload			*/
};

/*
 * Semaphore Device Ioctl.
 */

static
semioctl( dev, com, vec )

dev_t dev;
int com;
register int *vec;

{
	switch ( com ) {

	case SEMCTL:
		putuwd( vec+0,
			usemctl(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ) ));
		return;

	case SEMGET:
		putuwd( vec+0,
			usemget(getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ),
				getuwd( vec+4 ) ));
		return;

	case SEMOP:
		putuwd( vec+0,
			usemop(	getuwd( vec+1 ),
				getuwd( vec+2 ),
				getuwd( vec+3 ) ));
		return;

	default:
		u.u_error = EINVAL;
		return;
	}
}
@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106401004440000030000030000011777770507310700500006100000002314/newbits/kernel/USRSRC/i8086/drv/RCS/semstub.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.25.19;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Semaphore Device Driver Stub.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Nov 1986.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:12:04	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:29	src
 * Initial revision
 * 
 * 85/11/21	Allan Cornish		/usr/src/sys/i8086/drv/semstub.c
 * Initial Revision.
 */

semexit()
{
}
@
0707070064030106411004440000030000030000011777770507310700500005500000012562/newbits/kernel/USRSRC/i8086/drv/RCS/shm.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.53.22;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.14.52;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.36.00;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.25.21;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985, 1984
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Shared Memory Device Driver
 *
 *	This device driver provides System V compatible shared memory operations.
 *	Operations are performed through the shared memory device (/dev/shm).
 *	and are implemented as ioctl calls from shmctl, shmget, shmat, shmdt
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:12:17	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:32	src
 * Initial revision
 * 
 * 85/10/16	Allan Cornish
 * Driver split into shmcon.c, shm.c [driver implementation, System V shm].
 *
 * 85/07/22	Allan Cornish
 * Shmget, shmctl now return immediately if u.u_error is set.
 *
 * 85/07/19	Allan Cornish
 * Separation of io_seek into shmid and off improved through type casting.
 * Errno set to EFAULT if fucopy() or ufcopy() report no bytes transferred.
 * This would occur if an user address fault occurred.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Replaced shmaccess() by calls to ipcaccess(), increasing shared ipc code.
 * Eliminated shmlock() and shmunlock(), as shared memory use is synchronous.
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <seg.h>
#include <shm.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif


extern	unsigned NSHMID;
extern	struct shmid_ds *shmids;
extern	struct seg **shmsegs;

/*
 * Shmctl - Shared Memory Control Operations.
 */

ushmctl( shmid, cmd, buf )

unsigned shmid;
int cmd;
struct shmid_ds *buf;

{
	register struct shmid_ds *idp;
	int ret = 0;

	if ( u.u_error )
		return -1;

	if ( shmid >= NSHMID ) {
		u.u_error = EINVAL;
		return -1;
	}

	idp = &shmids[shmid];

	if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EINVAL;
		return -1;
	}

	switch ( cmd ) {

	case IPC_STAT:
		if ( ( ipcaccess( &idp->shm_perm ) & SHM_R ) == 0 ) {
			u.u_error = EACCES;
			return -1;
		}
		kucopy( idp, buf, sizeof(struct shmid_ds) );
		ret = 0;
		break;

	case IPC_SET:
		if ( (u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid) ) {
			u.u_error = EPERM;
			ret = -1;
			break;
		}
		idp->shm_perm.uid   = getuwd( &(buf->shm_perm.uid ) );
		idp->shm_perm.gid   = getuwd( &(buf->shm_perm.gid ) );
		idp->shm_perm.mode &= ~0777;
		idp->shm_perm.mode |= getuwd(&(buf->shm_perm.mode)) & 0777;
		ret = 0;
		break;

	case IPC_RMID:
		if ( (u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid) ) {
			u.u_error = EPERM;
			ret = -1;
			break;
		}
		idp->shm_perm.seq++;
		sfree(shmsegs[shmid]);
		idp->shm_perm.mode = 0;
		ret = 0;
		break;

	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * Shmget - Get Shared Memory Segment
 */

ushmget( skey, size, shmflg )

key_t skey;
unsigned size;
int shmflg;

{
	register struct shmid_ds *idp;
	struct shmid_ds *freeidp = 0;

	if ( u.u_error )
		return -1;

	for ( idp = &shmids[NSHMID]; --idp >= shmids; ) {

		if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {

			if ((freeidp == 0) ||
			    (freeidp->shm_ctime > idp->shm_ctime))
				freeidp = idp;
			continue;
		}

#ifdef	IPC_PRIVATE
		if (skey == IPC_PRIVATE)
			continue;
#endif

		if (skey == idp->shm_perm.key) {		/* found! */

			if ( (shmflg & IPC_CREAT) && (shmflg & IPC_EXCL) ) {

				u.u_error = EEXIST;
				return -1;
			}

			if ((idp->shm_perm.mode & shmflg) != (shmflg&0777)) {

				u.u_error = EACCES;
				return -1;
			}

			if ( idp->shm_segsz < size ) {

				u.u_error = EINVAL;
				return -1;
			}

			return idp - shmids;
		}
	}

	if ( !(shmflg & IPC_CREAT) ) {
		u.u_error = ENOENT;
		return -1;
	}

	if ( freeidp == 0 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	idp = freeidp;

	if ((shmsegs[idp - shmids] = salloc((size_t) size, SFNSWP)) == NULL){
		u.u_error = ENOSPC;
		return -1;
	}

	idp->shm_segsz = size;
	idp->shm_atime = 0;
	idp->shm_dtime = 0;
	idp->shm_ctime = timer.t_time;
	idp->shm_cpid  = SELF->p_pid;
	idp->shm_perm.cuid = idp->shm_perm.uid = u.u_uid;
	idp->shm_perm.cgid = idp->shm_perm.gid = u.u_gid;
	idp->shm_perm.mode = (shmflg & 0777) | IPC_ALLOC;
	idp->shm_perm.key  = skey;

#ifdef	IPC_PRIVATE
	if ( skey == IPC_PRIVATE )
		idp->shm_perm.mode |= SHM_DEST;
#endif

	return idp - shmids;
}
@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106371004440000030000030000011777770507310700700006000000014064/newbits/kernel/USRSRC/i8086/drv/RCS/shmcon.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.53.29;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.08.14.59;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.36.12;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.25.23;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987, 1985, 1984.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * System V Compatible Shared Memory Device Driver
 *
 *	This device driver provides System V compatible shared memory operations.
 *	Operations are performed through the shared memory device (/dev/shm).
 *	and are implemented as ioctl calls from shmctl, shmget, shmat, shmdt
 *	utilities.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:12:40	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:36	src
 * Initial revision
 * 
 * 87/03/02	Allan Cornish		/usr/src/sys/i8086/drv/shmcon.c
 * Shmioctl() now supports long key [was short] on SHMGET operations.
 * This allows compatability with System V.
 *
 * 85/10/16	Allan Cornish
 * Driver split into shmcon.c, shm.c [driver implementation, system V shm].
 *
 * 85/07/22	Allan Cornish
 * Shmget, shmctl now return immediately if u.u_error is set.
 *
 * 85/07/19	Allan Cornish
 * Separation of io_seek into shmid and off improved through type casting.
 * Errno set to EFAULT if fucopy() or ufcopy() report no bytes transferred.
 * This would occur if an user address fault occurred.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Replaced shmaccess() by calls to ipcaccess(), increasing shared ipc code.
 * Eliminated shmlock() and shmunlock(), as shared memory use is synchronous.
 *
 * 84/09/30	Allan Cornish
 * Initial Revision.
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <uproc.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <seg.h>
#include <shm.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif

/*
 * Functions.
 */

int shmload();
int shmread();
int shmwrite();
int shmioctl();
int nulldev();
int nonedev();

/*
 * Device Configuration.
 */

CON shmcon = {
	DFCHR,			/* Flags			*/
	24,			/* Major Index			*/
	nulldev,		/* Open				*/
	nulldev,		/* Close			*/
	nonedev,		/* Block			*/
	shmread,		/* Read				*/
	shmwrite,		/* Write			*/
	shmioctl,		/* Ioctl			*/
	nulldev,		/* Power fail			*/
	nulldev,		/* Timeout			*/
	shmload,		/* Load				*/
	nulldev			/* Unload			*/
};

unsigned NSHMID = 16;
struct shmid_ds *shmids;
struct seg **shmsegs;

/*
 * Shared Memory Device Load.
 */

static
shmload()
{
	register struct shmid_ds * idp;
	register unsigned wanted;
	
	if ( NSHMID == 0 )
		return 0;

	wanted = NSHMID * (sizeof(struct shmid_ds) + sizeof(struct seg *));

	if ( (shmids = kalloc( wanted )) == 0 ) {

		printf("couldn't kalloc %u shared memory ids\n", NSHMID );
		NSHMID = 0;
		return 0;
	}
	shmsegs = (struct seg *) &shmids[ NSHMID ];

	for ( idp = &shmids[NSHMID]; --idp >= shmids; )
		idp->shm_perm.mode = 0;

	return 0;
}

/*
** Shared Memory Read.
*/

static
shmread( dev, iop )

dev_t dev;
register IO *iop;

{
	register struct shmid_ds *idp;
	int shmid;
	unsigned off;
	faddr_t faddr;

	off   = ((unsigned *) &iop->io_seek)[0];
	shmid = ((unsigned *) &iop->io_seek)[1];

	if ( shmid >= NSHMID ) {
		u.u_error = EFAULT;
		return -1;
	}

	idp = &shmids[shmid];

	if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EIDRM;
		return -1;
	}

	if ( (ipcaccess(&idp->shm_perm) & SHM_R) == 0 ) {
		u.u_error = EACCES;
		return -1;
	}

	if ( ((long) off + iop->io_ioc) > idp->shm_segsz ) {
		u.u_error = EFAULT;
		return -1;
	}

	FP_SEL(faddr) = FP_SEL(shmsegs[shmid]->s_faddr);
	FP_OFF(faddr) = off;

	if ( ! fucopy( faddr, iop->io_base, iop->io_ioc ) ) {
		u.u_error = EFAULT;
		return -1;
	}

	iop->io_ioc = 0;
	return 0;
}

/*
** Shared Memory Write.
*/

static
shmwrite( dev, iop )

dev_t dev;
register IO *iop;

{
	register struct shmid_ds *idp;
	int shmid;
	unsigned off;
	faddr_t faddr;

	off   = ((unsigned *) &iop->io_seek)[0];
	shmid = ((unsigned *) &iop->io_seek)[1];

	if ( shmid >= NSHMID ) {
		u.u_error = EFAULT;
		return -1;
	}

	idp = &shmids[shmid];

	if ( (idp->shm_perm.mode & IPC_ALLOC) == 0 ) {
		u.u_error = EIDRM;
		return -1;
	}

	if ( (ipcaccess(&idp->shm_perm) & SHM_W) == 0 ) {
		u.u_error = EFAULT;
		return -1;
	}

	if ( ((long) off + iop->io_ioc) > idp->shm_segsz ) {
		u.u_error = EFAULT;
		return -1;
	}

	FP_SEL(faddr) = FP_SEL(shmsegs[shmid]->s_faddr);
	FP_OFF(faddr) = off;

	if ( ! ufcopy(iop->io_base, faddr, iop->io_ioc ) ) {
		u.u_error = EFAULT;
		return -1;
	}

	iop->io_ioc = 0;
	return 0;
}

/*
 * Shared Memory Device Ioctl.
 *
 *	Input:	dev = shared memory device (/dev/shm).
 *		com = command to perform (SHMCTL, SHMGET,SHMAT).
 *		vec = pointer to return value, followed by parameters.
 *
 *	Action:	Initiate command.
 *		Save commands return value in *vec.
 */

static
shmioctl( dev, com, vec )

dev_t dev;
int com;
int *vec;

{
	switch ( com ) {

	case SHMCTL:
		putuwd( vec+0,
			ushmctl( getuwd( vec+1 ),
				 getuwd( vec+2 ),
				 getuwd( vec+3 ) ));
		break;

	case SHMGET:
		putuwd( vec+0,
			ushmget( getuwd( vec+1 ),
				 getuwd( vec+2 ),
				 getuwd( vec+3 ),
				 getuwd( vec+4 ) ));
		break;

	default:
		u.u_error = EINVAL;
		break;
	}
}
@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@new version provided y hal for v321
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030106351004440000030000030000011777770507310701100006100000002320/newbits/kernel/USRSRC/i8086/drv/RCS/shmstub.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.25.25;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Shared Memory Device Driver Stub.
 *
 *			Author: Allan Cornish, INETCO Systems Ltd., Nov 1986.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 2.1	88/09/03  13:12:52	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:39	src
 * Initial revision
 * 
 * 85/11/21	Allan Cornish		/usr/src/sys/i8086/drv/shmstub.c
 * Initial Revision.
 */

shmexit()
{
}
@
0707070064030106341005550000030000030000011777770507310701100005700000032115/newbits/kernel/USRSRC/i8086/drv/RCS/ssqtest,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.28.07;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�" |�����F� �P��́�VWU����F��"P�l	���F�P�CP�V���F���]�CC.;��t�.�gdrw��k�
P�P����F��F��F��~��EW�p���v��GP�	���D��F��t
�~��E�P�k�ฎ�!��F��tP����~��E�P��뽸�P�����~�qt�B��P�����]_^�VWU��>�u�F����+��~�E���F�>���~����E�F����]_^�VWU�졜]_^�VWU��P�>�~/���F��>�u
+�������>�����>��E����F��F���]_^�VWU��FP�NP�P��]_^�VWU��F
P�v�:��]_^�VWU����F�P�v���P�v����F
P�F�P�	����]_^�VWU���X�F��^
�F
��F��^��F�����-�CC.;��u5.�g
	
 %3CCC��v�v�����P�

�����u����^�G~�OS�W����^���F�^�*�ȋ�;�t��vW������^��F�����=*u��+��F��~�t�^��F������F���0|&��9!�F�.�.�	�ȋ��-0�F��^��F������Ճ�lu��+��F���hu��+��F�~�u�~�t�^��F������ƻ=�CC.;��uH.�g"%DEFNOX[cdefnosx3`�����:���s��nP�P�
���2��F��F�
��F��F���F��F���F��F��F�P�v��v��v����F�V�~�u�T�~�t�)��~�t�^
�F
���W��~��^
�F
��F��F�����F��F�P�v��v������F��F��F��F�~�u���~�t���~�t9�^
�F
��F��F��F��F���G��G��G��|��^
�F
��F��F��F��F���G��O��F��F��^��F�����=^u��+��F��~�t�^��F������t��]t�^��F��ƈ���^���F��F��^�G~�OS�W����^���F��^��*���N�~�u�F��^�G~�OS�W����^���F��^��*���F�!��v�������F�"�F��~�u�^
�F
��F��F����t`W�v��[���u��+�;F�uF�F��~�u
�^��F��Lj�N�u����ċ^�G~�OS�W����^���F��^��*��뛃��t
�vW�R	���~�t�~�t�����cu����^������~�u�^�Gt�����F��]_^�VWU����v
�~�F��F��~�� ~� �^��v�����F��~�-u��+��F��u�~�+u-�^�G~�OS�W����^���F�^�*�F��^��^;?|m�ui�~�0t�
�^�^�G~�OS�W����^���F�^�*�F��^��;�|+�~�xt�� ��^�G��OS�W���F��^��^;?��F�-W�F�=
}!�F�-7�F�=
}�F�-0�F��|�~�	;v���uY�F�F�uQ�F�-x�F��uD�F���F�V�F�P�ƙRP�L��+F�V�F��V��^�G~�f��^���F�^�*��\��v�v��{���~�t�F��V��
�F��V����؃���]_^�VWU���%+��F߉F݃~
~�~
 ~�F
 �^��^�;F
|�
�^�G~�OS�W����^���Fۋ^ۊ*��{�CC.;��t��.�g$	
 +-.0123456789Ee����������������				�uw�^��^��]��t��uaG�^��F݋ƈ���'����t
��t��u��׃�|2��-��ȃ�����t
��t��u�믃�t��u���vV����^���F�P������]_^�VWU��~�E~�MW�^�W����^�?��*��= t׃�
t҃�	t͋�]_^�
VWU��FP�^P�j��]_^�VWU��F
P�v�T��]_^�VWU����F�P��P�v����F
P�F�P�)���N�}�F��F�P+�P�V����	�~��F����]_^�VWU���^�F
�F��^���F�F��^��F����=%t/�u���^�O}
�GSW�W
���ԋ^���F��^��Lj���F� �F����F����^��F������-u�F��^��F������F���0u�F�0�^��F������*u'�^��F���F��}
�F��؉F�^��F�����0�F���0|&��9!�F�.�.`�ȋ��-0�F�^��F�����Ճ�.uY�^��F������*u�^��F���F�^��F�����0�F���0|&��9!�F�.�.`�ȋ��-0�F�^��F�����Ճ�lu&�^��F������dt��ot
��ut��xu��%�����F��F����F��ǻ��CC.;��t��.�gDOUXcdefgorsuxI���
���?
�0D�^��F���F�~�}�؉F��F�-�
P�v�V� �������
P�^��F��7������^���W�F�V�F��~�y���؃��F�V��F�-�
P�v��v�V�?��뤸
P�^��w�7V�*�����F�������V�v��v�W�F�����F��j�F��^���F��u�F��F��F��F�����F�?t�~�|��+F�;F�~�N�-�F���F�F��^��F���^����^��7�v������F��F�F�+ƉF��}�F��~�uz�~�tG�~�0uA�^��?-u9�^�O}�GS�^��F���P�^�W
����^���F��^��F����^���F��N��t#�^�O}	�GS�v��ŋ^���F��^��F���;v�v;�^�O}�GS�^��F���P�^�W
���ڋ^���F��^��F����^�����~�u�*��F��N��u���^�O}�GS�v��W
���܋^���F��^��F���ȋ�]_^�VWU����v
�F��F��N��^����+��v���t �N��F��F��+��v�ڊ���^������N��^������^��?t�F�F�F��F����^���F��]_^�VWU����v�~�n��N�^���ǙRP�v�v
����F�V��t4�N�F�F�ǙRP�v�v
�����؊���^��F�V�F
�V��N�F�F�F
�؊���^��^�?t
��F�F��F���Ƌ�]_^�
VWU��v
�~�tS�|�u"�D��D
c�D�L�d��F�D�F�-�|�u�D��Ձ|Fu�D �ǁ|�u�DB빸��]_^�VWU��v�D��D
��D�d��D]_^�VWU��v�D��D
��+D�D�~�D+�D�d��D]_^�VWU��v�DF�D
��D�d��D]_^�VWU��v�D��4����؉D�D]_^�VWU��v�~
W�U���M}
�EWV�U
���
���ƈ*�]_^�VWU��v�~
�<t!�M}�EW��P�U
���	�����F��]_^�VWU��v�|u:�Du(�D
�P�������t��^u�P����D�u�DF�D
��A�Du�t��^u�D��D
6�D��D��D
��D
�P���D��D�D]_^�VWU����P+�PP�v����؋ʉ^��N����u	���u+���F�+�.�6��‹�]_^�VWU��vV�$���V�T��]_^�VWU��v�~
W����WV�U
��]_^�VWU��L��&r�<t�4�$������]_^�VWU������v���]_^�VWU��v�Du����/V�/�����D
�P�����|t�Du	�t�(���D��]_^�VWU��v�D��D�uI�+D���~W�t�D
�P�����;�t�>u�|�D;u�D����D+���L����]_^�VWU��vV�����t����i�>h6u
�^P�o�����D+DP�t�D
�P����؉D=u�>t�L��D믃|u�L@@룋D�D)D�<��*�]_^�VWU��P�v�>h6u
�^P������D��P�F�P�D
�P���=��t�t�F�*���>t
�L���L@@�����]_^�VWU��v�D���]_^�VWU��v�~
W����t�����E+EH�E����*�*�]_^�VWU��P�v�~
�ƈF��E��Eu4W�:���u)�P�F�P�E
�P����=u��*���>t�M�����]_^�VWU��v�DtV�T���D;w	V������8�P�<+|�ǙRP�D
�P����؋ʃ��u
���u������D�D+�]_^�VWU����F�P�AP�v�J���|��+���]_^�VWU��~��׹��+��O��+�]_^�VWU��~P�nP�����P�nP����P�����]_^�VWU����v+ɉN�N��N�����F��V���F���F�Fꘋ؋���u��=+t
=-u
�N���F������u����0�~��ws��~���w��F�tH�v��v��������F�P�v��s
�������
��������F��F��F��F��)�v��v������F��F��F��F�N��F��Ǚ�<�F���F��V��������F��V��Ǚ�F�V�F��V��������F�V�F�V�F��V��F�u���N�����.u�F�u�N�����F�t0�v��v��������F�P�v��	�������
��������v��v������F��F��F��F��et��Eu^��F����=+t
=-u
�N���F�����F���t�F�.�.��ȋ��-0�F���F�������F�t�F�)F���F�F��~�t�v������>�F�P����
�F�t�F��F��F��F��6	���F��F��F��F���]_^�
VWU����>�t+���F%��F�;Fs�F�F������v�������=��u���~�v}�n��~�s��F��҃>�u���ƉF������/;6�u���F��D�F������-���E�F��u���F�-
���F���-����F��E���]_^�VWU����~u+����F%���F�;Fr�+��6����F��F��N��t$��N���uC+��~�t
�F�%�����D����;6�t�P��P�P�0�����v������u���t���F�%����F����F�;F�s��뜋F�)F��F�=s�%���F����F�����F����F����F�������D��]_^�VWU��~tE�FHH���<��s�P��P�P����'��ρ������;�t
���u�6�]_^�VWU��̀��]_^�VWU��+�P�I�����~t$��F��;�v�����V�$���>u��]_^�͆��Ͷ��͓��̓��̈́��͑��VWU��v
���f��V�B������tV+�PW�����]_^�VWU��F
�VWU��F
P�v�t�t�t�4�L��
��D��D��D��]_^�[�6�6�6�6��VWU��^�VWU��^+��VWU��^�VWU��^�����F��G�����V���؈F��F���%�u�V�v�~
�F��F���~򥥥�F���V���؈F��F���%�u�w�����F��v�~ꥥ��V��v��~�F�N�+N�}�^��^��^����^��هV��v�~�F��9~�V��v�~�F�N��^����������n�
�����������N��^�:�t�vF�~�v�V�:�u��tA�&�u�u�u
�t9�y���E��������rI��������s	��������A�����������؉�6�>���]_^����������������VWU��+�*��F�y=�ط��7VWU��+�*��F�)VWU��*��V
�F�y���؃����
VWU��*��V
�F+ɋ��t������r����������
ψ	��+���]_^�VWU��v�VWU��v���F��u�G���֋L��t���v��Ċ�*�*��-�~�=v���F��N��L�̀+ۊf*�����D�f	�ߋD�f��*��$�f
�ߋF	��N�+���͋D�f��͋D�f
��͉~�+��F��f����D�f
�ʃ��F��f
��x
�n��f�������+�+��f�f�����V��&���F�u��
�u��f����߉>�	��]_^ø������n��أ���������+�������VWU��S�؋�S+��y
�^�W���V�F�y���؃���rFRP�V
�F�y���؃�FRP�V���
��s���؃�[��]_^ËË܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@@��[��]_^��Ë܋_��Ë܍_VWU��P�F�'����F�g��F
�'��֋�[��]_^��Ë܋_��Ë܍_VWU��P�v
�~+�+�� ��������;Wrw;r+W��[��]_^�VWU��v�~
�E�E;uW����u���ƈ*�=
uW�����t������*�]_^�VWU��v�F��D�D��F
�؉D�|�}�D��D
���D
���]_^�VWU��v
�D���]_^�VWU��v
�D��<��F�*�]_^�VWU��N�F
�~��F]_^�VWU��v�f
��:�t
�u����N��]_^�W�+������_�VWU��v�|����؋�=}%����狅���������
�����&2�Ʊ��H���
P���������������
���
������q��}!����狅�������������냃�&.�Ʊ��H���
P������������������������}�½����H]_^��VWU��v�VWU��v���F��u����[�ҋ\����V�
�u�M�Ċ�*��+��x�=v�6�F��^
�π�N�~	�f*��������؃���8�F��+ы�+���+\�|��xD�ϋ|+���>��Њ$+��[����Ӌ��L�̀;�t�r�@@���F���d+��s
�N|�s��ϋ>�D�f+�ʸ��&�$�f����������t�N$|L���T�΀�;�u����F��V�~��N��^�
�x	H�����������������s��H
�y��u"�6�>���f����߉�	��]_^ø������V����ܣ��{NULL}0123456789ABCDEF<w>rite/<r>ead/<d>elete/<q>uit:  %cNode #%2d written to tail of queue
Node #%2d read from head of queue
Can't read head of queue - queue empty
Node #%2d deleted from head of queue
Can't delete head of queue - queue empty
Done
Bad format in scanf
	
 N^n������You must compile with the -f flag to include printf() floating point.
Bad pointer in malloc.
Bad pointer in free.
�@@�������>ףp=
�#=�O��n�;e�X��9�GG��'8il��7�6Bz�Ք��4�a�w�+3��6A_p�1�������/�$���/.�Po	̼�,
�KB.�*�\	5�$4)��:�|�'�@@ B�CzE@@GP�H$tJ��L ��M(knO�Q@@�C�R��hT*�V�� �W�1�_cY��[�p+��ŝu@@@@@@@@@@@@@@@@@@PPPPP@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@�                                @@ahigh	
ahigh	
ahigh	
ahigh	
free_qbhigh	bhigh	bhigh	bhigh	ddlmulZmain_ retzW!retz�__a_first_�errno_claim	claim	claim	__a_count_�_fgetb_�_fgetc_Fssq_wr_tail_�retinf�"retinf�ddrmuld_fpinit_�_dtefg_�Count	_stropen_�atof_.write_$lop	��exp	��exp	��calloc_,fscanf_�rop	��pa	sbrk_�fputs_�pb	
_stderr_ndldivE!_fp_&malloc_�llmodfprintf_�	_fpac_drdiv;!exit_�dicvt@@dlsub�fclose_l0ssq_rd_head_Al1.dlcvtdsscanf_�lrmodl24brk_(dlmul�_fgeteof_�l3Dls	��_fputb_�l4Xllsgndrsub�_fputc_�_stdin_Nenviron_ q0	��l5k_stdout_^rp	q1	��overf�!rp	r0	��rp	b	
q2	��_ctype_q3	��drmul�dzero& signs	��dpush�vldivrrs	��sprintf_�	ungetc_bssq_rm_head_Mdone�"vlrem�lrsgns3	��done�ducvtVllmul�dvcvt�fflush_Vi	memset_�scanf_�vrdiv{l	lrmul�l	l	l	vrrem�vlmul�sign	��sign	��_fputt_6r	r	r	__a_scanp_�printf_�	alow	alow	alow	alow	lseek_blow	blow	blow	blow	strchr_ u	_pow10_4 close_vrmul�v	String	String	String	strlen_�abort_�index_ oerror_:!bptr	negreg*_exit_dladd�lexp	��finit_�ioctl_read_ fptr	��_fpseek_Visatty_�Char	
Char	
rexp	��dradd�_finish_�_fginit_�@
0707070064030106331004440000030000030000011777770507310701400006100000003133/newbits/kernel/USRSRC/i8086/drv/RCS/ssqtest.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.10.10.28.14;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/*
 * File:	ssqtest.c
 *
 * Purpose:	unit test of routines in ssqueue.c
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 */

/*
 * Includes.
 */
#include <stdio.h>
#include <coherent.h>
#include <sys/buf.h>
#include <scsiwork.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
extern char * calloc();
extern void ssq_wr_tail();
extern scsi_work_t * ssq_rd_head();
extern scsi_work_t * ssq_rm_head();

void main();

/*
 * main()
 */
void main()
{
	char cmd;
	int node_num = 0;
	scsi_work_t * sw;

	do {
		printf("<w>rite/<r>ead/<d>elete/<q>uit: ");
		scanf(" %c", &cmd);
		switch(cmd){
		case 'w':
			sw = (scsi_work_t *)calloc(1, sizeof(*sw));
			node_num++;
			sw->sw_type = node_num;
			ssq_wr_tail(sw);
			printf("Node #%2d written to tail of queue\n", node_num);
			break;
		case 'r':
			if (sw = ssq_rd_head())
				printf("Node #%2d read from head of queue\n", sw->sw_type);
			else
				printf("Can't read head of queue - queue empty\n");
			break;
		case 'd':
			if (sw = ssq_rm_head()) {
				free(sw);
				printf("Node #%2d deleted from head of queue\n", sw->sw_type);
			} else
				printf("Can't delete head of queue - queue empty\n");
			break;
		}
	} while (cmd != 'q');
	printf("Done\n");
}
@
0707070064030104221004440000030000030000011777770507310701500005400000056003/newbits/kernel/USRSRC/i8086/drv/RCS/st.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.54.42;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.28.32;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * This is a driver for the
 * Archive SC-400 Series Tape Controller.
 */
#include	<sys/coherent.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/const.h>
#include	<sys/inode.h>
#include 	<sys/mtioctl.h>
#include	<sys/sched.h>
#include	<sys/seg.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>

/*
 * Fixed parameters.
 */
#define	STMAJ	12			/* Major device */
#define	NCMDS	8			/* Max # chained commands */

/*
 * Configurable parameters
 */
int	STIRQ	= 3;			/* IRQ Level 3 */
int	STPORT	= 0x200;		/* I/O Port    */
int	STDMA	= 1;			/* DMA Channel */

#define	BIT(n)		(1 << (n))

/*
 * Forward referenced functions.
 */
void	stcache();
void	stflush();
void	stinvoke();
void	ststart();
void	stintr();
void	strecov();
void	stnext();
void	stdiag();
void	stspin();

/*
 * Driver configuration.
 */
int	stload();
int	stuload();
int	stopen();
int	stclose();
int	stread();
int	stwrite();
int	stioctl();
void	stwatch();
int	nulldev();
int	nonedev();

CON	stcon	= {
	DFCHR,				/* Flags	*/
	STMAJ,				/* Major index	*/
	stopen,				/* Open		*/
	stclose,			/* Close	*/
	nonedev,			/* Block	*/
	stread,				/* Read		*/
	stwrite,			/* Write	*/
	stioctl,			/* Ioctl	*/
	nulldev,			/* Powerfail	*/
	stwatch,			/* Timeout	*/
	stload,				/* Load		*/
	stuload				/* Unload	*/
};

/*
 * I/O Port Addresses
 */
#define	DATA_REG	(STPORT+0)	/* Data register */
#define	CTRL_REG	(STPORT+1)	/* Control/Status register */
#define	DMAGO_REG	(STPORT+2)	/* DMA Go register */
#define	DMARST_REG	(STPORT+3)	/* DMA reset register */

/*
 * Control Register
 */
#define	CR_RSTSAC	BIT(7)		/* 1 -> reset control micro	*/
#define	CR_REQ		BIT(6)		/* 1 -> request to LSI chip	*/
#define	CR_IEN		BIT(5)		/* 1 -> enables interrupts	*/
#define	CR_DNIEN	BIT(4)		/* 1 -> enable DONE interrupts	*/

/*
 * Status Register
 */
#define	SR_IRQF		BIT(7)		/* 1 -> Interrupt Request Flag	*/
#define	SR_NRDY		BIT(6)		/* 0 -> Ready			*/
#define	SR_NEXC		BIT(5)		/* 0 -> Exception		*/
#define	SR_DONE		BIT(4)		/* 1 -> DMA Done		*/
#define	SR_TO_PC	BIT(3)		/* 1 -> Direction is to PC	*/

/*
 * Controller Commands.
 */
#define	CC_SELECT	0x01		/* Select Drive 0 		*/
#define	CC_LOCK		0x11		/* Select Drive 0 and Lock	*/
#define	CC_BOT		0x21		/* Rewind to beginning of tape	*/
#define	CC_ERASE	0x22		/* Completely erase cartridge	*/
#define	CC_TENSION	0x24		/* Wind tape to BOT, EOT, BOT	*/
#define	CC_AUTO		0x25		/* Select auto-initialization	*/
#define	CC_QIC11	0x26		/* Select QIC-11 media format	*/
#define	CC_QIC24	0x27		/* Select QIC-24 media format	*/
#define	CC_WRITE	0x40		/* Write to tape		*/
#define	CC_WFM		0x60		/* Write file mark		*/
#define	CC_READ		0x80		/* Read from tape		*/
#define	CC_RFM		0xA0		/* Skip past next file mark	*/
#define	CC_SENSE	0xC0		/* Read controller status	*/

/*
 * Sense Status Bytes 0 and 1.
 */
#define	SS0_FIL		BIT(0)		/* File Mark Detected		*/
#define	SS0_BNL		BIT(1)		/* Bad Block Not located	*/
#define	SS0_UDA		BIT(2)		/* Unrecoverable data error	*/
#define	SS0_EOM		BIT(3)		/* End of media			*/
#define	SS0_WRP		BIT(4)		/* Write Protected Cartridge	*/
#define	SS0_USL		BIT(5)		/* Unselected Drive		*/
#define	SS0_CNI		BIT(6)		/* Cartridge Not In Place	*/
#define	SS0_ERR		(SS0_BNL+SS0_UDA+SS0_USL+SS0_CNI)

#define	SS1_POR		BIT(0)		/* Power on Reset Occurred	*/
#define	SS1_BOM		BIT(3)		/* Beginning of media		*/
#define	SS1_MBD		BIT(4)		/* Marginal Block Detected	*/
#define	SS1_NDT		BIT(5)		/* No Data Detected		*/
#define	SS1_ILL		BIT(6)		/* Illegal Command		*/
#define	SS1_ERR		(SS1_NDT+SS1_ILL)

/*
 * Device States.
 */
#define	SDEAD	0		/* controller not found    */
#define	SIDLE	1		/* controller idle	   */
#define	SCMD	2		/* initiating command	   */
#define	SRUN	3		/* performing command	   */
#define	SRDWR	4		/* starting read/write	   */
#define	SBLOCK	5		/* performing read/write   */
#define	SBLEND	6		/* concluding block i/o	   */
#define	SSENSE	7		/* reading status bytes	   */
#define	SSDONE	8		/* concluding status sense */

/*
 * Driver State Information.
 */
struct st_s {
	int	st_state;
	int	st_mode;		/* IPR or IPW			*/
	int	st_iocmd;		/* CC_READ or CC_WRITE		*/
	int	st_cmd;			/* last command	executed	*/
	int	st_cmds[NCMDS];		/* list of chained commands	*/
	int	st_ncmds;		/* num of chained commands	*/
	int	st_iswr;
	int	st_wasio;
	int	st_iseof;
	int	st_error;
	paddr_t	st_paddr;
	fsize_t	st_resid;
	fsize_t	st_size;
	saddr_t	st_sel;
	SEG *	st_seg;
	char	st_status[6];
	int	st_nstat;
	int	st_rdys;		/* number of ready watchdogs	*/
	int	st_nlost;		/* number of lost interrupts	*/
} st;

/**
 *
 * void
 * stload()		-- initialize tape device
 *
 *	Action:	Reset tape controller and drive.
 *		Seize tape interrupt vector.
 *
 *	Note:	If the tape controller is present and operational,
 *		a interrupt will occur and set st.st_state to SIDLE.
 */
static
stload()
{
	/*
	 * Paranoia - Turn off DMA.
	 * Should already be turned off.
	 */
	dmaoff( STDMA );

	/*
	 * Reset tape controller and drive
	 */
	outb( CTRL_REG, CR_RSTSAC );

	/*
	 * Wait at least 25 microseconds
	 */
	stspin( 25 );

	/*
	 * Terminate reset condition
	 */
	outb( CTRL_REG, CR_IEN );

	/*
	 * Seize tape interrupt vector.
	 */
	setivec( STIRQ, &stintr );
}

/**
 *
 * stuload( dev )		-- Unload tape device.
 * dev_t dev;
 */
stuload( dev )
dev_t dev;
{
	/*
	 * Turn off DMA.
	 */
	dmaoff( STDMA );

	/*
	 * Release tape interrupt vector.
	 */
	clrivec( STIRQ );

	/*
	 * Disable tape interrupts.
	 */
	outb( CTRL_REG, 0 );
}

/**
 *
 * stopen( dev, mode )		-- open tape device
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev  = tape device to be opened.
 *		mode = desired access mode.
 *
 *	Action:	Refuse access if tape drive does not exist or is in use.
 *		Refuse simultaneous read and write access.
 *		Refuse access if cartridge is not inserted in tape drive.
 *		Refuse write access to a write protected cartridge.
 *		Allocate tape cache.
 *		Initialize device state.
 *		Lock tape cartridge.
 */
static
stopen( dev, mode )
register dev_t	dev;
register int	mode;
{
	int s;

	/*
	 * Refuse access if no tape drive.
	 */
	if ( st.st_state == SDEAD ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Refuse access if tape drive is already open.
	 */
	if ( st.st_mode != 0 ) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Access must be read-only or write-only.
	 */
	if ( (mode != IPR) && (mode != IPW) ) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * Wait for tape drive to become idle.
	 */
	if ( stwait() < 0 ) {
		u.u_error = EINTR;
		return;
	}

	/*
	 * Initialize tape interface.
	 */
	s = sphi();
	outb( DMARST_REG, 0 );
	outb( CTRL_REG, CR_IEN );
	spl( s );

	/*
	 * Obtain tape status.
	 */
	stinvoke( CC_SENSE );

	/*
	 * Wait for tape status.
	 */
	if ( stwait() < 0 ) {
		u.u_error = EINTR;
		return;
	}

	/*
	 * Refuse access if no cartridge.
	 */
	if ( st.st_status[0] & (SS0_CNI|SS0_USL) ) {
		u.u_error = EDATTN;
		return;
	}

	/*
	 * Refuse write access to a write protected cartridge.
	 */
	if ( (mode == IPW) && (st.st_status[0] & SS0_WRP) ) {
		u.u_error = EROFS;
		return;
	}

	/*
	 * Calculate desired cache size in Kbytes.
	 */
	st.st_size = minor(dev) & ~0x80;
	if ( st.st_size == 0 )
		st.st_size = 256;

	/*
	 * Allocate cache
	 */
	for ( st.st_size *= 1024; st.st_size != 0; st.st_size -= 1024 )
		if ( st.st_seg = salloc( st.st_size, SFSYST|SFNSWP|SFNCLR ) )
			break;

	/*
	 * Refuse access if couldn't allocate cache.
	 */
	if ( st.st_seg == 0 ) {
		u.u_error = ENOMEM;
		return;
	};

	/*
	 * Initialize device state.
	 */
	st.st_sel   = FP_SEL(st.st_seg->s_faddr);
	st.st_iswr  = (mode == IPW);
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = (mode == IPW) ? st.st_size : 0 ;
	st.st_iocmd = (mode == IPW) ? CC_WRITE : CC_READ ;
	st.st_mode  = mode;
	st.st_iseof = 0;
	st.st_wasio = 0;
	st.st_error = 0;
	st.st_rdys  = 0;
	st.st_nlost = 0;

	/*
	 * Lock cartridge if at beginning of media.
	 */
	if ( st.st_status[1] & SS1_BOM )
		stinvoke( CC_LOCK );
}

/**
 *
 * stclose( dev, mode )		-- close tape device
 * dev_t dev;
 * int mode;
 *
 *	Input:	dev  = tape device to be closed.
 *		mode = access mode.
 *
 *	Action:	If access mode was for writing, flush the tape cache.
 *		If data was written to tape, write a file mark.
 *		If data was read from tape on the non rewinding device,
 *		read until end of file or an error is encountered.
 *		Rewind the tape if the rewinding device is open.
 *		Unlock the tape cartridge.
 *		Clear tape state and release tape cache memory.
 */
static
stclose( dev, mode )
register dev_t dev;
{
	/*
	 * Check if tape was opened for writing.
	 */
	if ( st.st_iswr ) {

		/*
		 * Flush the tape cache.
		 */
		stflush();

		/*
		 * Write a file mark if data was written to tape.
		 */
		if ( st.st_wasio )
			stinvoke( CC_WFM );
	}

	/*
	 * Check if non-rewinding device was opened for reading.
	 */
	else if ( st.st_wasio && (dev & 0x80 ) ) {

		/*
		 * Read file mark if not just past one.
		 */
		if ( (st.st_status[0] & SS0_FIL) == 0 )
			stinvoke( CC_RFM );
	}

	/*
	 * Rewinding device.
	 */
	if ( (dev & 0x80) == 0 ) {

		/*
		 * Wait for controller to idle.
		 */
		while ( stwait() < 0 )
			;

		/*
		 * Initiate rewind.
		 */
		stinvoke( CC_BOT   );

		/*
		 * Unlock the drive [turn off the light].
		 */
		stinvoke( CC_SELECT );
	}

	/*
	 * Clear tape state, releasing tape cache.
	 */
	sfree( st.st_seg );
	st.st_seg  = 0;
	st.st_mode = 0;
}

/**
 *
 * stread( dev, iop )	-- tape device read
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = tape device to be read from.
 *		iop = pointer to IO structure.
 *
 *	Action:	Transfer data from tape cache to user memory,
 *		filling the cache as required by initiating reads from tape.
 */

static
stread( dev, iop )
dev_t	dev;
register IO * iop;
{
	register int n;
	register int ioc;

	ioc = iop->io_ioc;
	
	while ( iop->io_ioc > 0 ) {

		/*
		 * Check for empty cache.
		 */
		while ( st.st_resid == 0 ) {

			/*
			 * Special handling if end of file was encountered.
			 */
			if ( st.st_iseof ) {

				/*
				 * Clear EOF if no data was transferred yet.
				 */
				if ( ioc == iop->io_ioc )
					st.st_iseof = 0;

				return;
			}

			/*
			 * Abort on I/O error.
			 */
			if ( u.u_error = st.st_error ) {
				stdiag();
				return;
			}

			/*
			 * Fill the cache from tape.
			 */
			stcache();
		}

		/*
		 * Determine max data transferable in one chunk.
		 */
		n = iop->io_ioc;
		if ( n > st.st_resid )
			n = st.st_resid;

		/*
		 * Transfer some data from cache to user memory.
		 */
		if ( pucopy( st.st_paddr, iop->io_base, n ) != n )
			return;

		/*
		 * Update addresses and counts.
		 */
		iop->io_base += n;
		iop->io_ioc  -= n;
		st.st_resid  -= n;
		st.st_paddr  += n;
	}
}

/**
 *
 * stwrite( dev, iop )	-- write to tape device
 * dev_t dev;
 * IO * iop;
 *
 *	Input:	dev = tape device to be written to.
 *		iop = pointer to IO structure.
 *
 *	Action:	Transfer data from user memory to tape cache,
 *		flushing the cache as required by initiating writes to tape.
 */

static
stwrite( dev, iop )
dev_t	dev;
register IO *iop;
{
	register int n;

	while ( iop->io_ioc > 0 ) {

		/*
		 * Determine max data transferable in one chunk.
		 */
		n = iop->io_ioc;
		if ( n > st.st_resid )
			n = st.st_resid;

		/*
		 * Transfer some data from user memory to cache.
		 */
		if ( upcopy( iop->io_base, st.st_paddr, n ) != n )
			break;

		/*
		 * Update addresses and counts.
		 */
		iop->io_base += n;
		iop->io_ioc  -= n;
		st.st_paddr  += n;
		st.st_resid  -= n;

		/*
		 * Flush the cache to tape if full.
		 */
		if ( st.st_resid == 0 )
			stflush();

		/*
		 * Abort on I/O error.
		 */
		if ( u.u_error = st.st_error ) {
			stdiag();
			return;
		}
	}
}

/**
 *
 * stioctl( dev, cmd, arg )	-- service tape I/O control requests
 * int dev;
 * int cmd;
 * int arg;
 *
 *	Input:	dev = tape device to be serviced
 *		cmd = ioctl command
 *		arg = argument to ioctl command
 *
 *	Action:	Service tape I/O control request.
 */

static
stioctl( dev, cmd, arg )
{
	if ( st.st_iswr )
		stflush();

	st.st_error = EINVAL;

	switch ( cmd ) {

	case MTERASE:
		stinvoke( CC_ERASE );
		break;

	case MTTENSE:
		stinvoke( CC_TENSION );
		break;

	case MTREWIND:
		if ( st.st_iswr && st.st_wasio ) {
			stinvoke( CC_WFM );
			st.st_wasio = 0;
		}
		stinvoke( CC_BOT );
		break;

	case MTWEOF:
		if ( st.st_iswr ) {
			stinvoke( CC_WFM );
			st.st_wasio = 0;
		}
		break;

	case MTFSKIP:
		if ( ! st.st_iswr ) {
			if ( ! st.st_iseof )
				stinvoke( CC_RFM );
			st.st_iseof = 0;
			st.st_resid = 0;
		}
		break;
	}

	/*
	 * Record tape error code.
	 */
	u.u_error = st.st_error;
}

/**
 *
 * void
 * stcache()	-- read from tape into cache
 *
 *	Action:	Read as much data as possible into the tape cache.
 *		Set st.st_paddr to the cache address.
 *		Set st.st_resid to the number of data bytes in the cache.
 */
static void
stcache()
{
	/*
	 * Try to fill cache from tape.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size;
	ststart();

	/*
	 * Update cache information.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size - st.st_resid;

	/*
	 * Clear the cache on I/O error.
	 */
	if ( st.st_error )
		st.st_resid = 0;
}

/**
 *
 * void
 * stflush()	-- flush cache to tape
 *
 *	Action:	Ensure tape cache is block aligned.
 *		Write cache to the tape.
 *		Set st.st_paddr to the cache address.
 *		Set st.st_resid to the number of cache bytes available.
 */
static void
stflush()
{
	static char zc;

	/*
	 * Check for empty cache.
	 */
	if ( st.st_resid == st.st_size )
		return;

	/*
	 * Block align the cache.
	 */
	while ( st.st_resid % BSIZE ) {
		kpcopy( &zc, st.st_paddr, 1 );
		st.st_paddr++;
		st.st_resid--;
	}

	/*
	 * Flush the cache to tape.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size - st.st_resid;
	ststart();

	/*
	 * Update cache information.
	 */
	st.st_paddr = st.st_seg->s_paddr;
	st.st_resid = st.st_size;
}

/**
 *
 * void
 * stinvoke()	-- start tape control operation
 *
 *	Action:	Initiate tape control operation.
 */
static void
stinvoke( cmd )
int cmd;
{
	register int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Wait for controller to become idle.
	 */
	while ( st.st_state != SIDLE ) {

		/*
		 * Create chained command if possible.
		 */
		if ( st.st_ncmds < NCMDS ) {
			st.st_cmds[ st.st_ncmds++ ] = cmd;
			spl( s );
			return;
		}

		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );
	}

	/*
	 * Setup for tape operation.
	 */
	drvl[STMAJ].d_time = 1;
	st.st_state = SCMD;
	st.st_error = 0;
	st.st_rdys  = 0;
	stspin( 100 );

	/*
	 * Request tape operation.
	 * Do NOT wait for results.
	 */
	outb( DATA_REG, st.st_cmd = cmd );
	outb( CTRL_REG, CR_IEN+CR_REQ );

	/*
	 * Enable interrupts.
	 */
	spl( s );
}

/**
 *
 * void
 * ststart()	-- start tape read/write operation
 *
 *	Action:	Initiate tape read/write operation.
 *		Wait for tape operation to complete.
 */
static void
ststart()
{
	register int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Wait for controller to become idle.
	 */
	while ( st.st_state != SIDLE )
		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );

	/*
	 * Setup for tape read/write.
	 */
	drvl[STMAJ].d_time = 1;
	st.st_state = SRDWR;
	st.st_error = 0;
	st.st_rdys  = 0;
	stspin( 100 );

	/*
	 * Tape read/write was last command executed.
	 */
	if ( st.st_cmd == st.st_iocmd ) {
		/*
		 * Resume tape i/o operation.
		 * Simulate RDY interrupt.
		 */
		stintr();
	}
	else {
		/*
		 * Request tape operation.
		 */
		outb( DATA_REG, st.st_cmd = st.st_iocmd );
		outb( CTRL_REG, CR_IEN+CR_REQ );
	}

	/*
	 * Wait for tape operation to complete.
	 */
	while ( st.st_state != SIDLE )
		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );

	/*
	 * Enable interrupts.
	 */
	spl( s );
}

/**
 *
 * void
 * stintr()	-- tape interrupt handler
 *
 *	Action:	Service tape interrupts.
 *		Perform transitions to new tape states.
 *		Wake sleeping processes if appropriate.
 */
static void
stintr()
{
	register int csr;
	register int s;

	s   = sphi();
	csr = inb( CTRL_REG );

	/*
	 * Initiate exception recovery.
	 */
	if ( (csr & SR_NEXC) == 0 ) {
		strecov();
		spl( s );
		return;
	}

	/*
	 * Clear ready watchdog count.
	 */
	st.st_rdys = 0;

	/*
	 * Process normal operations.
	 */
	switch ( st.st_state ) {

	case SCMD:
		/*
		 * Command has been acknowledged.
		 * Wait for command completion.
		 */
		outb( CTRL_REG, CR_IEN );
 		st.st_state = (st.st_cmd == CC_SENSE) ? SSENSE : SRUN;
 		st.st_nstat = 0;
		break;

	case SRUN:
		/*
		 * Command has completed.
		 * Chain a sense status command if no other chained commands.
		 */
		if ( st.st_ncmds == 0 )
			st.st_cmds[ st.st_ncmds++ ] = CC_SENSE;

		/*
		 * Initiate next chained command.
		 */
		stnext();
		break;

	case SRDWR:
		/*
		 * Read/Write command had been acknowledged.
		 * Clear tape request, enable done interrupt.
		 */
		outb( CTRL_REG, CR_IEN+CR_DNIEN );

		/*
		 * Define direct memory access parameters.
		 */
		dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr );

		/*
		 * If tape read command, wait for interface to switch direction
		 */
		if ( st.st_iocmd == CC_READ )
			while ( (inb(CTRL_REG) & SR_TO_PC) != SR_TO_PC )
				;

		/*
		 * Enable DMA transfer on tape interface and at DMA controller chip.
		 */
		st.st_state = SBLOCK;
		outb( DMAGO_REG, 0 );
		dmago( STDMA );
		break;

	case SBLOCK:
		/*
		 * Perform Block I/O.
		 * Ignore RDY interrupt, wait for [DMA] DONE interrupt.
		 */
		if ( (csr & SR_DONE) == 0 )
			break;

		/*
		 * Turn off DMA.
		 */
		dmaoff( STDMA );

		/*
		 * If more data remains to be transferred, reenable DMA.
		 * NOTE: do -= BEFORE if() to avoid potential compiler bug.
		 */
		st.st_resid -= BSIZE;
		if ( st.st_resid > 0 ) {
			st.st_paddr += BSIZE;
			dmaon( STDMA, st.st_paddr, BSIZE, st.st_iswr );
			outb( DMAGO_REG, 0 );
			dmago( STDMA );
			break;
		}

		/*
		 * Disable done interrupt.
		 * Wait for I/O completion.
		 */
		outb( CTRL_REG, CR_IEN );
		st.st_state = SBLEND;
		break;

	case SBLEND:
		/*
		 * Completion of Block I/O.
		 * Clear the file mark and beginning of media indicators.
		 * Record the fact that data has been transferred.
		 */
		st.st_status[0] &= ~SS0_FIL;
		st.st_status[1] &= ~SS1_BOM;
		st.st_wasio = 1;
		stnext();
		break;

	case SSENSE:
		/*
		 * Sense Status Byte.
		 * Wait for availability.
		 */
		do {
			csr = inb(CTRL_REG) & (SR_NRDY|SR_TO_PC);
		} while ( csr != SR_TO_PC );

		/*
		 * Save status byte.
		 */
		st.st_status[st.st_nstat] = inb(DATA_REG);

		/*
		 * Acknowledge reception.
		 * CR_REQ must be present for at least 20 microseconds.
		 */
		outb( CTRL_REG, CR_IEN+CR_REQ );
		stspin( 20 );
		outb( CTRL_REG, CR_IEN );

		/*
		 * Change state to status completion if all bytes saved.
		 */
		if ( ++(st.st_nstat) == 6 )
			st.st_state = SSDONE;
		break;

	case SSDONE:
		/*
		 * Completion of Sense Status Command.
		 * Check for file mark.
		 */
		if ( st.st_status[0] & SS0_FIL ) {
			outb( DMARST_REG, 0 );
			st.st_iseof = 1;
		}

		/*
		 * Check for I/O error.
		 */
		else if ( (st.st_status[0] & SS0_ERR) ||
			  (st.st_status[1] & SS1_ERR) ) {
			st.st_error = EIO;
		}

		/*
		 * Check for write protected cartridge.
		 */
		else if ( (st.st_iocmd == CC_WRITE) &&
			  (st.st_status[0] & SS0_WRP) ) {
			st.st_error = EROFS;
		}

		stnext();
		break;
	}

	spl( s );
}

/**
 *
 * void
 * strecov()	-- initiate recovery from exception conditions
 *
 *	Action:	Invoked when the tape controller asserts EXCEPTION.
 *		A sense status command is initiated to clear the exception.
 */
static void
strecov()
{
	/*
	 * Ensure tape interface is idle.
	 */
	outb( CTRL_REG, CR_IEN );
	stspin( 100 );

	/*
	 * Turn off DMA on read/write exception.
	 */
	if ( st.st_cmd == st.st_iocmd )
		dmaoff( STDMA );

	/*
	 * Initiate sense status command.
	 */
	outb( DATA_REG, st.st_cmd = CC_SENSE );
	outb( CTRL_REG, CR_IEN+CR_REQ );
	drvl[STMAJ].d_time = 1;
	st.st_state = SCMD;
	st.st_error = 0;
	st.st_rdys  = 0;
}

/**
 *
 * static void
 * stnext()	-- initiate next chained command.
 */
static void
stnext()
{
	/*
	 * Ensure tape interface is idle.
	 */
	outb( CTRL_REG, CR_IEN );
	drvl[STMAJ].d_time = 0;
	st.st_state = SIDLE;
	stspin( 100 );

	/*
	 * Initiate a chained command.
	 */
	if ( st.st_ncmds ) {
		outb( DATA_REG, st.st_cmd = st.st_cmds[ --st.st_ncmds ] );
		outb( CTRL_REG, CR_IEN+CR_REQ );
		drvl[STMAJ].d_time = 1;
		st.st_state = SCMD;
		st.st_error = 0;
		st.st_rdys  = 0;
		return;
	}

	/*
	 * Wake waiting processes.
	 */
	wakeup( &st );
}

/**
 *
 * void
 * stwatch()	-- periodic [1 sec] watchdog
 *
 *	Action:	If an exception condition exists, initate recovery actions.
 *		If ready condition exists for 1-2 seconds, simulate interrupt.
 *
 *	Notes:	If an exception condition occurs after a ready interrupt has
 *		been serviced, but before the ready condition is cleared,
 *		the exception interrupt will not occur, and is simulated here.
 */
static void
stwatch()
{
	register int csr;
	register int s;

	/*
	 * Disable interrupts, preventing critical race with stintr().
	 */
	s   = sphi();
	csr = inb(CTRL_REG);

	/*
	 * Initiate recovery from exception conditions.
	 */
	if ( (csr & SR_NEXC) == 0 )
		strecov();

	/*
	 * Reset ready watchdog if not ready.
	 */
	else if ( csr & SR_NRDY ) 
		st.st_rdys = 0;

	/*
	 * Simulate lost ready interrupts after 2 seconds.
	 */
	else if ( ++st.st_rdys >= 2 )
		stintr();

	/*
	 * Enable interrupts.
	 */
	spl( s );
}

/**
 * 
 * void
 * stdiag()	- Report tape status.
 *
 *	Action:	Identify and report the highest priority tape error.
 *		There will normally only be one valid error present.
 *		The USL error can invalidate most remaining flags.
 *		The CNI error can invalidate cartridge related flags.
 *
 *	Notes:	Never called from interrupt level, but always from background.
 */
static void
stdiag()
{
	if ( st.st_status[0] & SS0_USL )
		printf( "st: Unselected Drive\n" );

	else if ( st.st_status[0] & SS0_CNI )
		printf( "st: Cartridge missing\n" );

	else if ( st.st_status[1] & SS1_NDT )
		printf( "st: No data detected\n" );

	else if ( st.st_status[0] & SS0_BNL )
		printf( "st: Bad block not located\n" );

	else if ( st.st_status[0] & SS0_UDA )
		printf( "st: Unrecoverable data error\n" );

	else if ( st.st_status[1] & SS1_ILL )
		printf( "st: Illegal command\n" );

	else
		printf( "st: %x\n", (st.st_status[1] << 8) + st.st_status[0] );
}

/**
 *
 * int
 * stwait()	-- wait for tape controller to idle.
 *
 *	Return:	0  = tape controller idle.
 *		-1 = signal received.
 */
static int
stwait()
{
	int s;

	s = sphi();
	while ( st.st_state != SIDLE ) {

		sleep( &st, CVTTOUT, IVTTOUT, SVTTOUT );

		if ( SELF->p_ssig ) {
			spl( s );
			return -1;
		}
	}
	spl( s );

	return 0;
}

/**
 *
 * void
 * stspin( usec )	-- delay execution
 * int usec;
 *
 *	Input:	usec = number of micro-seconds to delay.
 *
 *	Action:	Wait at least 'usec' micro-seconds.
 *
 *	Notes:	Provides minimum delay required at times by tape controller.
 *		Should function properly up to at least 16 Mhz system clock.
 */

static void
stspin( usec )
register int usec;
{
	while ( --usec >= 0 )
		;
}
@


1.1
log
@Initial revision
@
text
@d10 1
a10 1
#include	<coherent.h>
@
0707070064030106321004440000030000030000011777770507310702200006200000001273/newbits/kernel/USRSRC/i8086/drv/RCS/template.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.55.08;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.28.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/*
 * File:
 *
 * Purpose:
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 */

/*
 * Includes.
 */

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
@


1.1
log
@Initial revision
@
text
@@
0707070064030106311004440000030000030000011777770507310702200005400000065450/newbits/kernel/USRSRC/i8086/drv/RCS/tn.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.55.15;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.28.41;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Tiac ARCNET PC-234 Device Driver
 *
 * True support for up to 4 network cards through minor devices 0-3.
 * Up to 4 protocols now supported.  Novell access is through normal
 * minor device.  Netbios access is through novell minor device + 16.
 */

#include <sys/coherent.h>
#include <sys/con.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>
#include <sys/tnioctl.h>
#include <errno.h>

/*
 * Network Major Device.
 */
#define	TNMAJOR	20

/*
 * External functions.
 */
extern int  wakeup();
extern void pollwake();
extern void defer();

/*
 * Driver functions.
 */
void	tnopen();
void	tnclose();
int	tnread();
int	tnwrite();
int	tnioctl();
void	tncycle();
void	tnload();
void	tnuload();
int	tnpoll();
int 	nonedev();
int	nulldev();
void	tn0intr();
void	tn1intr();
void	tn2intr();
void	tn3intr();
void	tnintr();

/*
 * Driver Configuration.
 */
CON
tncon = {
	DFCHR|DFPOL,			/* Flags	*/
	TNMAJOR,			/* Major Index	*/
	tnopen,				/* Open		*/
	tnclose,			/* Close	*/
	nonedev,			/* Block	*/
	tnread,				/* Read		*/
	tnwrite,			/* Write	*/
	tnioctl,			/* Ioctl	*/
	nulldev,			/* Power fail	*/
	tncycle,			/* Timeout	*/
	tnload,				/* Load		*/
	tnuload,			/* Unload	*/
	tnpoll				/* Poll		*/
};

/*
 * Interrupt Entry Points.
 */
void (*tnintf[4])() = {
	tn0intr,
	tn1intr,
	tn2intr,
	tn3intr
};

#define	BIT(n)		(1 << (n))

/*
 * Bitmask, indexed by bit numbers 0..7.
 */
static unsigned char bitm[8] = { BIT(0), BIT(1), BIT(2), BIT(3),
				 BIT(4), BIT(5), BIT(6), BIT(7) };

/*
 * Patchable parameters - Cards 0-3.
 */
		/* Card    0       1       2      3  */
int	TNIRQ [4] = {      2,      7,      4,      0 };
saddr_t	TNSEL [4] = { 0xD000, 0x0000, 0x0000, 0x0000 };
int	TNPORT[4] = {  0x2E0,  0x220,  0x240,  0x000 };

/*
 * Patchable parameters - Prefix Byte.
 * Indexed by high nibble of minor device.
 */
int	TNPREFIX[4] = { 0x00,   0xF3,   0x00,   0x00 };

/*
 * Patchable variables.
 * TNTIME = Transmit watchdog timer in seconds.
 */
int TNTIME = 5;

/*
 * Register addresses.
 */
#define	NIR		(tp->tnport)	/* Network Interrupt Mask Reg (w)  */
#define	NSR		(tp->tnport)	/* Network Status Register    (r)  */
#define	NCR		(tp->tnport+1)	/* Network Command Register   (w)  */
#define	NZR		(tp->tnport+8)	/* Network Zap (reset) Reg    (w)  */

/*
 * Network Interrupt Register (NIR).
 */
#define	NI_Tx		BIT(0)		/* Enable Transmitter Avail Intr   */
#define	NI_RECON	BIT(2)		/* Enable Reconfiguration   Intr   */
#define	NI_Rx		BIT(7)		/* Enable Receiver Full     Intr   */

/*
 * Network Status Register (NSR).
 */
#define	NS_TxRDY	BIT(0)		/* Transmitter Available	   */
#define	NS_TxACK	BIT(1)		/* Transmit Message Acknowledged   */
#define	NS_RECON	BIT(2)		/* Network Reconfiguration	   */
#define	NS_TEST		BIT(3)		/* Test				   */
#define	NS_POR		BIT(4)		/* Power on Reset		   */
#define	NS_ETS1		BIT(5)		/* Extended Timeout Status 1	   */
#define	NS_ETS2		BIT(6)		/* Extended Timeout Status 2	   */
#define	NS_RxRDY	BIT(7)		/* Packet Received - Receiver Off  */

/*
 * Network Command Register (NCR).
 */
#define	NC_TxDIS	(((0)<<3) + 1)	/* Disable Transmitter		   */
#define	NC_RxDIS	(((0)<<3) + 2)	/* Disable Receiver		   */
#define	NC_TxENA(n)	(((n)<<3) + 3)	/* Enable Transmitter on Page n	   */
#define	NC_RxENA(n)	(((n)<<3)+0x84)	/* Enable Receiver    on Page n    */
#define	NC_DFC		(((1)<<3) + 5)	/* Define Configuration (2k buf)   */
#define	NC_POR		(((1)<<3) + 6)	/* Clear NS_POR flag		   */
#define	NC_RECON	(((2)<<3) + 6)	/* Clear NS_RECON flag		   */

/*
 * Packet Control.
 */
struct tnet_s {

	/*
	 * Four buffers per card - 2 receive, 2 transmit.
	 */
	struct tnbuf_s {		/* tnget*,tnput* use tn_sel:tn_off */
		unsigned	tn_off;	/* tn_sel:tn_off  = current byte   */
		saddr_t		tn_sel;	/* network buffer selector	   */
		struct tnbuf_s *tn_next;/* pointer to next pkt in queue	   */
		unsigned	tn_ena;	/* Command to enable packet	   */
		unsigned	tn_base;/* tn_sel:tn_base = pkt address	   */
		unsigned	tn_xnid;/* Transmit node id		   */
		unsigned	tn_xlen;/* Transmit length		   */
	} tnbuf [4];

	struct tnbuf_s *	RxBusy[4];/* Queues of full receive packets*/
	struct tnbuf_s *	RxIdle;	/* Queue of empty receive packets  */

	struct tnbuf_s *	TxBusy;	/* Queue of full transmit packets  */
	struct tnbuf_s *	TxIdle;	/* Queue of empty transmit packets */

	event_t			RxPoll[4];/* Polls for input packets	   */
	event_t			TxPoll;	/* Polls for empty output packets  */

	char			RxReq[4];/* 1 = Proc waiting for recv buf  */
	char			TxReq;	/* 1 = Proc waiting for xmit buf   */
	char			refc[4];/* # opens, indexed by prefix code */

	unsigned		tnmask;	/* Interrupt enable mask	   */
	unsigned		tnport;	/* Base I/O port		   */
	char			tnaddr[8];/* ARC-NET Node ID, low byte 1st */

	unsigned		tntime;	/* transmit watchdog timer	   */
	unsigned		recon;	/* number of long reconfigurations */
	unsigned		pri;	/* priority event occurred	   */
	long			rbolt;	/* lbolt at last reconfiguration   */
	unsigned char		bad[32];/* bit mask of bad nodes	   */
	unsigned char		mod[32];/* bit mask of changed nodes	   */
	long			recons;	/* reconfiguration statistic	   */
	SEG *			statseg;/* Segment containing stats	   */

} tnet [4];

/*
 * Load Routine.
 */
void
tnload()
{
	register struct tnet_s  * tp;
	register struct tnbuf_s * np;
	faddr_t faddr;
	paddr_t paddr;
	int i;
	int nid;
	long delay;

	for ( tp = &tnet[0], i = 0; i < 4; i++, tp++ ) {

		/*
		 * Validate patchable parameters.
		 */
		if ( (TNSEL[i] == 0) || (TNPORT[i] == 0) || (TNIRQ[i] == 0) ) {
			TNPORT[i] = 0;
			TNSEL[i]  = 0;
			TNIRQ[i]  = 0;
			continue;
		}

		tp->tnport = TNPORT[i];

		/*
		 * Clear Power-On-Reset Flag.
		 */
		outb( NCR, NC_POR );

		/*
		 * Validate card presence.
		 * NOTE: tp->tnport must be programmed before using NIR macro.
		 */
		if ( inb(NSR) & (NS_TEST|NS_POR) ) {
			tp->tnport = 0;
			continue;
		}

		/*
		 * Convert physical address into virtual address.
		 */
		paddr = TNSEL[i] << 4L;
		faddr = ptov( paddr, (fsize_t) 2048 );

		/*
		 * Verify dual-port memory existence.
		 * NOTE: Do not overwrite first two bytes [0xD1,nid].
		 */
		sfword( faddr+8, 0x1234 );
		if ( ffword( faddr+8 ) != 0x1234 ) {
			vrelse( faddr );
			tp->tnport = 0;
			continue;
		}

		/*
		 * Allocate statistics segment.
		 */
		tp->statseg = salloc( (fsize_t) (256*NTNST*4), SFSYST|SFHIGH );

		/*
		 * Out of memory.
		 */
		if ( ! tp->statseg ) {
			printf( "tn%d: out of memory\n", i );
			vrelse( faddr );
			tp->tnport = 0;
			continue;
		}

		tp->tnbuf[0].tn_sel =
		tp->tnbuf[1].tn_sel =
		tp->tnbuf[2].tn_sel =
		tp->tnbuf[3].tn_sel = FP_SEL(faddr);

		tp->tnbuf[0].tn_ena  = NC_TxENA(0);
		tp->tnbuf[1].tn_ena  = NC_TxENA(1);
		tp->tnbuf[2].tn_ena  = NC_RxENA(2);
		tp->tnbuf[3].tn_ena  = NC_RxENA(3);

		tp->tnbuf[0].tn_base = 0 * 512;
		tp->tnbuf[1].tn_base = 1 * 512;
		tp->tnbuf[2].tn_base = 2 * 512;
		tp->tnbuf[3].tn_base = 3 * 512;

		/*
		 * Initialize transmit idle queue.
		 */
		tp->TxIdle		= &tp->tnbuf[0];
		tp->tnbuf[0].tn_next	= &tp->tnbuf[1];

		/*
		 * Initialize receive idle queue.
		 */
		tp->RxIdle		= &tp->tnbuf[2];
		tp->tnbuf[2].tn_next	= &tp->tnbuf[3];

		/*
		 * Validate Node Id.
		 */
		np = &tp->tnbuf[0];
		np->tn_off = 0;
		if ( tngetc(np) != 0xD1 ) {

			/*
			 * Initiate Power On Reset.
			 */
			outb( NZR, 1 );

			/*
			 * Wait minimimum of 180 [suggest 250] milli-seconds.
			 * Should function properly up to at least 16 Mhz clock.
			 */
			for ( delay = 250000L; --delay != 0; )
				;
		}

		/*
		 * Validate and Remember Node Id.
		 */
		np->tn_off = 0;
		if ( tngetc(np) == 0xD1 )
			tp->tnaddr[0] = tngetc( np );

		/*
		 * Record starting time of statistics collection.
		 */
		faddr = tp->statseg->s_faddr + TnELAPSED*4;
		for ( nid = 0; nid < 256; nid++, faddr += NTNST*4 )
			kfcopy( &lbolt, faddr, sizeof(lbolt) );

		memset( tp->bad, -1, 32 );	/* Assume LAN is down	   */
		memset( tp->mod,  0, 32 );	/* Assume no node changes  */
		tp->tnmask = NI_Rx | NI_RECON;	/* Interrupts to enable    */
		outb( NIR, 0 );			/* Disable Interrupts	   */
		outb( NCR, NC_POR );		/* Clear POR Flag	   */
		outb( NCR, NC_DFC );		/* Define 2K buf config	   */
		outb( NCR, NC_TxDIS );		/* Disable Transmitter	   */
		outb( NCR, tp->RxIdle->tn_ena);	/* Enable receiver	   */
		setivec( TNIRQ[i], tnintf[i] );	/* Seize Interrupt Vector  */
		outb( NIR, tp->tnmask );	/* Enable Interrupts       */
	}

	/*
	 * Enable watchdog timer
	 */
	drvl[TNMAJOR].d_time = 1;
}

/*
 * Unload Routine.
 */
void
tnuload( dev )
dev_t dev;
{
	register struct tnet_s  * tp;
	register int i;
	faddr_t faddr;

	/*
	 * Disable watchdog timer.
	 */
	drvl[TNMAJOR].d_time = 0;

	/*
	 * Scan network adaptors.
	 */
	for ( tp = &tnet[0], i = 0; i < 4; i++, tp++ ) {

		if ( tp->tnport == 0 )
			continue;

		/*
		 * Disable Interrupts
		 */
		outb( NIR, 0 );

		/*
		 * Release interrupt vector.
		 */
		clrivec( TNIRQ[i] );

		/*
		 * Release virtual address AFTER disabling interrupts.
		 */
		if ( FP_SEL(faddr) = tp->tnbuf[0].tn_sel )
			vrelse( faddr );

		/*
		 * Release stats segment.
		 */
		if ( tp->statseg != NULL )
			sfree( tp->statseg );
	}
}

/*
 * Open Routine.
 *
 *	Low nibble  of minor device is card identifier 0 to 3.
 *	High nibble of minor device is code identifier 0 to 3.
 */
void
tnopen( dev, mode )
dev_t dev;
{
	register struct tnet_s * tp;
	int card = (dev & 0x0F);
	int code = (dev & 0xF0) >> 4;

	/*
	 * Validate minor device and card existence.
	 */
	if ( (card > 3) || (code > 3) || (tnet[card].tnport == 0)) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Code identifiers 1 to 3 are only valid if a prefix code is known.
	 */
	if ( (code > 0) && (TNPREFIX[code] == 0) ) {
		u.u_error = ENXIO;
		return;
	}

	/*
	 * Access network information.
	 */
	tp = &tnet[card];

	/*
	 * Increment reference count (# opens).
	 */
	tp->refc[code]++;
}

/*
 * Close Routine.
 */
void
tnclose( dev )
dev_t dev;
{
	register struct tnet_s  * tp =tp = &tnet[ dev & 3];
	register struct tnbuf_s * np;
	int code = (dev & 0x30) >> 4;
	int s;

	/*
	 * Decrement reference count.
	 */
	if ( --tp->refc[code] != 0 )
		return;

	/*
	 * Last close.
	 * Release all queued packets.
	 */
	while ( np = tp->RxBusy[code] ) {
		s = sphi( );
		tp->RxBusy[code] = np->tn_next;
		tn_rxena( tp, np );
		spl( s );
	}
}

/*
 * Watchdog Timing Routine
 *
 *	If transmit has been enabled for 1-2 seconds:
 *		Abort transmission of packet, forcing interrupt.
 */
void
tncycle( )
{
	register struct tnet_s * tp;
	register int code;
	int s;

	/*
	 * Scan all network cards.
	 */
	for ( tp = &tnet[0]; tp <= &tnet[3]; tp++ ) {

		if ( ! tp->tnport )
			continue;

		/*
		 * Disable interrupts.
		 */
		s = sphi();

		/*
		 * Enable broadcasts after 5 seconds without reconfiguration.
		 */
		if ( (tp->recon > 0) && ((lbolt - tp->rbolt) > (5*HZ)) ) {
			/*
			 * LAN was previously down.
			 */
			if ( tp->bad[0] & 1 ) {
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnSTATMOD*4, 1 );
				tp->mod[0] |= 1;
				tp->pri = 1;
			}
			tp->bad[0] &= ~1;
			tp->recon   =  0;
		}

		/*
		 * Discard bad packet on transmit watchdog timeout.
		 */
		if ( (tp->tntime > 0) && (--(tp->tntime) == 0) )
			outb( NCR, NC_TxDIS );

		/*
		 * Enable interrupts.
		 */
		spl( s );

		/*
		 * LAN/DEVICE UP/DOWN event has occurred.
		 */
		if ( tp->pri == 1 ) {

			tp->pri = 2;

			for ( code = 0; code < 4; code++ )
				if ( tp->RxPoll[code].e_procp )
					pollwake( &tp->RxPoll[code] );
		}
	}
}

static
tnioctl( dev, com, arg )
dev_t dev;
int com;
register tnattr_t * arg;
{
	register struct tnet_s * tp = &tnet[dev & 3];
	faddr_t fp;
	int nid;
	long t;
	tnattr_t local;			/* to avoid fucopy() problems */

	switch ( com ) {

	case TNGETA:
	case TNGETAF:
		/*
		 * Access node statistics.
		 */
		nid = getubd( &arg->host[5] );
		fp  = tp->statseg->s_faddr + nid * (NTNST*4);

		/*
		 * Disable interrupts to avoid race condition with tnintr().
		 */
		sphi();

		/*
		 * Copy node status.
		 */
		if ( tp->bad[nid/8] & bitm[nid%8] )
			putubd( &arg->bad, 1 );
		else
			putubd( &arg->bad, 0 );

		/*
		 * Copy network reconfigurations to user space.
		 * NOTE: This is not a node statistic, but a network stat.
		 */
		kucopy( &tp->recons, &arg->recons, sizeof(tp->recons) );

		/*
		 * Copy node statistics to user space.
		 */
		fkcopy( fp, &local.stats[0], sizeof(local.stats) );
		kucopy( &local.stats[0], &arg->stats[0], sizeof(arg->stats) );

		/*
		 * Copy true elapsed time of statistics collection.
		 */
		fkcopy( fp+TnELAPSED*4, &t, sizeof(t) );
		t = lbolt - t;
		kucopy( &t, &arg->stats[TnELAPSED], sizeof(arg->stats[0]) );

		/*
		 * Clear node statistics.
		 * NOTE: Elapsed time statistic is time of last clear.
		 */
		if ( com == TNGETAF ) {
			fclear( fp, NTNST * 4 );
			kfcopy( &lbolt, fp+TnELAPSED*4, sizeof(lbolt) );
			if ( nid == 0 )
				tp->recons = 0;
		}

		/*
		 * Enable interrupts.
		 */
		splo();

		return( 0 );

	default:
		u.u_error = EINVAL;
	}
}

/*
 * Polling Routine.
 *
 *	Note:	Double-looks are performed to prevent critical race with
 *		interrupt handlers,  without having to disable interrupts.
 */
static
tnpoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	register struct tnet_s * tp = &tnet[dev & 3];
	int code = (dev & 0x30) >> 4;
	int rev = 0;

	/*
	 * Fast check for priority, input, and output polls.
	 * Priority poll checks for LAN UP/DOWN transition.
	 * Input    poll checks for a full receive buffer.
	 * Output   poll checks for an empty transmit buffer, or LAN down.
	 */
	if ( (ev & POLLPRI) && (tp->pri != 0) )
		rev |= POLLPRI;
	if ( (ev & POLLIN) && (tp->RxBusy[code] != NULL) )
		rev |= POLLIN;
	if ( (ev & POLLOUT) && ((tp->TxIdle != 0) || (tp->bad[0] & 1)) )
		rev |= POLLOUT;

	/*
	 * Fast check found an event, or this is a non-blocking poll.
	 */
	if ( (rev != 0) || (msec == 0) )
		return( rev );

	/*
	 * Blocking Input poll.
	 */
	if ( ev & POLLIN ) {

		pollopen( &tp->RxPoll[code] );

		/*
		 * Second look to avoid interrupt race.
		 */
		if ( tp->RxBusy[code] )
			return( POLLIN );
	}

	/*
	 * Blocking Output poll.
	 */
	if ( ev & POLLOUT ) {

		pollopen( &tp->TxPoll );

		/*
		 * Second look to avoid interrupt race.
		 * NOTE: When the LAN is down broadcasts [nid 0] are disabled.
		 */
		if ( (tp->TxIdle != 0) || (tp->bad[0] & 1) )
			return( POLLOUT );
	}

	return( rev );
}

/*
 * Interrupt Entry Point - Card 0.
 */
void
tn0intr()
{
	tnintr( &tnet[0] );
}

/*
 * Interrupt Entry Point - Card 1.
 */
void
tn1intr()
{
	tnintr( &tnet[1] );
}

/*
 * Interrupt Entry Point - Card 2.
 */
void
tn2intr()
{
	tnintr( &tnet[2] );
}

/*
 * Interrupt Entry Point - Card 3.
 */
void
tn3intr()
{
	tnintr( &tnet[3] );
}

/*
 * Interrupt Handler.
 *
 *	Process transmit/receive interrupts.
 */
void
tnintr( tp )
register struct tnet_s * tp;
{
	register struct tnbuf_s * np;
	register int csr;
	int nid;
	int n;
	int bit;

	/*
	 * Read interrupt status.
	 * Disable interrupts to ensure edge occurs later.
	 */
	csr = inb( NSR );
	tp->tnmask = NI_RECON;
	outb( NIR, 0 );

	/*
	 * Reconfigurations with a period of 840 msec [600-1100]
	 * increment tp->recon.  Other periods clear tp->recon.
	 * After 5 reconfigurations at 840 msecs, the network is down.
	 * After 1 reconfiguration at another interval, the network is up.
	 * Network also comes up in tncycle() 5 seconds after last reconfig.
	 */
	if ( csr & NS_RECON ) {

		outb( NCR, NC_RECON );
		nid = (unsigned) (lbolt - tp->rbolt) * (1000/HZ);
		tp->rbolt = lbolt;
		tp->recons++;

		/*
		 * Not a chained reconfiguration.
		 * Assume the network is up.
		 * NOTE: Expect 840 msecs, but allow interrupt latency slip.
		 */
		if ( (nid < 700) || (nid > 1000) ) {
			if ( tp->bad[0] & 1 ) {
				tp->mod[0] |=  1;
				tp->bad[0] &= ~1;
				tp->pri = 1;
			}
			tp->recon   =  0;
		}

		/*
		 * Chained reconfiguration - threshold exceeded.
		 */
		else if ( (++(tp->recon) == 5) && ((tp->bad[0] & 1) == 0) ) {
			faddr_t fp = tp->statseg->s_faddr;
			aflong( fp+TnSTATMOD*4, 1 );
			memset( tp->bad, -1, sizeof(tp->bad) );
			tp->mod[0] |= 1;
			tp->pri = 1;
		}
	}

	/*
	 * Service Power on Resets.
	 */
	if ( csr & NS_POR ) {

		csr &= ~(NS_RxRDY|NS_TxRDY);	/* Ignore receive/transmit */
		outb( NCR, NC_DFC );		/* Define 2K buf config	   */
		outb( NCR, NC_POR );		/* Clear POR flag	   */

		/*
		 * Enable receiver
		 */
		if ( np = tp->RxIdle )
			outb( NCR, np->tn_ena );

		/*
		 * Enable transmitter
		 */
		if ( np = tp->TxBusy )
			outb( NCR, np->tn_ena );
	}

	/*
	 * Service transmit interupts if transmit is pending.
	 */
	if ( np = tp->TxBusy ) {

		tp->tnmask |= NI_Tx;

		/*
		 * Check for transmission completed.
		 */
		if ( csr & NS_TxRDY ) {

			/*
			 * Destination Node Id is in 2nd byte of packet.
			 */
			np->tn_off = np->tn_base + 1;
			nid = tngetc( np );

			/*
			 * Get length of short/long packets.
			 */
			n = 256 - tngetc(np);
			if ( n == 256 )
				n = 512 - tngetc(np);

			/*
			 * Transmitted packet was acknowledged.
			 */
			if ( csr & NS_TxACK ) {
				/*
				 * Adjust global and node statistics.
				 */
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnTxPACKS*4, 1 );
				aflong( fp+TnTxBYTES*4, n );
				fp += nid * (NTNST * 4);
				aflong( fp+TnTxPACKS*4, 1 );
				aflong( fp+TnTxBYTES*4, n );
			}

			/*
			 * Transmitted packet was discarded.
			 * NOTE: Do not flag broadcast [nid 0] as bad.
			 */
			else if ( nid != 0 ) {
				/*
				 * Adjust global and node statistics.
				 */
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnDISCARD*4, 1 );
				fp += nid * (NTNST * 4);
				aflong( fp+TnDISCARD*4, 1 );
				aflong( fp+TnSTATMOD*4, 1 );

				/*
				 * Flag node as being bad.
				 */
				bit = bitm[ nid % 8 ];
				tp->bad[ nid / 8 ] |= bit;
				tp->mod[ nid / 8 ] |= bit;
				tp->pri = 1;
			}

			/*
			 * Move packet buffer to idle transmit queue.
			 */
			tp->TxBusy  = np->tn_next;
			np->tn_next = tp->TxIdle;
			tp->TxIdle  = np;

			/*
			 * Check for another packet to transmit.
			 */
			if ( np = tp->TxBusy ) {

				/*
				 * Enable transmitter, start watchdog timer.
				 */
				outb( NCR, np->tn_ena );
				tp->tntime = TNTIME;
			}

			/*
			 * Disable Transmit Interrupt, clear watchdog timer.
			 */
			else {
				tp->tnmask &= ~NI_Tx;
				tp->tntime  =  0;
			}

			/*
			 * Wake processes waiting to transmit.
			 */
			if ( tp->TxReq ) {
				tp->TxReq = 0;
				defer( wakeup, &tp->TxReq );
			}

			if ( tp->TxPoll.e_procp )
				defer( pollwake, &tp->TxPoll );
		}
	}

	/*
	 * Check for receive request.
	 */
	if ( np = tp->RxIdle ) {

		tp->tnmask |= NI_Rx;

		/*
		 * Check for packet received.
		 */
		if ( csr & NS_RxRDY ) {

			/*
			 * Remove first packet from receive ready queue.
			 * Re-enable receiver or disable receive interrupts.
			 */
			if ( tp->RxIdle = np->tn_next ) {
				outb( NCR, np->tn_next->tn_ena );
				np->tn_next = 0;
			}
			else
				tp->tnmask &= ~NI_Rx;

			/*
			 * Source Node Id is in 1st byte of packet.
			 */
			np->tn_off = np->tn_base;
			nid = tngetc( np );

			/*
			 * Try to establish our Node Id if not already set.
			 * Destination Node Id (our station)
			 * is in 2nd byte of the received packet.
			 * NOTE: Always read node id byte.
			 *	 This ensures offset bytes can be read.
			 */
			if ( (n = tngetc(np)) && (tp->tnaddr[0] == 0) )
				tp->tnaddr[0] = n;

			/*
			 * Get offset to first data byte in short/long packet.
			 * Short packet offset is in 3rd byte of packet.
			 * Long  packet offset is in 4th byte of packet.
			 */
			if ( n = tngetc(np) )
				np->tn_off = np->tn_base + n;
			else
				np->tn_off = np->tn_base + tngetc(np);

			/*
			 * LAN has come up.
			 * Clear bad flag for the broadcast node.
			 */
			if ( tp->bad[0] & 1 ) {
				tp->bad[ 0 ] &= ~1;
				tp->mod[ 0 ] |=  1;
				tp->pri = 1;
			}

			/*
			 * Node has come up.
			 * Clear bad flag for the Source Node.
			 */
			bit = bitm[ nid % 8 ];
			if ( tp->bad[ nid / 8 ] & bit ) {
				faddr_t fp = tp->statseg->s_faddr;
				aflong( fp+TnSTATMOD*4, 1 );
				fp += nid * (NTNST * 4);
				aflong( fp+TnSTATMOD*4, 1 );
				tp->bad[ nid / 8 ] &= ~bit;
				tp->mod[ nid / 8 ] |=  bit;
				tp->pri = 1;
			}

			/*
			 * Get first data byte from packet.
			 */
			bit = tngetc( np );

			/*
			 * Determine prefix code associated with packet.
			 */
			for ( n = 3; n > 0; n-- ) {
				if ( TNPREFIX[n] == bit )
					break;
			}

			/*
			 * Interface is open.
			 */
			if ( tp->refc[n] ) {

				/*
				 * Append received packet to received queue.
				 * NOTE: At most 2 packets in any queue.
				 */
				if ( tp->RxBusy[n] )
					tp->RxBusy[n]->tn_next = np;
				else
					tp->RxBusy[n] = np;
	
				/*
				 * Wake processes waiting to read.
				 */
				if ( tp->RxReq[n] ) {
					tp->RxReq[n] = 0;
					defer( wakeup, &tp->RxReq[n] );
				}
	
				if ( tp->RxPoll[n].e_procp )
					defer( pollwake, &tp->RxPoll[n] );
			}

			/*
			 * Interface is closed.
			 * Return packet to end of receive idle queue.
			 */
			else
				tn_rxena( tp, np );
		}
	}

	/*
	 * Restore interrupt mask.
	 */
	outb( NIR, tp->tnmask );
}

/*
 * Read Routine.
 *
 *	Wait for a packet to be received.
 *	Transform packet header and copy packet body.
 *	Place packet buffer on receive idle queue.
 *	If receiver was inhibited, enable receiver.
 */


tnread ( dev, iop )

dev_t dev;
register IO * iop;

{
	register struct tnet_s  * tp = &tnet[ dev & 3 ];
	register struct tnbuf_s * np;
	int code = (dev & 0x30) >> 4;
	unsigned len;
	unsigned cnt;
	unsigned srcid;
	int s;

	/*
	 * Driver information requested.
	 */
	if ( iop->io_ioc <= 2 + sizeof(tp->bad) + sizeof(tp->mod) ) {

		/*
		 * Supply null byte, then our node id.
		 */
		ioputc( 0, iop );
		ioputc( tp->tnaddr[0], iop );

		/*
		 * Bad and modified node bit masks requested.
		 * Disable interrupts during transfer to prevent
		 * critical race with tnintr().
		 */
		if ( iop->io_ioc == sizeof(tp->bad) + sizeof(tp->mod) ) {
			sphi();
			iowrite( iop, tp->bad, sizeof(tp->bad) );
			iowrite( iop, tp->mod, sizeof(tp->mod) );
			kclear( tp->mod, sizeof(tp->mod) );
			tp->pri = 0;
			splo();
		}

		/*
		 * Bad node bit mask requested.
		 */
		else if ( iop->io_ioc == sizeof(tp->bad) )
			iowrite( iop, tp->bad, sizeof(tp->bad) );

		return;
	}

	/*
	 * Wait for packet reception.
	 */
	for ( ; ; ) {

		s = sphi( );

		/*
		 * Check for received packet.
		 */
		if ( np = tp->RxBusy[code] ) {
			tp->RxBusy[code] = np->tn_next;
			np->tn_next = 0;
			spl( s );
			break;
		}

		/*
		 * Non-blocking reads.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			spl( s );
			return;
		}

		tp->RxReq[code] = 1;

		sleep( &tp->RxReq[code], CVTTIN, IVTTIN, SVTTIN );
		spl( s );

		/*
		 * Check for pending signal.
		 */
		if ( nondsig() ) {
			u.u_error = EINTR;
			return;
		}
	}

	/*
	 * Copy source and destination node ids
	 */
	np->tn_off = np->tn_base;
	ioputc( srcid = tngetc(np), iop );
	ioputc( tngetc(np), iop );

	/*
	 * Check for short packet.
	 */
	if ( cnt = tngetc(np) ) {

		np->tn_off = np->tn_base + cnt;
		len = 256 - cnt;
	}

	/*
	 * Check for long packet.
	 */
	else if ( cnt = tngetc(np) ) {

		np->tn_off = np->tn_base + cnt;
		len = 512 - cnt;
	}

	/*
	 * Check for non-empty packet.
	 */
	if ( cnt != 0 ) {

		/*
		 * Truncate packet if necessary.
		 */
		if ( iop->io_ioc < len )
			len = iop->io_ioc;

		/*
		 * Copy packet body.
		 */
		tucopy( np, iop->io_base, len );
		iop->io_ioc  -= len;
		iop->io_base += len;
	}

	/*
	 * Adjust received data statistics.
	 */
	if ( tp->statseg != NULL ) {
		faddr_t fp = tp->statseg->s_faddr;
		aflong( fp+TnRxPACKS*4, 1 );
		aflong( fp+TnRxBYTES*4, len );
		fp += srcid * (NTNST * 4);
		aflong( fp+TnRxPACKS*4, 1 );
		aflong( fp+TnRxBYTES*4, len );
	}

	/*
	 * Enable packet reception with buffer.
	 */
	tn_rxena( tp, np );
}


/*
 * Write Routine.
 *
 *	Wait for a empty transmit buffer to become available.
 *	Format the buffer and place on transmit queue.
 *	If transmit queue was empty, start transmitter.
 */

tnwrite ( dev, iop )

dev_t dev;
register IO * iop;

{
	register struct tnet_s  * tp = &tnet[ dev & 3 ];
	register struct tnbuf_s * np;
	unsigned len, cnt;
	int dstid;
	int s;

	/*
	 * Validate size of write.
	 */
	if ( ( iop->io_ioc < 3 ) || ( iop->io_ioc > 510 ) ) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * Destination Node Id is 2nd byte of write.
	 */
	iogetc( iop );
	dstid = iogetc( iop );

	/*
	 * Wait for empty transmit buffer.
	 */
	for ( ; ; ) {

		/*
		 * If Destination Node appears bad, set errno to EDATTN.
		 */
		if ( tp->bad[ dstid / 8 ] & (1 << (dstid % 8)) ) {
			u.u_error = EDATTN;
			return;
		}

		s = sphi( );

		/*
		 * Check for empty transmit buffer.
		 */
		if ( np = tp->TxIdle ) {

			tp->TxIdle  = np->tn_next;
			np->tn_next = 0;
			spl( s );
			break;
		}

		/*
		 * Non-blocking writes.
		 */
		if ( iop->io_flag & IONDLY ) {
			/*
			 * Adjust delayed write stats.
			 */
			faddr_t fp = tp->statseg->s_faddr;
			aflong( fp+TnWRTDLYS*4, 1 );
			fp += dstid * (NTNST * 4);
			aflong( fp+TnWRTDLYS*4, 1 );

			u.u_error = EAGAIN;
			spl( s );
			return;
		}

		tp->TxReq = 1;
		sleep( &tp->TxReq, CVTTOUT, IVTTOUT, SVTTOUT );
		spl( s );

		/*
		 * Check for pending signal.
		 */
		if ( nondsig() ) {
			u.u_error = EINTR;
			return;
		}
	}

	/*
	 * Copy source and destination node ids
	 * NOTE: Hardware inserts source node id automatically.
	 */
	np->tn_off = np->tn_base;
	tnputc( np, 0 );
	tnputc( np, dstid );

	len = iop->io_ioc;

	/*
	 * Check for long packet.
	 */
	if ( len > 253 ) {
		tnputc( np, 0 );
		tnputc( np, cnt = 512 - len );
		np->tn_off = np->tn_base + cnt;
	}

	/*
	 * Short packet.
	 */
	else {
		tnputc( np, cnt = 256 - len );
		np->tn_off = np->tn_base + cnt;
	}

	/*
	 * Copy packet body.
	 */
	utcopy( iop->io_base, np, len );
	iop->io_base += len;
	iop->io_ioc  -= len;

	/*
	 * Record length in header structure.
	 */
	np->tn_xlen = iop->io_ioc;

	sphi();

	/*
	 * Put packet on transmit ready queue, prime transmitter if necessary.
	 */
	if ( ! tp->TxBusy ) {
		tp->TxBusy = np;
		outb( NCR, np->tn_ena );	 /* enable transmitter	*/
		outb( NIR, tp->tnmask |= NI_Tx); /* enable xmit intr	*/
		tp->tntime = TNTIME;		 /* restart watchdog	*/
	}
	else
		tp->TxBusy->tn_next = np;

	spl(s);
}

/*
 * Enable packet reception with buffer.
 */
tn_rxena( tp, np )
register struct tnet_s  * tp;
register struct tnbuf_s * np;
{
	int s;

	s = sphi( );

	/*
	 * Put packet on receive ready queue, prime receiver if necessary.
	 */
	if ( tp->RxIdle == NULL ) {
		tp->RxIdle = np;
		outb( NCR, np->tn_ena );
		outb( NIR, tp->tnmask |= NI_Rx );
	}
	else
		tp->RxIdle->tn_next = np;

	np->tn_next = 0;
	spl( s );
}

/*
 * Adjust far long.
 */
static
aflong( fp, i )
faddr_t fp;
int i;
{
	long lw;

	fkcopy( fp, &lw, sizeof(lw) );
	lw += i;
	kfcopy( &lw, fp, sizeof(lw) );
}
@


1.1
log
@Initial revision
@
text
@d14 1
a14 1
#include <coherent.h>
a15 1
#include <sys/fun.h>
a18 1
#include <sys/types.h>
a19 1
#include <sys/timeout.h>
@
0707070064030106271004440000030000030000011777770507310703100005600000007407/newbits/kernel/USRSRC/i8086/drv/RCS/tnas.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.28.49;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.1.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ Tiac Network Assembler Support
/
/	tngetc( np )		-- get a character from a tiac network buffer
/	tnputc( np, c)		-- put a character into a tiac network buffer
/	tucopy( np, up, n)	-- copy n bytes from tiac buffer to user space
/	utcopy( up, np, n)	-- copy n bytes from user space to tiac buffer
/
////////

	.globl	tngetc_
	.globl	tnputc_
	.globl	tucopy_
	.globl	utcopy_

////////
/
/ Tngetc ( np )
/
/	Input:	np = pointer to seg:offset pair for tiac network buffer
/
/	Action:	Read character from network buffer, increment offset.
/
/	Return:	Character.
/
////////

tngetc_:				/ tngetc( np )
	push	si			/ char **np;
	push	bp			/ {
	mov	bp, sp			/	register char c;	/* AX */
	mov	bx, 6(bp)		/	register char *cp;	/* SI */
	push	ds			/
	lds	si, (bx)		/	cp = *np;
	cld				/
	lodsb				/	c = *cp++;
	pop	ds			/
	mov	(bx), si		/	*np = cp;
	subb	ah, ah			/
	pop	bp			/	return( c );
	pop	si			/ }
	ret

////////
/
/ Tnputc ( np, c )
/ char **np;
/ char c;
/
/	Input:	np = pointer to seg:offset pair for tiac network buffer
/		c  = character to transfer
/
/	Action:	Transfer character C to network buffer, increment offset.
/
/	Return:	Character C.
/
////////

tnputc_:				/ tnputc( np, c )
	push	di			/ char **np;			/* BX */
	push	bp			/ char c;			/* AX */
	mov	bp, sp			/ {
	mov	ax, 8(bp)		/	register char *cp;	/* DI */
	mov	bx, 6(bp)		/
	push	es			/
	les	di, (bx)		/	cp = *np;
	cld				/
	stosb				/	*cp++ = c;
	pop	es			/
	mov	(bx), di		/	*np = cp;
	pop	bp			/
	pop	di			/	return c;
	ret				/ }

////////
/
/ utcopy( up, np, n )
/ char * up;
/ char **np;
/ unsigned n;
/
/	Input:	up = offset in user data space for source data
/		np = pointer to seg:offset pair	for tiac network buffer
/		n  = number of bytes to transfer
/
/	Action:	Copy N bytes from user data space to network data space.
/		Add N to network data space offset.
/
/	Return: None.
/
////////

utcopy_:				/ utcopy( up, np, n )
	push	si			/
	push	di			/ register char *  up;		/* SI */
	push	bp			/ register char ** np;		/* BX */
	mov	bp, sp			/ register unsigned n;		/* CX */
	push	ds			/
	push	es			/ {
	mov	bx, 10(bp)		/	register char * cp;	/* DI */
					/
	les	di, (bx)		/	cp = *np;
					/
	mov	si, 8(bp)		/	up;
	mov	ds, uds_		/
					/
	mov	cx, 12(bp)		/	n;
					/
	cld				/
	clc				/
	rcr	cx, $1			/
	rep				/	for ( ; n != 0; --n )
	movsw				/		*cp++ = *up++;
	rcl	cx, $1			/
	rep				/
	movsb				/
					/
	pop	es			/
	pop	ds			/
	mov	(bx), di		/	*np = cp;
	pop	bp			/ }
	pop	di
	pop	si
	ret

////////
/
/ tucopy( np, up, n )
/ char **np;
/ char * up;
/ unsigned n;
/
/	Input:	np = pointer to seg:offset pair	for tiac network buffer
/		up = offset in user data space for destination
/		n  = number of bytes to transfer
/
/	Action:	Copy N bytes from network data space to user data space.
/		Add N to network data space offset.
/
/	Return: None.
/
////////

tucopy_:				/ tucopy( np, up, n )
	push	si			/
	push	di			/ register char ** np;		/* BX */
	push	bp			/ register char *  up;		/* DI */
	mov	bp, sp			/ register unsigned n;		/* CX */
	push	ds			/
	push	es			/ {
	mov	bx, 8(bp)		/	register char * cp;	/* SI */
					/
	mov	di, 10(bp)		/	up;
	mov	es, uds_		/
					/
	lds	si, (bx)		/	cp = *np;
					/
	mov	cx, 12(bp)		/	n;
					/
	cld				/
	clc				/
	rcr	cx, $1			/
	rep				/	for ( ; n != 0; --n )
	movsw				/		*up++ = *cp++;
	rcl	cx, $1			/
	rep				/
	movsb				/
					/
	pop	es			/
	pop	ds			/
	mov	(bx), si		/	*np = cp;
	pop	bp			/ }
	pop	di
	pop	si
	ret
@
0707070064030106571004440000030000030000011777770507310703100005500000047027/newbits/kernel/USRSRC/i8086/drv/RCS/nkb.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4; strict;
comment  @ * @;


1.4
date     91.06.20.14.51.43;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.17.12.33.54;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.13.12.53.07;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.31.59;  author bin;  state Exp;
branches ;
next     ;


desc
@loadable keyboard driver
initial version prov by hal
@


1.4
log
@update provided by hal
@
text
@/*
 * User configurable AT keyboard/display driver.
 * AT COHERENT
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <signal.h>
#include <sys/seg.h>
#include <sys/sched.h>
#include <sys/kb.h>

#define	ISMAJ		2		/* Keyboard major device */
#define	ISVEC		1		/* Keyboard interrupt vector */

#if	DEBUG
#define	KBDEBUG(x)	printf(x)	/* debugging output */
#define	KBDEBUG2(x,y)	printf(x,y)	/* debugging output */
#define	KBDEBUG3(x,y,z)	printf(x,y,z)	/* debugging output */
#else
#define	KBDEBUG(x)			/* no output */
#define	KBDEBUG2(x,y)			/* no output */
#define	KBDEBUG3(x,y,z)			/* no output */
#endif

/*
 * values for kbstate
 */
#define	KB_IDLE		0		/* nothing going on right now */
#define	KB_SINGLE	1		/* sent a single byte cmd to the kbd */
#define	KB_DOUBLE_1	2		/* sent 1st byte of 2-byte cmd to kbd */
#define	KB_DOUBLE_2	3		/* sent 2nd byte of 2-byte cmd to kbd */

/*
 * patchable params for non-standard keyboards
 */
int	KBDATA = 0x60;			/* Keyboard data */
int	KBCTRL = 0x61;			/* Keyboard control */
int	KBSTS_CMD = 0x64;		/* Keyboard status/command */
int	KBFLAG = 0x80;			/* Keyboard reset flag */
int	KBBOOT = 1;			/* 0: disallow reboot from keyboard */
int	KBTIMEOUT = 10000;		/* shouldn't need this much */
int	KBCMDBYTE = 0x05;		/* no translation */

/*
 * KBSTATUS bits
 */
#define	STS_OBUF_FULL	0x01		/* kbd output buffer full */
#define	STS_IBUF_FULL	0x02		/* kbd input buffer full */
#define	STS_SYSTEM	0x04
#define	STS_CMD_DATA	0x08		/* 1: command or status */
#define	STS_INHIBIT	0x10		/* 0: keyboard inhibited */
#define	STS_AUX_OBUF_FULL	0x20
#define	STS_TIMEOUT	0x40		/* general timeout */
#define	STS_PAR_ERR	0x80		/* parity error */

/*
 * The following are magic commands which read from or write to the
 * controller command byte. These get output to the KBSTS_CMD port.
 */
#define	C_READ_CMD	0x20		/* read controller command byte */
#define	C_WRITE_CMD	0x60		/* write controller command byte */
#define	C_TRANSLATE	0x40		/* translate enable bit in cmd byte */

/*
 * Globals
 * The keyboard mapping table is too large to fit into kernel data space,
 * so we need to allocate a segment to it.
 * The function keys tend to be small and tend to change substantially
 * more often than the mapping table, so we keep them in the kernel data space.
 */
static	unsigned shift;			/* state of all shift/lock keys */
static	SEG	*kbsegp;		/* keyboard table segment */
static	unsigned char	**funkeyp = 0;	/* ptr to array of func. keys ptrs */
static	FNKEY	*fnkeys = 0;		/* pointer to structure of values */
static	unsigned fklength;		/* length of k_fnval field in fnkeys */
static	unsigned prev_cmd;		/* previous command sent to KBD */
static	unsigned cmd2;			/* 2nd byte of command to KBD */
static	unsigned sh_index;		/* shift/lock state index */

/*
 * State variables.
 */
int		islock;			/* Keyboard locked flag */
int		isbusy;			/* Raw input conversion busy */
static	char	table_loaded;		/* true == keyboard table resident */
static	char	fk_loaded;		/* true == function keys resident */
static	int	kbstate = KB_IDLE;	/* current keyboard state */

/*
 * Functions.
 */
int		isrint();
int		istime();
void		isbatch();
int		mmstart();
int		isopen();
int		isclose();
int		isread();
int		mmwrite();
int		isioctl();
void		mmwatch();
int		isload();
int		isuload();
int		ispoll();
int		nulldev();
int		nonedev();
int		updleds();

/*
 * Configuration table.
 */
CON iscon ={
	DFCHR|DFPOL,			/* Flags */
	ISMAJ,				/* Major index */
	isopen,				/* Open */
	isclose,			/* Close */
	nulldev,			/* Block */
	isread,				/* Read */
	mmwrite,			/* Write */
	isioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	mmwatch,			/* Timeout */
	isload,				/* Load */
	isuload,			/* Unload */
	ispoll				/* Poll */
};

/*
 * Terminal structure.
 */
TTY	istty = {
	{0}, {0}, 0, mmstart, NULL, 0, 0
};

/*
 * Load entry point.
 */
isload()
{
	kbstate = KB_IDLE;
	table_loaded = 0;		/* no keyboard table yet */
	fk_loaded = 0;			/* no Fn keys yet */

	/*
	 * Enable mmwatch() invocation every second.
	 */
	drvl[ISMAJ].d_time = 1;

	/*
	 * Seize keyboard interrupt.
	 */
	setivec(ISVEC, isrint);

	/*
	 * Initiailize video display.
	 */
	mmstart( &istty );

	/*
	 * Allocate a segment to store the in-core keyboard table.
	 * This would be a lot more convenient in kernel data space,
	 * but small model COHERENT doesn't have that luxury.
	 */
	kbsegp = salloc((fsize_t)MAX_TABLE_SIZE, SFSYST|SFNSWP|SFHIGH);
	if (kbsegp == (SEG *)0)
		printf("kb: unable to allocate keyboard table segment\n");
	fklength = 0;
	KBDEBUG("Exiting kbload()\n");
}

/*
 * Unload entry point.
 */
isuload()
{
	if (kbstate != KB_IDLE)
		printf("kb: keyboard busy during unload\n");
	clrivec(ISVEC);
	if (kbsegp != (SEG *)0) {
		table_loaded = 0;
		sfree(kbsegp);
	}
}

/*
 * Open routine.
 */
isopen(dev)
dev_t dev;
{
	register int s;

	KBDEBUG(" kbopen()");
	if (minor(dev) != 0) {
		u.u_error = ENXIO;
		return;
	}
	if ((istty.t_flags&T_EXCL) != 0 && !super()) {
		u.u_error = ENODEV;
		return;
	}
	ttsetgrp(&istty, dev);

	s = sphi();
	if (istty.t_open++ == 0) {
		istty.t_flags = T_CARR;	/* indicate "carrier" */
		ttopen(&istty);
	}
	spl(s);
#if 0
	updleds();			/* update keyboard status LEDS */
#endif
}

/*
 * Close a tty.
 */
isclose(dev)
{
	register int s;

	s = sphi();
	if (--istty.t_open == 0) {
		ttclose(&istty);
	}
	spl(s);
}

/*
 * Read routine.
 */
isread(dev, iop)
dev_t dev;
IO *iop;
{
	ttread(&istty, iop, 0);
	if (istty.t_oq.cq_cc)
		mmtime(&istty);
}

/*
 * Ioctl routine.
 * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported.
 */
isioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	register int s;

	switch (com) {
	case TIOCSETF:
	case TIOCGETF:
		isfunction(com, (char *)vec);
		break;
	case TIOCSETKBT:
		issettable(vec);
		break;
	case TIOCGETKBT:
		isgettable(vec);
		break;
	default:				/* pass to TTY driver */
		s = sphi();
		ttioctl(&istty, com, vec);
		spl(s);
		break;
	}
}

/*
 * Set the in-core keyboard mapping table.
 * The table is sorted by scan code prior to calling ioctl().
 * All unused table entries (holes in the scan code map) have
 * a zero for the k_key field.
 * This makes key lookup at interrupt time fast by using the scan code
 * as an index into the table.
 */
issettable(vec)
char	*vec;
{
	register unsigned i;
	register int s;
	int timeout;
	register faddr_t faddr;		/* address of keyboard table */
	static	KBTBL	this_key;	/* current key from kbd table */
	unsigned int cmd_byte;

	KBDEBUG(" TIOCSETKBT");
	kb_cmd2(K_SCANCODE_CMD, 3);		/* select set 3 */
	kb_cmd(K_ALL_TMB_CMD);			/* default: TMB for all keys */
	faddr = kbsegp->s_faddr;
	for (i = 0; i < MAX_KEYS; ++i) {
		ukcopy(vec, &this_key, sizeof(this_key));
		kfcopy(&this_key, faddr, sizeof(this_key));
		faddr += sizeof(this_key);
		vec += sizeof(this_key);
		if (this_key.k_key != i && this_key.k_key != 0) {
			printf("kb: incorrect or unsorted table entry %d\n", i);
			u.u_error = EBADFMT;
			return;
		}
		if (this_key.k_key != i)
			continue;		/* no key */
		switch (this_key.k_flags&TMODE) {
		case T:				/* typematic */
			kb_cmd2(K_KEY_T_CMD, i);
			break;
		case M:				/* make only */
			kb_cmd2(K_KEY_M_CMD, i);
			break;
		case MB:			/* make/break */
			kb_cmd2(K_KEY_MB_CMD, i);
			break;
		case TMB:			/* typematic make/break */
			break;			/* this is the default */
		default:
			printf("kb: bad key mode\n");
		}
	}
	updleds();
	kb_cmd2(K_SCANCODE_CMD, 3);		/* select set 3 */
	kb_cmd(K_ENABLE_CMD);			/* start scanning */
	/*
	 * The following code disables translation from the on-board
	 * keyboard/aux controller. Without disabling translation, the
	 * received scan codes still look like code set 1 codes even
	 * though we put the keyboard controller in scan code set 3.
	 * Yes, this is progress....
	 */
#if 0
	while (inb(KBSTS_CMD) & STS_IBUF_FULL)
		;
	outb(KBSTS_CMD, C_READ_CMD);		/* read controller cmd byte */
	while (!(inb(KBSTS_CMD) & STS_OBUF_FULL))
		;
	cmd_byte = inb(KBDATA);
	KBDEBUG2(" cmd_byte=%x", cmd_byte);
#endif
	timeout = KBTIMEOUT;
	s = sphi();
	while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
		;
	outb(KBSTS_CMD, C_WRITE_CMD);		/* write controller cmd byte */
	for (timeout = 50; --timeout > 0; )
		;
	timeout = KBTIMEOUT;
	while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
		;
	outb(KBDATA, KBCMDBYTE);		 /* turn off translation */	
	timeout = KBTIMEOUT;
	while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
		;
	spl(s);
#if DEBUG
	kb_cmd2(K_SCANCODE_CMD, 0);		/* query s.c. mode */
#endif
	++table_loaded;
}

/*
 * Get the in-core keyboard mapping table and pass it to the user.
 */
isgettable(vec)
char	*vec;
{
	register unsigned i;
	register faddr_t faddr;		/* address of keyboard table */
	static	KBTBL	this_key;	/* current key from kbd table */

	KBDEBUG(" TIOCGETKBT");
	faddr = kbsegp->s_faddr;
	for (i = 0; i < MAX_KEYS; ++i) {
		fkcopy( faddr, &this_key, sizeof(this_key));
		kucopy( &this_key, vec, sizeof(this_key));
		faddr += sizeof(this_key);
		vec += sizeof(this_key);
	}
}

/*
 * Set and receive the function keys.
 */
isfunction(c, v)
int c;
FNKEY *v;
{
	register unsigned char *cp;
	register unsigned i;
	unsigned char	numkeys = 0;

	if (c == TIOCGETF) {
		KBDEBUG(" TIOCGETF");
		if (!fk_loaded)
			u.u_error = EINVAL;
		else
			kucopy(fnkeys, v, fklength);	/* copy ours to user */
	} else { /* TIOCSETF */
		/*
		 * If we had a previous function key arena, free it up.
		 * Since we don't know how large the function key arena will
		 * be, we must size it in the user data space prior to
		 * (re)kalloc()'ing it. This is ugly, but a helluva lot better
		 * than the old driver which used a hard coded limit of 150!
		 */
		KBDEBUG(" TIOCSETF");
		fk_loaded = 0;
		if (fnkeys != (FNKEY *)0)
			kfree(fnkeys);		/* free old arena */
		if (funkeyp != NULL)
			kfree(funkeyp);		/* free old ptr array */
		ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys));
		fklength = sizeof(FNKEY);
		cp = v->k_fnval;
		for (i = 0; i < numkeys; i++) {
			do {
				++fklength;
			} while (getubd(cp++) != DELIM);
		}
		fnkeys = (FNKEY *)kalloc(fklength);
		funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *));
		if (fnkeys == (FNKEY *)0 || funkeyp == NULL) {
			if (fnkeys != (FNKEY *)0) {
				kfree(fnkeys);
				fnkeys = 0;
			}
			if (funkeyp != NULL) {
				kfree(funkeyp);
				funkeyp = 0;
			}
			u.u_error = ENOMEM;
			return;
		}
		cp = fnkeys->k_fnval;			/* point to Fn ... */
		v = v->k_fnval;				/* ... key arena */
		for (i = 0; i < numkeys; i++) {
			funkeyp[i] = cp;	           /* save pointer */
			while ((*cp++ = getubd(v++)) != DELIM)  /* copy key */
				;
		}
		fnkeys->k_nfkeys = numkeys;
		fk_loaded = 1;
	}
}


/*
 * Poll routine.
 */
ispoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll failure.
	 */
	if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) {
		if ( msec != 0 )
			pollopen( &istty.t_ipolls );
		/*
		 * Second look AFTER enabling monitor, avoiding interrupt race.
		 */
		if ( istty.t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}
	return ev;
}

/*
 * Receive interrupt.
 */
isrint()
{
	register unsigned c;
	register unsigned r;
	static	char keyup;

	/*
	 * Schedule raw input handler if not already active.
	 */
	if ( !isbusy ) {
		defer( isbatch, &istty );
		isbusy = 1;
	}

	/*
	 * Pull character from the data
	 * port. Pulse the KBFLAG in the control
	 * port to reset the data buffer.
	 */
	r = inb(KBDATA) & 0xFF;
	c = inb(KBCTRL);
	outb(KBCTRL, c|KBFLAG);
	outb(KBCTRL, c);

	/*
	 * check returned value from keyboard to see if it's a command
	 * or status back to us. If not, it we assume that it's a key code.
	 */
	KBDEBUG2(" intr(%x)", r);
	switch (r) {
	case K_BREAK:
		keyup = 1;			/* key going up */
		break;
	case K_ECHO_R:
	case K_BAT_OK:
		break;				/* very nice, but ignored */
	case K_BAT_BAD:
		printf("kb: keyboard BAT failed\n");
		break;
	case K_RESEND:
		KBDEBUG("\nkb: request to resend command\n");
		outb(KBDATA, prev_cmd);
		break;
	case K_OVERRUN_23:
		printf("kb: keyboard buffer overrun\n");
		break;
	case K_ACK:
		/*
		 * we received an ACKnowledgement from the keyboard.
		 * advance the state machine and continue.
		 */
		KBDEBUG(" ACK");
		switch (kbstate) {
		case KB_IDLE:			/* shouldn't happen */
			printf("kb: ACK while keyboard idle\n");
			break;
		case KB_SINGLE:			/* done with 1-byte command */
		case KB_DOUBLE_2:		/* done w/ 2nd of 2-byte cmd */
			kbstate = KB_IDLE;
			wakeup(&kbstate);
			break;
		case KB_DOUBLE_1:
			kbstate = KB_DOUBLE_2;
			outb(KBDATA, cmd2);
			break;
		default:
			printf("kb: bad kbstate %d\n", kbstate);
			break;
		}
		break;
	default:
		process_key(r, keyup);
		keyup = 0;
	}
}

/*
 * Process a key given its scan code and direction.
 * 
 * In this table driven version of the keyboard driver, we trade off the
 * code complexity associated with all the black magic that used to be
 * performed on a per-key basis with the increased memory requirements
 * associated with the table driven approach.
 */
process_key( key, up)
unsigned key;
int	 up;
{
	register unsigned char *cp;
	KBTBL	key_vals;			/* table values for this key */
	unsigned val;
	unsigned char flags;

	KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down"));
	if (!table_loaded)
		return;				/* throw away key */
	fkcopy( kbsegp->s_faddr + (key * sizeof(KBTBL)),
		&key_vals, sizeof(key_vals));
	if (key_vals.k_key != key)		/* empty entry */
		return;
	flags = key_vals.k_flags;

	if (flags & S) {			/* some shift/lock key ? */
		switch (key_vals.k_val[BASE]) {
		case caps:
		case num:
			if (!up) {
				shift ^= (1 << key_vals.k_val[BASE]);
				updleds2();
			}
			break;
		case scroll:
			if (!up) {
				shift ^= (1 << key_vals.k_val[BASE]);
				updleds2();
				if (!(istty.t_sgttyb.sg_flags&RAWIN)) {
					if (istty.t_flags & T_STOP) {
						isin(istty.t_tchars.t_startc);
					} else {
						isin(istty.t_tchars.t_stopc);
					}
				}
			}
			break;
		default:
			if (up)
				shift &= ~(1 << key_vals.k_val[BASE]);
			else
				shift |= (1 << key_vals.k_val[BASE]);
			break;
		}
		/*
		 * Calculate the shift index based upon the state of
		 * the shift and lock keys.
		 */
		sh_index = BASE;		/* default condition */
		if (shift & (1 << altgr))
			sh_index = ALT_GR;
		else {
			if (shift & ((1 << lalt)|(1 << ralt)))
				sh_index |= ALT;
			if (shift & ((1 << lctrl)|(1 << rctrl)))
				sh_index |= CTRL;
			if (shift & ((1 << lshift)|(1 << rshift)))
				sh_index |= SHIFT;
		}
		return;
	} /* if (flags & S) */

	/*
	 * If the tty is not open or the key has no value in the current
	 * shift state, the key is just tossed away.
	 */
	if (up || !istty.t_open || key_vals.k_val[sh_index] == none)
		return;
	if (((flags & C) && (shift & (1 << caps)))
	   || ((flags & N) && (shift & (1 << num))))
		val = key_vals.k_val[sh_index^SHIFT];
	else
		val = key_vals.k_val[sh_index];

	/*
	 * Check for function key or special key implemented as
	 * a function key (reboot == f0, tab and back-tab, etc).
	 */
	if (flags & F) {
		if (val == 0 && !up && KBBOOT)
			boot();
		if (!fk_loaded || val >= fnkeys->k_nfkeys)
			return;
		if ((cp = funkeyp[val]) == NULL) /* has a value? */
			return;
		while (*cp != DELIM)
			isin(*cp++);		/* queue up Fn key value */
		return;
	}

	/*
	 * Normal key processing.
	 */
	isin(val);		 /* send the char */
	return;
}

/**
 *
 * void
 * ismmfunc( c )	-- process keyboard related output escape sequences
 * char c;
 */
void
ismmfunc(c)
register int c;
{
	switch (c) {
	case 't':	/* Enter numlock */
		shift |= (1 << num);
		updleds();			/* update LED status */
		break;
	case 'u':	/* Leave numlock */
		shift &= ~(1 << num);
		updleds();			/* update LED status */
		break;
	case '=':			/* Enter alternate keypad -- ignored */
	case '>':			/* Exit alternate keypad -- ignored */
		break;
	case 'c':	/* Reset terminal */
		islock = 0;
		break;
	}
}

/**
 *
 * void
 * isin( c )	-- append character to raw input silo
 * char c;
 */
static
isin( c )
register int c;
{
	/*
	 * Cache received character.
	 */
	istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c;

	if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) )
		istty.t_rawin.si_ix = 0;
}

/**
 *
 * void
 * isbatch()	-- raw input conversion routine
 *
 *	Action:	Enable the video display.
 *		Canonize the raw input silo.
 *
 *	Notes:	isbatch() was scheduled as a deferred process by isrint().
 */
static void
isbatch( tp )
register TTY * tp;
{
	register int c;
	static int lastc;

	/*
	 * Ensure video display is enabled.
	 */
	mm_von();
	isbusy = 0;

	/*
	 * Process all cached characters.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {
		/*
		 * Get next cached char.
		 */
		c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ];

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;

		if ( (islock == 0) || ISINTR || ISQUIT ) {
			ttin( tp, c );
		} else if ( (c == 'b') && (lastc == '\033') ) {
			islock = 0;
			ttin( tp, lastc );
			ttin( tp, c );
		} else if ( (c == 'c') && (lastc == '\033') ) {
			ttin( tp, lastc );
			ttin( tp, c );
		} else
			putchar('\007');
		lastc = c;
	}
}

/*
 * update the keyboard status LEDS.
 * we chose the shift/lock key positions so this would be easy.
 * this flavor of routine is called while processing a system call on
 * behalf of the user.
 */
updleds()
{
	kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7);
}

/*
 * same as above, but callable from interrupt routines and other places
 * which cannot sleep() waiting for the state machine to go idle.
 */
updleds2()
{
	register timeout;
	register int s;

	timeout = KBTIMEOUT;
	s = sphi();
	while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
		;
	kbstate = KB_DOUBLE_1;
	cmd2 = (shift >> 1) & 0x7;
	prev_cmd = K_LED_CMD;
	outb(KBDATA, K_LED_CMD);
	spl(s);
}

/*
 * unlock the scroll in case an interrupt character is received
 */
kbunscroll()
{
	shift &= ~(1 << scroll);
	updleds();
}

/*
 * ship a single byte command to the keyboard
 */
kb_cmd(cmd)
unsigned cmd;
{
	register int timeout;
	register int s;

	s = sphi();
	KBDEBUG2(" kb_cmd(%x)", cmd);
	while (kbstate != KB_IDLE)
		sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	kbstate = KB_SINGLE;
	timeout = KBTIMEOUT;
	while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
		;
	if (!timeout)
		printf("kb: command timeout\n");
	else {
		outb(KBDATA, cmd);
		while (kbstate != KB_IDLE)
			sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	}
	spl(s);
}

/*
 * ship a two byte command to the keyboard
 */
kb_cmd2(cmd, arg)
unsigned cmd, arg;
{
	register int timeout;
	register int s;

	s = sphi();
	KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg);
	while (kbstate != KB_IDLE)
		sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	kbstate = KB_DOUBLE_1;
	cmd2 = arg;
	prev_cmd = cmd;
	timeout = KBTIMEOUT;
	while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
		;
	if (!timeout)
		printf("kb: command timeout\n");
	else {
		outb(KBDATA, cmd);
		while (kbstate != KB_IDLE)
			sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN);
	}
	spl(s);
}

/* End of nkb.c */
@


1.3
log
@new version provided y hal for v321
@
text
@d5 2
a6 2
#include <coherent.h>
#include <i8086.h>
a12 1
#include <sys/timeout.h>
@


1.2
log
@update provided by norm
@
text
@d7 1
a7 1
#include <con.h>
d9 3
a11 3
#include <stat.h>
#include <tty.h>
#include <uproc.h>
d15 1
a15 1
#include <sched.h>
@


1.1
log
@Initial revision
@
text
@d16 1
a16 1
#include <kb.h>
@
0707070064030106251004440000030000030000011777770507310703600006000000013077/newbits/kernel/USRSRC/i8086/drv/RCS/kbmain.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.06.13.12.52.59;  author bin;  state Exp;
branches ;
next     ;


desc
@init ver prov by norm
@



1.1
log
@Initial revision
@
text
@/*
 * driver routine for loadable keyboard tables.
 *
 * prior to firing off the ioctl() which loads the new keyboard tables,
 * permform some simple validity checks on the table.
 * if errors are found, bail out without setting the new table.
 *
 * Version 1.0, 6/8/91
 */
#include <stdio.h>
#include <sgtty.h>
#include <sys/kb.h>
#include <sys/kbscan.h>
#include <errno.h>

#define	VERSION	"1.0"
#define	FALSE	(0 != 0)
#define	TRUE	(0 == 0)

/*
 * globals
 */
char	*argv0;				/* name of this executable */
int	errors;				/* for exit status */
char	verbose;			/* step-by-step details */
char	debug;				/* print out cooked table & exit */
KBTBL	table[MAX_KEYS];		/* cooked table for ioctl() */
FNKEY	*arena;				/* function key arena */

unsigned char	keyval[] = {		/* code set 3 mapped value */
none, K_1, K_2, K_3, K_4, K_5, K_6, K_7,
K_8, K_9, K_10, K_11, K_12, K_13, none, K_15,
K_16, K_17, K_18, K_19, K_20, K_21, K_22, K_23,
K_24, K_25, K_26, K_27, K_28, K_29, K_30, K_31,
K_32, K_33, K_34, K_35, K_36, K_37, K_38, K_39,
K_40, K_41, K_42, K_43, K_44, K_45, K_46, K_47,
K_48, K_49, K_50, K_51, K_52, K_53, K_54, K_55,
none, K_57, K_58, none, K_60, K_61, K_62, none,
K_64, none, none, none, none, none, none, none,
none, none, none, K_75, K_76, none, none, K_79,
K_80, K_81, none, K_83, K_84, K_85, K_86, none,
none, K_89, K_90, K_91, K_92, K_93, none, K_95,
K_96, K_97, K_98, K_99, K_100, K_101, K_102, K_103,
K_104, K_105, K_106, none, K_108, none, K_110, none,
K_112, K_113, K_114, K_115, K_116, K_117, K_118, K_119,
K_120, K_121, K_122, K_123, K_124, K_125, K_126
};

/*
 * externs from user-defined keyboard table
 */
extern	KBTBL	kbtbl[];			/* actual table */
extern	char	tbl_name[];			/* name of table as text */
extern	unsigned char *funkey[];		/* function key definitions */
extern	int	numfun;				/* # of function keys in tbl */
extern	int	numkey;				/* number of keys in kbtbl[] */

main(argc, argv)
char *argv[];
{
	unsigned char *cp, *ncp;
	int i, j;
	int fd;					/* console file descriptor */

	argv0 = argv[0];
	if ((arena = (FNKEY *)malloc(sizeof(FNKEY) + MAX_FCHAR)) == NULL) {
		err("out of memory");
		exit(errors);
	}
	if (argc > 1) {
		if (strcmp(argv[1], "-V") == 0)
			printf("Version %s\n", VERSION);
		else if (strcmp(argv[1], "-D") == 0)
			++debug;
		else
			usage();
	}

	if ((fd = open("/dev/console", 2)) < 0) {
		err("unable to access console");
		exit(errors);
	}

	/*
	 * loop through the user's keyboard table validating each entry.
	 * if the entry is good, copy it to the destination table.
	 */
	for (i = 0; i < numkey; ++i) {		/* loop thru user's keys */
		if (ok_entry(i)) {
			j = kbtbl[i].k_key;		/* map key */
			table[j] = kbtbl[i];		/* copy entry */
		} else
			++errors;
	}

	if (errors)
		exit(errors);
	/*
	 * build a function key arena consisting of the user defined
	 * special and function keys.
	 */
	ncp = arena->k_fnval;
	for (i = 0; i < numfun; ++i) {
		cp = funkey[i];
		do {
			if (ncp >= &arena->k_fnval[MAX_FCHAR]) {
				err("function key table overflow");
				exit(errors);
			}
			*ncp++ = *cp;
		} while (*cp++ != DELIM);
	}
	arena->k_nfkeys = numfun;

	if (debug) {
		dump();				/* print out cooked table */
		exit(0);
	}

	/*
	 * load the cooked keyboard table into the driver via a
	 * special ioctl() call.
	 */
	ioctl(fd, TIOCSETKBT, table);
	if (errno) {
		perror("keyboard table ioctl() failed");
		exit(++errors);
	}

	/*
	 * load the cooked function key table into the driver via a
	 * special ioctl() call.
	 */
	ioctl(fd, TIOCSETF, arena);
	if (errno) {
		perror("function key ioctl() failed");
		exit(++errors);
	}

	printf("Loaded %s\n", tbl_name);
	close(fd);
	exit(errors);
}

/*
 * validate a table entry
 */
ok_entry(n)
register int n;
{
	int i;
	int key = lookup(kbtbl[n].k_key);

	if (!key) {
		err("invalid key #0x%x in kbtbl[%d]", kbtbl[n].k_key, n);
		return FALSE;
	}
	if ((kbtbl[n].k_flags & (S|F)) == (S|F)) {
		err("invalid flag field for key K_%d", key);
		return FALSE;
	}
	if (kbtbl[n].k_flags & S) {
		for (i = BASE; i <= ALT_GR; ++i) {
			if (kbtbl[n].k_val[i] != kbtbl[n].k_val[BASE]) {
				err("inconsistent shift key entry for K_%d",
				    key);
				return FALSE;
			}
			if (kbtbl[n].k_val[i] < scroll
			   || kbtbl[n].k_val[i] > altgr) {
				err("bad shift key entry for K_%d",
				    key);
				return FALSE;
			}
		} /* for */
	} else if (kbtbl[n].k_flags & F) {
		for (i = BASE; i <= ALT_GR; ++i) {
			if (kbtbl[n].k_val[i] != none)
				if (kbtbl[n].k_val[i] >= numfun) {
					err("bad function key entry for K_%d",
					    key);
					return FALSE;
				}
		} /* for */
	} /* flag key */

	key = kbtbl[n].k_key;
	if (table[key].k_key != 0) {
		err("multiple entries for K_%d", key);
		return FALSE;
	}
	return TRUE;
}

/*
 * lookup the physical key number associated with a given
 * code set 3 scan code.
 *
 * return 0 if not found.
 */
lookup(sc)
unsigned sc;
{
	register int i;

	if (sc == none)
		return 0;
	for (i = 0; i < sizeof(keyval)/sizeof(keyval[0]); ++i)
		if (keyval[i] == (unsigned char)sc)
			return (i);
	return 0;
}

usage()
{
	fprintf(stderr, "usage:\t%s [-V]\n", argv0);
	exit(1);
}

err(msg)
char *msg;
{
	fprintf(stderr, "%s: ERROR: %r\n", argv0, &msg);
	++errors;
}

/*
 * dump the cooked keyboard table to stdout
 */
dump()
{
	int i, j;

	for (i = 0; i < MAX_KEYS; ++i) {
		printf("%02x: %02x ", i, table[i].k_key);
		for (j = 0; j < 9; ++j)
			printf("%02x ", table[i].k_val[j]);
		printf("(%02x)\n", table[i].k_flags);
	}
}
@
0707070064030106651004440000030000030000011777770507310704000005500000046523/newbits/kernel/USRSRC/i8086/drv/RCS/gkb.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.07.15.14.46.35;  author bin;  state Exp;
branches ;
next     ;


desc
@german keyboard driver
@



1.1
log
@Initial revision
@
text
@/*
 * Keyboard/display driver for German keyboard.
 * Coherent, IBM PC/XT and AT (in XT mode).
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <signal.h>
#include <sys/sched.h>

#define	ISMAJ	2			/* Keyboard major device */

#define	SPC	0376			/* Special encoding */
#define XXX	0377			/* Non-character */
#define	KBDATA	0x60			/* Keyboard data */
#define	KBCTRL	0x61			/* Keyboard control */
#define	KBFLAG	0x80			/* Keyboard reset flag */
#define	LEDCMD	0xED			/* status indicator command */
#define	KBACK	0xFA			/* status indicator acknowledge */
#define	EXTENDED0 0xE0			/* extended key seq initiator */
#define	EXTENDED1 0xE1			/* extended key seq initiator */

#define	KEYUP	0x80			/* Key up change */
#define	KEYSC	0x7F			/* Key scan code mask */
#define	LSHIFT	0x2A-1			/* Left shift key */
#define LSHIFTA 0x2B-1			/* Alternate left-shift key */
#define	RSHIFT	0x36-1			/* Right shift key */
#define	CTRL	0x1D-1			/* Control key */
/*-- #define	CAPLOCK	0x1D-1	--*/		/* Control key */
#define	ALT	0x38-1			/* ALT key or ALT GR */
#define	CAPLOCK	0x3A-1			/* Caps lock key */
/*-- #define	CTRL	0x3A-1	--*/		/* Caps lock key */
#define	NUMLOCK	0x45-1			/* Numeric lock key */
#define	DELETE	0x53-1			/* Del, as in CTRL-ALT-DEL */
#define BACKSP	0x0E-1			/* Back space */
#define SCRLOCK	0x46-1			/* Scroll lock */

/* Shift flags */
#define	SRS	0x01			/* Right shift key on */
#define	SLS	0x02			/* Left shift key on */
#define CTS	0x04			/* Ctrl key on */
#define ALS	0x08			/* Alt key on */
#define CPLS	0x10			/* Caps lock on */
#define NMLS	0x20			/* Num lock on */
#define AKPS	0x40			/* Alternate keypad shift */
#define SHFT	0x80			/* Shift key flag */
#define	AGS	0x100			/* Alt Graphics on */

/* Function key information */
#define	NFKEY	20			/* Number of settable functions */
#define	NFCHAR	150			/* Number of characters settable */
#define	NFBUF	(NFKEY*2+NFCHAR+1)	/* Size of buffer */

/*
 * Functions.
 */
int	isrint();
int	istime();
void	isbatch();
int	mmstart();
int	isopen();
int	isclose();
int	isread();
int	mmwrite();
int	isioctl();
void	mmwatch();
int	isload();
int	isuload();
int	ispoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON iscon ={
	DFCHR|DFPOL,			/* Flags */
	ISMAJ,				/* Major index */
	isopen,				/* Open */
	isclose,			/* Close */
	nulldev,			/* Block */
	isread,				/* Read */
	mmwrite,			/* Write */
	isioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	mmwatch,			/* Timeout */
	isload,				/* Load */
	isuload,			/* Unload */
	ispoll				/* Poll */
};

/*
 * Flag indicating turbo machine.
 */
int isturbo = 0;

/*
 * Terminal structure.
 */
TTY	istty = {
	{0}, {0}, 0, mmstart, NULL, 0, 0
};

/*
 * State variables.
 */
int		islock;			/* Keyboard locked flag */
int		isbusy;			/* Raw input conversion busy */
static	int	shift;			/* Overall shift state */
static	char	scroll;			/* Scroll lock state */
static  char	lshift = LSHIFT;	/* Left shift alternate state */
static	char	isfbuf[NFBUF];		/* Function key values */
static	char	*isfval[NFKEY];		/* Function key string pointers */
static	int	ledcmd;			/* LED update command flag */
static	char	extended;		/* extended key scan count */
static	char	extmode;		/* use extended mode for this key */
static	char	ext0seen;		/* 0xE0 prefix seen */

/*
 * Tables for converting key code to ASCII.
 * lmaptab specifies unshifted conversion,
 * umaptab specifies shifted conversion,
 * smaptab specifies the shift states which are active.
 * An entry of XXX says the key is dead.
 * An entry of SPC requires further processing.
 *
 * Key codes:
 *	ESC .. <- == 1 .. 14
 *	-> .. \n == 15 .. 28
 *	CTRL .. ` == 29 .. 41
 *	^Shift .. PrtSc == 42 .. 55
 * 	ALT .. CapsLock == 56 .. 58
 *	F1 .. F10 == 59 .. 68
 *	NumLock .. Del == 69 .. 83
 *	ISO, F11, F12 == 86 .. 88
 */
unsigned char agmaptab[] ={					/* Alt Gr */
	       XXX,  XXX,'\375','\374',XXX,  XXX,  XXX,		/* 1 - 7 */
	 '{',  '[',  ']',  '}', '\\',  XXX,  XXX,  XXX,		/* 8 - 15 */
	 '@@',  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 16 - 23 */
	 XXX,  XXX,  XXX,  '~',  XXX,  XXX,  XXX,  XXX,		/* 24 - 31 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 32 - 39 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 40 - 47 */
	 XXX,  XXX,'\346', XXX,  XXX,  XXX,  XXX,  XXX,		/* 48 - 55 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 56 - 63 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 64 - 71 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 72 - 79 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  '|',  XXX,		/* 80 - 87 */
	 XXX							/* 88 */
};

static unsigned char lmaptab[] ={
	     '\33',  '1',  '2',  '3',  '4',  '5',  '6',		/* 1 - 7 */
	 '7',  '8',  '9',  '0','\341','\'', '\b', '\t',		/* 8 - 15 */
	 'q',  'w',  'e',  'r',  't',  'z',  'u',  'i',		/* 16 - 23 */
	 'o',  'p','\201', '+', '\r',  XXX,  'a',  's',		/* 24 - 31 */
	 'd',  'f',  'g',  'h',  'j',  'k',  'l','\224',	/* 32 - 39 */
	'\204','^',  XXX,  '#',  'y', 'x',  'c',  'v',		/* 40 - 47 */
	 'b',  'n',  'm',  ',',  '.',  SPC,  XXX,  SPC,		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC,  XXX,  XXX,  '<',  XXX,		/* 80 - 87 */
	 XXX							/* 88 */
};

static unsigned char umaptab[] ={
	     '\33',  '!',  '"','\025', '$',  '%',  '&',		/* 1 - 7 */
	 '/',  '(',  ')',  '=',  '?',  '`', '\b',  SPC,		/* 8 - 15 */
	 'Q',  'W',  'E',  'R',  'T',  'Z',  'U',  'I',		/* 16 - 23 */
	 'O',  'P','\232',  '*', '\r',  XXX,  'A',  'S',	/* 24 - 31 */
	 'D',  'F',  'G',  'H',  'J',  'K',  'L','\231',	/* 32 - 39 */
	'\216','\370',XXX,'\'',  'Y',  'X',  'C',  'V',		/* 40 - 47 */
	 'B',  'N',  'M',  ';',  ':',  SPC,  XXX,  SPC,		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC,  XXX,  XXX,  '>',  XXX,		/* 80 - 87 */
	 XXX							/* 88 */
};

#define SS0	0			/* No shift */
#define SS1	(SLS|SRS|CTS)		/* Shift, Ctrl */
#define SES	(SLS|SRS)		/* Shift */
#define LET	(SLS|SRS|CPLS|CTS)	/* Shift, Caps, Ctrl */
#define KEY	(SLS|SRS|NMLS|AKPS)	/* Shift, Num, Alt keypad */

static unsigned char smaptab[] ={
	       SS0,  SES,  SS1,  SES,  SES,  SES,  SS1,		/* 1 - 7 */
	 SES,  SES,  SES,  SES,  SS1,  SES,  CTS,  SES,		/* 8 - 15 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  LET,		/* 16 - 23 */
	 LET,  LET,  SS1,  SS1,  CTS, SHFT,  LET,  LET,		/* 24 - 31 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  SES,		/* 32 - 39 */
	 SES,  SS1, SHFT,  SS1,  LET,  LET,  LET,  LET,		/* 40 - 47 */
	 LET,  LET,  LET,  SES,  SES,  SES, SHFT,  SES,		/* 48 - 55 */
	SHFT,  SS1, SHFT,  SS0,  SS0,  SS0,  SS0,  SS0,		/* 56 - 63 */
	 SS0,  SS0,  SS0,  SS0,  SS0, SHFT,  KEY,  KEY,		/* 64 - 71 */
	 KEY,  KEY,  SS0,  KEY,  KEY,  KEY,  SS0,  KEY,		/* 72 - 79 */
	 KEY,  KEY,  KEY,  KEY,  SS0,  SS0,  SES,  SS0,		/* 80 - 87 */
	 SS0
};

/*
 * Load entry point.
 *  Do reset the keyboard because it gets terribly munged
 *  if you type during the boot.
 */
isload()
{
	register int i;

	/*
	 * Reset keyboard if NOT an XT turbo.
	 */
	if ( ! isturbo ) {
		outb(KBCTRL, 0x0C);		/* Clock low */
		for (i = 10582; --i >= 0; );	/* For 20ms */
		outb(KBCTRL, 0xCC);		/* Clock high */
		for (i = 0; --i != 0; )
			;
		i = inb(KBDATA);
		outb(KBCTRL, 0xCC);			/* Clear keyboard */
		outb(KBCTRL, 0x4D);			/* Enable keyboard */
	}

	/*
	 * Enable mmwatch() invocation every second.
	 */
	drvl[ISMAJ].d_time = 1;

	/*
	 * Seize keyboard interrupt.
	 */
	setivec(1, isrint);

	/*
	 * Initiailize video display.
	 */
	mmstart( &istty );
}

/*
 * Unload entry point.
 */
isuload()
{
	clrivec(1);
}

/*
 * Default function key strings (terminated by -1 [\377])
 */
static char *deffuncs[] = {
	"\33[1x\377",	/* F1 */
	"\33[2x\377",	/* F2 */
	"\33[3x\377",	/* F3 */
	"\33[4x\377", 	/* F4 */
	"\33[5x\377",	/* F5 */
	"\33[6x\377",	/* F6 */
	"\33[7x\377",	/* F7 */
	"\33[8x\377",	/* F8 */
	"\33[9x\377",	/* F9 */
	"\33[0x\377",	/* F10 - historical value */
	"\33[1y\377",	/* F11 */
	"\33[2y\377",	/* F12 */
	"\33[3y\377",	/* F13 */
	"\33[4y\377", 	/* F14 */
	"\33[5y\377",	/* F15 */
	"\33[6y\377",	/* F16 */
	"\33[7y\377",	/* F17 */
	"\33[8y\377",	/* F18 */
	"\33[9y\377",	/* F19 */
	"\33[0y\377"	/* F20 */
};

/*
 * Open routine.
 */
isopen(dev)
dev_t dev;
{
	register int s;

	if (minor(dev) != 0) {
		u.u_error = ENXIO;
		return;
	}
	if ((istty.t_flags&T_EXCL)!=0 && super()==0) {
		u.u_error = ENODEV;
		return;
	}
	ttsetgrp(&istty, dev);

	s = sphi();
	if (istty.t_open++ == 0)
	{  initkeys();	 /* init function keys */
	   istty.t_flags = T_CARR;  /* indicate "carrier" */
	   ttopen(&istty);
	}
	spl(s);
	updleds();			/* update keyboard status LEDS */
}

/* Init function keys */
initkeys()
{	register int i;
	register char *cp1, *cp2;

	for (i=0; i<NFKEY; i++)
	    isfval[i] = 0;	    /* clear function key buffer */
	cp2 = isfbuf;	      	    /* pointer to key buffer */   
	for (i=0; i<NFKEY; i++)
	{  isfval[i] = cp2;	    /* save pointer to key string */
	   cp1 = deffuncs[i];       /* get init string pointer */
	   while ((*cp2++ = *cp1++) != -1)  /* copy key data */
	     if (cp2 >= &isfbuf[NFBUF-3])   /* overflow? */
	        return;
	}
}

/*
 * Close a tty.
 */
isclose(dev)
{
	register int s;

	s = sphi();
	if (--istty.t_open == 0)
	{  	s = sphi();
		ttclose(&istty);
		spl(s);
	}
}

/*
 * Read routine.
 */
isread(dev, iop)
dev_t dev;
IO *iop;
{
	ttread(&istty, iop, 0);
	if (istty.t_oq.cq_cc)
		mmtime(&istty);
}

/*
 * Ioctl routine.
 */
isioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	register int s;

	switch(com) {
	case TIOCSETF:
	case TIOCGETF:
		isfunction(com, (char *)vec);
		return;
	case TIOCSHIFT:   /* switch left-SHIFT and "\" */
		lshift = LSHIFTA;    /* alternate values */
		lmaptab[41] = '\\';
		lmaptab[42] = XXX;
		umaptab[41] = '|';
		umaptab[42] = XXX;
		smaptab[41] = SS1;
		smaptab[42] = SHFT;
		return;
	case TIOCCSHIFT:  /* normal (default) left-SHIFT and "\" */
		lshift = LSHIFT;     /* normal values */
		lmaptab[41] = XXX;
		lmaptab[42] = '\\';
		umaptab[41] = XXX;
		umaptab[42] = '|';
		smaptab[41] = SHFT;
		smaptab[42] = SS1;
		return;
	}
	s = sphi();
	ttioctl(&istty, com, vec);
	spl(s);
}

/*
 * Set and receive the function keys.
 */
isfunction(c, v)
int c;
char *v;
{
	register char *cp;
	register int i;

	if (c == TIOCGETF) {
		for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++)
		    putubd(v++, *cp);
	} else {
		for (i=0; i<NFKEY; i++)		/* zap current settings */
			isfval[i] = 0;
		cp = isfbuf;			/* pointer to key buffer */
		for (i=0; i<NFKEY; i++) {
			isfval[i] = cp;	        /* save pointer to key string */
			while ((*cp++ = getubd(v++)) != -1)  /* copy key data */
				if (cp >= &isfbuf[NFBUF-3])  /* overflow? */
					return;
		}
	}
}


/*
 * Poll routine.
 */
ispoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll failure.
	 */
	if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) {

		if ( msec != 0 )
			pollopen( &istty.t_ipolls );

		/*
		 * Second look AFTER enabling monitor, avoiding interrupt race.
		 */
		if ( istty.t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}

	return ev;
}

/*
 * Receive interrupt.
 */
isrint()
{
	register int	c;
	register int	s;
	register int	r;
	int	savests;
	int	update_leds = 0;

	/*
	 * Schedule raw input handler if not already active.
	 */
	if ( isbusy == 0 ) {
		defer( isbatch, &istty );
		isbusy = 1;
	}

	/*
	 * Pull character from the data
	 * port. Pulse the KBFLAG in the control
	 * port to reset the data buffer.
	 */
	r = inb(KBDATA) & 0xFF;
	c = inb(KBCTRL);
	outb(KBCTRL, c|KBFLAG);
	outb(KBCTRL, c);
#if	0
	printf("kbd: %x %s\n", r&0x7F, (r&KEYUP) ? "up" : "down");
#endif
	if (ledcmd) {
		ledcmd = 0;
		if (r == KBACK) {		/* output to status LEDS */
			c = scroll & 1;
			if (shift & NMLS)
				c |= 2;
			if (shift & CPLS)
				c |= 4;
			outb(KBDATA, c);
		}
		return;
	}
	if (extended > 0) {			/* if multi-character seq, */
		--extended;			/* ... ignore this char */
		return;
	}

	switch (r) {
	case EXTENDED0:				/* 0xE0 prefix found */
		ext0seen = 1;
		return;
	case EXTENDED1:				/* ignore extended sequences */
		extended = 5;
		return;
	case 0xFF:				/* Overrun */
		return;
	}

	if (ext0seen) {
		ext0seen = 0;
		extmode = 1;
	} else 
		extmode = 0;

	c = (r & KEYSC) - 1;			/* bias to internal format */

	/*
	 * Check for reset.
	 */
	if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS))
		boot();

	/*
	 * Track "shift" keys.
	 */
	s = smaptab[c];
	if (s&SHFT) {
		if (r&KEYUP) {			/* "shift" released */
			if (c == RSHIFT)
				shift &= ~SRS;
			else if (c == lshift)
				shift &= ~SLS;
			else if (c == CTRL)
				shift &= ~CTS;
			else if (c == ALT)
				shift &= extmode ? ~AGS : ~ALS;
		} else {			/* "shift" pressed */
			if (c == lshift)
				shift |= SLS;
			else if (c == RSHIFT)
				shift |= SRS;
			else if (c == CTRL)
				shift |= CTS;
			else if (c == ALT)
				shift |= extmode ? AGS : ALS;
			else if (c == CAPLOCK) {
				shift ^= CPLS;	/* toggle cap lock */
				updleds();
			} else if (c == NUMLOCK) {
				shift ^= NMLS;	/* toggle num lock */
				updleds();
			}
		}
		return;
	}

	/*
	 * No other key up codes of interest.
	 */
	if (r&KEYUP)
		return;

	/*
	 * If the tty is not open the character is
	 * just tossed away.
	 */
	if (istty.t_open == 0)
		return;

	/*
	 * Map character, based on the
	 * current state of the shift, control, alt graphics,
	 * meta (ALT) and lock flags.
	 */
	if (shift & AGS)			/* Alt Graphics ? */
		c = agmaptab[c];
	else if (shift & CTS) {
		if (s == CTS)			/* Map Ctrl (BS | NL) */
			c = (c == BACKSP) ? 0x7F : 0x0A;  
		else if (s==SS1 || s==LET)	/* Normal Ctrl map */
			c = umaptab[c]&0x1F;	/* Clear bits 5-6 */
		else				
			return;			/* Ignore this char */
	} else if (s &= shift) {
		if (shift & SES) {		 /* if shift on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = lmaptab[c];  /* use unshifted */
			else
				c = umaptab[c];	 /* use shifted */
		} else {			 /* if shift not on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = umaptab[c];	 /* use shifted */
			else
				c = lmaptab[c];	 /* use unshifted */
		}
	} else					 
		c = lmaptab[c];			 /* use unshifted */

	/*
	 * Act on character.
	 */
	if (c == XXX)				
		return;				 /* char to ignore */

	if (c != SPC) {			 /* not special char? */
		if (shift & ALS)	 /* ALT (meta bit)? */
			c |= 0x80;	 /* set meta */
		isin(c);		 /* send the char */
	} else
		update_leds += isspecial(r);	 /* special chars */
	if (update_leds) {
		savests = sphi();
		outb(KBDATA, LEDCMD);
		ledcmd = 1;
		spl(savests);
	}
}

/*
 * Handle special input sequences.
 * The character passed is the key number.
 *
 * The keypad is translated by the following table,
 * the first entry is the normal sequence, the second the shifted,
 * and the third the alternate keypad sequence.
 */
static char *keypad[][3] = {
	{ "\33[H",  "7", "\33?w" },	/* 71 */
	{ "\33[A",  "8", "\33?x" },	/* 72 */
	{ "\33[V",  "9", "\33?y" },	/* 73 */
	{ "\33[D",  "4", "\33?t" },	/* 75 */
	{ "\0337",  "5", "\33?u" },	/* 76 */
	{ "\33[C",  "6", "\33?v" },	/* 77 */
	{ "\33[24H","1", "\33?q" },	/* 79 */
	{ "\33[B",  "2", "\33?r" },	/* 80 */
	{ "\33[U",  "3", "\33?s" },	/* 81 */
	{ "\33[@@",  "0", "\33?p" },	/* 82 */
	{ "\33[P", ".",  "\33?n" }	/* 83 */
};

isspecial(c)
int c;
{
	register char *cp;
	register int s;
	int	update_leds = 0;

	cp = 0;

	switch (c) {
	case 15:					/* cursor back tab */
		cp = "\033[Z";
		break;
	case 53:
		if (extmode)
			cp = "/";
		else if (shift & SES)
			cp = "_";
		else
			cp = "-";
		break;
	case 55:					/* ignore PrtScr */
		if (!extmode)
			cp = "*";
		break;
	case 59: case 60: case 61: case 62: case 63:	/* Function keys */
	case 64: case 65: case 66: case 67: case 68:
		/* offset to function string */
		if ( shift & ALS )
			cp = isfval[c-49];
		else
			cp = isfval[c-59];
		break;

	case 70:		/* Scroll Lock -- stop/start output */
	{
		static char cbuf[2];

		cp = &cbuf[0];  /* working buffer */
		if (!(istty.t_sgttyb.sg_flags&RAWIN)) {	/* not if in RAW mode */
			++update_leds;
			if (istty.t_flags & T_STOP) {	/* output stopped? */
			   cbuf[0] = istty.t_tchars.t_startc;  /* start it */
			   scroll = 0;
			} else {
			   cbuf[0] = istty.t_tchars.t_stopc;   /* stop output */
			   scroll = 1;
			}
		}
		break;
	}

	case 79:		/* 1/End */
	case 80:		/* 2/DOWN */
	case 81:		/* 3/PgDn */
	case 82:		/* 0/Ins */
	case 83:		/* ./Del */
		--c;		/* adjust code */
	case 75:		/* 4/LEFT */
	case 76:		/* 5 */
	case 77:		/* 6/RIGHT */
		--c;		/* adjust code */
	case 71:		/* 7/Home/Clear */
	case 72:		/* 8/UP */
	case 73:		/* 9/PgUp */
		s = 0;			/* start off with normal keypad */
		if (shift & NMLS)	/* num lock? */
			s = 1;		/* set shift pad */
		if (shift & SES)	/* shift? */
			s ^= 1;		/* toggle shift pad */
		if (shift & AKPS)	/* alternate pad? */
			s = 2;		/* set alternate pad */		
		if (extmode)		/* not from keypad? */
			s = 0;		/* force normal sequence */
		cp = keypad[c-71][s];   /* get keypad value */
		break;
	}
	if (cp)					/* send string */
		while ((*cp != 0) && (*cp != -1))
			isin( *cp++ & 0377 );
	return update_leds;
}

/**
 *
 * void
 * ismmfunc( c )	-- process keyboard related output escape sequences
 * char c;
 */
void
ismmfunc(c)
register int c;
{
	switch (c) {
	case 't':	/* Enter numlock */
		shift |= NMLS;
		updleds();			/* update LED status */
		break;
	case 'u':	/* Leave numlock */
		shift &= ~NMLS;
		updleds();			/* update LED status */
		break;
	case '=':	/* Enter alternate keypad */
		shift |= AKPS;
		break;
	case '>':	/* Exit alternate keypad */
		shift &= ~AKPS;
		break;
	case 'c':	/* Reset terminal */
		islock = 0;
		shift  = 0;
		initkeys();
		updleds();			/* update LED status */
		break;
	}
}

/**
 *
 * void
 * isin( c )	-- append character to raw input silo
 * char c;
 */
static
isin( c )
register int c;
{
	/*
	 * Cache received character.
	 */
	istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c;

	if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) )
		istty.t_rawin.si_ix = 0;
}

/**
 *
 * void
 * isbatch()	-- raw input conversion routine
 *
 *	Action:	Enable the video display.
 *		Canonize the raw input silo.
 *
 *	Notes:	isbatch() was scheduled as a deferred process by isrint().
 */
static void
isbatch( tp )
register TTY * tp;
{
	register int c;
	static int lastc;

	/*
	 * Ensure video display is enabled.
	 */
	mm_von();

	isbusy = 0;

	/*
	 * Process all cached characters.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		/*
		 * Get next cached char.
		 */
		c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ];

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;

		if ( (islock == 0) || ISINTR || ISQUIT ) {
			ttin( tp, c );
		}

		else if ( (c == 'b') && (lastc == '\033') ) {
			islock = 0;
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else if ( (c == 'c') && (lastc == '\033') ) {
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else
			putchar('\007');

		lastc = c;
	}
}

/*
 * update the keyboard status LEDS
 */
updleds()
{
	int	s;

	s = sphi();
	outb(KBDATA, LEDCMD);
	ledcmd = 1;
	spl(s);
}

/*
 * unlock the scroll in case an interrupt character is received
 */
kbunscroll()
{
	scroll = 0;
	updleds();
}
@
0707070064030050461004440000000000000000011777770507310704600005600000075100/newbits/kernel/USRSRC/i8086/drv/RCS/mmas.m,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.07.24.08.11.46;  author bin;  state Exp;
branches ;
next     ;


desc
@prov by hal
@



1.1
log
@Initial revision
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.0.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/	Memory mapped video driver assembler assist.
/
////////
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal information
/		CX    - input count
/		BP    - references terminal information
/		AH    - character attributes
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
////////

	NCOL	= 80		/ number of columns
	NCB	= 2		/ number of horizontal bytes per char
	NCR	= 1		/ number of horizontal lines per char
	NHB	= 160		/ number of horizontal bytes per line
	NRB	= NCR*NHB	/ number of bytes per character row

	ATTR	= ah		/ attribute byte
	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	INTENSE	= 0x08		/ high intensity attribute bit
	BLINK	= 0x80		/ blinking attribute bit
	REVERSE	= 0x70		/ reverse video

////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_BASE	= 8

	IOSYS	= 0
	IOUSR	= 1

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_INVIS	= 20		/ cursor invisible mask
MM_SLOW		= 22		/ slow [no flicker] video update
MM_WRAP		= 23		/ wrap to start of next line

/ Characters
AZERO		= 0x30
CLOWER		= 0x63
HLOWER		= 0x68
LLOWER		= 0x6C
SEMIC		= 0x3B
SPACE		= 0x20

	.globl	VIDSLOW_	/ Patchable kernel variable.
	.prvd
mmdata:	.word	mminit
	.word	0x03B4
	.word	0xB000
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, 23, 24, 0, 0, 0, 23
	.word	0
VIDSLOW_:.byte	0
	.byte	1
	.shri

////////
/
/ mmgo( iop )
/ IO *iop;
/
////////

	.globl	mmgo_

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc

	cmp	IO_SEG(bx), $IOSYS	/ user address space
	je	0f
	mov	bx, uds_
	mov	ds, bx
0:
	mov	bp, $mmdata
	mov	dx, MM_PORT(bp)		/ turn video off if color board
	cmp	dx, $0x3B4
	je	3f
	cmpb	MM_SLOW(bp), $0		/ check for slow [flicker-free]
	je	2f

	mov	dx, $0x3DA
1:	inb	al, dx			/ wait for vertical retrace
	testb	al, $8
	je	1b
2:
	mov	dx, $0x3D8		/ disable video
	movb	al, $0x25
	outb	dx, al
3:
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	sub	bx, bx
	movb	ATTR, MM_ATTR(bp)
	ijmp	MM_FUNC(bp)

exit:	pop	bx
	pop	es
	pop	ds
	movb	MM_ATTR(bp), ATTR
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, MM_PORT(bp)		/ adjust cursor location
	mov	bx, POS
	or	bx, MM_INVIS(bp)
	shr	bx, $1

	movb	al, $14
	outb	dx, al
	inc	dx
	movb	al, bh
	outb	dx, al
	dec	dx
	movb	al, $15
	outb	dx, al
	inc	dx
	movb	al, bl
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ turn video on
	add	dx, $4
	movb	al, $0x29
	outb	dx, al
	mov	mmvcnt_, $600		/ 600 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret


////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $CLOWER		/ schedule keyboard initialization
	call	int11_			/ read equipment status
	and	ax, $0x30		/ isolate video bits
	cmp	ax, $0x30		/ if not monochrome
	je	0f
	mov	MM_PORT(bp), $0x3D4	/	set color port
	mov	MM_BASE(bp), $0xB800	/	set color base
	mov	es, MM_BASE(bp)		/
0:					/
	mov	dx, MM_PORT(bp)		/ turn video off
	add	dx, $4
	movb	al, $0x21
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ zero display offset
	movb	al, $12
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al
	dec	dx
	movb	al, $13
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ reset border to black
	add	dx, $5
	subb	al, al
	outb	dx, al

	inc	dx			/ reset TECMAR XMSR register
	outb	dx, al

	mov	MM_INVIS(bp), $0
	movb	ATTR, $0x07
	movb	MM_ATTR(bp), ATTR
	movb	MM_WRAP(bp), $1
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ mmspec - schedule special keyboard function
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	cld
	rep
	movsw
	movb	al, $SPACE
	pop	di
	mov	cx, $NCOL
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, cs:rowtab(bx)
	call	exit
	jmp	eval

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, cs:rowtab(bx)
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	stosw				/ Update display memory.
	incb	COL
	cmpb	COL, $NCOL		/ Past end of line?
	jge	0f
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	cmpb	MM_WRAP(bp), $0		/ Yes past, Wrap around?
	jne	0f
	sub	di, $2			/ No wrap, adjust back to end of line.
	decb	COL
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	subb	COL, COL		/ Wrap to next line.
	incb	ROW
	cmpb	ROW, MM_EROW(bp)	/ Past scrolling region?
	jg	0f
	jcxz	ewait			/ Not past, evaluate next character.
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

0:	movb	ROW, MM_EROW(bp)	/ Yes past, scroll up 1 line.
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	sub	POS, $2
	decb	COL
	jge	0f
	movb	COL, $NCOL-1
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
0:	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:asctab(bx)

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $SEMIC
	je	csi_n2
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

0:	cmpb	al, $HLOWER
	je	mm_cgh
	cmpb	al, $LLOWER
	je	mm_cgl
	jmp	eval

////////
/
/ Csi_q state - entered after input sequence ESC [ ?
/	
////////

0:	call	exit
csi_q:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_q

0:	cmpb	al, $HLOWER
	je	mm_cqh
	cmpb	al, $LLOWER
	je	mm_cql
	jmp	eval

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jg	0f
	subb	COL, COL		/ cannot step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process ESC [ > N1 h escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process ESC [ > N1 l escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	decb	COL
	jge	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	push	cx
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl
	movb	al, $SPACE
	rep
	stosw
	pop	cx
	cmpb	COL, $NCOL
	jb	0f
	subb	COL, $NCOL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	eval

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cqh - process ESC [ ? N1 h escape sequence
/
/	Recognized sequences:	ESC [ ? 4 h	-- Set smooth scroll.
/				ESC [ ? 7 h	-- Set wraparound.
/
////////

mm_cqh:	cmpb	MM_N1(bp), $4		/ Smooth scroll.
	jne	0f
	movb	MM_SLOW(bp), $1
0:	cmpb	MM_N1(bp), $7		/ Wraparound.
	jne	0f
	movb	MM_WRAP(bp), $1
0:	jmp	eval

////////
/
/ mm_cql - process ESC [ ? N1 l escape sequence
/
/	Recognized sequences:	ESC [ ? 4 l	-- Set jump scroll.
/				ESC [ ? 7 l	-- Reset wraparound.
/
////////

mm_cql:	cmpb	MM_N1(bp), $4		/ Jump scroll.
	jne	0f
	movb	MM_SLOW(bp), $0
0:	cmpb	MM_N1(bp), $7		/ No wraparound.
	jne	0f
	movb	MM_WRAP(bp), $0
0:	jmp	eval

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, $NCOL
	jb	0f
	subb	COL, $NCOL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, $NCOL-1
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter (mm_n1) specifies the vertical position (MM_ROW(bp)).
/	The second parameter (mm_n2) specifies the horizontal position (MM_COL(bp)).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	rep
	movsw
	mov	di, cs:rowtab(bx)
	mov	cx, $NCOL
	movb	al, $SPACE
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input, and causing cursor to vanish.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2


////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

mm_e2:	push	cx
	movb	al, $SPACE
0:	mov	cx, $NCOL
	rep
	stosw
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

mm_e1:	push	cx
	mov	cx, POS
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

mm_e0:	push	cx
	shlb	bl, $1
	mov	cx, cs:rowtab+2(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, cs:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, cs:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, cs:rowtab(bx)
	jle	0f
	shr	cx, $1
	std
	rep
	movsw
	mov	di, cs:rowtab(bx)
	mov	cx, $NCOL
	movb	al, $SPACE
	cld
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, $NCOL
	jb	0f
	movb	COL, $NCOL-1
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	 MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_INVIS(bp), $0
	jmp	eval

0:	mov	MM_INVIS(bp), $-1
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					5 - slow blink
/					7 - reverse video
/					8 - concealed on
/					30-37 - foreground color
/					40-47 - background color
/					50-57 - border color
/
////////

mm_sgr:	movb	al, MM_N1(bp)

	cmpb	al, $0			/ reset all = 0
	jne	0f
	movb	ATTR, $0x07
1:	jmp	eval

0:	cmpb	al, $1			/ bold = 1
	jne	0f
	orb	ATTR, $INTENSE
	jmp	1b

0:	cmpb	al, $4			/ underline = 4
	jne	0f
	cmp	MM_PORT(bp), $0x03D4	/ color card?
	je	1b			/ yes, ignore underline
	andb	ATTR, $~0x77
	orb	ATTR, $0x01
	jmp	1b

0:	cmpb	al, $5			/ blinking = 5
	jne	0f
	orb	ATTR, $BLINK
	jmp	1b

0:	cmpb	al, $7			/ reverse video = 7
	jne	0f
	movb	al, $0x70
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f
	movb	al, ATTR		/ yes, exchange foreground/background
	andb	al, $0x77
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
2:	andb	ATTR, $~0x77
	orb	ATTR, al
	jmp	1b

0:	cmpb	al, $8			/ concealed on = 8
	jne	0f
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f

	andb	ATTR, $0x70		/ Yes,	Set foreground color
	movb	al, ATTR		/	to background color.
	rorb	al, $1
	rorb	al, $1
	rorb	al, $1
	rorb	al, $1
	orb	ATTR, al
	jmp	1b

2:	andb	ATTR, $0x80		/ No, set attributes to non-display.
	jmp	1b			/	retain blink attribute.

0:	cmp	MM_PORT(bp), $0x03D4	/ color card?
	jne	1b			/ no, ignore remaining options
0:	subb	al, $30			/ foreground color
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x07
	orb	ATTR, cs:fcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x70
	orb	ATTR, cs:bcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	movb	al, cs:fcolor(bx)
	push	dx
	mov	dx, MM_PORT(bp)
	add	dx, $5
	outb	dx, al
	pop	dx
/	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	mmbell	/* EOT  ENQ  ACK  BEL  */
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/* BS   HT   LF   VT   */
	.word	eval,	mm_cr,	eval,	eval	/* FF   CR   SO   SI   */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3  */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	mm_esc	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/*   ! " # \040 - \043 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* $ % & quote \044 - \047 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ( ) * + \050 - \053 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* , - . / \054 - \057 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 0 1 2 3 \060 - \063 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 4 5 6 7 \064 - \067 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 8 9 : ; \070 - \073 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* < = > ? \074 - \077 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* @@ A B C \100 - \103 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* D E F G \104 - \107 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* H I J K \110 - \113 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* L M N O \114 - \117 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* P Q R S \120 - \123 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* T U V W \124 - \127 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* X Y Z [ \130 - \133 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* \ ] ^ _ \134 - \137 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ` a b c \140 - \143 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* d e f g \144 - \147 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* h i j k \150 - \153 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* l m n o \154 - \157 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* p q r s \160 - \163 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* t u v w \164 - \167 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* x y z { \170 - \173 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* | } ~ ? \174 - \177 */

////////
/
/ esctab - table of functions indexed by ESC characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/* NUL  SOH  STX  ETX  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* EOT  ENQ  ACK  BEL  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* BS   HT   LF   VT   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FF   CR   SO   SI   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DLE  DC1  DC2  DC3  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DC4  NAK  SYN  ETB  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* CAN  EM   SUB  ESC  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	mm_new	/* 4 5 6 7 \064 - \067 */
	.word	mm_old,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	mmspec,	mmspec,	eval	/* < = > ? \074 - \077 */
	.word	eval,	eval,	eval,	eval	/* @@ A B C \100 - \103 */
	.word	mm_ind,	mm_cnl,	eval,	eval	/* D E F G \104 - \107 */
	.word	eval,	eval,	eval,	eval	/* H I J K \110 - \113 */
	.word	eval,	mm_ri,	eval,	eval	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	eval	/* P Q R S \120 - \123 */
	.word	eval,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	eval,	csi_n1	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_dmi,	eval,	mm_emi,	mminit	/* ` a b c \140 - \143 */
	.word	eval,	eval,	eval,	eval	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	eval,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	eval,	eval	/* p q r s \160 - \163 */
	.word	mmspec,	mmspec,	eval,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */


////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	eval	/* EOT  ENQ  ACK  BEL  */
	.word	eval,	eval,	eval,	eval	/* BS   HT   LF   VT   */
	.word	eval,	eval,	eval,	eval	/* FF   CR   SO   SI   */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3  */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	eval	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	eval	/* 4 5 6 7 \064 - \067 */
	.word	eval,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	eval,	csi_gt,	csi_q	/* < = > ? \074 - \077 */
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/* @@ A B C \100 - \103 */
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/* D E F G \104 - \107 */
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/* H I J K \110 - \113 */
	.word	mm_il,	mm_dl,	eval,	mm_ea	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	mm_ind	/* P Q R S \120 - \123 */
	.word	mm_ri,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	mm_cbt,	eval	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_hpa,	mm_hpr,	eval,	eval	/* ` a b c \140 - \143 */
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	mm_sgr,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	mm_ssr,	eval	/* p q r s \160 - \163 */
	.word	eval,	eval,	mm_scr,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ coltab - integer array of offsets to each column
/
////////

coltab:	.word	 0*NCB,	 1*NCB,	 2*NCB,	 3*NCB
	.word	 4*NCB,	 5*NCB,	 6*NCB,	 7*NCB
	.word	 8*NCB,	 9*NCB,	10*NCB,	11*NCB
	.word	12*NCB,	13*NCB,	14*NCB,	15*NCB
	.word	16*NCB,	17*NCB,	18*NCB,	19*NCB
	.word	20*NCB,	21*NCB,	22*NCB,	23*NCB
	.word	24*NCB,	25*NCB,	26*NCB,	27*NCB
	.word	28*NCB,	29*NCB,	30*NCB,	31*NCB
	.word	32*NCB,	33*NCB,	34*NCB,	35*NCB
	.word	36*NCB,	37*NCB,	38*NCB,	39*NCB
	.word	40*NCB,	41*NCB,	42*NCB,	43*NCB
	.word	44*NCB,	45*NCB,	46*NCB,	47*NCB
	.word	48*NCB,	49*NCB,	50*NCB,	51*NCB
	.word	52*NCB,	53*NCB,	54*NCB,	55*NCB
	.word	56*NCB,	57*NCB,	58*NCB,	59*NCB
	.word	60*NCB,	61*NCB,	62*NCB,	63*NCB
	.word	64*NCB,	65*NCB,	66*NCB,	67*NCB
	.word	68*NCB,	69*NCB,	70*NCB,	71*NCB
	.word	72*NCB,	73*NCB,	74*NCB,	75*NCB
	.word	76*NCB,	77*NCB,	78*NCB,	79*NCB

////////
/
/ rowtab - array of offsets to each row
/
////////

rowtab:	.word	 0*NRB,	 1*NRB,	 2*NRB,	 3*NRB
	.word	 4*NRB,	 5*NRB,	 6*NRB,	 7*NRB
	.word	 8*NRB,	 9*NRB,	10*NRB,	11*NRB
	.word	12*NRB,	13*NRB,	14*NRB,	15*NRB
	.word	16*NRB,	17*NRB,	18*NRB,	19*NRB
	.word	20*NRB,	21*NRB,	22*NRB,	23*NRB
	.word	24*NRB,	25*NRB,	26*NRB,	27*NRB
	.word	28*NRB,	29*NRB,	30*NRB,	31*NRB

////////
/
/ fcolor - foreground color
/ bcolor - background color
/
/	indexed by ansi color (black,red,green,brown,blue,magenta,cyan,white)
/	yields graphics color (black,blue,green,cyan,red,magenta,brown,white)
/		which is properly shifted for installation in attribute byte.
/
////////

fcolor:	.byte	0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
bcolor:	.byte	0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70

////////
/
/ mm_voff()	-- turn video display off
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, mmdata+MM_PORT
	add	dx, $4
	movb	al, $0x21
	outb	dx, al
	ret

////////
/
/ mm_von()	-- turn video display on
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, mmdata+MM_PORT	/ enable video display
	add	dx, $4
	movb	al, $0x29
	outb	dx, al
	mov	mmvcnt_, $900		/ 900 seconds before video disabled
	ret
@
0707070064030031051004440000000000000000011777770507310705700005500000105150/newbits/kernel/USRSRC/i8086/drv/RCS/ati.m,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.07.24.08.12.00;  author bin;  state Exp;
branches ;
next     ;


desc
@prov by hal, replaced ati.s
@



1.1
log
@Initial revision
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.0.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
////////
/
/ Array Technologies Inc - Graphics Solution - Device Driver
/
/	 Supports 40/80/132 column color text
/		     80/132 column monochrome text
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal information
/		CX    - input count
/		BP    - references terminal information
/		AH    - character attributes
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
/ 
////////

	NCB	= 2		/ number of horizontal bytes per char
	NCR	= 1		/ number of horizontal lines per char
	NHB	= 160		/ number of horizontal bytes per line
	NRB	= NCR*NHB	/ number of bytes per character row

	ATTR	= ah		/ attribute byte
	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	INTENSE	= 0x08		/ high intensity attribute bit
	BLINK	= 0x80		/ blinking attribute bit
	REVERSE	= 0x70		/ reverse video

////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_BASE	= 8

	IOSYS	= 0
	IOUSR	= 1

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_INVIS	= 20		/ cursor invisible mask
MM_NCOL		= 22		/ number of columns
MM_DATA		= 24		/ pointer to crt data
MM_MODE		= 26		/ mode register [0x21=col80/132,0x20=col40]

/ ASCII characters
AZERO		= 0x30
CLOWER		= 0x63
SEMIC		= 0x3B
SPACE		= 0x20

	.prvd
mmdata:	.word	mminit
	.word	0x03D4
	.word	0xB800
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, 23, 24, 0, 0, 0, 23
	.word	0
	.word	80
	.word	creg80
	.byte	0x21, 0x00
	.shri

////////
/
/ creg40, creg80, creg132 - crt register values for 40/80/132 column color
/         mreg80, mreg132 - crt register values for 80/132 column monochrome
/
////////

creg40:	.byte	0x38, 0x28, 0x2D, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

creg80:	.byte	0x71, 0x50, 0x5A, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

mreg80:	.byte	0x61, 0x50, 0x52, 0x0F, 0x19, 0x06, 0x19, 0x19
	.byte	0x02, 0x0D, 0x0B, 0x0C, 0x00, 0x00, 0x00, 0x00

#ifdef ATI_132
	.globl	creg132
creg132:.byte	0xB5, 0x84, 0x97, 0x0A, 0x1F, 0x06, 0x19, 0x1C
	.byte	0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00

	.globl	mreg132
mreg132:.byte	0x9F, 0x84, 0x89, 0x0F, 0x19, 0x06, 0x19, 0x19
	.byte	0x02, 0x0D, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00
#endif

////////
/
/ mmgo( iop )
/ IO *iop;
/
////////

	.globl	mmgo_

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc
	cmp	IO_SEG(bx), $IOSYS
	je	0f
	mov	ds, uds_
0:	mov	bp, $mmdata

	mov	dx, MM_PORT(bp)		/ turn video off if color board
	cmp	dx, $0x3B4
	je	0f
	add	dx, $4
	movb	al, MM_MODE(bp)
	outb	dx, al
0:
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	sub	bx, bx
	movb	ATTR, MM_ATTR(bp)
	ijmp	MM_FUNC(bp)

exit:	pop	bx
	pop	es
	pop	ds
	movb	MM_ATTR(bp), ATTR
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, MM_PORT(bp)		/ adjust cursor location
	mov	bx, POS
	or	bx, MM_INVIS(bp)
	shr	bx, $1

	movb	al, $14
	outb	dx, al
	inc	dx
	movb	al, bh
	outb	dx, al
	dec	dx
	movb	al, $15
	outb	dx, al
	inc	dx
	movb	al, bl
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ turn video on
	add	dx, $4
	movb	al, MM_MODE(bp)
	orb	al, $0x08
	outb	dx, al
	mov	mmvcnt_, $300		/ 300 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $CLOWER		/ schedule keyboard initialization
	mov	MM_NCOL(bp), $80	/ set 80 column mode
	movb	MM_MODE(bp), $0x21
	mov	MM_DATA(bp), $creg80

#ifdef	ATI_132
	mov	dx, $0x3DF		/ clear 132 column color
	movb	al, $0x00		/ in mode select register
	outb	dx, al

	mov	dx, $0x3BA		/ clear 132 column monochrome
	movb	al, $0x00		/ in mode select register
	outb	dx, al
#endif

	call	int11_			/ read equipment status
	andb	al, $0x30		/ isolate video bits
	cmpb	al, $0x30		/ if monochrome
	jne	0f
	mov	MM_DATA(bp), $mreg80	/	set monochrome register info
	mov	MM_PORT(bp), $0x3B4	/	set monochrome port
	mov	MM_BASE(bp), $0xB000	/	set monochrome base
	mov	es, MM_BASE(bp)		/		and extra segment.

0:	call	newcrt			/ reprogram crt registers

reinit:	sub	ax, ax			/ regenerate row table
	mov	bx, $rowtab
1:	mov	ss:(bx), ax
	add	ax, MM_NCOL(bp)
	add	ax, MM_NCOL(bp)
	add	bx, $2
	cmp	bx, $rowend
	jb	1b

	mov	dx, MM_PORT(bp)		/ zero display offset
	movb	al, $12
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al
	dec	dx
	movb	al, $13
	outb	dx, al
	inc	dx
	subb	al, al
	outb	dx, al

	mov	dx, MM_PORT(bp)		/ reset border to black
	add	dx, $5
	subb	al, al
	outb	dx, al

	mov	MM_INVIS(bp), $0
	movb	ATTR, $0x07
	movb	MM_ATTR(bp), ATTR
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ newcrt -- reload crt registers
/
/	Action:	Program crt registers with values defined in code space
/		at offset given by MM_DATA(bp).
/
/	Note:	AX, BX, DX, DI trashed on exit.
/
////////

newcrt:	mov	dx, MM_PORT(bp)		/ turn video off
	add	dx, $4
	movb	al, MM_MODE(bp)
	outb	dx, al

	mov	di, MM_DATA(bp)		/ program crt registers, last to first
	mov	bx, $15			/ [delay between i/o]
	mov	dx, MM_PORT(bp)		/ [NOTE:DI=obsolete screen offset]
0:	movb	al, bl
	outb	dx, al
	movb	al, cs:(bx,di)
	inc	dx
	outb	dx, al
	dec	dx
	dec	bx
	jge	0b
	ret

////////
/
/ mm_so - stand out - define 40 column attributes
/
////////

mm_so:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	mm_si

	mov	MM_NCOL(bp), $40	/	setup for 40 column color
	movb	MM_MODE(bp), $0x20
	mov	MM_DATA(bp), $creg40

#ifdef	ATI_132
	mov	dx, $0x3DF		/	clear 132 column color
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/ program crt registers
	jmp	reinit

////////
/
/ mm_si - define 80 column attributes
/
////////

mm_si:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	0f

	mov	MM_NCOL(bp), $80
	movb	MM_MODE(bp), $0x21
	mov	MM_DATA(bp), $creg80

#ifdef	ATI_132
	mov	dx, $0x3DF		/	clear 132 column color
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/	reprogram crt registers.
	jmp	reinit

0:	mov	MM_NCOL(bp), $80
	mov	MM_DATA(bp), $mreg80
	movb	MM_MODE(bp), $0x21

#ifdef	ATI_132
	mov	dx, $0x3BA		/	clear 132 column monochrome
	movb	al, $0x00		/	in mode select register
	outb	dx, al			/	[delay between i/o]
#endif

	call	newcrt			/	reprogram crt registers
	jmp	reinit

////////
/
/ mm_132 - define 132 column attributes
/
////////

mm_132:
	cmp	MM_PORT(bp), $0x3D4	/ if color card
	jne	0f

#ifdef	ATI_132
	mov	MM_DATA(bp), $creg132	/	set color crt values
	mov	MM_NCOL(bp), $132	/	set columns to 132
	movb	MM_MODE(bp), $0x21

	call	newcrt			/	set 132 column crt values
					/	BEFORE setting mode select reg

	mov	dx, $0x3DF		/	set 132 columns
	movb	al, $0x10		/		in mode select register
	outb	dx, al
#endif
	jmp	reinit

0:
#ifdef	ATI_132
	mov	MM_NCOL(bp), $132	/	set columns to 132
	movb	MM_MODE(bp), $0x21	/	set 80/132 column display mode
	mov	MM_DATA(bp), $mreg132	/	set monochrome crt values

	call	newcrt			/	set 132 column crt values
					/	BEFORE setting mode select reg

	mov	dx, $0x3BA		/	set 132 columns monochrome
	movb	al, $0x08		/		in mode select register
	outb	dx, al
#endif
	jmp	reinit

////////
/
/ mmspec - schedule special keyboard function
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
	mov	si, ss:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, ss:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	cld
	rep
	movsw
	movb	al, $SPACE
	pop	di
	mov	cx, MM_NCOL(bp)
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	movb	bl, COL			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:coltab(bx)
	movb	bl, ROW
	shlb	bl, $1
	add	POS, ss:rowtab(bx)
	call	exit
	jmp	eval

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, COL			/ reposition to ROW and COL
	shl	bx, $1			/ [trash BH]
	mov	POS, cs:coltab(bx)
	subb	bh, bh			/ [clear BH]
	movb	bl, ROW
	shlb	bl, $1
	add	POS, ss:rowtab(bx)
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	stosw
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jnb	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	sub	POS, $2
	subb	COL, $1
	jnb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
0:	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	jc	mmputc
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $SEMIC
	je	csi_n2
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	1f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

1:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csgtab(bx)

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jnb	0f
	subb	COL, COL		/ cannot step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process ESC [ > N1 h escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process ESC [ > N1 l escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	push	cx
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl
	movb	al, $SPACE
	rep
	stosw
	pop	cx
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	eval

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The 1st parameter (mm_n1) specifies the vertical   position MM_ROW(bp).
/	The 2nd parameter (mm_n2) specifies the horizontal position MM_COL(bp).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	orb	ROW, ROW
	je	0f
	decb	ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
	mov	si, ss:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, ss:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	rep
	movsw
	mov	di, ss:rowtab(bx)
	mov	cx, MM_NCOL(bp)
	movb	al, $SPACE
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input, and causing cursor to vanish.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2


////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

mm_e2:	push	cx
	movb	al, $SPACE
0:	mov	cx, MM_NCOL(bp)
	rep
	stosw
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

mm_e1:	push	cx
	mov	cx, POS
	shlb	bl, $1
	mov	POS, ss:rowtab(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

mm_e0:	push	cx
	shlb	bl, $1
	mov	cx, ss:rowtab+2(bx)
	sub	cx, POS
	jl	0f
	movb	al, $SPACE
	shr	cx, $1
	rep
	stosw
0:	pop	cx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, ss:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, ss:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, ss:rowtab(bx)
	jle	0f
	shr	cx, $1
	std
	rep
	movsw
	mov	di, ss:rowtab(bx)
	mov	cx, MM_NCOL(bp)
	movb	al, $SPACE
	cld
	rep
	stosw
	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	di, ss:rowtab(bx)
0:	pop	cx
	pop	si
	pop	ds
	call	exit
	jmp	eval

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	orb	ROW, ROW
	je	0f
	decb	ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	orb	COL, COL
	je	0f
	decb	COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	 MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_INVIS(bp), $0
	jmp	eval

0:	mov	MM_INVIS(bp), $-1
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					5 - slow blink
/					7 - reverse video
/					30-37 - foreground color
/					40-47 - background color
/					50-57 - border color
/
////////

mm_sgr:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	ATTR, $0x07
1:	jmp	eval
0:	cmpb	al, $1		/ bold
	jne	0f
	orb	ATTR, $INTENSE
	jmp	1b
0:	cmpb	al, $4		/ underline
	jne	0f
	cmp	MM_PORT(bp), $0x03D4	/ color card?
	je	1b			/ yes, ignore underline
	andb	ATTR, $~0x77
	orb	ATTR, $0x01
	jmp	1b
0:	cmpb	al, $5		/ blinking
	jne	0f
	orb	ATTR, $BLINK
	jmp	1b
0:	cmpb	al, $7		/ reverse video
	jne	0f
	movb	al, $0x70
	cmp	MM_PORT(bp), $0x3D4	/ color card?
	jne	2f
	movb	al, ah			/ yes, exchange foreground/background
	andb	al, $0x77
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
	rolb	al, $1
2:	andb	ATTR, $~0x77
	orb	ATTR, al
	jmp	1b
0:	cmp	MM_PORT(bp), $0x03D4	/ color card?
	jne	1b			/ no, ignore remaining options
0:	subb	al, $30		/ foreground color
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x07
	orb	ATTR, cs:fcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	andb	ATTR, $~0x70
	orb	ATTR, cs:bcolor(bx)
	jmp	1f
0:	subb	al, $10
	jl	1f
	cmpb	al, $7
	jg	0f
	movb	bl, al
	movb	al, cs:fcolor(bx)
	push	dx
	mov	dx, MM_PORT(bp)
	add	dx, $5
	outb	dx, al
	pop	dx
/	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	mmbell	/	EOT  ENQ  ACK  BEL
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/	BS   HT   LF   VT
	.word	eval,	mm_cr,	mm_so,	mm_si	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
/ DEBUG: mm_132 is only inserted temporarily, for testing - 86/05/26
	.word	eval,	eval,	eval,	mm_132	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	mm_esc	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	  ! dquote # \040 - \043
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	$ % & quote \044 - \047
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	( ) * + \050 - \053
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	, - . / \054 - \057
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	0 1 2 3 \060 - \063
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	4 5 6 7 \064 - \067
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	8 9 : ; \070 - \073
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	< = > ? \074 - \077
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	@@ A B C \100 - \103
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	D E F G \104 - \107
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	H I J K \110 - \113
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	L M N O \114 - \117
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	P Q R S \120 - \123
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	T U V W \124 - \127
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	X Y Z [ \130 - \133
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	\ ] ^ _ \134 - \137
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	` a b c \140 - \143
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	d e f g \144 - \147
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	h i j k \150 - \153
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	l m n o \154 - \157
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	p q r s \160 - \163
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	t u v w \164 - \167
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	x y z { \170 - \173
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	| } ~ ? \174 - \177

////////
/
/ esctab - table of functions indexed by escape characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/	NUL  SOH  STX  ETX
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	EOT  ENQ  ACK  BEL
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	BS   HT   LF   VT
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	FF   CR   SO   SI
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	DLE  DC1  DC2  DC3
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	DC4  NAK  SYN  ETB
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	CAN  EM   SUB  ESC
	.word	mmputc,	mmputc,	mmputc,	mmputc	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! dquote # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & quote \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	mm_new	/	4 5 6 7 \064 - \067
	.word	mm_old,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	mmspec,	mmspec,	eval	/	< = > ? \074 - \077
	.word	eval,	eval,	eval,	eval	/	@@ A B C \100 - \103
	.word	mm_ind,	mm_cnl,	eval,	eval	/	D E F G \104 - \107
	.word	eval,	eval,	eval,	eval	/	H I J K \110 - \113
	.word	eval,	mm_ri,	eval,	eval	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	eval	/	P Q R S \120 - \123
	.word	eval,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	eval,	csi_n1	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	mm_dmi,	eval,	mm_emi,	mminit	/	` a b c \140 - \143
	.word	eval,	eval,	eval,	eval	/	d e f g \144 - \147
	.word	eval,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	eval,	eval,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	eval,	eval	/	p q r s \160 - \163
	.word	mmspec,	mmspec,	eval,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	eval	/	EOT  ENQ  ACK  BEL
	.word	eval,	eval,	eval,	eval	/	BS   HT   LF   VT
	.word	eval,	eval,	eval,	eval	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
	.word	eval,	eval,	eval,	eval	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	eval	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! dquote # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & quote \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	eval	/	4 5 6 7 \064 - \067
	.word	eval,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	eval,	csi_gt,	eval	/	< = > ? \074 - \077
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/	@@ A B C \100 - \103
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/	D E F G \104 - \107
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/	H I J K \110 - \113
	.word	mm_il,	mm_dl,	eval,	mm_ea	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	mm_ind	/	P Q R S \120 - \123
	.word	mm_ri,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	mm_cbt,	eval	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	mm_hpa,	mm_hpr,	eval,	eval	/	` a b c \140 - \143
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/	d e f g \144 - \147
	.word	eval,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	eval,	mm_sgr,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	mm_ssr,	eval	/	p q r s \160 - \163
	.word	eval,	eval,	mm_scr,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ csgtab - table of functions indexed by ESC [ > characters.
/
////////

csgtab:	.word	eval,	eval,	eval,	eval	/	NUL  SOH  STX  ETX
	.word	eval,	eval,	eval,	eval	/	EOT  ENQ  ACK  BEL
	.word	eval,	eval,	eval,	eval	/	BS   HT   LF   VT
	.word	eval,	eval,	eval,	eval	/	FF   CR   SO   SI
	.word	eval,	eval,	eval,	eval	/	DLE  DC1  DC2  DC3
	.word	eval,	eval,	eval,	eval	/	DC4  NAK  SYN  ETB
	.word	eval,	eval,	eval,	eval	/	CAN  EM   SUB  ESC
	.word	eval,	eval,	eval,	eval	/	FS   GS   RS   US
	.word	eval,	eval,	eval,	eval	/	  ! dquote # \040 - \043
	.word	eval,	eval,	eval,	eval	/	$ % & quote \044 - \047
	.word	eval,	eval,	eval,	eval	/	( ) * + \050 - \053
	.word	eval,	eval,	eval,	eval	/	, - . / \054 - \057
	.word	eval,	eval,	eval,	eval	/	0 1 2 3 \060 - \063
	.word	eval,	eval,	eval,	eval	/	4 5 6 7 \064 - \067
	.word	eval,	eval,	eval,	eval	/	8 9 : ; \070 - \073
	.word	eval,	eval,	eval,	eval	/	< = > ? \074 - \077
	.word	eval,	eval,	eval,	eval	/	@@ A B C \100 - \103
	.word	eval,	eval,	eval,	eval	/	D E F G \104 - \107
	.word	eval,	eval,	eval,	eval	/	H I J K \110 - \113
	.word	eval,	eval,	eval,	eval	/	L M N O \114 - \117
	.word	eval,	eval,	eval,	eval	/	P Q R S \120 - \123
	.word	eval,	eval,	eval,	eval	/	T U V W \124 - \127
	.word	eval,	eval,	eval,	eval	/	X Y Z [ \130 - \133
	.word	eval,	eval,	eval,	eval	/	\ ] ^ _ \134 - \137
	.word	eval,	eval,	eval,	eval	/	` a b c \140 - \143
	.word	eval,	eval,	eval,	eval	/	d e f g \144 - \147
	.word	mm_cgh,	eval,	eval,	eval	/	h i j k \150 - \153
	.word	mm_cgl,	eval,	eval,	eval	/	l m n o \154 - \157
	.word	eval,	eval,	eval,	eval	/	p q r s \160 - \163
	.word	eval,	eval,	eval,	eval	/	t u v w \164 - \167
	.word	eval,	eval,	eval,	eval	/	x y z { \170 - \173
	.word	eval,	eval,	eval,	eval	/	| } ~ ? \174 - \177

////////
/
/ coltab - integer array of offsets to each column - up to 132 columns
/
////////

coltab:	.word	  0*NCB,   1*NCB,   2*NCB,   3*NCB
	.word	  4*NCB,   5*NCB,   6*NCB,   7*NCB
	.word	  8*NCB,   9*NCB,  10*NCB,  11*NCB
	.word	 12*NCB,  13*NCB,  14*NCB,  15*NCB
	.word	 16*NCB,  17*NCB,  18*NCB,  19*NCB
	.word	 20*NCB,  21*NCB,  22*NCB,  23*NCB
	.word	 24*NCB,  25*NCB,  26*NCB,  27*NCB
	.word	 28*NCB,  29*NCB,  30*NCB,  31*NCB
	.word	 32*NCB,  33*NCB,  34*NCB,  35*NCB
	.word	 36*NCB,  37*NCB,  38*NCB,  39*NCB
	.word	 40*NCB,  41*NCB,  42*NCB,  43*NCB
	.word	 44*NCB,  45*NCB,  46*NCB,  47*NCB
	.word	 48*NCB,  49*NCB,  50*NCB,  51*NCB
	.word	 52*NCB,  53*NCB,  54*NCB,  55*NCB
	.word	 56*NCB,  57*NCB,  58*NCB,  59*NCB
	.word	 60*NCB,  61*NCB,  62*NCB,  63*NCB
	.word	 64*NCB,  65*NCB,  66*NCB,  67*NCB
	.word	 68*NCB,  69*NCB,  70*NCB,  71*NCB
	.word	 72*NCB,  73*NCB,  74*NCB,  75*NCB
	.word	 76*NCB,  77*NCB,  78*NCB,  79*NCB
	.word	 80*NCB,  81*NCB,  82*NCB,  83*NCB
	.word	 84*NCB,  85*NCB,  86*NCB,  87*NCB
	.word	 88*NCB,  89*NCB,  90*NCB,  91*NCB
	.word	 92*NCB,  93*NCB,  94*NCB,  95*NCB
	.word	 96*NCB,  97*NCB,  98*NCB,  99*NCB
	.word	100*NCB, 101*NCB, 102*NCB, 103*NCB
	.word	104*NCB, 105*NCB, 106*NCB, 107*NCB
	.word	108*NCB, 109*NCB, 110*NCB, 111*NCB
	.word	112*NCB, 113*NCB, 114*NCB, 115*NCB
	.word	116*NCB, 117*NCB, 118*NCB, 119*NCB
	.word	120*NCB, 121*NCB, 122*NCB, 123*NCB
	.word	124*NCB, 125*NCB, 126*NCB, 127*NCB
	.word	128*NCB, 129*NCB, 130*NCB, 131*NCB

////////
/
/ rowtab - array of offsets to each row - up to 44 rows
/	   automatically regenerated by reinit().
/
/	NOTE: In kernel data space to allow modification in protected mode.
/
////////

	.shrd
rowtab:	.word	 0*NRB,	 1*NRB,	 2*NRB,	 3*NRB
	.word	 4*NRB,	 5*NRB,	 6*NRB,	 7*NRB
	.word	 8*NRB,	 9*NRB,	10*NRB,	11*NRB
	.word	12*NRB,	13*NRB,	14*NRB,	15*NRB
	.word	16*NRB,	17*NRB,	18*NRB,	19*NRB
	.word	20*NRB,	21*NRB,	22*NRB,	23*NRB
	.word	24*NRB,	25*NRB,	26*NRB,	27*NRB
	.word	28*NRB,	29*NRB,	30*NRB,	31*NRB
	.word	32*NRB,	33*NRB,	34*NRB,	35*NRB
	.word	36*NRB,	37*NRB,	38*NRB,	39*NRB
	.word	40*NRB,	41*NRB,	42*NRB,	43*NRB
rowend:
	.shri

////////
/
/ fcolor - foreground color
/ bcolor - background color
/
/	indexed by ansi color (black,red,green,brown,blue,magenta,cyan,white)
/	yields graphics color (black,blue,green,cyan,red,magenta,brown,white)
/		which is properly shifted for installation in attribute byte.
/
////////

fcolor:	.byte	0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
bcolor:	.byte	0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70

////////
/
/ mm_voff()	-- Disable video display.
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, mmdata+MM_PORT
	add	dx, $4
	movb	al, mmdata+MM_MODE
	outb	dx, al
	ret

////////
/
/ mm_von()	-- Enable video display
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, mmdata+MM_PORT	/ enable video display
	add	dx, $4
	movb	al, mmdata+MM_MODE
	orb	al, $0x08
	outb	dx, al
	mov	mmvcnt_, $300		/ 300 seconds before video disabled
	ret
@
0707070064030147531004440000000000000000011777770507310707100005600000114157/newbits/kernel/USRSRC/i8086/drv/RCS/gras.m,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.07.24.08.12.22;  author bin;  state Exp;
branches ;
next     ;


desc
@prov by hal, replaced gras.s
@



1.1
log
@Initial revision
@
text
@/ (lgl-
/ 	COHERENT Driver Kit Version 1.0.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
	.globl	grread_
	.globl	grwrite_
	.globl	mmgo_

////////
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal attributes
/		CX    - input count
/		BP    - references terminal information
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
////////

#ifdef	HERCULES
	VSEG	= 0xB000	/ Video Display Segment
	BANKSZ	= 8192		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 8		/ number of horizontal lines per char
	NCR2	= 4		/ number of horizontal lines per char / 2
	NCR4	= 2		/ number of horizontal lines per char / 4
	NHB	= 90		/ number of horizontal bytes per line
#else
#ifdef TECMAR
	VSEG	= 0xA000	/ Video Display Segment
	BANKSZ	= 32768		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 16		/ number of horizontal lines per char
	NCR2	= 8		/ number of horizontal lines per char / 2
	NCR4	= 4		/ number of horizontal lines per char / 4
	NHB	= 80		/ number of horizontal bytes per line
#else
	VSEG    = 0xB800	/ Video Display Segment
	BANKSZ	= 8192		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 8		/ number of horizontal lines per char
	NCR2	= 4		/ number of horizontal lines per char / 2
	NCR4	= 2		/ number of horizontal lines per char / 4
	NHB	= 80		/ number of horizontal bytes per line
#endif
#endif

	NRB	= NHB*NCR	/ number of bytes per character row
	NRB2	= NHB*NCR2	/ number of bytes per character row / 2
	NRB4	= NHB*NCR4	/ number of bytes per character row / 4


	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	CSR	= 0x3D9		/ Color Select Register
	MSR	= 0x3D8		/ Mode Select Register
	XMSR	= 0x3DA		/ Extended Mode Select Register


////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_SEEK	= 4
	IO_BASE	= 8

	IOSYS	= 0

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_FLIP		= 20
MM_MASK		= 22
MM_ULINE	= 24
MM_CURSE	= 26
MM_VIS		= 28		/ set to -1 to make cursor visible
MM_NCOL		= 30
MM_WRAP		= 31

/ ASCII characters
AZERO		= 0x30
CLOWER		= 0x63
HLOWER		= 0x68
LLOWER		= 0x6C
SEMIC		= 0x3B

	.prvd
mmdata:	.word	mminit, 0x03D4, VSEG
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, LROW-1, LROW, 0, 0, 0, LROW-1
	.word	0, -1, 0, 0xff
	.word	0
	.byte	80
	.byte	1

	.shri
#ifdef	HERCULES
crtdata:.byte	 54,  45,  45,   8,  91,   1,  86,  88
	.byte	  2,   3,  32,   0,   0,   0,   0,   0
#else
#ifdef TECMAR
crtdata:.byte	 56,  40,  43,   8, 127,   6, 100, 112
	.byte	  3,   1,  32,   0,   0,   0,   0,   0
#else
crtdata:.byte	 56,  40,  43,   8, 127,   6, 100, 112
	.byte	  2,   1,  32,   0,   0,   0,   0,   0
#endif
#endif
	.shri

////////
/
/ mmgo( iop )		- Entry point for text stream output
/ IO *iop;
/
////////

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc
	cmp	IO_SEG(bx), $IOSYS
	je	0f
	mov	bx, uds_
	mov	ds, bx
0:	mov	bp, $mmdata
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	mov	ax, MM_CURSE(bp)
	and	ax, MM_VIS(bp)
#ifdef TECMAR
	xor	es:[NHB*6](POS), ax
	xor	es:[NHB*6]+BANKSZ(POS), ax
	xor	es:[NHB*7](POS), ax
	xor	es:[NHB*7]+BANKSZ(POS), ax
#else
	xor	es:[NHB*3](POS), ax	/ turn cursor off
	xor	es:[NHB*3]+BANKSZ(POS), ax
#endif
	sub	bx, bx
	ijmp	MM_FUNC(bp)

exit:	movb	bl, ROW			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	bl, $1
0:	add	POS, bx
	mov	ax, MM_CURSE(bp)
	and	ax, MM_VIS(bp)
#ifdef TECMAR
	xor	es:[NHB*6](POS), ax	/ turn cursor on
	xor	es:[NHB*6]+BANKSZ(POS), ax
	xor	es:[NHB*7](POS), ax
	xor	es:[NHB*7]+BANKSZ(POS), ax
#else
	xor	es:[NHB*3](POS), ax	/ turn cursor on
	xor	es:[NHB*3]+BANKSZ(POS), ax
#endif
	pop	bx
	pop	es
	pop	ds
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, $MSR		/ enable video display
	movb	al, $0x1A
	outb	dx, al
	mov	mmvcnt_, $480		/ 480 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx			/ Return the residual count.
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $CLOWER		/ schedule keyboard initialization
	mov	dx, $MSR		/ disable video display
	movb	al, $0x12
	outb	dx, al

	push	cx			/ program registers, last to first
	mov	bx, $15
	mov	dx, MM_PORT(bp)
0:	movb	al, bl
	outb	dx, al
	inc	dx
	movb	al, cs:crtdata(bx)
	outb	dx, al
	dec	dx
	dec	bx
	jge	0b
	pop	cx

	mov	dx, $CSR
	movb	al, $0x0F
	outb	dx, al

	mov	dx, $XMSR
#ifdef TECMAR
	movb	al, $31
#else
	movb	al, $0
#endif
	outb	dx, al

/	mov	dx, $XMSR
0:	inb	al, dx		/ wait for vertical retrace
	andb	al, $8
	je	0b

	mov	dx, $MSR
	movb	al, $0x1A	/ video display on
	outb	dx, al

	mov	MM_VIS(bp), $-1
	mov	MM_MASK(bp), $0xAAAA
	mov	MM_FLIP(bp), $0
	mov	MM_ULINE(bp), $0
	mov	MM_CURSE(bp), $0x00ff
	movb	MM_WRAP(bp), $1
	movb	MM_NCOL(bp), $80
	subb	COL, COL
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mmspec - pass special characters on to keyboard routine(s).
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/	Returns to mmwrite() to allow flow control on each output line.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jle	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	push	si
	push	di
	push	cx
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	pop	di
	push	di
	mov	cx, $NRB4
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	jmp	ewait

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, ROW			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	bl, $1
0:	add	POS, bx
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait0
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

ewait0:	call	exit
	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	cmpb	MM_NCOL(bp), $40
	jne	putc8


putc16:	push	ds
	push	si
	subb	ah, ah
	shlb	al, $1
	shl	ax, $1
	shl	ax, $1
	shl	ax, $1
	add	ax, $fontw_
	mov	si, ax
	mov	ax, cs
	mov	ds, ax
	mov	bx, $BANKSZ-2

	lodsw				/ row 0
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
	push	di			/ save position for next char
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif
	lodsw				/ row 1
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 2
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif

	lodsw				/ row 3
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 4
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif

	lodsw				/ row 5
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 6
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif
	lodsw				/ row 7
	or	ax, MM_ULINE(bp)
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax


	pop	di			/ restore position for next char
	pop	si
	pop	ds

	sub	bx, bx
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jge	0f
	jcxz	ewait1
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

ewait1:	jmp	ewait

putc8:	push	ds
	push	si
	subb	ah, ah
	shlb	al, $1
	shl	ax, $1
	shl	ax, $1
	add	ax, $0xFA6E
	mov	si, ax
	mov	ax, $0xF000
	mov	ds, ax
	mov	bx, $BANKSZ-1

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 0
	push	di			/ save position for next char
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah		/ row 1
	movb	es:80(bx,di), ah
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 1
	add	di, $79
#endif

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 2
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah
	movb	es:80(bx,di), ah	/ row 3
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 3
	add	di, $79
#endif

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 4
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah		/ row 5
	movb	es:80(bx,di), ah
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 5
	add	di, $79
#endif

	lodsw
	orb	ah, MM_ULINE(bp)
	xor	ax, MM_FLIP(bp)
	stosb				/ row 6
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah
	movb	es:80(bx,di), ah
#else
	movb	es:(bx,di), ah		/ row 7
#endif

	pop	di			/ restore position for next char
	pop	si
	pop	ds

	sub	bx, bx
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jge	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	decb	COL
	jge	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
0:	jmp	repos

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $SEMIC
	je	csi_n2
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

0:	cmpb	al, $HLOWER
	je	mm_cgh
	cmpb	al, $LLOWER
	je	mm_cgl
	jmp	eval

////////
/
/ Csi_q state - entered after input sequence ESC [ ?
/	
////////

0:	call	exit
csi_q:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_q

0:	cmpb	al, $HLOWER
	je	mm_cqh
	cmpb	al, $LLOWER
	je	mm_cql
	jmp	eval

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jg	0f
	subb	COL, COL		/ cannot step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process ESC [ > N1 h escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process ESC [ > N1 l escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	decb	COL
	jge	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	mov	bx, $BANKSZ
	push	cx
	push	si
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl

	mov	si, MM_MASK(bp)
	cmpb	MM_NCOL(bp), $80
	jne	0f
	mov	si, $-1
	inc	cx
	shr	cx, $1

0:	mov	ax, MM_FLIP(bp)
	and	ax, si
#ifdef TECMAR
	stosw				/ row 0
	mov	es:[NHB*0]-2(di,bx), ax
	mov	es:[NHB*1]-2(di), ax	/ row 1
	mov	es:[NHB*1]-2(di,bx), ax
	mov	es:[NHB*2]-2(di), ax	/ row 2
	mov	es:[NHB*2]-2(di,bx), ax
	mov	es:[NHB*3]-2(di), ax	/ row 3
	mov	es:[NHB*3]-2(di,bx), ax
	mov	es:[NHB*4]-2(di), ax	/ row 4
	mov	es:[NHB*4]-2(di,bx), ax
	mov	es:[NHB*5]-2(di), ax	/ row 5
	mov	es:[NHB*5]-2(di,bx), ax
	mov	es:[NHB*6]-2(di), ax	/ row 6
	mov	es:[NHB*6]-2(di,bx), ax
	or	ax, MM_ULINE(bp)
	and	ax, si
	mov	es:[NHB*7]-2(di), ax	/ row 7
	mov	es:[NHB*7]-2(di,bx), ax
#else
	stosw				/ row 0
	mov	es:[NHB*0]-2(di,bx), ax	/ row 1
	mov	es:[NHB*1]-2(di), ax	/ row 2
	mov	es:[NHB*1]-2(di,bx), ax	/ row 3
	mov	es:[NHB*2]-2(di), ax	/ row 4
	mov	es:[NHB*2]-2(di,bx), ax	/ row 5
	mov	es:[NHB*3]-2(di), ax	/ row 6
	or	ax, MM_ULINE(bp)
	and	ax, si
	mov	es:[NHB*3]-2(di,bx), ax	/ row 7
#endif
	loop	0b
	sub	bx, bx
	pop	si
	pop	cx
	cmpb	COL, MM_NCOL(bp)
	jl	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jle	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	repos

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cqh - process ESC [ ? N1 h escape sequence
/
/	Recognized sequences:	ESC [ ? 7 h	-- Set wraparound.
/
////////

mm_cqh:
	cmpb	MM_N1(bp), $7		/ Wraparound.
	jne	0f
	movb	MM_WRAP(bp), $1
0:	jmp	eval

////////
/
/ mm_cql - process ESC [ ? N1 l escape sequence
/
/	Recognized sequences:	ESC [ ? 7 l	-- Reset wraparound.
/
////////

mm_cql:
	cmpb	MM_N1(bp), $7		/ No wraparound.
	jne	0f
	movb	MM_WRAP(bp), $0
0:	jmp	eval

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter (mm_n1) specifies the vertical position (MM_ROW(bp)).
/	The second parameter (mm_n2) specifies the horizontal position (MM_COL(bp)).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	si
	push	di
	push	cx
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	di, cs:rowtab(bx)
	push	di
	mov	cx, $NRB4
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	subb	COL, COL
0:	pop	cx
	pop	si
	pop	ds
	jmp	repos

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2

////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

////////
/
/ mm_e2 - erase from POS for BL rows (minimum 1 row)
/
////////

mm_e2:	push	cx
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
0:	mov	cx, $NRB4
	rep
	stosw
	add	di, $BANKSZ-NRB2
	mov	cx, $NRB4
	rep
	stosw
	sub	di, $BANKSZ
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

////////
/
/ mm_e1 - erase from row BL to current cursor position.
/
////////

mm_e1:	push	dx
	push	cx
	push	di
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	di
	push	cx
	rep
	stosw
	pop	cx
	pop	di
	add	di, $BANKSZ
	rep
	stosw
0:	pop	cx
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	sub	cx, di
	jle	0f

	mov	dx, di
	mov	bx, cx
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 6
	stosb
#ifdef TECMAR
	add	dx, $80
	mov	di, dx
	mov	cx, bx
	rep			/ erase row 7
	stosb
	add	dx, $BANKSZ-560
#else
	add	dx, $BANKSZ-240
#endif
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 6
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 7
	stosb
1:	sub	bx, bx
	pop	cx
	pop	dx
	jmp	repos

////////
/
/ mm_e0 - erase from current cursor position to row BL inclusive.
/
////////

mm_e0:	push	dx
	push	cx
	push	di
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab+2(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	di
	push	cx
	rep
	stosw
	pop	cx
	pop	di
	add	di, $BANKSZ
	rep
	stosw
0:	pop	di
	sub	cx, cx
	movb	cl, MM_NCOL(bp)
	subb	cl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	cl, $1
0:	mov	dx, di
	mov	bx, cx
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 6
	stosb
#ifdef TECMAR
	add	dx, $80
	mov	di, dx
	mov	cx, bx
	rep			/ erase row 7
	stosb
	add	dx, $BANKSZ-560
#else
	add	dx, $BANKSZ-240
#endif
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 6
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 7
	stosb
1:	sub	bx, bx
	pop	cx
	pop	dx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, cs:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, cs:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, cs:rowtab(bx)
	jle	0f
	shr	cx, $1
	push	si
	push	di
	push	cx
	std
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	di, cs:rowtab(bx)
	push	di
	mov	cx, $NRB4
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	cld
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	subb	COL, COL
0:	pop	cx
	pop	si
	pop	ds
	jmp	repos

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_VIS(bp), $-1
	jmp	eval

0:	mov	MM_VIS(bp), $0
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					7 - reverse video
/
////////

mm_sgr:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	mov	MM_MASK(bp), $0xAAAA
	mov	MM_FLIP(bp), $0
	mov	MM_ULINE(bp), $0
	jmp	1f
0:	cmpb	al, $1		/ bold
	jne	0f
	mov	MM_MASK(bp), $-1
	jmp	1f
0:	cmpb	al, $4		/ underline
	jne	0f
	mov	MM_ULINE(bp), $0xFFFF
	jmp	1f
0:	cmpb	al, $7		/ reverse video
	jne	0f
	mov	MM_FLIP(bp), $-1
	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_so - stand out - enter 40 column mode
/
////////

mm_so:	cmpb	MM_NCOL(bp), $80
	jne	0f
	movb	MM_NCOL(bp), $40
	incb	COL
	shrb	COL, $1
0:	mov	MM_CURSE(bp), $0xffff
	jmp	repos

////////
/
/ mm_si - stand in - enter 80 column mode
/
////////

mm_si:	cmpb	MM_NCOL(bp), $40
	jne	0f
	movb	MM_NCOL(bp), $80
	shlb	COL, $1
0:	mov	MM_CURSE(bp), $0x00ff
	jmp	repos

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	mmbell	/* EOT  ENQ  ACK  BEL  */
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/* BS   HT   LF   VT  */
	.word	eval,	mm_cr,	mm_so,	mm_si	/* FF   CR   SO   SI  */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3 */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	mm_esc	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/*   ! " # \040 - \043 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* $ % & quote \044 - \047 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ( ) * + \050 - \053 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* , - . / \054 - \057 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 0 1 2 3 \060 - \063 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 4 5 6 7 \064 - \067 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 8 9 : ; \070 - \073 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* < = > ? \074 - \077 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* @@ A B C \100 - \103 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* D E F G \104 - \107 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* H I J K \110 - \113 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* L M N O \114 - \117 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* P Q R S \120 - \123 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* T U V W \124 - \127 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* X Y Z [ \130 - \133 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* \ ] ^ _ \134 - \137 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ` a b c \140 - \143 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* d e f g \144 - \147 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* h i j k \150 - \153 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* l m n o \154 - \157 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* p q r s \160 - \163 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* t u v w \164 - \167 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* x y z { \170 - \173 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* | } ~ ? \174 - \177 */

////////
/
/ esctab - table of functions indexed by escape characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/* NUL  SOH  STX  ETX  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* EOT  ENQ  ACK  BEL  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* BS   HT   LF   VT  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FF   CR   SO   SI  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DLE  DC1  DC2  DC3 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DC4  NAK  SYN  ETB  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* CAN  EM   SUB  ESC  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	mm_new	/* 4 5 6 7 \064 - \067 */
	.word	mm_old,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	mmspec,	mmspec,	eval	/* < = > ? \074 - \077 */
	.word	eval,	eval,	eval,	eval	/* @@ A B C \100 - \103 */
	.word	mm_ind,	mm_cnl,	eval,	eval	/* D E F G \104 - \107 */
	.word	eval,	eval,	eval,	eval	/* H I J K \110 - \113 */
	.word	eval,	mm_ri,	eval,	eval	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	eval	/* P Q R S \120 - \123 */
	.word	eval,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	eval,	csi_n1	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_dmi,	eval,	mm_emi,	mminit	/* ` a b c \140 - \143 */
	.word	eval,	eval,	eval,	eval	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	eval,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	eval,	eval	/* p q r s \160 - \163 */
	.word	mmspec,	mmspec,	eval,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	eval	/* EOT  ENQ  ACK  BEL  */
	.word	eval,	eval,	eval,	eval	/* BS   HT   LF   VT  */
	.word	eval,	eval,	eval,	eval	/* FF   CR   SO   SI  */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3 */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	eval	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	eval	/* 4 5 6 7 \064 - \067 */
	.word	eval,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	eval,	csi_gt,	eval	/* < = > ? \074 - \077 */
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/* @@ A B C \100 - \103 */
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/* D E F G \104 - \107 */
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/* H I J K \110 - \113 */
	.word	mm_il,	mm_dl,	eval,	mm_ea	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	mm_ind	/* P Q R S \120 - \123 */
	.word	mm_ri,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	mm_cbt,	eval	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_hpa,	mm_hpr,	eval,	eval	/* ` a b c \140 - \143 */
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	mm_sgr,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	mm_ssr,	eval	/* p q r s \160 - \163 */
	.word	eval,	eval,	mm_scr,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ rowtab - array of offsets to each row
/
////////

rowtab:	.word	 0*NRB2,	 1*NRB2,	 2*NRB2,	 3*NRB2
	.word	 4*NRB2,	 5*NRB2,	 6*NRB2,	 7*NRB2
	.word	 8*NRB2,	 9*NRB2,	10*NRB2,	11*NRB2
	.word	12*NRB2,	13*NRB2,	14*NRB2,	15*NRB2
	.word	16*NRB2,	17*NRB2,	18*NRB2,	19*NRB2
	.word	20*NRB2,	21*NRB2,	22*NRB2,	23*NRB2
	.word	24*NRB2,	25*NRB2,	26*NRB2,	27*NRB2
	.word	28*NRB2,	29*NRB2,	30*NRB2,	31*NRB2
	.word	32*NRB2,	33*NRB2,	34*NRB2,	35*NRB2
	.word	36*NRB2,	37*NRB2,	38*NRB2,	39*NRB2
	.word	40*NRB2,	41*NRB2,	42*NRB2,	43*NRB2
	.word	44*NRB2,	45*NRB2,	46*NRB2,	47*NRB2
	.word	48*NRB2,	49*NRB2,	50*NRB2,	51*NRB2

////////
/
/ grread( dev, iop ) - read graphics display memory
/
////////

grread_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	mov	bp, 10(bp)
	push	ds
	push	es
	cmp	IO_SEG(bp), $IOSYS
	je	0f
	mov	ax, uds_
	mov	es, ax
0:	mov	di, IO_BASE(bp)
	mov	ax, $VSEG
	mov	ds, ax

#ifndef TECMAR
	mov	ax, IO_SEEK(bp)
	add	ax, IO_IOC(bp)
	cmp	ax, $BANKSZ*2
	ja	done
#endif

	mov	ax, IO_SEEK(bp)
	sub	dx, dx
	mov	cx, $NHB
	div	cx
	mov	si, dx
	mov	bx, ax
	shr	ax, $1
	mul	cx
	mov	dx, si
	add	si, ax
	testb	bl, $1
	jne	read2

read1:	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	push	si
	rep
	movsb
	pop	si
read2:	add	si, $BANKSZ
	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	rep
	movsb
	sub	si, $BANKSZ
	sub	dx, dx
	jmp	read1

done:	pop	es
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ grwrite( dev, iop ) - write graphics display memory
/
////////

grwrite_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	mov	bp, 10(bp)
	push	ds
	push	es
	cmp	IO_SEG(bp), $IOSYS
	je	0f
	mov	ax, uds_
	mov	ds, ax
0:	mov	si, IO_BASE(bp)
	mov	ax, $VSEG
	mov	es, ax

#ifndef TECMAR
	mov	ax, IO_SEEK(bp)
	add	ax, IO_IOC(bp)
	cmp	ax, $BANKSZ*2
	ja	done
#endif

	mov	ax, IO_SEEK(bp)
	sub	dx, dx
	mov	cx, $NHB
	div	cx
	mov	di, dx
	mov	bx, ax
	shr	ax, $1
	mul	cx
	mov	dx, di
	add	di, ax
	testb	bl, $1
	jne	page2

page1:	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	push	di
	rep
	movsb
	pop	di
page2:	add	di, $BANKSZ
	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	rep
	movsb
	sub	di, $BANKSZ
	sub	dx, dx
	jmp	page1

////////
/
/ mm_voff()	-- Disable video display
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, $MSR
	movb	al, $0x12
	outb	dx, al
	ret

////////
/
/ mm_von()	-- Enable video display
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, $MSR		/ enable video display
	movb	al, $0x1A
	outb	dx, al
	mov	ss:mmvcnt_, $480	/ 480 seconds before video disabled
	ret
@
0707070064030114141004440000000000000000011777770507310710300005600000032530/newbits/kernel/USRSRC/i8086/drv/RCS/Mf.mwc,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    root:1.1; strict;
comment  @@;


1.1
date     91.07.24.11.44.31;  author root;  state Exp;
branches ;
next     ;


desc
@init ver prov by hal
@



1.1
log
@Initial revision
@
text
@# Makefile for AT specific Coherent drivers
# Environment variable USRSYS must be defined!  Try /usr/sys ...
# Environment variable KOBJ must be defined!  Try /usr/kobj ...

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

DEBUG=0

# Loadable driver directory
LDRV=$(USRSYS)/ldrv

ARCHIVES=$(USRSYS)/lib/aha154x.a \
	$(USRSYS)/lib/al.a \
	$(USRSYS)/lib/at.a \
	$(USRSYS)/lib/ati.a \
	$(USRSYS)/lib/fl.a \
	$(USRSYS)/lib/gkb.a \
	$(USRSYS)/lib/gr.a \
	$(USRSYS)/lib/hs.a \
	$(USRSYS)/lib/kb.a \
	$(USRSYS)/lib/lp.a \
	$(USRSYS)/lib/mm.a \
	$(USRSYS)/lib/ms.a \
	$(USRSYS)/lib/nkb.a \
	$(USRSYS)/lib/rm.a \
	$(USRSYS)/lib/rs.a \
	$(USRSYS)/lib/st.a \
	$(USRSYS)/lib/tn.a \

DRVOBJ=	$(KOBJ)/aha.o \
	$(KOBJ)/alx.o \
	$(KOBJ)/at.o \
	$(KOBJ)/atas.o \
	$(KOBJ)/bufq.o \
	$(KOBJ)/ms.o \
	$(KOBJ)/ati.o \
	$(KOBJ)/com1.o $(KOBJ)/com2.o \
	$(KOBJ)/fdisk.o \
	$(KOBJ)/fl.o \
	$(KOBJ)/fontw.o \
	$(KOBJ)/gr.o $(KOBJ)/gras.o \
	$(KOBJ)/hs.o \
	$(KOBJ)/nkb.o \
	$(KOBJ)/gkb.o \
	$(KOBJ)/kb.o \
	$(KOBJ)/mm.o \
	$(KOBJ)/lp.o \
	$(KOBJ)/mmas.o \
	$(KOBJ)/rm.o \
	$(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o \
	$(KOBJ)/scsi.o \
	$(KOBJ)/ss.o \
	$(KOBJ)/ssas.o \
	$(KOBJ)/st.o \
	$(KOBJ)/tn.o $(KOBJ)/tnas.o \

DRIVERS=$(LDRV)/aha154x \
	$(LDRV)/al0 \
	$(LDRV)/al1 \
	$(LDRV)/at \
	$(LDRV)/fl \
	$(LDRV)/gr \
	$(LDRV)/hs \
	$(LDRV)/lp \
	$(LDRV)/mm \
	$(LDRV)/ms \
	$(LDRV)/rm \
	$(LDRV)/ss \

install: $(ARCHIVES) $(DRIVERS)
	@@exec /bin/sync

all:	$(DRVOBJ)
	@@exec /bin/sync

$(USRSYS)/lib/aha154x.a: $(KOBJ)/scsi.o $(KOBJ)/aha.o $(KOBJ)/fdisk.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/al.a: $(KOBJ)/com1.o $(KOBJ)/com2.o $(KOBJ)/alx.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/at.a: $(KOBJ)/at.o $(KOBJ)/atas.o $(KOBJ)/fdisk.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/ati.a: $(KOBJ)/mm.o $(KOBJ)/ati.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/fl.a: $(KOBJ)/fl.o
	rm -f $(USRSYS)/lib/fl.a
	ar rc $(USRSYS)/lib/fl.a $(KOBJ)/fl.o
$(USRSYS)/lib/gkb.a: $(KOBJ)/gkb.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/gr.a: $(KOBJ)/mm.o $(KOBJ)/gr.o $(KOBJ)/gras.o \
				$(KOBJ)/fontw.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/hs.a: $(KOBJ)/hs.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/kb.a: $(KOBJ)/kb.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/lp.a: $(KOBJ)/lp.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/mm.a: $(KOBJ)/mm.o $(KOBJ)/mmas.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/ms.a: $(KOBJ)/ms.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/nkb.a: $(KOBJ)/nkb.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/rm.a: $(KOBJ)/rm.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/rs.a: $(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/ss.a: $(KOBJ)/ss.o $(KOBJ)/ssas.o $(KOBJ)/bufq.o $(KOBJ)/fdisk.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/st.a: $(KOBJ)/st.o
	rm -f $@@
	ar rc $@@ $<
$(USRSYS)/lib/tn.a: $(KOBJ)/tn.o $(KOBJ)/tnas.o
	rm -f $@@
	ar rc $@@ $<

$(KOBJ)/aha.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/buf.h		\
		$(SYSINC)/sched.h		\
		$(SYSINC)/scsiwork.h	\
		$(SYSINC)/aha154x.h	\
		aha.c
	$(CC) $(CFLAGS) -c -o $@@ aha.c

$(KOBJ)/alx.o:				\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		alx.c
	$(CC) $(CFLAGS) -c -o $@@ alx.c

$(KOBJ)/at.o: at.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h
	$(CC) $(CFLAGS) -DVERBOSE=1 -c -o $@@ at.c

$(KOBJ)/atas.o: atas.s
	$(AS) -go $@@ $<

$(KOBJ)/ati.o: ati.m
	$(CC) $(CFLAGS) -DATI_132=1 -c -o $@@ ati.m

$(KOBJ)/bufq.o:			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/buf.h		\
		bufq.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o $@@ bufq.c

$(KOBJ)/com1.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM1=1 -c -o $@@ al.c

$(KOBJ)/com2.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM2=1 -c -o $@@ al.c

$(KOBJ)/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@@ fdisk.c

$(KOBJ)/fl.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdioctl.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		fl.c
	$(CC) $(CFLAGS) -c -o $@@ fl.c

$(KOBJ)/fontw.o: tools/fontgen.c
	$(CC) -o tools/fontgen tools/fontgen.c
	exec tools/fontgen > fontw.s
	exec /bin/rm tools/fontgen
	$(AS) -gxo $(KOBJ)/fontw.o fontw.s
	exec /bin/rm fontw.s

$(KOBJ)/gr.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		gr.c
	$(CC) $(CFLAGS) -c -o $@@ gr.c

$(KOBJ)/gras.o: gras.m
	$(CC) $(CFLAGS) -c -o $@@ gras.m

$(KOBJ)/hgas.o: gras.s
	$(CC) $(CFLAGS) -c -o $@@ -DHERCULES gras.m

$(KOBJ)/hd.o: hd.c
	$(CC) $(CFLAGS) -c -o $@@ hd.c

$(KOBJ)/hs.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		hs.c
	$(CC) $(CFLAGS) -c -o $@@ hs.c

$(KOBJ)/kb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		kb.c
	$(CC) $(CFLAGS) -c -o $@@ kb.c

$(KOBJ)/gkb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		gkb.c
	$(CC) $(CFLAGS) -c -o $@@ gkb.c

$(KOBJ)/nkb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/kb.h		\
		nkb.c
	$(CC) $(CFLAGS) -c -o $@@ nkb.c

$(KOBJ)/lp.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		lp.c
	$(CC) $(CFLAGS) -c -o $@@ lp.c

$(KOBJ)/mm.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/sched.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/timeout.h	\
		mm.c
	$(CC) $(CFLAGS) -c -o $@@ mm.c

$(KOBJ)/mmas.o: mmas.m
	$(CC) $(CFLAGS) -c -o $@@ mmas.m

$(KOBJ)/ms.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/ms.h		\
		$(USRINC)/errno.h	\
		ms.c
	$(CC) $(CFLAGS) -c -o $@@ ms.c

$(KOBJ)/rm.o: rm.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/buf.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/stat.h
	$(CC) $(CFLAGS) -c -o $@@ rm.c

$(KOBJ)/rs0.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS0 -c -o $@@ rs.c

$(KOBJ)/rs1.o: 				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS1 -c -o $@@ rs.c

$(KOBJ)/rsas.o: rsas.s
	$(AS) -gxo $@@ rsas.s

$(KOBJ)/scsi.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/sdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/scsiwork.h	\
		scsi.c
	$(CC) $(CFLAGS) -c -o $(KOBJ)/scsi.o scsi.c

$(KOBJ)/ss.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/io.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/proc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ss.h		\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/scsiwork.h	\
		ss.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o $(KOBJ)/ss.o ss.c

$(KOBJ)/ssas.o:				\
		ssas.s
	$(AS) -go $@@ $<

$(KOBJ)/st.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/const.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/mtioctl.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		st.c
	$(CC) $(CFLAGS) -c -o $@@ st.c

$(KOBJ)/tn.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		tn.c
	$(CC) $(CFLAGS) -c -o $@@ tn.c

$(KOBJ)/tnas.o: tnas.s
	$(AS) -gxo $@@ tnas.s

# How to make loadable drivers.

$(LDRV)/aha154x:	$(USRSYS)/lib/aha154x.a
	( cd $(USRSYS); ldconfig aha154x )

$(LDRV)/al0:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al0 )

$(LDRV)/al1:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al1 )

$(LDRV)/at:	$(USRSYS)/lib/at.a
	( cd $(USRSYS); ldconfig at )

$(LDRV)/fl:	$(USRSYS)/lib/fl.a
	( cd $(USRSYS); ldconfig fl )

$(LDRV)/gr:	$(USRSYS)/lib/gr.a
	( cd $(USRSYS); ldconfig gr )

$(LDRV)/hs:	$(USRSYS)/lib/hs.a
	( cd $(USRSYS); ldconfig hs )

$(LDRV)/lp:	$(USRSYS)/lib/lp.a
	( cd $(USRSYS); ldconfig lp )

$(LDRV)/mm:	$(USRSYS)/lib/mm.a
	( cd $(USRSYS); ldconfig mm )

$(LDRV)/ms:	$(USRSYS)/lib/ms.a
	( cd $(USRSYS); ldconfig ms )

$(LDRV)/rm:	$(USRSYS)/lib/rm.a
	( cd $(USRSYS); ldconfig rm )

$(LDRV)/ss:	$(USRSYS)/lib/ss.a
	( cd $(USRSYS); ldconfig ss )
@
0707070064030141331006440000030000030000011777770507310710600005200000012516/newbits/kernel/USRSRC/i8086/drv/kbmain.c/*
 * driver routine for loadable keyboard tables.
 *
 * prior to firing off the ioctl() which loads the new keyboard tables,
 * permform some simple validity checks on the table.
 * if errors are found, bail out without setting the new table.
 *
 * Version 1.0, 6/8/91
 */
#include <stdio.h>
#include <sgtty.h>
#include <sys/kb.h>
#include <sys/kbscan.h>
#include <errno.h>

#define	VERSION	"1.0"
#define	FALSE	(0 != 0)
#define	TRUE	(0 == 0)

/*
 * globals
 */
char	*argv0;				/* name of this executable */
int	errors;				/* for exit status */
char	verbose;			/* step-by-step details */
char	debug;				/* print out cooked table & exit */
KBTBL	table[MAX_KEYS];		/* cooked table for ioctl() */
FNKEY	*arena;				/* function key arena */

unsigned char	keyval[] = {		/* code set 3 mapped value */
none, K_1, K_2, K_3, K_4, K_5, K_6, K_7,
K_8, K_9, K_10, K_11, K_12, K_13, none, K_15,
K_16, K_17, K_18, K_19, K_20, K_21, K_22, K_23,
K_24, K_25, K_26, K_27, K_28, K_29, K_30, K_31,
K_32, K_33, K_34, K_35, K_36, K_37, K_38, K_39,
K_40, K_41, K_42, K_43, K_44, K_45, K_46, K_47,
K_48, K_49, K_50, K_51, K_52, K_53, K_54, K_55,
none, K_57, K_58, none, K_60, K_61, K_62, none,
K_64, none, none, none, none, none, none, none,
none, none, none, K_75, K_76, none, none, K_79,
K_80, K_81, none, K_83, K_84, K_85, K_86, none,
none, K_89, K_90, K_91, K_92, K_93, none, K_95,
K_96, K_97, K_98, K_99, K_100, K_101, K_102, K_103,
K_104, K_105, K_106, none, K_108, none, K_110, none,
K_112, K_113, K_114, K_115, K_116, K_117, K_118, K_119,
K_120, K_121, K_122, K_123, K_124, K_125, K_126
};

/*
 * externs from user-defined keyboard table
 */
extern	KBTBL	kbtbl[];			/* actual table */
extern	char	tbl_name[];			/* name of table as text */
extern	unsigned char *funkey[];		/* function key definitions */
extern	int	numfun;				/* # of function keys in tbl */
extern	int	numkey;				/* number of keys in kbtbl[] */

main(argc, argv)
char *argv[];
{
	unsigned char *cp, *ncp;
	int i, j;
	int fd;					/* console file descriptor */

	argv0 = argv[0];
	if ((arena = (FNKEY *)malloc(sizeof(FNKEY) + MAX_FCHAR)) == NULL) {
		err("out of memory");
		exit(errors);
	}
	if (argc > 1) {
		if (strcmp(argv[1], "-V") == 0)
			printf("Version %s\n", VERSION);
		else if (strcmp(argv[1], "-D") == 0)
			++debug;
		else
			usage();
	}

	if ((fd = open("/dev/console", 2)) < 0) {
		err("unable to access console");
		exit(errors);
	}

	/*
	 * loop through the user's keyboard table validating each entry.
	 * if the entry is good, copy it to the destination table.
	 */
	for (i = 0; i < numkey; ++i) {		/* loop thru user's keys */
		if (ok_entry(i)) {
			j = kbtbl[i].k_key;		/* map key */
			table[j] = kbtbl[i];		/* copy entry */
		} else
			++errors;
	}

	if (errors)
		exit(errors);
	/*
	 * build a function key arena consisting of the user defined
	 * special and function keys.
	 */
	ncp = arena->k_fnval;
	for (i = 0; i < numfun; ++i) {
		cp = funkey[i];
		do {
			if (ncp >= &arena->k_fnval[MAX_FCHAR]) {
				err("function key table overflow");
				exit(errors);
			}
			*ncp++ = *cp;
		} while (*cp++ != DELIM);
	}
	arena->k_nfkeys = numfun;

	if (debug) {
		dump();				/* print out cooked table */
		exit(0);
	}

	/*
	 * load the cooked keyboard table into the driver via a
	 * special ioctl() call.
	 */
	ioctl(fd, TIOCSETKBT, table);
	if (errno) {
		perror("keyboard table ioctl() failed");
		exit(++errors);
	}

	/*
	 * load the cooked function key table into the driver via a
	 * special ioctl() call.
	 */
	ioctl(fd, TIOCSETF, arena);
	if (errno) {
		perror("function key ioctl() failed");
		exit(++errors);
	}

	printf("Loaded %s\n", tbl_name);
	close(fd);
	exit(errors);
}

/*
 * validate a table entry
 */
ok_entry(n)
register int n;
{
	int i;
	int key = lookup(kbtbl[n].k_key);

	if (!key) {
		err("invalid key #0x%x in kbtbl[%d]", kbtbl[n].k_key, n);
		return FALSE;
	}
	if ((kbtbl[n].k_flags & (S|F)) == (S|F)) {
		err("invalid flag field for key K_%d", key);
		return FALSE;
	}
	if (kbtbl[n].k_flags & S) {
		for (i = BASE; i <= ALT_GR; ++i) {
			if (kbtbl[n].k_val[i] != kbtbl[n].k_val[BASE]) {
				err("inconsistent shift key entry for K_%d",
				    key);
				return FALSE;
			}
			if (kbtbl[n].k_val[i] < scroll
			   || kbtbl[n].k_val[i] > altgr) {
				err("bad shift key entry for K_%d",
				    key);
				return FALSE;
			}
		} /* for */
	} else if (kbtbl[n].k_flags & F) {
		for (i = BASE; i <= ALT_GR; ++i) {
			if (kbtbl[n].k_val[i] != none)
				if (kbtbl[n].k_val[i] >= numfun) {
					err("bad function key entry for K_%d",
					    key);
					return FALSE;
				}
		} /* for */
	} /* flag key */

	key = kbtbl[n].k_key;
	if (table[key].k_key != 0) {
		err("multiple entries for K_%d", key);
		return FALSE;
	}
	return TRUE;
}

/*
 * lookup the physical key number associated with a given
 * code set 3 scan code.
 *
 * return 0 if not found.
 */
lookup(sc)
unsigned sc;
{
	register int i;

	if (sc == none)
		return 0;
	for (i = 0; i < sizeof(keyval)/sizeof(keyval[0]); ++i)
		if (keyval[i] == (unsigned char)sc)
			return (i);
	return 0;
}

usage()
{
	fprintf(stderr, "usage:\t%s [-V]\n", argv0);
	exit(1);
}

err(msg)
char *msg;
{
	fprintf(stderr, "%s: ERROR: %r\n", argv0, &msg);
	++errors;
}

/*
 * dump the cooked keyboard table to stdout
 */
dump()
{
	int i, j;

	for (i = 0; i < MAX_KEYS; ++i) {
		printf("%02x: %02x ", i, table[i].k_key);
		for (j = 0; j < 9; ++j)
			printf("%02x ", table[i].k_val[j]);
		printf("(%02x)\n", table[i].k_flags);
	}
}
0707070064030143450407550000000000000000011777770507310711000005100000000000/newbits/kernel/USRSRC/i8086/drv/objects0707070064030107500407550000030000030000011777770507310711000004700000000000/newbits/kernel/USRSRC/i8086/drv/tools0707070064030112621004440000030000030000011777770507310711000006100000003706/newbits/kernel/USRSRC/i8086/drv/tools/fontgen.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * fontgen - generate 16x8 font assembler source on stdout.
 */

#define	BIT(n)	(1 << (n))
#define	BITS(n)	(((n) >= 4) ? (3 << (((n) - 4) * 2)) : (3 << (((n) + 4) * 2)))

unsigned char ibuf[1024];
unsigned char odef[] = "\tB________ = 0000000\n";
unsigned char obuf[] = "\t.word\tB________\n";

main()
{
	register unsigned s;
	register unsigned j;
	register unsigned i;
	extern long lseek();

	/*
	 * Read fonts from /dev/mem at offset 0xFFA6E.
	 */
	close(0);
	if (open("/dev/mem", 0) != 0)
		fatal("/dev/mem: can't open\n");
	if (lseek( 0, 0xFFA6EL, 0) != 0xFFA6EL)
		fatal("/dev/mem: can't seek to fonts");
	if (read( 0, ibuf, sizeof ibuf ) != sizeof ibuf)
		fatal("/dev/mem: can't read fonts");

	/*
	 * Define symbolic constants.
	 */
	for (i=0; i < 256; ++i) {
		/* Generate constant's name. */
		s = i;
		for (j=10; --j >= 2; s>>=1)
			odef[j] = (s&1) ? 'X' : '_';

		/* Convert 8 pixel width to 16 pixels */
		s = 0;
		for (j=0; j < 8; ++j)
			if (i & BIT(j))
				s |= BITS(j);

		/* Generate constant's value */
		for (j=19; j >= 14; --j) {
			odef[j] = (s & 7) + '0';
			s >>= 3;
		}

		/* Print constant's name and value */
		send( odef );
	}
	send( "\n\t.globl\tfontw_\nfontw_:" );

	/*
	 * Define fonts for 128 characters.
	 */
	for (i=0; i < sizeof ibuf; ++i) {

		/* Format and print one pixel line */
		j = 16;
		s = ibuf[i];
		while ( --j >= 8 ) {
			obuf[j] = (s&1) ? 'X' : '_' ;
			s >>= 1;
		}
		send( obuf );

		/* Insert blank line between characters for readability */
		if ( (i & 7) == 7 )
			send( "\n" );
	}
	exit( 0 );
}

/*
 * Fatal( msg ) - report error, and abort.
 */

fatal( msg )
register char *msg;
{
	write( 2, msg, strlen(msg) );
	exit( 1 );
}

/*
 * send( s ) - write null-terminated string to standard output.
 */

send( s )
register char *s;
{
	write( 1, s, strlen(s) );
}
0707070064030127070407550000030000030000011777770507310711000005300000000000/newbits/kernel/USRSRC/i8086/drv/tools/RCS0707070064030046021004440000030000030000011777770507310711000006700000004266/newbits/kernel/USRSRC/i8086/drv/tools/RCS/fontgen.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @ * @;


1.1
date     91.07.02.09.23.11;  author bin;  state Exp;
branches ;
next     ;


desc
@init ver prov by hel
@



1.1
log
@Initial revision
@
text
@/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * fontgen - generate 16x8 font assembler source on stdout.
 */

#define	BIT(n)	(1 << (n))
#define	BITS(n)	(((n) >= 4) ? (3 << (((n) - 4) * 2)) : (3 << (((n) + 4) * 2)))

unsigned char ibuf[1024];
unsigned char odef[] = "\tB________ = 0000000\n";
unsigned char obuf[] = "\t.word\tB________\n";

main()
{
	register unsigned s;
	register unsigned j;
	register unsigned i;
	extern long lseek();

	/*
	 * Read fonts from /dev/mem at offset 0xFFA6E.
	 */
	close(0);
	if (open("/dev/mem", 0) != 0)
		fatal("/dev/mem: can't open\n");
	if (lseek( 0, 0xFFA6EL, 0) != 0xFFA6EL)
		fatal("/dev/mem: can't seek to fonts");
	if (read( 0, ibuf, sizeof ibuf ) != sizeof ibuf)
		fatal("/dev/mem: can't read fonts");

	/*
	 * Define symbolic constants.
	 */
	for (i=0; i < 256; ++i) {
		/* Generate constant's name. */
		s = i;
		for (j=10; --j >= 2; s>>=1)
			odef[j] = (s&1) ? 'X' : '_';

		/* Convert 8 pixel width to 16 pixels */
		s = 0;
		for (j=0; j < 8; ++j)
			if (i & BIT(j))
				s |= BITS(j);

		/* Generate constant's value */
		for (j=19; j >= 14; --j) {
			odef[j] = (s & 7) + '0';
			s >>= 3;
		}

		/* Print constant's name and value */
		send( odef );
	}
	send( "\n\t.globl\tfontw_\nfontw_:" );

	/*
	 * Define fonts for 128 characters.
	 */
	for (i=0; i < sizeof ibuf; ++i) {

		/* Format and print one pixel line */
		j = 16;
		s = ibuf[i];
		while ( --j >= 8 ) {
			obuf[j] = (s&1) ? 'X' : '_' ;
			s >>= 1;
		}
		send( obuf );

		/* Insert blank line between characters for readability */
		if ( (i & 7) == 7 )
			send( "\n" );
	}
	exit( 0 );
}

/*
 * Fatal( msg ) - report error, and abort.
 */

fatal( msg )
register char *msg;
{
	write( 2, msg, strlen(msg) );
	exit( 1 );
}

/*
 * send( s ) - write null-terminated string to standard output.
 */

send( s )
register char *s;
{
	write( 1, s, strlen(s) );
}
@
0707070064030112631006440000030000030000011777770507310711100005700000004521/newbits/kernel/USRSRC/i8086/drv/tools/parms.c/* parms.c - display hard drive parameters per "atparm" in kernel */

#include <stdio.h>
#include <l.out.h>

/*
 * For easy referencing.
 */
#define	at_table		nl[0].n_value
#define	plowner		nl[1].n_value
#define NDRIVE		2

struct dparm_s {
	unsigned short	d_ncyl;		/* number of cylinders */
	unsigned char	d_nhead;	/* number of heads */
	unsigned short	d_rwcc;		/* reduced write current cyl */
	unsigned short	d_wpcc;		/* write pre-compensation cyl */
	unsigned char	d_eccl;		/* max ecc data length */
	unsigned char	d_ctrl;		/* control byte */
	unsigned char	d_fill2[3];
	unsigned short	d_landc;	/* landing zone cylinder */
	unsigned char	d_nspt;		/* number of sectors per track */
	unsigned char	d_fill3;

}	atparm[ NDRIVE ] = {
	0				/* Initialized to allow patching */
};

/*
 * Table for namelist.
 */
struct nlist nl[] ={
	"atparm_",		0,	0,
	""
};

/*
 * Symbols.
 */
char	 *kfile;			/* Kernel data memory file */
char	 *nfile;			/* Namelist file */
int	 kfd;				/* Kernel memory file descriptor */

main(argc, argv)
char *argv[];
{
	register int i;
	register char *cp;

	initialise();
	for (i=1; i<argc; i++) {
		for (cp=&argv[i][0]; *cp; cp++) {
			switch (*cp) {
			case '-':
				continue;
			case 'c':
				if (++i >= argc)
					usage();
				nfile = argv[i];
				continue;
			default:
				usage();
			}
		}
	}
	execute();
	exit(0);
}

/*
 * Initialise.
 */
initialise()
{
	nfile = "/coherent";
	kfile = "/dev/kmem";
}

/*
 * Print out usage.
 */
usage()
{
	panic("Usage: parms [-][c kernel_file]");
}

/*
 * Display parameters
 */
execute()
{
	int dr;

	nlist(nfile, nl);
	if (nl[0].n_type == 0)
		panic("Bad namelist file %s", nfile);
	if ((kfd = open(kfile, 0)) < 0)
		panic("Cannot open %s", kfile);

	kread((long)at_table, atparm, sizeof(atparm));
	printf("Hard drive parameters as stored in \"at\" driver:\n");
	for (dr = 0;  dr < NDRIVE;  dr++) {
		printf("drive %d  cyl=%4d  hd=%2d  spt=%2d  ctrl=%02x\n",
			dr, atparm[dr].d_ncyl, atparm[dr].d_nhead,
			atparm[dr].d_nspt, atparm[dr].d_ctrl);
	}
}

/*
 * Read `n' bytes into the buffer `bp' from kernel memory
 * starting at seek position `s'.
 */
kread(s, bp, n)
long s;
{
	lseek(kfd, (long)s, 0);
	if (read(kfd, bp, n) != n)
		panic("Kernel memory read error");
}

/*
 * Print out an error message and exit.
 */
panic(a1)
char *a1;
{
	fflush(stdout);
	fprintf(stderr, "%r", &a1);
	fprintf(stderr, "\n");
	exit(1);
}
0707070064030112641004440000030000030000011777770507310711100005700000003746/newbits/kernel/USRSRC/i8086/drv/tools/prate.c/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * prate.c - display polling rate of com[1-4] drivers
 */

#include <stdio.h>
#include <l.out.h>
#include <poll_clk.h>

/*
 * For easy referencing.
 */
#define	plrate		nl[0].n_value
#define	plowner		nl[1].n_value

/*
 * Table for namelist.
 */
struct nlist nl[] ={
	"poll_rate_",		0,	0,
	"poll_owner_",		0,	0,
	""
};

/*
 * Symbols.
 */
char	 *kfile;			/* Kernel data memory file */
char	 *nfile;			/* Namelist file */
int	 kfd;				/* Kernel memory file descriptor */

main(argc, argv)
char *argv[];
{
	register int i;
	register char *cp;

	initialise();
	for (i=1; i<argc; i++) {
		for (cp=&argv[i][0]; *cp; cp++) {
			switch (*cp) {
			case '-':
				continue;
			case 'c':
				if (++i >= argc)
					usage();
				nfile = argv[i];
				continue;
			default:
				usage();
			}
		}
	}
	execute();
	exit(0);
}

/*
 * Initialise.
 */
initialise()
{
	nfile = "/coherent";
	kfile = "/dev/kmem";
}

/*
 * Print out usage.
 */
usage()
{
	panic("Usage: prate [-][c kernel_file]");
}

/*
 * Display polling rate
 */
execute()
{
	int rate, owner;

	nlist(nfile, nl);
	if (nl[0].n_type == 0)
		panic("Bad namelist file %s", nfile);
	if ((kfd = open(kfile, 0)) < 0)
		panic("Cannot open %s", kfile);

	kread((long)plrate, &rate, sizeof(rate));
	kread((long)plowner, &owner, sizeof(owner));
	if (rate) {
		if (owner & POLL_AL)
			printf("al driver is ");
		else if (owner & POLL_HS)
			printf("hs driver is ");
		printf("polling at %d Hz\n", rate);
	} else
		printf("polling is OFF\n");
}

/*
 * Read `n' bytes into the buffer `bp' from kernel memory
 * starting at seek position `s'.
 */
kread(s, bp, n)
long s;
{
	lseek(kfd, (long)s, 0);
	if (read(kfd, bp, n) != n)
		panic("Kernel memory read error");
}

/*
 * Print out an error message and exit.
 */
panic(a1)
char *a1;
{
	fflush(stdout);
	fprintf(stderr, "%r", &a1);
	fprintf(stderr, "\n");
	exit(1);
}
0707070064030107730407550000030000030000011777770507310711200004700000000000/newbits/kernel/USRSRC/i8086/drv/stuff0707070064030050661006440000030000030000011777770507310711200004700000046137/newbits/kernel/USRSRC/i8086/drv/gkb.c/*
 * Keyboard/display driver for German keyboard.
 * Coherent, IBM PC/XT and AT (in XT mode).
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <signal.h>
#include <sys/sched.h>

#define	ISMAJ	2			/* Keyboard major device */

#define	SPC	0376			/* Special encoding */
#define XXX	0377			/* Non-character */
#define	KBDATA	0x60			/* Keyboard data */
#define	KBCTRL	0x61			/* Keyboard control */
#define	KBFLAG	0x80			/* Keyboard reset flag */
#define	LEDCMD	0xED			/* status indicator command */
#define	KBACK	0xFA			/* status indicator acknowledge */
#define	EXTENDED0 0xE0			/* extended key seq initiator */
#define	EXTENDED1 0xE1			/* extended key seq initiator */

#define	KEYUP	0x80			/* Key up change */
#define	KEYSC	0x7F			/* Key scan code mask */
#define	LSHIFT	0x2A-1			/* Left shift key */
#define LSHIFTA 0x2B-1			/* Alternate left-shift key */
#define	RSHIFT	0x36-1			/* Right shift key */
#define	CTRL	0x1D-1			/* Control key */
/*-- #define	CAPLOCK	0x1D-1	--*/		/* Control key */
#define	ALT	0x38-1			/* ALT key or ALT GR */
#define	CAPLOCK	0x3A-1			/* Caps lock key */
/*-- #define	CTRL	0x3A-1	--*/		/* Caps lock key */
#define	NUMLOCK	0x45-1			/* Numeric lock key */
#define	DELETE	0x53-1			/* Del, as in CTRL-ALT-DEL */
#define BACKSP	0x0E-1			/* Back space */
#define SCRLOCK	0x46-1			/* Scroll lock */

/* Shift flags */
#define	SRS	0x01			/* Right shift key on */
#define	SLS	0x02			/* Left shift key on */
#define CTS	0x04			/* Ctrl key on */
#define ALS	0x08			/* Alt key on */
#define CPLS	0x10			/* Caps lock on */
#define NMLS	0x20			/* Num lock on */
#define AKPS	0x40			/* Alternate keypad shift */
#define SHFT	0x80			/* Shift key flag */
#define	AGS	0x100			/* Alt Graphics on */

/* Function key information */
#define	NFKEY	20			/* Number of settable functions */
#define	NFCHAR	150			/* Number of characters settable */
#define	NFBUF	(NFKEY*2+NFCHAR+1)	/* Size of buffer */

/*
 * Functions.
 */
int	isrint();
int	istime();
void	isbatch();
int	mmstart();
int	isopen();
int	isclose();
int	isread();
int	mmwrite();
int	isioctl();
void	mmwatch();
int	isload();
int	isuload();
int	ispoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON iscon ={
	DFCHR|DFPOL,			/* Flags */
	ISMAJ,				/* Major index */
	isopen,				/* Open */
	isclose,			/* Close */
	nulldev,			/* Block */
	isread,				/* Read */
	mmwrite,			/* Write */
	isioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	mmwatch,			/* Timeout */
	isload,				/* Load */
	isuload,			/* Unload */
	ispoll				/* Poll */
};

/*
 * Flag indicating turbo machine.
 */
int isturbo = 0;

/*
 * Terminal structure.
 */
TTY	istty = {
	{0}, {0}, 0, mmstart, NULL, 0, 0
};

/*
 * State variables.
 */
int		islock;			/* Keyboard locked flag */
int		isbusy;			/* Raw input conversion busy */
static	int	shift;			/* Overall shift state */
static	char	scroll;			/* Scroll lock state */
static  char	lshift = LSHIFT;	/* Left shift alternate state */
static	char	isfbuf[NFBUF];		/* Function key values */
static	char	*isfval[NFKEY];		/* Function key string pointers */
static	int	ledcmd;			/* LED update command flag */
static	char	extended;		/* extended key scan count */
static	char	extmode;		/* use extended mode for this key */
static	char	ext0seen;		/* 0xE0 prefix seen */

/*
 * Tables for converting key code to ASCII.
 * lmaptab specifies unshifted conversion,
 * umaptab specifies shifted conversion,
 * smaptab specifies the shift states which are active.
 * An entry of XXX says the key is dead.
 * An entry of SPC requires further processing.
 *
 * Key codes:
 *	ESC .. <- == 1 .. 14
 *	-> .. \n == 15 .. 28
 *	CTRL .. ` == 29 .. 41
 *	^Shift .. PrtSc == 42 .. 55
 * 	ALT .. CapsLock == 56 .. 58
 *	F1 .. F10 == 59 .. 68
 *	NumLock .. Del == 69 .. 83
 *	ISO, F11, F12 == 86 .. 88
 */
unsigned char agmaptab[] ={					/* Alt Gr */
	       XXX,  XXX,'\375','\374',XXX,  XXX,  XXX,		/* 1 - 7 */
	 '{',  '[',  ']',  '}', '\\',  XXX,  XXX,  XXX,		/* 8 - 15 */
	 '@',  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 16 - 23 */
	 XXX,  XXX,  XXX,  '~',  XXX,  XXX,  XXX,  XXX,		/* 24 - 31 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 32 - 39 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 40 - 47 */
	 XXX,  XXX,'\346', XXX,  XXX,  XXX,  XXX,  XXX,		/* 48 - 55 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 56 - 63 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 64 - 71 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  XXX,		/* 72 - 79 */
	 XXX,  XXX,  XXX,  XXX,  XXX,  XXX,  '|',  XXX,		/* 80 - 87 */
	 XXX							/* 88 */
};

static unsigned char lmaptab[] ={
	     '\33',  '1',  '2',  '3',  '4',  '5',  '6',		/* 1 - 7 */
	 '7',  '8',  '9',  '0','\341','\'', '\b', '\t',		/* 8 - 15 */
	 'q',  'w',  'e',  'r',  't',  'z',  'u',  'i',		/* 16 - 23 */
	 'o',  'p','\201', '+', '\r',  XXX,  'a',  's',		/* 24 - 31 */
	 'd',  'f',  'g',  'h',  'j',  'k',  'l','\224',	/* 32 - 39 */
	'\204','^',  XXX,  '#',  'y', 'x',  'c',  'v',		/* 40 - 47 */
	 'b',  'n',  'm',  ',',  '.',  SPC,  XXX,  SPC,		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC,  XXX,  XXX,  '<',  XXX,		/* 80 - 87 */
	 XXX							/* 88 */
};

static unsigned char umaptab[] ={
	     '\33',  '!',  '"','\025', '$',  '%',  '&',		/* 1 - 7 */
	 '/',  '(',  ')',  '=',  '?',  '`', '\b',  SPC,		/* 8 - 15 */
	 'Q',  'W',  'E',  'R',  'T',  'Z',  'U',  'I',		/* 16 - 23 */
	 'O',  'P','\232',  '*', '\r',  XXX,  'A',  'S',	/* 24 - 31 */
	 'D',  'F',  'G',  'H',  'J',  'K',  'L','\231',	/* 32 - 39 */
	'\216','\370',XXX,'\'',  'Y',  'X',  'C',  'V',		/* 40 - 47 */
	 'B',  'N',  'M',  ';',  ':',  SPC,  XXX,  SPC,		/* 48 - 55 */
	 XXX,  ' ',  XXX,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 56 - 63 */
	 SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,  SPC,		/* 64 - 71 */
	 SPC,  SPC,  '-',  SPC,  SPC,  SPC,  '+',  SPC,		/* 72 - 79 */
	 SPC,  SPC,  SPC,  SPC,  XXX,  XXX,  '>',  XXX,		/* 80 - 87 */
	 XXX							/* 88 */
};

#define SS0	0			/* No shift */
#define SS1	(SLS|SRS|CTS)		/* Shift, Ctrl */
#define SES	(SLS|SRS)		/* Shift */
#define LET	(SLS|SRS|CPLS|CTS)	/* Shift, Caps, Ctrl */
#define KEY	(SLS|SRS|NMLS|AKPS)	/* Shift, Num, Alt keypad */

static unsigned char smaptab[] ={
	       SS0,  SES,  SS1,  SES,  SES,  SES,  SS1,		/* 1 - 7 */
	 SES,  SES,  SES,  SES,  SS1,  SES,  CTS,  SES,		/* 8 - 15 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  LET,		/* 16 - 23 */
	 LET,  LET,  SS1,  SS1,  CTS, SHFT,  LET,  LET,		/* 24 - 31 */
	 LET,  LET,  LET,  LET,  LET,  LET,  LET,  SES,		/* 32 - 39 */
	 SES,  SS1, SHFT,  SS1,  LET,  LET,  LET,  LET,		/* 40 - 47 */
	 LET,  LET,  LET,  SES,  SES,  SES, SHFT,  SES,		/* 48 - 55 */
	SHFT,  SS1, SHFT,  SS0,  SS0,  SS0,  SS0,  SS0,		/* 56 - 63 */
	 SS0,  SS0,  SS0,  SS0,  SS0, SHFT,  KEY,  KEY,		/* 64 - 71 */
	 KEY,  KEY,  SS0,  KEY,  KEY,  KEY,  SS0,  KEY,		/* 72 - 79 */
	 KEY,  KEY,  KEY,  KEY,  SS0,  SS0,  SES,  SS0,		/* 80 - 87 */
	 SS0
};

/*
 * Load entry point.
 *  Do reset the keyboard because it gets terribly munged
 *  if you type during the boot.
 */
isload()
{
	register int i;

	/*
	 * Reset keyboard if NOT an XT turbo.
	 */
	if ( ! isturbo ) {
		outb(KBCTRL, 0x0C);		/* Clock low */
		for (i = 10582; --i >= 0; );	/* For 20ms */
		outb(KBCTRL, 0xCC);		/* Clock high */
		for (i = 0; --i != 0; )
			;
		i = inb(KBDATA);
		outb(KBCTRL, 0xCC);			/* Clear keyboard */
		outb(KBCTRL, 0x4D);			/* Enable keyboard */
	}

	/*
	 * Enable mmwatch() invocation every second.
	 */
	drvl[ISMAJ].d_time = 1;

	/*
	 * Seize keyboard interrupt.
	 */
	setivec(1, isrint);

	/*
	 * Initiailize video display.
	 */
	mmstart( &istty );
}

/*
 * Unload entry point.
 */
isuload()
{
	clrivec(1);
}

/*
 * Default function key strings (terminated by -1 [\377])
 */
static char *deffuncs[] = {
	"\33[1x\377",	/* F1 */
	"\33[2x\377",	/* F2 */
	"\33[3x\377",	/* F3 */
	"\33[4x\377", 	/* F4 */
	"\33[5x\377",	/* F5 */
	"\33[6x\377",	/* F6 */
	"\33[7x\377",	/* F7 */
	"\33[8x\377",	/* F8 */
	"\33[9x\377",	/* F9 */
	"\33[0x\377",	/* F10 - historical value */
	"\33[1y\377",	/* F11 */
	"\33[2y\377",	/* F12 */
	"\33[3y\377",	/* F13 */
	"\33[4y\377", 	/* F14 */
	"\33[5y\377",	/* F15 */
	"\33[6y\377",	/* F16 */
	"\33[7y\377",	/* F17 */
	"\33[8y\377",	/* F18 */
	"\33[9y\377",	/* F19 */
	"\33[0y\377"	/* F20 */
};

/*
 * Open routine.
 */
isopen(dev)
dev_t dev;
{
	register int s;

	if (minor(dev) != 0) {
		u.u_error = ENXIO;
		return;
	}
	if ((istty.t_flags&T_EXCL)!=0 && super()==0) {
		u.u_error = ENODEV;
		return;
	}
	ttsetgrp(&istty, dev);

	s = sphi();
	if (istty.t_open++ == 0)
	{  initkeys();	 /* init function keys */
	   istty.t_flags = T_CARR;  /* indicate "carrier" */
	   ttopen(&istty);
	}
	spl(s);
	updleds();			/* update keyboard status LEDS */
}

/* Init function keys */
initkeys()
{	register int i;
	register char *cp1, *cp2;

	for (i=0; i<NFKEY; i++)
	    isfval[i] = 0;	    /* clear function key buffer */
	cp2 = isfbuf;	      	    /* pointer to key buffer */   
	for (i=0; i<NFKEY; i++)
	{  isfval[i] = cp2;	    /* save pointer to key string */
	   cp1 = deffuncs[i];       /* get init string pointer */
	   while ((*cp2++ = *cp1++) != -1)  /* copy key data */
	     if (cp2 >= &isfbuf[NFBUF-3])   /* overflow? */
	        return;
	}
}

/*
 * Close a tty.
 */
isclose(dev)
{
	register int s;

	s = sphi();
	if (--istty.t_open == 0)
	{  	s = sphi();
		ttclose(&istty);
		spl(s);
	}
}

/*
 * Read routine.
 */
isread(dev, iop)
dev_t dev;
IO *iop;
{
	ttread(&istty, iop, 0);
	if (istty.t_oq.cq_cc)
		mmtime(&istty);
}

/*
 * Ioctl routine.
 */
isioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	register int s;

	switch(com) {
	case TIOCSETF:
	case TIOCGETF:
		isfunction(com, (char *)vec);
		return;
	case TIOCSHIFT:   /* switch left-SHIFT and "\" */
		lshift = LSHIFTA;    /* alternate values */
		lmaptab[41] = '\\';
		lmaptab[42] = XXX;
		umaptab[41] = '|';
		umaptab[42] = XXX;
		smaptab[41] = SS1;
		smaptab[42] = SHFT;
		return;
	case TIOCCSHIFT:  /* normal (default) left-SHIFT and "\" */
		lshift = LSHIFT;     /* normal values */
		lmaptab[41] = XXX;
		lmaptab[42] = '\\';
		umaptab[41] = XXX;
		umaptab[42] = '|';
		smaptab[41] = SHFT;
		smaptab[42] = SS1;
		return;
	}
	s = sphi();
	ttioctl(&istty, com, vec);
	spl(s);
}

/*
 * Set and receive the function keys.
 */
isfunction(c, v)
int c;
char *v;
{
	register char *cp;
	register int i;

	if (c == TIOCGETF) {
		for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++)
		    putubd(v++, *cp);
	} else {
		for (i=0; i<NFKEY; i++)		/* zap current settings */
			isfval[i] = 0;
		cp = isfbuf;			/* pointer to key buffer */
		for (i=0; i<NFKEY; i++) {
			isfval[i] = cp;	        /* save pointer to key string */
			while ((*cp++ = getubd(v++)) != -1)  /* copy key data */
				if (cp >= &isfbuf[NFBUF-3])  /* overflow? */
					return;
		}
	}
}


/*
 * Poll routine.
 */
ispoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll failure.
	 */
	if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) {

		if ( msec != 0 )
			pollopen( &istty.t_ipolls );

		/*
		 * Second look AFTER enabling monitor, avoiding interrupt race.
		 */
		if ( istty.t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}

	return ev;
}

/*
 * Receive interrupt.
 */
isrint()
{
	register int	c;
	register int	s;
	register int	r;
	int	savests;
	int	update_leds = 0;

	/*
	 * Schedule raw input handler if not already active.
	 */
	if ( isbusy == 0 ) {
		defer( isbatch, &istty );
		isbusy = 1;
	}

	/*
	 * Pull character from the data
	 * port. Pulse the KBFLAG in the control
	 * port to reset the data buffer.
	 */
	r = inb(KBDATA) & 0xFF;
	c = inb(KBCTRL);
	outb(KBCTRL, c|KBFLAG);
	outb(KBCTRL, c);
#if	0
	printf("kbd: %x %s\n", r&0x7F, (r&KEYUP) ? "up" : "down");
#endif
	if (ledcmd) {
		ledcmd = 0;
		if (r == KBACK) {		/* output to status LEDS */
			c = scroll & 1;
			if (shift & NMLS)
				c |= 2;
			if (shift & CPLS)
				c |= 4;
			outb(KBDATA, c);
		}
		return;
	}
	if (extended > 0) {			/* if multi-character seq, */
		--extended;			/* ... ignore this char */
		return;
	}

	switch (r) {
	case EXTENDED0:				/* 0xE0 prefix found */
		ext0seen = 1;
		return;
	case EXTENDED1:				/* ignore extended sequences */
		extended = 5;
		return;
	case 0xFF:				/* Overrun */
		return;
	}

	if (ext0seen) {
		ext0seen = 0;
		extmode = 1;
	} else 
		extmode = 0;

	c = (r & KEYSC) - 1;			/* bias to internal format */

	/*
	 * Check for reset.
	 */
	if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS))
		boot();

	/*
	 * Track "shift" keys.
	 */
	s = smaptab[c];
	if (s&SHFT) {
		if (r&KEYUP) {			/* "shift" released */
			if (c == RSHIFT)
				shift &= ~SRS;
			else if (c == lshift)
				shift &= ~SLS;
			else if (c == CTRL)
				shift &= ~CTS;
			else if (c == ALT)
				shift &= extmode ? ~AGS : ~ALS;
		} else {			/* "shift" pressed */
			if (c == lshift)
				shift |= SLS;
			else if (c == RSHIFT)
				shift |= SRS;
			else if (c == CTRL)
				shift |= CTS;
			else if (c == ALT)
				shift |= extmode ? AGS : ALS;
			else if (c == CAPLOCK) {
				shift ^= CPLS;	/* toggle cap lock */
				updleds();
			} else if (c == NUMLOCK) {
				shift ^= NMLS;	/* toggle num lock */
				updleds();
			}
		}
		return;
	}

	/*
	 * No other key up codes of interest.
	 */
	if (r&KEYUP)
		return;

	/*
	 * If the tty is not open the character is
	 * just tossed away.
	 */
	if (istty.t_open == 0)
		return;

	/*
	 * Map character, based on the
	 * current state of the shift, control, alt graphics,
	 * meta (ALT) and lock flags.
	 */
	if (shift & AGS)			/* Alt Graphics ? */
		c = agmaptab[c];
	else if (shift & CTS) {
		if (s == CTS)			/* Map Ctrl (BS | NL) */
			c = (c == BACKSP) ? 0x7F : 0x0A;  
		else if (s==SS1 || s==LET)	/* Normal Ctrl map */
			c = umaptab[c]&0x1F;	/* Clear bits 5-6 */
		else				
			return;			/* Ignore this char */
	} else if (s &= shift) {
		if (shift & SES) {		 /* if shift on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = lmaptab[c];  /* use unshifted */
			else
				c = umaptab[c];	 /* use shifted */
		} else {			 /* if shift not on */
			if (s & (CPLS|NMLS))     /* if caps/num lock */
				c = umaptab[c];	 /* use shifted */
			else
				c = lmaptab[c];	 /* use unshifted */
		}
	} else					 
		c = lmaptab[c];			 /* use unshifted */

	/*
	 * Act on character.
	 */
	if (c == XXX)				
		return;				 /* char to ignore */

	if (c != SPC) {			 /* not special char? */
		if (shift & ALS)	 /* ALT (meta bit)? */
			c |= 0x80;	 /* set meta */
		isin(c);		 /* send the char */
	} else
		update_leds += isspecial(r);	 /* special chars */
	if (update_leds) {
		savests = sphi();
		outb(KBDATA, LEDCMD);
		ledcmd = 1;
		spl(savests);
	}
}

/*
 * Handle special input sequences.
 * The character passed is the key number.
 *
 * The keypad is translated by the following table,
 * the first entry is the normal sequence, the second the shifted,
 * and the third the alternate keypad sequence.
 */
static char *keypad[][3] = {
	{ "\33[H",  "7", "\33?w" },	/* 71 */
	{ "\33[A",  "8", "\33?x" },	/* 72 */
	{ "\33[V",  "9", "\33?y" },	/* 73 */
	{ "\33[D",  "4", "\33?t" },	/* 75 */
	{ "\0337",  "5", "\33?u" },	/* 76 */
	{ "\33[C",  "6", "\33?v" },	/* 77 */
	{ "\33[24H","1", "\33?q" },	/* 79 */
	{ "\33[B",  "2", "\33?r" },	/* 80 */
	{ "\33[U",  "3", "\33?s" },	/* 81 */
	{ "\33[@",  "0", "\33?p" },	/* 82 */
	{ "\33[P", ".",  "\33?n" }	/* 83 */
};

isspecial(c)
int c;
{
	register char *cp;
	register int s;
	int	update_leds = 0;

	cp = 0;

	switch (c) {
	case 15:					/* cursor back tab */
		cp = "\033[Z";
		break;
	case 53:
		if (extmode)
			cp = "/";
		else if (shift & SES)
			cp = "_";
		else
			cp = "-";
		break;
	case 55:					/* ignore PrtScr */
		if (!extmode)
			cp = "*";
		break;
	case 59: case 60: case 61: case 62: case 63:	/* Function keys */
	case 64: case 65: case 66: case 67: case 68:
		/* offset to function string */
		if ( shift & ALS )
			cp = isfval[c-49];
		else
			cp = isfval[c-59];
		break;

	case 70:		/* Scroll Lock -- stop/start output */
	{
		static char cbuf[2];

		cp = &cbuf[0];  /* working buffer */
		if (!(istty.t_sgttyb.sg_flags&RAWIN)) {	/* not if in RAW mode */
			++update_leds;
			if (istty.t_flags & T_STOP) {	/* output stopped? */
			   cbuf[0] = istty.t_tchars.t_startc;  /* start it */
			   scroll = 0;
			} else {
			   cbuf[0] = istty.t_tchars.t_stopc;   /* stop output */
			   scroll = 1;
			}
		}
		break;
	}

	case 79:		/* 1/End */
	case 80:		/* 2/DOWN */
	case 81:		/* 3/PgDn */
	case 82:		/* 0/Ins */
	case 83:		/* ./Del */
		--c;		/* adjust code */
	case 75:		/* 4/LEFT */
	case 76:		/* 5 */
	case 77:		/* 6/RIGHT */
		--c;		/* adjust code */
	case 71:		/* 7/Home/Clear */
	case 72:		/* 8/UP */
	case 73:		/* 9/PgUp */
		s = 0;			/* start off with normal keypad */
		if (shift & NMLS)	/* num lock? */
			s = 1;		/* set shift pad */
		if (shift & SES)	/* shift? */
			s ^= 1;		/* toggle shift pad */
		if (shift & AKPS)	/* alternate pad? */
			s = 2;		/* set alternate pad */		
		if (extmode)		/* not from keypad? */
			s = 0;		/* force normal sequence */
		cp = keypad[c-71][s];   /* get keypad value */
		break;
	}
	if (cp)					/* send string */
		while ((*cp != 0) && (*cp != -1))
			isin( *cp++ & 0377 );
	return update_leds;
}

/**
 *
 * void
 * ismmfunc( c )	-- process keyboard related output escape sequences
 * char c;
 */
void
ismmfunc(c)
register int c;
{
	switch (c) {
	case 't':	/* Enter numlock */
		shift |= NMLS;
		updleds();			/* update LED status */
		break;
	case 'u':	/* Leave numlock */
		shift &= ~NMLS;
		updleds();			/* update LED status */
		break;
	case '=':	/* Enter alternate keypad */
		shift |= AKPS;
		break;
	case '>':	/* Exit alternate keypad */
		shift &= ~AKPS;
		break;
	case 'c':	/* Reset terminal */
		islock = 0;
		shift  = 0;
		initkeys();
		updleds();			/* update LED status */
		break;
	}
}

/**
 *
 * void
 * isin( c )	-- append character to raw input silo
 * char c;
 */
static
isin( c )
register int c;
{
	/*
	 * Cache received character.
	 */
	istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c;

	if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) )
		istty.t_rawin.si_ix = 0;
}

/**
 *
 * void
 * isbatch()	-- raw input conversion routine
 *
 *	Action:	Enable the video display.
 *		Canonize the raw input silo.
 *
 *	Notes:	isbatch() was scheduled as a deferred process by isrint().
 */
static void
isbatch( tp )
register TTY * tp;
{
	register int c;
	static int lastc;

	/*
	 * Ensure video display is enabled.
	 */
	mm_von();

	isbusy = 0;

	/*
	 * Process all cached characters.
	 */
	while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) {

		/*
		 * Get next cached char.
		 */
		c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ];

		if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 )
			tp->t_rawin.si_ox = 0;
		else
			tp->t_rawin.si_ox++;

		if ( (islock == 0) || ISINTR || ISQUIT ) {
			ttin( tp, c );
		}

		else if ( (c == 'b') && (lastc == '\033') ) {
			islock = 0;
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else if ( (c == 'c') && (lastc == '\033') ) {
			ttin( tp, lastc );
			ttin( tp, c );
		}

		else
			putchar('\007');

		lastc = c;
	}
}

/*
 * update the keyboard status LEDS
 */
updleds()
{
	int	s;

	s = sphi();
	outb(KBDATA, LEDCMD);
	ledcmd = 1;
	spl(s);
}

/*
 * unlock the scroll in case an interrupt character is received
 */
kbunscroll()
{
	scroll = 0;
	updleds();
}
0707070064030112151006440000000000000000011777770507310711600005000000032047/newbits/kernel/USRSRC/i8086/drv/Mf.mwc# Makefile for AT specific Coherent drivers
# Environment variable USRSYS must be defined!  Try /usr/sys ...
# Environment variable KOBJ must be defined!  Try /usr/kobj ...

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

DEBUG=0

# Loadable driver directory
LDRV=$(USRSYS)/ldrv

ARCHIVES=$(USRSYS)/lib/aha154x.a \
	$(USRSYS)/lib/al.a \
	$(USRSYS)/lib/at.a \
	$(USRSYS)/lib/ati.a \
	$(USRSYS)/lib/fl.a \
	$(USRSYS)/lib/gkb.a \
	$(USRSYS)/lib/gr.a \
	$(USRSYS)/lib/hs.a \
	$(USRSYS)/lib/kb.a \
	$(USRSYS)/lib/lp.a \
	$(USRSYS)/lib/mm.a \
	$(USRSYS)/lib/ms.a \
	$(USRSYS)/lib/nkb.a \
	$(USRSYS)/lib/rm.a \
	$(USRSYS)/lib/rs.a \
	$(USRSYS)/lib/st.a \
	$(USRSYS)/lib/tn.a \

DRVOBJ=	$(KOBJ)/aha.o \
	$(KOBJ)/alx.o \
	$(KOBJ)/at.o \
	$(KOBJ)/atas.o \
	$(KOBJ)/bufq.o \
	$(KOBJ)/ms.o \
	$(KOBJ)/ati.o \
	$(KOBJ)/com1.o $(KOBJ)/com2.o \
	$(KOBJ)/fdisk.o \
	$(KOBJ)/fl.o \
	$(KOBJ)/fontw.o \
	$(KOBJ)/gr.o $(KOBJ)/gras.o \
	$(KOBJ)/hs.o \
	$(KOBJ)/nkb.o \
	$(KOBJ)/gkb.o \
	$(KOBJ)/kb.o \
	$(KOBJ)/mm.o \
	$(KOBJ)/lp.o \
	$(KOBJ)/mmas.o \
	$(KOBJ)/rm.o \
	$(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o \
	$(KOBJ)/scsi.o \
	$(KOBJ)/ss.o \
	$(KOBJ)/ssas.o \
	$(KOBJ)/st.o \
	$(KOBJ)/tn.o $(KOBJ)/tnas.o \

DRIVERS=$(LDRV)/aha154x \
	$(LDRV)/al0 \
	$(LDRV)/al1 \
	$(LDRV)/at \
	$(LDRV)/fl \
	$(LDRV)/gr \
	$(LDRV)/hs \
	$(LDRV)/lp \
	$(LDRV)/mm \
	$(LDRV)/ms \
	$(LDRV)/rm \
	$(LDRV)/ss \

install: $(ARCHIVES) $(DRIVERS)
	@exec /bin/sync

all:	$(DRVOBJ)
	@exec /bin/sync

$(USRSYS)/lib/aha154x.a: $(KOBJ)/scsi.o $(KOBJ)/aha.o $(KOBJ)/fdisk.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/al.a: $(KOBJ)/com1.o $(KOBJ)/com2.o $(KOBJ)/alx.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/at.a: $(KOBJ)/at.o $(KOBJ)/atas.o $(KOBJ)/fdisk.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/ati.a: $(KOBJ)/mm.o $(KOBJ)/ati.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/fl.a: $(KOBJ)/fl.o
	rm -f $(USRSYS)/lib/fl.a
	ar rc $(USRSYS)/lib/fl.a $(KOBJ)/fl.o
$(USRSYS)/lib/gkb.a: $(KOBJ)/gkb.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/gr.a: $(KOBJ)/mm.o $(KOBJ)/gr.o $(KOBJ)/gras.o \
				$(KOBJ)/fontw.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/hs.a: $(KOBJ)/hs.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/kb.a: $(KOBJ)/kb.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/lp.a: $(KOBJ)/lp.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/mm.a: $(KOBJ)/mm.o $(KOBJ)/mmas.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/ms.a: $(KOBJ)/ms.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/nkb.a: $(KOBJ)/nkb.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/rm.a: $(KOBJ)/rm.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/rs.a: $(KOBJ)/rs0.o $(KOBJ)/rs1.o $(KOBJ)/rsas.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/ss.a: $(KOBJ)/ss.o $(KOBJ)/ssas.o $(KOBJ)/bufq.o $(KOBJ)/fdisk.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/st.a: $(KOBJ)/st.o
	rm -f $@
	ar rc $@ $<
$(USRSYS)/lib/tn.a: $(KOBJ)/tn.o $(KOBJ)/tnas.o
	rm -f $@
	ar rc $@ $<

$(KOBJ)/aha.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/buf.h		\
		$(SYSINC)/sched.h		\
		$(SYSINC)/scsiwork.h	\
		$(SYSINC)/aha154x.h	\
		aha.c
	$(CC) $(CFLAGS) -c -o $@ aha.c

$(KOBJ)/alx.o:				\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		alx.c
	$(CC) $(CFLAGS) -c -o $@ alx.c

$(KOBJ)/at.o: at.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h
	$(CC) $(CFLAGS) -DVERBOSE=1 -c -o $@ at.c

$(KOBJ)/atas.o: atas.s
	$(AS) -go $@ $<

$(KOBJ)/ati.o: ati.m
	$(CC) $(CFLAGS) -DATI_132=1 -c -o $@ ati.m

$(KOBJ)/bufq.o:			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/buf.h		\
		bufq.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o $@ bufq.c

$(KOBJ)/com1.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM1=1 -c -o $@ al.c

$(KOBJ)/com2.o: 			\
		$(SYSINC)/al.h		\
		$(SYSINC)/clist.h	\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		al.c
	$(CC) $(CFLAGS) -DALCOM2=1 -c -o $@ al.c

$(KOBJ)/fdisk.o:			\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/uproc.h	\
		fdisk.c
	$(CC) $(CFLAGS) -c -o $@ fdisk.c

$(KOBJ)/fl.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/dmac.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/fdioctl.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		fl.c
	$(CC) $(CFLAGS) -c -o $@ fl.c

$(KOBJ)/fontw.o: tools/fontgen.c
	$(CC) -o tools/fontgen tools/fontgen.c
	exec tools/fontgen > fontw.s
	exec /bin/rm tools/fontgen
	$(AS) -gxo $(KOBJ)/fontw.o fontw.s
	exec /bin/rm fontw.s

$(KOBJ)/gr.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		gr.c
	$(CC) $(CFLAGS) -c -o $@ gr.c

$(KOBJ)/gras.o: gras.m
	$(CC) $(CFLAGS) -c -o $@ gras.m

$(KOBJ)/hgas.o: gras.s
	$(CC) $(CFLAGS) -c -o $@ -DHERCULES gras.m

$(KOBJ)/hd.o: hd.c
	$(CC) $(CFLAGS) -c -o $@ hd.c

$(KOBJ)/hs.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		hs.c
	$(CC) $(CFLAGS) -c -o $@ hs.c

$(KOBJ)/kb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		kb.c
	$(CC) $(CFLAGS) -c -o $@ kb.c

$(KOBJ)/gkb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		gkb.c
	$(CC) $(CFLAGS) -c -o $@ gkb.c

$(KOBJ)/nkb.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(USRINC)/signal.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/kb.h		\
		nkb.c
	$(CC) $(CFLAGS) -c -o $@ nkb.c

$(KOBJ)/lp.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/i8086.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/stat.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/uproc.h	\
		lp.c
	$(CC) $(CFLAGS) -c -o $@ lp.c

$(KOBJ)/mm.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/sched.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/stat.h	\
		$(SYSINC)/io.h		\
		$(SYSINC)/tty.h		$(SYSINC)/ktty.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/timeout.h	\
		mm.c
	$(CC) $(CFLAGS) -c -o $@ mm.c

$(KOBJ)/mmas.o: mmas.m
	$(CC) $(CFLAGS) -c -o $@ mmas.m

$(KOBJ)/ms.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/uproc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/ms.h		\
		$(USRINC)/errno.h	\
		ms.c
	$(CC) $(CFLAGS) -c -o $@ ms.c

$(KOBJ)/rm.o: rm.c			\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/buf.h		\
		$(USRINC)/errno.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/stat.h
	$(CC) $(CFLAGS) -c -o $@ rm.c

$(KOBJ)/rs0.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS0 -c -o $@ rs.c

$(KOBJ)/rs1.o: 				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ins8250.h	\
		$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
		$(SYSINC)/sched.h	\
		$(SYSINC)/stat.h	\
		$(USRINC)/termio.h	\
		$(SYSINC)/uproc.h	\
		rs.c
	$(CC) $(CFLAGS) -DRS1 -c -o $@ rs.c

$(KOBJ)/rsas.o: rsas.s
	$(AS) -gxo $@ rsas.s

$(KOBJ)/scsi.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/sdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/scsiwork.h	\
		scsi.c
	$(CC) $(CFLAGS) -c -o $(KOBJ)/scsi.o scsi.c

$(KOBJ)/ss.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h $(SYSINC)/mmu.h \
		$(SYSINC)/io.h		\
		$(SYSINC)/sched.h	\
		$(SYSINC)/uproc.h	\
		$(SYSINC)/proc.h	\
		$(SYSINC)/con.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/ss.h		\
		$(SYSINC)/fdisk.h	\
		$(SYSINC)/hdioctl.h	\
		$(SYSINC)/buf.h		\
		$(SYSINC)/scsiwork.h	\
		ss.c
	$(CC) $(CFLAGS) -DDEBUG=$(DEBUG) -c -o $(KOBJ)/ss.o ss.c

$(KOBJ)/ssas.o:				\
		ssas.s
	$(AS) -go $@ $<

$(KOBJ)/st.o:				\
		$(SYSINC)/buf.h		\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(SYSINC)/const.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/inode.h	\
		$(SYSINC)/mtioctl.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/seg.h		\
		$(SYSINC)/stat.h	\
		$(SYSINC)/uproc.h	\
		st.c
	$(CC) $(CFLAGS) -c -o $@ st.c

$(KOBJ)/tn.o:				\
		$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
					$(SYSINC)/machine.h $(SYSINC)/param.h \
					$(SYSINC)/fun.h \
		$(SYSINC)/con.h		\
		$(SYSINC)/devices.h	\
		$(USRINC)/errno.h	\
		$(SYSINC)/sched.h	\
		$(SYSINC)/timeout.h	\
		$(SYSINC)/types.h	\
		$(SYSINC)/uproc.h	\
		tn.c
	$(CC) $(CFLAGS) -c -o $@ tn.c

$(KOBJ)/tnas.o: tnas.s
	$(AS) -gxo $@ tnas.s

# How to make loadable drivers.

$(LDRV)/aha154x:	$(USRSYS)/lib/aha154x.a
	( cd $(USRSYS); ldconfig aha154x )

$(LDRV)/al0:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al0 )

$(LDRV)/al1:	$(USRSYS)/lib/al.a
	( cd $(USRSYS); ldconfig al1 )

$(LDRV)/at:	$(USRSYS)/lib/at.a
	( cd $(USRSYS); ldconfig at )

$(LDRV)/fl:	$(USRSYS)/lib/fl.a
	( cd $(USRSYS); ldconfig fl )

$(LDRV)/gr:	$(USRSYS)/lib/gr.a
	( cd $(USRSYS); ldconfig gr )

$(LDRV)/hs:	$(USRSYS)/lib/hs.a
	( cd $(USRSYS); ldconfig hs )

$(LDRV)/lp:	$(USRSYS)/lib/lp.a
	( cd $(USRSYS); ldconfig lp )

$(LDRV)/mm:	$(USRSYS)/lib/mm.a
	( cd $(USRSYS); ldconfig mm )

$(LDRV)/ms:	$(USRSYS)/lib/ms.a
	( cd $(USRSYS); ldconfig ms )

$(LDRV)/rm:	$(USRSYS)/lib/rm.a
	( cd $(USRSYS); ldconfig rm )

$(LDRV)/ss:	$(USRSYS)/lib/ss.a
	( cd $(USRSYS); ldconfig ss )
0707070064030106231006440000000000000000011777770507310712200005000000113567/newbits/kernel/USRSRC/i8086/drv/gras.m/ (lgl-
/ 	COHERENT Driver Kit Version 1.0.0
/ 	Copyright (c) 1982, 1990 by Mark Williams Company.
/ 	All rights reserved. May not be copied without permission.
/ -lgl)
	.globl	grread_
	.globl	grwrite_
	.globl	mmgo_

////////
/
/ State driven code
/
/	Input:	DS:SI - input string
/		ES:DI - current screen location
/		SS:BP - terminal attributes
/		CX    - input count
/		BP    - references terminal information
/		AL    - character
/		BH    - (usually) kept zeroed for efficiency
/		DH    - current row
/		DL    - current column
/
////////

#ifdef	HERCULES
	VSEG	= 0xB000	/ Video Display Segment
	BANKSZ	= 8192		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 8		/ number of horizontal lines per char
	NCR2	= 4		/ number of horizontal lines per char / 2
	NCR4	= 2		/ number of horizontal lines per char / 4
	NHB	= 90		/ number of horizontal bytes per line
#else
#ifdef TECMAR
	VSEG	= 0xA000	/ Video Display Segment
	BANKSZ	= 32768		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 16		/ number of horizontal lines per char
	NCR2	= 8		/ number of horizontal lines per char / 2
	NCR4	= 4		/ number of horizontal lines per char / 4
	NHB	= 80		/ number of horizontal bytes per line
#else
	VSEG    = 0xB800	/ Video Display Segment
	BANKSZ	= 8192		/ Size of Display Banks
	LROW	= 24		/ Last legal row
	NCR	= 8		/ number of horizontal lines per char
	NCR2	= 4		/ number of horizontal lines per char / 2
	NCR4	= 2		/ number of horizontal lines per char / 4
	NHB	= 80		/ number of horizontal bytes per line
#endif
#endif

	NRB	= NHB*NCR	/ number of bytes per character row
	NRB2	= NHB*NCR2	/ number of bytes per character row / 2
	NRB4	= NHB*NCR4	/ number of bytes per character row / 4


	ZERO	= bh		/ (almost) always zero
	ROW	= dh		/ currently active vertical position
	COL	= dl		/ currently active horizontal position
	POS	= di		/ currently active display address

	CSR	= 0x3D9		/ Color Select Register
	MSR	= 0x3D8		/ Mode Select Register
	XMSR	= 0x3DA		/ Extended Mode Select Register


////////
/
/ Magic constants from <sys/io.h>
/
////////

	IO_SEG	= 0
	IO_IOC	= 2
	IO_SEEK	= 4
	IO_BASE	= 8

	IOSYS	= 0

////////
/
/ Data
/
////////

MM_FUNC		= 0		/ current state
MM_PORT		= 2		/ adapter base i/o port
MM_BASE		= 4		/ adapter base memory address
MM_ROW		= 6		/ screen row
MM_COL		= 7		/ screen column
MM_POS		= 8		/ screen position
MM_ATTR		= 10		/ attributes
MM_N1		= 11		/ numeric argument 1
MM_N2		= 12		/ numeric argument 2
MM_BROW		= 13		/ base row
MM_EROW		= 14		/ end row
MM_LROW		= 15		/ legal row limit
MM_SROW		= 16		/ saved cursor row
MM_SCOL		= 17		/ saved cursor column
MM_IBROW	= 18		/ initial base row
MM_IEROW	= 19		/ initial end row
MM_FLIP		= 20
MM_MASK		= 22
MM_ULINE	= 24
MM_CURSE	= 26
MM_VIS		= 28		/ set to -1 to make cursor visible
MM_NCOL		= 30
MM_WRAP		= 31

/ ASCII characters
AZERO		= 0x30
CLOWER		= 0x63
HLOWER		= 0x68
LLOWER		= 0x6C
SEMIC		= 0x3B

	.prvd
mmdata:	.word	mminit, 0x03D4, VSEG
	.byte	0, 0
	.word	0
	.byte	0x7, 0, 0, 0, LROW-1, LROW, 0, 0, 0, LROW-1
	.word	0, -1, 0, 0xff
	.word	0
	.byte	80
	.byte	1

	.shri
#ifdef	HERCULES
crtdata:.byte	 54,  45,  45,   8,  91,   1,  86,  88
	.byte	  2,   3,  32,   0,   0,   0,   0,   0
#else
#ifdef TECMAR
crtdata:.byte	 56,  40,  43,   8, 127,   6, 100, 112
	.byte	  3,   1,  32,   0,   0,   0,   0,   0
#else
crtdata:.byte	 56,  40,  43,   8, 127,   6, 100, 112
	.byte	  2,   1,  32,   0,   0,   0,   0,   0
#endif
#endif
	.shri

////////
/
/ mmgo( iop )		- Entry point for text stream output
/ IO *iop;
/
////////

mmgo_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	push	ds
	push	es
	cld
	mov	bx, 8(bp)		/ iop
	mov	si, IO_BASE(bx)		/ iop->io_base
	mov	cx, IO_IOC(bx)		/ iop->io_ioc
	cmp	IO_SEG(bx), $IOSYS
	je	0f
	mov	bx, uds_
	mov	ds, bx
0:	mov	bp, $mmdata
	movb	ROW, MM_ROW(bp)
	movb	COL, MM_COL(bp)
	mov	es,  MM_BASE(bp)
	mov	POS, MM_POS(bp)
	mov	ax, MM_CURSE(bp)
	and	ax, MM_VIS(bp)
#ifdef TECMAR
	xor	es:[NHB*6](POS), ax
	xor	es:[NHB*6]+BANKSZ(POS), ax
	xor	es:[NHB*7](POS), ax
	xor	es:[NHB*7]+BANKSZ(POS), ax
#else
	xor	es:[NHB*3](POS), ax	/ turn cursor off
	xor	es:[NHB*3]+BANKSZ(POS), ax
#endif
	sub	bx, bx
	ijmp	MM_FUNC(bp)

exit:	movb	bl, ROW			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	bl, $1
0:	add	POS, bx
	mov	ax, MM_CURSE(bp)
	and	ax, MM_VIS(bp)
#ifdef TECMAR
	xor	es:[NHB*6](POS), ax	/ turn cursor on
	xor	es:[NHB*6]+BANKSZ(POS), ax
	xor	es:[NHB*7](POS), ax
	xor	es:[NHB*7]+BANKSZ(POS), ax
#else
	xor	es:[NHB*3](POS), ax	/ turn cursor on
	xor	es:[NHB*3]+BANKSZ(POS), ax
#endif
	pop	bx
	pop	es
	pop	ds
	mov	MM_FUNC(bp), bx
	movb	MM_ROW(bp), ROW		/ save row,column
	movb	MM_COL(bp), COL
	mov	MM_POS(bp), POS		/ save position

	mov	dx, $MSR		/ enable video display
	movb	al, $0x1A
	outb	dx, al
	mov	mmvcnt_, $480		/ 480 seconds before video disabled

	mov	bp, sp
	mov	bx, 8(bp)
	mov	ax, cx			/ Return the residual count.
	xchg	cx, IO_IOC(bx)
	sub	cx, IO_IOC(bx)
	add	IO_BASE(bx), cx
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ mminit - initialize screen
/
////////

mminit:	movb	ss:mmesc_, $CLOWER		/ schedule keyboard initialization
	mov	dx, $MSR		/ disable video display
	movb	al, $0x12
	outb	dx, al

	push	cx			/ program registers, last to first
	mov	bx, $15
	mov	dx, MM_PORT(bp)
0:	movb	al, bl
	outb	dx, al
	inc	dx
	movb	al, cs:crtdata(bx)
	outb	dx, al
	dec	dx
	dec	bx
	jge	0b
	pop	cx

	mov	dx, $CSR
	movb	al, $0x0F
	outb	dx, al

	mov	dx, $XMSR
#ifdef TECMAR
	movb	al, $31
#else
	movb	al, $0
#endif
	outb	dx, al

/	mov	dx, $XMSR
0:	inb	al, dx		/ wait for vertical retrace
	andb	al, $8
	je	0b

	mov	dx, $MSR
	movb	al, $0x1A	/ video display on
	outb	dx, al

	mov	MM_VIS(bp), $-1
	mov	MM_MASK(bp), $0xAAAA
	mov	MM_FLIP(bp), $0
	mov	MM_ULINE(bp), $0
	mov	MM_CURSE(bp), $0x00ff
	movb	MM_WRAP(bp), $1
	movb	MM_NCOL(bp), $80
	subb	COL, COL
	movb	ROW, MM_IBROW(bp)
	movb	MM_BROW(bp), ROW
	movb	bl, MM_IEROW(bp)
	movb	MM_EROW(bp), bl
	sub	bx, bx
	movb	MM_N1(bp), $2
	jmp	mm_ed

////////
/
/ mmbell - schedule beep
/
////////

mmbell:	movb	ss:mmbeeps_, $-1
	jmp	eval

////////
/
/ mmspec - pass special characters on to keyboard routine(s).
/
////////

mmspec:	movb	ss:mmesc_, al
	jmp	eval

////////
/
/ mm_cnl - cursor next line
/
/	Moves the active position to the first column of the next display line.
/	Scrolls the active display if necessary.
/	Returns to mmwrite() to allow flow control on each output line.
/
////////

mm_cnl:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jle	repos
	movb	ROW, MM_EROW(bp)
/	jmp	scrollup

////////
/
/ scrollup - scroll display upwards
/
////////

scrollup:
	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_BROW(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	push	cx
	sub	cx, di
	shr	cx, $1
	push	si
	push	di
	push	cx
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	pop	di
	push	di
	mov	cx, $NRB4
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	pop	cx
	pop	si
	pop	ds
	jmp	ewait

////////
/
/ repos - reposition cursor
/
////////

repos:	movb	bl, ROW			/ reposition to ROW and COL
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	bl, $1
0:	add	POS, bx
/	jmp	eval

////////
/
/ eval - evaluate input character
/
////////

eval:	jcxz	ewait0
	dec	cx				/ evaluate next char
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

ewait0:	call	exit
	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mmputc - put character on screen
/
////////

mmputc:	cmpb	MM_NCOL(bp), $40
	jne	putc8


putc16:	push	ds
	push	si
	subb	ah, ah
	shlb	al, $1
	shl	ax, $1
	shl	ax, $1
	shl	ax, $1
	add	ax, $fontw_
	mov	si, ax
	mov	ax, cs
	mov	ds, ax
	mov	bx, $BANKSZ-2

	lodsw				/ row 0
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
	push	di			/ save position for next char
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif
	lodsw				/ row 1
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 2
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif

	lodsw				/ row 3
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 4
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif

	lodsw				/ row 5
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax
	add	di, $78

	lodsw				/ row 6
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	stosw
#ifdef TECMAR
	mov	es:(bx,di), ax
	add	di, $78
#endif
	lodsw				/ row 7
	or	ax, MM_ULINE(bp)
	xor	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
#ifdef TECMAR
	stosw
#endif
	mov	es:(bx,di), ax


	pop	di			/ restore position for next char
	pop	si
	pop	ds

	sub	bx, bx
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jge	0f
	jcxz	ewait1
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

ewait1:	jmp	ewait

putc8:	push	ds
	push	si
	subb	ah, ah
	shlb	al, $1
	shl	ax, $1
	shl	ax, $1
	add	ax, $0xFA6E
	mov	si, ax
	mov	ax, $0xF000
	mov	ds, ax
	mov	bx, $BANKSZ-1

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 0
	push	di			/ save position for next char
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah		/ row 1
	movb	es:80(bx,di), ah
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 1
	add	di, $79
#endif

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 2
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah
	movb	es:80(bx,di), ah	/ row 3
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 3
	add	di, $79
#endif

	lodsw
	xor	ax, MM_FLIP(bp)
	stosb				/ row 4
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah		/ row 5
	movb	es:80(bx,di), ah
	add	di, $79+80
#else
	movb	es:(bx,di), ah		/ row 5
	add	di, $79
#endif

	lodsw
	orb	ah, MM_ULINE(bp)
	xor	ax, MM_FLIP(bp)
	stosb				/ row 6
#ifdef TECMAR
	movb	es:(bx,di), al
	movb	es:79(di), ah
	movb	es:80(bx,di), ah
#else
	movb	es:(bx,di), ah		/ row 7
#endif

	pop	di			/ restore position for next char
	pop	si
	pop	ds

	sub	bx, bx
	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jge	0f
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

0:	subb	COL, COL
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos

0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ Ewait - wait for next input char to evaluate
/
////////

ewait:	call	exit
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cr - carriage return
/
/	Moves the active position to first position of current display line.
/
////////

mm_cr:	subb	COL, COL
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	jcxz	ewait
	dec	cx
	lodsb
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:asctab(bx)

////////
/
/ mm_cub - cursor backwards
/
////////

mm_cub:	decb	COL
	jge	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	subb	COL, COL
	movb	ROW, MM_BROW(bp)
0:	jmp	repos

////////
/
/ Esc state - entered when last char was ESC - transient state.
/
////////

0:	call	exit
mm_esc:	jcxz	0b
	dec	cx
	lodsb
	movb	MM_N1(bp), ZERO
	movb	MM_N2(bp), ZERO
	movb	bl, al
	shlb	bl, $1
	ijmp	cs:esctab(bx)

////////
/
/ Csi_n1 state - entered when last two chars were ESC [
/
/	Action:	Evaluates numeric chars as numeric parameter 1.
/
////////

0:	call	exit
csi_n1:	jcxz	0b
	dec	cx
	lodsb
	cmpb	al, $SEMIC
	je	csi_n2
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_n1

////////
/
/ Csi_n2 state - entered after input sequence ESC [ n ;
/
////////

0:	call	exit
csi_n2:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	csival
	shlb	MM_N2(bp), $1	/ n2 * 2
	movb	al, MM_N2(bp)	/ n2 * 2
	shlb	al, $1		/ n2 * 4
	shlb	al, $1		/ n2 * 8
	addb	al, MM_N2(bp)	/ n2 * 10
	addb	al, bl		/ n2 * 10 + digit
	movb	MM_N2(bp), al	/ n2 = (n2 * 10) + digit
	jmp	csi_n2

csival:	movb	bl, al
	shlb	bl, $1
	ijmp	cs:csitab(bx)

////////
/
/ Csi_gt state - entered after input sequence ESC [ >
/	
////////

0:	call	exit
csi_gt:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_gt

0:	cmpb	al, $HLOWER
	je	mm_cgh
	cmpb	al, $LLOWER
	je	mm_cgl
	jmp	eval

////////
/
/ Csi_q state - entered after input sequence ESC [ ?
/	
////////

0:	call	exit
csi_q:	jcxz	0b
	dec	cx
	lodsb
	movb	bl, al
	subb	bl, $AZERO
	cmpb	bl, $9
	ja	0f
	shlb	MM_N1(bp), $1	/ n1 * 2
	movb	al, MM_N1(bp)	/ n1 * 2
	shlb	al, $1		/ n1 * 4
	shlb	al, $1		/ n1 * 8
	addb	al, MM_N1(bp)	/ n1 * 10
	addb	al, bl		/ n1 * 10 + digit
	movb	MM_N1(bp), al	/ n1 = (n1 * 10) + digit
	jmp	csi_q

0:	cmpb	al, $HLOWER
	je	mm_cqh
	cmpb	al, $LLOWER
	je	mm_cql
	jmp	eval

////////
/
/ mm_cbt - cursor backward tabulation
/
/	Moves the active position horizontally in the backward direction
/	to the preceding in a series of predetermined positions.
/
////////

mm_cbt:	orb	COL, $7			/ calculate next tab stop
	incb	COL
	subb	COL, $16		/ step back two tab positions
	jg	0f
	subb	COL, COL		/ cannot step past column 0
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cgh - process ESC [ > N1 h escape sequence
/
/	Recognized sequences:	ESC [ > 13 h	-- Set CRT saver enabled.
/
////////

mm_cgh:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $1
0:	jmp	eval

////////
/
/ mm_cgl - process ESC [ > N1 l escape sequence
/
/	Recognized sequences:	ESC [ > 13 l	-- Reset CRT saver.
/
////////

mm_cgl:	cmpb	MM_N1(bp), $13
	jne	0f
	mov	ss:mmcrtsav_, $0
0:	jmp	eval

////////
/
/ mm_cha - cursor horizontal absolute
/
/	Advances the active position forward or backward along the active line
/	to the character position specified by the parameter.
/	A parameter value of zero or one moves the active position to the
/	first character position of the active line.
/	A parameter value of N moves the active position to character position
/	N of the active line.
/
////////

mm_cha:	movb	COL, MM_N1(bp)
	decb	COL
	jge	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor


////////
/
/ mm_cht - cursor horizontal tabulation
/
/	Advances the active position horizontally to the next or following
/	in a series of predetermined positions.
/
////////

mm_cht:	mov	bx, $BANKSZ
	push	cx
	push	si
	sub	cx, cx
	movb	cl, COL
	orb	cl, $7
	incb	cl
	subb	cl, COL
	addb	COL, cl

	mov	si, MM_MASK(bp)
	cmpb	MM_NCOL(bp), $80
	jne	0f
	mov	si, $-1
	inc	cx
	shr	cx, $1

0:	mov	ax, MM_FLIP(bp)
	and	ax, si
#ifdef TECMAR
	stosw				/ row 0
	mov	es:[NHB*0]-2(di,bx), ax
	mov	es:[NHB*1]-2(di), ax	/ row 1
	mov	es:[NHB*1]-2(di,bx), ax
	mov	es:[NHB*2]-2(di), ax	/ row 2
	mov	es:[NHB*2]-2(di,bx), ax
	mov	es:[NHB*3]-2(di), ax	/ row 3
	mov	es:[NHB*3]-2(di,bx), ax
	mov	es:[NHB*4]-2(di), ax	/ row 4
	mov	es:[NHB*4]-2(di,bx), ax
	mov	es:[NHB*5]-2(di), ax	/ row 5
	mov	es:[NHB*5]-2(di,bx), ax
	mov	es:[NHB*6]-2(di), ax	/ row 6
	mov	es:[NHB*6]-2(di,bx), ax
	or	ax, MM_ULINE(bp)
	and	ax, si
	mov	es:[NHB*7]-2(di), ax	/ row 7
	mov	es:[NHB*7]-2(di,bx), ax
#else
	stosw				/ row 0
	mov	es:[NHB*0]-2(di,bx), ax	/ row 1
	mov	es:[NHB*1]-2(di), ax	/ row 2
	mov	es:[NHB*1]-2(di,bx), ax	/ row 3
	mov	es:[NHB*2]-2(di), ax	/ row 4
	mov	es:[NHB*2]-2(di,bx), ax	/ row 5
	mov	es:[NHB*3]-2(di), ax	/ row 6
	or	ax, MM_ULINE(bp)
	and	ax, si
	mov	es:[NHB*3]-2(di,bx), ax	/ row 7
#endif
	loop	0b
	sub	bx, bx
	pop	si
	pop	cx
	cmpb	COL, MM_NCOL(bp)
	jl	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jle	0f
	movb	ROW, MM_EROW(bp)
	jmp	scrollup
0:	jmp	repos

////////
/
/ mm_cpl - cursor preceding line
/
/	Moves the active position to the first position of the preceding
/	display line.
/
////////

mm_cpl:	subb	COL, COL
	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jnb	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cqh - process ESC [ ? N1 h escape sequence
/
/	Recognized sequences:	ESC [ ? 7 h	-- Set wraparound.
/
////////

mm_cqh:
	cmpb	MM_N1(bp), $7		/ Wraparound.
	jne	0f
	movb	MM_WRAP(bp), $1
0:	jmp	eval

////////
/
/ mm_cql - process ESC [ ? N1 l escape sequence
/
/	Recognized sequences:	ESC [ ? 7 l	-- Reset wraparound.
/
////////

mm_cql:
	cmpb	MM_N1(bp), $7		/ No wraparound.
	jne	0f
	movb	MM_WRAP(bp), $0
0:	jmp	eval

////////
/
/ mm_cud - cursor down
/
/	Moves the active position downward without altering the
/	horizontal position.
/
////////

mm_cud:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuf - cursor forward
/
/	Moves the active position in the forward direction.
/
////////

mm_cuf:	incb	COL
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	subb	COL, MM_NCOL(bp)
	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jna	0f
	movb	ROW, MM_EROW(bp)
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos

////////
/
/ mm_cup - cursor position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter (mm_n1) specifies the vertical position (MM_ROW(bp)).
/	The second parameter (mm_n2) specifies the horizontal position (MM_COL(bp)).
/	A parameter value of 0 or 1 for the first or second parameter
/	moves the active position to the first line or column in the
/	display respectively.
/
////////

mm_cup:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	addb	ROW, MM_BROW(bp)
	cmpb	ROW, MM_EROW(bp)
	jb	0f
	movb	ROW, MM_EROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_cuu - cursor up
/
/	Moves the active position upward without altering the horizontal
/	position.
/
////////

mm_cuu:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_dl - delete line
/
/	Removes the contents of the active line.
/	The contents of all following lines are shifted in a block
/	toward the active line.
/
////////

mm_dl:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	mov	si, cs:rowtab+2(bx)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	si
	push	di
	push	cx
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	di, cs:rowtab(bx)
	push	di
	mov	cx, $NRB4
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	subb	COL, COL
0:	pop	cx
	pop	si
	pop	ds
	jmp	repos

////////
/
/ mm_dmi - disable manual input
/
/	Set flag preventing keyboard input.
/
////////

mm_dmi:
	mov	ss:islock_, $1
	jmp	eval

////////
/
/ mm_ea - erase in area
/
/	Erase some or all of the characters in the currently active area
/	according to the parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of active area
/
////////

mm_ea:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_EROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	movb	bl, MM_BROW(bp)
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	movb	bl, ROW
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	movb	bl, MM_EROW(bp)
	subb	bl, ROW
	jmp	mm_e2

////////
/
/ mm_ed - erase in display
/
/	Erase some or all of the characters in the display according to the
/	parameter
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase all of display
/
////////

mm_ed:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	movb	bl, MM_LROW(bp)
	jmp	mm_e0
0:	cmpb	al, $1
	jne	0f
	subb	bl, bl
	jmp	mm_e1
0:	subb	COL, COL
	movb	ROW, MM_BROW(bp)
	sub	POS, POS
	movb	bl, MM_LROW(bp)
	jmp	mm_e2

////////
/
/ mm_el - erase in line
/
/	Erase some or all of the characters in the line according to the
/	parameter:
/		0 - erase from active position to end inclusive (default)
/		1 - erase from start to active position inclusive
/		2 - erase entire line
/
////////

mm_el:	movb	al, MM_N1(bp)
	movb	bl, ROW
	cmpb	al, $0
	je	mm_e0
	cmpb	al, $1
	je	mm_e1
	shlb	bl, $1
	mov	POS, cs:rowtab(bx)
	subb	COL, COL
	subb	bl, bl
/	jmp	mm_e2

////////
/
/ mm_e2 - erase from POS for BL rows (minimum 1 row)
/
////////

mm_e2:	push	cx
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
0:	mov	cx, $NRB4
	rep
	stosw
	add	di, $BANKSZ-NRB2
	mov	cx, $NRB4
	rep
	stosw
	sub	di, $BANKSZ
	decb	bl
	jge	0b
	pop	cx
	jmp	repos

////////
/
/ mm_e1 - erase from row BL to current cursor position.
/
////////

mm_e1:	push	dx
	push	cx
	push	di
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	cx, cs:rowtab(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	di
	push	cx
	rep
	stosw
	pop	cx
	pop	di
	add	di, $BANKSZ
	rep
	stosw
0:	pop	cx
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab(bx)
	sub	cx, di
	jle	0f

	mov	dx, di
	mov	bx, cx
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 6
	stosb
#ifdef TECMAR
	add	dx, $80
	mov	di, dx
	mov	cx, bx
	rep			/ erase row 7
	stosb
	add	dx, $BANKSZ-560
#else
	add	dx, $BANKSZ-240
#endif
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 6
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 7
	stosb
1:	sub	bx, bx
	pop	cx
	pop	dx
	jmp	repos

////////
/
/ mm_e0 - erase from current cursor position to row BL inclusive.
/
////////

mm_e0:	push	dx
	push	cx
	push	di
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	shlb	bl, $1
	mov	cx, cs:rowtab+2(bx)
	movb	bl, ROW
	shlb	bl, $1
	mov	di, cs:rowtab+2(bx)
	sub	cx, di
	jle	0f
	shr	cx, $1
	push	di
	push	cx
	rep
	stosw
	pop	cx
	pop	di
	add	di, $BANKSZ
	rep
	stosw
0:	pop	di
	sub	cx, cx
	movb	cl, MM_NCOL(bp)
	subb	cl, COL
	cmpb	MM_NCOL(bp), $40
	jne	0f
	shlb	cl, $1
0:	mov	dx, di
	mov	bx, cx
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 6
	stosb
#ifdef TECMAR
	add	dx, $80
	mov	di, dx
	mov	cx, bx
	rep			/ erase row 7
	stosb
	add	dx, $BANKSZ-560
#else
	add	dx, $BANKSZ-240
#endif
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 0
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 1
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 2
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 3
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 4
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 5
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#ifdef TECMAR
	rep			/ erase row 6
	stosb
	add	dx, $80
	mov	di, dx
	mov	cx, bx
#endif
	rep			/ erase row 7
	stosb
1:	sub	bx, bx
	pop	cx
	pop	dx
	jmp	repos

////////
/
/ mm_emi - enable manual input
/
/	Clear flag preventing keyboard input.
/
////////

mm_emi:
	mov	ss:islock_, $0
	jmp	eval

////////
/
/ mm_il - insert line
/
/	Insert a erased line at the active line by shifting the contents
/	of the active line and all following lines away from the active line.
/	The contents of the last line in the scrolling region are removed.
/
////////

scrolldown:
mm_il:	push	ds
	push	si
	push	cx
	mov	ds, MM_BASE(bp)
	movb	bl, MM_EROW(bp)
	shlb	bl, $1
	mov	si, cs:rowtab(bx)
	mov	cx, si
	sub	si, $2
	mov	di, cs:rowtab+2(bx)
	sub	di, $2
	movb	bl, ROW
	shlb	bl, $1
	sub	cx, cs:rowtab(bx)
	jle	0f
	shr	cx, $1
	push	si
	push	di
	push	cx
	std
	rep
	movsw
	pop	cx
	pop	di
	pop	si
	add	si, $BANKSZ
	add	di, $BANKSZ
	rep
	movsw
	mov	di, cs:rowtab(bx)
	push	di
	mov	cx, $NRB4
	mov	ax, MM_FLIP(bp)
	and	ax, MM_MASK(bp)
	cld
	rep
	stosw
	pop	di
	add	di, $BANKSZ
	mov	cx, $NRB4
	rep
	stosw
	subb	COL, COL
0:	pop	cx
	pop	si
	pop	ds
	jmp	repos

////////
/
/ mm_hpa - horizontal position absolute
/
/	Moves the active position within the active line to the position
/	specified by the parameter.  A parameter value of zero or one
/	moves the active position to the first position of the active line.
/
////////

mm_hpa:	movb	COL, MM_N1(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hpr - horizontal position relative
/
/	Moves the active position forward the number of positions specified
/	by the parameter.  A parameter value of zero or one indicates a
/	single-position move.
/
////////

mm_hpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	COL, al
	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_hvp - horizontal and vertical position
/
/	Moves the active position to the position specified by two parameters.
/	The first parameter specifies the vertical position (MM_ROW(bp)).
/	The second parameter specifies the horizontal position (MM_COL(bp)).
/	A parameter value of zero or one moves the active position to the
/	first line or column in the display.
/
////////

mm_hvp:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	movb	COL, MM_N2(bp)
	decb	COL
	jg	0f
	subb	COL, COL
0:	cmpb	COL, MM_NCOL(bp)
	jb	0f
	movb	COL, MM_NCOL(bp)
	decb	COL
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_ind - index
/
/	Causes the active position to move downward one line without changing
/	the horizontal position.  Scrolling occurs if below scrolling region.
/
////////

mm_ind:	incb	ROW
	cmpb	ROW, MM_EROW(bp)
	jg	0f
	jmp	repos
0:	movb	ROW, MM_EROW(bp)
	jmp	scrollup

////////
/
/ mm_new - save cursor position
/
////////

mm_new:	movb	MM_SCOL(bp), COL
	movb	MM_SROW(bp), ROW
	jmp	eval

////////
/
/ mm_old - restore old cursor position
/
////////

mm_old:	movb	COL, MM_SCOL(bp)
	movb	ROW, MM_SROW(bp)
	jmp	repos

////////
/
/ mm_ri - reverse index
/
/	Moves the active position to the same horizontal position on the
/	preceding line.  Scrolling occurs if above scrolling region.
/
////////

mm_ri:	decb	ROW
	cmpb	ROW, MM_BROW(bp)
	jge	0f
	movb	ROW, MM_BROW(bp)
	jmp	scrolldown
0:	jmp	repos

////////
/
/ mm_scr - select cursor rendition
/
/	Invokes the cursor rendition specified by the parameter.
/
/	Recognized renditions are:	0 - cursor visible
/					1 - cursor invisible
////////

mm_scr:	decb	MM_N1(bp)
	je	0f
	jg	1f
	mov	MM_VIS(bp), $-1
	jmp	eval

0:	mov	MM_VIS(bp), $0
1:	jmp	eval

////////
/
/ mm_sgr - select graphic rendition
/
/	Invokes the graphic rendition specified by the parameter.
/	All following characters in the data stream are rendered
/	according to the parameters until the next occurrence of
/	SGR in the data stream.
/
/	Recognized renditions are:	1 - high intensity
/					4 - underline
/					7 - reverse video
/
////////

mm_sgr:	movb	al, MM_N1(bp)
	cmpb	al, $0
	jne	0f
	mov	MM_MASK(bp), $0xAAAA
	mov	MM_FLIP(bp), $0
	mov	MM_ULINE(bp), $0
	jmp	1f
0:	cmpb	al, $1		/ bold
	jne	0f
	mov	MM_MASK(bp), $-1
	jmp	1f
0:	cmpb	al, $4		/ underline
	jne	0f
	mov	MM_ULINE(bp), $0xFFFF
	jmp	1f
0:	cmpb	al, $7		/ reverse video
	jne	0f
	mov	MM_FLIP(bp), $-1
	jmp	1f
0:
1:	jmp	eval

////////
/
/ mm_so - stand out - enter 40 column mode
/
////////

mm_so:	cmpb	MM_NCOL(bp), $80
	jne	0f
	movb	MM_NCOL(bp), $40
	incb	COL
	shrb	COL, $1
0:	mov	MM_CURSE(bp), $0xffff
	jmp	repos

////////
/
/ mm_si - stand in - enter 80 column mode
/
////////

mm_si:	cmpb	MM_NCOL(bp), $40
	jne	0f
	movb	MM_NCOL(bp), $80
	shlb	COL, $1
0:	mov	MM_CURSE(bp), $0x00ff
	jmp	repos

////////
/
/ mm_ssr - set scrolling region
/
////////

mm_ssr:	movb	al, MM_N1(bp)
	decb	al
	jge	0f
	subb	al, al
0:	cmpb	al, MM_LROW(bp)
	ja	1f
	movb	bl, MM_N2(bp)
	decb	bl
	jge	0f
	subb	bl, bl
0:	cmpb	bl, MM_LROW(bp)
	ja	1f
	cmpb	al, bl
	ja	1f
	movb	MM_BROW(bp), al
	movb	MM_EROW(bp), bl
	movb	ROW, al
	subb	COL, COL
1:	jmp	repos

////////
/
/ mm_vpa - vertical position absolute
/
/	Moves the active position to the line specified by the parameter
/	without changing the horizontal position.
/	A parameter value of 0 or 1 moves the active position vertically
/	to the first line.
/
////////

mm_vpa:	movb	ROW, MM_N1(bp)
	decb	ROW
	jg	0f
	subb	ROW, ROW
0:	cmpb	ROW, MM_LROW(bp)
	jna	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ mm_vpr - vertical position relative
/
/	Moves the active position downward the number of lines specified
/	by the parameter without changing the horizontal position.
/	A parameter value of zero or one moves the active position
/	one line downward.
/
////////

mm_vpr:	movb	al, MM_N1(bp)
	orb	al, al
	jne	0f
	incb	al
0:	addb	ROW, al
	cmpb	ROW, MM_LROW(bp)
	jb	0f
	movb	ROW, MM_LROW(bp)
0:	jmp	repos			/ reposition cursor

////////
/
/ asctab - table of functions indexed by ascii characters
/
////////

asctab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	mmbell	/* EOT  ENQ  ACK  BEL  */
	.word	mm_cub,	mm_cht,	mm_cnl,	mm_ind	/* BS   HT   LF   VT  */
	.word	eval,	mm_cr,	mm_so,	mm_si	/* FF   CR   SO   SI  */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3 */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	mm_esc	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/*   ! " # \040 - \043 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* $ % & quote \044 - \047 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ( ) * + \050 - \053 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* , - . / \054 - \057 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 0 1 2 3 \060 - \063 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 4 5 6 7 \064 - \067 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* 8 9 : ; \070 - \073 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* < = > ? \074 - \077 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* @ A B C \100 - \103 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* D E F G \104 - \107 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* H I J K \110 - \113 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* L M N O \114 - \117 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* P Q R S \120 - \123 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* T U V W \124 - \127 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* X Y Z [ \130 - \133 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* \ ] ^ _ \134 - \137 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* ` a b c \140 - \143 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* d e f g \144 - \147 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* h i j k \150 - \153 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* l m n o \154 - \157 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* p q r s \160 - \163 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* t u v w \164 - \167 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* x y z { \170 - \173 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* | } ~ ? \174 - \177 */

////////
/
/ esctab - table of functions indexed by escape characters.
/
////////

esctab:	.word	mmputc,	mmputc,	mmputc,	mmputc	/* NUL  SOH  STX  ETX  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* EOT  ENQ  ACK  BEL  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* BS   HT   LF   VT  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FF   CR   SO   SI  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DLE  DC1  DC2  DC3 */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* DC4  NAK  SYN  ETB  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* CAN  EM   SUB  ESC  */
	.word	mmputc,	mmputc,	mmputc,	mmputc	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	mm_new	/* 4 5 6 7 \064 - \067 */
	.word	mm_old,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	mmspec,	mmspec,	eval	/* < = > ? \074 - \077 */
	.word	eval,	eval,	eval,	eval	/* @ A B C \100 - \103 */
	.word	mm_ind,	mm_cnl,	eval,	eval	/* D E F G \104 - \107 */
	.word	eval,	eval,	eval,	eval	/* H I J K \110 - \113 */
	.word	eval,	mm_ri,	eval,	eval	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	eval	/* P Q R S \120 - \123 */
	.word	eval,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	eval,	csi_n1	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_dmi,	eval,	mm_emi,	mminit	/* ` a b c \140 - \143 */
	.word	eval,	eval,	eval,	eval	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	eval,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	eval,	eval	/* p q r s \160 - \163 */
	.word	mmspec,	mmspec,	eval,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ csitab - table of functions indexed by ESC [ characters.
/
////////

csitab:	.word	eval,	eval,	eval,	eval	/* NUL  SOH  STX  ETX  */
	.word	eval,	eval,	eval,	eval	/* EOT  ENQ  ACK  BEL  */
	.word	eval,	eval,	eval,	eval	/* BS   HT   LF   VT  */
	.word	eval,	eval,	eval,	eval	/* FF   CR   SO   SI  */
	.word	eval,	eval,	eval,	eval	/* DLE  DC1  DC2  DC3 */
	.word	eval,	eval,	eval,	eval	/* DC4  NAK  SYN  ETB  */
	.word	eval,	eval,	eval,	eval	/* CAN  EM   SUB  ESC  */
	.word	eval,	eval,	eval,	eval	/* FS   GS   RS   US   */
	.word	eval,	eval,	eval,	eval	/*   ! " # \040 - \043 */
	.word	eval,	eval,	eval,	eval	/* $ % & quote \044 - \047 */
	.word	eval,	eval,	eval,	eval	/* ( ) * + \050 - \053 */
	.word	eval,	eval,	eval,	eval	/* , - . / \054 - \057 */
	.word	eval,	eval,	eval,	eval	/* 0 1 2 3 \060 - \063 */
	.word	eval,	eval,	eval,	eval	/* 4 5 6 7 \064 - \067 */
	.word	eval,	eval,	eval,	eval	/* 8 9 : ; \070 - \073 */
	.word	eval,	eval,	csi_gt,	eval	/* < = > ? \074 - \077 */
	.word	eval,	mm_cuu,	mm_cud,	mm_cuf	/* @ A B C \100 - \103 */
	.word	mm_cub,	mm_cnl,	mm_cpl,	mm_cha	/* D E F G \104 - \107 */
	.word	mm_cup,	mm_cht,	mm_ed,	mm_el	/* H I J K \110 - \113 */
	.word	mm_il,	mm_dl,	eval,	mm_ea	/* L M N O \114 - \117 */
	.word	eval,	eval,	eval,	mm_ind	/* P Q R S \120 - \123 */
	.word	mm_ri,	eval,	eval,	eval	/* T U V W \124 - \127 */
	.word	eval,	eval,	mm_cbt,	eval	/* X Y Z [ \130 - \133 */
	.word	eval,	eval,	eval,	eval	/* \ ] ^ _ \134 - \137 */
	.word	mm_hpa,	mm_hpr,	eval,	eval	/* ` a b c \140 - \143 */
	.word	mm_vpa,	mm_vpr,	mm_hvp,	mm_cup	/* d e f g \144 - \147 */
	.word	eval,	eval,	eval,	eval	/* h i j k \150 - \153 */
	.word	eval,	mm_sgr,	eval,	eval	/* l m n o \154 - \157 */
	.word	eval,	eval,	mm_ssr,	eval	/* p q r s \160 - \163 */
	.word	eval,	eval,	mm_scr,	eval	/* t u v w \164 - \167 */
	.word	eval,	eval,	eval,	eval	/* x y z { \170 - \173 */
	.word	eval,	eval,	eval,	eval	/* | } ~ ? \174 - \177 */

////////
/
/ rowtab - array of offsets to each row
/
////////

rowtab:	.word	 0*NRB2,	 1*NRB2,	 2*NRB2,	 3*NRB2
	.word	 4*NRB2,	 5*NRB2,	 6*NRB2,	 7*NRB2
	.word	 8*NRB2,	 9*NRB2,	10*NRB2,	11*NRB2
	.word	12*NRB2,	13*NRB2,	14*NRB2,	15*NRB2
	.word	16*NRB2,	17*NRB2,	18*NRB2,	19*NRB2
	.word	20*NRB2,	21*NRB2,	22*NRB2,	23*NRB2
	.word	24*NRB2,	25*NRB2,	26*NRB2,	27*NRB2
	.word	28*NRB2,	29*NRB2,	30*NRB2,	31*NRB2
	.word	32*NRB2,	33*NRB2,	34*NRB2,	35*NRB2
	.word	36*NRB2,	37*NRB2,	38*NRB2,	39*NRB2
	.word	40*NRB2,	41*NRB2,	42*NRB2,	43*NRB2
	.word	44*NRB2,	45*NRB2,	46*NRB2,	47*NRB2
	.word	48*NRB2,	49*NRB2,	50*NRB2,	51*NRB2

////////
/
/ grread( dev, iop ) - read graphics display memory
/
////////

grread_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	mov	bp, 10(bp)
	push	ds
	push	es
	cmp	IO_SEG(bp), $IOSYS
	je	0f
	mov	ax, uds_
	mov	es, ax
0:	mov	di, IO_BASE(bp)
	mov	ax, $VSEG
	mov	ds, ax

#ifndef TECMAR
	mov	ax, IO_SEEK(bp)
	add	ax, IO_IOC(bp)
	cmp	ax, $BANKSZ*2
	ja	done
#endif

	mov	ax, IO_SEEK(bp)
	sub	dx, dx
	mov	cx, $NHB
	div	cx
	mov	si, dx
	mov	bx, ax
	shr	ax, $1
	mul	cx
	mov	dx, si
	add	si, ax
	testb	bl, $1
	jne	read2

read1:	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	push	si
	rep
	movsb
	pop	si
read2:	add	si, $BANKSZ
	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	rep
	movsb
	sub	si, $BANKSZ
	sub	dx, dx
	jmp	read1

done:	pop	es
	pop	ds
	pop	bp
	pop	di
	pop	si
	ret

////////
/
/ grwrite( dev, iop ) - write graphics display memory
/
////////

grwrite_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	mov	bp, 10(bp)
	push	ds
	push	es
	cmp	IO_SEG(bp), $IOSYS
	je	0f
	mov	ax, uds_
	mov	ds, ax
0:	mov	si, IO_BASE(bp)
	mov	ax, $VSEG
	mov	es, ax

#ifndef TECMAR
	mov	ax, IO_SEEK(bp)
	add	ax, IO_IOC(bp)
	cmp	ax, $BANKSZ*2
	ja	done
#endif

	mov	ax, IO_SEEK(bp)
	sub	dx, dx
	mov	cx, $NHB
	div	cx
	mov	di, dx
	mov	bx, ax
	shr	ax, $1
	mul	cx
	mov	dx, di
	add	di, ax
	testb	bl, $1
	jne	page2

page1:	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	push	di
	rep
	movsb
	pop	di
page2:	add	di, $BANKSZ
	mov	cx, $NHB
	sub	cx, dx
	cmp	cx, IO_IOC(bp)
	jle	0f
	mov	cx, IO_IOC(bp)
	jcxz	done
0:	sub	IO_IOC(bp), cx
	add	IO_BASE(bp), cx
	rep
	movsb
	sub	di, $BANKSZ
	sub	dx, dx
	jmp	page1

////////
/
/ mm_voff()	-- Disable video display
/
////////
	.globl	mm_voff_
mm_voff_:
	mov	dx, $MSR
	movb	al, $0x12
	outb	dx, al
	ret

////////
/
/ mm_von()	-- Enable video display
/
////////
	.globl	mm_von_
mm_von_:
	mov	dx, $MSR		/ enable video display
	movb	al, $0x1A
	outb	dx, al
	mov	ss:mmvcnt_, $480	/ 480 seconds before video disabled
	ret
0707070064030150020407550000030000030000011777770507310713200004400000000000/newbits/kernel/USRSRC/i8086/ibm_at0707070064030112141006440000030000030000011777770507310713200005200000075156/newbits/kernel/USRSRC/i8086/ibm_at/as2.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/ (lgl-
/	The information contained herein is a trade secret of Mark Williams
/	Company, and  is confidential information.  It is provided  under a
/	license agreement,  and may be  copied or disclosed  only under the
/	terms of  that agreement.  Any  reproduction or disclosure  of this
/	material without the express written authorization of Mark Williams
/	Company or persuant to the license agreement is unlawful.
/
/	COHERENT Version 2.3.37
/	Copyright (c) 1982, 1983, 1984.
/	An unpublished work by Mark Williams Company, Chicago.
/	All rights reserved.
/ -lgl)
////////
/
/ Machine language assist for
/ Coherent on the IBM personal computer.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.2  91/06/06  18:14:46  norm
/ Get memory size by reading CMOS.

/ Revision 1.3	88/08/05  15:37:32	src
/ AMD 286 hardware specific fixes removed - hardware now correct.
/ Virtual Selector F000 initialized to access ROM at F0000.
/ Normal kernel stack now used during initialization.
/ 
/ Revision 1.2	88/06/29  19:05:31	src
/ AT Coherent can now come up in real-mode by patching 'realmode' variable.
/ 
/ Revision 1.1	88/03/24  17:33:18	src
/ Initial revision
/ 
/ 88/03/10	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
/ These partial fixes will be removed once all CPU's are replaced.
/
/ 88/03/07	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Obsolete video() function deleted - not used, or usable in protected mode.
/ Auto-increment mode no longer assumed, but enforced on block moves.
/
/ 88/03/04	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Memory sizing now flushes instruction pipeline before read-verify.
/ Otherwise bus capacitance on some machines gives invalid memory indication.
/ plrcopy, prlcopy, pclear, upcopy, kpcopy, pucopy, and pkcopy now ensure
/ registers DS and ES refer to kernel data before calling ptov() or vrelse().
/ MAXMEM variable added to specify maximum low memory in clicks.
/
/ 87/11/22	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Added check for extended memory in protected mode.
/
/ 87/11/14	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ boot() now requests 8042 controller to initiate processor reset.
/
/ 87/11/05	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ slrcopy/srlcopy/sclear renamed plrcopy/prlcopy/pclear and moved here.
/
/ 87/10/27	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ System stack/data segments now setup here rather than in as1.s
/ System stack/data moved to next 128 byte boundary for protected mode.
/
/ 87/08/31	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Timer channel 1 now reprogrammed for memory refresh.
/
/ 87/07/08	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Timer chip now programmed for 100 hz clock interrupt rather than 20 hz.
/
////////

EFAULT	=	14			/ Bad argument
EXTMEML =	0x17			/ Ext. mem size (low) offset in CMOS
EXTMEMH = 	0x18			/               (high)
PFLAGS	=	0x22			/ Offset int PROC.
PFKERN	=	0x80			/ Kernel process flag bit.
PIC	=	0x20			/ 8259 CSR  I/O port.
PICM	=	0x21			/ 8259 IMR  I/O port.
PIT	=	0x40			/ 8253 base I/O port.
KBDATA	=	0x60			/ 8042 keyboard mpu data I/O port.
KBCTRL	=	0x64			/ 8042 keyboard mpu ctrl I/O port.
CMOSA	=	0x70			/ Real-time Clock/CMOS addr I/O port.
CMOSD	=	0x71			/ Real-time Clock/CMOS data I/O port.
SPIC	=	0xA0			/ Slave 8259 CSR I/O port.
SPICM	=	0xA1			/ Slave 8259 IMR I/O port.
UPASIZE	=	1024			/ Size of uproc and stack

////////
/
/ System entry point. Under PC-DOS,
/ which thinks that Coherent is just a large
/ user program, the code is offset by 0x100
/ to allow space for the base page.
/
////////

	.blkb	0x0100			/ PC-DOS base page.
	cli				/ No interrupts, please.

	int	0x11			/ Obtain int 11 value before printf().
	mov	cs:val11, ax		/ Use boot block's stack for last time.

/
/ Enable the A20 address line, which is normally disabled by the ROM BIOS.
/ This line is under the control of the 8042 keyboard interface controller.
/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/
	loopne	0b			/
	jmp	.+2		/ DELAY /
					/
	movb	al, $0xD1		/ Request next output byte to be
	outb	KBCTRL, al		/	sent to the 8042 output port.
					/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/
	loopne	0b			/
	jmp	.+2		/ DELAY /
					/
	movb	al, $0xDF		/ Enable A20 address line.
	outb	KBDATA, al		/ See Page 1-44, IBM-AT Tech Ref.
					/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/ NOTE: A20 not enabled for up to 20 us.
	loopne	0b			/

/
/ Reprogram the 8253 timer so that channel 0, 
/ which is used as the clock, interrupts at exactly
/ 100 HZ, instead of 18.2 HZ.
/
	movb	al, $0x36		/ Timer 0, LSB, MSB, mode 3
	outb	PIT+3, al
	jmp	.+2		/ DELAY /
	jmp	.+2		/ DELAY /
	movb	al, $0x9C		/ Lsb of 59659/5 = 11932
	outb	PIT, al
	jmp	.+2		/ DELAY /
	jmp	.+2		/ DELAY /
	movb	al, $0x2E		/ Msb of 59659/5 = 11932
	outb	PIT, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/

/ Reprogram channel 1 on the 8253 timer which is used for memory refresh.
/	movb	al, $0x54		/ Timer 1, LSB, mode 2
/	outb	PIT+3, al
/	jmp	.+2		/ DELAY	/
/	jmp	.+2		/ DELAY	/
/	movb	al, $18			/ LSB of 18.
/	outb	PIT+1, al
/	jmp	.+2		/ DELAY	/
/	jmp	.+2		/ DELAY	/

/ Reprogram the 1st programmable interrupt controller.
/ It's default vector table collides with iAPX 286 protection vectors.

	movb	al, $0x11		/ ICW1 - edge, master, ICW4
	outb	PIC, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0x20		/ ICW2 - Reserve 1st 32 vectors for 286
	outb	PICM, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0x04		/ ICW3 - master level 2
	outb	PICM, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0x01		/ ICW4 - 8086 mode, master.
	outb	PICM, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0xFE		/ Disable interrupts from master PIC.
	outb	PICM, al		/ (except for clock interrupt).

	movb	al, $0xFF
	outb	SPICM, al		/ Disable interrupts from slave PIC.

/ Set up all trap vectors.
/ The machine traps all have their own
/ linkages. We have to steal the clock from
/ the ROM, because the stacks might get switched
/ during the INT 1C, and the EOI would get sent
/ to the 8259 at a strange time.

	sub	ax, ax			/ Map DS over the 8088
	mov	ds, ax			/ vector area.

	mov	0x0000, $trap0		/ Divide error vector
	mov	0x0002, cs
	mov	0x0004, $trap1		/ Single step.
	mov	0x0006, cs
	mov	0x0008, $trap2		/ NMI
	mov	0x000A, cs
	mov	0x000C, $trap3		/ INT 3 (break)
	mov	0x000E, cs
	mov	0x0010, $trap4		/ Overflow.
	mov	0x0012, cs
	mov	0x0014, $trap5		/ Bound range exceeded.
	mov	0x0016, cs
	mov	0x0018, $trap6		/ Invalid Opcode
	mov	0x001A, cs
	mov	0x001C, $trap7		/ Processor extension not available
	mov	0x001E, cs
	mov	0x0020, $trap8		/ Double exception detected.
	mov	0x0022, cs
	mov	0x0024, $trap9		/ Processor extension segment overrun.
	mov	0x0026, cs
	mov	0x0028, $trap10		/ Invalid task state segment.
	mov	0x002A, cs
	mov	0x002C, $trap11		/ Segment not present.
	mov	0x002E, cs
	mov	0x0030, $trap12		/ Stack segment overrun or not present.
	mov	0x0032, cs
	mov	0x0034, $trap13		/ General protection.
	mov	0x0036, cs

	mov	0x0080, $clk		/ Clock.
	mov	0x0082, cs
	mov	0x0084, $dev1		/ Device 1
	mov	0x0086, cs
	mov	0x0088, $dev9		/ Device 2 maps into Device 9
	mov	0x008A, cs
	mov	0x008C, $dev3		/ Device 3
	mov	0x008E, cs
	mov	0x0090, $dev4		/ Device 4
	mov	0x0092, cs
	mov	0x0094, $dev5		/ Device 5
	mov	0x0096, cs
	mov	0x0098, $dev6		/ Device 6
	mov	0x009A, cs
	mov	0x009C, $dev7		/ Device 7
	mov	0x009E, cs

	mov	0x01C0, $dev8		/ Device 8
	mov	0x01C2, cs
	mov	0x01C4, $dev9		/ Device 9
	mov	0x01C6, cs
	mov	0x01C8, $dev10		/ Device 10
	mov	0x01CA, cs
	mov	0x01CC, $dev11		/ Device 11
	mov	0x01CE, cs
	mov	0x01D0, $dev12		/ Device 12
	mov	0x01D2, cs
	mov	0x01D4, $dev13		/ Device 13
	mov	0x01D6, cs
	mov	0x01D8, $dev14		/ Device 14
	mov	0x01DA, cs
	mov	0x01DC, $dev15		/ Device 15
	mov	0x01DE, cs

	mov	bx, $0x0200		/ INT 80 (sys 0)
0:	mov	(bx), $syc		/ Set up the system call
	mov	2(bx), cs		/ trap vector.
	add	bx, $4			/ Move to next vector and
	cmp	bx, $0x0400		/ loop until all
	jb	0b			/ vectors are reset.

/ Set up the system stack and data segments, by looking at the size of
/ the text and adding this to the base address already in the CS.
/ Relocate the stack and data to a 128 byte boundary.

	mov	ax, $etext_+15		/ End of text segment
	shr	ax, $4			/ Convert to paragraphs.
	mov	cx, cs			/ Get code segment base.
	add	ax, cx			/
	mov	ds, ax			/ Current data segment
	add	ax, $31			/ Allow virtual-physical alignment
	and	ax, $~31		/	[use 512 byte, need 128 byte]
					/
	cmp	realmode_, $0		/ Virtual Addressing enabled?
	jne	0f			/
	mov	idtsel_, ax		/ Interrupt descriptor table [2 Kbytes]
	add	ax, $0x0080		/	2K >> 4
	mov	gdtsel_, ax		/ Global descriptor table [64 Kbytes]
	add	ax, $0x1000		/	64K >> 4
0:					/
	mov	es, ax			/
	mov	si, $edata_-1		/ Copy data to new location, backwards.
	mov	di, $edata_-1		/
	mov	cx, $edata_		/
	std				/
	rep				/
	movsb				/
					/
	mov	ds, ax			/ Update data segment,
	mov	ss, ax			/ and stack segment.
	mov	sp, $u_+UPASIZE-32	/ Set up initial stack.
	mov	scs_, cs		/ Save code segment and
	mov	sds_, ds		/ data segment bases.
	mov	cs:cds, ds		/ For interrupts.

/ Size up memory, starting just above the system.
/ The memory is cleared, because somebody has to do a write
/ to set up the parity bits.

	mov	di, $edata_		/ Clear at edata...
	mov	cx, $512		/ for 1 Kbyte
	sub	ax, ax
	cld
	rep
	stosw

	mov	bp, $edata_+1023	/ Compute base.
	shr	bp, $4
	add	bp, sds_
	shr	bp, $6			/ Round down to a Kbyte boundary
	shl	bp, $6			/ so's we're in sync.

0:	sub	di, di			/ Destination.
	mov	es, bp			/ Set extra segment and
	mov	es:(di), ax		/ clear a word.
	jmp	.+2		/ FLUSH	/
	cmp	es:(di), ax		/ Should be zero now.
	jne	0f			/ Branch if memory end

	mov	cx, $512		/ 1K bytes, in words.
	cld
	rep
	stosw				/ Clear this 1K
	add	bp, $64			/ Move along by 1K
	cmp	bp, MAXMEM
	jb	0b			/ If not at video ram yet

0:	mov	es, sds_		/ Map extra.

	mov	ax, bp			/ Calculate top of low memory.
	rol	ax, $4			/
	mov	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/

	cmp	realmode_, $0		/ Real Addressing Mode?
	je	0f			/
	mov	coretop_, ax		/ Yes, Record top of memory,
	mov	coretop_+2, dx		/
	jmp	start			/ and bring up system.
0:
	mov	holebot_, ax		/ Record bottom of I/O memory.
	mov	holebot_+2, dx		/

	mov	ax, gdtsel_		/ Format global descriptor table map.
	rol	ax, $4			/
	mov	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/
	mov	gdtmap_+0, $0xFFFF	/ Limit: 64K bytes.
	mov	gdtmap_+2, ax		/
	mov	gdtmap_+4, dx		/
					/
	sub	ax, ax			/ Erase global descriptor table.
	mov	cx, $0x8000		/	[32K words = 64K bytes]
	mov	es, gdtsel_		/
	sub	di, di			/
	cld				/
	rep				/
	stosw				/
					/
	mov	ax, idtsel_		/ Format interrupt descriptor table map
	rol	ax, $4			/
	mov	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/
	mov	idtmap_+0, $2047	/ Limit: 2K bytes.
	mov	idtmap_+2, ax		/
	mov	idtmap_+4, dx		/
					/
	sub	ax, ax			/ Erase interrupt descriptor table.
	mov	cx, $1024		/	[1K words = 2K bytes]
	mov	es, idtsel_		/
	sub	di, di			/
	cld				/
	rep				/
	stosw				/
					/
	mov	es, gdtsel_		/
	mov	di, cs			/ Define kernel code global selector.
	mov	ax, $etext_-1		/	Limit: etext.
	stosw				/
	mov	dx, $0x9A00		/	Flags: Present, executable.
	mov	ax, cs			/	Base:  cs << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, ss			/ Define kernel data global selector.
	mov	ax, $0xFFFF		/	Limit: 64K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, ss			/	Base:  ss << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, $8			/ Define task state segment selector[8]
	mov	ax, $43			/	Limit: 44 bytes.
	stosw				/
	mov	dx, $0x8100		/	Flags: Present, avail tss seg.
	mov	ax, ss			/	Base:  (ss << 4) + &tss.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/
	add	ax, $tss_		/
	adc	dx, $0			/
	stosw				/
	mov	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, gdtsel_		/ Define gdt access global selector.
	mov	ax, $0xFFFF		/	Limit: 64K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, gdtsel_		/	Base: gdtsel << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, idtsel_		/ Define idt access global selector.
	mov	ax, $2047		/	Limit: 2K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, idtsel_		/	Base: idtsel << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, $0xB000		/ Define video access global selector.
	mov	ax, $0xFFFF		/	Limit: 64K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, $0xB000		/	Base:  0xB000 << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, $0xB800		/ Define video access global selector.
	mov	ax, $0x7FFF		/	Limit: 32 Kbytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, $0xB800		/	Base:  0xB800 << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/

	mov	di, $0xF000		/ Define ROM access global selector.
	mov	ax, $0xFFFF		/	Limit: 64 Kbytes.
	stosw				/
	mov	dx, $0x9000		/	Flags: Present, read only.
	mov	ax, $0xF000		/	Base:  0xF000 << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/

	mov	es, idtsel_		/ Map ES over the intr descr table.
	sub	ax, ax			/ Map DS over the 8088 vector area.
	mov	ds, ax			/
	sub	si, si			/
	sub	di, di			/
	mov	bx, cs			/ Make CS available for comparison.
	mov	cx, $256		/ Install 256 interrupt descriptors.
					/
0:	lodsw				/ Copy interrupt IP
	stosw				/
	lodsw				/ Copy interrupt CS
	stosw				/
					/
	cmp	ax, bx			/ Coherent interrupt handler?
	mov	ax, $0x8600		/
	je	1f			/
	sub	ax, ax			/ No, clear flags.
					/
1:	stosw				/ Define IDT flags.
	sub	ax, ax			/ Reserved IDT word.
	stosw				/
	loop	0b			/ Repeat for all 256 entries.
					/
	mov	ax, ss			/ Restore data and extra segments.
	mov	ds, ax			/
	mov	es, ax			/
					/
	clts				/ Clear task switched flag.
	lgdt	gdtmap_			/ Load global descriptor table map.
	lidt	idtmap_			/ Load interrupt descriptor table map.
					/
	smsw	ax			/ Enter protected mode.
	or	ax, $1			/
	lmsw	ax			/
	jmp	.+2			/ Clear pipeline.
					/
	mov	ax, $0x0008		/ Load task state segment register.
	ltr	ax			/
	sub	ax, ax			/ Load local descriptor table register.
	lldt	ax			/
					/
					/
					/ Register usage:
					/ DX:AX = extended mem physical addr.
					/ BX = 0.
					/ SI = selector into extended memory.
					/ ES = selector into extended memory.
					/ DS = selector into global descr table
					/
	movb	al, $EXTMEMH		/ high byte of pair
	outb	CMOSA, al		/ to CMOS memory port
	jmp	.+2			/ DELAY
	inb	al, CMOSD		/ get value from CMOS
	xchgb	ah, al
	jmp	.+2			/ DELAY
	movb	al, $EXTMEML		/ low byte of pair
	outb	CMOSA, al		/ to CMOS memory port
	jmp	.+2			/ DELAY
	inb	al, CMOSD		/ get rest of pair from CMOS
	shr	ax, $6			/ K -> 64K conversion
	add	ax, $0x0010		/ bias up to 1MB
	mov	CMOSmax_, ax		/ save count of 64K hunks
	sub	ax, ax			/
	mov	dx, $0x0010		/ Initial 64 Kbyte bank of extended mem.
	mov	holetop_, ax		/ Recorded extended memory bot in bytes.
	mov	holetop_+2, dx		/
					/
	mov	ds, gdtsel_		/ Map DS onto global descr table.
	mov	si, $0xFFF8		/ Define scratch access global selector.
	mov	0(si), $0xFFFF		/	Limit: 64K bytes.
	mov	2(si), $0x0000		/	Base:  1 Mbyte.
	mov	4(si), $0x9210		/	Flags: Present, writable.
	mov	6(si), $0x0000		/
					/
	sub	bx, bx			/
0:	sub	di, di			/ Destination.
	mov	cx, $0x8000		/ 64K bytes, in words.
	mov	2(si), ax		/ Adjust gdt to desired DX:AX mem locn.
	movb	4(si), dl		/
	mov	es, si			/ Map ES onto 64K bank of extended mem.
	mov	es:(di), bx		/ Write word of extended memory.
	jmp	.+2		/ FLUSH	/
	cmp	es:(di), bx		/ Verify word was correctly written.
	jne	0f			/ Branch if memory end.
					/
	cld				/
	rep				/
	stosw				/ Clear this 64K of extended memory.
					/
	inc	dx			/ Step to next 64K bank.
	cmp	dx, ss:CMOSmax_		/ See if we're beyond what the CMOS
	jge	0f			/    says we have.
	cmp	dx, $0x00F0		/ Stop at 15 Mbyte boundary; the last
	jl	0b			/    Mbyte is a dup of the 1st Mbyte.
					/
0:	movb	5(si), $0		/ Free the scratch selector.
					/
	mov	bx, ss			/ Restore data and extra segments.
	mov	ds, bx			/ NOTE: Do not modify DX:AX.
	mov	es, bx			/
					/
	mov	coretop_, ax		/ Recorded top of extended core memory.
	mov	coretop_+2, dx		/
	jmp	start			/ Bring up system.

////////
/
/ Trap an interrupt linkage.
/ Each of the machine traps has a special little
/ linkage, that sets up the type code and sends
/ control off to the common trap processor. Device
/ interrupts, other than the clock (IR0), are
/ done here.
/
////////

trap0:
	call	tsave
	mov	16(bx), $0x0000		/ Divide error.
	jmp	trap_

trap1:
	call	tsave
	mov	16(bx), $0x0100		/ Single step.
	jmp	trap_

trap2:
	call	tsave
	mov	16(bx), $0x0200		/ Non-maskable interrupt.
	jmp	trap_

trap3:
	call	tsave
	mov	16(bx), $0x0300		/ INT 3 (breakpoint).
	jmp	trap_

trap4:
	call	tsave
	mov	16(bx), $0x0400		/ Overflow.
	jmp	trap_

trap5:
	call	tsave
	mov	16(bx), $0x0500		/ Bound check.
	jmp	trap_

trap6:
	call	tsave
	mov	16(bx), $0x0600		/ Invalid opcode.
	jmp	trap_

trap7:
	call	tsave
	mov	16(bx), $0x0700		/ Processor Extension not available.
	jmp	trap_

trap8:
	pop	ax			/ Get error code from stack [always 0]
	call	tsave
	mov	16(bx), $0x0800		/ Double Exception detected
	jmp	trap_

trap9:
	call	tsave
	mov	16(bx), $0x0900		/ Processor extension segment overrun
	jmp	trap_

trap10:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0A00		/ Invalid task state segment
	jmp	trap_

trap11:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0B00		/ Segment not present
	jmp	trap_

trap12:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0C00		/ Stack segment overrun or not present
	jmp	trap_

trap13:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0D00		/ General protection
	jmp	trap_

	.globl	syc

syc:
	call	tsave
	mov	16(bx), $0x2000		/ System calls.
	jmp	trap_

ran:
	call	tsave
	mov	16(bx), $0x2100		/ Random trap.
	jmp	trap_

dev1:
	call	tsave
	mov	16(bx), $0x4001		/ Device 1: keyboard
	ijmp	vecs_+[2*1]

/dev2:	call	tsave			/ Device 2: mapped into device 9
/	mov	16(bx), $0x4002
/	ijmp	vecs_+[2*2]

dev3:
	call	tsave
	mov	16(bx), $0x4003		/ Device 3: al1
	ijmp	vecs_+[2*3]

dev4:
	call	tsave
	mov	16(bx), $0x4004		/ Device 4: al0
	ijmp	vecs_+[2*4]

dev5:
	call	tsave
	mov	16(bx), $0x4005		/ Device 5: hard disk
	ijmp	vecs_+[2*5]

dev6:
	call	tsave
	mov	16(bx), $0x4006		/ Device 6: floppy
	ijmp	vecs_+[2*6]

dev7:
	call	tsave
	mov	16(bx), $0x4007		/ Device 7: lp
	ijmp	vecs_+[2*7]

dev8:
	call	tsave
	mov	16(bx), $0x4008		/ Device 8:
	ijmp	vecs_+[2*8]

dev9:
	call	tsave
	mov	16(bx), $0x4009		/ Device 9:
	ijmp	vecs_+[2*9]

dev10:
	call	tsave
	mov	16(bx), $0x400A		/ Device 10:
	ijmp	vecs_+[2*10]

dev11:
	call	tsave
	mov	16(bx), $0x400B		/ Device 11:
	ijmp	vecs_+[2*11]

dev12:
	call	tsave
	mov	16(bx), $0x400C		/ Device 12:
	ijmp	vecs_+[2*12]

dev13:
	call	tsave
	mov	16(bx), $0x400D		/ Device 13:
	ijmp	vecs_+[2*13]

dev14:
	call	tsave
	mov	16(bx), $0x400E		/ Device 14:
	ijmp	vecs_+[2*14]

dev15:
	call	tsave
	mov	16(bx), $0x400F		/ Device 15:
	ijmp	vecs_+[2*15]

////////
/
/ Clock interrupt.
/ The clock interrupt is stolen from the ROM;
/ if you don't do this the EOI sequence for the 8259
/ may get mangled on context switches.
/
////////

clk:
	call	tsave			/ Perform trap save.
	mov	16(bx), $0x4000

	sub	ax, ax			/ Assume system mode, push user flag
	push	ax
	push	18(bx)			/ IP at tick time

	cmpb	depth_, $0		/ Correct ?
	jne	0f			/ If ne, yes.
	mov	bx, cprocp_		/ User depth, check if the
	test	PFLAGS(bx), $PFKERN	/ current process is a kernel process.
	jne	0f			/ If ne, yes.
	mov	bx, sp			/ Load stack index
	inc	2(bx)			/ and set user mode.

0:	call	clock_			/ Call common clock and
	add	sp, $4			/ pop arguments.

	ret				/ Back to "tsave".

////////
/
/ This routine is called by "tsave" to dismiss an interrupt.
/ The interrupt code is in "ax".
/
////////

	.globl	eoi

eoi:
	cmpb	al, $8			/ Is this on the slave PIC?
	jb	0f			/ Jump if not.
	movb	al, $0x20		/ Send a non specific EOI
	outb	SPIC, al		/ to the slave PIC.
0:	movb	al, $0x20		/ Send a non specific EOI
	outb	PIC, al			/ to the master PIC.
	ret				/ Done.

////////
/
/ Block I/O to ports.
/ Mainly used to read and write the silo memories in the discs.
/ Delibrately only transfers 1 byte per loop to avoid
/ timing problems on AT I/O chips.
/
/ void	outcopy(port, off, seg, n);
/ int	port;			/* Port address */
/ char *off;			/* Offset in segment */
/ unsigned seg;			/* Segment register base */
/ int	n;			/* Byte count */
/ 
/ void	incopy(port, off, seg, n);
/ int	port;			/* Device */
/ char *off;			/* Offset */
/ unsigned seg;			/* Segment register base */
/ int	n;			/* Byte count */
/
////////

	.globl	incopy_
	.globl	outcopy_

incopy_:
	push	di
	push	es
	push	bp
	mov	bp, sp
	mov	dx, 8(bp)		/device port
	les	di, 10(bp)		/seg,off pair
	mov	cx, 14(bp)		/n bytes
	jcxz	1f

	cld				/auto-increment
0:	inb	al, dx
	stosb
	loop	0b

1:	pop	bp
	pop	es			/restore regs
	pop	di
	ret

outcopy_:
	push	si
	push	ds
	push	bp
	mov	bp, sp
	mov	dx, 8(bp)		/device port
	lds	si, 10(bp)		/offset
	mov	cx, 14(bp)		/count
	jcxz	1f

	cld				/auto-increment
0:	lodsb
	outb	dx, al
	loop	0b

1:	pop	bp
	pop	ds
	pop	si
	ret

////////
/
/ Copy "n" bytes of memory from base "p1" to base "p2".
/ The copy must be done from left to right.
/
/ plrcopy(p1, p2, n)
/ paddr_t p1, p2;
/ size_t n;
/
////////

	.globl	plrcopy_

plrcopy_:
	push	si			/ Save sequence
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds
	push	es			/ Save es

	push	18(bp)			/ Map SI:DI at destination ptov(p2,n).
	push	16(bp)
	push	14(bp)
	push	12(bp)
	call	ptov_
	add	sp, $8
	mov	si, dx
	mov	di, ax

	push	18(bp)			/ Map DX:AX at source	ptov(p1,n);
	push	16(bp)
	push	10(bp)
	push	8(bp)
	call	ptov_
	add	sp, $8

	mov	es, si			/ Map ES:DI at destination.
	mov	ds, dx			/ Map DS:SI at source.
	mov	si, ax

	mov	cx, 16(bp)		/ Transfer count in bytes.
	cld				/ Auto Increment.
	clc				/
	rcr	cx, $1			/ Word count
	rep				/
	movsw				/ Move words
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte

	mov	si, es			/ Remember mapped selectors.
	mov	di, ds			/
	pop	es			/ Restore es
	pop	ds			/ Restore ds

	push	si			/ Release mapped selectors.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	push	di			/
	push	ax			/
	call	vrelse_			/
	add	sp, $4			/

	pop	bp			/ Standard return
	pop	di
	pop	si
	ret				/ Return

////////
/
/ Copy "n" bytes of memory from base "p1" to base "p2".
/ The copy must be done from right to left.
/
/ prlcopy(p1, p2, n)
/ paddr_t p1, p2;
/ size_t n;
/
////////

	.globl	prlcopy_

prlcopy_:
	push	si			/ Save sequence
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds
	push	es			/ Save es

	push	18(bp)			/ Map SI:DI at destination ptov(p2,n).
	push	16(bp)
	push	14(bp)
	push	12(bp)
	call	ptov_
	add	sp, $8
	mov	si, dx
	mov	di, ax

	push	18(bp)			/ Map DX:AX at source	ptov(p1,n);
	push	16(bp)
	push	10(bp)
	push	8(bp)
	call	ptov_
	add	sp, $8

	mov	es, si			/ Map ES:DI at destination.
	mov	ds, dx			/ Map DS:SI at source.
	mov	si, ax

	mov	cx, 16(bp)		/ Transfer count in bytes
	add	si, cx			/ Point DS:SI at the end
	dec	si			/ of the source.
	add	di, cx			/ Point ES:DI at the end
	dec	di			/ of the destination.

	std				/ Auto decrement
	clc				/
	rcr	cx, $1			/ Word Count
	rep				/
	movsw				/ Move words
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte
	cld				/ Auto increment

	mov	si, es			/ Remember mapped selectors.
	mov	di, ds			/
	pop	es			/ Restore es
	pop	ds			/ Restore ds

	push	si			/ Release mapped selectors.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	push	di			/
	push	ax			/
	call	vrelse_			/
	add	sp, $4			/
					/
	mov	ax, 16(bp)		/ Return transfer count.
	pop	bp			/ Standard return
	pop	di
	pop	si
	ret

////////
/
/ Clear "n" bytes of memory starting at physical address "p".
/
/ pclear( p, n )
/ paddr_t p;
/ size_t n;
/
/
/	Notes:	At most 64K bytes of memory can be cleared.
/
////////

	.globl	pclear_

pclear_:
	push	si			/ Standard save
	push	di
	push	bp
	mov	bp, sp

	push	es			/ Save es

	push	14(bp)			/ Map ES:DI at ptov(p2,n).
	push	12(bp)
	push	10(bp)
	push	8(bp)
	call	ptov_
	add	sp, $8
	mov	es, dx
	mov	di, ax

	shr	14(bp), $1		/ Convert count from bytes to words.
	rcr	12(bp), $1
	mov	cx, 12(bp)		/ Count in words.

	sub	ax, ax			/ Get a 0.
	cld				/ Zero the block.
	rep
	stosw

	mov	ax, es			/ Remember mapped selector.
	pop	es			/ Restore es.

	push	ax			/ Release mapped selector.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/

	pop	bp			/ Standard return.
	pop	di
	pop	si
	ret

////////
/
/ Block copy chunks of memory to a physical
/ location from a location in either the system
/ or user data space.
/
/ upcopy(u, p, n)
/ char *u;
/ paddr_t p;
/ int n;
/
/ kpcopy(k, p, n);
/ char *k;
/ paddr_t p;
/ int n;
/
////////

	.globl	upcopy_

upcopy_:
	mov	bx, sp			/ Get set for stack index.
	mov	ax, 2(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax, 8(bx)		/ Count
	jc	kuerr			/ Out of bounds
	cmp	ax, udl_		/ In range?
	ja	kuerr			/ No
	push	uds_			/ Mark transfer ds as being user ds.
	jmp	1f			/ Finish in common code.

	.globl	kpcopy_

kpcopy_:
	push	ds			/ Mark transfer ds as being kernel ds.

1:	push	si			/ Standard save
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds, es
	push	es

	sub	ax, ax			/ ES:DI = ptov(p,n).
	push	ax			/
	push	16(bp)			/
	push	14(bp)			/
	push	12(bp)			/
	call	ptov_			/
	add	sp, $8			/
	mov	es, dx			/
	mov	di, ax			/
					/
	mov	ds, 6(bp)		/ DS:SI = source address.
	mov	si, 10(bp)		/
	mov	cx, 16(bp)		/ Byte count
					/
	cld				/ Auto Increment
	clc				/
	rcr	cx, $1			/ Word count
	rep				/
	movsw				/ Move words
	rcl	cx, $1			/ Move odd byte
	rep				/
	movsb				/
					/
	mov	ax, es			/ Remember mapped selector.
	pop	es			/ Restore es, ds.
	pop	ds			/
					/
	push	ax			/ Release mapped selector.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	mov	ax, 16(bp)		/ Return transfer count.
					/
	pop	bp			/ Standard return.
	pop	di
	pop	si
	add	sp, $2			/ Discard marked transfer ds.
	ret

////////
/
/ Block copy memory from physical address "p"
/ to either user or system data space.
/
/ pucopy(p, u, n)
/ paddr_t p;
/ char *u;
/ int n;
/
/ pkcopy(p, k, n);
/ paddr_t p;
/ char *k;
/ int n;
/
////////

	.globl	pucopy_

pucopy_:
	mov	bx, sp			/ Stack index
	mov	ax, 6(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax, 8(bx)		/ Count
	jc	kuerr			/ Out of bounds
	cmp	ax, udl_		/ In range?
	ja	kuerr			/ No
	push	uds_			/ Mark transfer es as being user ds.
	jmp	1f			/ Common code

	.globl	pkcopy_

pkcopy_:
	push	ds			/ Mark transfer es as being kernel ds.

1:	push	si			/ Standard save
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds, es.
	push	es

	sub	ax, ax			/ DS:SI = ptov(p,n).
	push	ax
	push	16(bp)
	push	12(bp)
	push	10(bp)
	call	ptov_
	add	sp, $8
	mov	ds, dx
	mov	si, ax

	mov	es, 6(bp)		/ ES:DI = destination.
	mov	di, 14(bp)		/
	mov	cx, 16(bp)		/ Count

	cld				/ Incremental move
	clc				/
	rcr	cx, $1			/ Word count
	rep				/
	movsw				/ Move words.
	rcl	cx, $1			/ Move odd byte.
	rep				/
	movsb				/
					/
	mov	ax, ds			/ Rememember mapped selector.
	pop	es			/ Restore es, ds.
	pop	ds			/
					/
	push	ax			/ Release mapped selector.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	mov	ax, 16(bp)		/ Return transfer count.
					/
	pop	bp			/ Restore registers.
	pop	di			/
	pop	si			/
	add	sp, $2			/ Discard marked transfer es.
	ret				/ Fin

////////
/
/ All of the above copy routines jump to
/ "kuerr", with the stack untouched, if they detect
/ a bounds error on a user address.
/
////////

kuerr:
	mov	bx,$u_			/ Pointer to user area
	movb	(bx),$EFAULT		/ Bad parameter error
	sub	ax,ax			/ Didn't copy anything
	ret				/ Return

////////
/
/ Read the equipment description. Use
/ the "int 11" interface, so that the IBM
/ ROM will do all the details.
/
////////

	.globl	int11_

int11_:	mov	ax, cs:val11		/ Ask the ROM
	ret				/ to put stuff in AX

////////
/
/ Bootstrap.
/ Called by the keyboard driver on control-alt-del.
/ Requests the 8042 controller to initiate a processor reset,
/ which is the only way to terminate protected mode operation.
/
/	Reference: IBM-AT Technical Reference Manual,
/			Real-time Clock/CMOS RAM [Page 1-45]
/			Keyboard controller [Page 1-40]
/			Test 3, Page 5-68.
/
////////

	.globl	boot_
boot_:
	cli				/ Disable interrupts.
					/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/
	loopne	0b			/
	jmp	.+2		/ DELAY /
					/
	movb	al, $0xFE		/ Issue a shutdown command
	outb	KBCTRL, al		/ to the 8042 control port.
					/
0:	hlt				/ Halt until processor reset occurs.
	jmp	0b

////////
/
/ Data.
/
////////

	.globl	MAXMEM
	.globl	vecs_
	.globl	realmode_
	.globl	gdtsel_, gdtmap_
	.globl	idtsel_, idtmap_
	.globl	CMOSmax_

	.shri
val11:	.word	0			/ Value obtained from int11 [in code].

	.prvd
MAXMEM:	.word	0xA000			/ In paragraphs, must be mult. of 64
CMOSmax_:.word	0x0000			/ Max extended memory according ...
					/ ... to CMOS bytes 0x17 and 0x18 ...
					/ ... in 64K chunks.
realmode_:.word	0			/ Virtual Addressing Mode Enabled
gdtmap_:.blkw	3			/ Global descriptor table definition
idtmap_:.blkw	3			/ Interrupt descriptor table definition
gdtsel_:.word	0			/ Global descriptor table selector
idtsel_:.word	0			/ Interrupt descriptor table selector
vecs_:	.word	vret_			/ Interrupt vector table
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_

////////
/
/ Task State Segment - Coherent runs as a single protected mode task.
/
////////
	.globl	tss_

	.prvd
tss_:				/ Task State Segment.
tss_lnk:.word	0		/  0: Back link selector to TSS.
tss_sp0:.word	0		/  2: SP for CPL 0.
tss_ss0:.word	0		/  4: SS for CPL 0.
tss_sp1:.word	0		/  6: SP for CPL 1.
tss_ss1:.word	0		/  8: SS for CPL 1.
tss_sp2:.word	0		/ 10: SP for CPL 2.
tss_ss2:.word	0		/ 12: SS for CPL 2.
tss_ip:	.word	0		/ 14: IP (Entry point).
tss_psw:.word	0		/ 16: Flag word.
tss_ax:	.word	0		/ 18: Register AX.
tss_cx:	.word	0		/ 20: Register CX.
tss_dx:	.word	0		/ 22: Register DX.
tss_bx:	.word	0		/ 24: Register BX.
tss_bp:	.word	0		/ 26: Register BP.
tss_sp:	.word	0		/ 28: Register SP.
tss_si:	.word	0		/ 30: Register SI.
tss_di:	.word	0		/ 32: Register DI.
tss_es:	.word	0		/ 34: Register ES.
tss_cs:	.word	0		/ 36: Register CS.
tss_ss:	.word	0		/ 38: Register SS.
tss_ds:	.word	0		/ 40: Register DS.
tss_ldt:.word	0		/ 42: Task LDT Selector.
0707070064030104411004440000030000030000011777770507310714100005300000010442/newbits/kernel/USRSRC/i8086/ibm_at/dmac.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * The routines in this file
 * deal with the 8237 programmable
 * DMA controller on the system board.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  09:33:31 	src
 * Initial revision
 * 
 * 86/12/18	Allan Cornish		/usr/src/sys/i8086/ibm_at/dmac.c
 * Full support for DMA channels 5..7 added.
 */
#include	<sys/types.h>
#include	<sys/dmac.h>

/*
 * This table maps channel
 * numbers into DMA page address
 * register ports. The wiring of the
 * RA lines on the 74LS670 is a bit
 * strange.
 */
static	int	dmaport[8] = {
	DMAPAGE+7,			/* 0 (Free) */
	DMAPAGE+3,			/* 1 (Free) */
	DMAPAGE+1,			/* 2 (Floppy) */
	DMAPAGE+2,			/* 3 (Free) */
	DMAPAGE+15,			/* 4 (Cascade) */
	DMAPAGE+11,			/* 5 */
	DMAPAGE+9,			/* 6 */
	DMAPAGE+10			/* 7 */
};

/*
 * Program the channel of the
 * 8237 DMA controller specified by
 * "chan". The "paddr" is a 20 bit
 * physical address. The "count" is
 * the byte count. The "wflag" is
 * true if this is a write, from the
 * point of view of the device.
 * True return if the mapping can be
 * set up, given the 64K limits.
 * The "count" is predecremented, so
 * that backplane "+T/C" is issued at
 * the expected point in time.
 */
dmaon(chan, paddr, count, wflag)
register int	chan;
paddr_t		paddr;
unsigned	count;
{
	register int	port;
	register int	s;

	/*
	 * Change from 0 based transfer count to -1 based.
	 */
	count--;

	/*
	 * Select byte/word transfer.
	 * Channels 0-4 use byte transfer.
	 * Channels 5-7 use word transfers, with low 17 addr bits right shifted.
	 */
	if ( chan >= 5 ) {
		count >>= 1;
		paddr >>= 1;
		paddr  += (paddr & 0xFF0000L);
	}

	/*
	 * Check for DMA straddle.
	 */
	if ( dmaseg(paddr) != dmaseg(paddr+count) )
		return (0);

	s = sphi();

	/*
	 * Select DMA controller.
	 */
	if ( chan < 4 ) {
		port = DMA;

		/*
		 * Program for dma read/write operation.
		 */
		if ( wflag != 0 )
			outb( port + (SETMODE * 1), (chan & 3) | RDMEM );
		else
			outb( port + (SETMODE * 1), (chan & 3) | WRMEM );
		outb( port + (CLEARFL * 1), 0 );
	}
	else {
		port = SDMA;

		/*
		 * Program for dma read/write operation.
		 */
		if ( wflag != 0 )
			outb( SDMA + (SETMODE * 2), (chan & 3) | RDMEM );
		else
			outb( SDMA + (SETMODE * 2), (chan & 3) | WRMEM );
		outb( SDMA + (CLEARFL * 2), 0 );
	}

	/*
	 * Select memory bank.
	 */
	outb( dmaport[chan], (int)(paddr >> 16) );

	if ( chan < 4 )
		port += ((chan & 3) << 1);
	else
		port += ((chan & 3) << 2);

	/*
	 * Program memory offset in bank.
	 */
	outb( port, ((int) paddr) >> 0 );
	outb( port, ((int) paddr) >> 8 );

	port++;
	if ( chan >= 4 )
		port++;

	/*
	 * Program transfer count.
	 */
	outb( port, count >> 0 );
	outb( port, count >> 8 );

	spl(s);
	return (1);
}

/*
 * dmago( chan ) - initiate dma transfer
 */
dmago( chan )
register int chan;
{
	/*
	 * Enable dma transfers.
	 */
	if ( chan < 4 )
		outb( DMA  + (SETMASK * 1), (chan & 3) | MASKOFF );
	else
		outb( SDMA + (SETMASK * 2), (chan & 3) | MASKOFF );
}

/*
 * dmaoff( chan ) - turn dma channel off, return residual count
 */
dmaoff( chan )
register int chan;
{
	register int port;
	register int count;
	int s;

	/*
	 * Disable DMA transfers.
	 * Obtain the -1 based residual count.
	 */
	s = sphi();
	if ( chan < 4 ) {
		outb(  DMA + (SETMASK * 1), (chan & 3) | MASKON );
		port = DMA + ((chan & 3) << 1) + 1;
	}
	else {
		outb(  SDMA + (SETMASK * 2), (chan & 3) | MASKON );
		port = SDMA + ((chan & 3) << 2) + 2;
	}
	count  = inb(port);
	count += inb(port) << 8;
	spl( s );

	/*
	 * Convert residual from -1 based to 0 based.
	 */
	count++;

	/*
	 * Convert residual from word based to byte based.
	 */
	if ( chan >= 5 )
		count <<= 1;

	/*
	 * Return residual count in bytes.
	 */
	return count;
}
0707070064030150001004440000030000030000011777770507310714200005300000011206/newbits/kernel/USRSRC/i8086/ibm_at/dump.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 * Function to dump Kernel data inforation.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:33:35	src
 * Initial revision
 * 
 */
#include <ascii.h>
#include <coherent.h>
#include <sys/i8086.h>
#include <sys/proc.h>
#include <sys/uproc.h>
#include <sys/seg.h>

int nodump = 1;

/*
 * Note: ip1 is a dummy parameter facilitating access to calling stack frame.
 */
dumpall( ip1 )
int ip1;
{
	register PROC * pp;
	register SEG  * sp;
	faddr_t gp;
	faddr_t fp;
	int s;
	extern saddr_t gdtsel;
	extern saddr_t uasa, ucs, uds, scs, sds;
	extern int nesterr;

	if ( nodump )
		return;

	s = sphi();

	printf("\nuasa=%x ucs=%x uds=%x scs=%x sds=%x nesterr=%u\n",
		uasa, ucs, uds, scs, sds, nesterr );


	printf("\nGlobal Descriptor Table:\n");
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = 5;	/* offset of flags byte */
	FP_SEL(fp) = 0;
	FP_OFF(fp) = 0;
	do {
		if ( ffbyte(gp) )
			vprint(fp);
		FP_OFF(gp) += 8;
		FP_SEL(fp) += 8;
	} while ( FP_SEL(fp) != 0 );

	showevq();
	showtim();
	putchar( A_FF );
	
	printf("\nProcesses:\n");
	for ( pp = procq.p_nforw; pp != &procq; pp = pp->p_nforw )
		showproc( pp );
	putchar( A_FF );

	printf( "\nMemory Segments:\n\n" );
	for ( sp = segmq.s_forw; sp != &segmq; sp = sp->s_forw )
		showseg( sp, "" );
	putchar( A_FF );

	if ( segdq.s_forw != &segdq ) {
		printf( "\nDisk Segments:\n\n");
		for ( sp = segdq.s_forw; sp != &segdq; sp = sp->s_forw )
			showseg( sp, "" );
		putchar( A_FF );
	}

	printf("\nLocal Stack: sp=%x\n", (&ip1)-1 );
	FP_SEL(fp) = sds;
	FP_OFF(fp) = (char*)(&u) + 1022;
	do {
		printf("        %x: %x\n", FP_OFF(fp), ffword(fp) );
		FP_OFF(fp)  -= 2;
	} while ( FP_OFF(fp) >= (&ip1)-1 );
	putchar( A_FF );

	printf("\nUser Stack: ss:sp = %x:%x\n", regl[OSS], regl[OSP] );
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = regl[OSS] & ~7;
	if ( ((regl[OSS]&7) == 0) && regl[OSS] && regl[OSP] && ffbyte(gp+5) ) {
		FP_SEL(fp) = regl[OSS];
		FP_OFF(fp) = regl[OSP] + 120;
		if ( FP_OFF(fp) > udl )
			FP_OFF(fp) = udl & ~1;
		do {
			printf("        %x: %x\n", FP_OFF(fp), ffword(fp) );
			FP_OFF(fp)  -= 2;
		} while ( FP_OFF(fp) >= regl[OSP] );
	}
	putchar( A_FF );

	putchar( A_LF );
	spl( s );
}

static
showevq()
{
	register PROC * pp;
	register int i;

	printf("\nEvent Queues:\n");

	for ( i = 0; i < nel(linkq); i++ ) {

		if ( linkq[i].p_lforw == linkq[i].p_lback )
			continue;

		pp = linkq[i].p_lforw;
		printf("%x:", i );

		do {
			printf("\t%x: lforw=%x lback=%x pid=%d event=%x\n",
				pp,
				pp->p_lforw,
				pp->p_lback,
				pp->p_pid,
				pp->p_event
			);
		} while ((pp = pp->p_lforw) != (PROC *) &linkq[i] );
	}
}

static
showtim()
{
	register TIM * tp;
	register int i;

	printf("\nTiming Queues: lbolt=%lx\n", lbolt );

	for ( i = 0; i < nel(timq); i++ ) {

		if ( ! (tp = timq[i]) )
			continue;

		printf("%x:", i );

		do {
		    printf("\t%x: next=%x last=%x func=%x farg=%x lbolt=%lx\n",
			tp,
			tp->t_next,
			tp->t_last,
			tp->t_func,
			tp->t_farg,
			tp->t_lbolt
		    );
		} while ( tp = tp->t_next );
	}
}

static
showproc( pp )
register PROC * pp;
{
	register int i;

	printf("\n%x:\tnforw=%x nback=%x pid=%d ppid=%d state=%x flags=%x\n",
		pp,
		pp->p_nforw,		/* Forward pointer */
		pp->p_nback,		/* Backward pointer */
		pp->p_pid,		/* Process id */
		pp->p_ppid,		/* Process id of parent */
		pp->p_state,
		pp->p_flags
	);

	if ( pp->p_polltim.t_last )
	printf("\tpolltim@%x: next=%x last=%x func=%x farg=%x lbolt=%lx\n",
		&pp->p_polltim,
		pp->p_polltim.t_next,
		pp->p_polltim.t_last,
		pp->p_polltim.t_func,
		pp->p_polltim.t_farg,
		pp->p_polltim.t_lbolt
	);

	if ( pp->p_alrmtim.t_last )
	printf("\talrmtim@%x: next=%x last=%x func=%x farg=%x lbolt=%lx\n",
		&pp->p_alrmtim,
		pp->p_alrmtim.t_next,
		pp->p_alrmtim.t_last,
		pp->p_alrmtim.t_func,
		pp->p_alrmtim.t_farg,
		pp->p_alrmtim.t_lbolt
	);

	for ( i = 0; i <= NUSEG; i++ ) {
	static char * nam[] = {  "UA", "SS", "SI", "PI", "SD",  "PD", "UX" };
		if ( pp->p_segp[i] ) {
			printf("\n    %s: ", nam[i] );
			showseg( pp->p_segp[i], "        " );
		}
	}
}

static
showseg( sp, prefix )
register SEG * sp;
char * prefix;
{
	printf("%x: forw=%x back=%x ip=%x flags=%x urefc=%d lrefc=%d\n",
		sp,
		sp->s_forw,		/* Forward pointer */
		sp->s_back,		/* Backward pointer */
		sp->s_ip,		/* Inode pointer for shared text */
		sp->s_flags,		/* Flags */
		sp->s_urefc,		/* Reference count of segment */
		sp->s_lrefc		/* Lock reference count */
	);

	printf( "%s    faddr=%X size=%X paddr=%X\n",
		prefix,
		sp->s_faddr,		/* Memory access selector */
		sp->s_size,		/* Size in bytes */
		sp->s_paddr		/* Physical base address */
	);

	printf("%s    ", prefix);
	vprint( sp->s_faddr );
}
0707070064030147771004440000030000030000011777770507310714400005200000004442/newbits/kernel/USRSRC/i8086/ibm_at/md2.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * 8086/8088 Coherent.
 * IBM PC.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:33:38	src
 * Initial revision
 * 
 * 87/10/26	Allan Cornish		/usr/src/sys/i8086/ibm_at/md2.c
 * Clrivec() now properly resets the interrupt vector for intr 2 in slot 9.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/clist.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

int nirqslave;
/*
 * Set an interrupt vector.
 * Make an entry in the "vecs" table, for
 * use by the assist. Make sure that the channel
 * on the 8259 is armed.
 * Note that interrupt vectors 2 and 9 are mapped into channel 9.
 */
setivec(level, fun)
register int	level;
int		(*fun)();
{
	register int	picm;
	extern	 int	(*vecs[])();
	extern	 int	vret();

	if ((level &= 0x0F) == 2)
		level = 9;
	if (level==0 || vecs[level]!=&vret) {
		u.u_error = EDBUSY;
		return;
	}
	vecs[level] = fun;
	if ( level >= 8 ) {
		++nirqslave;
		picm = inb(SPICM);
		picm &= ~(0x01 << (level-8));
		outb(SPICM, picm);
		level = 2;
	}
	picm = inb(PICM);
	picm &= ~(0x01 << level);
	outb(PICM, picm);
}

/*
 * Clear an interrupt vector.
 */
clrivec(level)
register int	level;
{
	register int	picm;
	extern	 int	(*vecs[])();
	extern	 int	vret();

	if ((level &= 0x0F) == 2)
		level = 9;
	if (level == 0)
		panic("clrivec: level=%d", level);
	vecs[level] = &vret;
	if (level >= 8) {
		--nirqslave;
		picm = inb(SPICM);
		picm |= (0x01 << (level-8));
		outb(SPICM, picm);
		level = 2;
	}
	if ((level != 2) || (nirqslave == 0)) {
		picm = inb(PICM);
		picm |= (0x01 << level);
		outb(PICM, picm);
	}
}
0707070064030147761004440000030000030000011777770507310714400005200000016532/newbits/kernel/USRSRC/i8086/ibm_at/mmu.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Coherent.
 * Memory Management Unit.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:33:41	src
 * Initial revision
 * 
 * 88/03/04	Allan Cornish	/usr/src/sys/i8086/ibm_at/mmu.c
 * Real-mode code ifdef'ed out [REAL_MODE].
 *
 * 88/02/16	Allan Cornish	/usr/src/sys/i8086/ibm_at/mmu.c
 * vtop() now incorporates offset from virtual address into physical address.
 *
 * 87/11/13	Allan Cornish	/usr/src/sys/i8086/ibm_at/mmu.c
 * Initial version.
 */
#include <sys/coherent.h>
#include <sys/seg.h>
#include <sys/mmu.h>

/**
 *
 * static faddr_t
 * gdtalloc()		-- search for empty global descriptor table entry
 */
static faddr_t
gdtalloc()
{
	register saddr_t sel;
	static saddr_t osel;
	faddr_t fp;
	int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Search for idle virtual selector.
	 */
	for ( fp = 0, sel = osel + 8; sel != osel; sel += 8 ) {

		/*
		 * Selector 0 is NOT usable.
		 */
		if ( sel == 0 )
			continue;

		/*
		 * Selector is available.
		 */
		if ( ffbyte( sel+5, gdtsel ) != 0 )
			continue;

		/*
		 * Mark selector as being Descriptor[10].
		 */
		sfbyte( sel+5, gdtsel, 0x10 );

		/*
		 * Record selector for next search.
		 */
		osel = sel;

		FP_SEL(fp) = sel;
		break;
	}

	/*
	 * Enable interrupts.
	 */
	spl( s );

	return( fp );
}

/**
 *
 * void
 * vprint( fp )			-- print virtual address information.
 * faddr_t fp;
 *
 *	Input:	fp = segment:offset pair for virtual address in question.
 *
 *	Action:	Print information about virtual address.
 */

void
vprint( fp )
faddr_t fp;
{
	faddr_t gp;
	paddr_t paddr;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return;
#endif

	/*
	 * Create far pointer to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp) & ~7;

	FP_OFF(paddr) = ffword(gp+2);
	FP_SEL(paddr) = ffbyte(gp+4);

	/*
	 * Print information about gdt entry.
	 */
	printf("sel=%x paddr=%X lim=%x flags=%x\n",
		FP_OFF(gp), paddr, ffword(gp), ffbyte(gp+5) );
}

/**
 *
 * void
 * vremap( sp )			-- (re)map segment virtual address
 * SEG * sp;
 *
 *	Input:	sp = pointer to segment structure to be (re)mapped.
 *
 *	Action:	Update segment information.
 */
void
vremap( segp )
SEG * segp;
{
	register SEG * sp = segp;
	register int m;
	faddr_t gp;
	int s;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode disabled.
	 */
	if ( gdtsel == 0 ) {
		/*
		 * Calculate virtual address as shifted physical address.
		 */
		FP_SEL(sp->s_faddr) = sp->s_paddr >> 4;
		FP_OFF(sp->s_faddr) = sp->s_paddr & 15;
		return;
	}
#endif

	/*
	 * Create far pointer to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(sp->s_faddr);

	/*
	 * Allocate virtual selector if not already specified.
	 */
	if ( FP_SEL(sp->s_faddr) == 0 )  {
		if ( (sp->s_faddr = gdtalloc()) == 0 )
			panic( "vremap: out of gdt's\n" );
		FP_OFF(gp) = FP_SEL(sp->s_faddr);
	}

	/*
	 * Ensure selector is valid gdt at privilege level 0.
	 */
	if ( FP_SEL(sp->s_faddr) & 7 ) {
		panic("vremap( faddr=%X, ip=%x ) - not gdt at level 0\n",
			sp->s_faddr, (&segp)[-1] );
	}

	/*
	 * Verify selector is not free.
	 */
	if ( ffbyte( gp+5 ) == 0 ) {
		panic("vremap( faddr=%X, ip=%x ) - selector is free\n",
			sp->s_faddr, (&segp)[-1] );
	}

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Set limit.
	 */
	sfword( gp+0, (unsigned) (sp->s_size - 1) );

	/*
	 * Set low word of base, high byte of base.
	 */
	sfword( gp+2, FP_OFF(sp->s_paddr) );
	sfbyte( gp+4, FP_SEL(sp->s_paddr) );

	/*
	 * Set access byte:
	 *	Code = Present[80],Descriptor[10],Executable[08],Readable[02].
	 *	Data = Present[80],Descriptor[10], 		 Writable[02].
	 */
	m = 0x12;
	if ( sp->s_flags & SFCORE )
		m |= 0x80;
	if ( sp->s_flags & SFTEXT )
		m |= 0x08;
	sfbyte( gp+5, m );

	/*
	 * Clear reserved word.
	 */
	sfword( gp+6, 0 );

	/*
	 * Enable interrupts.
	 */
	spl(s);
}

/**
 *
 * faddr_t
 * ptov( paddr, n )		-- physical to virtual [address]
 * paddr_t paddr;
 * fsize_t n;
 *
 *	Input:	paddr = physical address.
 *		n = size in bytes.
 *
 *	Return:	Corresponding segment:offset virtual address, or 0.
 *
 *	Notes:	Limited to 20 bit physical addresses.
 *		This routine is not functional in protected mode.
 */

faddr_t
ptov( paddr, n )
paddr_t paddr;
fsize_t n;
{
	faddr_t fp;
	faddr_t gp;
	int s;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return( ((paddr >> 4) << 16) + (paddr % 16) );
#endif

	/*
	 * Allocate virtual selector.
	 */
	if ( (fp = gdtalloc()) == 0 )
		panic( "ptov:ip=%x: out of gdt's\n", ((char*) &paddr)[-1] );

	/*
	 * Create far pointer to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp);

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Set limit.
	 */
	sfword( gp+0, (unsigned) (n - 1) );

	/*
	 * Set low word of base, high byte of base.
	 */
	sfword( gp+2, FP_OFF(paddr) );
	sfbyte( gp+4, FP_SEL(paddr) );

	/*
	 * Set access byte: Present[80], Descriptor[10], Writable[02].
	 */
	sfbyte( gp+5, 0x92 );

	/*
	 * Clear reserved word.
	 */
	sfword( gp+6, 0 );

	/*
	 * Enable interrupts.
	 */
	spl( s );

	/*
	 * Return virtual address.
	 */
	return( fp );
}

/**
 *
 * paddr_t
 * vtop( fp )			-- virtual to physical [address]
 * faddr_t fp;
 *
 *	Input:	fp = segment:offset virtual address.
 *
 *	Return:	 * = corresponding physical address.
 *		-1 = invalid virtual address.
 */
paddr_t
vtop( fp )
faddr_t fp;
{
	faddr_t gp;
	paddr_t paddr;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return( (FP_SEL(fp) << 4L) + FP_OFF(fp) );
#endif

	/*
	 * Convert virtual address to point to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp);

	/*
	 * Validity check - Selector must be Present[80] and Descriptor[10].
	 */
	if ( (ffbyte(gp+5) & 0x90) != 0x90 ) {
		panic( "vtop:ip=%x: sel %x invalid\n",
			((char **) &fp)[-1],
			FP_SEL(fp) );
	}

	/*
	 * Extract physical address from gdt entry.
	 */
	FP_OFF(paddr) = ffword(gp+2);
	FP_SEL(paddr) = ffbyte(gp+4);

	/*
	 * Adjust physical address by virtual address offset.
	 */
	paddr += FP_OFF(fp);

	/*
	 * Return physical address.
	 */
	return( paddr );
}

/**
 *
 * void
 * vrelse( fp )		-- release virtual address
 * faddr_t fp;
 *
 */

void
vrelse( fp )
faddr_t fp;
{
	faddr_t gp;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return;
#endif

	/*
	 * Validity check.
	 */
	if ( (FP_SEL(fp) == 0) || (FP_SEL(fp) & 7) )
		panic( "vrelse: sel %x invalid\n", FP_SEL(fp) );

	/*
	 * Construct virtual address to point to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp);

	/*
	 * Virtual selector already released, or not a segment descriptor.
	 */
	if ( (ffbyte(gp+5) & 0x10) != 0x10 ) {
		panic( "vrelse:ip=%x: sel %x already released\n",
			((char **) &fp)[-1],
			FP_SEL(fp) );
	}

	/*
	 * Release virtual selector.
	 */
	sfbyte( gp+5, 0 );
}
0707070064030104510407550000030000030000011777770507310714600005000000000000/newbits/kernel/USRSRC/i8086/ibm_at/RCS0707070064030104421004440000030000030000011777770507310714600006100000011310/newbits/kernel/USRSRC/i8086/ibm_at/RCS/dmac.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.41.41;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.35.42;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * The routines in this file
 * deal with the 8237 programmable
 * DMA controller on the system board.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  09:33:31 	src
 * Initial revision
 * 
 * 86/12/18	Allan Cornish		/usr/src/sys/i8086/ibm_at/dmac.c
 * Full support for DMA channels 5..7 added.
 */
#include	<sys/types.h>
#include	<sys/dmac.h>

/*
 * This table maps channel
 * numbers into DMA page address
 * register ports. The wiring of the
 * RA lines on the 74LS670 is a bit
 * strange.
 */
static	int	dmaport[8] = {
	DMAPAGE+7,			/* 0 (Free) */
	DMAPAGE+3,			/* 1 (Free) */
	DMAPAGE+1,			/* 2 (Floppy) */
	DMAPAGE+2,			/* 3 (Free) */
	DMAPAGE+15,			/* 4 (Cascade) */
	DMAPAGE+11,			/* 5 */
	DMAPAGE+9,			/* 6 */
	DMAPAGE+10			/* 7 */
};

/*
 * Program the channel of the
 * 8237 DMA controller specified by
 * "chan". The "paddr" is a 20 bit
 * physical address. The "count" is
 * the byte count. The "wflag" is
 * true if this is a write, from the
 * point of view of the device.
 * True return if the mapping can be
 * set up, given the 64K limits.
 * The "count" is predecremented, so
 * that backplane "+T/C" is issued at
 * the expected point in time.
 */
dmaon(chan, paddr, count, wflag)
register int	chan;
paddr_t		paddr;
unsigned	count;
{
	register int	port;
	register int	s;

	/*
	 * Change from 0 based transfer count to -1 based.
	 */
	count--;

	/*
	 * Select byte/word transfer.
	 * Channels 0-4 use byte transfer.
	 * Channels 5-7 use word transfers, with low 17 addr bits right shifted.
	 */
	if ( chan >= 5 ) {
		count >>= 1;
		paddr >>= 1;
		paddr  += (paddr & 0xFF0000L);
	}

	/*
	 * Check for DMA straddle.
	 */
	if ( dmaseg(paddr) != dmaseg(paddr+count) )
		return (0);

	s = sphi();

	/*
	 * Select DMA controller.
	 */
	if ( chan < 4 ) {
		port = DMA;

		/*
		 * Program for dma read/write operation.
		 */
		if ( wflag != 0 )
			outb( port + (SETMODE * 1), (chan & 3) | RDMEM );
		else
			outb( port + (SETMODE * 1), (chan & 3) | WRMEM );
		outb( port + (CLEARFL * 1), 0 );
	}
	else {
		port = SDMA;

		/*
		 * Program for dma read/write operation.
		 */
		if ( wflag != 0 )
			outb( SDMA + (SETMODE * 2), (chan & 3) | RDMEM );
		else
			outb( SDMA + (SETMODE * 2), (chan & 3) | WRMEM );
		outb( SDMA + (CLEARFL * 2), 0 );
	}

	/*
	 * Select memory bank.
	 */
	outb( dmaport[chan], (int)(paddr >> 16) );

	if ( chan < 4 )
		port += ((chan & 3) << 1);
	else
		port += ((chan & 3) << 2);

	/*
	 * Program memory offset in bank.
	 */
	outb( port, ((int) paddr) >> 0 );
	outb( port, ((int) paddr) >> 8 );

	port++;
	if ( chan >= 4 )
		port++;

	/*
	 * Program transfer count.
	 */
	outb( port, count >> 0 );
	outb( port, count >> 8 );

	spl(s);
	return (1);
}

/*
 * dmago( chan ) - initiate dma transfer
 */
dmago( chan )
register int chan;
{
	/*
	 * Enable dma transfers.
	 */
	if ( chan < 4 )
		outb( DMA  + (SETMASK * 1), (chan & 3) | MASKOFF );
	else
		outb( SDMA + (SETMASK * 2), (chan & 3) | MASKOFF );
}

/*
 * dmaoff( chan ) - turn dma channel off, return residual count
 */
dmaoff( chan )
register int chan;
{
	register int port;
	register int count;
	int s;

	/*
	 * Disable DMA transfers.
	 * Obtain the -1 based residual count.
	 */
	s = sphi();
	if ( chan < 4 ) {
		outb(  DMA + (SETMASK * 1), (chan & 3) | MASKON );
		port = DMA + ((chan & 3) << 1) + 1;
	}
	else {
		outb(  SDMA + (SETMASK * 2), (chan & 3) | MASKON );
		port = SDMA + ((chan & 3) << 2) + 2;
	}
	count  = inb(port);
	count += inb(port) << 8;
	spl( s );

	/*
	 * Convert residual from -1 based to 0 based.
	 */
	count++;

	/*
	 * Convert residual from word based to byte based.
	 */
	if ( chan >= 5 )
		count <<= 1;

	/*
	 * Return residual count in bytes.
	 */
	return count;
}
@


1.1
log
@Initial revision
@
text
@d27 2
a28 2
#include	<types.h>
#include	<dmac.h>
@
0707070064030104531004440000030000030000011777770507310714700006100000011775/newbits/kernel/USRSRC/i8086/ibm_at/RCS/dump.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.41.52;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.35.45;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 * Function to dump Kernel data inforation.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:33:35	src
 * Initial revision
 * 
 */
#include <ascii.h>
#include <coherent.h>
#include <sys/i8086.h>
#include <sys/proc.h>
#include <sys/uproc.h>
#include <sys/seg.h>

int nodump = 1;

/*
 * Note: ip1 is a dummy parameter facilitating access to calling stack frame.
 */
dumpall( ip1 )
int ip1;
{
	register PROC * pp;
	register SEG  * sp;
	faddr_t gp;
	faddr_t fp;
	int s;
	extern saddr_t gdtsel;
	extern saddr_t uasa, ucs, uds, scs, sds;
	extern int nesterr;

	if ( nodump )
		return;

	s = sphi();

	printf("\nuasa=%x ucs=%x uds=%x scs=%x sds=%x nesterr=%u\n",
		uasa, ucs, uds, scs, sds, nesterr );


	printf("\nGlobal Descriptor Table:\n");
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = 5;	/* offset of flags byte */
	FP_SEL(fp) = 0;
	FP_OFF(fp) = 0;
	do {
		if ( ffbyte(gp) )
			vprint(fp);
		FP_OFF(gp) += 8;
		FP_SEL(fp) += 8;
	} while ( FP_SEL(fp) != 0 );

	showevq();
	showtim();
	putchar( A_FF );
	
	printf("\nProcesses:\n");
	for ( pp = procq.p_nforw; pp != &procq; pp = pp->p_nforw )
		showproc( pp );
	putchar( A_FF );

	printf( "\nMemory Segments:\n\n" );
	for ( sp = segmq.s_forw; sp != &segmq; sp = sp->s_forw )
		showseg( sp, "" );
	putchar( A_FF );

	if ( segdq.s_forw != &segdq ) {
		printf( "\nDisk Segments:\n\n");
		for ( sp = segdq.s_forw; sp != &segdq; sp = sp->s_forw )
			showseg( sp, "" );
		putchar( A_FF );
	}

	printf("\nLocal Stack: sp=%x\n", (&ip1)-1 );
	FP_SEL(fp) = sds;
	FP_OFF(fp) = (char*)(&u) + 1022;
	do {
		printf("        %x: %x\n", FP_OFF(fp), ffword(fp) );
		FP_OFF(fp)  -= 2;
	} while ( FP_OFF(fp) >= (&ip1)-1 );
	putchar( A_FF );

	printf("\nUser Stack: ss:sp = %x:%x\n", regl[OSS], regl[OSP] );
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = regl[OSS] & ~7;
	if ( ((regl[OSS]&7) == 0) && regl[OSS] && regl[OSP] && ffbyte(gp+5) ) {
		FP_SEL(fp) = regl[OSS];
		FP_OFF(fp) = regl[OSP] + 120;
		if ( FP_OFF(fp) > udl )
			FP_OFF(fp) = udl & ~1;
		do {
			printf("        %x: %x\n", FP_OFF(fp), ffword(fp) );
			FP_OFF(fp)  -= 2;
		} while ( FP_OFF(fp) >= regl[OSP] );
	}
	putchar( A_FF );

	putchar( A_LF );
	spl( s );
}

static
showevq()
{
	register PROC * pp;
	register int i;

	printf("\nEvent Queues:\n");

	for ( i = 0; i < nel(linkq); i++ ) {

		if ( linkq[i].p_lforw == linkq[i].p_lback )
			continue;

		pp = linkq[i].p_lforw;
		printf("%x:", i );

		do {
			printf("\t%x: lforw=%x lback=%x pid=%d event=%x\n",
				pp,
				pp->p_lforw,
				pp->p_lback,
				pp->p_pid,
				pp->p_event
			);
		} while ((pp = pp->p_lforw) != (PROC *) &linkq[i] );
	}
}

static
showtim()
{
	register TIM * tp;
	register int i;

	printf("\nTiming Queues: lbolt=%lx\n", lbolt );

	for ( i = 0; i < nel(timq); i++ ) {

		if ( ! (tp = timq[i]) )
			continue;

		printf("%x:", i );

		do {
		    printf("\t%x: next=%x last=%x func=%x farg=%x lbolt=%lx\n",
			tp,
			tp->t_next,
			tp->t_last,
			tp->t_func,
			tp->t_farg,
			tp->t_lbolt
		    );
		} while ( tp = tp->t_next );
	}
}

static
showproc( pp )
register PROC * pp;
{
	register int i;

	printf("\n%x:\tnforw=%x nback=%x pid=%d ppid=%d state=%x flags=%x\n",
		pp,
		pp->p_nforw,		/* Forward pointer */
		pp->p_nback,		/* Backward pointer */
		pp->p_pid,		/* Process id */
		pp->p_ppid,		/* Process id of parent */
		pp->p_state,
		pp->p_flags
	);

	if ( pp->p_polltim.t_last )
	printf("\tpolltim@@%x: next=%x last=%x func=%x farg=%x lbolt=%lx\n",
		&pp->p_polltim,
		pp->p_polltim.t_next,
		pp->p_polltim.t_last,
		pp->p_polltim.t_func,
		pp->p_polltim.t_farg,
		pp->p_polltim.t_lbolt
	);

	if ( pp->p_alrmtim.t_last )
	printf("\talrmtim@@%x: next=%x last=%x func=%x farg=%x lbolt=%lx\n",
		&pp->p_alrmtim,
		pp->p_alrmtim.t_next,
		pp->p_alrmtim.t_last,
		pp->p_alrmtim.t_func,
		pp->p_alrmtim.t_farg,
		pp->p_alrmtim.t_lbolt
	);

	for ( i = 0; i <= NUSEG; i++ ) {
	static char * nam[] = {  "UA", "SS", "SI", "PI", "SD",  "PD", "UX" };
		if ( pp->p_segp[i] ) {
			printf("\n    %s: ", nam[i] );
			showseg( pp->p_segp[i], "        " );
		}
	}
}

static
showseg( sp, prefix )
register SEG * sp;
char * prefix;
{
	printf("%x: forw=%x back=%x ip=%x flags=%x urefc=%d lrefc=%d\n",
		sp,
		sp->s_forw,		/* Forward pointer */
		sp->s_back,		/* Backward pointer */
		sp->s_ip,		/* Inode pointer for shared text */
		sp->s_flags,		/* Flags */
		sp->s_urefc,		/* Reference count of segment */
		sp->s_lrefc		/* Lock reference count */
	);

	printf( "%s    faddr=%X size=%X paddr=%X\n",
		prefix,
		sp->s_faddr,		/* Memory access selector */
		sp->s_size,		/* Size in bytes */
		sp->s_paddr		/* Physical base address */
	);

	printf("%s    ", prefix);
	vprint( sp->s_faddr );
}
@


1.1
log
@Initial revision
@
text
@@
0707070064030147551004440000030000030000011777770507310715100006000000005500/newbits/kernel/USRSRC/i8086/ibm_at/RCS/md2.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.41.58;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.35.48;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * 8086/8088 Coherent.
 * IBM PC.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:33:38	src
 * Initial revision
 * 
 * 87/10/26	Allan Cornish		/usr/src/sys/i8086/ibm_at/md2.c
 * Clrivec() now properly resets the interrupt vector for intr 2 in slot 9.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/clist.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

int nirqslave;
/*
 * Set an interrupt vector.
 * Make an entry in the "vecs" table, for
 * use by the assist. Make sure that the channel
 * on the 8259 is armed.
 * Note that interrupt vectors 2 and 9 are mapped into channel 9.
 */
setivec(level, fun)
register int	level;
int		(*fun)();
{
	register int	picm;
	extern	 int	(*vecs[])();
	extern	 int	vret();

	if ((level &= 0x0F) == 2)
		level = 9;
	if (level==0 || vecs[level]!=&vret) {
		u.u_error = EDBUSY;
		return;
	}
	vecs[level] = fun;
	if ( level >= 8 ) {
		++nirqslave;
		picm = inb(SPICM);
		picm &= ~(0x01 << (level-8));
		outb(SPICM, picm);
		level = 2;
	}
	picm = inb(PICM);
	picm &= ~(0x01 << level);
	outb(PICM, picm);
}

/*
 * Clear an interrupt vector.
 */
clrivec(level)
register int	level;
{
	register int	picm;
	extern	 int	(*vecs[])();
	extern	 int	vret();

	if ((level &= 0x0F) == 2)
		level = 9;
	if (level == 0)
		panic("clrivec: level=%d", level);
	vecs[level] = &vret;
	if (level >= 8) {
		--nirqslave;
		picm = inb(SPICM);
		picm |= (0x01 << (level-8));
		outb(SPICM, picm);
		level = 2;
	}
	if ((level != 2) || (nirqslave == 0)) {
		picm = inb(PICM);
		picm |= (0x01 << level);
		outb(PICM, picm);
	}
}
@


1.1
log
@Initial revision
@
text
@d26 3
a28 3
#include <coherent.h>
#include <i8086.h>
#include <clist.h>
d30 3
a32 3
#include <inode.h>
#include <proc.h>
#include <seg.h>
d34 1
a34 1
#include <uproc.h>
@
0707070064030104461004440000030000030000011777770507310715100006000000017361/newbits/kernel/USRSRC/i8086/ibm_at/RCS/mmu.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.42.02;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.35.54;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Coherent.
 * Memory Management Unit.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:33:41	src
 * Initial revision
 * 
 * 88/03/04	Allan Cornish	/usr/src/sys/i8086/ibm_at/mmu.c
 * Real-mode code ifdef'ed out [REAL_MODE].
 *
 * 88/02/16	Allan Cornish	/usr/src/sys/i8086/ibm_at/mmu.c
 * vtop() now incorporates offset from virtual address into physical address.
 *
 * 87/11/13	Allan Cornish	/usr/src/sys/i8086/ibm_at/mmu.c
 * Initial version.
 */
#include <sys/coherent.h>
#include <sys/seg.h>
#include <sys/mmu.h>

/**
 *
 * static faddr_t
 * gdtalloc()		-- search for empty global descriptor table entry
 */
static faddr_t
gdtalloc()
{
	register saddr_t sel;
	static saddr_t osel;
	faddr_t fp;
	int s;

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Search for idle virtual selector.
	 */
	for ( fp = 0, sel = osel + 8; sel != osel; sel += 8 ) {

		/*
		 * Selector 0 is NOT usable.
		 */
		if ( sel == 0 )
			continue;

		/*
		 * Selector is available.
		 */
		if ( ffbyte( sel+5, gdtsel ) != 0 )
			continue;

		/*
		 * Mark selector as being Descriptor[10].
		 */
		sfbyte( sel+5, gdtsel, 0x10 );

		/*
		 * Record selector for next search.
		 */
		osel = sel;

		FP_SEL(fp) = sel;
		break;
	}

	/*
	 * Enable interrupts.
	 */
	spl( s );

	return( fp );
}

/**
 *
 * void
 * vprint( fp )			-- print virtual address information.
 * faddr_t fp;
 *
 *	Input:	fp = segment:offset pair for virtual address in question.
 *
 *	Action:	Print information about virtual address.
 */

void
vprint( fp )
faddr_t fp;
{
	faddr_t gp;
	paddr_t paddr;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return;
#endif

	/*
	 * Create far pointer to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp) & ~7;

	FP_OFF(paddr) = ffword(gp+2);
	FP_SEL(paddr) = ffbyte(gp+4);

	/*
	 * Print information about gdt entry.
	 */
	printf("sel=%x paddr=%X lim=%x flags=%x\n",
		FP_OFF(gp), paddr, ffword(gp), ffbyte(gp+5) );
}

/**
 *
 * void
 * vremap( sp )			-- (re)map segment virtual address
 * SEG * sp;
 *
 *	Input:	sp = pointer to segment structure to be (re)mapped.
 *
 *	Action:	Update segment information.
 */
void
vremap( segp )
SEG * segp;
{
	register SEG * sp = segp;
	register int m;
	faddr_t gp;
	int s;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode disabled.
	 */
	if ( gdtsel == 0 ) {
		/*
		 * Calculate virtual address as shifted physical address.
		 */
		FP_SEL(sp->s_faddr) = sp->s_paddr >> 4;
		FP_OFF(sp->s_faddr) = sp->s_paddr & 15;
		return;
	}
#endif

	/*
	 * Create far pointer to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(sp->s_faddr);

	/*
	 * Allocate virtual selector if not already specified.
	 */
	if ( FP_SEL(sp->s_faddr) == 0 )  {
		if ( (sp->s_faddr = gdtalloc()) == 0 )
			panic( "vremap: out of gdt's\n" );
		FP_OFF(gp) = FP_SEL(sp->s_faddr);
	}

	/*
	 * Ensure selector is valid gdt at privilege level 0.
	 */
	if ( FP_SEL(sp->s_faddr) & 7 ) {
		panic("vremap( faddr=%X, ip=%x ) - not gdt at level 0\n",
			sp->s_faddr, (&segp)[-1] );
	}

	/*
	 * Verify selector is not free.
	 */
	if ( ffbyte( gp+5 ) == 0 ) {
		panic("vremap( faddr=%X, ip=%x ) - selector is free\n",
			sp->s_faddr, (&segp)[-1] );
	}

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Set limit.
	 */
	sfword( gp+0, (unsigned) (sp->s_size - 1) );

	/*
	 * Set low word of base, high byte of base.
	 */
	sfword( gp+2, FP_OFF(sp->s_paddr) );
	sfbyte( gp+4, FP_SEL(sp->s_paddr) );

	/*
	 * Set access byte:
	 *	Code = Present[80],Descriptor[10],Executable[08],Readable[02].
	 *	Data = Present[80],Descriptor[10], 		 Writable[02].
	 */
	m = 0x12;
	if ( sp->s_flags & SFCORE )
		m |= 0x80;
	if ( sp->s_flags & SFTEXT )
		m |= 0x08;
	sfbyte( gp+5, m );

	/*
	 * Clear reserved word.
	 */
	sfword( gp+6, 0 );

	/*
	 * Enable interrupts.
	 */
	spl(s);
}

/**
 *
 * faddr_t
 * ptov( paddr, n )		-- physical to virtual [address]
 * paddr_t paddr;
 * fsize_t n;
 *
 *	Input:	paddr = physical address.
 *		n = size in bytes.
 *
 *	Return:	Corresponding segment:offset virtual address, or 0.
 *
 *	Notes:	Limited to 20 bit physical addresses.
 *		This routine is not functional in protected mode.
 */

faddr_t
ptov( paddr, n )
paddr_t paddr;
fsize_t n;
{
	faddr_t fp;
	faddr_t gp;
	int s;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return( ((paddr >> 4) << 16) + (paddr % 16) );
#endif

	/*
	 * Allocate virtual selector.
	 */
	if ( (fp = gdtalloc()) == 0 )
		panic( "ptov:ip=%x: out of gdt's\n", ((char*) &paddr)[-1] );

	/*
	 * Create far pointer to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp);

	/*
	 * Disable interrupts.
	 */
	s = sphi();

	/*
	 * Set limit.
	 */
	sfword( gp+0, (unsigned) (n - 1) );

	/*
	 * Set low word of base, high byte of base.
	 */
	sfword( gp+2, FP_OFF(paddr) );
	sfbyte( gp+4, FP_SEL(paddr) );

	/*
	 * Set access byte: Present[80], Descriptor[10], Writable[02].
	 */
	sfbyte( gp+5, 0x92 );

	/*
	 * Clear reserved word.
	 */
	sfword( gp+6, 0 );

	/*
	 * Enable interrupts.
	 */
	spl( s );

	/*
	 * Return virtual address.
	 */
	return( fp );
}

/**
 *
 * paddr_t
 * vtop( fp )			-- virtual to physical [address]
 * faddr_t fp;
 *
 *	Input:	fp = segment:offset virtual address.
 *
 *	Return:	 * = corresponding physical address.
 *		-1 = invalid virtual address.
 */
paddr_t
vtop( fp )
faddr_t fp;
{
	faddr_t gp;
	paddr_t paddr;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return( (FP_SEL(fp) << 4L) + FP_OFF(fp) );
#endif

	/*
	 * Convert virtual address to point to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp);

	/*
	 * Validity check - Selector must be Present[80] and Descriptor[10].
	 */
	if ( (ffbyte(gp+5) & 0x90) != 0x90 ) {
		panic( "vtop:ip=%x: sel %x invalid\n",
			((char **) &fp)[-1],
			FP_SEL(fp) );
	}

	/*
	 * Extract physical address from gdt entry.
	 */
	FP_OFF(paddr) = ffword(gp+2);
	FP_SEL(paddr) = ffbyte(gp+4);

	/*
	 * Adjust physical address by virtual address offset.
	 */
	paddr += FP_OFF(fp);

	/*
	 * Return physical address.
	 */
	return( paddr );
}

/**
 *
 * void
 * vrelse( fp )		-- release virtual address
 * faddr_t fp;
 *
 */

void
vrelse( fp )
faddr_t fp;
{
	faddr_t gp;

#if REAL_MODE > 0
	/*
	 * Virtual Address Mode Disabled.
	 */
	if ( gdtsel == 0 )
		return;
#endif

	/*
	 * Validity check.
	 */
	if ( (FP_SEL(fp) == 0) || (FP_SEL(fp) & 7) )
		panic( "vrelse: sel %x invalid\n", FP_SEL(fp) );

	/*
	 * Construct virtual address to point to appropriate gdt entry.
	 */
	FP_SEL(gp) = gdtsel;
	FP_OFF(gp) = FP_SEL(fp);

	/*
	 * Virtual selector already released, or not a segment descriptor.
	 */
	if ( (ffbyte(gp+5) & 0x10) != 0x10 ) {
		panic( "vrelse:ip=%x: sel %x already released\n",
			((char **) &fp)[-1],
			FP_SEL(fp) );
	}

	/*
	 * Release virtual selector.
	 */
	sfbyte( gp+5, 0 );
}
@


1.1
log
@Initial revision
@
text
@d32 1
a32 1
#include <coherent.h>
@
0707070064030104441004440000030000030000011777770507310715400006000000076047/newbits/kernel/USRSRC/i8086/ibm_at/RCS/as2.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    ;
comment  @@;


1.2
date     91.06.06.18.14.46;  author norm;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.06.18.13.16;  author hal;  state Exp;
branches ;
next     ;


desc
@Machine-dependent stuff.
@


1.2
log
@Get memory size by reading CMOS.
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/ (lgl-
/	The information contained herein is a trade secret of Mark Williams
/	Company, and  is confidential information.  It is provided  under a
/	license agreement,  and may be  copied or disclosed  only under the
/	terms of  that agreement.  Any  reproduction or disclosure  of this
/	material without the express written authorization of Mark Williams
/	Company or persuant to the license agreement is unlawful.
/
/	COHERENT Version 2.3.37
/	Copyright (c) 1982, 1983, 1984.
/	An unpublished work by Mark Williams Company, Chicago.
/	All rights reserved.
/ -lgl)
////////
/
/ Machine language assist for
/ Coherent on the IBM personal computer.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.3	88/08/05  15:37:32	src
/ AMD 286 hardware specific fixes removed - hardware now correct.
/ Virtual Selector F000 initialized to access ROM at F0000.
/ Normal kernel stack now used during initialization.
/ 
/ Revision 1.2	88/06/29  19:05:31	src
/ AT Coherent can now come up in real-mode by patching 'realmode' variable.
/ 
/ Revision 1.1	88/03/24  17:33:18	src
/ Initial revision
/ 
/ 88/03/10	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
/ These partial fixes will be removed once all CPU's are replaced.
/
/ 88/03/07	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Obsolete video() function deleted - not used, or usable in protected mode.
/ Auto-increment mode no longer assumed, but enforced on block moves.
/
/ 88/03/04	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Memory sizing now flushes instruction pipeline before read-verify.
/ Otherwise bus capacitance on some machines gives invalid memory indication.
/ plrcopy, prlcopy, pclear, upcopy, kpcopy, pucopy, and pkcopy now ensure
/ registers DS and ES refer to kernel data before calling ptov() or vrelse().
/ MAXMEM variable added to specify maximum low memory in clicks.
/
/ 87/11/22	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Added check for extended memory in protected mode.
/
/ 87/11/14	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ boot() now requests 8042 controller to initiate processor reset.
/
/ 87/11/05	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ slrcopy/srlcopy/sclear renamed plrcopy/prlcopy/pclear and moved here.
/
/ 87/10/27	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ System stack/data segments now setup here rather than in as1.s
/ System stack/data moved to next 128 byte boundary for protected mode.
/
/ 87/08/31	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Timer channel 1 now reprogrammed for memory refresh.
/
/ 87/07/08	Allan Cornish		/usr/src/sys/i8086/ibm_at/as2.s
/ Timer chip now programmed for 100 hz clock interrupt rather than 20 hz.
/
////////

EFAULT	=	14			/ Bad argument
EXTMEML =	0x17			/ Ext. mem size (low) offset in CMOS
EXTMEMH = 	0x18			/               (high)
PFLAGS	=	0x22			/ Offset int PROC.
PFKERN	=	0x80			/ Kernel process flag bit.
PIC	=	0x20			/ 8259 CSR  I/O port.
PICM	=	0x21			/ 8259 IMR  I/O port.
PIT	=	0x40			/ 8253 base I/O port.
KBDATA	=	0x60			/ 8042 keyboard mpu data I/O port.
KBCTRL	=	0x64			/ 8042 keyboard mpu ctrl I/O port.
CMOSA	=	0x70			/ Real-time Clock/CMOS addr I/O port.
CMOSD	=	0x71			/ Real-time Clock/CMOS data I/O port.
SPIC	=	0xA0			/ Slave 8259 CSR I/O port.
SPICM	=	0xA1			/ Slave 8259 IMR I/O port.
UPASIZE	=	1024			/ Size of uproc and stack

////////
/
/ System entry point. Under PC-DOS,
/ which thinks that Coherent is just a large
/ user program, the code is offset by 0x100
/ to allow space for the base page.
/
////////

	.blkb	0x0100			/ PC-DOS base page.
	cli				/ No interrupts, please.

	int	0x11			/ Obtain int 11 value before printf().
	mov	cs:val11, ax		/ Use boot block's stack for last time.

/
/ Enable the A20 address line, which is normally disabled by the ROM BIOS.
/ This line is under the control of the 8042 keyboard interface controller.
/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/
	loopne	0b			/
	jmp	.+2		/ DELAY /
					/
	movb	al, $0xD1		/ Request next output byte to be
	outb	KBCTRL, al		/	sent to the 8042 output port.
					/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/
	loopne	0b			/
	jmp	.+2		/ DELAY /
					/
	movb	al, $0xDF		/ Enable A20 address line.
	outb	KBDATA, al		/ See Page 1-44, IBM-AT Tech Ref.
					/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/ NOTE: A20 not enabled for up to 20 us.
	loopne	0b			/

/
/ Reprogram the 8253 timer so that channel 0, 
/ which is used as the clock, interrupts at exactly
/ 100 HZ, instead of 18.2 HZ.
/
	movb	al, $0x36		/ Timer 0, LSB, MSB, mode 3
	outb	PIT+3, al
	jmp	.+2		/ DELAY /
	jmp	.+2		/ DELAY /
	movb	al, $0x9C		/ Lsb of 59659/5 = 11932
	outb	PIT, al
	jmp	.+2		/ DELAY /
	jmp	.+2		/ DELAY /
	movb	al, $0x2E		/ Msb of 59659/5 = 11932
	outb	PIT, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/

/ Reprogram channel 1 on the 8253 timer which is used for memory refresh.
/	movb	al, $0x54		/ Timer 1, LSB, mode 2
/	outb	PIT+3, al
/	jmp	.+2		/ DELAY	/
/	jmp	.+2		/ DELAY	/
/	movb	al, $18			/ LSB of 18.
/	outb	PIT+1, al
/	jmp	.+2		/ DELAY	/
/	jmp	.+2		/ DELAY	/

/ Reprogram the 1st programmable interrupt controller.
/ It's default vector table collides with iAPX 286 protection vectors.

	movb	al, $0x11		/ ICW1 - edge, master, ICW4
	outb	PIC, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0x20		/ ICW2 - Reserve 1st 32 vectors for 286
	outb	PICM, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0x04		/ ICW3 - master level 2
	outb	PICM, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0x01		/ ICW4 - 8086 mode, master.
	outb	PICM, al
	jmp	.+2		/ DELAY	/
	jmp	.+2		/ DELAY	/
	movb	al, $0xFE		/ Disable interrupts from master PIC.
	outb	PICM, al		/ (except for clock interrupt).

	movb	al, $0xFF
	outb	SPICM, al		/ Disable interrupts from slave PIC.

/ Set up all trap vectors.
/ The machine traps all have their own
/ linkages. We have to steal the clock from
/ the ROM, because the stacks might get switched
/ during the INT 1C, and the EOI would get sent
/ to the 8259 at a strange time.

	sub	ax, ax			/ Map DS over the 8088
	mov	ds, ax			/ vector area.

	mov	0x0000, $trap0		/ Divide error vector
	mov	0x0002, cs
	mov	0x0004, $trap1		/ Single step.
	mov	0x0006, cs
	mov	0x0008, $trap2		/ NMI
	mov	0x000A, cs
	mov	0x000C, $trap3		/ INT 3 (break)
	mov	0x000E, cs
	mov	0x0010, $trap4		/ Overflow.
	mov	0x0012, cs
	mov	0x0014, $trap5		/ Bound range exceeded.
	mov	0x0016, cs
	mov	0x0018, $trap6		/ Invalid Opcode
	mov	0x001A, cs
	mov	0x001C, $trap7		/ Processor extension not available
	mov	0x001E, cs
	mov	0x0020, $trap8		/ Double exception detected.
	mov	0x0022, cs
	mov	0x0024, $trap9		/ Processor extension segment overrun.
	mov	0x0026, cs
	mov	0x0028, $trap10		/ Invalid task state segment.
	mov	0x002A, cs
	mov	0x002C, $trap11		/ Segment not present.
	mov	0x002E, cs
	mov	0x0030, $trap12		/ Stack segment overrun or not present.
	mov	0x0032, cs
	mov	0x0034, $trap13		/ General protection.
	mov	0x0036, cs

	mov	0x0080, $clk		/ Clock.
	mov	0x0082, cs
	mov	0x0084, $dev1		/ Device 1
	mov	0x0086, cs
	mov	0x0088, $dev9		/ Device 2 maps into Device 9
	mov	0x008A, cs
	mov	0x008C, $dev3		/ Device 3
	mov	0x008E, cs
	mov	0x0090, $dev4		/ Device 4
	mov	0x0092, cs
	mov	0x0094, $dev5		/ Device 5
	mov	0x0096, cs
	mov	0x0098, $dev6		/ Device 6
	mov	0x009A, cs
	mov	0x009C, $dev7		/ Device 7
	mov	0x009E, cs

	mov	0x01C0, $dev8		/ Device 8
	mov	0x01C2, cs
	mov	0x01C4, $dev9		/ Device 9
	mov	0x01C6, cs
	mov	0x01C8, $dev10		/ Device 10
	mov	0x01CA, cs
	mov	0x01CC, $dev11		/ Device 11
	mov	0x01CE, cs
	mov	0x01D0, $dev12		/ Device 12
	mov	0x01D2, cs
	mov	0x01D4, $dev13		/ Device 13
	mov	0x01D6, cs
	mov	0x01D8, $dev14		/ Device 14
	mov	0x01DA, cs
	mov	0x01DC, $dev15		/ Device 15
	mov	0x01DE, cs

	mov	bx, $0x0200		/ INT 80 (sys 0)
0:	mov	(bx), $syc		/ Set up the system call
	mov	2(bx), cs		/ trap vector.
	add	bx, $4			/ Move to next vector and
	cmp	bx, $0x0400		/ loop until all
	jb	0b			/ vectors are reset.

/ Set up the system stack and data segments, by looking at the size of
/ the text and adding this to the base address already in the CS.
/ Relocate the stack and data to a 128 byte boundary.

	mov	ax, $etext_+15		/ End of text segment
	shr	ax, $4			/ Convert to paragraphs.
	mov	cx, cs			/ Get code segment base.
	add	ax, cx			/
	mov	ds, ax			/ Current data segment
	add	ax, $31			/ Allow virtual-physical alignment
	and	ax, $~31		/	[use 512 byte, need 128 byte]
					/
	cmp	realmode_, $0		/ Virtual Addressing enabled?
	jne	0f			/
	mov	idtsel_, ax		/ Interrupt descriptor table [2 Kbytes]
	add	ax, $0x0080		/	2K >> 4
	mov	gdtsel_, ax		/ Global descriptor table [64 Kbytes]
	add	ax, $0x1000		/	64K >> 4
0:					/
	mov	es, ax			/
	mov	si, $edata_-1		/ Copy data to new location, backwards.
	mov	di, $edata_-1		/
	mov	cx, $edata_		/
	std				/
	rep				/
	movsb				/
					/
	mov	ds, ax			/ Update data segment,
	mov	ss, ax			/ and stack segment.
	mov	sp, $u_+UPASIZE-32	/ Set up initial stack.
	mov	scs_, cs		/ Save code segment and
	mov	sds_, ds		/ data segment bases.
	mov	cs:cds, ds		/ For interrupts.

/ Size up memory, starting just above the system.
/ The memory is cleared, because somebody has to do a write
/ to set up the parity bits.

	mov	di, $edata_		/ Clear at edata...
	mov	cx, $512		/ for 1 Kbyte
	sub	ax, ax
	cld
	rep
	stosw

	mov	bp, $edata_+1023	/ Compute base.
	shr	bp, $4
	add	bp, sds_
	shr	bp, $6			/ Round down to a Kbyte boundary
	shl	bp, $6			/ so's we're in sync.

0:	sub	di, di			/ Destination.
	mov	es, bp			/ Set extra segment and
	mov	es:(di), ax		/ clear a word.
	jmp	.+2		/ FLUSH	/
	cmp	es:(di), ax		/ Should be zero now.
	jne	0f			/ Branch if memory end

	mov	cx, $512		/ 1K bytes, in words.
	cld
	rep
	stosw				/ Clear this 1K
	add	bp, $64			/ Move along by 1K
	cmp	bp, MAXMEM
	jb	0b			/ If not at video ram yet

0:	mov	es, sds_		/ Map extra.

	mov	ax, bp			/ Calculate top of low memory.
	rol	ax, $4			/
	mov	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/

	cmp	realmode_, $0		/ Real Addressing Mode?
	je	0f			/
	mov	coretop_, ax		/ Yes, Record top of memory,
	mov	coretop_+2, dx		/
	jmp	start			/ and bring up system.
0:
	mov	holebot_, ax		/ Record bottom of I/O memory.
	mov	holebot_+2, dx		/

	mov	ax, gdtsel_		/ Format global descriptor table map.
	rol	ax, $4			/
	mov	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/
	mov	gdtmap_+0, $0xFFFF	/ Limit: 64K bytes.
	mov	gdtmap_+2, ax		/
	mov	gdtmap_+4, dx		/
					/
	sub	ax, ax			/ Erase global descriptor table.
	mov	cx, $0x8000		/	[32K words = 64K bytes]
	mov	es, gdtsel_		/
	sub	di, di			/
	cld				/
	rep				/
	stosw				/
					/
	mov	ax, idtsel_		/ Format interrupt descriptor table map
	rol	ax, $4			/
	mov	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/
	mov	idtmap_+0, $2047	/ Limit: 2K bytes.
	mov	idtmap_+2, ax		/
	mov	idtmap_+4, dx		/
					/
	sub	ax, ax			/ Erase interrupt descriptor table.
	mov	cx, $1024		/	[1K words = 2K bytes]
	mov	es, idtsel_		/
	sub	di, di			/
	cld				/
	rep				/
	stosw				/
					/
	mov	es, gdtsel_		/
	mov	di, cs			/ Define kernel code global selector.
	mov	ax, $etext_-1		/	Limit: etext.
	stosw				/
	mov	dx, $0x9A00		/	Flags: Present, executable.
	mov	ax, cs			/	Base:  cs << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, ss			/ Define kernel data global selector.
	mov	ax, $0xFFFF		/	Limit: 64K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, ss			/	Base:  ss << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, $8			/ Define task state segment selector[8]
	mov	ax, $43			/	Limit: 44 bytes.
	stosw				/
	mov	dx, $0x8100		/	Flags: Present, avail tss seg.
	mov	ax, ss			/	Base:  (ss << 4) + &tss.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	xor	dx, ax			/
	add	ax, $tss_		/
	adc	dx, $0			/
	stosw				/
	mov	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, gdtsel_		/ Define gdt access global selector.
	mov	ax, $0xFFFF		/	Limit: 64K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, gdtsel_		/	Base: gdtsel << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, idtsel_		/ Define idt access global selector.
	mov	ax, $2047		/	Limit: 2K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, idtsel_		/	Base: idtsel << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, $0xB000		/ Define video access global selector.
	mov	ax, $0xFFFF		/	Limit: 64K bytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, $0xB000		/	Base:  0xB000 << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/
					/
	mov	di, $0xB800		/ Define video access global selector.
	mov	ax, $0x7FFF		/	Limit: 32 Kbytes.
	stosw				/
	mov	dx, $0x9200		/	Flags: Present, writable.
	mov	ax, $0xB800		/	Base:  0xB800 << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/

	mov	di, $0xF000		/ Define ROM access global selector.
	mov	ax, $0xFFFF		/	Limit: 64 Kbytes.
	stosw				/
	mov	dx, $0x9000		/	Flags: Present, read only.
	mov	ax, $0xF000		/	Base:  0xF000 << 4.
	rol	ax, $4			/
	xor	dx, ax			/
	and	ax, $0xFFF0		/
	stosw				/
	xor	ax, dx			/
	stosw				/
	sub	ax, ax			/
	stosw				/

	mov	es, idtsel_		/ Map ES over the intr descr table.
	sub	ax, ax			/ Map DS over the 8088 vector area.
	mov	ds, ax			/
	sub	si, si			/
	sub	di, di			/
	mov	bx, cs			/ Make CS available for comparison.
	mov	cx, $256		/ Install 256 interrupt descriptors.
					/
0:	lodsw				/ Copy interrupt IP
	stosw				/
	lodsw				/ Copy interrupt CS
	stosw				/
					/
	cmp	ax, bx			/ Coherent interrupt handler?
	mov	ax, $0x8600		/
	je	1f			/
	sub	ax, ax			/ No, clear flags.
					/
1:	stosw				/ Define IDT flags.
	sub	ax, ax			/ Reserved IDT word.
	stosw				/
	loop	0b			/ Repeat for all 256 entries.
					/
	mov	ax, ss			/ Restore data and extra segments.
	mov	ds, ax			/
	mov	es, ax			/
					/
	clts				/ Clear task switched flag.
	lgdt	gdtmap_			/ Load global descriptor table map.
	lidt	idtmap_			/ Load interrupt descriptor table map.
					/
	smsw	ax			/ Enter protected mode.
	or	ax, $1			/
	lmsw	ax			/
	jmp	.+2			/ Clear pipeline.
					/
	mov	ax, $0x0008		/ Load task state segment register.
	ltr	ax			/
	sub	ax, ax			/ Load local descriptor table register.
	lldt	ax			/
					/
					/
					/ Register usage:
					/ DX:AX = extended mem physical addr.
					/ BX = 0.
					/ SI = selector into extended memory.
					/ ES = selector into extended memory.
					/ DS = selector into global descr table
					/
	movb	al, $EXTMEMH		/ high byte of pair
	outb	CMOSA, al		/ to CMOS memory port
	jmp	.+2			/ DELAY
	inb	al, CMOSD		/ get value from CMOS
	xchgb	ah, al
	jmp	.+2			/ DELAY
	movb	al, $EXTMEML		/ low byte of pair
	outb	CMOSA, al		/ to CMOS memory port
	jmp	.+2			/ DELAY
	inb	al, CMOSD		/ get rest of pair from CMOS
	shr	ax, $6			/ K -> 64K conversion
	add	ax, $0x0010		/ bias up to 1MB
	mov	CMOSmax_, ax		/ save count of 64K hunks
	sub	ax, ax			/
	mov	dx, $0x0010		/ Initial 64 Kbyte bank of extended mem.
	mov	holetop_, ax		/ Recorded extended memory bot in bytes.
	mov	holetop_+2, dx		/
					/
	mov	ds, gdtsel_		/ Map DS onto global descr table.
	mov	si, $0xFFF8		/ Define scratch access global selector.
	mov	0(si), $0xFFFF		/	Limit: 64K bytes.
	mov	2(si), $0x0000		/	Base:  1 Mbyte.
	mov	4(si), $0x9210		/	Flags: Present, writable.
	mov	6(si), $0x0000		/
					/
	sub	bx, bx			/
0:	sub	di, di			/ Destination.
	mov	cx, $0x8000		/ 64K bytes, in words.
	mov	2(si), ax		/ Adjust gdt to desired DX:AX mem locn.
	movb	4(si), dl		/
	mov	es, si			/ Map ES onto 64K bank of extended mem.
	mov	es:(di), bx		/ Write word of extended memory.
	jmp	.+2		/ FLUSH	/
	cmp	es:(di), bx		/ Verify word was correctly written.
	jne	0f			/ Branch if memory end.
					/
	cld				/
	rep				/
	stosw				/ Clear this 64K of extended memory.
					/
	inc	dx			/ Step to next 64K bank.
	cmp	dx, ss:CMOSmax_		/ See if we're beyond what the CMOS
	jge	0f			/    says we have.
	cmp	dx, $0x00F0		/ Stop at 15 Mbyte boundary; the last
	jl	0b			/    Mbyte is a dup of the 1st Mbyte.
					/
0:	movb	5(si), $0		/ Free the scratch selector.
					/
	mov	bx, ss			/ Restore data and extra segments.
	mov	ds, bx			/ NOTE: Do not modify DX:AX.
	mov	es, bx			/
					/
	mov	coretop_, ax		/ Recorded top of extended core memory.
	mov	coretop_+2, dx		/
	jmp	start			/ Bring up system.

////////
/
/ Trap an interrupt linkage.
/ Each of the machine traps has a special little
/ linkage, that sets up the type code and sends
/ control off to the common trap processor. Device
/ interrupts, other than the clock (IR0), are
/ done here.
/
////////

trap0:
	call	tsave
	mov	16(bx), $0x0000		/ Divide error.
	jmp	trap_

trap1:
	call	tsave
	mov	16(bx), $0x0100		/ Single step.
	jmp	trap_

trap2:
	call	tsave
	mov	16(bx), $0x0200		/ Non-maskable interrupt.
	jmp	trap_

trap3:
	call	tsave
	mov	16(bx), $0x0300		/ INT 3 (breakpoint).
	jmp	trap_

trap4:
	call	tsave
	mov	16(bx), $0x0400		/ Overflow.
	jmp	trap_

trap5:
	call	tsave
	mov	16(bx), $0x0500		/ Bound check.
	jmp	trap_

trap6:
	call	tsave
	mov	16(bx), $0x0600		/ Invalid opcode.
	jmp	trap_

trap7:
	call	tsave
	mov	16(bx), $0x0700		/ Processor Extension not available.
	jmp	trap_

trap8:
	pop	ax			/ Get error code from stack [always 0]
	call	tsave
	mov	16(bx), $0x0800		/ Double Exception detected
	jmp	trap_

trap9:
	call	tsave
	mov	16(bx), $0x0900		/ Processor extension segment overrun
	jmp	trap_

trap10:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0A00		/ Invalid task state segment
	jmp	trap_

trap11:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0B00		/ Segment not present
	jmp	trap_

trap12:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0C00		/ Stack segment overrun or not present
	jmp	trap_

trap13:
	pop	ax			/ Get error code from stack
	call	tsave
	mov	16(bx), $0x0D00		/ General protection
	jmp	trap_

	.globl	syc

syc:
	call	tsave
	mov	16(bx), $0x2000		/ System calls.
	jmp	trap_

ran:
	call	tsave
	mov	16(bx), $0x2100		/ Random trap.
	jmp	trap_

dev1:
	call	tsave
	mov	16(bx), $0x4001		/ Device 1: keyboard
	ijmp	vecs_+[2*1]

/dev2:	call	tsave			/ Device 2: mapped into device 9
/	mov	16(bx), $0x4002
/	ijmp	vecs_+[2*2]

dev3:
	call	tsave
	mov	16(bx), $0x4003		/ Device 3: al1
	ijmp	vecs_+[2*3]

dev4:
	call	tsave
	mov	16(bx), $0x4004		/ Device 4: al0
	ijmp	vecs_+[2*4]

dev5:
	call	tsave
	mov	16(bx), $0x4005		/ Device 5: hard disk
	ijmp	vecs_+[2*5]

dev6:
	call	tsave
	mov	16(bx), $0x4006		/ Device 6: floppy
	ijmp	vecs_+[2*6]

dev7:
	call	tsave
	mov	16(bx), $0x4007		/ Device 7: lp
	ijmp	vecs_+[2*7]

dev8:
	call	tsave
	mov	16(bx), $0x4008		/ Device 8:
	ijmp	vecs_+[2*8]

dev9:
	call	tsave
	mov	16(bx), $0x4009		/ Device 9:
	ijmp	vecs_+[2*9]

dev10:
	call	tsave
	mov	16(bx), $0x400A		/ Device 10:
	ijmp	vecs_+[2*10]

dev11:
	call	tsave
	mov	16(bx), $0x400B		/ Device 11:
	ijmp	vecs_+[2*11]

dev12:
	call	tsave
	mov	16(bx), $0x400C		/ Device 12:
	ijmp	vecs_+[2*12]

dev13:
	call	tsave
	mov	16(bx), $0x400D		/ Device 13:
	ijmp	vecs_+[2*13]

dev14:
	call	tsave
	mov	16(bx), $0x400E		/ Device 14:
	ijmp	vecs_+[2*14]

dev15:
	call	tsave
	mov	16(bx), $0x400F		/ Device 15:
	ijmp	vecs_+[2*15]

////////
/
/ Clock interrupt.
/ The clock interrupt is stolen from the ROM;
/ if you don't do this the EOI sequence for the 8259
/ may get mangled on context switches.
/
////////

clk:
	call	tsave			/ Perform trap save.
	mov	16(bx), $0x4000

	sub	ax, ax			/ Assume system mode, push user flag
	push	ax
	push	18(bx)			/ IP at tick time

	cmpb	depth_, $0		/ Correct ?
	jne	0f			/ If ne, yes.
	mov	bx, cprocp_		/ User depth, check if the
	test	PFLAGS(bx), $PFKERN	/ current process is a kernel process.
	jne	0f			/ If ne, yes.
	mov	bx, sp			/ Load stack index
	inc	2(bx)			/ and set user mode.

0:	call	clock_			/ Call common clock and
	add	sp, $4			/ pop arguments.

	ret				/ Back to "tsave".

////////
/
/ This routine is called by "tsave" to dismiss an interrupt.
/ The interrupt code is in "ax".
/
////////

	.globl	eoi

eoi:
	cmpb	al, $8			/ Is this on the slave PIC?
	jb	0f			/ Jump if not.
	movb	al, $0x20		/ Send a non specific EOI
	outb	SPIC, al		/ to the slave PIC.
0:	movb	al, $0x20		/ Send a non specific EOI
	outb	PIC, al			/ to the master PIC.
	ret				/ Done.

////////
/
/ Block I/O to ports.
/ Mainly used to read and write the silo memories in the discs.
/ Delibrately only transfers 1 byte per loop to avoid
/ timing problems on AT I/O chips.
/
/ void	outcopy(port, off, seg, n);
/ int	port;			/* Port address */
/ char *off;			/* Offset in segment */
/ unsigned seg;			/* Segment register base */
/ int	n;			/* Byte count */
/ 
/ void	incopy(port, off, seg, n);
/ int	port;			/* Device */
/ char *off;			/* Offset */
/ unsigned seg;			/* Segment register base */
/ int	n;			/* Byte count */
/
////////

	.globl	incopy_
	.globl	outcopy_

incopy_:
	push	di
	push	es
	push	bp
	mov	bp, sp
	mov	dx, 8(bp)		/device port
	les	di, 10(bp)		/seg,off pair
	mov	cx, 14(bp)		/n bytes
	jcxz	1f

	cld				/auto-increment
0:	inb	al, dx
	stosb
	loop	0b

1:	pop	bp
	pop	es			/restore regs
	pop	di
	ret

outcopy_:
	push	si
	push	ds
	push	bp
	mov	bp, sp
	mov	dx, 8(bp)		/device port
	lds	si, 10(bp)		/offset
	mov	cx, 14(bp)		/count
	jcxz	1f

	cld				/auto-increment
0:	lodsb
	outb	dx, al
	loop	0b

1:	pop	bp
	pop	ds
	pop	si
	ret

////////
/
/ Copy "n" bytes of memory from base "p1" to base "p2".
/ The copy must be done from left to right.
/
/ plrcopy(p1, p2, n)
/ paddr_t p1, p2;
/ size_t n;
/
////////

	.globl	plrcopy_

plrcopy_:
	push	si			/ Save sequence
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds
	push	es			/ Save es

	push	18(bp)			/ Map SI:DI at destination ptov(p2,n).
	push	16(bp)
	push	14(bp)
	push	12(bp)
	call	ptov_
	add	sp, $8
	mov	si, dx
	mov	di, ax

	push	18(bp)			/ Map DX:AX at source	ptov(p1,n);
	push	16(bp)
	push	10(bp)
	push	8(bp)
	call	ptov_
	add	sp, $8

	mov	es, si			/ Map ES:DI at destination.
	mov	ds, dx			/ Map DS:SI at source.
	mov	si, ax

	mov	cx, 16(bp)		/ Transfer count in bytes.
	cld				/ Auto Increment.
	clc				/
	rcr	cx, $1			/ Word count
	rep				/
	movsw				/ Move words
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte

	mov	si, es			/ Remember mapped selectors.
	mov	di, ds			/
	pop	es			/ Restore es
	pop	ds			/ Restore ds

	push	si			/ Release mapped selectors.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	push	di			/
	push	ax			/
	call	vrelse_			/
	add	sp, $4			/

	pop	bp			/ Standard return
	pop	di
	pop	si
	ret				/ Return

////////
/
/ Copy "n" bytes of memory from base "p1" to base "p2".
/ The copy must be done from right to left.
/
/ prlcopy(p1, p2, n)
/ paddr_t p1, p2;
/ size_t n;
/
////////

	.globl	prlcopy_

prlcopy_:
	push	si			/ Save sequence
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds
	push	es			/ Save es

	push	18(bp)			/ Map SI:DI at destination ptov(p2,n).
	push	16(bp)
	push	14(bp)
	push	12(bp)
	call	ptov_
	add	sp, $8
	mov	si, dx
	mov	di, ax

	push	18(bp)			/ Map DX:AX at source	ptov(p1,n);
	push	16(bp)
	push	10(bp)
	push	8(bp)
	call	ptov_
	add	sp, $8

	mov	es, si			/ Map ES:DI at destination.
	mov	ds, dx			/ Map DS:SI at source.
	mov	si, ax

	mov	cx, 16(bp)		/ Transfer count in bytes
	add	si, cx			/ Point DS:SI at the end
	dec	si			/ of the source.
	add	di, cx			/ Point ES:DI at the end
	dec	di			/ of the destination.

	std				/ Auto decrement
	clc				/
	rcr	cx, $1			/ Word Count
	rep				/
	movsw				/ Move words
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte
	cld				/ Auto increment

	mov	si, es			/ Remember mapped selectors.
	mov	di, ds			/
	pop	es			/ Restore es
	pop	ds			/ Restore ds

	push	si			/ Release mapped selectors.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	push	di			/
	push	ax			/
	call	vrelse_			/
	add	sp, $4			/
					/
	mov	ax, 16(bp)		/ Return transfer count.
	pop	bp			/ Standard return
	pop	di
	pop	si
	ret

////////
/
/ Clear "n" bytes of memory starting at physical address "p".
/
/ pclear( p, n )
/ paddr_t p;
/ size_t n;
/
/
/	Notes:	At most 64K bytes of memory can be cleared.
/
////////

	.globl	pclear_

pclear_:
	push	si			/ Standard save
	push	di
	push	bp
	mov	bp, sp

	push	es			/ Save es

	push	14(bp)			/ Map ES:DI at ptov(p2,n).
	push	12(bp)
	push	10(bp)
	push	8(bp)
	call	ptov_
	add	sp, $8
	mov	es, dx
	mov	di, ax

	shr	14(bp), $1		/ Convert count from bytes to words.
	rcr	12(bp), $1
	mov	cx, 12(bp)		/ Count in words.

	sub	ax, ax			/ Get a 0.
	cld				/ Zero the block.
	rep
	stosw

	mov	ax, es			/ Remember mapped selector.
	pop	es			/ Restore es.

	push	ax			/ Release mapped selector.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/

	pop	bp			/ Standard return.
	pop	di
	pop	si
	ret

////////
/
/ Block copy chunks of memory to a physical
/ location from a location in either the system
/ or user data space.
/
/ upcopy(u, p, n)
/ char *u;
/ paddr_t p;
/ int n;
/
/ kpcopy(k, p, n);
/ char *k;
/ paddr_t p;
/ int n;
/
////////

	.globl	upcopy_

upcopy_:
	mov	bx, sp			/ Get set for stack index.
	mov	ax, 2(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax, 8(bx)		/ Count
	jc	kuerr			/ Out of bounds
	cmp	ax, udl_		/ In range?
	ja	kuerr			/ No
	push	uds_			/ Mark transfer ds as being user ds.
	jmp	1f			/ Finish in common code.

	.globl	kpcopy_

kpcopy_:
	push	ds			/ Mark transfer ds as being kernel ds.

1:	push	si			/ Standard save
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds, es
	push	es

	sub	ax, ax			/ ES:DI = ptov(p,n).
	push	ax			/
	push	16(bp)			/
	push	14(bp)			/
	push	12(bp)			/
	call	ptov_			/
	add	sp, $8			/
	mov	es, dx			/
	mov	di, ax			/
					/
	mov	ds, 6(bp)		/ DS:SI = source address.
	mov	si, 10(bp)		/
	mov	cx, 16(bp)		/ Byte count
					/
	cld				/ Auto Increment
	clc				/
	rcr	cx, $1			/ Word count
	rep				/
	movsw				/ Move words
	rcl	cx, $1			/ Move odd byte
	rep				/
	movsb				/
					/
	mov	ax, es			/ Remember mapped selector.
	pop	es			/ Restore es, ds.
	pop	ds			/
					/
	push	ax			/ Release mapped selector.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	mov	ax, 16(bp)		/ Return transfer count.
					/
	pop	bp			/ Standard return.
	pop	di
	pop	si
	add	sp, $2			/ Discard marked transfer ds.
	ret

////////
/
/ Block copy memory from physical address "p"
/ to either user or system data space.
/
/ pucopy(p, u, n)
/ paddr_t p;
/ char *u;
/ int n;
/
/ pkcopy(p, k, n);
/ paddr_t p;
/ char *k;
/ int n;
/
////////

	.globl	pucopy_

pucopy_:
	mov	bx, sp			/ Stack index
	mov	ax, 6(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax, 8(bx)		/ Count
	jc	kuerr			/ Out of bounds
	cmp	ax, udl_		/ In range?
	ja	kuerr			/ No
	push	uds_			/ Mark transfer es as being user ds.
	jmp	1f			/ Common code

	.globl	pkcopy_

pkcopy_:
	push	ds			/ Mark transfer es as being kernel ds.

1:	push	si			/ Standard save
	push	di
	push	bp
	mov	bp, sp

	push	ds			/ Save ds, es.
	push	es

	sub	ax, ax			/ DS:SI = ptov(p,n).
	push	ax
	push	16(bp)
	push	12(bp)
	push	10(bp)
	call	ptov_
	add	sp, $8
	mov	ds, dx
	mov	si, ax

	mov	es, 6(bp)		/ ES:DI = destination.
	mov	di, 14(bp)		/
	mov	cx, 16(bp)		/ Count

	cld				/ Incremental move
	clc				/
	rcr	cx, $1			/ Word count
	rep				/
	movsw				/ Move words.
	rcl	cx, $1			/ Move odd byte.
	rep				/
	movsb				/
					/
	mov	ax, ds			/ Rememember mapped selector.
	pop	es			/ Restore es, ds.
	pop	ds			/
					/
	push	ax			/ Release mapped selector.
	push	ax			/ NOTE: Offset is ignored.
	call	vrelse_			/
	add	sp, $4			/
					/
	mov	ax, 16(bp)		/ Return transfer count.
					/
	pop	bp			/ Restore registers.
	pop	di			/
	pop	si			/
	add	sp, $2			/ Discard marked transfer es.
	ret				/ Fin

////////
/
/ All of the above copy routines jump to
/ "kuerr", with the stack untouched, if they detect
/ a bounds error on a user address.
/
////////

kuerr:
	mov	bx,$u_			/ Pointer to user area
	movb	(bx),$EFAULT		/ Bad parameter error
	sub	ax,ax			/ Didn't copy anything
	ret				/ Return

////////
/
/ Read the equipment description. Use
/ the "int 11" interface, so that the IBM
/ ROM will do all the details.
/
////////

	.globl	int11_

int11_:	mov	ax, cs:val11		/ Ask the ROM
	ret				/ to put stuff in AX

////////
/
/ Bootstrap.
/ Called by the keyboard driver on control-alt-del.
/ Requests the 8042 controller to initiate a processor reset,
/ which is the only way to terminate protected mode operation.
/
/	Reference: IBM-AT Technical Reference Manual,
/			Real-time Clock/CMOS RAM [Page 1-45]
/			Keyboard controller [Page 1-40]
/			Test 3, Page 5-68.
/
////////

	.globl	boot_
boot_:
	cli				/ Disable interrupts.
					/
	sub	cx, cx			/
0:	inb	al, KBCTRL		/ Wait for 8042 input buffer to empty.
	testb	al, $2			/
	loopne	0b			/
	jmp	.+2		/ DELAY /
					/
	movb	al, $0xFE		/ Issue a shutdown command
	outb	KBCTRL, al		/ to the 8042 control port.
					/
0:	hlt				/ Halt until processor reset occurs.
	jmp	0b

////////
/
/ Data.
/
////////

	.globl	MAXMEM
	.globl	vecs_
	.globl	realmode_
	.globl	gdtsel_, gdtmap_
	.globl	idtsel_, idtmap_
	.globl	CMOSmax_

	.shri
val11:	.word	0			/ Value obtained from int11 [in code].

	.prvd
MAXMEM:	.word	0xA000			/ In paragraphs, must be mult. of 64
CMOSmax_:.word	0x0000			/ Max extended memory according ...
					/ ... to CMOS bytes 0x17 and 0x18 ...
					/ ... in 64K chunks.
realmode_:.word	0			/ Virtual Addressing Mode Enabled
gdtmap_:.blkw	3			/ Global descriptor table definition
idtmap_:.blkw	3			/ Interrupt descriptor table definition
gdtsel_:.word	0			/ Global descriptor table selector
idtsel_:.word	0			/ Interrupt descriptor table selector
vecs_:	.word	vret_			/ Interrupt vector table
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_
	.word	vret_

////////
/
/ Task State Segment - Coherent runs as a single protected mode task.
/
////////
	.globl	tss_

	.prvd
tss_:				/ Task State Segment.
tss_lnk:.word	0		/  0: Back link selector to TSS.
tss_sp0:.word	0		/  2: SP for CPL 0.
tss_ss0:.word	0		/  4: SS for CPL 0.
tss_sp1:.word	0		/  6: SP for CPL 1.
tss_ss1:.word	0		/  8: SS for CPL 1.
tss_sp2:.word	0		/ 10: SP for CPL 2.
tss_ss2:.word	0		/ 12: SS for CPL 2.
tss_ip:	.word	0		/ 14: IP (Entry point).
tss_psw:.word	0		/ 16: Flag word.
tss_ax:	.word	0		/ 18: Register AX.
tss_cx:	.word	0		/ 20: Register CX.
tss_dx:	.word	0		/ 22: Register DX.
tss_bx:	.word	0		/ 24: Register BX.
tss_bp:	.word	0		/ 26: Register BP.
tss_sp:	.word	0		/ 28: Register SP.
tss_si:	.word	0		/ 30: Register SI.
tss_di:	.word	0		/ 32: Register DI.
tss_es:	.word	0		/ 34: Register ES.
tss_cs:	.word	0		/ 36: Register CS.
tss_ss:	.word	0		/ 38: Register SS.
tss_ds:	.word	0		/ 40: Register DS.
tss_ldt:.word	0		/ 42: Task LDT Selector.
@


1.1
log
@Shipped with COH 3.0.0
@
text
@d70 2
d542 13
d583 2
d889 1
a889 1
/ fsize_t n;
d961 1
a961 1
/ fsize_t n;
d1039 1
a1039 1
/ fsize_t n;
d1322 1
d1329 3
@
0707070064030064240407550000000000000000011777770507310716400005400000000000/newbits/kernel/USRSRC/i8086/ibm_at/objects0707070064030147740407550000030000030000011777770507310716400004100000000000/newbits/kernel/USRSRC/i8086/src0707070064030111371006440000030000030000011777770507310716400004700000061647/newbits/kernel/USRSRC/i8086/src/as1.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $

/ (lgl-
/	The information contained herein is a trade secret of Mark Williams
/	Company, and  is confidential information.  It is provided  under a
/	license agreement,  and may be  copied or disclosed  only under the
/	terms of  that agreement.  Any  reproduction or disclosure  of this
/	material without the express written authorization of Mark Williams
/	Company or persuant to the license agreement is unlawful.
/
/	COHERENT Version 2.3.37
/	Copyright (c) 1982, 1983, 1984.
/	An unpublished work by Mark Williams Company, Chicago.
/	All rights reserved.
/ -lgl)
////////
/
/ Machine language assist for
/ 8086/8088 Coherent. This contains the parts
/ that are common to all machines.
/
/ Note that several of the following constants can be invalidated
/ by changing the contents of ../h/*proc.h among others,
/ or by changing the number of automatic variables in the functions
/ called on the paths leading to consave or conrest.  Tread with caution.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.2  91/06/20  14:07:20  hal
/ I'm not sure what changed here.

/ Revision 1.3	88/08/05  08:32:09 	src
/ Kludges for AMD 286 bug have been removed.
/ 
/ Revision 1.2	88/06/24  16:02:08	src
/ Bug:	inb/outb did not work properly in split stack/data operation.
/ Fix:	inb/outb now explicitly reference the stack segment.
/ 
/ Revision 1.1	88/03/24  17:39:08	src
/ Initial revision
/ 
/ 88/03/10	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
/ These partial fixes will be removed once all CPU's are replaced.
/
/ 88/03/04	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ tmpcs*/tmpds* temporary variables renamed to sav_*.
/ usave/conrest/etc now handle odd byte alignment on stack.
/ envrest/conrest now do interrupt return as last instruction.
/
/ 87/12/21	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ fclear(f,n) function added.
/
/ 87/12/04	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ kfcopy(k,f,n) and fkcopy(f,k,n) routines added.
/
/ 87/12/03	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ popf replaced by 'push cs; mov ax,$0f; push ax; iret; 0:' due to popf int bug.
/
/ 87/11/05	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ slrcopy/srlcopy/sclear renamed plrcopy/prlcopy/pclear and moved to ibm*/as2.s
/
/ 87/10/27	Allan Cornish	/usr/src/sys/i8086/src/as1.s
/ System stack/data segments now setup in ibm/ibm_at as2.s
/
/ 87/02/06	Allan Cornish
/ Functions ffword and sfword added to fetch and set far memory.
/
////////

UPASIZE	=	1024			/ Size of uproc and stack
USIZE	=	0x114			/ sizeof(UPROC)
USZ1	=	140			/ Word count for usave, uproc size
UMCSP	=	0x06			/ offset of sp in u_syscon
EFAULT	=	14			/ Bad argument
PFLAGS	=	0x22			/ Offset into PROC.
PFKERN	=	0x80			/ Kernel process flag bit.
SIDEV	=	0x40			/ Device interrupt trap code.

////////
/
/ After performing machine specific
/ trap vector setup, the startup code jumps
/ here. The DS maps the vectors.
/
////////

	.globl	start

start:
/ Call the machine setup code.
/ Call Coherent main.
/ On return, send control off to the user
/ at its entry point.

	mov	sp, $u_+UPASIZE-32	/ Stack pointer for init
	call	i8086_			/ Do it.
	sti				/ Interrupts on, and
	call	main_			/ call Coherent mainline.
	cli				/ Interrupts off.
	incb	depth_			/ Set stack depth to user.
	sub	ax, ax			/ User mode IP.
	mov	bx, uds_		/ User mode DS, ES, SS
	mov	cx, ucs_		/ User mode CS.
	mov	dx, $0x0200		/ User mode FL.

	mov	ds, bx			/ Map data segment
	mov	es, bx			/ Map extra segment
	mov	ss, bx			/ Map stack segment

	mov	sp, $sb-aicodep_	/ User's stack
	push	dx			/ Flags
	push	cx			/ CS
	push	ax			/ IP
	iret				/ Go to user state.

////////
/
/ Trap and interrupt save.
/ These routines will be very familiar to any
/ RSX-11M hackers out there; it is just the ever
/ common co-routine call. The caller is called back,
/ with "bx" pointing to the saved "ax" on the stack,
/ with interrupts enabled. The called routine must
/ set 16(bx), which was initially the call back address,
/ to something non zero in the high byte if it does
/ not want an EOI sent to the 8259.
/
/ ttsave, tksave, tisave, and tusave could be folded into a single routine
/ with many tests and branches, but the frequency of passage through
/ this code warrants a minimally branched execution, and special casing
/ the interrupted context allows minimal memory references.
/
////////

	.globl	tsave

tsave:				/ What level of interrupt ?
	push	ds			/ Save current data base
	mov	ds, cs:cds		/ remap to system data space.
	pop	sav_ds			/
	decb	depth_			/ Adjust stack depth.
	je	tkusave			/ If e, stack switch may be needed.
ttsave:				/ Interrupted within interrupt
	cmp	sp,$u_+USIZE+50		/ Check for stack
	jbe	tabort			/ overflow
	push	ss			/ Fake save ss
	push	sp			/ Fake save sp
	push	sav_ds			/ Save ds
	push	bx			/ Save bx

	sti				/ More interrupts ok

	push	ax			/ Save ax
	push	dx			/ and remainder
	push	cx			/ of machine
	push	es			/ state
	mov	ax,ds			/ Map es
	mov	es,ax			/ to system ds
	mov	bx,sp			/ Load index
	icall	16(bx)			/ and call the caller
	mov	bx,sp			/ Load index
	mov	ax,16(bx)		/ fetch trap type
	cmpb	ah, $SIDEV		/ see if eoi
	jne	ttkdone			/ can be skipped

	cli				/ don't let eoi swamp us
	call	eoi			/ Dismiss interrupt
ttkdone:			/ Common ttsave/tksave finish
	pop	es			/ Restore
	pop	cx			/ the
	pop	dx			/ machine state
	pop	ax			/ state

	cli				/ No more interrupts

	incb	depth_			/ Reset stack level
	pop	bx			/ Restore the
	pop	ds			/ last parts
	add	sp,$6			/ forget ss, sp, and ra.
	iret				/ Done.

tabort:				/ Uarea stack overflowed
	add	sp,$300			/ Make room for death.
	mov	ax,$oops		/ Load
	push	ax			/ message
	call	panic_			/ and die.

tkusave:			/ Kernel or user process interrupted
	mov	sav_bx,bx		/ Save bx in temp
	mov	bx,cprocp_		/ Load proc pointer
	test	PFLAGS(bx),$PFKERN	/ Kernel process ?
	je	tusave			/ Sorry, go do it all.
tksave:				/ Kernel process interrupted
	push	ss			/ Fake save ss
	push	sp			/ Fake save sp
	push	sav_ds			/ Save ds
	push	sav_bx			/ Save bx

	sti				/ More interrupts ok.

	cmp	bx,iprocp_		/ Is this the idle process ?
	je	tisave			/ Yes, very easy
	push	ax			/ Save the
	push	dx			/ rest of
	push	cx			/ the machine
	push	es			/ state
	mov	ax,ds			/ And map
	mov	es,ax			/ extra to system data
	mov	bx,sp			/ Load index
	icall	16(bx)			/ and call the caller back.
	mov	bx,sp			/ Load index
	mov	ax,16(bx)		/ and pull trap type.
	cmpb	ah, $SIDEV		/ Machine trap?
	jne	ttkdone			/ Yes, skip dismiss
	call	eoi			/ Dismiss interrupt
	jmp	ttkdone			/ Finish above

tisave:				/ Idle process interrupted, nothing to save
	sub	sp,$8			/ Push junk
	mov	bx,sp			/ Load index
	icall	16(bx)			/ and call the caller back.
	mov	bx,sp			/ Load index
	mov	ax,16(bx)		/ and pull trap type.
	cmpb	ah, $SIDEV		/ Machine trap ?
	jne	0f			/ Yes, skip dismiss.
	call	eoi			/ Dismiss interrupt
0:
	call	stand_			/ Clock, part 2
	cli				/ No more interrupts

	add	sp,$18			/ Pop everything
	incb	depth_			/ Reset level
	iret				/ Done

tusave:				/ User process interrupted
	mov	bx, $u_+UPASIZE		/ Get base of user area and
	pop	-8(bx)			/ pop the data that
	pop	-6(bx)			/ was pushed onto the user
	pop	-4(bx)			/ stack onto the new
	pop	-2(bx)			/ system stack.
	mov	sav_ss, ss		/ Save the old stack segment
	mov	sav_sp, sp		/ and stack pointer, then
	mov	ss, sds_		/ switch onto the
	lea	sp, -8(bx)		/ new stack in the user area.
	push	sav_ss			/ Push old ss
	push	sav_sp			/ Push old sp
	push	sav_ds			/ Push old ds and
	push	sav_bx			/ push old bx.

	sti				/ Allow more interrupts.

	push	ax			/ Save the
	push	dx			/ remainder of
	push	cx			/ the machine
	push	es			/ state.
	mov	ax, ds			/ Map extra
	mov	es, ax			/ segment to system data.
	mov	bx, sp			/ Load up an index into the stack
	icall	16(bx)			/ and call the caller back.
	mov	bx, sp			/ Load up stack index.
	mov	ax, 16(bx)		/ Pull trap type.
	cmpb	ah, $SIDEV		/ Is this a machine trap ?
	jne	0f			/ Yes, skip dismiss.
	call	eoi			/ Do the dismiss.
0:	mov	bx, cprocp_		/ Have we become kernel?
	test	PFLAGS(bx), $PFKERN	/ If so, do kernel return.
	jne	ttkdone			/

	call	stand_			/ Clock, part 2
	pop	es			/ Restore the
	pop	cx			/ easy part of the
	pop	dx			/ machine
	pop	ax			/ state.

	cli				/ Interrupts off.

	incb	depth_			/ Adjust stack depth and
	pop	sav_bx			/ Pop off the old bx and
	pop	sav_ds			/ ds into statics, then
	pop	bx			/ map DS:BX over top of what
	pop	ds			/ was the previous stack.
	add	sp, $2			/ Pop ra.
	pop	-6(bx)			/ Copy the IP,
	pop	-4(bx)			/ the CS and the old
	pop	-2(bx)			/ FW onto the user's stack, then
	lea	sp, -6(bx)		/ switch back
	mov	bx, ds			/ to the
	mov	ss, bx			/ user's stack.
	mov	ds, cs:cds		/
	mov	bx, sav_bx		/ Reload the bx and the
	mov	ds, sav_ds		/ ds, then
	iret				/ exit interrupt.

////////
/
/ This dummy routine is put in vector
/ table slots that are unused. All it does is
/ return to the caller.
/
////////

	.globl	vret_

vret_:	ret

////////
/
/ Fetch a word from the user's data space.
/
/ getuwd(u)
/ char *u;
/
////////

	.globl	getuwd_
	.globl	getupd_

getuwd_:
getupd_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save extra map and
	mov	es, uds_		/ remap over the user's data.
	mov	ax,es:(bx)		/ Get word
	pop	es			/ Restore es.
	ret				/ Return

////////
/
/ Fetch a word from the user's code space.
/
/ getuwi(u)
/ char *u;
/
////////

	.globl	getuwi_

getuwi_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Argument
	cmp	bx,ucl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save extra.
	mov	es,ucs_			/ Users data segment
	mov	ax,es:(bx)		/ Get word
	pop	es			/ Restore extra.
	ret				/ Return

////////
/
/ Fetch a byte from the user's data space.
/
/ getubd(u)
/ char *u;
/
////////

	.globl	getubd_

getubd_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save es.
	mov	es,uds_			/ Users data segment
	movb	al,es:(bx)		/ Get word
	pop	es			/ Restore es.
	subb	ah,ah			/ Clear upper half
	ret				/ Return

////////
/
/ Store a word into the user's data space.
/
/ putuwd(u, w)
/ char *u;
/ int w;
/
////////

	.globl	putuwd_

putuwd_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ New value
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save es.
	mov	es,uds_			/ Users data segment
	mov	es:(bx),ax		/ Set value
	pop	es			/ Restore es.
	sub	ax,ax			/ Succesful
	ret				/ Return

////////
/
/ Store a word into the user's code space.
/
/ putuwi(u, w)
/ char *u;
/ int w;
/
////////

	.globl	putuwi_

putuwi_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ New value
	mov	bx,2(bx)		/ Argument
	cmp	bx,ucl_			/ In range?
	ja	kuerr			/ No

	push	ucs_			/ Get physical address.
	sub	ax, ax			/ DX:AX = phy = vtop( ucs:0 );
	push	ax			/
	call	vtop_			/
	add	sp, $4			/
					/
	sub	bx, bx			/ Get writable virtual address.
	push	bx			/ DX:AX = fp = ptov( phy, ucl );
	push	ucl_			/
	push	dx			/
	push	ax			/
	call	ptov_			/
	add	sp, $8			/
					/
	mov	bx, sp			/
	mov	ax, 4(bx)		/ New value
	mov	bx, 2(bx)		/ Argument
	push	es			/ Save ES
	mov	es, dx			/ Users (writable) code segment
	mov	es:(bx), ax		/ Set value
	pop	es			/ Restore es
					/
	push	dx			/ Release writable virtual address.
	sub	ax, ax			/ vrelse( fp );
	push	ax			/
	call	vrelse_			/
	add	sp, $4			/
					/
	sub	ax,ax			/ Succesful
	ret				/ Return

////////
/
/ Store a byte into the user's data space.
/
/ putubd(u, w)
/ char *u;
/ int w;
/
////////

	.globl	putubd_

putubd_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ New value
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save es.
	mov	es,uds_			/ Users data segment
	movb	es:(bx),al		/ Set value
	pop	es			/ Restore es.
	sub	ax,ax			/ Succesful
	ret				/ Return

////////
/
/ Block transfer "n" bytes from location
/ "k" in the system map to location "u" in the
/ user's data space. Return the number of bytes
/ transferred.
/
/ kucopy(k, u, n)
/ char *k;
/ char *u;
/ int n;
/
////////

	.globl	kucopy_

kucopy_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax,6(bx)		/ Add count
	jc	kuerr			/ Out of bounds
	cmp	ax,udl_			/ In range?
	ja	kuerr			/ No

	push	si			/ Save si
	push	di			/ Save di
	push	es			/ Save es.

	mov	si,2(bx)		/ Kernel address
	mov	di,4(bx)		/ User address
	mov	cx,6(bx)		/ Count
	mov	ax,cx			/ Move here to return
	mov	es,uds_			/ Map extra segment to user

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count
	rep				/
	movsw				/ Move words.
	rcl	cx, $1
	rep
	movsb				/ Move odd byte.

	pop	es			/ Restore es.
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ Block copy "n" bytes from location "u" in
/ the user data space to location "k" in the system
/ data space. Return the actual number of bytes
/ moved.
/
/ ukcopy(u, k, n)
/ char *u;
/ char *k;
/ int n;
/
////////

	.globl	ukcopy_

ukcopy_:
	mov	bx,sp			/ Base pointer
	mov	ax,2(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax,6(bx)		/ Count
	jc	kuerr			/ Out of bounds
	cmp	ax,udl_			/ In range?
	ja	kuerr			/ No

	push	si			/ Save si
	push	di			/ Save di
	push	ds			/ Save ds

	mov	si,2(bx)		/ User address
	mov	di,4(bx)		/ Kernel address
	mov	cx,6(bx)		/ Count
	mov	ax,cx			/ Move here to return
	mov	bx, uds_		/ Map data segment
	mov	ds, bx			/ avoiding bug in 8088.

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Word count, odd byte in carry.
	rep				/
	movsw				/ Move words.
	rcl	cx, $1
	rep				/ Move odd byte.
	movsb

	pop	ds			/ Restore ds
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ All of the above copy routines jump to
/ "kuerr", with the stack untouched, if they detect
/ a bounds error on a user address.
/
////////

kuerr:
	mov	bx,$u_			/ Pointer to user area
	movb	(bx),$EFAULT		/ Bad parameter error
	sub	ax,ax			/ Didn't copy anything
	ret				/ Return

////////
/
/ sfbyte( fp, b )	-- set far byte
/ int far * fp;
/ int b;
/
////////

	.globl	sfbyte_

sfbyte_:push	es		/ sfbyte( fp, b )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ register int b;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	movb	es:(di), al	/	*fp = b;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ sfword( fp, w )	-- set far word
/ int far * fp;
/ int w;
/
////////

	.globl	sfword_

sfword_:push	es		/ sfword( fp, w )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ register int w;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	mov	es:(di), ax	/	*fp = w;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ ffbyte( fp )		-- fetch far byte
/ int far * fp;
/
////////

	.globl	ffbyte_

ffbyte_:push	es		/ ffbyte( fp )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	sub	ax, ax		/
	movb	al, es:(di)	/	return *fp;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ ffword( fp )		-- fetch far word
/ int far * fp;
/
////////

	.globl	ffword_

ffword_:push	es		/ ffword( fp )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	mov	ax, es:(di)	/	return *fp;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ Block transfer "n" bytes from location
/ "k" in the system map to location "f"
/ in the virtual address space.
/ Return the number of bytes / transferred.
/
/ kfcopy(k, f, n)
/ char *k;
/ faddr_t f;
/ int n;
/
////////

	.globl	kfcopy_

kfcopy_:
	push	si			/ Save si
	push	di			/ Save di
	push	bp			/ Save bp
	mov	bp, sp			/ Base pointer
	push	es			/ Save es.

	mov	si, 8(bp)		/ Kernel address
	les	di, 10(bp)		/ Far address
	mov	cx, 14(bp)		/ Count
	mov	ax, cx			/ Move here to return

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count.
	rep				/
	movsw				/ Move words.
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte.
					/
	pop	es			/ Restore es.
	pop	bp			/ Restore bp.
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ Block transfer "n" bytes from location
/ "f" in the virtual addres sspace to
/ location "f" in the system map.
/ Return the number of bytes / transferred.
/
/ fkcopy(f, k, n)
/ faddr_t f;
/ char *k;
/ int n;
/
////////

	.globl	fkcopy_

fkcopy_:
	push	si			/ Save si
	push	di			/ Save di
	push	bp			/ Save bp
	mov	bp, sp			/ Base pointer
	push	ds			/ Save ds.

	lds	si, 8(bp)		/ Far address
	mov	di, 12(bp)		/ Kernel address
	mov	cx, 14(bp)		/ Count
	mov	ax, cx			/ Move here to return

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count.
	rep				/
	movsw				/ Move words.
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte.
					/
	pop	ds			/ Restore ds.
	pop	bp			/ Restore bp.
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ fclear( fp, n )	- Erase far memory.
/ faddr_t fp;
/ unsigned n;
/
////////

	.globl	fclear_

fclear_:
	push	es			/ Save es
	push	di			/ Save di
	push	bp			/ Save bp
	mov	bp, sp			/ Base pointer

	les	di, 8(bp)		/ Far address
	mov	cx, 12(bp)		/ Count
	sub	ax, ax			/

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count.
	rep				/
	stosw				/ Clear words.
	rcl	cx, $1			/
	rep				/
	stosb				/ Clear odd byte.
					/
	pop	bp			/ Restore bp.
	pop	di			/ Restore di.
	pop	es			/ Restore es.
	ret				/ Return

////////
/
/ Profile scaling.
/
////////

	.globl	pscale_

pscale_:
	mov	bx,sp			/ Base pointer
	mov	ax,2(bx)		/ Multiply
	mul	4(bx)			/
	mov	ax,dx			/ Get high half
	ret				/ And return

////////
/
/ Save the environment of a process
/ envsave(p)
/ MENV *p;
/
/ Save the context of a process
/ consave(p)
/ MCON *p;
/
////////

	.globl	consave_
	.globl	envsave_

envsave_:
consave_:
	mov	cx, di			/ Hide di.
	mov	bx, sp			/ Point bx at the stack and
	mov	di, 2(bx)		/ di at the MCON block.
	cld				/ Ensure increment.
	mov	ax, cx			/ Save di
	stosw
	mov	ax, si			/ Save si
	stosw
	mov	ax, bp			/ Save bp
	stosw
	mov	ax, sp			/ Save sp
	stosw
	mov	ax, (bx)		/ Save ra as pc
	stosw
	pushf				/ Save fw
	pop	ax
	stosw
	movb	al, depth_		/ Save stack depth
	cbw
	stosw
	mov	di, cx			/ Put di back,
	sub	ax, ax			/ indicate a state save and
	ret				/ return to caller.

////////
/
/ Restore the environment of a process.
/ envrest(p)
/ MENV *p;
/
////////

	.globl	envrest_

envrest_:
	cli
	cld
	mov	bx,sp			/ Base pointer
	mov	si,2(bx)		/ Pointer to context
	lodsw				/ Restore di
	mov	di,ax			/
	lodsw				/ Restore si
	mov	cx,ax			/ Save for later
	lodsw				/ Restore bp
	mov	bp,ax			/
	lodsw				/ Restore sp
	mov	sp,ax			/
	mov	bx,ax			/ Our frame
	push	cs			/ Push current CS
	lodsw				/ Restore pc
	push	ax			/
	lodsw				/ Restore flags
	mov	(bx),ax			/ Stack now in form PSW,CS,IP.
	lodsw				/ Restore stack depth
	cli				/ No more interrupts
	movb	depth_, al
	mov	si,cx			/ Restore si
	mov	ax,$1			/ We are restoring
	iret				/ Return through PSW,CS,IP.

////////
/
/ Restore the context of a process.
/ Called with interrupts disabled from dispatch.
/ conrest(u, o)
/ saddr_t u;
/
////////

	.globl	conrest_

conrest_:
	decb	depth_			/ Falsify user/system state
	sti				/ Interrupts ok here
			/ Save current uarea
	call	usave_			/ Save the uarea in its segment.
			/ Copy in new uarea
	mov	bx,sp			/ Base pointer
	mov	ax, 2(bx)		/ Fetch uarea saddr_t
	mov	bx, 4(bx)		/ Fetch syscon offset
	mov	uasa_, ax		/ Save uarea saddr_t
	mov	cx,$USZ1		/ uproc size
/	mov	es,sds_			/ system data segment
	mov	di,$u_			/ system data uarea offset
	mov	ds,ax			/ uarea segment
	sub	si,si			/ uarea offset
	mov	sp,UMCSP(bx)		/ new stack
	cld				/ increment
	rep				/ repeat
	movsw				/ copy uproc
	mov	di,sp			/ stack offset in system data
	and	di,$~1			/ ensure word alignment
	mov	cx,$u_+UPASIZE		/ compute byte
	sub	cx,di			/ count
	mov	si,$UPASIZE		/ compute offset
	sub	si,cx			/ in segment
	shr	cx,$1			/ make word count
	rep				/ repeat
	movsw				/ copy stack
			/ Clean up
	mov	ax, es			/ Restore data
	mov	ds, ax			/ segment
			/ Now restore context
	add	bx, $u_			/ convert to address
	mov	si, bx			/ Get source index for restore
	lodsw				/ Restore di
	mov	di,ax			/
	lodsw				/ Restore si
	mov	cx,ax			/ Save for later
	lodsw				/ Restore bp
	mov	bp,ax			/
	lodsw				/ Restore sp
	mov	sp,ax			/
	mov	bx,ax			/ Our frame
	push	cs			/ Push current CS
	lodsw				/ Restore pc
	push	ax			/
	lodsw				/ Restore flags
	mov	(bx),ax			/ Stack now in form PSW,CS,IP.
	lodsw				/ Restore stack depth
	cli				/ No more interrupts
	movb	depth_, al
	mov	si,cx			/ Restore si
	mov	ax,$1			/ We are restoring
	iret				/ Return through PSW,CS,IP.

////////
/ usave()
/ Save uarea in segment.
/ Knowing that ds points to the system data segment
/ and that es should map there also.
/ And guaranteed not to step on ax or bx for conrest
/
	.globl	usave_
0:	ret
usave_:
	cmp	uasa_, $0		/
	je	0b
	push	es			/ Save es
	push	si			/ Save si
	push	di			/ Save di
	mov	cx,$USZ1		/ count
	sub	di,di			/ uarea segment offset
	mov	es,uasa_		/ uarea segment
	mov	si,$u_			/ system data offset
/	mov	ds,sds_			/ system data segment
	cld				/ increment
	rep				/ repeat
	movsw				/ copy uproc
	mov	si,sp			/ stack offset in system data
	and	si,$~1			/ ensure word alignment
	mov	cx,$u_+UPASIZE		/ compute byte
	sub	cx,si			/ count
	mov	di,$UPASIZE		/ compute offset
	sub	di,cx			/ in segment
	shr	cx,$1			/ make word count
	rep				/ repeat
	movsw				/ copy stack
	pop	di			/ Restore di
	pop	si			/ Restore si
	pop	es			/ Restore extra
	ret

/ Save useful registers.
/
	.globl	msysgen_
/
/ msysgen(p)
/ MGEN *p;
/
msysgen_:
	ret				/ Nothing useful to save

/ Disable interrupts.  Previous value is returned.
/
	.globl	sphi_

sphi_:
	pushf				/ Save flags
	pop	ax			/ Return current value
	cli				/ Disable interrupts
	ret				/ And return

/ Enable interrupts.  Previous value is returned.
/
	.globl	splo_

splo_:
	pushf
	pop	ax
	sti
	ret

/ Change interrupt flag.  Previous value is returned.
/
	.globl	spl_

spl_:
	pop	ax			/ ip
	pop	bx			/ psw
	push	bx
	push	bx			/ push psw, cs, ip for iret
	push	cs
	push	ax
	pushf				/ old psw
	pop	ax
	iret

////////
/
/ Idle routine.
/ Enable interupts, and wait for something to
/ happen. Does not do anything to the 8259, bacause
/ this will be set up correctly.
/
////////

	.globl	_idle_

_idle_:	sti				/ Interupts on.
	hlt				/ Wait for an interrupt
	ret				/ and return.

////////
/
/ The world is indeed grim.
/ Halt. Keep the interrupts on so that the
/ keyboard can get int.
/
////////

	.globl	halt_

halt_:	sti				/ Be safe,
0:
	hlt				/ and halt.
	jmp	0b			/ Paranoid, yes sir.

////////
/
/ Basic port level I/O.
/
/ int	inb(port);
/ int	outb(port, data);
/
////////

	.globl	inb_
	.globl	outb_

inb_:	mov	bx, sp
	mov	dx, ss:2(bx)
	sub	ax, ax
	inb	al, dx
	ret

outb_:	mov	bx, sp
	mov	dx, ss:2(bx)
	mov	ax, ss:4(bx)
	outb	dx, al
	ret

////////
/
/ Routines to move data to and from
/ the system auxiliary segment.
/
////////

	.globl	ageti_

ageti_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Pointer
	push	es			/ Save extra mapping and
	mov	es, sas_		/ remap.
	mov	ax,es:(bx)		/ Get value
	pop	es			/ Restore es and
	ret				/ Return

	.globl	aputp_
	.globl	aputi_

aputp_:
aputi_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ Value
	mov	bx,2(bx)		/ Pointer
	push	es			/ Save extra base and
	mov	es, sas_		/ remap.
	mov	es:(bx),ax		/ Set value
	pop	es			/ Restore extra base
	ret				/ Return

	.globl	aputc_

aputc_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ Value
	mov	bx,2(bx)		/ Pointer
	push	es			/ Save es and
	mov	es, sas_		/ remap.
	movb	es:(bx),al		/ Set value
	pop	es			/ Restore es and
	ret				/ Return

////////
/
/ Data. 
/ A small number of variables must be
/ in the code segment. All of these variables have
/ something to do with the interrupt linkage; when you
/ get an interrupt the only thing that is valid is
/ the code segment.
/
////////

	.globl	cds

	.shri
cds:	.blkw	1			/ Copy of "sds_".

	.globl	u_
	.globl	depth_,	sas_,	scs_,	sds_,	ucs_
	.globl	ucl_,	uds_,	udl_

	.bssd
	.even
u_:	.blkb	UPASIZE

	.prvd
oops:	.ascii	"stack overflow"
	.byte	0

depth_:	.byte	0			/ System state.

	.even
sas_:	.blkw	1			/ System auxiliary segment.
scs_:	.blkw	1			/ System code segment.
sds_:	.blkw	1			/ System data segment.
ucs_:	.blkw	1			/ User code segment.
ucl_:	.blkw	1			/ User code limit.
uds_:	.blkw	1			/ User data segment.
udl_:	.blkw	1			/ User data limit.
sav_ds:	.blkw	1			/ Four scratch words
sav_bx:	.blkw	1
sav_ss:	.blkw	1
sav_sp:	.blkw	1

////////
/
/ This is the image of the init process.
/ It gets copied into a user segment when the system
/ is first brought up. It must be in the data segment, because
/ that is how it is used, and it must be dephased in a funny
/ way because it is executed at location 0.
/
////////

	.globl	aicodep_		/ Position of code.
	.globl	aicodes_		/ Size of code.
	.globl	aidatap_		/ Position of data.
	.globl	aidatas_		/ Size of data.

	.shrd
aicodep_:
	sub	ax,ax			/ No environment
	push	ax
	mov	ax,$argl-aidatap_	/ Argument list
	push	ax
	mov	ax,$fn-aidatap_		/ File name
	push	ax
	sub	sp,$2			/ Dummy word for exec
	sys	11			/ Sys exec
	jmp	.			/ This should not return
aicodes_ = .-aicodep_

aidatap_:
	.word	0			/
	.word	0			/ Errno
	.word	0			/
	.word	0			/
	.word	0			/
	.word	0			/
	.word	0			/
	.word	0			/
argl:	.word	fn-aidatap_		/ argv[0] = "/etc/init";
	.word	a1-aidatap_		/ argv[1] = "";
	.word	0			/ argv[2] = NULL;

fn:	.ascii	"/etc/init\000"
a1:	.byte	0

	.even
	.blkb	64
sb:
aidatas_ = .-aidatap_
0707070064030104471006440000030000030000011777770507310717400005100000007712/newbits/kernel/USRSRC/i8086/src/clist.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $

/ (lgl-
/	The information contained herein is a trade secret of Mark Williams
/	Company, and  is confidential information.  It is provided  under a
/	license agreement,  and may be  copied or disclosed  only under the
/	terms of  that agreement.  Any  reproduction or disclosure  of this
/	material without the express written authorization of Mark Williams
/	Company or persuant to the license agreement is unlawful.
/
/	COHERENT Version 2.3.37
/	Copyright (c) 1982, 1983, 1984.
/	An unpublished work by Mark Williams Company, Chicago.
/	All rights reserved.
/ -lgl)
////////
/
/ i8086 coherent clist hack.
/ cltinit, getq and putq have been tuned.
/ the remaining functions are as produced by cc -S coh/clist.c
/ with NCPCL substituted
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  17:39:16	src
/ Initial revision
/ 

#include <sys/const.h>

	.shri
L10001:	.word	NCPCL+2
	.globl	cltinit_
cltinit_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	sub	sp, $0x0C

	pushf			/ s =
	cli			/ sphi()
	sub	di, di
	mov	ax, NCLIST_
	imul	cs:L10001
	mov	-0x0C(bp), ax
	add	ax, clistp_
	mov	-0x04(bp), ax

L3:	sub	-0x04(bp), $NCPCL+2
	mov	ax, -0x04(bp)
	cmp	ax, clistp_
	jb	L2

L10002:	mov	si, -0x04(bp)
	mov	(si), di
	mov	di, si
	jmp	L3

L2:	mov	cltfree_, di
	call	spl_
	add	sp, $0x02

	mov	sp, bp
	pop	bp
	pop	di
	pop	si
	ret

	.globl	getq_

getq_:
	mov	dx, si
	push	bp
	mov	bp, sp

	mov	bp, 4(bp)	/ bp = cqp
	sub	ax, ax		/ ax = 0
	cmp	(bp), ax	/ if (cqp->cq_cc == 0)
	jne	0f
	dec	ax		/ return (-1)
	jmp	2f

0:	pushf			/ s =
	cli			/ sphi()
	mov	si, 6(bp)	/ si = op = cqp->cq_op
	mov	bx, 8(bp)	/ bx = ox = cqp->cq_ox
	movb	al, 2(bx,si)	/ ax = op->cl_ch[ox]
	dec	(bp)		/ if (--cqp->cq_cc == 0)
	je	0f
	inc	bx		/ ++ox
	cmp	bx, $NCPCL	/ if (ox == NCPL)
	jne	1f

0:	sub	bx, bx		/ ox = 0;
	mov	cx, (si)	/ cx = np = op->cl_fp
	mov	6(bp), cx	/ cqp->cq_op = np
	cmp	cx, bx		/ if (np == 0)
	jne	0f
	mov	2(bp), bx	/ cqp->cq_ip = 0
	mov	4(bp), bx	/ cqp->cq_ix = 0

0:	mov	cx, cltfree_	/ cx = tmp = cltfree
	mov	(si), cx	/ op->cl_fp = tmp
	mov	cltfree_, si	/ cltfree = op
	cmp	cltwant_, bx	/ if (cltwant != 0)
	je	1f
	mov	cltwant_, bx	/ cltwant = 0
	mov	cx, $cltwant_	/ wakeup(&cltwant)
	push	bx	/ save
	push	dx	/ save
	push	ax	/ save
	push	cx
	call	wakeup_
	pop	cx	/ clear stack
	pop	ax	/ restore
	pop	dx	/ restore
	pop	bx	/ restore

1:	mov	8(bp), bx	/ cqp->cq_ox = ox
	mov	cx, ax
	call	spl_		/ spl(s)
	add	sp, $2
	mov	ax, cx

2:	pop	bp
	mov	si, dx
	ret

	.globl	putq_

putq_:
	mov	dx, si
	push	bp
	mov	bp, sp

	mov	cx, 6(bp)	/ cx = c
	mov	bp, 4(bp)	/ bp = cqp
	sub	ax, ax		/ ax = 0
	pushf			/ s =
	cli			/ sphi()
	mov	si, 2(bp)	/ si = ip = cqp->cq_ip
	mov	bx, 4(bp)	/ bx = ix = cqp->cq_ix
	cmp	bx, ax		/ if (ix == 0)
	jne	2f
	mov	si, cltfree_	/ ip = cltfree
	cmp	si, ax		/ if (ip == 0)
	jne	0f
	call	spl_		/ spl(s)
	add	sp, $2
	mov	ax, $-1		/ return (-1)
	jmp	3f

0:	mov	bx, (si)	/ tmp = ip->cl_fp
	mov	cltfree_, bx	/ cltfree = tmp
	mov	(si), ax	/ ip->cl_fp = 0
	mov	bx, 2(bp)	/ np = cqp->cq_ip
	cmp	bx, ax		/ if (np == 0)
	jne	0f
	mov	6(bp), si	/ cqp->cq_op = ip
	jmp	1f

0:	mov	(bx), si	/ np->cl_fp = ip

1:	mov	2(bp), si	/ cqp->cq_ip = ip
	mov	bx, ax		/ bx = ix = cqp->cq_ix = 0

2:	movb	2(bx,si), cl	/ ip->cl_ch[ix] = c
	inc	bx		/ ix++
	cmp	bx, $NCPCL	/ if (ix == NCPCL)
	jne	0f
	mov	bx, ax		/ ix = 0

0:	mov	4(bp), bx	/ cqp->cq_ix = ix
	inc	(bp)		/ cqp->cq_cc++
	call	spl_		/ spl(s)
	add	sp, $2
	mov	ax, cx		/ return (c)

3:	pop	bp
	mov	si, dx
	ret

	.globl	clrq_

clrq_:
	push	si
	push	di
	push	bp
	mov	bp, sp

	mov	si, 0x08(bp)
	call	sphi_
	mov	di, ax

L18:	push	si
	call	getq_
	add	sp, $0x02
	or	ax, ax
	jge	L18
	push	di
	call	spl_
	add	sp, $0x02

	pop	bp
	pop	di
	pop	si
	ret

	.globl	waitq_

waitq_:
	push	si
	push	di
	push	bp
	mov	bp, sp

L21:	cmp	cltfree_, $0x00
	jne	L19
	mov	cltwant_, $0x01
	sub	ax, ax
	push	ax
	push	ax
	mov	ax, $0x0100
	push	ax
	mov	ax, $cltwant_
	push	ax
	call	sleep_
	add	sp, $0x08
	jmp	L21

L19:	pop	bp
	pop	di
	pop	si
	ret
0707070064030147721006440000030000030000011777770507310717500005300000003433/newbits/kernel/USRSRC/i8086/src/clocked.c/*
 * clocked.c - support routines for alternate clock rate
 *
 *  altclk_in(hz, fn) - install routine with specified rate
 *                      "hz" should be a multiple of system rate of 100 Hz
 *			return 0 if completed ok, -1 otherwise
 *
 *  altclk_out()      - uninstall alternate clock routine and restore system rate
 *			return old value of "altclk"
 *
 *  altclk_rate(hz)   - set clock interrupt rate
 *			new rate must be an even multiple of system rate "HZ"
 *			return 0 if completed ok, -1 otherwise
 *
 *  History:
 *    90/08/08 hws	initial version, works with hs.c modified for com[1-4]
 *    90/08/14 hws	make it more like a Unix system call
 */

#include	<sys/coherent.h>		/* altclk */
#include	<sys/const.h>		/* HZ */

#define	PIT	0x40		/* 8253 port */
#define	TMR0_M3	0x36		/* timer 0, mode 3 */

#if 0
				/* nominal IBM rate is 1.1900 MHz */
#define	SYS_HZ	1190000L	/* rate of input clock to timer 0 */
#else
				/* current kernel rate is 1.1932 MHz */
#define	SYS_HZ	1193200L	/* rate of input clock to timer 0 */
#endif

typedef int (*PFI)();		/* pointer to function returning int */

altclk_rate(hz)
unsigned int hz;
{
	int s;			/* to save CPU irpt flag */
	unsigned int interval;	/* period for hz, in units of 1.19 MHz ticks */
	int ret;

	if (hz >= HZ && hz % HZ == 0) {		/* can't go slower than HZ! */
		interval = SYS_HZ/hz;
		s = sphi();			/* disable irpts */
		outb(PIT+3, TMR0_M3);
		outb(PIT, interval & 0xff);
		outb(PIT, interval >> 8);	/* unsigned shift */
		spl(s);				/* restore previous irpt state */
		ret = 0;
	} else {
		ret = -1;
	}
	return ret;
}

int altclk_in(hz, fn)
int hz;
PFI fn;
{
	int ret;

	if ((ret = altclk_rate(hz)) == 0)
		altclk = fn;
	return ret;
}

PFI altclk_out()
{
	PFI ret;

	ret = altclk;
	if (ret) {
		altclk_rate(HZ);
		altclk = 0;
	}
	return ret;
}
0707070064030147701004440000030000030000011777770507310717600005200000000376/newbits/kernel/USRSRC/i8086/src/cs_sel.s////////
/
/ Get cs selector - return 0 if in kernel, CS if not in kernel.
/
/ This version is for resident drivers.
/ There is a different version (cs_self.s) for loadable drivers.
/
/ int	cs_sel();
/
////////

	.globl	cs_sel_
cs_sel_:
	sub	ax, ax
	ret
0707070064030147711006440000030000030000011777770507310717600005100000011606/newbits/kernel/USRSRC/i8086/src/defer.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/

////////
/
/ Defer a function [from interrupt level] for later execution
/
/	defer( f, a )	- defer a function [usually from interrupt level]
/	defend()	- execute deferred functions
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.2	88/04/04  17:05:05	src
/ ldefer/ldefend functions now allow deferred functions from loadable drivers.
/ 
/ Revision 1.1	88/03/24  17:39:20	src
/ Initial revision
/ 
/ 86/11/19	Allan Cornish		/usr/src/sys/i8086/src/defer.s
/ defer(func,arg) and defend() functions ported to Coherent from RTX.
/
////////

	.globl	defend_
	.globl	defer_
	.globl	ldefer

	.bssd
defunc:	.blkw	128		/ static void (*defunc[128])();
defarg:	.blkw	128		/ static char * defarg[128];
defqix:	.blkw	1		/ static int defqix;
defqox:	.blkw	1		/ static int defqox;
ldcseg:	.blkw	128		/ static saddr_t ldcseg[128];
ldfunc:	.blkw	128		/ static void (*ldfunc[128])();
	.shri

////////
/
/ void
/ defer( f, a )		-- defer a function [usually from interrupt level]
/ int (*f)();
/ char *a;
/
/	Input:	f = pointer to function to be deferred.
/		a = argument to pass to function when it is invoked.
/
/	Action:	Schedule function 'f' to be invoked with argument 'a'
/		during the transition from interrupt service level back
/		to user mode.
/
/	Return:	None.
/
/	Notes:	13 instructions executed.  Interrupt latency = 7 instructions.
/		Only 127 functions can be deferred at any one time.
/		Exceeding this limit will cause loss of ALL deferred functions.
/
////////

defer_:				/
	pop	ax		/ Convert IP into PSW,CS,IP to allow iret.
	pushf			/
	push	cs		/
	push	ax		/
	mov	bx, sp		/ defer( f, a )
	mov	ax, ss:6(bx)	/ register int (*f)();		/* AX */
	mov	dx, ss:8(bx)	/ register char *a;		/* DX */
				/ {
				/	register int x;		/* BX */
				/
	cli			/	sphi();
	mov	bx, defqix	/	x = defqix;
	mov	defunc(bx), ax	/	defunc[x] = f;
	mov	defarg(bx), dx	/	defarg[x] = a;
	addb	defqix, $2	/	defqix++;
//	sti			/	splo();
	iret			/ }

////////
/
/ void
/ defend( )		-- evaluate deferred functions
/
/	Action:	Evaluate all deferred functions.
/
/	Notes:	Should be called periodically by busy-wait device drivers.
/		4 + (n * 7) instructions executed, where n = # deferred func.
////////

defend_:			/ defend()
				/ {
				/
	mov	bx, defqox	/	register int x = defqox;    /* BX */
				/
	cmp	bx, defqix	/	if ( x != defqix ) {
	je	1f		/
				/		do {
0:	addb	defqox, $2	/			defqox++;
				/
	push	defarg(bx)	/			(*defunc[x])
	icall	defunc(bx)	/				(defarg[x]);
	add	sp, $2		/
				/
	mov	bx, defqox	/			x = defqox;
	cmp	bx, defqix	/
	jne	0b		/		} while ( x != defqix );
				/	}
1:	ret			/ }

////////
/
/ void
/ ldefer( f, a )	-- defer a far function [usually from interrupt level]
/ int (far*f)();
/ char *a;
/
/	Input:	f = pointer to loadable driver function to be deferred.
/		a = argument to pass to function when it is invoked.
/
/	Action:	Schedule loadable driver function 'f' to be invoked with
/		argument 'a' during the transition from interrupt service
/		level back to user mode.
/
/	Return:	None.
/
/	Notes:	16 instructions executed.  Interrupt latency = 8 instructions.
/		Only 127 functions can be deferred at any one time.
/		Exceeding this limit will cause loss of ALL deferred functions.
/
////////

ldefer:				/
	pop	ax		/ Convert IP into PSW,CS,IP to allow iret.
	pushf			/
	push	cs		/
	push	ax		/
	mov	bx, sp		/ defer( f, a )
	mov	ax, ss:6(bx)	/ register int (*f)();		/* CX:AX */
	mov	cx, ss:8(bx)	/
	mov	dx, ss:10(bx)	/ register char *a;		/* DX */
				/ {
				/	register int x;		/* BX */
				/
	cli			/	sphi();
	mov	bx, defqix	/	x = defqix;
	mov	ldfunc(bx), ax	/	ldfunc[x] = FP_OFF(f);
	mov	ldcseg(bx), cx	/	ldcseg[x] = FP_SEL(f);
	mov	defunc(bx),$ldefend/	defunc[x] = ldefend;
	mov	defarg(bx), dx	/	defarg[x] = a;
	addb	defqix, $2	/	defqix++;
//	sti			/	splo();
	iret			/ }

////////
/
/ static void
/ ldefend( )		-- evaluate deferred far function
/
/	Action:	Evaluate deferred far function.
/
/	Notes:	Only called by defend().  Register BX contains driver's defqox.
/
////////

ldefend:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	mov	ax, ldfunc(bx)	/ AX = Driver function to be invoked.
				/
	push	ldcseg(bx)	/ Define driver entry point.
	push	four		/
				/
	xcall	-4(bp)		/ Invoke driver entry point, which will
				/	in turn invoke the deferred function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

	.prvd
four:	.word	4
	.shri
0707070064030147671006440000030000030000011777770507310720000005300000007734/newbits/kernel/USRSRC/i8086/src/dmalock.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, Ltd, and is  confidential information.   It is provided
 *	under a license agreement,  and may be copied or disclosed  only
 *	under  the  terms  of  that  agreement.    Any  reproduction  or
 *	disclosure  of  this   material   without  the  express  written
 *	authorization of INETCO Systems, Ltd. or persuant to the license
 *	agreement is unlawful.
 *
 *	Copyright (c) 1989
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 *
 * $Description: $
 *	Routines to lock/unlock the DMA controller chip.
 *
 * $Author: root $
 *
 * $Creation: June 21, 1989 $
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	89/06/30  16:21:26 	src
 * Initial revision
 * 
 */

#include <sys/timeout.h>

typedef void (* vfp_t)();		/* Void function pointer type.	     */

/*
 * If the following variable is non-zero, DMA controller locking is enabled,
 * allowing at access to only one DMA channel at a time.
 */
int DMALCK = 1;

static TIM * dmatail = (TIM *)0;	/* DMA deferred function queue tail. */
static TIM * dmahead = (TIM *)0;	/* DMA deferred function queue head. */

/*
 * int
 * dmalock( dfp, fun, arg )
 * TIM * dfp;
 * vfp_t fun;
 * int	 arg;
 *
 *	Inputs:	dfp  = Deferred function structure pointer.
 *		fun  = Function to call if request is deferred.
 *		arg  = Argument to pass to function.
 *
 *	Action:	Either locks DMA controller immediately or defers function
 *		call until lock can be granted.
 *
 *	Return:	0 = Lock granted or -1 = Lock deferred.
 *
 *	Notes:	DMA controller locking was introduced to cure a bug on the
 *		NCR DMA controller, where overlapped DMA caused problems.
 *		No action is taken if DMA locking is disabled.
 */

int
dmalock( dfp, fun, arg )
register TIM  * dfp;
vfp_t		fun;
int		arg;
{
	register int s;		/* Interrupt mask state. */

	/*
	 * If DMA locking is disabled, allow functions to proceed.
	 */
 	if ( DMALCK == 0 )
		return( 0 );

	/*
	 * Record function and argument to be invoked upon dmaunlock.
	 */
	dfp->t_func = fun;
	dfp->t_farg = arg;
	dfp->t_next = (TIM *)0;

	s = sphi();

	/*
	 * If the queue is empty, put our structure at the head.
	 */
	if ( dmahead == (TIM *)0 ) {
		dmahead = dfp;
		dmatail = dfp;
		spl( s );
		return( 0 );
	}

	/*
	 * PARANOIA:	If our structure is already at the head of the queue,
	 *		print a message and return.
	 */
	if ( dmahead == dfp ) {
		spl( s );
		printf( "dmalock: driver attempting to doubly lock DMA controller.\n" );
		return( 0 );
	}

	/*
	 * Append to tail of DMA deferred function queue.
	 */
	dmatail->t_next = dfp;
	dmatail		= dfp;
	spl( s );
	return( -1 );
}

/*
 * void
 * dmaunlock( dfp )
 * TIM * dfp;
 *
 *	Inputs:	dfp = Deferred function structure pointer.
 *
 *	Action:	Unlocks the DMA controller and calls the next deferred
 *		function, if any.
 *
 *	Notes:	No action is taken if the deferred function structure pointer
 *		is not the same as the one used to lock the DMA controller.
 */

void
dmaunlock( dfp )
register TIM * dfp;
{
	register TIM *	qp;	/* Temporary function queue pointer.	*/
	register int	s;	/* Interrupt mask state.		*/

	s = sphi();

	/*
	 * If the DMA controller is not locked, return.
	 */
	if ( dmahead == (TIM *)0 ) {
		spl( s );
		return;
	}

 	/*
	 * If our lock is not the one holding the DMA controller:
	 */
	if ( dmahead != dfp ) {

		/*
		 * Look for us in queue.
		 */
		for ( qp = dmahead; qp != dmatail; qp = qp->t_next )

			/*
			 * If found, remove us.
			 */
			if ( qp->t_next == dfp ) {
				qp->t_next = dfp->t_next;

				if ( dmatail == dfp )
					dmatail = qp;

				break;
			}

		spl( s );
		return;
	}

	/*
	 * If there are no functions waiting for us, empty queue and return.
	 */
	if ( dmahead == dmatail ) {
		dmahead = (TIM *)0;
		spl( s );
		return;
	}

	/*
	 * Remove us and execute next deferred function.
	 */
	dmahead = dmahead->t_next;
	spl( s );
	(*dmahead->t_func)( dmahead->t_farg, dmahead );
}

0707070064030147661006440000030000030000011777770507310720200005000000043427/newbits/kernel/USRSRC/i8086/src/exec.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * This file contains a special version
 * of "sys exec" for the i8086. This version has
 * no driver load code in it (save space) and has
 * special load code so that the text of a shared
 * and separated image can be shared.
 * Loadable kernel processes are partially supported:
 * the process text and data must be ld'ed with the system
 * and the l.out executed must have no loadable or allocateable
 * segments.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:26	src
 * Initial revision
 * 
 * 88/01/21	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * Segments are now de-associated from processes before freeing the segment.
 *
 * 87/12/03	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * ld_start() now reverts to kernel mode [depth=0] from user mode [depth=1].
 *
 * 87/11/25	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/11/14	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * Init code+data now split into icodep/icodes and idatap/idatas.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/10/09	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * pload() now handles new format [separate code] loadable device drivers.
 *
 * 87/10/08	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * Exsread() initializes the (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <l.out.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>
#include <sys/i8086.h>

/*
 * Sizes.
 */
#define	sh	((fsize_t)sizeof(struct ldheader))
#define si	lssize[L_SHRI]
#define pi	lssize[L_PRVI]
#define bi	lssize[L_BSSI]
#define sd	lssize[L_SHRD]
#define pd	lssize[L_PRVD]
#define bd	lssize[L_BSSD]

/*
 * Segments.
 */
#define upsp	pp->p_segp[SIUSERP]
#define sssp	pp->p_segp[SISTACK]
#define	sisp	pp->p_segp[SISTEXT]
#define pisp	pp->p_segp[SIPTEXT]
#define pdsp	pp->p_segp[SIPDATA]

/*
 * Loadable driver initiation point.
 */
static
ld_start()
{
	register SEG * sp;
	register int ret;

	/*
	 * Kernel processes start by default at user level.
	 * Revert to kernel level.
	 */
	if ( depth == 1 )
		depth--;

	/*
	 * Initialize memory references.
	 */
	u.u_btime = timer.t_time;
	sproto();
	segload();


	/*
	 * Invoke the driver if it has a shared or private code segment.
	 */
	ret = 100;
	if ( (sp = SELF->p_segp[SISTEXT]) || (sp = SELF->p_segp[SIPTEXT]) ) {
		ret = ld_xcall( sp->s_faddr );
	}

	uexit( ret );
}

/*
 * Set up the first process, a small programme which will exec
 * the init programme.
 */
eveinit(sp)
SEG *sp;
{
	register PROC *pp;
	SELF = pp = eprocp;

	/*
	 * Record user area.
	 */
	pp->p_segp[SIUSERP] = sp;

	/*
	 * Allocate, record, initialize code segment, make it executable.
	 */
	if ((sp=salloc((fsize_t)icodes, 0)) == NULL)
		panic("eveinit(code)");
	pp->p_segp[SIPTEXT] = sp;
	kfcopy( icodep, sp->s_faddr, icodes );
	sp->s_flags |= SFTEXT;
	vremap(sp);

	/*
	 * Allocate, record, and initialize data segment.
	 */
	if ((sp=salloc((fsize_t)idatas, 0)) == NULL)
		panic("eveinit(data)");
	pp->p_segp[SIPDATA] = sp;
	kfcopy( idatap, sp->s_faddr, idatas );

	/*
	 * Allocate and record stack segment.
	 */
	if ((sp=salloc((fsize_t)UPASIZE, SFDOWN)) == NULL)
		panic("eveinit()");
	pp->p_segp[SISTACK] = sp;

	/*
	 * Start process.
	 */
	u.u_argp = 0;
	if (sproto() == 0)
		panic("eveinit()");
	segload();
}

/*
 * Load a driver which has already been linked into the system image.
 */
pload( np )
char * np;
{
	register INODE * ip;
	register PROC  * cpp;
	struct seg     * sp;
	fsize_t		lssize[NUSEG];		/* Segment sizes */
	int		lflag;			/* l_flags from l.out */
	vaddr_t		pc;			/* l_entry from l.out */
	int		r;			/* Flag for "exload" */
	int		s;
	extern char	end[];


	if (super() == 0) {
		return( -1 );
	}

	/*
	 * Coalesce memory BEFORE loading driver, since it can't be moved.
	 */
	krunch(10000);

	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
		return( -1 );
	}

	/*
	 * New format loadable drivers must have separate code/data.
	 * It must have executable code, but no initialized data.
	 * Uninitialized data must match the kernel data size.
	 */
	if ( ((lflag & (LF_KER|LF_SHR|LF_SEP)) != (LF_SEP|LF_KER))
	  || (si==0) || (sd!=0) || (pd!=0) || (bd != (int)end) ) {
		u.u_error = EBADFMT;
		idetach(ip);
		return( -1 );
	}

	/*
	 * Allocate and initialize driver code segment.
	 * NOTE: Must be system segment to prevent relocation.
	 */
	sp = ssalloc(&r, ip, SFTEXT|SFHIGH|SFNSWP|SFSYST, si+pi+bi, sh, si+pi);

	/*
	 * Release driver object file.
	 */
	idetach(ip);

	if ( r < 0 ) {
		u.u_error = ENOMEM;
		return( -1 );
	}

	/*
	 * Spawn kernel process to service driver.
	 */
	if ((cpp = process(ld_start)) == NULL ) {
		u.u_error = ENOMEM;
		sfree(sp);
		return( -1 );
	}

	/*
	 * Record the basename of the loaded driver.
	 */
	kscopy( u.u_direct.d_name, cpp->p_segp[SIUSERP],
		offset(uproc,u_comm[0]), sizeof(u.u_comm) );

	/*
	 * Record the driver code segment in the process's private code.
	 */
	cpp->p_segp[SIPTEXT] = sp;
	cpp->p_cval = CVCHILD;
	cpp->p_sval = SVCHILD;
	cpp->p_rval = RVCHILD;
	cpp->p_ppid = 1;

	/*
	 * Make the process executable.
	 */
	s = sphi();
	setrun( cpp );
	spl( s );

	/*
	 * Return driver process id.
	 */
	return( cpp->p_pid );
}

/*
 * Given a major number, undo the previous function.
 */
puload(m)
int m;
{
	register CON *cp;
	register DRV *dp;

	dp = &drvl[m];
	lock(dp->d_gate);
	if (m>=drvn || (cp=dp->d_conp)==NULL) {
		u.u_error = ENXIO;
		goto ret;
	}
	(*cp->c_uload)();
	if ( ! u.u_error)
		dp->d_conp = NULL;
ret:
	unlock(dp->d_gate);
	return (0);
}

/*
 * Pass control to an image in a file.
 * Make sure the format is acceptable. Release
 * the old segments. Read in the new ones. Some special
 * care is taken so that shared and (more important) shared
 * and separated images can be run on the 8086.
 */
pexece(np, argp, envp)
char	*np;
char	*argp[];
char	*envp[];
{
	register INODE	*ip;			/* Load file INODE */
	register PROC	*pp;			/* A cheap copy of SELF */
	register SEG	*ssp;			/* New stack segment */
 	register SEG    *segp;
	register fsize_t	ss;			/* Segment size temp. */
	register int	i;			/* For looping over segments */
	int		r;			/* Flag for "exload" */
	int		lflag;			/* l_flags from l.out */
	vaddr_t		pc;			/* l_entry from l.out */
	vaddr_t		sp;			/* Initial stack pointer */
	fsize_t		lssize[NUSEG];		/* Segment sizes */
	fsize_t		codsize;		/* Total if CS segment	*/
	fsize_t		datsize;		/* Total of DS segment	*/
	extern fsize_t	exround();		/* Paragraph rounder */

	pp = SELF;
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
		return;
	}

	if ( (lflag & LF_SEP) == 0 ) {
		u.u_error = EBADFMT;
		idetach(ip);
		return;
	}

	/*
	 * Kernel processes are now supported through the sload() system call.
	 * 87/10/09	Allan Cornish.
	 */
	if ((lflag&LF_KER) != 0) {
		u.u_error = EBADFMT;
		idetach(ip);
		return;
	}

	/*
	 * If a shared and separated image
 	 * has stuff in segments that makes it impossible
	 * to share, give an error immediately so that we don't
	 * lose the parent.
	 */
	lflag &= LF_SHR|LF_SEP;

	if (lflag==(LF_SHR|LF_SEP) && (pi!=0 || bi!=0)) {
		u.u_error = EBADFMT;
		idetach(ip);
		return;
	}

	if ((ssp=exstack(&sp, argp, envp)) == NULL) {
		idetach(ip);
		return;
	}

	switch (lflag) {
	case LF_SEP:
		codsize = si+pi+bi;
		datsize = ssp->s_size+sd+pd+bd;
		break;
	case LF_SHR|LF_SEP:
		codsize = si;
		datsize = ssp->s_size+exround(sd)+pd+bd;
		break;
	}
	codsize = (codsize+(BSIZE-1)) & ~(BSIZE-1);
	datsize = (datsize+(BSIZE-1)) & ~(BSIZE-1);
	if ( (codsize >= MAXU) || (datsize >= MAXU) ) {
		u.u_error = E2BIG;
		idetach(ip);
		return;
	}

	/*
	 * At this point the file has been
	 * validated as an object module, and the
	 * argument list has been built. Release all of
	 * the original segments. At this point we have
	 * committed to the new image. A "sys exec" that
	 * gets an I/O error is doomed.
 	 * NOTE: User-area segment is NOT released.
 	 *	 Segment pointer in proc is erased BEFORE invoking sfree().
	 */
	for ( i = 1; i < NUSEG; ++i ) {
 		if ((segp = pp->p_segp[i]) != NULL) {
			pp->p_segp[i] = NULL;
			sfree(segp);
		}
	}

	/*
	 * Read in the loadable segments.
	 */
	sssp = ssp;
	switch (lflag) {
	case 0:
		ss = si+pi+sd+pd;
		pdsp = ssalloc(&r, ip, 0, ss+bi+bd, sh, ss);
		if (r < 0)
			goto out;
		break;

	case LF_SHR:
		ss = exround(si+sd);
		pdsp = ssalloc(&r, ip, 0, ss+pi+pd+bi+bd, sh, si);
		if (r < 0)
			goto out;
		if (exsread(pdsp, ip, sd, sh+si+pi, si) == NULL)
			goto out;
		if (exsread(pdsp, ip, pi, sh+si, ss) == NULL)
			goto out;
		if (exsread(pdsp, ip, pd, sh+si+pi+sd, ss+pi) == NULL)
			goto out;
		break;

	case LF_SEP:
		pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+pi, sd+pd);
		if (r < 0)
			goto out;
		break;

	case LF_SHR|LF_SEP:
		/* pi=0, bi=0 */
		sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si);
		if (r < 0)
			goto out;
		ss = exround(sd);
		pdsp = ssalloc(&r, ip, 0, ss+pd+bd, sh+si, sd);
		if (r<0 || exsread(pdsp, ip, pd, sh+si+sd, ss) == NULL)
			goto out;
	}
	if (sproto() == 0)
		 goto out;
#if 0
	if ( (datsize != pdsp->s_size) ||
	     ( (lflag==LF_SEP) && (codsize != pisp->s_size) ) ||
	     ( (lflag==(LF_SEP|LF_SHR)) && (codsize != sisp->s_size) ) ) {
		printf("\nExec ERROR:  codsize: 0x%X  datsize: 0x%X\n", 
					codsize, datsize);
		printf(
		"pdsp->s_size: 0x%X  pisp->s_size: 0x%X  sisp->s_size: 0x%X\n",
			pdsp->s_size, pisp->s_size, sisp->s_size);
	}
#endif
	/*
	 * The new image is read in
	 * and mapped. Perform the final grunge
	 * (set-uid stuff, accounting, loading up
	 * registers, etc).
	 */
	u.u_flag &= ~AFORK;
	kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
	if (iaccess(ip, IPR) == 0) {	/* Can't read ? no dump or trace */
		pp->p_flags |= PFNDMP;
		pp->p_flags &= ~PFTRAC;
	}
	if (iaccess(ip, IPW) == 0)	/* Can't write ? no trace */
		pp->p_flags &= ~PFTRAC;
	if ((ip->i_mode&ISUID) != 0) {	/* Set user id ? no trace */
		pp->p_uid = u.u_uid = ip->i_uid;
		pp->p_flags &= ~PFTRAC;
	}
	if ((ip->i_mode&ISGID) != 0) {	/* Set group id ? no trace */
		u.u_gid = ip->i_gid;
		pp->p_flags &= ~PFTRAC;
	}
	for (i=0; i<NSIG; ++i)
		if (u.u_sfunc[i] != SIG_IGN)
			u.u_sfunc[i] = SIG_DFL;
	if ((pp->p_flags&PFTRAC) != 0)	/* Being traced */
		sendsig(SIGTRAP, pp);
	idetach(ip);
	msetusr(pc, sp);
	segload();
	return (0);

	/*
	 * We did not make it.
	 * Release the INODE for the load
	 * file, and return through the "sys exit"
	 * code with a "SIGSYS", or with the signal actually received
	 * if we are aborting due to interrupted exec.
	 */
out:
	idetach(ip);
	if (u.u_error == EINTR)
		pexit(nondsig());
	pexit(SIGSYS);
}

/*
 * Open an l.out, make sure it is an l.out and executable and return the
 * appropriate information.
 */
INODE *
exlopen(np, ssizep, flagp, pcp)
char *np;
fsize_t *ssizep;
int *flagp;
vaddr_t *pcp;
{
	register INODE *ip;
	register struct ldheader *ldp;
	register int n;
	register BUF *bp;
	int m;

	/*
	 * Make sure the file is really an executable l.out and read the
	 * header in.
	 */
	if (ftoi(np, 'r') != 0)
		return (NULL);
	ip = u.u_cdiri;
	if (iaccess(ip, IPE) == 0) {
		idetach(ip);
		return (NULL);
	}
	if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
		u.u_error = EACCES;
		idetach(ip);
		return (NULL);
	}
	if ((bp=vread(ip, (daddr_t)0)) == NULL) {
		u.u_error = EBADFMT;
		idetach(ip);
		return (NULL);
	}

	/*
	 * Copy everything we need from the l.out header and check magic
	 * number and machine type.
	 */
	ldp = FP_OFF(bp->b_faddr);
	m = ldp->l_magic;
	canint(m);
	if (m != L_MAGIC) {
		u.u_error = ENOEXEC;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	m = ldp->l_machine;
	canint(m);
	if (m != mactype) {
		u.u_error = EBADFMT;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(fsize_t));
	for (n=0; n<NXSEG; n++)
		cansize(ssizep[n]);
	*flagp = ldp->l_flag;
	canint(*flagp);
	*pcp = ldp->l_entry;
	canvaddr(*pcp);
	brelease(bp);
	return (ip);
}

/*
 * Given a segment `sp', read `ss' bytes from the inode `ip' starting
 * at seek address `sa' into offset `so' in the segment.
 */
SEG *
exsread(sp, ip, ss, sa, so)
register SEG *sp;
INODE *ip;
fsize_t ss;
fsize_t sa;
fsize_t so;
{
	while (ss > 0) {
		u.u_io.io_seg = IOPHY;
		u.u_io.io_seek = sa;
		u.u_io.io_phys = sp->s_paddr + so;
		u.u_io.io_flag = 0;
		if (ss >= 4096) {
			u.u_io.io_ioc = 4096;
			ss -= 4096;
		} else {
			u.u_io.io_ioc = ss;
			ss = 0;
		}
		sp->s_lrefc++;
		iread(ip, &u.u_io);
		sp->s_lrefc--;
		if (nondsig()) {
			u.u_error = EINTR;
			break;
		}
		sa += 4096;
		so += 4096;
	}
	if (u.u_error == 0)
		return (sp);
	return (NULL);
}

/*
 * Given a pointer to a list of arguments and a pointer to a list of
 * environments, return a stack with the arguments and environments on it.
 */
SEG *
exstack(iusp, argp, envp)
char **iusp;		/* Back patch sp value */
char *argp[];		/* Arguments for new process */
char *envp[];		/* Environments for new process */
{
	SEG *sp;		/* Stack segment pointer */
	struct adata {		/* Storage for arg and env data */
		char	**up;		/* User vector pointer */
		int	np;		/* Number of pointers in vector */
		int	nc;		/* Number of characters in strings */
	} arg, env;
	struct sdata {		/* To keep segment pointers */
		vaddr_t	base;		/* Top of segment virtual */
		vaddr_t	ap;		/* Argc, argv, envp pointer */
		vaddr_t	vp;		/* Argv[i], envp[i] pointer */
		vaddr_t	cp;		/* Argv[i][j], envp[i][j] pointer */
	} aux, stk;
	aold_t aold;			/* Auxiliary map storage */
	register char **usrvp;		/* Vector pointer into user seg */
	register char *usrcp;		/* Character pointer into user seg */
	register int c;			/* Character fetched from user */
	register int chrsz;		/* Size of strings */
	register struct adata *adp;	/* Arg and env scanner */
	register int vecsz;		/* Size of vectors */
	register int stksz;		/* Size of stack argument region */

	/* Validate and evaluate size of args and envs */
	arg.up = argp;
	env.up = envp;
	chrsz = 0;
	vecsz = 0;
	for (adp = &arg; ; adp = &env) {
		adp->np = 0;
		adp->nc = 0;
		if (excount(adp->up, &adp->np, &adp->nc) == 0)
			return (NULL);
		chrsz += adp->nc * sizeof(char);
		vecsz += adp->np * sizeof(char *);
		if (adp == &env)
			break;
	}

	/* Calculate stack size and allocate it */
	chrsz = roundu(chrsz, sizeof(int));
	stksz = sizeof(int)		/* argc */
		+ sizeof(char **)	/* argv */
		+ sizeof(char **)	/* envp */
		+ vecsz			/* argv[i] and envp[i] */
		+ chrsz			/* *argv[i] and *envp[i] */
		+ sizeof(int)		/* Mystery zero word */
		+ sizeof(char *)	/* Splimit for z8000 */
		+ sizeof(int);		/* errno */
	stksz += ISTSIZE;
	if (stksz > MADSIZE) {
		u.u_error = E2BIG;
		return (NULL);
	}
	if ((sp=salloc((fsize_t)stksz, SFDOWN)) == NULL)
		return (NULL);
	stksz -= ISTSIZE;

	/*
	 * Initialize segment data.
	 */
	asave(aold);

	abase(FP_SEL(sp->s_faddr));
	aux.base = sp->s_size;
	aux.ap = aux.base - stksz;
	aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **);
	aux.cp = aux.vp + vecsz;

	stk.base = ISTVIRT;
	stk.ap = stk.base - stksz;
	stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **);
	stk.cp = stk.vp + vecsz;

	/*
	 * Write argc.
	 */
	aputi((int *)aux.ap, arg.np-1);
	aux.ap += sizeof(int);

	/*
	 * Arguments and environments.
	 */
	for (adp = &arg; ; adp = &env) {

		/* Write argv or envp */
		aputp((char ***)aux.ap, (char **)stk.vp);
		aux.ap += sizeof(char **);
		if ((usrvp = adp->up) != NULL) {

			/* Write argv[i] or envp[i] */
			while ((usrcp = getupd(usrvp++)) != NULL) {
				aputp((char **)aux.vp, (char *)stk.cp);
				aux.vp += sizeof(char *);
				stk.vp += sizeof(char *);

				/* Write argv[i][j] or envp[i][j] */
				do {
					c = getubd(usrcp++);
					aputc((char *)aux.cp, c);
					aux.cp += sizeof(char);
					stk.cp += sizeof(char);
				} while (c != '\0');
			}
		}

		/* Write argv[argc] or envp[envc] */
		aputp((char **)aux.vp, NULL);
		aux.vp += sizeof(char *);
		stk.vp += sizeof(char *);
		if (adp == &env)
			break;
	}

	/*
	 * Clear out the slop.
	 */
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* errno */
	aux.base -= sizeof(char *);
	aputp((char **) aux.base, (char *)stk.base - sp->s_size + SOVSIZE);
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* mystery word */

	arest(aold);

	/*
	 * Patch some values and return.
	 */
	*iusp = stk.ap;		/* Patch initial usp */
	u.u_argc = arg.np-1;
	u.u_argp = stk.vp;	/* Points after NULL of envs */
	return (sp);
}

/*
 * Given a pointer to a list of arguments, a pointer to an argument count
 * and a pointer to a byte count, update incrementally the argument count
 * and the byte count.
 */
excount(usrvp, nap, nbp)
register char **usrvp;
int *nap;
int *nbp;
{
	register char *usrcp;
	register int c;
	register unsigned nb;
	register unsigned na;

	na = 1;
	nb = 0;
	if (usrvp != NULL) {
		for (;;) {
			usrcp = getupd(usrvp++);
			if (u.u_error)
				return (0);
			if (usrcp == NULL)
				break;
			na++;
			for (;;) {
				c = getubd(usrcp++);
				if (u.u_error)
					return (0);
				nb++;
				if (c == '\0')
					break;
			}
		}
	}
	*nap += na;
	*nbp += nb;
	return (1);
}

/*
 * Round up a size to a paragraph
 * (mod 16) boundry.
 * This is really mod 512 to make swapping work
 */
fsize_t
exround(s)
fsize_t	s;
{
	return ((s+15)&~0x0F);
}
0707070064030147651006440000030000030000011777770507310720700005200000007677/newbits/kernel/USRSRC/i8086/src/krunch.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Coherent.
 * Segment crunch.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:33	src
 * Initial revision
 * 
 * 87/12/02	Allan Cornish	/usr/src/sys/i8086/src/krunch.c
 * krunch() now locks/unlocks segment gate.
 *
 * 87/11/26	Allan Cornish	/usr/src/sys/i8086/src/krunch.c
 * krunch() now called to merge unused memory by moving segments.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/proc.h>
#include <sys/seg.h>

/*
 * Time interval in clock ticks between krunch attempts: default 2 seconds.
 */
int KRUNCH = 200;

/**
 *
 * krunch( n )
 * int n;
 *
 *	Input:	n = maximum number of segments to be moved.
 *
 *	Action:	Scan the segmentation list, looking for unused memory
 *		immediately below unlocked application segments,
 *		moving the segment down into the unused memory.
 */
krunch( n )
int n;
{
	register SEG *sp;
	paddr_t paddr;
	saddr_t osel;
	static TIM tim;
	int s;

	if ( depth != 0 ) {
		printf("krunch(%d,depth=%d) ", n, depth );	/** DEBUG **/
		return;
	}

	/*
	 * Do not crunch segment list if swapper is active.
	 */
	if ( (KRUNCH == 0) || (sexflag != 0) )
		return;

	/*
	 * Segment count of 0 indicates a request to schedule delayed krunch(1).
	 */
	if ( n <= 0 ) {
		if ( tim.t_last != NULL )
			timeout( &tim, KRUNCH, krunch, 1 );
		return;
	}

	/*
	 * Segmentation is locked - retry later.
	 */
	s = sphi();
	if ( locked(seglink) ) {
		timeout( &tim, KRUNCH, krunch, n );
		spl(s);
		return;
	}
	lock(seglink);
	spl(s);

#if EBUG > 1
	printf("krunch(%d) ", n );
#endif

	for ( paddr = corebot, sp = &segmq;
	      (sp = sp->s_forw) != &segmq ;
	      paddr = sp->s_paddr + sp->s_size ) {

		/*
		 * No hole exists.
		 */
		if ( paddr == sp->s_paddr )
			continue;

#if EBUG > 1
		printf("hole(p=%X,n=%X) seg(p=%X,n=%X,f=%x,u=%x,l=%x) ",
			paddr,
			sp->s_paddr - paddr,
			sp->s_paddr,
			sp->s_size,
			sp->s_flags & (SFSYST|SFHIGH),
			sp->s_urefc,
			sp->s_lrefc );
#endif

		/*
		 * Don't try to shuffle high segments into low memory.
		 */
		if ( sp->s_flags & SFHIGH )
			break;

		/*
		 * System segment.
		 */
		if ( sp->s_flags & SFSYST )
			continue;

		/*
		 * Segment may be in process of being swapped in/out.
		 */
		if ( (sp->s_flags & SFCORE) == 0 )
			continue;

		/*
		 * Segment is locked for I/O.
		 */
		if ( sp->s_lrefc != sp->s_urefc )
			continue;

#if EBUG > 0
		printf("move(dst=%X,src=%X,len=%X) ",
			paddr, sp->s_paddr,sp->s_size );
#endif
		/*
		 * Remember previous virtual address.
		 */
		osel = FP_SEL(sp->s_faddr);

		/*
		 * Shift segment into the hole.
		 */
		plrcopy( sp->s_paddr, paddr, sp->s_size );
		sp->s_paddr = paddr;
		vremap( sp );

#if EBUG > 0
		if ( FP_SEL(sp->s_faddr) != osel ) {
			printf("krunch: osel=%x nsel=%x\n",
				osel, FP_SEL(sp->s_faddr) );
		}
#endif

		/*
		 * Ensure user segmentation is updated.
		 * We may have moved the current process.
		 */
		if ( (SELF->p_pid != 0) && ((ucs == osel) || (uds == osel)) )
			segload();
		if ( uasa == osel )
			uasa = FP_SEL(sp->s_faddr);

		/*
		 * Crunch count reached.
		 */
		if ( --n <= 0 )
			break;
	}

	/*
	 * Cancel timer if all low memory holes eliminated.
	 */
	if ( (KRUNCH == 0) || (sp == &segmq) || (sp->s_flags & SFHIGH) )
		timeout( &tim, 0, NULL, 0 );

	/*
	 * Attempt to crunch another segment in KRUNCH clock ticks.
	 */
	else
		timeout( &tim, KRUNCH, krunch, 1 );

	unlock(seglink);

#if EBUG > 0
	printf("\n");
#endif
}
0707070064030147641006440000030000030000011777770507310721000004600000004047/newbits/kernel/USRSRC/i8086/src/ld.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1986
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Pseudo-Device Interface to Loadable Drivers.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:36	src
 * Initial revision
 * 
 * 87/12/08	Allan Cornish	/usr/src/sys/i8086/src/ld.c
 * Block device interface added to loadable drivers.
 *
 * 87/10/25	Allan Cornish		/usr/src/sys/i8086/drv/ld.c
 * Initial version.
 */

#include	<sys/coherent.h>
#include 	<sys/fdisk.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>

/*
 * Driver configuration.
 */
void	ld_open();
void	ld_close();
void	ld_read();
void	ld_write();
void	ld_block();
int	ld_ioctl();
void	ld_power();
void	ld_time();
int	ld_poll();
void	nulldev();
void	nonedev();

/*
 * Loadable driver: Pseudeo-device configuration.
 */
CON ldrvpsy = {
	DFCHR|DFBLK|DFPOL,		/* Flags */
	0,				/* Major index */
	ld_open,			/* Open */
	ld_close,			/* Close */
	ld_block,			/* Block */
	ld_read,			/* Read */
	ld_write,			/* Write */
	ld_ioctl,			/* Ioctl */
	ld_power,			/* Powerfail */
	ld_time,			/* Timeout */
	nulldev,			/* Load */
	nulldev,			/* Unload */
	ld_poll				/* Poll */
};

/*
 * Loadable driver: Code selectors.
 */
saddr_t ldrvsel[NDRV];

/*
 * Loadable driver: Pointers to driver configuration table.
 */
CON * ldrvcon[NDRV];

/*
 * Loadable driver: Selector referencing interrupt handler's code segment.
 */
saddr_t ldrvics[16];

/*
 * Loadable driver: Pointers to interrupt handlers within the loadable driver.
 */
void (*ldrvipc[16])();
0707070064030147621006440000030000030000011777770507310721000005000000031676/newbits/kernel/USRSRC/i8086/src/ldas.s/ /usr/src/sys/i8086/src/ldas.s
/ 
////////
/
/	Loadable Driver Interface Routines.
/
/	Loadable drivers execute in separate code segments, and are unable
/	to directly call kernel service routines.
/	Loadable drivers call a kernel service stub within their code segment,
/	which has has the same name as the desired service routine.
/	The driver service stub performs a far call to one of these routines.
/	These routines perform a near call to the desired kernel routine,
/	and then perform a far return to the driver service stub routine.
/	The driver service stub routine then does a near return to the driver.
/
/ 90/09/11  Hal Snyder
/ Add ld_call()
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.2	91/03/01  09:23:04	root
/ Part of COHERENT 3.1.0 kernel
/ 
/ Revision 1.1	88/03/24  17:39:39	src
/ Initial revision
/ 
/ 87/12/08	Allan Cornish	/usr/src/sys/i8086/src/ldas.s
/ Block device interface added to loadable drivers.
/ ldtimcall() function added to support timed functions in loadable drivers.
/
/ 87/10/25	Allan Cornish	/usr/src/sys/i8086/src/ldas.s
/ Initial version - interface to/from loadable driver processes.
/
////////

	.globl	ld_xcall_
	.globl	ld_call_
	.globl	xcalled
	.globl	ldtimcall_
	.globl	ld_open_
	.globl	ld_close_
	.globl	ld_read_
	.globl	ld_write_
	.globl	ld_block_
	.globl	ld_ioctl_
	.globl	ld_power_
	.globl	ld_time_
	.globl	ld_poll_
	.globl	ldrvint_		/ void  (*ldrvint[16])();

////////
/
/ Constants
/
////////

	T_LDRV	= 12			/ Offset(tim,t_ldrv).
	B_FLAG	= 6			/ Offset(buf,b_flag).
	B_DEV	= 8			/ Offset(buf,b_dev ).
	BFERR	= 4			/ buf.b_flag bit set on I/O error.
	DRV_J	= 4			/ offset in driver of dispatcher

////////
/
/ External References
/
////////

	.globl	nonedev_		/ extern void	 nonedev();
	.globl	ldrvcon_		/ extern CON *	 ldrvcon[NDRV];
	.globl	ldrvsel_		/ extern saddr_t ldrvsel[NDRV];
	.globl	ldrvics_		/ extern saddr_t ldrvics[16];
	.globl	ldrvipc_		/ extern void  (*ldrvipc[16])();

////////
/
/ Shared Data
/
////////
	.shrd
ldrvint_:			/ Loadable Driver Interrupt Entry Points.
	.word	ld_intr0
	.word	ld_intr1
	.word	ld_intr2
	.word	ld_intr3
	.word	ld_intr4
	.word	ld_intr5
	.word	ld_intr6
	.word	ld_intr7
	.word	ld_intr8
	.word	ld_intr9
	.word	ld_intr10
	.word	ld_intr11
	.word	ld_intr12
	.word	ld_intr13
	.word	ld_intr14
	.word	ld_intr15

////////
/
/ Private Data
/
////////

	.prvd
	.shri

////////
/
/ Driver Configuration: Offsets to Function Pointers
/
////////

	C_OPEN=4
	C_CLOSE=6
	C_BLOCK=8
	C_READ=10
	C_WRITE=12
	C_IOCTL=14
	C_POWER=16
	C_TIMER=18
	C_LOAD=20
	C_ULOAD=22
	C_POLL=24

////////
/
/ ld_xcall( fp )	- invoke far function.
/ int (far *fp)();
/
////////

ld_xcall_:
	cli
	push	bp
	mov	bp, sp
	xcall	4(bp)
	pop	bp
	ret

////////
/
/ call a driver function from the kernel
/   sel		- CS selector for the driver
/   fn		- offset in the driver of the function we want
/   arg[1-3]    - optional arguments
/
/ ld_call(sel, fn, arg1, arg2, arg3)
/ int sel;
/ int (*fn)(void);
/ int arg1, arg2, arg3;
/
////////

/ stack when ld_call() is called:
/	arg3
/	arg2
/	arg1
/	fn
/	sel
/	return IP

ld_call_:			/ PARAMETERS (arg[1-3]) MUST BE FOUND AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
/	lea	bp, 4(sp)	/ this is what the next 2 instructions do
	mov	bp, sp
	add	bp, $4
				/
	push	0(bp)		/ Push sel to allow far call
	push	$DRV_J		/
				/
	mov	ax, 2(bp)	/ Push fn
				/
	xcall	-8(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	lea	sp, -4(bp)	/
	pop	bp		/
	ret			/

////////
/
/
/ ldtimcall( arg, tp )  - service timed far function.
/
////////

ldtimcall_:				/
	push	bp			/
	mov	bp, sp			/
					/
	mov	bx, 6(bp)		/
	mov	ax, T_LDRV+2(bx)	/
	push	ax			/ Loadable driver code selector.
	push	$DRV_J			/ Loadable driver invocation offset.
	mov	ax, T_LDRV(bx)		/ Desired far function.
					/
	xcall	-4(bp)			/
					/
	mov	sp, bp			/
	pop	bp			/
	ret

////////
/
/ xcalled( f, args )
/ int (*f)();
/
/	Input:	AX is pointer to kernel function to be invoked.
/
/	Action:	Perform a near call to the specified kernel function,
/		passing 6 words as optional arguments.
/		Perform a far return.
/
/	Notes:	Invoked by far call from loadable device driver.
/
////////

xcalled:			/ 6(bp) = grand-parent IP.
	push	bp		/ 4(bp) = parent CS
	mov	bp, sp		/ 2(bp) = parent IP
				/ AX    = destination function.
	push	20(bp)	/ Arg 7 /
	push	18(bp)	/ Arg 6	/
	push	16(bp)	/ Arg 5	/
	push	14(bp)	/ Arg 4	/
	push	12(bp)	/ Arg 3	/
	push	10(bp)	/ Arg 2	/
	push	 8(bp)	/ Arg 1	/
	icall	ax		/
				/
	mov	sp, bp		/ Return to loadable driver.
	pop	bp		/
	xret			/

////////
/
/ ld_open( dev, mode )		- Open Routine.
/ dev_t dev;
/ int mode;
/
////////

ld_open_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_OPEN(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_close( dev )		- Close Routine.
/ dev_t dev;
/
////////

ld_close_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_CLOSE(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_read( dev, iop )		- Read Routine.
/ dev_t dev;
/ IO * iop;
/
////////

ld_read_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_READ(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

///////
/
/ ld_write( dev, iop )		- Write Routine.
/ dev_t dev;
/ IO * iop;
/
////////

ld_write_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_WRITE(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

///////
/
/ ld_block( bp )		- Block Routine.
/ BUF * bp;
/
////////

ld_block_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	mov	bx, 4(bp)	/ Calculate major device number * 2.
	movb	bl, B_DEV+1(bx)	/
	subb	bh, bh		/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_BLOCK(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	bx, 4(bp)	/ bp->b_flag |= BFERR.
	or    B_FLAG(bx),$BFERR	/
	mov	sp, bp		/
	pop	bp		/
	jmp	bdone_		/ bdone(bp);

////////
/
/ ld_ioctl( dev, iop )		- Ioctl Routine.
/ dev_t dev;
/ IO * iop;
/
////////

ld_ioctl_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_IOCTL(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_power( dev )		- Powerfail Routine.
/ dev_t dev;
/
////////

ld_power_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_POWER(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_time( dev )		- Timer Routine.
/ dev_t dev;
/
////////

ld_time_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_TIMER(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_poll( dev, ev, msec )	- Poll Routine.
/ dev_t dev;
/ int ev;
/ int msec;
/
////////

ld_poll_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_POLL(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ Loadable Driver Interrupt Entry Points.
/
/	Invoked by Coherent to service specific interrupt.
/	Identifies which loadable driver interrupt vector to be used.
/	Invokes interrupt handler which will do far call to loadable driver.
/
////////

ld_intr0:
	mov	bx, $0		/
	jmp	ld_intr		/

ld_intr1:
	mov	bx, $2		/
	jmp	ld_intr		/

ld_intr2:
	mov	bx, $4		/
	jmp	ld_intr		/

ld_intr3:
	mov	bx, $6		/
	jmp	ld_intr		/

ld_intr4:
	mov	bx, $8		/
	jmp	ld_intr		/

ld_intr5:
	mov	bx, $10		/
	jmp	ld_intr		/

ld_intr6:
	mov	bx, $12		/
	jmp	ld_intr		/

ld_intr7:
	mov	bx, $14		/
	jmp	ld_intr		/

ld_intr8:
	mov	bx, $16		/
	jmp	ld_intr		/

ld_intr9:
	mov	bx, $18		/
	jmp	ld_intr		/

ld_intr10:
	mov	bx, $20		/
	jmp	ld_intr		/

ld_intr11:
	mov	bx, $22		/
	jmp	ld_intr		/

ld_intr12:
	mov	bx, $24		/
	jmp	ld_intr		/

ld_intr13:
	mov	bx, $26		/
	jmp	ld_intr		/

ld_intr14:
	mov	bx, $28		/
	jmp	ld_intr		/

ld_intr15:
	mov	bx, $30		/
	jmp	ld_intr		/

////////
/
/ Loadable driver interrupt handler.
/
/
/	Input:	bx = interrupt number * 2.
/
////////

ld_intr:
	push	bp		/
	mov	bp, sp		/
				/
	mov	cx,ldrvics_(bx)	/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	ax,ldrvipc_(bx)	/ Identify interrupt handler to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
0:	mov	sp, bp		/
	pop	bp		/
	ret			/
0707070064030147631006440000030000030000011777770507310721300004700000012535/newbits/kernel/USRSRC/i8086/src/md1.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * 8086/8088 Coherent.
 * All machines.
 * Machine dependent stuff.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	88/08/05  15:34:26	src
 * mproto(), segload(), and msetsys() functions simplified.
 * 
 * Revision 1.1	88/03/24  17:39:43	src
 * Initial revision
 * 
 * 88/03/10	Allan Cornish		/usr/src/sys/coh/proc.c
 * Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
 * These partial fixes will be removed once all CPU's are replaced.
 *
 * 88/02/13	Allan Cornish		/usr/src/sys/i8086/src/md1.c
 * segload() now checks for regl[OIP] being system code segment.
 * iAPX-286 protected mode interrupt gates enable interrupts momentarily.
 *
 * 88/01/21	Allan Cornish		/usr/src/sys/i8086/src/md1.c
 * Segments are now de-associated from processes before freeing the segment.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/i8086/src/md1.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/09/21	Allan Cornish	/usr/src/sys/i8086/src/md1.c
 * mproto() and setload() modified to support loadable driver processes.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/clist.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Calculate segmentation for a
 * new program. If there is a stack segment
 * present merge it into the data segment and
 * relocate the argument list.
 * Make sure that the changes are reflected in the u.u_segl array
 * which sproto sets up.
 */
mproto()
{
	register PROC	*pp;
	register SEG	*dsp;
	register SEG	*ssp;
	register SEG	*csp;
	fsize_t		ds;
	fsize_t		ss;
	unsigned int	so;
	unsigned int	*up;
	unsigned int	v;

	pp = SELF;

	dsp = pp->p_segp[SIPDATA];

	if ( ((pp->p_flags & PFKERN) == 0)
	  && ((ssp=pp->p_segp[SISTACK]) != NULL) ) {
		ds = dsp->s_size;
		ss = ssp->s_size;
		so = ds + ss;
		if (seggrow(dsp, (fsize_t)so) == 0)
			return (0);
		plrcopy( ssp->s_paddr, dsp->s_paddr + ds, ss);
		pp->p_segp[SISTACK] = NULL;
		sfree(ssp);
		u.u_sproto.mp_svb = ds;
		u.u_sproto.mp_svl = so;
		if (u.u_argp != NULL) {
			abase(FP_SEL(dsp->s_faddr));
			up = u.u_argp += so;
			--up;
			while (ageti(--up) != NULL)
				;
			up -= 2+u.u_argc;
			while ((v=ageti(up)) != NULL)
				aputi(up++, v+so);
			while ((v=ageti(++up)) != NULL)
				aputi(up, v+so);
		}
		return (sproto());	/* Recurse to fix u.u_segl */
	}

	/*
	 * Shared code, private code, or kernel code [csp == NULL].
	 * NOTE: Combined code/data no longer supported.
	 */
	if ( (csp = pp->p_segp[SISTEXT]) == NULL )
		csp = pp->p_segp[SIPTEXT];

	/*
	 * Special case if no code/data segment specified.
	 */
	u.u_sproto.mp_cbp = (csp != NULL) ? &FP_SEL(csp->s_faddr) : &scs;
	u.u_sproto.mp_dbp = (dsp != NULL) ? &FP_SEL(dsp->s_faddr) : &sds;
	u.u_sproto.mp_csl = (csp != NULL) ? csp->s_size - 1 : 0;
	u.u_sproto.mp_dsl = (dsp != NULL) ? dsp->s_size - 1 : 0;

	return (1);
}

/*
 * Load up segmentation registers.
 */
segload()
{
	register unsigned *ip;
	register unsigned s;

	ucs = *u.u_sproto.mp_cbp;
	uds = *u.u_sproto.mp_dbp;
	ucl =  u.u_sproto.mp_csl;
	udl =  u.u_sproto.mp_dsl;

	ip = regl;
	ip[OCS] = ucs;
	ip[ODS] = s = uds;
	ip[OES] = s;
	ip[OSS] = s;
}

/*
 * Set up a new process.
 */
msetusr(ip, sp)
vaddr_t sp;
vaddr_t ip;
{
	regl[OIP] = ip;
	regl[OSP] = sp + u.u_sproto.mp_svl;
}

/*
 * Set up initial context for a system process.
 * System processes run at depth 1, just like any
 * user process. This is necessary to make sure that
 * the machine state save is correctly handled, just
 * in case the clock hits a kernel process executing
 * out of the IBM ROM.
 */
msetsys(mp, fn, us)
register MCON *mp;
int (*fn)();
saddr_t us;
{
	mp->mc_sp = (int)(&u) + UPASIZE - 32;
	mp->mc_pc = fn;
	mp->mc_fw = 0;
	mp->mc_depth = 1;
}

/*
 * Set the given address in the user area to the given value if it is
 * okay to do so.
 */
msetuof(a, v)
register int a;
{
	if (a<UPASIZE+OBP*2 || a>UPASIZE+OFW*2)
		return (0);
	if (a == UPASIZE+OCS*2)
		return (0);
	if (a == UPASIZE+ODS*2)
		return (0);
	if (a == UPASIZE+OES*2)
		return (0);
	if (a == UPASIZE+OSS*2)
		return (0);
	if (a == UPASIZE+OID*2)		/* Protect trap id */
		return (0);
	if (a == UPASIZE+ORA*2)
		return (0);		/* Protect trap return link */
	*((int *)((int)&u+a)) = v;
	return (1);
}

/*
 * Cause a signal routine to be executed.
 */
msigint(n, f)
{
	register int *usp;

	usp = regl[OSP];
	putuwd(--usp, regl[OFW]);
	putuwd(--usp, regl[OIP]);
	putuwd(--usp, n);
	regl[OFW] &= ~MFTTB;
	regl[OIP] = f;
	regl[OSP] = usp;
	if (n != SIGTRAP)
		u.u_sfunc[n-1] = SIG_DFL;
}

/*
 * Cause the next instruction to single step.
 */
msigsin()
{
	regl[OFW] |= MFTTB;
}

/*
 * Fix up context.
 */
mfixcon(pp)
PROC *pp;
{
}

/*
 * Idle kernel process.
 */
idle()
{
	for (;;) {
		disflag = 1;
		_idle();
	}
}
0707070064030147611006440000030000030000011777770507310721500005100000007165/newbits/kernel/USRSRC/i8086/src/mmain.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * 8086/8088 Coherent.
 * All machines.
 * Machine dependent stuff.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	88/08/05  15:43:42	src
 * Bug:	Spawning large number of processes would cause system to crash.
 * Fix:	Kernel alloc space no longer overlaps loadable driver data.
 * 
 * Revision 1.1	88/03/24  17:39:46	src
 * Initial revision
 * 
 * 88/02/24	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * corebot is now aligned on a 512 byte boundary.
 *
 * 87/11/30	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Check for kernel data space > 64 Kbytes now done AFTER rounding up.
 *
 * 87/11/21	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Use of bruc/ctob macros eliminated since no longer valid in protected mode.
 *
 * 87/11/14	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Init code+data now split into icodep/icodes and idatap/idatas.
 *
 * 87/11/12	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Corebot/coretop now paddr_t rather than saddr_t to support protected mode.
 *
 * 87/10/05	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Loadable driver data slot allocation added.
 *
 * 87/05/08	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Ctob(sds) is now cast as ctob((paddr_t)sds) to avoid address truncation.
 *
 * 86/07/23	Allan Cornish
 * Added check for kernel data space exceeding 64 Kbytes.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/clist.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>
#include <sys/buf.h>

saddr_t uasa;	/* Currently active uarea */

/*
 * General initialisation.
 */
i8086()
{
	register unsigned allocp;
	extern vaddr_t	aicodep;
	extern vaddr_t	aicodes;
	extern vaddr_t	aidatap;
	extern vaddr_t	aidatas;
	extern vaddr_t	etext;
	extern vaddr_t	end;
	auto faddr_t	fp;
	long datsize;
	unsigned bsize, csize, isize, ssize;

	/*
	 * Set up memory bases.
	 * Align the buffers modulo BSIZE (512) in the physical space,
	 * so that any machines that have only 16 bit DMA counters will
	 * work out.
	 */
	datsize = (long)&end;
	datsize += ALLSIZE;
	datsize += NBUF * sizeof(BUF);
	datsize += ssize = NSLOT*(sizeof(int) + slotsz);
	datsize += isize = NINODE*sizeof(INODE);
	datsize += csize = NCLIST*sizeof(CLIST);
	datsize += bsize = NBUF*BSIZE;
	datsize = (datsize + 511) & ~511;
	if ( datsize >= 0x10000L )
		panic("Kernel data exceeds 64 Kbytes");

	blockp  = datsize - bsize - ((sds&0x1F)<<4);
	clistp  = (unsigned)blockp - csize;
	inodep  = (unsigned)clistp - isize;
	slotp   = (unsigned)inodep - ssize;
	allocp = &end;
	blockp += (sds << 4L);
	if ((unsigned)allocp > (unsigned)slotp)
		panic("No alloc space");
	corebot = ((sds << 4L) + datsize + 511) & ~511;
	asize = (unsigned)slotp - allocp;
	msize = (coretop-holetop+holebot-corebot) / 1024;
	allkp = setarena(allocp, asize);
	icodep = (char *)&aicodep;
	icodes = (int)&aicodes;
	idatap = (char *)&aidatap;
	idatas = (int)&aidatas;
	fp = ptov( corebot, (fsize_t) UPASIZE );
	uasa   = FP_SEL(fp);
}

0707070064030147571004440000030000030000011777770507310721500005300000000547/newbits/kernel/USRSRC/i8086/src/support.c#include <sys/al.h>
/*
 * the following kernel resident parts are shared by loadable serial drivers
 *   (see al.h and poll_clk.h)
 */
int	com_usage[NUM_AL_PORTS];	/* COM_UNUSED/COM_IRQ/COM_POLLED */
TTY	*(tp_table[NUM_AL_PORTS]);	/* table of pointers for polling */
int	poll_rate;			/* poll_* variables are explained */
int	poll_owner;			/* in poll_clk.h */
0707070064030147601006440000030000030000011777770507310721500004700000012002/newbits/kernel/USRSRC/i8086/src/tab.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Tables for the Intel 8086.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:50	src
 * Initial revision
 * 
 * 87/08/14	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added tick() as system call 73.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added alarm2() as system call 72.
 *
 * 86/11/21	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added msgctl(), msgget(), msgrcv(), msgsnd() as system calls 68 to 71.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added fcntl() and poll() as system calls 66 and 67.
 *
 * 85/07/09	Allan Cornish
 * Added getpgrp() as system call 63.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/systab.h>

/*
 * System call functions.
 */
int	unone();
int	unull();
int	uexit();
int	ufork();
int	uread();
int	uwrite();
int	uopen();
int	uclose();
int	uwait();
int	ucreat();
int	ulink();
int	uunlink();
int	uexece();
int	uchdir();
int	umknod();
int	uchmod();
int	uchown();
char	*ubrk();
int	ustat();
long	ulseek();
int	ugetpid();
int	umount();
int	uumount();
int	usetuid();
int	ugetuid();
int	ustime();
int	uptrace();
int	ualarm();
int	ufstat();
int	upause();
int	uutime();
int	ustty();
int	ugtty();
int	uaccess();
int	unice();
int	uftime();
int	uftime();
int	usync();
int	ukill();
int	udup();
int	upipe();
int	utimes();
int	uprofil();
long	uunique();
int	usetgid();
int	ugetgid();
int	(*usignal())();
int	usload();
int	usuload();
int	uacct();
int	ulock();
int	uioctl();
int	ugetegid();
int	uumask();
int	uchroot();
int	usetpgrp();
int	ugetpgrp();
int	ugeteuid();
int	ufcntl();
int	upoll();
long	ualarm2();
long	utick();

/*
 * System call table.
 */
struct systab sysitab[NMICALL] ={
	0,  INT,	unone,			/*  0 = ??? */
	2,  INT,	uexit,			/*  1 = exit */
	0,  INT,	ufork,			/*  2 = fork */
	6,  INT,	uread,			/*  3 = read */
	6,  INT,	uwrite,			/*  4 = write */
	4,  INT,	uopen,			/*  5 = open */
	2,  INT,	uclose,			/*  6 = close */
	2,  INT,	uwait,			/*  7 = wait */
	4,  INT,	ucreat,			/*  8 = creat */
	4,  INT,	ulink,			/*  9 = link */
	2,  INT,	uunlink,		/* 10 = unlink */
	6,  INT,	uexece,			/* 11 = exec */
	2,  INT,	uchdir,			/* 12 = chdir */
	0,  INT,	unone,			/* 13 = ??? */
	6,  INT,	umknod,			/* 14 = mknod */
	4,  INT,	uchmod,			/* 15 = chmod */
	6,  INT,	uchown,			/* 16 = chown */
	2,  INT,	ubrk,			/* 17 = break */
	4,  INT,	ustat,			/* 18 = stat */
	8,  LONG,	ulseek,			/* 19 = lseek */
	0,  INT,	ugetpid,		/* 20 = getpid */
	6,  INT,	umount,			/* 21 = mount */
	2,  INT,	uumount,		/* 22 = umount */
	2,  INT,	usetuid,		/* 23 = setuid */
	0,  INT,	ugetuid,		/* 24 = getuid */
	2,  INT,	ustime,			/* 25 = stime */
	8,  INT,	uptrace,		/* 26 = ptrace */
	2,  INT,	ualarm,			/* 27 = alarm */
	4,  INT,	ufstat,			/* 28 = fstat */
	0,  INT,	upause,			/* 29 = pause */
	4,  INT,	uutime,			/* 30 = utime */
	0,  INT,	unone,			/* 31 = ??? */
	0,  INT,	unone,			/* 32 = ??? */
	4,  INT,	uaccess,		/* 33 = access */
	2,  INT,	unice,			/* 34 = nice */
	2,  INT,	uftime,			/* 35 = ftime */
	0,  INT,	usync,			/* 36 = sync */
	4,  INT,	ukill,			/* 37 = kill */
	0,  INT,	unone,			/* 38 = ??? */
	0,  INT,	unone,			/* 39 = ??? */
	0,  INT,	unone,			/* 40 = ??? */
	4,  INT,	udup,			/* 41 = dup */
	2,  INT,	upipe,			/* 42 = pipe */
	2,  INT,	utimes,			/* 43 = times */
	8,  INT,	uprofil,		/* 44 = profil */
	0,  LONG,	uunique,		/* 45 = unique */
	2,  INT,	usetgid,		/* 46 = setgid */
	0,  INT,	ugetgid,		/* 47 = getgid */
	4,  INT,	usignal,		/* 48 = signal */
	0,  INT,	unone,			/* 49 = ??? */
	0,  INT,	unone,			/* 50 = ??? */
	2,  INT,	uacct,			/* 51 = acct */
	0,  INT,	unull,			/* 52 = ??? (phys) */
	0,  INT,	ulock,			/* 53 = lock */
	6,  INT,	uioctl,			/* 54 = ioctl */
	0,  INT,	unone,			/* 55 = ??? (mpx) */
	0,  INT,	ugetegid,		/* 56 = getegid */
	0,  INT,	ugeteuid,		/* 57 = geteuid */
	0,  INT,	unone,			/* 58 = ??? */
	0,  INT,	unone,			/* 59 = ??? */
	2,  INT,	uumask,			/* 60 = umask */
	2,  INT,	uchroot,		/* 61 = chroot */
	0,  INT,	usetpgrp,		/* 62 = setpgrp */
	0,  INT,	ugetpgrp,		/* 63 = getpgrp */
	2,  INT,	usload,			/* 64 = sload */
	2,  INT,	usuload,		/* 65 = suload */
	6,  INT,	ufcntl,			/* 66 = fcntl */
	8,  INT,        upoll,			/* 67 = poll */
	0,  INT,	unone,			/* 68 (was 6, msgctl) */
	0,  INT,	unone,			/* 69 (was 6, msgget) */
	0,  INT,	unone,			/* 70 (was 12, msgrcv) */
	0,  INT,	unone,			/* 71 (was 8, msgsnd) */
	4,  LONG,	ualarm2,		/* 72 = alarm2 */
	0,  LONG,	utick			/* 73 = tick  */
};
0707070064030147561006440000030000030000011777770507310721700005000000012415/newbits/kernel/USRSRC/i8086/src/trap.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Trap handler.
 * 8086/8088 Coherent, IBM PC.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:53	src
 * Initial revision
 * 
 * 88/03/06	Allan Cornish		/usr/src/sys/i8086/src/trap.c
 * Exception diagnostistics extended.
 *
 * 87/11/02	Allan Cornish		/usr/src/sys/i8086/src/trap.c
 * iAPX 286 exception traps added.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/systab.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

#ifndef	EBUG
#define	EBUG 1
#endif

/*
 * Trap handler.
 * The arguments are the registers,
 * saved on the stack by machine code. This call
 * is different from most C calls in that the registers
 * get copied back; if you change a "trap" parameter then
 * the machine register will be altered when the trap is
 * dismissed.
 */
trap(es, cx, dx, ax, bx, ds, usp, uss, id, ip, cs, fw)
unsigned es, cx, dx, ax, bx, ds, usp, uss, id, ip, cs, fw;
{
	register struct	systab	*stp;
	register int	syscall;
	register int	callnum;
	register int	sigcode;
	long		l;

	if ( (id >> 8) == SINMI )
		panic( "Parity error: cs=%x ip=%x\n", cs, ip );

	if (depth != 0) {
#if EBUG > 0
		faddr_t fp;
		FP_SEL(fp) = ax;  printf("ax "); vprint(fp);
		FP_SEL(fp) = cs;  printf("cs "); vprint(fp);
		FP_SEL(fp) = ds;  printf("ds "); vprint(fp);
		FP_SEL(fp) = es;  printf("es "); vprint(fp);
		FP_SEL(fp) = uss; printf("ss "); vprint(fp);
#endif
		panic("system trap: id=%x ip=%x ax=%x", id, ip, ax);
	}

	if ((SELF->p_flags&PFKERN) != 0) {
#if EBUG > 0
		faddr_t fp;
		FP_SEL(fp) = ax;  printf("ax "); vprint(fp);
		FP_SEL(fp) = cs;  printf("cs "); vprint(fp);
		FP_SEL(fp) = ds;  printf("ds "); vprint(fp);
		FP_SEL(fp) = es;  printf("es "); vprint(fp);
		FP_SEL(fp) = uss; printf("ss "); vprint(fp);
#endif
		panic("pid%d: kernel process trap: id=%x, ip=%x ax=%d",
			SELF->p_pid, id, ip, ax);
	}

	/*
	 * System call.
	 */
	if ( (id >> 8) == SISYS ) {
		u.u_error = 0;
		sigcode = 0;
		syscall = getuwi(ip-2);
		if (u.u_error != 0 || (syscall&0xFF) != 0xCD) {
			sigcode = SIGSYS;
			goto trapend;
		}
		callnum = (syscall>>8) & 0x7F;
		if (callnum >= NMICALL) {
			sigcode = SIGSYS;
			goto trapend;
		}
		stp = &sysitab[callnum];
		ukcopy(usp+2, u.u_args, stp->s_alen);
		if (u.u_error != 0) {
			sigcode = SIGSYS;
			goto trapend;
		}
		u.u_io.io_seg = IOUSR;
		if (envsave(&u.u_sigenv) != 0)
			u.u_error = EINTR;
		else if ( stp->s_alen <= (3 * sizeof(int)) ) {
			l = (*(long(*)())stp->s_func)(u.u_args[0],
						      u.u_args[1],
						      u.u_args[2] );
			ax = ((struct l *) &l)->l_lo;
			dx = ((struct l *) &l)->l_hi;
		}
		else {
			l = (*(long(*)())stp->s_func)(u.u_args[0],
						      u.u_args[1],
						      u.u_args[2],
						      u.u_args[3],
						      u.u_args[4],
						      u.u_args[5]);
			ax = ((struct l *) &l)->l_lo;
			dx = ((struct l *) &l)->l_hi;
		}
		if (u.u_error != 0) {
			ax = -1;
			dx = -1;
			putuwd(MUERR, u.u_error);
			if (u.u_error == EFAULT)
				sigcode = SIGSYS;
		}
	}

	/*
	 * Trap.
	 */
	else switch (id>>8) {

	case SIDIV:
		sigcode = SIGDIVE;
		break;

	case SISST:
		sigcode = SIGTRAP;
		break;

	case SIBPT:
		sigcode = SIGTRAP;
		break;

	case SIOVF:
		sigcode = SIGOVFL;
		break;

	case SIBND:
		/*
		 * Bound
		 */
		sigcode = SIGOVFL;
		break;

	case SIOP:
		/*
		 * Invalid opcode
		 */
		sigcode = SIGSEGV;
		break;

	case SIXNP:
		/*
		 * Processor extension not available
		 */
		sigcode = SIGSEGV;
		break;

	case SIDBL:
		/*
		 * Double exception
		 */
		panic("double exception: cs=%x ip=%x", cs, ip);
		sigcode = SIGSEGV;
		break;

	case SIXS:
		/*
		 * Processor extension segment overrun
		 */
		sigcode = SIGSEGV;
		break;

	case SITS:
		/*
		 * Invalid task state segment
		 */
		panic("invalid tss: cs=%x ip=%x", cs, ip);
		sigcode = SIGSEGV;
		break;

	case SINP:
		/*
		 * Segment not present
		 */
		sigcode = SIGSEGV;
		break;

	case SISS:
		/*
		 * Stack segment overrun/not present
		 */
		sigcode = SIGKILL;
		break;

	case SIGP:
		/*
		 * General protection.
		 */
		sigcode = SIGSEGV;
		break;

	default:
		panic("user trap: id=%x ip=%x\n", id, ip );
	}

trapend:
	if ( sigcode != 0 ) {
		if ( sigcode == SIGSEGV ) {
#if EBUG > 0
			faddr_t fp;
			FP_SEL(fp) = ax;  printf("\tax "); vprint(fp);
			FP_SEL(fp) = cs;  printf("\tcs "); vprint(fp);
			FP_SEL(fp) = ds;  printf("\tds "); vprint(fp);
			FP_SEL(fp) = es;  printf("\tes "); vprint(fp);
			FP_SEL(fp) = uss; printf("\tss "); vprint(fp);
			printf("user trap: SEGV id=%x ax=%x pid=%d\n",
				id, ax, SELF->p_pid );
			printf("\tip=%x sp=%x\n", ip, usp );

			/*
			 * Force core dump.
			 */
			u.u_sfunc[SIGSEGV] = SIG_DFL;
#endif
		}
		sendsig(sigcode, SELF);
	}
}
0707070064030104720407550000030000030000011777770507310722000004500000000000/newbits/kernel/USRSRC/i8086/src/RCS0707070064030057031004440000030000030000011777770507310722000005600000035446/newbits/kernel/USRSRC/i8086/src/RCS/ldas.s,vhead     1.2;
access   ;
symbols  ;
locks    ;
comment  @/ @;


1.2
date     91.03.01.09.23.04;  author root;  state Exp;
branches 1.2.1.1;
next	1.1;

1.1
date     91.03.01.09.21.44;  author root;  state Exp;
branches ;
next	;

1.2.1.1
date     91.03.14.13.32.09;  author root;  state Exp;
branches ;
next	;


desc
@Hooks linked to kernel code segment for linkage to loaded drivers
@


1.2
log
@Part of COHERENT 3.1.0 kernel
@
text
@/ /usr/src/sys/i8086/src/ldas.s
/ 
////////
/
/	Loadable Driver Interface Routines.
/
/	Loadable drivers execute in separate code segments, and are unable
/	to directly call kernel service routines.
/	Loadable drivers call a kernel service stub within their code segment,
/	which has has the same name as the desired service routine.
/	The driver service stub performs a far call to one of these routines.
/	These routines perform a near call to the desired kernel routine,
/	and then perform a far return to the driver service stub routine.
/	The driver service stub routine then does a near return to the driver.
/
/ 90/09/11  Hal Snyder
/ Add ld_call()
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  17:39:39	src
/ Initial revision
/ 
/ 87/12/08	Allan Cornish	/usr/src/sys/i8086/src/ldas.s
/ Block device interface added to loadable drivers.
/ ldtimcall() function added to support timed functions in loadable drivers.
/
/ 87/10/25	Allan Cornish	/usr/src/sys/i8086/src/ldas.s
/ Initial version - interface to/from loadable driver processes.
/
////////

	.globl	ld_xcall_
	.globl	ld_call_
	.globl	xcalled
	.globl	ldtimcall_
	.globl	ld_open_
	.globl	ld_close_
	.globl	ld_read_
	.globl	ld_write_
	.globl	ld_block_
	.globl	ld_ioctl_
	.globl	ld_power_
	.globl	ld_time_
	.globl	ld_poll_
	.globl	ldrvint_		/ void  (*ldrvint[16])();

////////
/
/ Constants
/
////////

	T_LDRV	= 12			/ Offset(tim,t_ldrv).
	B_FLAG	= 6			/ Offset(buf,b_flag).
	B_DEV	= 8			/ Offset(buf,b_dev ).
	BFERR	= 4			/ buf.b_flag bit set on I/O error.
	DRV_J	= 4			/ offset in driver of dispatcher

////////
/
/ External References
/
////////

	.globl	nonedev_		/ extern void	 nonedev();
	.globl	ldrvcon_		/ extern CON *	 ldrvcon[NDRV];
	.globl	ldrvsel_		/ extern saddr_t ldrvsel[NDRV];
	.globl	ldrvics_		/ extern saddr_t ldrvics[16];
	.globl	ldrvipc_		/ extern void  (*ldrvipc[16])();

////////
/
/ Shared Data
/
////////
	.shrd
ldrvint_:			/ Loadable Driver Interrupt Entry Points.
	.word	ld_intr0
	.word	ld_intr1
	.word	ld_intr2
	.word	ld_intr3
	.word	ld_intr4
	.word	ld_intr5
	.word	ld_intr6
	.word	ld_intr7
	.word	ld_intr8
	.word	ld_intr9
	.word	ld_intr10
	.word	ld_intr11
	.word	ld_intr12
	.word	ld_intr13
	.word	ld_intr14
	.word	ld_intr15

////////
/
/ Private Data
/
////////

	.prvd
	.shri

////////
/
/ Driver Configuration: Offsets to Function Pointers
/
////////

	C_OPEN=4
	C_CLOSE=6
	C_BLOCK=8
	C_READ=10
	C_WRITE=12
	C_IOCTL=14
	C_POWER=16
	C_TIMER=18
	C_LOAD=20
	C_ULOAD=22
	C_POLL=24

////////
/
/ ld_xcall( fp )	- invoke far function.
/ int (far *fp)();
/
////////

ld_xcall_:
	cli
	push	bp
	mov	bp, sp
	xcall	4(bp)
	pop	bp
	ret

////////
/
/ call a driver function from the kernel
/   sel		- CS selector for the driver
/   fn		- offset in the driver of the function we want
/   arg[1-3]    - optional arguments
/
/ ld_call(sel, fn, arg1, arg2, arg3)
/ int sel;
/ int (*fn)(void);
/ int arg1, arg2, arg3;
/
////////

/ stack when ld_call() is called:
/	arg3
/	arg2
/	arg1
/	fn
/	sel
/	return IP

ld_call_:			/ PARAMETERS (arg[1-3]) MUST BE FOUND AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
/	lea	bp, 4(sp)	/ this is what the next 2 instructions do
	mov	bp, sp
	add	bp, $4
				/
	push	0(bp)		/ Push sel to allow far call
	push	$DRV_J		/
				/
	mov	ax, 2(bp)	/ Push fn
				/
	xcall	-8(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	lea	sp, -4(bp)	/
	pop	bp		/
	ret			/

////////
/
/
/ ldtimcall( arg, tp )  - service timed far function.
/
////////

ldtimcall_:				/
	push	bp			/
	mov	bp, sp			/
					/
	mov	bx, 6(bp)		/
	mov	ax, T_LDRV+2(bx)	/
	push	ax			/ Loadable driver code selector.
	push	$DRV_J			/ Loadable driver invocation offset.
	mov	ax, T_LDRV(bx)		/ Desired far function.
					/
	xcall	-4(bp)			/
					/
	mov	sp, bp			/
	pop	bp			/
	ret

////////
/
/ xcalled( f, args )
/ int (*f)();
/
/	Input:	AX is pointer to kernel function to be invoked.
/
/	Action:	Perform a near call to the specified kernel function,
/		passing 6 words as optional arguments.
/		Perform a far return.
/
/	Notes:	Invoked by far call from loadable device driver.
/
////////

xcalled:			/ 6(bp) = grand-parent IP.
	push	bp		/ 4(bp) = parent CS
	mov	bp, sp		/ 2(bp) = parent IP
				/ AX    = destination function.
	push	20(bp)	/ Arg 7 /
	push	18(bp)	/ Arg 6	/
	push	16(bp)	/ Arg 5	/
	push	14(bp)	/ Arg 4	/
	push	12(bp)	/ Arg 3	/
	push	10(bp)	/ Arg 2	/
	push	 8(bp)	/ Arg 1	/
	icall	ax		/
				/
	mov	sp, bp		/ Return to loadable driver.
	pop	bp		/
	xret			/

////////
/
/ ld_open( dev, mode )		- Open Routine.
/ dev_t dev;
/ int mode;
/
////////

ld_open_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_OPEN(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_close( dev )		- Close Routine.
/ dev_t dev;
/
////////

ld_close_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_CLOSE(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_read( dev, iop )		- Read Routine.
/ dev_t dev;
/ IO * iop;
/
////////

ld_read_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_READ(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

///////
/
/ ld_write( dev, iop )		- Write Routine.
/ dev_t dev;
/ IO * iop;
/
////////

ld_write_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_WRITE(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

///////
/
/ ld_block( bp )		- Block Routine.
/ BUF * bp;
/
////////

ld_block_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	mov	bx, 4(bp)	/ Calculate major device number * 2.
	movb	bl, B_DEV+1(bx)	/
	subb	bh, bh		/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_BLOCK(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	bx, 4(bp)	/ bp->b_flag |= BFERR.
	or    B_FLAG(bx),$BFERR	/
	mov	sp, bp		/
	pop	bp		/
	jmp	bdone_		/ bdone(bp);

////////
/
/ ld_ioctl( dev, iop )		- Ioctl Routine.
/ dev_t dev;
/ IO * iop;
/
////////

ld_ioctl_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_IOCTL(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_power( dev )		- Powerfail Routine.
/ dev_t dev;
/
////////

ld_power_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_POWER(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_time( dev )		- Timer Routine.
/ dev_t dev;
/
////////

ld_time_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_TIMER(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ ld_poll( dev, ev, msec )	- Poll Routine.
/ dev_t dev;
/ int ev;
/ int msec;
/
////////

ld_poll_:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	sub	bx, bx		/ Calculate major device number * 2.
	movb	bl, 5(bp)	/
	shl	bx, $1		/
				/
	mov	cx, ldrvsel_(bx)/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	bx, ldrvcon_(bx)/ Identify driver configuration.
	or	bx, bx		/
	je	0f		/
				/
	mov	ax, C_POLL(bx)	/ Identify driver function to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

0:	mov	sp, bp
	pop	bp
	jmp	nonedev_

////////
/
/ Loadable Driver Interrupt Entry Points.
/
/	Invoked by Coherent to service specific interrupt.
/	Identifies which loadable driver interrupt vector to be used.
/	Invokes interrupt handler which will do far call to loadable driver.
/
////////

ld_intr0:
	mov	bx, $0		/
	jmp	ld_intr		/

ld_intr1:
	mov	bx, $2		/
	jmp	ld_intr		/

ld_intr2:
	mov	bx, $4		/
	jmp	ld_intr		/

ld_intr3:
	mov	bx, $6		/
	jmp	ld_intr		/

ld_intr4:
	mov	bx, $8		/
	jmp	ld_intr		/

ld_intr5:
	mov	bx, $10		/
	jmp	ld_intr		/

ld_intr6:
	mov	bx, $12		/
	jmp	ld_intr		/

ld_intr7:
	mov	bx, $14		/
	jmp	ld_intr		/

ld_intr8:
	mov	bx, $16		/
	jmp	ld_intr		/

ld_intr9:
	mov	bx, $18		/
	jmp	ld_intr		/

ld_intr10:
	mov	bx, $20		/
	jmp	ld_intr		/

ld_intr11:
	mov	bx, $22		/
	jmp	ld_intr		/

ld_intr12:
	mov	bx, $24		/
	jmp	ld_intr		/

ld_intr13:
	mov	bx, $26		/
	jmp	ld_intr		/

ld_intr14:
	mov	bx, $28		/
	jmp	ld_intr		/

ld_intr15:
	mov	bx, $30		/
	jmp	ld_intr		/

////////
/
/ Loadable driver interrupt handler.
/
/
/	Input:	bx = interrupt number * 2.
/
////////

ld_intr:
	push	bp		/
	mov	bp, sp		/
				/
	mov	cx,ldrvics_(bx)	/ Prepare driver interface CS:IP.
	jcxz	0f		/
	push	cx		/
	push	$DRV_J		/ Loadable driver invocation offset.
				/
	mov	ax,ldrvipc_(bx)	/ Identify interrupt handler to be invoked.
	or	ax, ax		/
	je	0f		/
				/
	xcall	-4(bp)		/ Invoke driver interface, which will
				/	in turn invoke driver function.
				/
0:	mov	sp, bp		/
	pop	bp		/
	ret			/
@


1.2.1.1
log
@has kernel printf's for interrupts called
@
text
@a19 3
/ Revision 1.2	91/03/01  09:23:04	root
/ Part of COHERENT 3.1.0 kernel
/ 
a94 2
foo:	.ascii	"I%d %x:%x\n\000"	

d674 1
a674 2
	.globl	printf_	/ for debugging
	.globl	ld_intr	/ for debugging
a677 13
	
/ Diagnostic call: printf(foo, bx/2, ldrvics[bx], ldrvipc[bx])
push	bx
push	ldrvipc_(bx)
push	ldrvics_(bx)
mov	ax,bx
shr	ax,$1
push	ax
push	$foo
call	printf_
add	sp,$8
pop	bx
/ End of diagnostic call	
@


1.1
log
@Part of COHERENT 3.0.0 kernel
@
text
@d1 1
a1 1
/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
d3 1
a3 10
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/ 
/	Copyright (c) 1987
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
a4 3

////////
/
d16 2
d33 1
d57 1
a101 1
four:	.word	4
d139 4
d144 36
d191 1
a191 1
	push	four			/ Loadable driver invocation offset.
d251 1
a251 1
	push	four		/
d290 1
a290 1
	push	four		/
d330 1
a330 1
	push	four		/
d370 1
a370 1
	push	four		/
d410 1
a410 1
	push	four		/
d452 1
a452 1
	push	four		/
d491 1
a491 1
	push	four		/
d530 1
a530 1
	push	four		/
d571 1
a571 1
	push	four		/
d682 1
a682 1
	push	four		/
@
0707070064030103041004440000030000030000011777770507310722400006100000001077/newbits/kernel/USRSRC/i8086/src/RCS/support.c,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    ; strict;
comment  @ * @;


1.1
date     91.06.04.14.37.52;  author hal;  state Exp;
branches ;
next     ;


desc
@Export variables needed for polling, e.g. by async drivers.
@



1.1
log
@Mystery version from dyna - lacks poll_rate & poll_owner
@
text
@#include <al.h>
/*
 * the following kernel resident parts are shared by loadable serial drivers
 *   (see al.h and poll_clk.h)
 */
int	com_usage[NUM_AL_PORTS];	/* COM_UNUSED/COM_IRQ/COM_POLLED */
TTY	*(tp_table[NUM_AL_PORTS]);	/* table of pointers for polling */
@
0707070064030104671004440000030000030000011777770507310722500005500000062130/newbits/kernel/USRSRC/i8086/src/RCS/as1.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.36.30;  author bin;  state Exp;
branches ;
next     ;


desc
@/dev/rfva0
@



1.1
log
@Initial revision
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $

/ (lgl-
/	The information contained herein is a trade secret of Mark Williams
/	Company, and  is confidential information.  It is provided  under a
/	license agreement,  and may be  copied or disclosed  only under the
/	terms of  that agreement.  Any  reproduction or disclosure  of this
/	material without the express written authorization of Mark Williams
/	Company or persuant to the license agreement is unlawful.
/
/	COHERENT Version 2.3.37
/	Copyright (c) 1982, 1983, 1984.
/	An unpublished work by Mark Williams Company, Chicago.
/	All rights reserved.
/ -lgl)
////////
/
/ Machine language assist for
/ 8086/8088 Coherent. This contains the parts
/ that are common to all machines.
/
/ Note that several of the following constants can be invalidated
/ by changing the contents of ../h/*proc.h among others,
/ or by changing the number of automatic variables in the functions
/ called on the paths leading to consave or conrest.  Tread with caution.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.3	88/08/05  08:32:09 	src
/ Kludges for AMD 286 bug have been removed.
/ 
/ Revision 1.2	88/06/24  16:02:08	src
/ Bug:	inb/outb did not work properly in split stack/data operation.
/ Fix:	inb/outb now explicitly reference the stack segment.
/ 
/ Revision 1.1	88/03/24  17:39:08	src
/ Initial revision
/ 
/ 88/03/10	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
/ These partial fixes will be removed once all CPU's are replaced.
/
/ 88/03/04	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ tmpcs*/tmpds* temporary variables renamed to sav_*.
/ usave/conrest/etc now handle odd byte alignment on stack.
/ envrest/conrest now do interrupt return as last instruction.
/
/ 87/12/21	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ fclear(f,n) function added.
/
/ 87/12/04	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ kfcopy(k,f,n) and fkcopy(f,k,n) routines added.
/
/ 87/12/03	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ popf replaced by 'push cs; mov ax,$0f; push ax; iret; 0:' due to popf int bug.
/
/ 87/11/05	Allan Cornish		/usr/src/sys/i8086/src/as1.s
/ slrcopy/srlcopy/sclear renamed plrcopy/prlcopy/pclear and moved to ibm*/as2.s
/
/ 87/10/27	Allan Cornish	/usr/src/sys/i8086/src/as1.s
/ System stack/data segments now setup in ibm/ibm_at as2.s
/
/ 87/02/06	Allan Cornish
/ Functions ffword and sfword added to fetch and set far memory.
/
////////

UPASIZE	=	1024			/ Size of uproc and stack
USIZE	=	0x114			/ sizeof(UPROC)
USZ1	=	140			/ Word count for usave, uproc size
UMCSP	=	0x06			/ offset of sp in u_syscon
EFAULT	=	14			/ Bad argument
PFLAGS	=	0x22			/ Offset into PROC.
PFKERN	=	0x80			/ Kernel process flag bit.
SIDEV	=	0x40			/ Device interrupt trap code.

////////
/
/ After performing machine specific
/ trap vector setup, the startup code jumps
/ here. The DS maps the vectors.
/
////////

	.globl	start

start:
/ Call the machine setup code.
/ Call Coherent main.
/ On return, send control off to the user
/ at its entry point.

	mov	sp, $u_+UPASIZE-32	/ Stack pointer for init
	call	i8086_			/ Do it.
	sti				/ Interrupts on, and
	call	main_			/ call Coherent mainline.
	cli				/ Interrupts off.
	incb	depth_			/ Set stack depth to user.
	sub	ax, ax			/ User mode IP.
	mov	bx, uds_		/ User mode DS, ES, SS
	mov	cx, ucs_		/ User mode CS.
	mov	dx, $0x0200		/ User mode FL.

	mov	ds, bx			/ Map data segment
	mov	es, bx			/ Map extra segment
	mov	ss, bx			/ Map stack segment

	mov	sp, $sb-aicodep_	/ User's stack
	push	dx			/ Flags
	push	cx			/ CS
	push	ax			/ IP
	iret				/ Go to user state.

////////
/
/ Trap and interrupt save.
/ These routines will be very familiar to any
/ RSX-11M hackers out there; it is just the ever
/ common co-routine call. The caller is called back,
/ with "bx" pointing to the saved "ax" on the stack,
/ with interrupts enabled. The called routine must
/ set 16(bx), which was initially the call back address,
/ to something non zero in the high byte if it does
/ not want an EOI sent to the 8259.
/
/ ttsave, tksave, tisave, and tusave could be folded into a single routine
/ with many tests and branches, but the frequency of passage through
/ this code warrants a minimally branched execution, and special casing
/ the interrupted context allows minimal memory references.
/
////////

	.globl	tsave

tsave:				/ What level of interrupt ?
	push	ds			/ Save current data base
	mov	ds, cs:cds		/ remap to system data space.
	pop	sav_ds			/
	decb	depth_			/ Adjust stack depth.
	je	tkusave			/ If e, stack switch may be needed.
ttsave:				/ Interrupted within interrupt
	cmp	sp,$u_+USIZE+50		/ Check for stack
	jbe	tabort			/ overflow
	push	ss			/ Fake save ss
	push	sp			/ Fake save sp
	push	sav_ds			/ Save ds
	push	bx			/ Save bx

	sti				/ More interrupts ok

	push	ax			/ Save ax
	push	dx			/ and remainder
	push	cx			/ of machine
	push	es			/ state
	mov	ax,ds			/ Map es
	mov	es,ax			/ to system ds
	mov	bx,sp			/ Load index
	icall	16(bx)			/ and call the caller
	mov	bx,sp			/ Load index
	mov	ax,16(bx)		/ fetch trap type
	cmpb	ah, $SIDEV		/ see if eoi
	jne	ttkdone			/ can be skipped

	cli				/ don't let eoi swamp us
	call	eoi			/ Dismiss interrupt
ttkdone:			/ Common ttsave/tksave finish
	pop	es			/ Restore
	pop	cx			/ the
	pop	dx			/ machine state
	pop	ax			/ state

	cli				/ No more interrupts

	incb	depth_			/ Reset stack level
	pop	bx			/ Restore the
	pop	ds			/ last parts
	add	sp,$6			/ forget ss, sp, and ra.
	iret				/ Done.

tabort:				/ Uarea stack overflowed
	add	sp,$300			/ Make room for death.
	mov	ax,$oops		/ Load
	push	ax			/ message
	call	panic_			/ and die.

tkusave:			/ Kernel or user process interrupted
	mov	sav_bx,bx		/ Save bx in temp
	mov	bx,cprocp_		/ Load proc pointer
	test	PFLAGS(bx),$PFKERN	/ Kernel process ?
	je	tusave			/ Sorry, go do it all.
tksave:				/ Kernel process interrupted
	push	ss			/ Fake save ss
	push	sp			/ Fake save sp
	push	sav_ds			/ Save ds
	push	sav_bx			/ Save bx

	sti				/ More interrupts ok.

	cmp	bx,iprocp_		/ Is this the idle process ?
	je	tisave			/ Yes, very easy
	push	ax			/ Save the
	push	dx			/ rest of
	push	cx			/ the machine
	push	es			/ state
	mov	ax,ds			/ And map
	mov	es,ax			/ extra to system data
	mov	bx,sp			/ Load index
	icall	16(bx)			/ and call the caller back.
	mov	bx,sp			/ Load index
	mov	ax,16(bx)		/ and pull trap type.
	cmpb	ah, $SIDEV		/ Machine trap?
	jne	ttkdone			/ Yes, skip dismiss
	call	eoi			/ Dismiss interrupt
	jmp	ttkdone			/ Finish above

tisave:				/ Idle process interrupted, nothing to save
	sub	sp,$8			/ Push junk
	mov	bx,sp			/ Load index
	icall	16(bx)			/ and call the caller back.
	mov	bx,sp			/ Load index
	mov	ax,16(bx)		/ and pull trap type.
	cmpb	ah, $SIDEV		/ Machine trap ?
	jne	0f			/ Yes, skip dismiss.
	call	eoi			/ Dismiss interrupt
0:
	call	stand_			/ Clock, part 2
	cli				/ No more interrupts

	add	sp,$18			/ Pop everything
	incb	depth_			/ Reset level
	iret				/ Done

tusave:				/ User process interrupted
	mov	bx, $u_+UPASIZE		/ Get base of user area and
	pop	-8(bx)			/ pop the data that
	pop	-6(bx)			/ was pushed onto the user
	pop	-4(bx)			/ stack onto the new
	pop	-2(bx)			/ system stack.
	mov	sav_ss, ss		/ Save the old stack segment
	mov	sav_sp, sp		/ and stack pointer, then
	mov	ss, sds_		/ switch onto the
	lea	sp, -8(bx)		/ new stack in the user area.
	push	sav_ss			/ Push old ss
	push	sav_sp			/ Push old sp
	push	sav_ds			/ Push old ds and
	push	sav_bx			/ push old bx.

	sti				/ Allow more interrupts.

	push	ax			/ Save the
	push	dx			/ remainder of
	push	cx			/ the machine
	push	es			/ state.
	mov	ax, ds			/ Map extra
	mov	es, ax			/ segment to system data.
	mov	bx, sp			/ Load up an index into the stack
	icall	16(bx)			/ and call the caller back.
	mov	bx, sp			/ Load up stack index.
	mov	ax, 16(bx)		/ Pull trap type.
	cmpb	ah, $SIDEV		/ Is this a machine trap ?
	jne	0f			/ Yes, skip dismiss.
	call	eoi			/ Do the dismiss.
0:	mov	bx, cprocp_		/ Have we become kernel?
	test	PFLAGS(bx), $PFKERN	/ If so, do kernel return.
	jne	ttkdone			/

	call	stand_			/ Clock, part 2
	pop	es			/ Restore the
	pop	cx			/ easy part of the
	pop	dx			/ machine
	pop	ax			/ state.

	cli				/ Interrupts off.

	incb	depth_			/ Adjust stack depth and
	pop	sav_bx			/ Pop off the old bx and
	pop	sav_ds			/ ds into statics, then
	pop	bx			/ map DS:BX over top of what
	pop	ds			/ was the previous stack.
	add	sp, $2			/ Pop ra.
	pop	-6(bx)			/ Copy the IP,
	pop	-4(bx)			/ the CS and the old
	pop	-2(bx)			/ FW onto the user's stack, then
	lea	sp, -6(bx)		/ switch back
	mov	bx, ds			/ to the
	mov	ss, bx			/ user's stack.
	mov	ds, cs:cds		/
	mov	bx, sav_bx		/ Reload the bx and the
	mov	ds, sav_ds		/ ds, then
	iret				/ exit interrupt.

////////
/
/ This dummy routine is put in vector
/ table slots that are unused. All it does is
/ return to the caller.
/
////////

	.globl	vret_

vret_:	ret

////////
/
/ Fetch a word from the user's data space.
/
/ getuwd(u)
/ char *u;
/
////////

	.globl	getuwd_
	.globl	getupd_

getuwd_:
getupd_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save extra map and
	mov	es, uds_		/ remap over the user's data.
	mov	ax,es:(bx)		/ Get word
	pop	es			/ Restore es.
	ret				/ Return

////////
/
/ Fetch a word from the user's code space.
/
/ getuwi(u)
/ char *u;
/
////////

	.globl	getuwi_

getuwi_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Argument
	cmp	bx,ucl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save extra.
	mov	es,ucs_			/ Users data segment
	mov	ax,es:(bx)		/ Get word
	pop	es			/ Restore extra.
	ret				/ Return

////////
/
/ Fetch a byte from the user's data space.
/
/ getubd(u)
/ char *u;
/
////////

	.globl	getubd_

getubd_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save es.
	mov	es,uds_			/ Users data segment
	movb	al,es:(bx)		/ Get word
	pop	es			/ Restore es.
	subb	ah,ah			/ Clear upper half
	ret				/ Return

////////
/
/ Store a word into the user's data space.
/
/ putuwd(u, w)
/ char *u;
/ int w;
/
////////

	.globl	putuwd_

putuwd_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ New value
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save es.
	mov	es,uds_			/ Users data segment
	mov	es:(bx),ax		/ Set value
	pop	es			/ Restore es.
	sub	ax,ax			/ Succesful
	ret				/ Return

////////
/
/ Store a word into the user's code space.
/
/ putuwi(u, w)
/ char *u;
/ int w;
/
////////

	.globl	putuwi_

putuwi_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ New value
	mov	bx,2(bx)		/ Argument
	cmp	bx,ucl_			/ In range?
	ja	kuerr			/ No

	push	ucs_			/ Get physical address.
	sub	ax, ax			/ DX:AX = phy = vtop( ucs:0 );
	push	ax			/
	call	vtop_			/
	add	sp, $4			/
					/
	sub	bx, bx			/ Get writable virtual address.
	push	bx			/ DX:AX = fp = ptov( phy, ucl );
	push	ucl_			/
	push	dx			/
	push	ax			/
	call	ptov_			/
	add	sp, $8			/
					/
	mov	bx, sp			/
	mov	ax, 4(bx)		/ New value
	mov	bx, 2(bx)		/ Argument
	push	es			/ Save ES
	mov	es, dx			/ Users (writable) code segment
	mov	es:(bx), ax		/ Set value
	pop	es			/ Restore es
					/
	push	dx			/ Release writable virtual address.
	sub	ax, ax			/ vrelse( fp );
	push	ax			/
	call	vrelse_			/
	add	sp, $4			/
					/
	sub	ax,ax			/ Succesful
	ret				/ Return

////////
/
/ Store a byte into the user's data space.
/
/ putubd(u, w)
/ char *u;
/ int w;
/
////////

	.globl	putubd_

putubd_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ New value
	mov	bx,2(bx)		/ Argument
	cmp	bx,udl_			/ In range?
	ja	kuerr			/ No

	push	es			/ Save es.
	mov	es,uds_			/ Users data segment
	movb	es:(bx),al		/ Set value
	pop	es			/ Restore es.
	sub	ax,ax			/ Succesful
	ret				/ Return

////////
/
/ Block transfer "n" bytes from location
/ "k" in the system map to location "u" in the
/ user's data space. Return the number of bytes
/ transferred.
/
/ kucopy(k, u, n)
/ char *k;
/ char *u;
/ int n;
/
////////

	.globl	kucopy_

kucopy_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax,6(bx)		/ Add count
	jc	kuerr			/ Out of bounds
	cmp	ax,udl_			/ In range?
	ja	kuerr			/ No

	push	si			/ Save si
	push	di			/ Save di
	push	es			/ Save es.

	mov	si,2(bx)		/ Kernel address
	mov	di,4(bx)		/ User address
	mov	cx,6(bx)		/ Count
	mov	ax,cx			/ Move here to return
	mov	es,uds_			/ Map extra segment to user

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count
	rep				/
	movsw				/ Move words.
	rcl	cx, $1
	rep
	movsb				/ Move odd byte.

	pop	es			/ Restore es.
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ Block copy "n" bytes from location "u" in
/ the user data space to location "k" in the system
/ data space. Return the actual number of bytes
/ moved.
/
/ ukcopy(u, k, n)
/ char *u;
/ char *k;
/ int n;
/
////////

	.globl	ukcopy_

ukcopy_:
	mov	bx,sp			/ Base pointer
	mov	ax,2(bx)		/ User address
	dec	ax			/ Don't wrap too soon
	add	ax,6(bx)		/ Count
	jc	kuerr			/ Out of bounds
	cmp	ax,udl_			/ In range?
	ja	kuerr			/ No

	push	si			/ Save si
	push	di			/ Save di
	push	ds			/ Save ds

	mov	si,2(bx)		/ User address
	mov	di,4(bx)		/ Kernel address
	mov	cx,6(bx)		/ Count
	mov	ax,cx			/ Move here to return
	mov	bx, uds_		/ Map data segment
	mov	ds, bx			/ avoiding bug in 8088.

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Word count, odd byte in carry.
	rep				/
	movsw				/ Move words.
	rcl	cx, $1
	rep				/ Move odd byte.
	movsb

	pop	ds			/ Restore ds
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ All of the above copy routines jump to
/ "kuerr", with the stack untouched, if they detect
/ a bounds error on a user address.
/
////////

kuerr:
	mov	bx,$u_			/ Pointer to user area
	movb	(bx),$EFAULT		/ Bad parameter error
	sub	ax,ax			/ Didn't copy anything
	ret				/ Return

////////
/
/ sfbyte( fp, b )	-- set far byte
/ int far * fp;
/ int b;
/
////////

	.globl	sfbyte_

sfbyte_:push	es		/ sfbyte( fp, b )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ register int b;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	movb	es:(di), al	/	*fp = b;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ sfword( fp, w )	-- set far word
/ int far * fp;
/ int w;
/
////////

	.globl	sfword_

sfword_:push	es		/ sfword( fp, w )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ register int w;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	mov	es:(di), ax	/	*fp = w;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ ffbyte( fp )		-- fetch far byte
/ int far * fp;
/
////////

	.globl	ffbyte_

ffbyte_:push	es		/ ffbyte( fp )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	sub	ax, ax		/
	movb	al, es:(di)	/	return *fp;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ ffword( fp )		-- fetch far word
/ int far * fp;
/
////////

	.globl	ffword_

ffword_:push	es		/ ffword( fp )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	mov	ax, es:(di)	/	return *fp;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret

////////
/
/ Block transfer "n" bytes from location
/ "k" in the system map to location "f"
/ in the virtual address space.
/ Return the number of bytes / transferred.
/
/ kfcopy(k, f, n)
/ char *k;
/ faddr_t f;
/ int n;
/
////////

	.globl	kfcopy_

kfcopy_:
	push	si			/ Save si
	push	di			/ Save di
	push	bp			/ Save bp
	mov	bp, sp			/ Base pointer
	push	es			/ Save es.

	mov	si, 8(bp)		/ Kernel address
	les	di, 10(bp)		/ Far address
	mov	cx, 14(bp)		/ Count
	mov	ax, cx			/ Move here to return

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count.
	rep				/
	movsw				/ Move words.
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte.
					/
	pop	es			/ Restore es.
	pop	bp			/ Restore bp.
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ Block transfer "n" bytes from location
/ "f" in the virtual addres sspace to
/ location "f" in the system map.
/ Return the number of bytes / transferred.
/
/ fkcopy(f, k, n)
/ faddr_t f;
/ char *k;
/ int n;
/
////////

	.globl	fkcopy_

fkcopy_:
	push	si			/ Save si
	push	di			/ Save di
	push	bp			/ Save bp
	mov	bp, sp			/ Base pointer
	push	ds			/ Save ds.

	lds	si, 8(bp)		/ Far address
	mov	di, 12(bp)		/ Kernel address
	mov	cx, 14(bp)		/ Count
	mov	ax, cx			/ Move here to return

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count.
	rep				/
	movsw				/ Move words.
	rcl	cx, $1			/
	rep				/
	movsb				/ Move odd byte.
					/
	pop	ds			/ Restore ds.
	pop	bp			/ Restore bp.
	pop	di			/ Restore di
	pop	si			/ Restore si
	ret				/ Return

////////
/
/ fclear( fp, n )	- Erase far memory.
/ faddr_t fp;
/ unsigned n;
/
////////

	.globl	fclear_

fclear_:
	push	es			/ Save es
	push	di			/ Save di
	push	bp			/ Save bp
	mov	bp, sp			/ Base pointer

	les	di, 8(bp)		/ Far address
	mov	cx, 12(bp)		/ Count
	sub	ax, ax			/

	cld				/ Auto increment
	clc				/
	rcr	cx, $1			/ Calculate Word count.
	rep				/
	stosw				/ Clear words.
	rcl	cx, $1			/
	rep				/
	stosb				/ Clear odd byte.
					/
	pop	bp			/ Restore bp.
	pop	di			/ Restore di.
	pop	es			/ Restore es.
	ret				/ Return

////////
/
/ Profile scaling.
/
////////

	.globl	pscale_

pscale_:
	mov	bx,sp			/ Base pointer
	mov	ax,2(bx)		/ Multiply
	mul	4(bx)			/
	mov	ax,dx			/ Get high half
	ret				/ And return

////////
/
/ Save the environment of a process
/ envsave(p)
/ MENV *p;
/
/ Save the context of a process
/ consave(p)
/ MCON *p;
/
////////

	.globl	consave_
	.globl	envsave_

envsave_:
consave_:
	mov	cx, di			/ Hide di.
	mov	bx, sp			/ Point bx at the stack and
	mov	di, 2(bx)		/ di at the MCON block.
	cld				/ Ensure increment.
	mov	ax, cx			/ Save di
	stosw
	mov	ax, si			/ Save si
	stosw
	mov	ax, bp			/ Save bp
	stosw
	mov	ax, sp			/ Save sp
	stosw
	mov	ax, (bx)		/ Save ra as pc
	stosw
	pushf				/ Save fw
	pop	ax
	stosw
	movb	al, depth_		/ Save stack depth
	cbw
	stosw
	mov	di, cx			/ Put di back,
	sub	ax, ax			/ indicate a state save and
	ret				/ return to caller.

////////
/
/ Restore the environment of a process.
/ envrest(p)
/ MENV *p;
/
////////

	.globl	envrest_

envrest_:
	cli
	cld
	mov	bx,sp			/ Base pointer
	mov	si,2(bx)		/ Pointer to context
	lodsw				/ Restore di
	mov	di,ax			/
	lodsw				/ Restore si
	mov	cx,ax			/ Save for later
	lodsw				/ Restore bp
	mov	bp,ax			/
	lodsw				/ Restore sp
	mov	sp,ax			/
	mov	bx,ax			/ Our frame
	push	cs			/ Push current CS
	lodsw				/ Restore pc
	push	ax			/
	lodsw				/ Restore flags
	mov	(bx),ax			/ Stack now in form PSW,CS,IP.
	lodsw				/ Restore stack depth
	cli				/ No more interrupts
	movb	depth_, al
	mov	si,cx			/ Restore si
	mov	ax,$1			/ We are restoring
	iret				/ Return through PSW,CS,IP.

////////
/
/ Restore the context of a process.
/ Called with interrupts disabled from dispatch.
/ conrest(u, o)
/ saddr_t u;
/
////////

	.globl	conrest_

conrest_:
	decb	depth_			/ Falsify user/system state
	sti				/ Interrupts ok here
			/ Save current uarea
	call	usave_			/ Save the uarea in its segment.
			/ Copy in new uarea
	mov	bx,sp			/ Base pointer
	mov	ax, 2(bx)		/ Fetch uarea saddr_t
	mov	bx, 4(bx)		/ Fetch syscon offset
	mov	uasa_, ax		/ Save uarea saddr_t
	mov	cx,$USZ1		/ uproc size
/	mov	es,sds_			/ system data segment
	mov	di,$u_			/ system data uarea offset
	mov	ds,ax			/ uarea segment
	sub	si,si			/ uarea offset
	mov	sp,UMCSP(bx)		/ new stack
	cld				/ increment
	rep				/ repeat
	movsw				/ copy uproc
	mov	di,sp			/ stack offset in system data
	and	di,$~1			/ ensure word alignment
	mov	cx,$u_+UPASIZE		/ compute byte
	sub	cx,di			/ count
	mov	si,$UPASIZE		/ compute offset
	sub	si,cx			/ in segment
	shr	cx,$1			/ make word count
	rep				/ repeat
	movsw				/ copy stack
			/ Clean up
	mov	ax, es			/ Restore data
	mov	ds, ax			/ segment
			/ Now restore context
	add	bx, $u_			/ convert to address
	mov	si, bx			/ Get source index for restore
	lodsw				/ Restore di
	mov	di,ax			/
	lodsw				/ Restore si
	mov	cx,ax			/ Save for later
	lodsw				/ Restore bp
	mov	bp,ax			/
	lodsw				/ Restore sp
	mov	sp,ax			/
	mov	bx,ax			/ Our frame
	push	cs			/ Push current CS
	lodsw				/ Restore pc
	push	ax			/
	lodsw				/ Restore flags
	mov	(bx),ax			/ Stack now in form PSW,CS,IP.
	lodsw				/ Restore stack depth
	cli				/ No more interrupts
	movb	depth_, al
	mov	si,cx			/ Restore si
	mov	ax,$1			/ We are restoring
	iret				/ Return through PSW,CS,IP.

////////
/ usave()
/ Save uarea in segment.
/ Knowing that ds points to the system data segment
/ and that es should map there also.
/ And guaranteed not to step on ax or bx for conrest
/
	.globl	usave_
0:	ret
usave_:
	cmp	uasa_, $0		/
	je	0b
	push	es			/ Save es
	push	si			/ Save si
	push	di			/ Save di
	mov	cx,$USZ1		/ count
	sub	di,di			/ uarea segment offset
	mov	es,uasa_		/ uarea segment
	mov	si,$u_			/ system data offset
/	mov	ds,sds_			/ system data segment
	cld				/ increment
	rep				/ repeat
	movsw				/ copy uproc
	mov	si,sp			/ stack offset in system data
	and	si,$~1			/ ensure word alignment
	mov	cx,$u_+UPASIZE		/ compute byte
	sub	cx,si			/ count
	mov	di,$UPASIZE		/ compute offset
	sub	di,cx			/ in segment
	shr	cx,$1			/ make word count
	rep				/ repeat
	movsw				/ copy stack
	pop	di			/ Restore di
	pop	si			/ Restore si
	pop	es			/ Restore extra
	ret

/ Save useful registers.
/
	.globl	msysgen_
/
/ msysgen(p)
/ MGEN *p;
/
msysgen_:
	ret				/ Nothing useful to save

/ Disable interrupts.  Previous value is returned.
/
	.globl	sphi_

sphi_:
	pushf				/ Save flags
	pop	ax			/ Return current value
	cli				/ Disable interrupts
	ret				/ And return

/ Enable interrupts.  Previous value is returned.
/
	.globl	splo_

splo_:
	pushf
	pop	ax
	sti
	ret

/ Change interrupt flag.  Previous value is returned.
/
	.globl	spl_

spl_:
	pop	ax			/ ip
	pop	bx			/ psw
	push	bx
	push	bx			/ push psw, cs, ip for iret
	push	cs
	push	ax
	pushf				/ old psw
	pop	ax
	iret

////////
/
/ Idle routine.
/ Enable interupts, and wait for something to
/ happen. Does not do anything to the 8259, bacause
/ this will be set up correctly.
/
////////

	.globl	_idle_

_idle_:	sti				/ Interupts on.
	hlt				/ Wait for an interrupt
	ret				/ and return.

////////
/
/ The world is indeed grim.
/ Halt. Keep the interrupts on so that the
/ keyboard can get int.
/
////////

	.globl	halt_

halt_:	sti				/ Be safe,
0:
	hlt				/ and halt.
	jmp	0b			/ Paranoid, yes sir.

////////
/
/ Basic port level I/O.
/
/ int	inb(port);
/ int	outb(port, data);
/
////////

	.globl	inb_
	.globl	outb_

inb_:	mov	bx, sp
	mov	dx, ss:2(bx)
	sub	ax, ax
	inb	al, dx
	ret

outb_:	mov	bx, sp
	mov	dx, ss:2(bx)
	mov	ax, ss:4(bx)
	outb	dx, al
	ret

////////
/
/ Routines to move data to and from
/ the system auxiliary segment.
/
////////

	.globl	ageti_

ageti_:
	mov	bx,sp			/ Base pointer
	mov	bx,2(bx)		/ Pointer
	push	es			/ Save extra mapping and
	mov	es, sas_		/ remap.
	mov	ax,es:(bx)		/ Get value
	pop	es			/ Restore es and
	ret				/ Return

	.globl	aputp_
	.globl	aputi_

aputp_:
aputi_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ Value
	mov	bx,2(bx)		/ Pointer
	push	es			/ Save extra base and
	mov	es, sas_		/ remap.
	mov	es:(bx),ax		/ Set value
	pop	es			/ Restore extra base
	ret				/ Return

	.globl	aputc_

aputc_:
	mov	bx,sp			/ Base pointer
	mov	ax,4(bx)		/ Value
	mov	bx,2(bx)		/ Pointer
	push	es			/ Save es and
	mov	es, sas_		/ remap.
	movb	es:(bx),al		/ Set value
	pop	es			/ Restore es and
	ret				/ Return

////////
/
/ Data. 
/ A small number of variables must be
/ in the code segment. All of these variables have
/ something to do with the interrupt linkage; when you
/ get an interrupt the only thing that is valid is
/ the code segment.
/
////////

	.globl	cds

	.shri
cds:	.blkw	1			/ Copy of "sds_".

	.globl	u_
	.globl	depth_,	sas_,	scs_,	sds_,	ucs_
	.globl	ucl_,	uds_,	udl_

	.bssd
	.even
u_:	.blkb	UPASIZE

	.prvd
oops:	.ascii	"stack overflow"
	.byte	0

depth_:	.byte	0			/ System state.

	.even
sas_:	.blkw	1			/ System auxiliary segment.
scs_:	.blkw	1			/ System code segment.
sds_:	.blkw	1			/ System data segment.
ucs_:	.blkw	1			/ User code segment.
ucl_:	.blkw	1			/ User code limit.
uds_:	.blkw	1			/ User data segment.
udl_:	.blkw	1			/ User data limit.
sav_ds:	.blkw	1			/ Four scratch words
sav_bx:	.blkw	1
sav_ss:	.blkw	1
sav_sp:	.blkw	1

////////
/
/ This is the image of the init process.
/ It gets copied into a user segment when the system
/ is first brought up. It must be in the data segment, because
/ that is how it is used, and it must be dephased in a funny
/ way because it is executed at location 0.
/
////////

	.globl	aicodep_		/ Position of code.
	.globl	aicodes_		/ Size of code.
	.globl	aidatap_		/ Position of data.
	.globl	aidatas_		/ Size of data.

	.shrd
aicodep_:
	sub	ax,ax			/ No environment
	push	ax
	mov	ax,$argl-aidatap_	/ Argument list
	push	ax
	mov	ax,$fn-aidatap_		/ File name
	push	ax
	sub	sp,$2			/ Dummy word for exec
	sys	11			/ Sys exec
	jmp	.			/ This should not return
aicodes_ = .-aicodep_

aidatap_:
	.word	0			/
	.word	0			/ Errno
	.word	0			/
	.word	0			/
	.word	0			/
	.word	0			/
	.word	0			/
	.word	0			/
argl:	.word	fn-aidatap_		/ argv[0] = "/etc/init";
	.word	a1-aidatap_		/ argv[1] = "";
	.word	0			/ argv[2] = NULL;

fn:	.ascii	"/etc/init\000"
a1:	.byte	0

	.even
	.blkb	64
sb:
aidatas_ = .-aidatap_
@
0707070064030104501004440000030000030000011777770507310723200005700000010474/newbits/kernel/USRSRC/i8086/src/RCS/clist.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.39.15;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.37;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $

/ (lgl-
/	The information contained herein is a trade secret of Mark Williams
/	Company, and  is confidential information.  It is provided  under a
/	license agreement,  and may be  copied or disclosed  only under the
/	terms of  that agreement.  Any  reproduction or disclosure  of this
/	material without the express written authorization of Mark Williams
/	Company or persuant to the license agreement is unlawful.
/
/	COHERENT Version 2.3.37
/	Copyright (c) 1982, 1983, 1984.
/	An unpublished work by Mark Williams Company, Chicago.
/	All rights reserved.
/ -lgl)
////////
/
/ i8086 coherent clist hack.
/ cltinit, getq and putq have been tuned.
/ the remaining functions are as produced by cc -S coh/clist.c
/ with NCPCL substituted
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  17:39:16	src
/ Initial revision
/ 

#include <sys/const.h>

	.shri
L10001:	.word	NCPCL+2
	.globl	cltinit_
cltinit_:
	push	si
	push	di
	push	bp
	mov	bp, sp
	sub	sp, $0x0C

	pushf			/ s =
	cli			/ sphi()
	sub	di, di
	mov	ax, NCLIST_
	imul	cs:L10001
	mov	-0x0C(bp), ax
	add	ax, clistp_
	mov	-0x04(bp), ax

L3:	sub	-0x04(bp), $NCPCL+2
	mov	ax, -0x04(bp)
	cmp	ax, clistp_
	jb	L2

L10002:	mov	si, -0x04(bp)
	mov	(si), di
	mov	di, si
	jmp	L3

L2:	mov	cltfree_, di
	call	spl_
	add	sp, $0x02

	mov	sp, bp
	pop	bp
	pop	di
	pop	si
	ret

	.globl	getq_

getq_:
	mov	dx, si
	push	bp
	mov	bp, sp

	mov	bp, 4(bp)	/ bp = cqp
	sub	ax, ax		/ ax = 0
	cmp	(bp), ax	/ if (cqp->cq_cc == 0)
	jne	0f
	dec	ax		/ return (-1)
	jmp	2f

0:	pushf			/ s =
	cli			/ sphi()
	mov	si, 6(bp)	/ si = op = cqp->cq_op
	mov	bx, 8(bp)	/ bx = ox = cqp->cq_ox
	movb	al, 2(bx,si)	/ ax = op->cl_ch[ox]
	dec	(bp)		/ if (--cqp->cq_cc == 0)
	je	0f
	inc	bx		/ ++ox
	cmp	bx, $NCPCL	/ if (ox == NCPL)
	jne	1f

0:	sub	bx, bx		/ ox = 0;
	mov	cx, (si)	/ cx = np = op->cl_fp
	mov	6(bp), cx	/ cqp->cq_op = np
	cmp	cx, bx		/ if (np == 0)
	jne	0f
	mov	2(bp), bx	/ cqp->cq_ip = 0
	mov	4(bp), bx	/ cqp->cq_ix = 0

0:	mov	cx, cltfree_	/ cx = tmp = cltfree
	mov	(si), cx	/ op->cl_fp = tmp
	mov	cltfree_, si	/ cltfree = op
	cmp	cltwant_, bx	/ if (cltwant != 0)
	je	1f
	mov	cltwant_, bx	/ cltwant = 0
	mov	cx, $cltwant_	/ wakeup(&cltwant)
	push	bx	/ save
	push	dx	/ save
	push	ax	/ save
	push	cx
	call	wakeup_
	pop	cx	/ clear stack
	pop	ax	/ restore
	pop	dx	/ restore
	pop	bx	/ restore

1:	mov	8(bp), bx	/ cqp->cq_ox = ox
	mov	cx, ax
	call	spl_		/ spl(s)
	add	sp, $2
	mov	ax, cx

2:	pop	bp
	mov	si, dx
	ret

	.globl	putq_

putq_:
	mov	dx, si
	push	bp
	mov	bp, sp

	mov	cx, 6(bp)	/ cx = c
	mov	bp, 4(bp)	/ bp = cqp
	sub	ax, ax		/ ax = 0
	pushf			/ s =
	cli			/ sphi()
	mov	si, 2(bp)	/ si = ip = cqp->cq_ip
	mov	bx, 4(bp)	/ bx = ix = cqp->cq_ix
	cmp	bx, ax		/ if (ix == 0)
	jne	2f
	mov	si, cltfree_	/ ip = cltfree
	cmp	si, ax		/ if (ip == 0)
	jne	0f
	call	spl_		/ spl(s)
	add	sp, $2
	mov	ax, $-1		/ return (-1)
	jmp	3f

0:	mov	bx, (si)	/ tmp = ip->cl_fp
	mov	cltfree_, bx	/ cltfree = tmp
	mov	(si), ax	/ ip->cl_fp = 0
	mov	bx, 2(bp)	/ np = cqp->cq_ip
	cmp	bx, ax		/ if (np == 0)
	jne	0f
	mov	6(bp), si	/ cqp->cq_op = ip
	jmp	1f

0:	mov	(bx), si	/ np->cl_fp = ip

1:	mov	2(bp), si	/ cqp->cq_ip = ip
	mov	bx, ax		/ bx = ix = cqp->cq_ix = 0

2:	movb	2(bx,si), cl	/ ip->cl_ch[ix] = c
	inc	bx		/ ix++
	cmp	bx, $NCPCL	/ if (ix == NCPCL)
	jne	0f
	mov	bx, ax		/ ix = 0

0:	mov	4(bp), bx	/ cqp->cq_ix = ix
	inc	(bp)		/ cqp->cq_cc++
	call	spl_		/ spl(s)
	add	sp, $2
	mov	ax, cx		/ return (c)

3:	pop	bp
	mov	si, dx
	ret

	.globl	clrq_

clrq_:
	push	si
	push	di
	push	bp
	mov	bp, sp

	mov	si, 0x08(bp)
	call	sphi_
	mov	di, ax

L18:	push	si
	call	getq_
	add	sp, $0x02
	or	ax, ax
	jge	L18
	push	di
	call	spl_
	add	sp, $0x02

	pop	bp
	pop	di
	pop	si
	ret

	.globl	waitq_

waitq_:
	push	si
	push	di
	push	bp
	mov	bp, sp

L21:	cmp	cltfree_, $0x00
	jne	L19
	mov	cltwant_, $0x01
	sub	ax, ax
	push	ax
	push	ax
	mov	ax, $0x0100
	push	ax
	mov	ax, $cltwant_
	push	ax
	call	sleep_
	add	sp, $0x08
	jmp	L21

L19:	pop	bp
	pop	di
	pop	si
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030104651004440000030000030000011777770507310723300006000000000762/newbits/kernel/USRSRC/i8086/src/RCS/cs_sel.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.36.38;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@////////
/
/ Get cs selector - return 0 if in kernel, CS if not in kernel.
/
/ This version is for resident drivers.
/ There is a different version (cs_self.s) for loadable drivers.
/
/ int	cs_sel();
/
////////

	.globl	cs_sel_
cs_sel_:
	sub	ax, ax
	ret
@
0707070064030104631004440000030000030000011777770507310723400005700000012370/newbits/kernel/USRSRC/i8086/src/RCS/defer.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.39.31;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/

////////
/
/ Defer a function [from interrupt level] for later execution
/
/	defer( f, a )	- defer a function [usually from interrupt level]
/	defend()	- execute deferred functions
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.2	88/04/04  17:05:05	src
/ ldefer/ldefend functions now allow deferred functions from loadable drivers.
/ 
/ Revision 1.1	88/03/24  17:39:20	src
/ Initial revision
/ 
/ 86/11/19	Allan Cornish		/usr/src/sys/i8086/src/defer.s
/ defer(func,arg) and defend() functions ported to Coherent from RTX.
/
////////

	.globl	defend_
	.globl	defer_
	.globl	ldefer

	.bssd
defunc:	.blkw	128		/ static void (*defunc[128])();
defarg:	.blkw	128		/ static char * defarg[128];
defqix:	.blkw	1		/ static int defqix;
defqox:	.blkw	1		/ static int defqox;
ldcseg:	.blkw	128		/ static saddr_t ldcseg[128];
ldfunc:	.blkw	128		/ static void (*ldfunc[128])();
	.shri

////////
/
/ void
/ defer( f, a )		-- defer a function [usually from interrupt level]
/ int (*f)();
/ char *a;
/
/	Input:	f = pointer to function to be deferred.
/		a = argument to pass to function when it is invoked.
/
/	Action:	Schedule function 'f' to be invoked with argument 'a'
/		during the transition from interrupt service level back
/		to user mode.
/
/	Return:	None.
/
/	Notes:	13 instructions executed.  Interrupt latency = 7 instructions.
/		Only 127 functions can be deferred at any one time.
/		Exceeding this limit will cause loss of ALL deferred functions.
/
////////

defer_:				/
	pop	ax		/ Convert IP into PSW,CS,IP to allow iret.
	pushf			/
	push	cs		/
	push	ax		/
	mov	bx, sp		/ defer( f, a )
	mov	ax, ss:6(bx)	/ register int (*f)();		/* AX */
	mov	dx, ss:8(bx)	/ register char *a;		/* DX */
				/ {
				/	register int x;		/* BX */
				/
	cli			/	sphi();
	mov	bx, defqix	/	x = defqix;
	mov	defunc(bx), ax	/	defunc[x] = f;
	mov	defarg(bx), dx	/	defarg[x] = a;
	addb	defqix, $2	/	defqix++;
//	sti			/	splo();
	iret			/ }

////////
/
/ void
/ defend( )		-- evaluate deferred functions
/
/	Action:	Evaluate all deferred functions.
/
/	Notes:	Should be called periodically by busy-wait device drivers.
/		4 + (n * 7) instructions executed, where n = # deferred func.
////////

defend_:			/ defend()
				/ {
				/
	mov	bx, defqox	/	register int x = defqox;    /* BX */
				/
	cmp	bx, defqix	/	if ( x != defqix ) {
	je	1f		/
				/		do {
0:	addb	defqox, $2	/			defqox++;
				/
	push	defarg(bx)	/			(*defunc[x])
	icall	defunc(bx)	/				(defarg[x]);
	add	sp, $2		/
				/
	mov	bx, defqox	/			x = defqox;
	cmp	bx, defqix	/
	jne	0b		/		} while ( x != defqix );
				/	}
1:	ret			/ }

////////
/
/ void
/ ldefer( f, a )	-- defer a far function [usually from interrupt level]
/ int (far*f)();
/ char *a;
/
/	Input:	f = pointer to loadable driver function to be deferred.
/		a = argument to pass to function when it is invoked.
/
/	Action:	Schedule loadable driver function 'f' to be invoked with
/		argument 'a' during the transition from interrupt service
/		level back to user mode.
/
/	Return:	None.
/
/	Notes:	16 instructions executed.  Interrupt latency = 8 instructions.
/		Only 127 functions can be deferred at any one time.
/		Exceeding this limit will cause loss of ALL deferred functions.
/
////////

ldefer:				/
	pop	ax		/ Convert IP into PSW,CS,IP to allow iret.
	pushf			/
	push	cs		/
	push	ax		/
	mov	bx, sp		/ defer( f, a )
	mov	ax, ss:6(bx)	/ register int (*f)();		/* CX:AX */
	mov	cx, ss:8(bx)	/
	mov	dx, ss:10(bx)	/ register char *a;		/* DX */
				/ {
				/	register int x;		/* BX */
				/
	cli			/	sphi();
	mov	bx, defqix	/	x = defqix;
	mov	ldfunc(bx), ax	/	ldfunc[x] = FP_OFF(f);
	mov	ldcseg(bx), cx	/	ldcseg[x] = FP_SEL(f);
	mov	defunc(bx),$ldefend/	defunc[x] = ldefend;
	mov	defarg(bx), dx	/	defarg[x] = a;
	addb	defqix, $2	/	defqix++;
//	sti			/	splo();
	iret			/ }

////////
/
/ static void
/ ldefend( )		-- evaluate deferred far function
/
/	Action:	Evaluate deferred far function.
/
/	Notes:	Only called by defend().  Register BX contains driver's defqox.
/
////////

ldefend:			/ PARAMETERS MUST REMAIN AT 4(BP).
	push	bp		/ DRIVER RESIDENT CODE RELIES ON THIS.
	mov	bp, sp		/
				/
	mov	ax, ldfunc(bx)	/ AX = Driver function to be invoked.
				/
	push	ldcseg(bx)	/ Define driver entry point.
	push	four		/
				/
	xcall	-4(bp)		/ Invoke driver entry point, which will
				/	in turn invoke the deferred function.
				/
	mov	sp, bp		/ Return to caller.
	pop	bp		/
	ret			/

	.prvd
four:	.word	4
	.shri
@


1.1
log
@Initial revision
@
text
@@
0707070064030104661004440000030000030000011777770507310723500006100000004300/newbits/kernel/USRSRC/i8086/src/RCS/clocked.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.39.27;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.46;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/*
 * clocked.c - support routines for alternate clock rate
 *
 *  altclk_in(hz, fn) - install routine with specified rate
 *                      "hz" should be a multiple of system rate of 100 Hz
 *			return 0 if completed ok, -1 otherwise
 *
 *  altclk_out()      - uninstall alternate clock routine and restore system rate
 *			return old value of "altclk"
 *
 *  altclk_rate(hz)   - set clock interrupt rate
 *			new rate must be an even multiple of system rate "HZ"
 *			return 0 if completed ok, -1 otherwise
 *
 *  History:
 *    90/08/08 hws	initial version, works with hs.c modified for com[1-4]
 *    90/08/14 hws	make it more like a Unix system call
 */

#include	<sys/coherent.h>		/* altclk */
#include	<sys/const.h>		/* HZ */

#define	PIT	0x40		/* 8253 port */
#define	TMR0_M3	0x36		/* timer 0, mode 3 */

#if 0
				/* nominal IBM rate is 1.1900 MHz */
#define	SYS_HZ	1190000L	/* rate of input clock to timer 0 */
#else
				/* current kernel rate is 1.1932 MHz */
#define	SYS_HZ	1193200L	/* rate of input clock to timer 0 */
#endif

typedef int (*PFI)();		/* pointer to function returning int */

altclk_rate(hz)
unsigned int hz;
{
	int s;			/* to save CPU irpt flag */
	unsigned int interval;	/* period for hz, in units of 1.19 MHz ticks */
	int ret;

	if (hz >= HZ && hz % HZ == 0) {		/* can't go slower than HZ! */
		interval = SYS_HZ/hz;
		s = sphi();			/* disable irpts */
		outb(PIT+3, TMR0_M3);
		outb(PIT, interval & 0xff);
		outb(PIT, interval >> 8);	/* unsigned shift */
		spl(s);				/* restore previous irpt state */
		ret = 0;
	} else {
		ret = -1;
	}
	return ret;
}

int altclk_in(hz, fn)
int hz;
PFI fn;
{
	int ret;

	if ((ret = altclk_rate(hz)) == 0)
		altclk = fn;
	return ret;
}

PFI altclk_out()
{
	PFI ret;

	ret = altclk;
	if (ret) {
		altclk_rate(HZ);
		altclk = 0;
	}
	return ret;
}
@


1.1
log
@Initial revision
@
text
@d20 1
a20 1
#include	"coherent.h"		/* altclk */
@
0707070064030104641004440000030000030000011777770507310723500006100000010521/newbits/kernel/USRSRC/i8086/src/RCS/dmalock.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.39.37;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.47;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, Ltd, and is  confidential information.   It is provided
 *	under a license agreement,  and may be copied or disclosed  only
 *	under  the  terms  of  that  agreement.    Any  reproduction  or
 *	disclosure  of  this   material   without  the  express  written
 *	authorization of INETCO Systems, Ltd. or persuant to the license
 *	agreement is unlawful.
 *
 *	Copyright (c) 1989
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 *
 * $Description: $
 *	Routines to lock/unlock the DMA controller chip.
 *
 * $Author: root $
 *
 * $Creation: June 21, 1989 $
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	89/06/30  16:21:26 	src
 * Initial revision
 * 
 */

#include <sys/timeout.h>

typedef void (* vfp_t)();		/* Void function pointer type.	     */

/*
 * If the following variable is non-zero, DMA controller locking is enabled,
 * allowing at access to only one DMA channel at a time.
 */
int DMALCK = 1;

static TIM * dmatail = (TIM *)0;	/* DMA deferred function queue tail. */
static TIM * dmahead = (TIM *)0;	/* DMA deferred function queue head. */

/*
 * int
 * dmalock( dfp, fun, arg )
 * TIM * dfp;
 * vfp_t fun;
 * int	 arg;
 *
 *	Inputs:	dfp  = Deferred function structure pointer.
 *		fun  = Function to call if request is deferred.
 *		arg  = Argument to pass to function.
 *
 *	Action:	Either locks DMA controller immediately or defers function
 *		call until lock can be granted.
 *
 *	Return:	0 = Lock granted or -1 = Lock deferred.
 *
 *	Notes:	DMA controller locking was introduced to cure a bug on the
 *		NCR DMA controller, where overlapped DMA caused problems.
 *		No action is taken if DMA locking is disabled.
 */

int
dmalock( dfp, fun, arg )
register TIM  * dfp;
vfp_t		fun;
int		arg;
{
	register int s;		/* Interrupt mask state. */

	/*
	 * If DMA locking is disabled, allow functions to proceed.
	 */
 	if ( DMALCK == 0 )
		return( 0 );

	/*
	 * Record function and argument to be invoked upon dmaunlock.
	 */
	dfp->t_func = fun;
	dfp->t_farg = arg;
	dfp->t_next = (TIM *)0;

	s = sphi();

	/*
	 * If the queue is empty, put our structure at the head.
	 */
	if ( dmahead == (TIM *)0 ) {
		dmahead = dfp;
		dmatail = dfp;
		spl( s );
		return( 0 );
	}

	/*
	 * PARANOIA:	If our structure is already at the head of the queue,
	 *		print a message and return.
	 */
	if ( dmahead == dfp ) {
		spl( s );
		printf( "dmalock: driver attempting to doubly lock DMA controller.\n" );
		return( 0 );
	}

	/*
	 * Append to tail of DMA deferred function queue.
	 */
	dmatail->t_next = dfp;
	dmatail		= dfp;
	spl( s );
	return( -1 );
}

/*
 * void
 * dmaunlock( dfp )
 * TIM * dfp;
 *
 *	Inputs:	dfp = Deferred function structure pointer.
 *
 *	Action:	Unlocks the DMA controller and calls the next deferred
 *		function, if any.
 *
 *	Notes:	No action is taken if the deferred function structure pointer
 *		is not the same as the one used to lock the DMA controller.
 */

void
dmaunlock( dfp )
register TIM * dfp;
{
	register TIM *	qp;	/* Temporary function queue pointer.	*/
	register int	s;	/* Interrupt mask state.		*/

	s = sphi();

	/*
	 * If the DMA controller is not locked, return.
	 */
	if ( dmahead == (TIM *)0 ) {
		spl( s );
		return;
	}

 	/*
	 * If our lock is not the one holding the DMA controller:
	 */
	if ( dmahead != dfp ) {

		/*
		 * Look for us in queue.
		 */
		for ( qp = dmahead; qp != dmatail; qp = qp->t_next )

			/*
			 * If found, remove us.
			 */
			if ( qp->t_next == dfp ) {
				qp->t_next = dfp->t_next;

				if ( dmatail == dfp )
					dmatail = qp;

				break;
			}

		spl( s );
		return;
	}

	/*
	 * If there are no functions waiting for us, empty queue and return.
	 */
	if ( dmahead == dmatail ) {
		dmahead = (TIM *)0;
		spl( s );
		return;
	}

	/*
	 * Remove us and execute next deferred function.
	 */
	dmahead = dmahead->t_next;
	spl( s );
	(*dmahead->t_func)( dmahead->t_farg, dmahead );
}

@


1.1
log
@Initial revision
@
text
@@
0707070064030104621004440000030000030000011777770507310723600005600000044253/newbits/kernel/USRSRC/i8086/src/RCS/exec.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.39.41;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.49;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * This file contains a special version
 * of "sys exec" for the i8086. This version has
 * no driver load code in it (save space) and has
 * special load code so that the text of a shared
 * and separated image can be shared.
 * Loadable kernel processes are partially supported:
 * the process text and data must be ld'ed with the system
 * and the l.out executed must have no loadable or allocateable
 * segments.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:26	src
 * Initial revision
 * 
 * 88/01/21	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * Segments are now de-associated from processes before freeing the segment.
 *
 * 87/12/03	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * ld_start() now reverts to kernel mode [depth=0] from user mode [depth=1].
 *
 * 87/11/25	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/11/14	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * Init code+data now split into icodep/icodes and idatap/idatas.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/10/09	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * pload() now handles new format [separate code] loadable device drivers.
 *
 * 87/10/08	Allan Cornish		/usr/src/sys/i8086/src/exec.c
 * Exsread() initializes the (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <l.out.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>
#include <sys/i8086.h>

/*
 * Sizes.
 */
#define	sh	((fsize_t)sizeof(struct ldheader))
#define si	lssize[L_SHRI]
#define pi	lssize[L_PRVI]
#define bi	lssize[L_BSSI]
#define sd	lssize[L_SHRD]
#define pd	lssize[L_PRVD]
#define bd	lssize[L_BSSD]

/*
 * Segments.
 */
#define upsp	pp->p_segp[SIUSERP]
#define sssp	pp->p_segp[SISTACK]
#define	sisp	pp->p_segp[SISTEXT]
#define pisp	pp->p_segp[SIPTEXT]
#define pdsp	pp->p_segp[SIPDATA]

/*
 * Loadable driver initiation point.
 */
static
ld_start()
{
	register SEG * sp;
	register int ret;

	/*
	 * Kernel processes start by default at user level.
	 * Revert to kernel level.
	 */
	if ( depth == 1 )
		depth--;

	/*
	 * Initialize memory references.
	 */
	u.u_btime = timer.t_time;
	sproto();
	segload();


	/*
	 * Invoke the driver if it has a shared or private code segment.
	 */
	ret = 100;
	if ( (sp = SELF->p_segp[SISTEXT]) || (sp = SELF->p_segp[SIPTEXT]) ) {
		ret = ld_xcall( sp->s_faddr );
	}

	uexit( ret );
}

/*
 * Set up the first process, a small programme which will exec
 * the init programme.
 */
eveinit(sp)
SEG *sp;
{
	register PROC *pp;
	SELF = pp = eprocp;

	/*
	 * Record user area.
	 */
	pp->p_segp[SIUSERP] = sp;

	/*
	 * Allocate, record, initialize code segment, make it executable.
	 */
	if ((sp=salloc((fsize_t)icodes, 0)) == NULL)
		panic("eveinit(code)");
	pp->p_segp[SIPTEXT] = sp;
	kfcopy( icodep, sp->s_faddr, icodes );
	sp->s_flags |= SFTEXT;
	vremap(sp);

	/*
	 * Allocate, record, and initialize data segment.
	 */
	if ((sp=salloc((fsize_t)idatas, 0)) == NULL)
		panic("eveinit(data)");
	pp->p_segp[SIPDATA] = sp;
	kfcopy( idatap, sp->s_faddr, idatas );

	/*
	 * Allocate and record stack segment.
	 */
	if ((sp=salloc((fsize_t)UPASIZE, SFDOWN)) == NULL)
		panic("eveinit()");
	pp->p_segp[SISTACK] = sp;

	/*
	 * Start process.
	 */
	u.u_argp = 0;
	if (sproto() == 0)
		panic("eveinit()");
	segload();
}

/*
 * Load a driver which has already been linked into the system image.
 */
pload( np )
char * np;
{
	register INODE * ip;
	register PROC  * cpp;
	struct seg     * sp;
	fsize_t		lssize[NUSEG];		/* Segment sizes */
	int		lflag;			/* l_flags from l.out */
	vaddr_t		pc;			/* l_entry from l.out */
	int		r;			/* Flag for "exload" */
	int		s;
	extern char	end[];


	if (super() == 0) {
		return( -1 );
	}

	/*
	 * Coalesce memory BEFORE loading driver, since it can't be moved.
	 */
	krunch(10000);

	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
		return( -1 );
	}

	/*
	 * New format loadable drivers must have separate code/data.
	 * It must have executable code, but no initialized data.
	 * Uninitialized data must match the kernel data size.
	 */
	if ( ((lflag & (LF_KER|LF_SHR|LF_SEP)) != (LF_SEP|LF_KER))
	  || (si==0) || (sd!=0) || (pd!=0) || (bd != (int)end) ) {
		u.u_error = EBADFMT;
		idetach(ip);
		return( -1 );
	}

	/*
	 * Allocate and initialize driver code segment.
	 * NOTE: Must be system segment to prevent relocation.
	 */
	sp = ssalloc(&r, ip, SFTEXT|SFHIGH|SFNSWP|SFSYST, si+pi+bi, sh, si+pi);

	/*
	 * Release driver object file.
	 */
	idetach(ip);

	if ( r < 0 ) {
		u.u_error = ENOMEM;
		return( -1 );
	}

	/*
	 * Spawn kernel process to service driver.
	 */
	if ((cpp = process(ld_start)) == NULL ) {
		u.u_error = ENOMEM;
		sfree(sp);
		return( -1 );
	}

	/*
	 * Record the basename of the loaded driver.
	 */
	kscopy( u.u_direct.d_name, cpp->p_segp[SIUSERP],
		offset(uproc,u_comm[0]), sizeof(u.u_comm) );

	/*
	 * Record the driver code segment in the process's private code.
	 */
	cpp->p_segp[SIPTEXT] = sp;
	cpp->p_cval = CVCHILD;
	cpp->p_sval = SVCHILD;
	cpp->p_rval = RVCHILD;
	cpp->p_ppid = 1;

	/*
	 * Make the process executable.
	 */
	s = sphi();
	setrun( cpp );
	spl( s );

	/*
	 * Return driver process id.
	 */
	return( cpp->p_pid );
}

/*
 * Given a major number, undo the previous function.
 */
puload(m)
int m;
{
	register CON *cp;
	register DRV *dp;

	dp = &drvl[m];
	lock(dp->d_gate);
	if (m>=drvn || (cp=dp->d_conp)==NULL) {
		u.u_error = ENXIO;
		goto ret;
	}
	(*cp->c_uload)();
	if ( ! u.u_error)
		dp->d_conp = NULL;
ret:
	unlock(dp->d_gate);
	return (0);
}

/*
 * Pass control to an image in a file.
 * Make sure the format is acceptable. Release
 * the old segments. Read in the new ones. Some special
 * care is taken so that shared and (more important) shared
 * and separated images can be run on the 8086.
 */
pexece(np, argp, envp)
char	*np;
char	*argp[];
char	*envp[];
{
	register INODE	*ip;			/* Load file INODE */
	register PROC	*pp;			/* A cheap copy of SELF */
	register SEG	*ssp;			/* New stack segment */
 	register SEG    *segp;
	register fsize_t	ss;			/* Segment size temp. */
	register int	i;			/* For looping over segments */
	int		r;			/* Flag for "exload" */
	int		lflag;			/* l_flags from l.out */
	vaddr_t		pc;			/* l_entry from l.out */
	vaddr_t		sp;			/* Initial stack pointer */
	fsize_t		lssize[NUSEG];		/* Segment sizes */
	fsize_t		codsize;		/* Total if CS segment	*/
	fsize_t		datsize;		/* Total of DS segment	*/
	extern fsize_t	exround();		/* Paragraph rounder */

	pp = SELF;
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
		return;
	}

	if ( (lflag & LF_SEP) == 0 ) {
		u.u_error = EBADFMT;
		idetach(ip);
		return;
	}

	/*
	 * Kernel processes are now supported through the sload() system call.
	 * 87/10/09	Allan Cornish.
	 */
	if ((lflag&LF_KER) != 0) {
		u.u_error = EBADFMT;
		idetach(ip);
		return;
	}

	/*
	 * If a shared and separated image
 	 * has stuff in segments that makes it impossible
	 * to share, give an error immediately so that we don't
	 * lose the parent.
	 */
	lflag &= LF_SHR|LF_SEP;

	if (lflag==(LF_SHR|LF_SEP) && (pi!=0 || bi!=0)) {
		u.u_error = EBADFMT;
		idetach(ip);
		return;
	}

	if ((ssp=exstack(&sp, argp, envp)) == NULL) {
		idetach(ip);
		return;
	}

	switch (lflag) {
	case LF_SEP:
		codsize = si+pi+bi;
		datsize = ssp->s_size+sd+pd+bd;
		break;
	case LF_SHR|LF_SEP:
		codsize = si;
		datsize = ssp->s_size+exround(sd)+pd+bd;
		break;
	}
	codsize = (codsize+(BSIZE-1)) & ~(BSIZE-1);
	datsize = (datsize+(BSIZE-1)) & ~(BSIZE-1);
	if ( (codsize >= MAXU) || (datsize >= MAXU) ) {
		u.u_error = E2BIG;
		idetach(ip);
		return;
	}

	/*
	 * At this point the file has been
	 * validated as an object module, and the
	 * argument list has been built. Release all of
	 * the original segments. At this point we have
	 * committed to the new image. A "sys exec" that
	 * gets an I/O error is doomed.
 	 * NOTE: User-area segment is NOT released.
 	 *	 Segment pointer in proc is erased BEFORE invoking sfree().
	 */
	for ( i = 1; i < NUSEG; ++i ) {
 		if ((segp = pp->p_segp[i]) != NULL) {
			pp->p_segp[i] = NULL;
			sfree(segp);
		}
	}

	/*
	 * Read in the loadable segments.
	 */
	sssp = ssp;
	switch (lflag) {
	case 0:
		ss = si+pi+sd+pd;
		pdsp = ssalloc(&r, ip, 0, ss+bi+bd, sh, ss);
		if (r < 0)
			goto out;
		break;

	case LF_SHR:
		ss = exround(si+sd);
		pdsp = ssalloc(&r, ip, 0, ss+pi+pd+bi+bd, sh, si);
		if (r < 0)
			goto out;
		if (exsread(pdsp, ip, sd, sh+si+pi, si) == NULL)
			goto out;
		if (exsread(pdsp, ip, pi, sh+si, ss) == NULL)
			goto out;
		if (exsread(pdsp, ip, pd, sh+si+pi+sd, ss+pi) == NULL)
			goto out;
		break;

	case LF_SEP:
		pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+pi, sd+pd);
		if (r < 0)
			goto out;
		break;

	case LF_SHR|LF_SEP:
		/* pi=0, bi=0 */
		sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si);
		if (r < 0)
			goto out;
		ss = exround(sd);
		pdsp = ssalloc(&r, ip, 0, ss+pd+bd, sh+si, sd);
		if (r<0 || exsread(pdsp, ip, pd, sh+si+sd, ss) == NULL)
			goto out;
	}
	if (sproto() == 0)
		 goto out;
#if 0
	if ( (datsize != pdsp->s_size) ||
	     ( (lflag==LF_SEP) && (codsize != pisp->s_size) ) ||
	     ( (lflag==(LF_SEP|LF_SHR)) && (codsize != sisp->s_size) ) ) {
		printf("\nExec ERROR:  codsize: 0x%X  datsize: 0x%X\n", 
					codsize, datsize);
		printf(
		"pdsp->s_size: 0x%X  pisp->s_size: 0x%X  sisp->s_size: 0x%X\n",
			pdsp->s_size, pisp->s_size, sisp->s_size);
	}
#endif
	/*
	 * The new image is read in
	 * and mapped. Perform the final grunge
	 * (set-uid stuff, accounting, loading up
	 * registers, etc).
	 */
	u.u_flag &= ~AFORK;
	kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
	if (iaccess(ip, IPR) == 0) {	/* Can't read ? no dump or trace */
		pp->p_flags |= PFNDMP;
		pp->p_flags &= ~PFTRAC;
	}
	if (iaccess(ip, IPW) == 0)	/* Can't write ? no trace */
		pp->p_flags &= ~PFTRAC;
	if ((ip->i_mode&ISUID) != 0) {	/* Set user id ? no trace */
		pp->p_uid = u.u_uid = ip->i_uid;
		pp->p_flags &= ~PFTRAC;
	}
	if ((ip->i_mode&ISGID) != 0) {	/* Set group id ? no trace */
		u.u_gid = ip->i_gid;
		pp->p_flags &= ~PFTRAC;
	}
	for (i=0; i<NSIG; ++i)
		if (u.u_sfunc[i] != SIG_IGN)
			u.u_sfunc[i] = SIG_DFL;
	if ((pp->p_flags&PFTRAC) != 0)	/* Being traced */
		sendsig(SIGTRAP, pp);
	idetach(ip);
	msetusr(pc, sp);
	segload();
	return (0);

	/*
	 * We did not make it.
	 * Release the INODE for the load
	 * file, and return through the "sys exit"
	 * code with a "SIGSYS", or with the signal actually received
	 * if we are aborting due to interrupted exec.
	 */
out:
	idetach(ip);
	if (u.u_error == EINTR)
		pexit(nondsig());
	pexit(SIGSYS);
}

/*
 * Open an l.out, make sure it is an l.out and executable and return the
 * appropriate information.
 */
INODE *
exlopen(np, ssizep, flagp, pcp)
char *np;
fsize_t *ssizep;
int *flagp;
vaddr_t *pcp;
{
	register INODE *ip;
	register struct ldheader *ldp;
	register int n;
	register BUF *bp;
	int m;

	/*
	 * Make sure the file is really an executable l.out and read the
	 * header in.
	 */
	if (ftoi(np, 'r') != 0)
		return (NULL);
	ip = u.u_cdiri;
	if (iaccess(ip, IPE) == 0) {
		idetach(ip);
		return (NULL);
	}
	if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
		u.u_error = EACCES;
		idetach(ip);
		return (NULL);
	}
	if ((bp=vread(ip, (daddr_t)0)) == NULL) {
		u.u_error = EBADFMT;
		idetach(ip);
		return (NULL);
	}

	/*
	 * Copy everything we need from the l.out header and check magic
	 * number and machine type.
	 */
	ldp = FP_OFF(bp->b_faddr);
	m = ldp->l_magic;
	canint(m);
	if (m != L_MAGIC) {
		u.u_error = ENOEXEC;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	m = ldp->l_machine;
	canint(m);
	if (m != mactype) {
		u.u_error = EBADFMT;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(fsize_t));
	for (n=0; n<NXSEG; n++)
		cansize(ssizep[n]);
	*flagp = ldp->l_flag;
	canint(*flagp);
	*pcp = ldp->l_entry;
	canvaddr(*pcp);
	brelease(bp);
	return (ip);
}

/*
 * Given a segment `sp', read `ss' bytes from the inode `ip' starting
 * at seek address `sa' into offset `so' in the segment.
 */
SEG *
exsread(sp, ip, ss, sa, so)
register SEG *sp;
INODE *ip;
fsize_t ss;
fsize_t sa;
fsize_t so;
{
	while (ss > 0) {
		u.u_io.io_seg = IOPHY;
		u.u_io.io_seek = sa;
		u.u_io.io_phys = sp->s_paddr + so;
		u.u_io.io_flag = 0;
		if (ss >= 4096) {
			u.u_io.io_ioc = 4096;
			ss -= 4096;
		} else {
			u.u_io.io_ioc = ss;
			ss = 0;
		}
		sp->s_lrefc++;
		iread(ip, &u.u_io);
		sp->s_lrefc--;
		if (nondsig()) {
			u.u_error = EINTR;
			break;
		}
		sa += 4096;
		so += 4096;
	}
	if (u.u_error == 0)
		return (sp);
	return (NULL);
}

/*
 * Given a pointer to a list of arguments and a pointer to a list of
 * environments, return a stack with the arguments and environments on it.
 */
SEG *
exstack(iusp, argp, envp)
char **iusp;		/* Back patch sp value */
char *argp[];		/* Arguments for new process */
char *envp[];		/* Environments for new process */
{
	SEG *sp;		/* Stack segment pointer */
	struct adata {		/* Storage for arg and env data */
		char	**up;		/* User vector pointer */
		int	np;		/* Number of pointers in vector */
		int	nc;		/* Number of characters in strings */
	} arg, env;
	struct sdata {		/* To keep segment pointers */
		vaddr_t	base;		/* Top of segment virtual */
		vaddr_t	ap;		/* Argc, argv, envp pointer */
		vaddr_t	vp;		/* Argv[i], envp[i] pointer */
		vaddr_t	cp;		/* Argv[i][j], envp[i][j] pointer */
	} aux, stk;
	aold_t aold;			/* Auxiliary map storage */
	register char **usrvp;		/* Vector pointer into user seg */
	register char *usrcp;		/* Character pointer into user seg */
	register int c;			/* Character fetched from user */
	register int chrsz;		/* Size of strings */
	register struct adata *adp;	/* Arg and env scanner */
	register int vecsz;		/* Size of vectors */
	register int stksz;		/* Size of stack argument region */

	/* Validate and evaluate size of args and envs */
	arg.up = argp;
	env.up = envp;
	chrsz = 0;
	vecsz = 0;
	for (adp = &arg; ; adp = &env) {
		adp->np = 0;
		adp->nc = 0;
		if (excount(adp->up, &adp->np, &adp->nc) == 0)
			return (NULL);
		chrsz += adp->nc * sizeof(char);
		vecsz += adp->np * sizeof(char *);
		if (adp == &env)
			break;
	}

	/* Calculate stack size and allocate it */
	chrsz = roundu(chrsz, sizeof(int));
	stksz = sizeof(int)		/* argc */
		+ sizeof(char **)	/* argv */
		+ sizeof(char **)	/* envp */
		+ vecsz			/* argv[i] and envp[i] */
		+ chrsz			/* *argv[i] and *envp[i] */
		+ sizeof(int)		/* Mystery zero word */
		+ sizeof(char *)	/* Splimit for z8000 */
		+ sizeof(int);		/* errno */
	stksz += ISTSIZE;
	if (stksz > MADSIZE) {
		u.u_error = E2BIG;
		return (NULL);
	}
	if ((sp=salloc((fsize_t)stksz, SFDOWN)) == NULL)
		return (NULL);
	stksz -= ISTSIZE;

	/*
	 * Initialize segment data.
	 */
	asave(aold);

	abase(FP_SEL(sp->s_faddr));
	aux.base = sp->s_size;
	aux.ap = aux.base - stksz;
	aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **);
	aux.cp = aux.vp + vecsz;

	stk.base = ISTVIRT;
	stk.ap = stk.base - stksz;
	stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **);
	stk.cp = stk.vp + vecsz;

	/*
	 * Write argc.
	 */
	aputi((int *)aux.ap, arg.np-1);
	aux.ap += sizeof(int);

	/*
	 * Arguments and environments.
	 */
	for (adp = &arg; ; adp = &env) {

		/* Write argv or envp */
		aputp((char ***)aux.ap, (char **)stk.vp);
		aux.ap += sizeof(char **);
		if ((usrvp = adp->up) != NULL) {

			/* Write argv[i] or envp[i] */
			while ((usrcp = getupd(usrvp++)) != NULL) {
				aputp((char **)aux.vp, (char *)stk.cp);
				aux.vp += sizeof(char *);
				stk.vp += sizeof(char *);

				/* Write argv[i][j] or envp[i][j] */
				do {
					c = getubd(usrcp++);
					aputc((char *)aux.cp, c);
					aux.cp += sizeof(char);
					stk.cp += sizeof(char);
				} while (c != '\0');
			}
		}

		/* Write argv[argc] or envp[envc] */
		aputp((char **)aux.vp, NULL);
		aux.vp += sizeof(char *);
		stk.vp += sizeof(char *);
		if (adp == &env)
			break;
	}

	/*
	 * Clear out the slop.
	 */
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* errno */
	aux.base -= sizeof(char *);
	aputp((char **) aux.base, (char *)stk.base - sp->s_size + SOVSIZE);
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* mystery word */

	arest(aold);

	/*
	 * Patch some values and return.
	 */
	*iusp = stk.ap;		/* Patch initial usp */
	u.u_argc = arg.np-1;
	u.u_argp = stk.vp;	/* Points after NULL of envs */
	return (sp);
}

/*
 * Given a pointer to a list of arguments, a pointer to an argument count
 * and a pointer to a byte count, update incrementally the argument count
 * and the byte count.
 */
excount(usrvp, nap, nbp)
register char **usrvp;
int *nap;
int *nbp;
{
	register char *usrcp;
	register int c;
	register unsigned nb;
	register unsigned na;

	na = 1;
	nb = 0;
	if (usrvp != NULL) {
		for (;;) {
			usrcp = getupd(usrvp++);
			if (u.u_error)
				return (0);
			if (usrcp == NULL)
				break;
			na++;
			for (;;) {
				c = getubd(usrcp++);
				if (u.u_error)
					return (0);
				nb++;
				if (c == '\0')
					break;
			}
		}
	}
	*nap += na;
	*nbp += nb;
	return (1);
}

/*
 * Round up a size to a paragraph
 * (mod 16) boundry.
 * This is really mod 512 to make swapping work
 */
fsize_t
exround(s)
fsize_t	s;
{
	return ((s+15)&~0x0F);
}
@


1.1
log
@Initial revision
@
text
@d66 1
a66 1
#include <i8086.h>
@
0707070064030104611004440000030000030000011777770507310724300006000000010526/newbits/kernel/USRSRC/i8086/src/RCS/krunch.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.39.59;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.54;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987.
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Coherent.
 * Segment crunch.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:33	src
 * Initial revision
 * 
 * 87/12/02	Allan Cornish	/usr/src/sys/i8086/src/krunch.c
 * krunch() now locks/unlocks segment gate.
 *
 * 87/11/26	Allan Cornish	/usr/src/sys/i8086/src/krunch.c
 * krunch() now called to merge unused memory by moving segments.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/proc.h>
#include <sys/seg.h>

/*
 * Time interval in clock ticks between krunch attempts: default 2 seconds.
 */
int KRUNCH = 200;

/**
 *
 * krunch( n )
 * int n;
 *
 *	Input:	n = maximum number of segments to be moved.
 *
 *	Action:	Scan the segmentation list, looking for unused memory
 *		immediately below unlocked application segments,
 *		moving the segment down into the unused memory.
 */
krunch( n )
int n;
{
	register SEG *sp;
	paddr_t paddr;
	saddr_t osel;
	static TIM tim;
	int s;

	if ( depth != 0 ) {
		printf("krunch(%d,depth=%d) ", n, depth );	/** DEBUG **/
		return;
	}

	/*
	 * Do not crunch segment list if swapper is active.
	 */
	if ( (KRUNCH == 0) || (sexflag != 0) )
		return;

	/*
	 * Segment count of 0 indicates a request to schedule delayed krunch(1).
	 */
	if ( n <= 0 ) {
		if ( tim.t_last != NULL )
			timeout( &tim, KRUNCH, krunch, 1 );
		return;
	}

	/*
	 * Segmentation is locked - retry later.
	 */
	s = sphi();
	if ( locked(seglink) ) {
		timeout( &tim, KRUNCH, krunch, n );
		spl(s);
		return;
	}
	lock(seglink);
	spl(s);

#if EBUG > 1
	printf("krunch(%d) ", n );
#endif

	for ( paddr = corebot, sp = &segmq;
	      (sp = sp->s_forw) != &segmq ;
	      paddr = sp->s_paddr + sp->s_size ) {

		/*
		 * No hole exists.
		 */
		if ( paddr == sp->s_paddr )
			continue;

#if EBUG > 1
		printf("hole(p=%X,n=%X) seg(p=%X,n=%X,f=%x,u=%x,l=%x) ",
			paddr,
			sp->s_paddr - paddr,
			sp->s_paddr,
			sp->s_size,
			sp->s_flags & (SFSYST|SFHIGH),
			sp->s_urefc,
			sp->s_lrefc );
#endif

		/*
		 * Don't try to shuffle high segments into low memory.
		 */
		if ( sp->s_flags & SFHIGH )
			break;

		/*
		 * System segment.
		 */
		if ( sp->s_flags & SFSYST )
			continue;

		/*
		 * Segment may be in process of being swapped in/out.
		 */
		if ( (sp->s_flags & SFCORE) == 0 )
			continue;

		/*
		 * Segment is locked for I/O.
		 */
		if ( sp->s_lrefc != sp->s_urefc )
			continue;

#if EBUG > 0
		printf("move(dst=%X,src=%X,len=%X) ",
			paddr, sp->s_paddr,sp->s_size );
#endif
		/*
		 * Remember previous virtual address.
		 */
		osel = FP_SEL(sp->s_faddr);

		/*
		 * Shift segment into the hole.
		 */
		plrcopy( sp->s_paddr, paddr, sp->s_size );
		sp->s_paddr = paddr;
		vremap( sp );

#if EBUG > 0
		if ( FP_SEL(sp->s_faddr) != osel ) {
			printf("krunch: osel=%x nsel=%x\n",
				osel, FP_SEL(sp->s_faddr) );
		}
#endif

		/*
		 * Ensure user segmentation is updated.
		 * We may have moved the current process.
		 */
		if ( (SELF->p_pid != 0) && ((ucs == osel) || (uds == osel)) )
			segload();
		if ( uasa == osel )
			uasa = FP_SEL(sp->s_faddr);

		/*
		 * Crunch count reached.
		 */
		if ( --n <= 0 )
			break;
	}

	/*
	 * Cancel timer if all low memory holes eliminated.
	 */
	if ( (KRUNCH == 0) || (sp == &segmq) || (sp->s_flags & SFHIGH) )
		timeout( &tim, 0, NULL, 0 );

	/*
	 * Attempt to crunch another segment in KRUNCH clock ticks.
	 */
	else
		timeout( &tim, KRUNCH, krunch, 1 );

	unlock(seglink);

#if EBUG > 0
	printf("\n");
#endif
}
@


1.1
log
@Initial revision
@
text
@d29 1
a29 1
#include <coherent.h>
@
0707070064030104601004440000030000030000011777770507310724400005400000004676/newbits/kernel/USRSRC/i8086/src/RCS/ld.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.40.05;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.56;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1986
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Pseudo-Device Interface to Loadable Drivers.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:36	src
 * Initial revision
 * 
 * 87/12/08	Allan Cornish	/usr/src/sys/i8086/src/ld.c
 * Block device interface added to loadable drivers.
 *
 * 87/10/25	Allan Cornish		/usr/src/sys/i8086/drv/ld.c
 * Initial version.
 */

#include	<sys/coherent.h>
#include 	<sys/fdisk.h>
#include	<sys/buf.h>
#include	<sys/con.h>
#include	<sys/stat.h>
#include	<sys/uproc.h>
#include	<errno.h>

/*
 * Driver configuration.
 */
void	ld_open();
void	ld_close();
void	ld_read();
void	ld_write();
void	ld_block();
int	ld_ioctl();
void	ld_power();
void	ld_time();
int	ld_poll();
void	nulldev();
void	nonedev();

/*
 * Loadable driver: Pseudeo-device configuration.
 */
CON ldrvpsy = {
	DFCHR|DFBLK|DFPOL,		/* Flags */
	0,				/* Major index */
	ld_open,			/* Open */
	ld_close,			/* Close */
	ld_block,			/* Block */
	ld_read,			/* Read */
	ld_write,			/* Write */
	ld_ioctl,			/* Ioctl */
	ld_power,			/* Powerfail */
	ld_time,			/* Timeout */
	nulldev,			/* Load */
	nulldev,			/* Unload */
	ld_poll				/* Poll */
};

/*
 * Loadable driver: Code selectors.
 */
saddr_t ldrvsel[NDRV];

/*
 * Loadable driver: Pointers to driver configuration table.
 */
CON * ldrvcon[NDRV];

/*
 * Loadable driver: Selector referencing interrupt handler's code segment.
 */
saddr_t ldrvics[16];

/*
 * Loadable driver: Pointers to interrupt handlers within the loadable driver.
 */
void (*ldrvipc[16])();
@


1.1
log
@Initial revision
@
text
@d29 1
a29 1
#include	<coherent.h>
@
0707070064030104571004440000030000030000011777770507310724400005500000013432/newbits/kernel/USRSRC/i8086/src/RCS/md1.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.40.17;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.57;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * 8086/8088 Coherent.
 * All machines.
 * Machine dependent stuff.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	88/08/05  15:34:26	src
 * mproto(), segload(), and msetsys() functions simplified.
 * 
 * Revision 1.1	88/03/24  17:39:43	src
 * Initial revision
 * 
 * 88/03/10	Allan Cornish		/usr/src/sys/coh/proc.c
 * Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
 * These partial fixes will be removed once all CPU's are replaced.
 *
 * 88/02/13	Allan Cornish		/usr/src/sys/i8086/src/md1.c
 * segload() now checks for regl[OIP] being system code segment.
 * iAPX-286 protected mode interrupt gates enable interrupts momentarily.
 *
 * 88/01/21	Allan Cornish		/usr/src/sys/i8086/src/md1.c
 * Segments are now de-associated from processes before freeing the segment.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/i8086/src/md1.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/09/21	Allan Cornish	/usr/src/sys/i8086/src/md1.c
 * mproto() and setload() modified to support loadable driver processes.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/clist.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Calculate segmentation for a
 * new program. If there is a stack segment
 * present merge it into the data segment and
 * relocate the argument list.
 * Make sure that the changes are reflected in the u.u_segl array
 * which sproto sets up.
 */
mproto()
{
	register PROC	*pp;
	register SEG	*dsp;
	register SEG	*ssp;
	register SEG	*csp;
	fsize_t		ds;
	fsize_t		ss;
	unsigned int	so;
	unsigned int	*up;
	unsigned int	v;

	pp = SELF;

	dsp = pp->p_segp[SIPDATA];

	if ( ((pp->p_flags & PFKERN) == 0)
	  && ((ssp=pp->p_segp[SISTACK]) != NULL) ) {
		ds = dsp->s_size;
		ss = ssp->s_size;
		so = ds + ss;
		if (seggrow(dsp, (fsize_t)so) == 0)
			return (0);
		plrcopy( ssp->s_paddr, dsp->s_paddr + ds, ss);
		pp->p_segp[SISTACK] = NULL;
		sfree(ssp);
		u.u_sproto.mp_svb = ds;
		u.u_sproto.mp_svl = so;
		if (u.u_argp != NULL) {
			abase(FP_SEL(dsp->s_faddr));
			up = u.u_argp += so;
			--up;
			while (ageti(--up) != NULL)
				;
			up -= 2+u.u_argc;
			while ((v=ageti(up)) != NULL)
				aputi(up++, v+so);
			while ((v=ageti(++up)) != NULL)
				aputi(up, v+so);
		}
		return (sproto());	/* Recurse to fix u.u_segl */
	}

	/*
	 * Shared code, private code, or kernel code [csp == NULL].
	 * NOTE: Combined code/data no longer supported.
	 */
	if ( (csp = pp->p_segp[SISTEXT]) == NULL )
		csp = pp->p_segp[SIPTEXT];

	/*
	 * Special case if no code/data segment specified.
	 */
	u.u_sproto.mp_cbp = (csp != NULL) ? &FP_SEL(csp->s_faddr) : &scs;
	u.u_sproto.mp_dbp = (dsp != NULL) ? &FP_SEL(dsp->s_faddr) : &sds;
	u.u_sproto.mp_csl = (csp != NULL) ? csp->s_size - 1 : 0;
	u.u_sproto.mp_dsl = (dsp != NULL) ? dsp->s_size - 1 : 0;

	return (1);
}

/*
 * Load up segmentation registers.
 */
segload()
{
	register unsigned *ip;
	register unsigned s;

	ucs = *u.u_sproto.mp_cbp;
	uds = *u.u_sproto.mp_dbp;
	ucl =  u.u_sproto.mp_csl;
	udl =  u.u_sproto.mp_dsl;

	ip = regl;
	ip[OCS] = ucs;
	ip[ODS] = s = uds;
	ip[OES] = s;
	ip[OSS] = s;
}

/*
 * Set up a new process.
 */
msetusr(ip, sp)
vaddr_t sp;
vaddr_t ip;
{
	regl[OIP] = ip;
	regl[OSP] = sp + u.u_sproto.mp_svl;
}

/*
 * Set up initial context for a system process.
 * System processes run at depth 1, just like any
 * user process. This is necessary to make sure that
 * the machine state save is correctly handled, just
 * in case the clock hits a kernel process executing
 * out of the IBM ROM.
 */
msetsys(mp, fn, us)
register MCON *mp;
int (*fn)();
saddr_t us;
{
	mp->mc_sp = (int)(&u) + UPASIZE - 32;
	mp->mc_pc = fn;
	mp->mc_fw = 0;
	mp->mc_depth = 1;
}

/*
 * Set the given address in the user area to the given value if it is
 * okay to do so.
 */
msetuof(a, v)
register int a;
{
	if (a<UPASIZE+OBP*2 || a>UPASIZE+OFW*2)
		return (0);
	if (a == UPASIZE+OCS*2)
		return (0);
	if (a == UPASIZE+ODS*2)
		return (0);
	if (a == UPASIZE+OES*2)
		return (0);
	if (a == UPASIZE+OSS*2)
		return (0);
	if (a == UPASIZE+OID*2)		/* Protect trap id */
		return (0);
	if (a == UPASIZE+ORA*2)
		return (0);		/* Protect trap return link */
	*((int *)((int)&u+a)) = v;
	return (1);
}

/*
 * Cause a signal routine to be executed.
 */
msigint(n, f)
{
	register int *usp;

	usp = regl[OSP];
	putuwd(--usp, regl[OFW]);
	putuwd(--usp, regl[OIP]);
	putuwd(--usp, n);
	regl[OFW] &= ~MFTTB;
	regl[OIP] = f;
	regl[OSP] = usp;
	if (n != SIGTRAP)
		u.u_sfunc[n-1] = SIG_DFL;
}

/*
 * Cause the next instruction to single step.
 */
msigsin()
{
	regl[OFW] |= MFTTB;
}

/*
 * Fix up context.
 */
mfixcon(pp)
PROC *pp;
{
}

/*
 * Idle kernel process.
 */
idle()
{
	for (;;) {
		disflag = 1;
		_idle();
	}
}
@


1.1
log
@Initial revision
@
text
@d44 3
a46 3
#include <coherent.h>
#include <i8086.h>
#include <clist.h>
@
0707070064030104561004440000030000030000011777770507310724600005700000010120/newbits/kernel/USRSRC/i8086/src/RCS/mmain.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.40.23;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.36.58;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * 8086/8088 Coherent.
 * All machines.
 * Machine dependent stuff.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	88/08/05  15:43:42	src
 * Bug:	Spawning large number of processes would cause system to crash.
 * Fix:	Kernel alloc space no longer overlaps loadable driver data.
 * 
 * Revision 1.1	88/03/24  17:39:46	src
 * Initial revision
 * 
 * 88/02/24	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * corebot is now aligned on a 512 byte boundary.
 *
 * 87/11/30	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Check for kernel data space > 64 Kbytes now done AFTER rounding up.
 *
 * 87/11/21	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Use of bruc/ctob macros eliminated since no longer valid in protected mode.
 *
 * 87/11/14	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Init code+data now split into icodep/icodes and idatap/idatas.
 *
 * 87/11/12	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Corebot/coretop now paddr_t rather than saddr_t to support protected mode.
 *
 * 87/10/05	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Loadable driver data slot allocation added.
 *
 * 87/05/08	Allan Cornish		/usr/src/sys/i8086/src/mmain.c
 * Ctob(sds) is now cast as ctob((paddr_t)sds) to avoid address truncation.
 *
 * 86/07/23	Allan Cornish
 * Added check for kernel data space exceeding 64 Kbytes.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/clist.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>
#include <sys/buf.h>

saddr_t uasa;	/* Currently active uarea */

/*
 * General initialisation.
 */
i8086()
{
	register unsigned allocp;
	extern vaddr_t	aicodep;
	extern vaddr_t	aicodes;
	extern vaddr_t	aidatap;
	extern vaddr_t	aidatas;
	extern vaddr_t	etext;
	extern vaddr_t	end;
	auto faddr_t	fp;
	long datsize;
	unsigned bsize, csize, isize, ssize;

	/*
	 * Set up memory bases.
	 * Align the buffers modulo BSIZE (512) in the physical space,
	 * so that any machines that have only 16 bit DMA counters will
	 * work out.
	 */
	datsize = (long)&end;
	datsize += ALLSIZE;
	datsize += NBUF * sizeof(BUF);
	datsize += ssize = NSLOT*(sizeof(int) + slotsz);
	datsize += isize = NINODE*sizeof(INODE);
	datsize += csize = NCLIST*sizeof(CLIST);
	datsize += bsize = NBUF*BSIZE;
	datsize = (datsize + 511) & ~511;
	if ( datsize >= 0x10000L )
		panic("Kernel data exceeds 64 Kbytes");

	blockp  = datsize - bsize - ((sds&0x1F)<<4);
	clistp  = (unsigned)blockp - csize;
	inodep  = (unsigned)clistp - isize;
	slotp   = (unsigned)inodep - ssize;
	allocp = &end;
	blockp += (sds << 4L);
	if ((unsigned)allocp > (unsigned)slotp)
		panic("No alloc space");
	corebot = ((sds << 4L) + datsize + 511) & ~511;
	asize = (unsigned)slotp - allocp;
	msize = (coretop-holetop+holebot-corebot) / 1024;
	allkp = setarena(allocp, asize);
	icodep = (char *)&aicodep;
	icodes = (int)&aicodes;
	idatap = (char *)&aidatap;
	idatas = (int)&aidatas;
	fp = ptov( corebot, (fsize_t) UPASIZE );
	uasa   = FP_SEL(fp);
}

@


1.1
log
@Initial revision
@
text
@d52 3
a54 3
#include <coherent.h>
#include <i8086.h>
#include <clist.h>
d57 1
a57 1
#include <proc.h>
@
0707070064030104551004440000030000030000011777770507310724700005500000012700/newbits/kernel/USRSRC/i8086/src/RCS/tab.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.40.29;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.37.00;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Tables for the Intel 8086.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:50	src
 * Initial revision
 * 
 * 87/08/14	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added tick() as system call 73.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added alarm2() as system call 72.
 *
 * 86/11/21	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added msgctl(), msgget(), msgrcv(), msgsnd() as system calls 68 to 71.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added fcntl() and poll() as system calls 66 and 67.
 *
 * 85/07/09	Allan Cornish
 * Added getpgrp() as system call 63.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/systab.h>

/*
 * System call functions.
 */
int	unone();
int	unull();
int	uexit();
int	ufork();
int	uread();
int	uwrite();
int	uopen();
int	uclose();
int	uwait();
int	ucreat();
int	ulink();
int	uunlink();
int	uexece();
int	uchdir();
int	umknod();
int	uchmod();
int	uchown();
char	*ubrk();
int	ustat();
long	ulseek();
int	ugetpid();
int	umount();
int	uumount();
int	usetuid();
int	ugetuid();
int	ustime();
int	uptrace();
int	ualarm();
int	ufstat();
int	upause();
int	uutime();
int	ustty();
int	ugtty();
int	uaccess();
int	unice();
int	uftime();
int	uftime();
int	usync();
int	ukill();
int	udup();
int	upipe();
int	utimes();
int	uprofil();
long	uunique();
int	usetgid();
int	ugetgid();
int	(*usignal())();
int	usload();
int	usuload();
int	uacct();
int	ulock();
int	uioctl();
int	ugetegid();
int	uumask();
int	uchroot();
int	usetpgrp();
int	ugetpgrp();
int	ugeteuid();
int	ufcntl();
int	upoll();
long	ualarm2();
long	utick();

/*
 * System call table.
 */
struct systab sysitab[NMICALL] ={
	0,  INT,	unone,			/*  0 = ??? */
	2,  INT,	uexit,			/*  1 = exit */
	0,  INT,	ufork,			/*  2 = fork */
	6,  INT,	uread,			/*  3 = read */
	6,  INT,	uwrite,			/*  4 = write */
	4,  INT,	uopen,			/*  5 = open */
	2,  INT,	uclose,			/*  6 = close */
	2,  INT,	uwait,			/*  7 = wait */
	4,  INT,	ucreat,			/*  8 = creat */
	4,  INT,	ulink,			/*  9 = link */
	2,  INT,	uunlink,		/* 10 = unlink */
	6,  INT,	uexece,			/* 11 = exec */
	2,  INT,	uchdir,			/* 12 = chdir */
	0,  INT,	unone,			/* 13 = ??? */
	6,  INT,	umknod,			/* 14 = mknod */
	4,  INT,	uchmod,			/* 15 = chmod */
	6,  INT,	uchown,			/* 16 = chown */
	2,  INT,	ubrk,			/* 17 = break */
	4,  INT,	ustat,			/* 18 = stat */
	8,  LONG,	ulseek,			/* 19 = lseek */
	0,  INT,	ugetpid,		/* 20 = getpid */
	6,  INT,	umount,			/* 21 = mount */
	2,  INT,	uumount,		/* 22 = umount */
	2,  INT,	usetuid,		/* 23 = setuid */
	0,  INT,	ugetuid,		/* 24 = getuid */
	2,  INT,	ustime,			/* 25 = stime */
	8,  INT,	uptrace,		/* 26 = ptrace */
	2,  INT,	ualarm,			/* 27 = alarm */
	4,  INT,	ufstat,			/* 28 = fstat */
	0,  INT,	upause,			/* 29 = pause */
	4,  INT,	uutime,			/* 30 = utime */
	0,  INT,	unone,			/* 31 = ??? */
	0,  INT,	unone,			/* 32 = ??? */
	4,  INT,	uaccess,		/* 33 = access */
	2,  INT,	unice,			/* 34 = nice */
	2,  INT,	uftime,			/* 35 = ftime */
	0,  INT,	usync,			/* 36 = sync */
	4,  INT,	ukill,			/* 37 = kill */
	0,  INT,	unone,			/* 38 = ??? */
	0,  INT,	unone,			/* 39 = ??? */
	0,  INT,	unone,			/* 40 = ??? */
	4,  INT,	udup,			/* 41 = dup */
	2,  INT,	upipe,			/* 42 = pipe */
	2,  INT,	utimes,			/* 43 = times */
	8,  INT,	uprofil,		/* 44 = profil */
	0,  LONG,	uunique,		/* 45 = unique */
	2,  INT,	usetgid,		/* 46 = setgid */
	0,  INT,	ugetgid,		/* 47 = getgid */
	4,  INT,	usignal,		/* 48 = signal */
	0,  INT,	unone,			/* 49 = ??? */
	0,  INT,	unone,			/* 50 = ??? */
	2,  INT,	uacct,			/* 51 = acct */
	0,  INT,	unull,			/* 52 = ??? (phys) */
	0,  INT,	ulock,			/* 53 = lock */
	6,  INT,	uioctl,			/* 54 = ioctl */
	0,  INT,	unone,			/* 55 = ??? (mpx) */
	0,  INT,	ugetegid,		/* 56 = getegid */
	0,  INT,	ugeteuid,		/* 57 = geteuid */
	0,  INT,	unone,			/* 58 = ??? */
	0,  INT,	unone,			/* 59 = ??? */
	2,  INT,	uumask,			/* 60 = umask */
	2,  INT,	uchroot,		/* 61 = chroot */
	0,  INT,	usetpgrp,		/* 62 = setpgrp */
	0,  INT,	ugetpgrp,		/* 63 = getpgrp */
	2,  INT,	usload,			/* 64 = sload */
	2,  INT,	usuload,		/* 65 = suload */
	6,  INT,	ufcntl,			/* 66 = fcntl */
	8,  INT,        upoll,			/* 67 = poll */
	0,  INT,	unone,			/* 68 (was 6, msgctl) */
	0,  INT,	unone,			/* 69 (was 6, msgget) */
	0,  INT,	unone,			/* 70 (was 12, msgrcv) */
	0,  INT,	unone,			/* 71 (was 8, msgsnd) */
	4,  LONG,	ualarm2,		/* 72 = alarm2 */
	0,  LONG,	utick			/* 73 = tick  */
};
@


1.1
log
@Initial revision
@
text
@d38 3
a40 3
#include <coherent.h>
#include <i8086.h>
#include <systab.h>
@
0707070064030104541004440000030000030000011777770507310725100005600000013351/newbits/kernel/USRSRC/i8086/src/RCS/trap.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.40.35;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.37.02;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Trap handler.
 * 8086/8088 Coherent, IBM PC.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:53	src
 * Initial revision
 * 
 * 88/03/06	Allan Cornish		/usr/src/sys/i8086/src/trap.c
 * Exception diagnostistics extended.
 *
 * 87/11/02	Allan Cornish		/usr/src/sys/i8086/src/trap.c
 * iAPX 286 exception traps added.
 */
#include <sys/coherent.h>
#include <sys/i8086.h>
#include <sys/systab.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

#ifndef	EBUG
#define	EBUG 1
#endif

/*
 * Trap handler.
 * The arguments are the registers,
 * saved on the stack by machine code. This call
 * is different from most C calls in that the registers
 * get copied back; if you change a "trap" parameter then
 * the machine register will be altered when the trap is
 * dismissed.
 */
trap(es, cx, dx, ax, bx, ds, usp, uss, id, ip, cs, fw)
unsigned es, cx, dx, ax, bx, ds, usp, uss, id, ip, cs, fw;
{
	register struct	systab	*stp;
	register int	syscall;
	register int	callnum;
	register int	sigcode;
	long		l;

	if ( (id >> 8) == SINMI )
		panic( "Parity error: cs=%x ip=%x\n", cs, ip );

	if (depth != 0) {
#if EBUG > 0
		faddr_t fp;
		FP_SEL(fp) = ax;  printf("ax "); vprint(fp);
		FP_SEL(fp) = cs;  printf("cs "); vprint(fp);
		FP_SEL(fp) = ds;  printf("ds "); vprint(fp);
		FP_SEL(fp) = es;  printf("es "); vprint(fp);
		FP_SEL(fp) = uss; printf("ss "); vprint(fp);
#endif
		panic("system trap: id=%x ip=%x ax=%x", id, ip, ax);
	}

	if ((SELF->p_flags&PFKERN) != 0) {
#if EBUG > 0
		faddr_t fp;
		FP_SEL(fp) = ax;  printf("ax "); vprint(fp);
		FP_SEL(fp) = cs;  printf("cs "); vprint(fp);
		FP_SEL(fp) = ds;  printf("ds "); vprint(fp);
		FP_SEL(fp) = es;  printf("es "); vprint(fp);
		FP_SEL(fp) = uss; printf("ss "); vprint(fp);
#endif
		panic("pid%d: kernel process trap: id=%x, ip=%x ax=%d",
			SELF->p_pid, id, ip, ax);
	}

	/*
	 * System call.
	 */
	if ( (id >> 8) == SISYS ) {
		u.u_error = 0;
		sigcode = 0;
		syscall = getuwi(ip-2);
		if (u.u_error != 0 || (syscall&0xFF) != 0xCD) {
			sigcode = SIGSYS;
			goto trapend;
		}
		callnum = (syscall>>8) & 0x7F;
		if (callnum >= NMICALL) {
			sigcode = SIGSYS;
			goto trapend;
		}
		stp = &sysitab[callnum];
		ukcopy(usp+2, u.u_args, stp->s_alen);
		if (u.u_error != 0) {
			sigcode = SIGSYS;
			goto trapend;
		}
		u.u_io.io_seg = IOUSR;
		if (envsave(&u.u_sigenv) != 0)
			u.u_error = EINTR;
		else if ( stp->s_alen <= (3 * sizeof(int)) ) {
			l = (*(long(*)())stp->s_func)(u.u_args[0],
						      u.u_args[1],
						      u.u_args[2] );
			ax = ((struct l *) &l)->l_lo;
			dx = ((struct l *) &l)->l_hi;
		}
		else {
			l = (*(long(*)())stp->s_func)(u.u_args[0],
						      u.u_args[1],
						      u.u_args[2],
						      u.u_args[3],
						      u.u_args[4],
						      u.u_args[5]);
			ax = ((struct l *) &l)->l_lo;
			dx = ((struct l *) &l)->l_hi;
		}
		if (u.u_error != 0) {
			ax = -1;
			dx = -1;
			putuwd(MUERR, u.u_error);
			if (u.u_error == EFAULT)
				sigcode = SIGSYS;
		}
	}

	/*
	 * Trap.
	 */
	else switch (id>>8) {

	case SIDIV:
		sigcode = SIGDIVE;
		break;

	case SISST:
		sigcode = SIGTRAP;
		break;

	case SIBPT:
		sigcode = SIGTRAP;
		break;

	case SIOVF:
		sigcode = SIGOVFL;
		break;

	case SIBND:
		/*
		 * Bound
		 */
		sigcode = SIGOVFL;
		break;

	case SIOP:
		/*
		 * Invalid opcode
		 */
		sigcode = SIGSEGV;
		break;

	case SIXNP:
		/*
		 * Processor extension not available
		 */
		sigcode = SIGSEGV;
		break;

	case SIDBL:
		/*
		 * Double exception
		 */
		panic("double exception: cs=%x ip=%x", cs, ip);
		sigcode = SIGSEGV;
		break;

	case SIXS:
		/*
		 * Processor extension segment overrun
		 */
		sigcode = SIGSEGV;
		break;

	case SITS:
		/*
		 * Invalid task state segment
		 */
		panic("invalid tss: cs=%x ip=%x", cs, ip);
		sigcode = SIGSEGV;
		break;

	case SINP:
		/*
		 * Segment not present
		 */
		sigcode = SIGSEGV;
		break;

	case SISS:
		/*
		 * Stack segment overrun/not present
		 */
		sigcode = SIGKILL;
		break;

	case SIGP:
		/*
		 * General protection.
		 */
		sigcode = SIGSEGV;
		break;

	default:
		panic("user trap: id=%x ip=%x\n", id, ip );
	}

trapend:
	if ( sigcode != 0 ) {
		if ( sigcode == SIGSEGV ) {
#if EBUG > 0
			faddr_t fp;
			FP_SEL(fp) = ax;  printf("\tax "); vprint(fp);
			FP_SEL(fp) = cs;  printf("\tcs "); vprint(fp);
			FP_SEL(fp) = ds;  printf("\tds "); vprint(fp);
			FP_SEL(fp) = es;  printf("\tes "); vprint(fp);
			FP_SEL(fp) = uss; printf("\tss "); vprint(fp);
			printf("user trap: SEGV id=%x ax=%x pid=%d\n",
				id, ax, SELF->p_pid );
			printf("\tip=%x sp=%x\n", ip, usp );

			/*
			 * Force core dump.
			 */
			u.u_sfunc[SIGSEGV] = SIG_DFL;
#endif
		}
		sendsig(sigcode, SELF);
	}
}
@


1.1
log
@Initial revision
@
text
@d29 3
a31 3
#include <coherent.h>
#include <i8086.h>
#include <systab.h>
d33 1
a33 1
#include <proc.h>
@
0707070064030104521004440000030000030000011777770507310725200006100000012415/newbits/kernel/USRSRC/i8086/src/RCS/tab.c.310,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.37.04;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Tables for the Intel 8086.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  17:39:50	src
 * Initial revision
 * 
 * 87/08/14	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added tick() as system call 73.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added alarm2() as system call 72.
 *
 * 86/11/21	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added msgctl(), msgget(), msgrcv(), msgsnd() as system calls 68 to 71.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/i8086/src/tab.c
 * Added fcntl() and poll() as system calls 66 and 67.
 *
 * 85/07/09	Allan Cornish
 * Added getpgrp() as system call 63.
 */
#include <coherent.h>
#include <i8086.h>
#include <systab.h>

/*
 * System call functions.
 */
int	unone();
int	unull();
int	uexit();
int	ufork();
int	uread();
int	uwrite();
int	uopen();
int	uclose();
int	uwait();
int	ucreat();
int	ulink();
int	uunlink();
int	uexece();
int	uchdir();
int	umknod();
int	uchmod();
int	uchown();
char	*ubrk();
int	ustat();
long	ulseek();
int	ugetpid();
int	umount();
int	uumount();
int	usetuid();
int	ugetuid();
int	ustime();
int	uptrace();
int	ualarm();
int	ufstat();
int	upause();
int	uutime();
int	ustty();
int	ugtty();
int	uaccess();
int	unice();
int	uftime();
int	uftime();
int	usync();
int	ukill();
int	udup();
int	upipe();
int	utimes();
int	uprofil();
long	uunique();
int	usetgid();
int	ugetgid();
int	(*usignal())();
int	usload();
int	usuload();
int	uacct();
int	ulock();
int	uioctl();
int	ugetegid();
int	uumask();
int	uchroot();
int	usetpgrp();
int	ugetpgrp();
int	ugeteuid();
int	ufcntl();
int	upoll();
int	umsgctl();
int	umsgget();
int	umsgrcv();
int	umsgsnd();
long	ualarm2();
long	utick();

/*
 * System call table.
 */
struct systab sysitab[NMICALL] ={
	0,  INT,	unone,			/*  0 = ??? */
	2,  INT,	uexit,			/*  1 = exit */
	0,  INT,	ufork,			/*  2 = fork */
	6,  INT,	uread,			/*  3 = read */
	6,  INT,	uwrite,			/*  4 = write */
	4,  INT,	uopen,			/*  5 = open */
	2,  INT,	uclose,			/*  6 = close */
	2,  INT,	uwait,			/*  7 = wait */
	4,  INT,	ucreat,			/*  8 = creat */
	4,  INT,	ulink,			/*  9 = link */
	2,  INT,	uunlink,		/* 10 = unlink */
	6,  INT,	uexece,			/* 11 = exec */
	2,  INT,	uchdir,			/* 12 = chdir */
	0,  INT,	unone,			/* 13 = ??? */
	6,  INT,	umknod,			/* 14 = mknod */
	4,  INT,	uchmod,			/* 15 = chmod */
	6,  INT,	uchown,			/* 16 = chown */
	2,  INT,	ubrk,			/* 17 = break */
	4,  INT,	ustat,			/* 18 = stat */
	8,  LONG,	ulseek,			/* 19 = lseek */
	0,  INT,	ugetpid,		/* 20 = getpid */
	6,  INT,	umount,			/* 21 = mount */
	2,  INT,	uumount,		/* 22 = umount */
	2,  INT,	usetuid,		/* 23 = setuid */
	0,  INT,	ugetuid,		/* 24 = getuid */
	2,  INT,	ustime,			/* 25 = stime */
	8,  INT,	uptrace,		/* 26 = ptrace */
	2,  INT,	ualarm,			/* 27 = alarm */
	4,  INT,	ufstat,			/* 28 = fstat */
	0,  INT,	upause,			/* 29 = pause */
	4,  INT,	uutime,			/* 30 = utime */
	0,  INT,	unone,			/* 31 = ??? */
	0,  INT,	unone,			/* 32 = ??? */
	4,  INT,	uaccess,		/* 33 = access */
	2,  INT,	unice,			/* 34 = nice */
	2,  INT,	uftime,			/* 35 = ftime */
	0,  INT,	usync,			/* 36 = sync */
	4,  INT,	ukill,			/* 37 = kill */
	0,  INT,	unone,			/* 38 = ??? */
	0,  INT,	unone,			/* 39 = ??? */
	0,  INT,	unone,			/* 40 = ??? */
	4,  INT,	udup,			/* 41 = dup */
	2,  INT,	upipe,			/* 42 = pipe */
	2,  INT,	utimes,			/* 43 = times */
	8,  INT,	uprofil,		/* 44 = profil */
	0,  LONG,	uunique,		/* 45 = unique */
	2,  INT,	usetgid,		/* 46 = setgid */
	0,  INT,	ugetgid,		/* 47 = getgid */
	4,  INT,	usignal,		/* 48 = signal */
	0,  INT,	unone,			/* 49 = ??? */
	0,  INT,	unone,			/* 50 = ??? */
	2,  INT,	uacct,			/* 51 = acct */
	0,  INT,	unull,			/* 52 = ??? (phys) */
	0,  INT,	ulock,			/* 53 = lock */
	6,  INT,	uioctl,			/* 54 = ioctl */
	0,  INT,	unone,			/* 55 = ??? (mpx) */
	0,  INT,	ugetegid,		/* 56 = getegid */
	0,  INT,	ugeteuid,		/* 57 = geteuid */
	0,  INT,	unone,			/* 58 = ??? */
	0,  INT,	unone,			/* 59 = ??? */
	2,  INT,	uumask,			/* 60 = umask */
	2,  INT,	uchroot,		/* 61 = chroot */
	0,  INT,	usetpgrp,		/* 62 = setpgrp */
	0,  INT,	ugetpgrp,		/* 63 = getpgrp */
	2,  INT,	usload,			/* 64 = sload */
	2,  INT,	usuload,		/* 65 = suload */
	6,  INT,	ufcntl,			/* 66 = fcntl */
	8,  INT,        upoll,			/* 67 = poll */
	6,  INT,	umsgctl,		/* 68 = msgctl */
	6,  INT,	umsgget,		/* 69 = msgget */
	12, INT,	umsgrcv,		/* 70 = msgrcv */
	8,  INT,	umsgsnd,		/* 71 = msgsnd */
	4,  LONG,	ualarm2,		/* 72 = alarm2 */
	0,  LONG,	utick			/* 73 = tick  */
};
@
0707070064030112060407550000030000030000011777770507310725400005100000000000/newbits/kernel/USRSRC/i8086/src/objects0707070064030112040407550000000000000000011777770507310725400004500000000000/newbits/kernel/USRSRC/i8086/objects0707070064030147540407550000030000030000011777770507310725400003300000000000/newbits/kernel/USRSRC/coh0707070064030110751006440000030000030000011777770507310725400004300000004473/newbits/kernel/USRSRC/coh/alloc.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Storage allocator.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:48:16  bin
 * initial version prov by hal
 * 
 * Revision 1.1	88/03/24  16:13:25	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/alloc.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/uproc.h>

/*
 * Create an arena.
 */
ALL *
setarena(cp, n)
register char *cp;
{
	register ALL *ap1;
	register ALL *ap2;

	if ((char *)(ap1=align(cp)) < (char *)cp)
		ap1++;
	if ((ap2=align(&cp[n])-1) < ap1)
		panic("Arena %o too small", (int) cp);
	ap1->a_link = (char *)ap2;
	ap2->a_link = (char *)ap1;
	setused(ap2);
	return (ap1);
}

/*
 * Allocate `l' bytes of memory.
 */
char *
alloc(apq, l)
ALL *apq;
unsigned l;
{
	register ALL *ap;
	register ALL *ap1;
	register ALL *ap2;
	register unsigned i;
	register unsigned n;
	register unsigned s;

	n = 1 + (l + sizeof(ALL) - 1) / sizeof(ALL);
	for (i=0; i<2; i++) {
		for (ap1=apq; link(ap1)!=apq; ap1=link(ap1)) {
			if (ap1 == NULL)
				panic("Corrupt arena");
			if (tstfree(ap1)) {
			       for (ap2=link(ap1); tstfree(ap2); ap2=link(ap2))
					if (ap2 == apq)
						break;
				ap1->a_link = (char *)ap2;
				if ((s=ap2-ap1) >= n) {
					if (s > n) {
						if (i == 0)
							continue;
						ap = &ap1[n];
						ap->a_link = (char *)ap2;
						ap1->a_link = (char *)ap;
					}
					setused(ap1);
					kclear((char *)ap1->a_data, l);
					return (ap1->a_data);
				}
			}
		}
	}
	u.u_error = EKSPACE;
	return (NULL);
}

/*
 * Free memory.
 */
free(cp)
char *cp;
{
	register ALL *ap;
	extern char end;

	ap = ((ALL *)cp) - 1;
	if (ap<(ALL *)&end || tstfree(ap))
		panic("Bad free %o\n", (unsigned)cp);
	setfree(ap);
}
0707070064030110741006440000030000030000011777770507310725400004100000031655/newbits/kernel/USRSRC/coh/bio.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Buffered I/O.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:49:45  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:13:29	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/bio.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/bio.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/bio.c
 * ioreq() now only wakes &stimer if the swap timer is active.
 *
 * 86/12/12	Allan Cornish		/usr/src/sys/coh/bio.c
 * Added 3rd arg to dpoll() to specify blocking poll if non-zero.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/bio.c
 * Added dpoll() routine to perform device polls [System V.3 compatible].
 *
 * 86/07/24	Allan Cornish		/usr/src/sys/coh/bio.c
 * Added check in devinit() for null dp->d_conp->c_load function pointer.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Initialise buffer headers.
 */
bufinit()
{
	register BUF *bp;
	faddr_t f;
	paddr_t p;

	FP_SEL(f) = sds;
	FP_OFF(f) = 0;
	p = blockp;
	FP_OFF(f) = blockp - vtop(f);

	bufl = kalloc(NBUF * sizeof(BUF));
	if (bufl == NULL)
		panic("bufinit: no space for BUF's");

	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		bp->b_dev = NODEV;
		bp->b_faddr = f;
		bp->b_paddr = p;
		FP_OFF(f) += BSIZE;
		p += BSIZE;
	}
}

/*
 * Synchronise the buffer cache.
 */
bsync()
{
	register BUF *bp;

	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		if ((bp->b_flag&BFMOD) == 0)
			continue;
		lock(bp->b_gate);
		if ((bp->b_flag&BFMOD) != 0)
			bwrite(bp, 1);
		unlock(bp->b_gate);
	}
}

/*
 * Synchronise all block for a particular device in the buffer cache
 * and invalidate all references.
 */
bflush(dev)
register dev_t dev;
{
	register BUF *bp;

	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		if (bp->b_dev != dev)
			continue;
		lock(bp->b_gate);
		if (bp->b_dev == dev) {
			if ((bp->b_flag&BFMOD) != 0)
				bwrite(bp, 1);
			bp->b_dev = NODEV;
		}
		unlock(bp->b_gate);
	}
}

/*
 * Return a buffer containing the given block from the given device.
 * If `f' is not set, the read is asynchronous and no buffer is returned.
 */
BUF *
bread(dev, bno, f)
dev_t dev;
daddr_t bno;
register int f;
{
	register BUF *bp;
	register int s;

	bp = bclaim(dev, bno);
	if ((bp->b_flag&BFNTP) != 0) {
		if (f != 0)
			bp->b_flag &= ~BFASY;
		else {
			bp->b_flag |= BFASY;
			bumap(bp);
		}
		bp->b_req = BREAD;
		bp->b_count = BSIZE;
		s = sphi();
		dblock(dev, bp);
		if (f == 0) {
			spl(s);
			return (NULL);
		}
		while ((bp->b_flag&BFNTP) != 0)
			sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
		spl(s);
		if ((bp->b_flag&BFERR) != 0) {
			u.u_error = bp->b_err ? bp->b_err : EIO;
			brelease(bp);
			return (NULL);
		}
		if (bp->b_resid == BSIZE) {
			brelease(bp);
			return (NULL);
		}
	}
	if (f == 0) {
		brelease(bp);
		return (NULL);
	}
	u.u_block++;
	return (bp);
}

/*
 * If the requested buffer is in the buffer cache, return a pointer to
 * it.  If not, pick an empty buffer, set it up and return it.
 */
BUF *
bclaim(dev, bno)
dev_t dev;
daddr_t bno;
{
	register BUF *bp;
	register BUF *bp1;
	register unsigned seqn;
	register int s;

again:
	bp1 = NULL;
	seqn = 0;
	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		if (bp->b_bno == bno  &&  bp->b_dev == dev) {
			lock(bp->b_gate);
			if (bp->b_bno != bno  ||  bp->b_dev != dev) {
				unlock(bp->b_gate);
				goto again;
			}
			if ((bp->b_flag&BFERR) != 0)
				bp->b_flag |= BFNTP;
			bsmap(bp);
			return (bp);
		}
		if (locked(bp->b_gate) == 0) {
			if (bufseqn-bp->b_seqn >= seqn) {
				bp1 = bp;
				seqn = bufseqn - bp->b_seqn;
			}
		}
	}
	if (bp1 == NULL) {
		s = sphi();
		for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
			if (locked(bp->b_gate) == 0) {
				if (bufseqn-bp->b_seqn >= seqn) {
					bp1 = bp;
					seqn = bufseqn - bp->b_seqn;
				}
			}
		}
		if (bp1 == NULL) {
			bufneed = 1;
			sleep((char *)&bufneed, CVBLKIO, IVBLKIO, SVBLKIO);
			spl(s);
			goto again;
		}
		spl(s);
	}
	bp = bp1;
	lock(bp->b_gate);
	if ((bp->b_flag&BFMOD) != 0) {
		bwrite(bp, 0);
		goto again;
	}
	bp->b_flag = BFNTP;
	bp->b_dev = dev;
	bp->b_bno = bno;
	bsmap(bp);
	return (bp);
}

/*
 * Write the given buffer out.  If `f' is set, the write is synchronous,
 * otherwise asynchronous.  This routine must be called with the buffer
 * gate locked.
 */
bwrite(bp, f)
register BUF *bp;
{
	register int s;

	if (f != 0)
		bp->b_flag &= ~BFASY;
	else {
		bp->b_flag |= BFASY;
		bumap(bp);
	}
	bp->b_flag |= BFNTP;
	bp->b_req = BWRITE;
	bp->b_count = BSIZE;
	s = sphi();
	dblock(bp->b_dev, bp);
	if (f == 0) {
		spl(s);
		return;
	}
	while ((bp->b_flag&BFNTP) != 0)
		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
	spl(s);
}

/*
 * This is called by the driver when I/O has completed on a buffer.
 */
bdone(bp)
register BUF *bp;
{
	if (bp->b_req == BWRITE)
		bp->b_flag &= ~BFMOD;
	if (bp->b_req == BREAD) {
		if ((bp->b_flag&BFERR) != 0)
			bp->b_dev = NODEV;
	}
	if ((bp->b_flag&BFASY) != 0) {
		bp->b_flag &= ~BFASY;
		brelease(bp);
	}
	bp->b_flag &= ~BFNTP;
	wakeup((char *)bp);
}

/*
 * Release the given buffer.
 */
brelease(bp)
register BUF *bp;
{
	if ((bp->b_flag&BFERR) == 0)
		bp->b_seqn = bufseqn++;
	else {
		bp->b_flag &= ~BFERR;
		bp->b_dev = NODEV;
	}
	bp->b_flag &= ~BFNTP;
	bumap(bp);
	unlock(bp->b_gate);
	if (bufneed != 0) {
		bufneed = 0;
		wakeup((char *)&bufneed);
	}
}

/*
 * Map the given buffer.
 */
bsmap(bp)
register BUF *bp;
{
	bsave(bp->b_map);
	bp->b_flag |= BFMAP;
	bmapv(bconv(bp->b_paddr));
}

/*
 * Unmap the given buffer.
 */
bumap(bp)
register BUF *bp;
{
	if ((bp->b_flag&BFMAP) == 0)
		return;
	bp->b_flag &= ~BFMAP;
	brest(bp->b_map);
}

/*
 * Read data from the I/O segment into kernel space.
 */
ioread(iop, v, n)
register IO *iop;
register char *v;
register unsigned n;
{
	switch (iop->io_seg) {
	case IOSYS:
		iop->io_base += kkcopy(iop->io_base, v, n);
		break;
	case IOUSR:
		iop->io_base += ukcopy(iop->io_base, v, n);
		break;
	case IOPHY:
		iop->io_phys += pkcopy(iop->io_phys, v, n);
		break;
	}
	iop->io_ioc -= n;
}

/*
 * Write data from kernel space to the I/O segment.
 */
iowrite(iop, v, n)
register IO *iop;
register char *v;
register unsigned n;
{
	switch (iop->io_seg) {
	case IOSYS:
		iop->io_base += kkcopy(v, iop->io_base, n);
		break;
	case IOUSR:
		iop->io_base += kucopy(v, iop->io_base, n);
		break;
	case IOPHY:
		iop->io_phys += kpcopy(v, iop->io_phys, n);
		break;
	}
	iop->io_ioc -= n;
}

/*
 * Get a character from the I/O segment.
 */
iogetc(iop)
register IO *iop;
{
	register int c;

	if (iop->io_ioc == 0)
		return (-1);
	--iop->io_ioc;
	if (iop->io_seg == IOSYS)
		c = *iop->io_base++ & 0377;
	else {
		c = getubd(iop->io_base++);
		if (u.u_error)
			return (-1);
	}
	return (c);
}

/*
 * Put a character using the I/O segment.
 */
ioputc(c, iop)
register IO *iop;
{
	if (iop->io_ioc == 0)
		return (-1);
	--iop->io_ioc;
	if (iop->io_seg == IOSYS)
		*iop->io_base++ = c;
	else {
		putubd(iop->io_base++, c);
		if (u.u_error)
			return (-1);
	}
	return (c);
}

/*
 * Given a buffer pointer, an I/O structure, a device, request type, and
 * a flags word, check the I/O structure and perform the I/O request.
 */
ioreq(bp, iop, dev, req, f)
register BUF *bp;
register IO *iop;
dev_t dev;
{
	register SEG *sp;
	register int n;
	register int s;
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	lock(bp->b_gate);
	n = cp->c_flag;	/* n should do something with that flag */
	drest(dold);
	sp = NULL;
	if (iop != NULL) {
		if ((f&BFBLK) != 0) {
			if (blocko(iop->io_seek) != 0) {
				u.u_error = EIO;
				goto out;
			}
		}
		if ((f&BFIOC) != 0) {
			if ((sp=iomapvp(iop, bp)) == NULL) {
				u.u_error = EIO;
				goto out;
			}
		}
	}
	bp->b_flag = f|BFNTP;
	bp->b_req = req;
	bp->b_dev = dev;
	if (iop != NULL) {
		bp->b_bno = blockn(iop->io_seek);
		bp->b_count = iop->io_ioc;
	}
	if (sp != NULL) {
		bp->b_faddr = ptov( bp->b_paddr, (fsize_t) bp->b_count );
		sp->s_lrefc++;
	}
	s = sphi();
	dblock(dev, bp);
	while ((bp->b_flag&BFNTP) != 0)
		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
	spl(s);
	if (sp != NULL) {
		vrelse( bp->b_faddr );
		sp->s_lrefc--;
	}
	if (stimer.t_last != 0)
		wakeup((char *)&stimer);
	if ((bp->b_flag&BFERR) != 0) {
		u.u_error = bp->b_err ? bp->b_err : EIO;
		goto out;
	}
	if (iop != NULL) {
		n = iop->io_ioc - bp->b_resid;
		iop->io_seek += n;
		iop->io_ioc -= n;
	}
out:
	unlock(bp->b_gate);
}

/*
 * Given an I/O structure and a buffer header, see if the addresses
 * in the I/O structure are valid and set up the buffer header.
 */
SEG *
iomapvp(iop, bp)
register IO *iop;
register BUF *bp;
{
	register SR *srp;
	register SEG *sp;
	register vaddr_t b;

	if (iop->io_seg != IOUSR)
		panic("Raw I/O from non user");
	for (srp=u.u_segl; srp<&u.u_segl[NUSEG]; srp++) {
		if ((sp=srp->sr_segp) == NULL)
			continue;
		if ((srp->sr_flag&SRFDATA) == 0)
			continue;
/* Yet another bug in the 8000 C compiler
		if ((long)(b=iop->io_base) < (long)srp->sr_base)
*/
		if ((b=iop->io_base) < srp->sr_base)
			continue;
		if ((long)b+iop->io_ioc > (long)srp->sr_base + sp->s_size)
			continue;
		bp->b_paddr = sp->s_paddr + (vaddr_t) (b - srp->sr_base);
		return (sp);
	}
	return (NULL);
}

/*
 * Initialise devices.
 */
devinit()
{
	register DRV *dp;
	register int mind;

	for ( dp = drvl, mind = 0; mind < drvn; mind++, dp++ ) {
		if ((dp->d_conp != NULL) && (dp->d_conp->c_load != NULL)) {
			(*dp->d_conp->c_load)();
		}
	}
}

/*
 * Open a device.
 */
dopen(dev, m, f)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	if ((cp->c_flag&f) == 0) {
		u.u_error = ENXIO;
		return;
	}
	(*cp->c_open)(dev, m);
	drest(dold);
}

/*
 * Close a device.
 */
dclose(dev)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_close)(dev);
	drest(dold);
}

/*
 * Call the block entry point of a device.
 */
dblock(dev, bp)
dev_t dev;
BUF *bp;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_block)(bp);
	drest(dold);
}

/*
 * Read from a device.
 */
dread(dev, iop)
register dev_t dev;
register IO *iop;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_read)(dev, iop);
	drest(dold);
}

/*
 * Write to a device.
 */
dwrite(dev, iop)
register dev_t dev;
register IO *iop;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_write)(dev, iop);
	drest(dold);
}

/*
 * Call the ioctl function for a device.
 */
dioctl(dev, com, vec)
register dev_t dev;
union ioctl *vec;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_ioctl)(dev, com, vec);
	drest(dold);
}

/*
 * Call the powerfail entry point of a device.
 */
dpower(dev)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_power)(dev);
	drest(dold);
}

/*
 * Call the timeout entry point of a device.
 */
dtime(dev)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_timer)(dev);
	drest(dold);
}

/*
 * Poll a device.
 */
dpoll(dev, ev, msec)
register dev_t dev;
int ev;
int msec;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return POLLNVAL;

	if ( cp->c_flag & DFPOL )
		ev = (*cp->c_poll)(dev, ev, msec);
	else
		ev = POLLNVAL;

	drest(dold);
	return ev;
}

/*
 * Given a device, return the flags word.
 */
dflag(dev)
dev_t dev;
{
	register CON *cp;
	register int f;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return (DFERR);
	f = cp->c_flag;
	drest(dold);
	return (f);
}

/*
 * Given a device, and a pointer to a driver map save area, save the
 * current map in the driver map save area and map in the new device,
 * returning a pointer to the configuration entry for that device.
 */
CON *
drvmap(dev, doldp)
dev_t dev;
dold_t *doldp;
{
	register DRV *dp;
	register unsigned m;

	if ((m=major(dev)) >= drvn) {
		u.u_error = ENXIO;
		return (NULL);
	}
	dp = &drvl[m];
	if (locked(dp->d_gate)) {
		u.u_error = ENXIO;
		return (NULL);
	}
	if (dp->d_conp == NULL) {
		u.u_error = ENXIO;
		return (NULL);
	}
	dsave(*doldp);
	if (dp->d_map != 0)
		dmapv(dp->d_map);
	return (dp->d_conp);
}

/*
 * Non existant device.
 */
nonedev()
{
	u.u_error = ENXIO;
}

/*
 * Null device.
 */
nulldev()
{
}
0707070064030103071006440000030000030000011777770507310725700004300000005623/newbits/kernel/USRSRC/coh/clist.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Character list management.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:50:03  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:13:33	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <clist.h>
#include <sched.h>

/*
 * Initialise character list queues.
 */
cltinit()
{
	register cmap_t cm;
	register cmap_t lm;
	register paddr_t p;
	register int s;
	cold_t om;

	s = sphi();
	csave(om);
	lm = 0;
	for (p = clistp+NCLIST*sizeof(CLIST); (p-=sizeof(CLIST)) >= clistp; ) {
		cm = cconv(p);
		cmapv(cm);
		cvirt(cm)->cl_fp = lm;
		lm = cm;
	}
	cltfree = lm;
	crest(om);
	spl(s);
}

/*
 * Get a character from the given queue.
 */
getq(cqp)
register CQUEUE *cqp;
{
	register cmap_t op;
	register cmap_t np;
	register int ox;
	register int c;
	register int s;
	cold_t om;

	if (cqp->cq_cc == 0)
		return (-1);
	s = sphi();
	op = cqp->cq_op;
	ox = cqp->cq_ox;
	csave(om);
	cmapv(op);
	c = cvirt(op)->cl_ch[ox]&0377;
	crest(om);
	if (--cqp->cq_cc==0 || ++cqp->cq_ox==NCPCL) {
		cqp->cq_ox = 0;
		cmapv(op);
		np = cvirt(op)->cl_fp;
		cvirt(op)->cl_fp = cltfree;
		crest(om);
		cqp->cq_op = np;
		cltfree = op;
		if (np == 0) {
			cqp->cq_ip = 0;
			cqp->cq_ix = 0;
		}
		if (cltwant) {
			cltwant = 0;
			wakeup((char *)&cltwant);
		}
	}
	spl(s);
	return (c);
}

/*
 * Put a character on the given queue.
 */
putq(cqp, c)
register CQUEUE *cqp;
{
	register cmap_t ip;
	register int ix;
	register int s;
	register cmap_t np;
	cold_t om;

	s = sphi();
	ip = cqp->cq_ip;
	csave(om);
	if ((ix=cqp->cq_ix) == 0) {
		if ((ip=cltfree) == 0) {
			spl(s);
			return (-1);
		}
		cmapv(ip);
		cltfree = cvirt(ip)->cl_fp;
		cvirt(ip)->cl_fp = 0;
		crest(om);
		if ((np=cqp->cq_ip) == 0)
			cqp->cq_op = ip;
		else {
			cmapv(np);
			cvirt(np)->cl_fp = ip;
			crest(om);
		}
		cqp->cq_ip = ip;
	}
	cmapv(ip);
	cvirt(ip)->cl_ch[ix] = c;
	crest(om);
	if (++cqp->cq_ix == NCPCL)
		cqp->cq_ix = 0;
	cqp->cq_cc++;
	spl(s);
	return (c);
}

/*
 * Clear a character queue.
 */
clrq(cqp)
register CQUEUE *cqp;
{
	register int s;

	s = sphi();
	while (getq(cqp) >= 0)
		;
	spl(s);
}

/*
 * Wait for more character queues to become available.
 */
waitq()
{
	while (cltfree == 0) {
		cltwant = 1;
		sleep((char *)&cltwant, CVCLIST, IVCLIST, SVCLIST);
	}
}
0707070064030147511006440000030000030000011777770507310726000004300000014376/newbits/kernel/USRSRC/coh/clock.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Clock.
 * The clock comes in two parts.  There is the routine `clock' which
 * gets called every tick at high priority.  It does the minimum it
 * can and returns as soon as possible.  The second routine, `stand',
 * gets called whenever we are about to return from an interrupt to
 * user mode a low priority.  It can look at flags that the clock set
 * and do the things the clock really wanted to do but didn't have time.
 * Stand is truly the kernel of the system.
 *
 * 90/08/13	Hal Snyder		/usr/src/sys/coh/clock.c
 * Add external altclk to allow polled device drivers.
 * (extern'ed in coherent.h)
 * 
 * 87/10/26	Allan cornish		/usr/src/sys/coh/clock.c
 * Timed functions are now invoked with TIM * tp as second argument.
 * This facilitates the use of timed functions within loadable drivers.
 *
 * 87/07/07	Allan Cornish		/usr/src/sys/coh/clock.c
 * Clocks static variable added - incremented by clock, decremented by stand().
 * Lbolt variable added - clock ticks since startup - incremented by stand().
 * Support for multiple timing queues ported from RTX.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/clock.c
 * stand() now only wakes &stimer if swap timer is active.
 *
 * 86/11/24	Allan Cornish		/usr/src/sys/coh/clock.c
 * Added support for new t_last field in tim struct.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/clock.c
 * Stand() calls defend() to execute functions deferred from interrupt level.
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <sys/timeout.h>
#include <sys/uproc.h>
#include <sys/mdata.h>

int (*altclk)();	/* pointer to higher-speed clock function */
int altsel;	/* if nonzero, CS for LOADABLE driver owning altclk() */

static int clocks;

/*
 * This routine is called once every tick (1/HZ seconds).
 * It gets called with the programme counter that was interrupted
 * a flag telling whether we were in user or kernel mode and the
 * previous priority we were in.
 */
clock(pc, umode)
vaddr_t pc;
{
	register PROC *pp;
	/*
	 * Ignore clock interrupts till we are ready.
	 */
	if (batflag == 0)
		return;

	/*
	 * Hook for alternate clock interrupt;
	 * Call polling function ("altclk") if there is one.
	 *
	 * For near function, "altsel" is 0 and "altclk" is offset.
	 * For far function, "altsel" is the CS selector and "altclk"
	 * is the offset.
	 *
	 * Since the polling function ends with a near rather than
	 * far return, far invocation is via ld_call() (ldas.s) which uses
	 * the despatch routine at CS:4 (ld.s) in any loadable driver.
	 */
	if (altclk) {
		if (altsel) {	/* will do far call to altclk fn */
			if (ld_call(altsel, altclk))
				return;
		} else
			if ((*altclk)())
				return;
	}

	/*
	 * Update timers.  Decrement time slice.
	 */
	utimer += 1;
	clocks += 1;
	timer.t_tick += 1;
	quantum -= 1;

	/*
	 * Give processes their schedule values per tick.
	 */
	if (procq.p_lforw->p_cval > CVCLOCK) {
		procq.p_lforw->p_cval -= CVCLOCK;
		procq.p_cval += CVCLOCK;
	}

	/*
	 * Tax current process and update his times.
	 */
	pp = SELF;
	pp->p_cval >>= 1;
	if (umode == 0)
		pp->p_stime++;
	else {
		pp->p_utime++;
		u.u_ppc = pc;
	}
}

/*
 * Do everything the clock wanted to do but couldn't as it would have
 * taken too long.
 * Also perform any system bookkeeping required at regular intervals.
 */
stand()
{
	int s;

	u.u_error = 0;

	/*
	 * Update the clock.
	 */
	while (timer.t_tick >= HZ) {
		timer.t_time++;
		timer.t_tick -= HZ;
		outflag = 1;
	}

	/*
	 * Check expiration of quantum.
	 */
	if (quantum <= 0) {
		quantum = 0;
		disflag = 1;
	}

	/*
	 * Check the timed function queue if necessary.
	 */
	if ( clocks > 0 )
	do {
		register TIM * np;
		register TIM * tp;

		/*
		 * Update [serviced] clock ticks since startup.
		 */
		lbolt++;

		/*
		 * Remove timing list from queue, creating new temporary queue.
		 */
		tp = (TIM *) &timq[ lbolt % nel(timq) ];
		s  = sphi();

		/*
		 * Scan timing list.
		 */
		for ( np = tp->t_next; tp = np; ) {

			/*
			 * Remember next function in timing list.
			 * NOTE: Must be done before function is invoked,
			 *	 since it may start a new timer.
			 */
			np = tp->t_next;

			/*
			 * Function has not timed out: leave it on timing list.
			 */
			if ( tp->t_lbolt != lbolt )
				continue;

			/*
			 * Remove function from timing list.
			 */
			if ( tp->t_last->t_next = tp->t_next )
				tp->t_next->t_last = tp->t_last;
			tp->t_last = NULL;

			/*
			 * Invoke function.
			 */
			spl(s);
			(*tp->t_func)( tp->t_farg, tp );
			sphi();
		}

		spl( s );

	} while ( --clocks > 0 );

	/*
	 * Timeout any devices.
	 */
	if (outflag) {
		register int n;

		outflag = 0;
		for (n=0; n<drvn; n++) {
			if (drvl[n].d_time == 0)
				continue;
			s = sphi();
			dtime((dev_t)makedev(n, 0));
			spl(s);
		}
	}

	/*
	 * Do profiling.
	 */
	if (u.u_pscale != 0) {
		register unsigned p;
		register vaddr_t a;

		p = u.u_pscale;
		a = (int *)u.u_pbase +
		    pscale(u.u_ppc-u.u_pofft, p/sizeof (int));
		if (a < u.u_pbend)
			putuwd(a, getuwd(a)+1);
	}

	/*
	 * Check for signals and execute them.
	 */
	if (SELF->p_ssig)
		actvsig();

	/*
	 * Execute deferred functions.
	 */
	defend();

	/*
	 * Should we dispatch?
	 */
	if ((SELF->p_flags&PFDISP) != 0) {
		SELF->p_flags &= ~PFDISP;
		disflag = 1;
		if ( stimer.t_last != 0 )
			wakeup((char *)&stimer);
	}

#ifdef QWAKEUP
	/*
	 * Dispatch pending wakeups.
	 */
	while (ntowake)
		wakeup2();

#endif
	/*
	 * Redispatch.
	 * This used to be a function call in tsave,
	 * expanded in line here.
	 */
	if (disflag) {
		register PROC *pp;

#ifndef QWAKEUP
		s=sphi();
#endif
		if ((pp=SELF)!=iprocp)
			setrun(pp);
		dispatch();
#ifndef QWAKEUP
		spl(s);
#endif
	}
}
0707070064030110731006440000030000030000011777770507310726200004200000031434/newbits/kernel/USRSRC/coh/exec.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Exec and driver load code.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:50:20  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:13:39	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/exec.c
 * Exsread() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <l.out.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Sizes.
 */
#define	sh	((fsize_t)sizeof(struct ldheader))
#define si	lssize[L_SHRI]
#define pi	lssize[L_PRVI]
#define bi	lssize[L_BSSI]
#define sd	lssize[L_SHRD]
#define pd	lssize[L_PRVD]
#define bd	lssize[L_BSSD]

/*
 * Segments.
 */
#define upsp	pp->p_segp[SIUSERP]
#define sssp	pp->p_segp[SISTACK]
#define	sisp	pp->p_segp[SISTEXT]
#define pisp	pp->p_segp[SIPTEXT]
#define sdsp	pp->p_segp[SISDATA]
#define pdsp	pp->p_segp[SIPDATA]

/*
 * Set up the first process, a small programme which will exec
 * the init programme.
 */
eveinit(sp)
SEG *sp;
{
	register PROC *pp;

	SELF = pp = eprocp;
	pp->p_segp[SIUSERP] = sp;
	if ((sp=salloc((fsize_t)icodes, 0)) == NULL)
		panic("eveinit()");
	pp->p_segp[SIPDATA] = sp;
	kscopy(icodep, sp, 0, icodes);
	if ((sp=salloc((fsize_t)UPASIZE, SFDOWN)) == NULL)
		panic("eveinit()");
	pp->p_segp[SISTACK] = sp;
	u.u_argp = 0;
	if (sproto() == 0)
		panic("eveinit()");
	segload();
}

/*
 * Given a major number, a file containing a device driver and a configuration
 * pointer, load the driver on the major number.
 */
pload(m, np, cp)
char *np;
CON *cp;
{
	register INODE *ip;
	register SEG *sp;
	register DRV *dp;
	register fsize_t ss;
	dold_t dold;
	int lflag;
	int r;
	vaddr_t pc;
	fsize_t lssize[NUSEG];

	if (m >= drvn) {
		u.u_error = ENXIO;
		return;
	}
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL)
		return;
	ss = pi+si+pd+sd;
	sp = ssalloc(&r, ip, SFSHRX, ss+bi+bd, sh, ss);
	idetach(ip);
	if (r < 0)
		return;
	dp = &drvl[m];
	lock(dp->d_gate);
	if (dp->d_conp != NULL) {
		unlock(dp->d_gate);
		sfree(sp);
		u.u_error = EDBUSY;
		return;
	}
	dp->d_time = 0;
	dp->d_conp = cp;
	dp->d_segp = sp;
	dp->d_map = sp->s_mbase;
	dsave(dold);
	dmapv(dp->d_map);
	(*cp->c_load)();
	drest(dold);
	unlock(dp->d_gate);
}

/*
 * Given a major number, undo the previous function.
 */
puload(m)
int m;
{
	register CON *cp;
	register DRV *dp;
	dold_t dold;

	dp = &drvl[m];
	lock(dp->d_gate);
	if (m>=drvn || dp->d_segp==NULL || (cp=dp->d_conp)==NULL) {
		u.u_error = ENXIO;
		goto ret;
	}
	dsave(dold);
	dmapv(dp->d_map);
	(*cp->c_uload)();
	drest(dold);
	if (u.u_error)
		goto ret;
	sfree(dp->d_segp);
	dp->d_conp = NULL;
	dp->d_segp = NULL;
	dp->d_map = 0;
ret:
	unlock(dp->d_gate);
	return (0);
}

/*
 * Given the name of an executable l.out, a null terminated argument
 * list and a null terminated environment list, execute the l.out with the
 * given arguments and environments.
 */
pexece(np, argp, envp)
char	*np;
char	*argp[];
char	*envp[];
{
	register INODE	*ip;			/* Load file INODE */
	register PROC	*pp;			/* A cheap copy of SELF */
	register SEG	*ssp;			/* New stack segment */
	register fsize_t	ss;			/* Segment size temp. */
	register int	kprocflag;		/* Set if kernal process */
	register int	i;			/* For looping over segments */
	int		r;			/* Flag for "exload" */
	int		lflag;			/* l_flags from l.out */
	vaddr_t		pc;			/* l_entry from l.out */
	vaddr_t		sp;			/* Initial stack pointer */
	fsize_t		lssize[NUSEG];		/* Segment sizes */

	pp = SELF;
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL)
		return;
	if ((lflag&LF_KER) != 0) {
		pp->p_flags |= PFKERN;
		kprocflag = 1;
		ssp = NULL;
		if (super() == 0) {
			idetach(ip);
			return;
		}
	} else {
		kprocflag = 0;
		if ((ssp=exstack(&sp, argp, envp)) == NULL) {
			idetach(ip);
			return;
		}
	}
	/*
	 * At this point the file has been
	 * validated as an object module, and the
	 * argument list has been build. Release all of
	 * the original segments. At this point we have
	 * committed to the new image. A "sys exec" that
	 * gets an I/O error is doomed.
	 */
	for (i=1; i<NUSEG; ++i) {
		if (pp->p_segp[i] != NULL) {
			sfree(pp->p_segp[i]);
			pp->p_segp[i] = NULL;
		}
	}
	sssp = ssp;
	/*
	 * Read in load module.
	 */
	switch (lflag&(LF_SHR|LF_SEP)) {
	case 0:
		ss = si+pi+sd+pd;
		pdsp = ssalloc(&r, ip, kprocflag?SFHIGH:0, ss+bi+bd, sh, ss);
		if (r < 0)
			goto out;
		break;

	case LF_SHR:
		sdsp = ssalloc(&r, ip, SFSHRX, si+sd, sh, si);
		if (r < 0)
			goto out;
		if (r == 0) {
			if (exsread(sdsp, ip, sd, sh+si+pi, si) == 0)
				goto out;
		}
		pdsp = ssalloc(&r, ip, 0, pi+pd+bi+bd, sh+si, pi);
		if (r < 0)
			goto out;
		if (r == 0) {
			if (exsread(pdsp, ip, pd, sh+si+pi+sd, pi) == 0)
				goto out;
		}
		break;

	case LF_SEP:
		pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+bi, sd+pd);
		if (r < 0)
			goto out;
		break;

	case LF_SHR|LF_SEP:
		sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si);
		if (r < 0)
			goto out;
		pisp = ssalloc(&r, ip, SFTEXT, pi+bi, sh+si, pi);
		if (r < 0)
			goto out;
		sdsp = ssalloc(&r, ip, SFSHRX, sd, sh+si+pi, sd);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, pd+bd, sh+si+pi+pd, pd);
		if (r < 0)
			goto out;
	}
	if (sproto() == 0)
		goto out;
	/*
	 * The new image is read in
	 * and mapped. Perform the final grunge
	 * (set-uid stuff, accounting, loading up
	 * registers, etc).
	 */
	u.u_flag &= ~AFORK;
	kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
	if (iaccess(ip, IPR) == 0)
		pp->p_flags |= PFNDMP;
	if ((ip->i_mode&ISUID) != 0)
		pp->p_uid = u.u_uid = ip->i_uid;
	if ((ip->i_mode&ISGID) != 0)
		u.u_gid = ip->i_gid;
	for (i=0; i<NSIG; ++i) {
		if (u.u_sfunc[i] != SIG_IGN)
			u.u_sfunc[i] = SIG_DFL;
	}
	if ((pp->p_flags&PFTRAC) != 0)
		sendsig(SIGTRAP, pp);
	idetach(ip);
	msetusr(pc, sp);
	segload();
	return (0);

	/*
	 * We did not make it.
	 * Release the INODE for the load
	 * file, and return through the "sys exit"
 	 * code. A better exit status should be
	 * chosen!
	 */
out:
	idetach(ip);
	pexit(0);
}

/*
 * Open an l.out, make sure it is an l.out and executable and return the
 * appropriate information.
 */
INODE *
exlopen(np, ssizep, flagp, pcp)
char *np;
fsize_t *ssizep;
int *flagp;
vaddr_t *pcp;
{
	register INODE *ip;
	register struct ldheader *ldp;
	register int n;
	register BUF *bp;
	int m;

	/*
	 * Make sure the file is really an executable l.out and read the
	 * header in.
	 */
	if (ftoi(np, 'r') != 0)
		return (NULL);
	ip = u.u_cdiri;
	if (iaccess(ip, IPE) == 0) {
		idetach(ip);
		return (NULL);
	}
	if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
		u.u_error = EACCES;
		idetach(ip);
		return (NULL);
	}
	if ((bp=vread(ip, (daddr_t)0)) == NULL) {
		u.u_error = EBADFMT;
		idetach(ip);
		return (NULL);
	}

	/*
	 * Copy everything we need from the l.out header and check magic
	 * number and machine type.
	 */
	ldp = bp->b_vaddr;
	m = ldp->l_magic;
	canint(m);
	if (m != L_MAGIC) {
		u.u_error = ENOEXEC;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	m = ldp->l_machine;
	canint(m);
	if (m != mactype) {
		u.u_error = EBADFMT;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(fsize_t));
	for (n=0; n<NXSEG; n++)
		cansize(ssizep[n]);
	*flagp = ldp->l_flag;
	canint(*flagp);
	*pcp = ldp->l_entry;
	canvaddr(*pcp);
	brelease(bp);
	return (ip);
}

/*
 * Given a segment `sp', read `ss' bytes from the inode `ip' starting
 * at seek address `sa' into offset `so' in the segment.
 */
SEG *
exsread(sp, ip, ss, sa, so)
register SEG *sp;
INODE *ip;
fsize_t sa;
fsize_t ss;
fsize_t so;
{
	u.u_io.io_seg = IOPHY;
	u.u_io.io_ioc = ss;
	u.u_io.io_seek = sa;
	u.u_io.io_phys = ctob((paddr_t)sp->s_mbase) + so;
	u.u_io.io_flag = 0;
	iread(ip, &u.u_io);
	return (u.u_error==0);
}

/*
 * Given a pointer to a list of arguments and a pointer to a list of
 * environments, return a stack with the arguments and environments on it.
 */
SEG *
exstack(iusp, argp, envp)
char **iusp;		/* Back patch sp value */
char *argp[];		/* Arguments for new process */
char *envp[];		/* Environments for new process */
{
	SEG *sp;		/* Stack segment pointer */
	struct adata {		/* Storage for arg and env data */
		char	**up;		/* User vector pointer */
		int	np;		/* Number of pointers in vector */
		int	nc;		/* Number of characters in strings */
	} arg, env;
	struct sdata {		/* To keep segment pointers */
		vaddr_t	base;		/* Top of segment virtual */
		vaddr_t	ap;		/* Argc, argv, envp pointer */
		vaddr_t	vp;		/* Argv[i], envp[i] pointer */
		vaddr_t	cp;		/* Argv[i][j], envp[i][j] pointer */
	} aux, stk;
	aold_t aold;			/* Auxiliary map storage */
	register char **usrvp;		/* Vector pointer into user seg */
	register char *usrcp;		/* Character pointer into user seg */
	register int c;			/* Character fetched from user */
	register int chrsz;		/* Size of strings */
	register struct adata *adp;	/* Arg and env scanner */
	register int vecsz;		/* Size of vectors */
	register int stksz;		/* Size of stack argument region */

	/* Validate and evaluate size of args and envs */
	arg.up = argp;
	env.up = envp;
	chrsz = 0;
	vecsz = 0;
	for (adp = &arg; ; adp = &env) {
		adp->np = 0;
		adp->nc = 0;
		if (excount(adp->up, &adp->np, &adp->nc) == 0)
			return (NULL);
		chrsz += adp->nc * sizeof(char);
		vecsz += adp->np * sizeof(char *);
		if (adp == &env)
			break;
	}

	/* Calculate stack size and allocate it */
	chrsz = roundu(chrsz, sizeof(int));
	stksz = sizeof(int)		/* argc */
		+ sizeof(char **)	/* argv */
		+ sizeof(char **)	/* envp */
		+ vecsz			/* argv[i] and envp[i] */
		+ chrsz			/* *argv[i] and *envp[i] */
		+ sizeof(int)		/* Mystery zero word */
		+ sizeof(char *)	/* Splimit for z8000 */
		+ sizeof(int);		/* errno */
	stksz += ISTSIZE;
	if (stksz > MADSIZE) {
		u.u_error = E2BIG;
		return (NULL);
	}
	if ((sp=salloc((fsize_t)stksz, SFDOWN)) == NULL)
		return (NULL);
	stksz -= ISTSIZE;

	/*
	 * Initialize segment data.
	 */
	asave(aold);

	aux.base = abase(sp->s_mbase) + ctob(sp->s_size);
	aux.ap = aux.base - stksz;
	aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **);
	aux.cp = aux.vp + vecsz;

	stk.base = ISTVIRT;
	stk.ap = stk.base - stksz;
	stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **);
	stk.cp = stk.vp + vecsz;

	/*
	 * Write argc.
	 */
	aputi((int *)aux.ap, arg.np-1);
	aux.ap += sizeof(int);

	/*
	 * Arguments and environments.
	 */
	for (adp = &arg; ; adp = &env) {

		/* Write argv or envp */
		aputp((char ***)aux.ap, (char **)stk.vp);
		aux.ap += sizeof(char **);
		if ((usrvp = adp->up) != NULL) {

			/* Write argv[i] or envp[i] */
			while ((usrcp = getupd(usrvp++)) != NULL) {
				aputp((char **)aux.vp, (char *)stk.cp);
				aux.vp += sizeof(char *);
				stk.vp += sizeof(char *);

				/* Write argv[i][j] or envp[i][j] */
				do {
					c = getubd(usrcp++);
					aputc((char *)aux.cp, c);
					aux.cp += sizeof(char);
					stk.cp += sizeof(char);
				} while (c != '\0');
			}
		}

		/* Write argv[argc] or envp[envc] */
		aputp((char **)aux.vp, NULL);
		aux.vp += sizeof(char *);
		stk.vp += sizeof(char *);
		if (adp == &env)
			break;
	}

	/*
	 * Clear out the slop.
	 */
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* errno */
	aux.base -= sizeof(char *);
	aputp((char **) aux.base, (char *)stk.base-ctob(sp->s_size)+SOVSIZE);
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* mystery word */

	arest(aold);

	/*
	 * Patch some values and return.
	 */
	*iusp = stk.ap;		/* Patch initial usp */
	u.u_argc = arg.np-1;
	u.u_argp = stk.vp;	/* Points after NULL of envs */
	return (sp);
}

/*
 * Given a pointer to a list of arguments, a pointer to an argument count
 * and a pointer to a byte count, update incrementally the argument count
 * and the byte count.
 */
excount(usrvp, nap, nbp)
register char **usrvp;
int *nap;
int *nbp;
{
	register char *usrcp;
	register int c;
	register unsigned nb;
	register unsigned na;

	na = 1;
	nb = 0;
	if (usrvp != NULL) {
		for (;;) {
			usrcp = getupd(usrvp++);
			if (u.u_error)
				return (0);
			if (usrcp == NULL)
				break;
			na++;
			for (;;) {
				c = getubd(usrcp++);
				if (u.u_error)
					return (0);
				nb++;
				if (c == '\0')
					break;
			}
		}
	}
	*nap += na;
	*nbp += nb;
	return (1);
}
0707070064030147521006440000030000030000011777770507310726500004000000006425/newbits/kernel/USRSRC/coh/fd.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * File descriptor routines.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:50:35  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:13:43	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/fd.h>
#include <sys/inode.h>
#include <sys/uproc.h>

/*
 * Given a file number, return the file descriptor.
 */
FD *
fdget(fd)
register unsigned fd;
{
	register FD *fdp;

	if (fd>=NUFILE || (fdp=u.u_filep[fd])==NULL) {
		u.u_error = EBADF;
		return (NULL);
	}
	return (fdp);
}

/*
 * Duplicate a file descriptor number.  This has the same calling
 * sequence as the dup2 system call and even uses the silly DUP2 bit.
 */
fddup(ofd, nfd)
register unsigned ofd;
register unsigned nfd;
{
	register FD *fdp;

	if ((fdp=fdget(ofd&~DUP2)) == NULL)
		return (-1);
	if ((ofd&DUP2) != 0) {
		if (nfd >= NUFILE) {
			u.u_error = EBADF;
			return (-1);
		}
		ofd &= ~DUP2;
		if (ofd == nfd)
			return (nfd);
		if (u.u_filep[nfd] != NULL) {
			fdclose(nfd);
			if (u.u_error)
				return (-1);
		}
	} else {
		for (nfd=0; nfd<NUFILE; nfd++)
			if (u.u_filep[nfd] == NULL)
				break;
		if (nfd == NUFILE) {
			u.u_error = EMFILE;
			return (-1);
		}
	}
	u.u_filep[nfd] = fdp;
	fdp->f_refc++;
	return (nfd);
}

/*
 * Given an inode, and a mode containing permission flags, open the
 * inode with the appropriate permissions and return a file descriptor
 * containing it.
 */
fdopen(ip, mode)
register INODE *ip;
{
	register FD **fdpp;
	register FD *fdp;

	for (fdpp=u.u_filep; fdpp<&u.u_filep[NUFILE]; fdpp++) {
		if (*fdpp != NULL)
			continue;
		if ((fdp=kalloc(sizeof(FD))) == NULL)
			return (-1);
		iopen(ip, mode);
		if (u.u_error) {
			kfree(fdp);
			return (-1);
		}
		fdp->f_flag = mode;
		fdp->f_refc = 1;
		fdp->f_seek = 0;
		fdp->f_ip = ip;
		*fdpp = fdp;
		return (fdpp-u.u_filep);
	}
	u.u_error = EMFILE;
	return (-1);
}

/*
 * Close the given file number.
 */
fdclose(fd)
register unsigned fd;
{
	register FD *fdp;

	if (fd>=NUFILE || (fdp=u.u_filep[fd])==NULL) {
		u.u_error = EBADF;
		return;
	}
	u.u_filep[fd] = NULL;
	if (fdp->f_refc == 0)
		panic("fdclose()");
	if (--fdp->f_refc == 0) {
		iclose(fdp->f_ip);
		kfree(fdp);
	}
}

/*
 * Assuming we have made a copy of the user area, increment the reference
 * of all open files.  (used in fork).
 */
fdadupl()
{
	register FD **fdpp;
	register FD *fdp;

	for (fdpp=u.u_filep; fdpp<&u.u_filep[NUFILE]; fdpp++) {
		if ((fdp=*fdpp) == NULL)
			continue;
		fdp->f_refc++;
	}
}

/*
 * Close all open files in the current process.
 */
fdaclose()
{
	register int fd;

	for (fd=0; fd<NUFILE; fd++) {
		if (u.u_filep[fd] == NULL)
			continue;
		fdclose(fd);
	}
}
0707070064030103701006440000030000030000011777770507310726500004100000034033/newbits/kernel/USRSRC/coh/fs1.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Filesystem (mostly handling of in core inodes).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.5  91/07/24  07:50:40  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:13:47	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/fs1.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 86/12/13	Allan Cornish		/usr/src/sys/coh/fs1.c
 * isync() no longer updates the disk image of a character device inode.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/fs1.c
 * idirent() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/dir.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/mount.h>>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Get character for `ftoi' depending on what space the characters are
 * coming from.
 */
#define ftoic(p)	(u.u_io.io_seg==IOSYS ? *p : getubd(p))

/*
 * Map the given filename to an inode.  If an error is encountered,
 * `u.u_error' is set.  `u.u_error' is always returned.  As this routine
 * needs to set several things, depending on the type of access, `t',
 * there are places in the processes' user area reserved for this routine
 * to set.  These are defined in the user process structure.  The seek
 * position is always set to the position of the directory entry of the
 * child if the child exists or the first free position if it doesn't.
 *  'r' =>  Reference.  A pointer to the child's inode is returned locked.
 *  'c' =>  Create.  If the child exists, a pointer to the inode is returned
 *          locked.  Otherwise if the parent directory exists, a pointer to
 *          the parent directory is returned locked.  Otherwise, an error.
 *  'u' =>  Unlink.  The parent directory is returned unlocked.  The child's
 *          inode number is returned.  The seek position is also set.
 */
ftoi(np, t)
char *np;
{
	register INODE *cip;
	register char *cp;
	register int c;
	register struct direct *dp;
	register BUF *bp;
	fsize_t cseek, fseek, s;
	int fflag, mflag;
	dev_t dev;
	ino_t ino;
	daddr_t b;

	u.u_cdirn = 0;
	u.u_cdiri = NULL;
	u.u_pdiri = NULL;
	if ((c=ftoic(np++)) != '/')
		cip = u.u_cdir;
	else {
		c = ftoic(np++);
		cip = u.u_rdir;
	}
	while (c == '/')
		c = ftoic(np++);
	ilock(cip);
	cip->i_refc++;
	if (c == '\0') {
		if (t == 'r') {
			u.u_cdiri = cip;
			return (u.u_error);
		}
		u.u_error = ENOENT;
		idetach(cip);
		return (u.u_error);
	}
	for (;;) {
		cp = u.u_direct.d_name;
		while (c!='/' && c!='\0') {
			if (cp < &u.u_direct.d_name[DIRSIZ])
				*cp++ = c;
			c = ftoic(np++);
		}
		while (c == '/')
			c = ftoic(np++);
		while (cp < &u.u_direct.d_name[DIRSIZ])
			*cp++ = '\0';
		if ((cip->i_mode&IFMT) != IFDIR)
			u.u_error = ENOTDIR;
		else
			iaccess(cip, IPE);
		if (u.u_error) {
			idetach(cip);
			return (u.u_error);
		}
		cp = u.u_direct.d_name;
		if (cip->i_ino==ROOTIN && cip->i_dev!=rootdev)
			if (*cp++=='.' && *cp++=='.' && *cp++=='\0')
				cip = ftoim(cip);
		b = 0;
		fflag = 0;
		mflag = 0;
		cseek = 0;
		s = cip->i_size;
		while (s > 0) {
			if ((bp=vread(cip, b++)) == NULL) {
				idetach(cip);
				return (u.u_error);
			}
			dp = FP_OFF(bp->b_faddr);
			while (dp < FP_OFF(bp->b_faddr)+BSIZE) {
				if ((s-=sizeof(*dp)) < 0)
					break;
				if ((ino=dp->d_ino) == 0) {
					if (fflag == 0) {
						fflag++;
						fseek = cseek;
					}
				} else {
					if (direq(dp)) {
						canino(ino);
						mflag = 1;
						s = 0;
						break;
					}
				}
				cseek += sizeof(*dp);
				dp++;
			}
			brelease(bp);
		}
		dev = cip->i_dev;
		if (fflag == 0)
			fseek = cseek;
		if (mflag == 0) {
			if (c=='\0' && t=='c') {
				u.u_pdiri = cip;
				u.u_io.io_seek = fseek;
			} else {
				u.u_error = ENOENT;
				idetach(cip);
			}
			return (u.u_error);
		}
		if (c == '\0') {
			if (t == 'u') {
				u.u_cdirn = ino;
				u.u_pdiri = cip;
				u.u_io.io_seek = cseek;
				return (u.u_error);
			}
			idetach(cip);
			u.u_cdiri = iattach(dev, ino);
			return (u.u_error);
		}
		idetach(cip);
		if ((cip=iattach(dev, ino)) == NULL)
			return (u.u_error);
	}
}

/*
 * Given an inode which is the root of a file system, return the inode
 * on which the file system was mounted.
 */
INODE *
ftoim(ip)
register INODE *ip;
{
	register MOUNT *mp;

	for (mp=mountp; mp!=NULL; mp=mp->m_next) {
		if (mp->m_dev == ip->i_dev) {
			idetach(ip);
			ip = mp->m_ip;
			ilock(ip);
			ip->i_refc++;
			break;
		}
	}
	return (ip);
}

/*
 * Compare the string in `u.u_direct.d_name' with the name in the
 * given directory pointer.
 */
direq(dp)
struct direct *dp;
{
	register char *cp1, *cp2;
	register unsigned n;

	if (dp->d_ino == 0)
		return (0);
	cp1 = dp->d_name;
	cp2 = u.u_direct.d_name;
	n = DIRSIZ;
	do {
		if (*cp1++ != *cp2++)
			return (0);
	} while (--n);
	return (1);
}

/*
 * Make an inode of the given mode and device.  The parent directory,
 * name and such stuff is set by ftoi.
 */
INODE *
imake(mode, rdev)
unsigned mode;
dev_t rdev;
{
	register INODE *ip;

	ip = NULL;
	mode &= ~u.u_umask;
	if ((mode&ISVTXT)!=0 && super()==0)
		goto det;
	if (iaccess(u.u_pdiri, IPW) == 0)
		goto det;
	if ((ip=ialloc(u.u_pdiri->i_dev, mode)) == NULL)
		goto det;
	ip->i_nlink = 1;
	ip->i_a.i_rdev = rdev;
	idirent(ip->i_ino);
	iamc(ip);	/* creat/mknod - atime/mtime/ctime */
det:
	idetach(u.u_pdiri);
	return (ip);
}

/*
 * Write a directory entry out.  Everything necessary has been conveniently
 * set by `ftoi', except the new inode number of this directory entry.
 */
idirent(ino)
{
	u.u_direct.d_ino = ino;
	canino(u.u_direct.d_ino);
	u.u_io.io_ioc  = sizeof (struct direct);
	u.u_io.io_base = &u.u_direct;
	u.u_io.io_seg  = IOSYS;
	u.u_io.io_flag = 0;
	iwrite(u.u_pdiri, &u.u_io);
}

/*
 * Return a pointer to a locked inode in core containing the given
 * inode number and device.
 */
INODE *
iattach(dev, ino)
{
	register INODE *ip;
	register INODE *fip;
	register unsigned lrt;
	register MOUNT *mp;

	for (;;) {
		fip = NULL;
		for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
			if (ip->i_ino==ino && ip->i_dev==dev)
				break;
			if (ip->i_refc == 0) {
				if (fip==NULL || ip->i_lrt<lrt) {
					fip = ip;
					lrt = ip->i_lrt;
				}
			}
		}
		if (ip < inodep) {
			if ((ip=fip) == NULL) {
				devmsg(dev, "Inode table overflow");
/*DEBUG*/
{ char cmd[11];int i;
for(i=0;i<10&&u.u_comm[i];i++)
    cmd[i]=u.u_comm[i];
cmd[i]='\0';
printf("cmd=%s time=%lu\n",cmd, u.u_btime);
}
				u.u_error = ENFILE;
				return (NULL);
			}
			ilock(ip);
			if (ip->i_refc != 0) {
				iunlock(ip);
				continue;
			}
			ip->i_dev = dev;
			ip->i_ino = ino;
			ip->i_refc = 1;
			ip->i_lrt = timer.t_time;
			if (icopydm(ip) == 0) {
				ip->i_ino = 0;
				ip->i_refc = 0;
				iunlock(ip);
				return (NULL);
			}
			return (ip);
		}
		if ((ip->i_flag&IFMNT) != 0) {
			for (mp=mountp; mp!=NULL; mp=mp->m_next) {
				if (mp->m_ip == ip) {
					ino = ROOTIN;
					dev = mp->m_dev;
					break;
				}
			}
			continue;
		}
		ilock(ip);
		if (ip->i_ino!=ino || ip->i_dev!=dev) {
			iunlock(ip);
			continue;
		}
		if (ip->i_refc < 0)
			panic("ialloc(%p), ip");
		ip->i_refc++;
		ip->i_lrt = timer.t_time;
		return (ip);
	}
}

/*
 * Given a locked inode, deaccess it.
 */
idetach(ip)
register INODE *ip;
{
	if (ilocked(ip)==0 || ip->i_refc<=0)
		panic("idetach(%p)", ip);
	if (--ip->i_refc == 0) {
		if ((ip->i_flag&(IFACC|IFMOD|IFCRT)) != 0
		 || ip->i_nlink == 0)
			icopymd(ip);
	}
	iunlock(ip);
}

/*
 * Given a inode which isn't locked, lock it and then deaccess.
 */
ldetach(ip)
register INODE *ip;
{
	ilock(ip);
	idetach(ip);
}

/*
 * A specialized routine for finding whether the given inode may be unlinked.
 * Quite simple you say, but we already have an inode locked and could run
 * into gating problems if we were to lock another.  So we look through the
 * cache to see if the inode is there.  If it is, we can easily tell.  If it
 * isn't, `icopydm' is called with a static.  This routine is only used by
 * `uunlink'.
 */
iucheck(dev, ino)
register dev_t dev;
register ino_t ino;
{
	register INODE *ip;
	INODE inode;

	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_ino==ino && ip->i_dev==dev)
			break;
	}
	if (ip < inodep) {
		ip = &inode;
		ip->i_dev = dev;
		ip->i_ino = ino;
		if (icopydm(ip) == 0)
			return (0);
	}
	if ((ip->i_mode&IFMT) == IFDIR) {
		if (super() == 0)
			return (0);
	}
	return (1);
}

/*
 * Copy an inode from disk to memory performing canonization.
 */
icopydm(ip)
register INODE *ip;
{
	register struct dinode *dip;
	register BUF *bp;
	register ino_t ino;
	struct dinode dinode;
	vaddr_t v;

	ip->i_flag = 0;
	ino = ip->i_ino;

	if ((bp=bread(ip->i_dev, (daddr_t)iblockn(ino), 1)) == NULL)
		return (0);

	dip = &dinode;
	v = (char *)((struct dinode *)FP_OFF(bp->b_faddr) + iblocko(ino));
	kkcopy( v, dip, sizeof(dinode));
	brelease(bp);
	ip->i_mode = dip->di_mode;
	canshort(ip->i_mode);
	ip->i_nlink = dip->di_nlink;
	canshort(ip->i_nlink);
	ip->i_uid = dip->di_uid;
	canshort(ip->i_uid);
	ip->i_gid = dip->di_gid;
	canshort(ip->i_gid);
	ip->i_size = dip->di_size;
	cansize(ip->i_size);

	switch (ip->i_mode&IFMT) {
	case IFBLK:
	case IFCHR:
		ip->i_a.i_rdev = dip->di_a.di_rdev;
		candev(ip->i_a.i_rdev);
		break;
	case IFREG:
	case IFDIR:
		l3tol(ip->i_a.i_addr, dip->di_a.di_addb, NADDR);
		break;
	case IFPIPE:
		l3tol(ip->i_pipe, dip->di_addp, ND);
		ip->i_pnc = dip->di_pnc;
		canint(ip->i_pnc);
		ip->i_prx = dip->di_prx;
		canint(ip->i_prx);
		ip->i_pwx = dip->di_pwx;
		canint(ip->i_pwx);
		break;
	default:
		kclear(&ip->i_a, sizeof(ip->i_a));
		break;
	}

	ip->i_atime = dip->di_atime;
	cantime(ip->i_atime);
	ip->i_mtime = dip->di_mtime;
	cantime(ip->i_mtime);
	ip->i_ctime = dip->di_ctime;
	cantime(ip->i_ctime);
	return (1);
}

/*
 * Copy an inode from memory back on to disk performing canonization.
 */
icopymd(ip)
register INODE *ip;
{
	register struct dinode *dip;
	register BUF *bp;
	register ino_t ino;
	struct dinode dinode;
	vaddr_t v;

	if (getment(ip->i_dev, 0) == NULL)
		return;

	ino = ip->i_ino;
	if (ip->i_refc==0 && ip->i_nlink==0 && ino!=BADFIN && ino!=ROOTIN) {
		iclear(ip);
		ip->i_lrt = 0;
		ip->i_mode = 0;
		ifree(ip->i_dev, ino);
	}

	dip = &dinode;
	dip->di_mode = ip->i_mode;
	canshort(dip->di_mode);
	dip->di_nlink = ip->i_nlink;
	canshort(dip->di_nlink);
	dip->di_uid = ip->i_uid;
	canshort(dip->di_uid);
	dip->di_gid = ip->i_gid;
	canshort(dip->di_gid);
	dip->di_size = ip->i_size;
	cansize(dip->di_size);

	switch (ip->i_mode&IFMT) {
	case IFBLK:
	case IFCHR:
		dip->di_a.di_rdev = ip->i_a.i_rdev;
		candev(dip->di_a.di_rdev);
		break;
	case IFREG:
	case IFDIR:
		ltol3(dip->di_addr, ip->i_a.i_addr, NADDR);
		break;
	case IFPIPE:
		ltol3(dip->di_addp, ip->i_pipe, ND);
		dip->di_pnc = ip->i_pnc;
		canshort(dip->di_pnc);
		dip->di_prx = ip->i_prx;
		canshort(dip->di_prx);
		dip->di_pwx = ip->i_pwx;
		canshort(dip->di_pwx);
		break;
	default:
		kclear(&dip->di_a, sizeof(dip->di_a));
		break;
	}

	dip->di_atime = ip->i_atime;
	cantime(dip->di_atime);
	dip->di_mtime = ip->i_mtime;
	cantime(dip->di_mtime);
	dip->di_ctime = ip->i_ctime;
	cantime(dip->di_ctime);

	if ((bp=bread(ip->i_dev, (daddr_t)iblockn(ino), 1)) == NULL)
		return;

	v = (char *)((struct dinode *)FP_OFF(bp->b_faddr) + iblocko(ino));
	kkcopy(dip, v, sizeof(dinode));
	bp->b_flag |= BFMOD;
	brelease(bp);
	ip->i_flag &= ~(IFACC|IFMOD|IFCRT);
}

/*
 * Copy all relevant inodes out on device `dev'.
 */
isync(dev)
register dev_t dev;
{
	register INODE *ip;

	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_refc == 0)
			continue;
		if (ip->i_dev != dev)
			continue;
		if ( (ip->i_mode & IFMT) == IFCHR )
			continue;
		if ((ip->i_flag&(IFACC|IFMOD|IFCRT)) == 0)
			continue;
		icopymd(ip);
	}
}

/*
 * Clear the given inode and all space associated with it.
 */
iclear(ip)
register INODE *ip;
{
	register int n;
	register daddr_t b;

	switch (ip->i_mode&IFMT) {
	case IFPIPE:
		ip->i_pnc = 0;
		ip->i_prx = 0;
		ip->i_pwx = 0;
		n = ND;
		break;
	case IFDIR:
	case IFREG:
		n = NADDR;
		break;
	default:
		return;
	}
	while (n > ND) {
		if ((b=ip->i_a.i_addr[--n]) != 0)
			indfree(ip->i_dev, b, 1+n-ND);
	}
	while (n > 0) {
		if ((b=ip->i_a.i_addr[--n]) != 0)
			bfree(ip->i_dev, b);
	}
	ip->i_size = 0;
	kclear(ip->i_a.i_addr, sizeof(ip->i_a.i_addr));
	iamc(ip);	/* creat/pipe - atime/mtime/ctime */
}

/*
 * Copy the appropriate information from the inode to the stat buffer.
 */
istat(ip, sbp)
register INODE *ip;
register struct stat *sbp;
{
	sbp->st_dev = ip->i_dev;
	sbp->st_ino = ip->i_ino;
	sbp->st_mode = ip->i_mode;
	sbp->st_nlink = ip->i_nlink;
	sbp->st_uid = ip->i_uid;
	sbp->st_gid = ip->i_gid;
	sbp->st_rdev = NODEV;
	sbp->st_size = ip->i_size;
	sbp->st_atime = ip->i_atime;
	sbp->st_mtime = ip->i_mtime;
	sbp->st_ctime = ip->i_ctime;
	switch (ip->i_mode&IFMT) {
	case IFBLK:
	case IFCHR:
		sbp->st_rdev = ip->i_a.i_rdev;
		sbp->st_size = 0;
		break;
	case IFPIPE:
		sbp->st_size = ip->i_pnc;
		break;
	}
}

/*
 * See if it is possible to access the given inode with the bits in
 * the given mode.
 * If the mode includes writing, and i_refc is > 1, then check for
 * shared text problems.
 */
iaccess(ip, mode)
register INODE *ip;
register int mode;
{
	if ((imode(ip, u.u_uid, u.u_gid)&mode) != mode) {
		u.u_error = EACCES;
		return (0);
	}
	if ((mode&IPW) != 0 && ip->i_refc > 1 && sbusy(ip)) {
		u.u_error = ETXTBSY;
		return (0);
	}
	return (1);
}

/*
 * Get the maximum allowable mode on a file.
 */
imode(ip, uid, gid)
register INODE *ip;
{
	if (uid == 0)
		return (IPR|IPW|IPE);
	if (uid == ip->i_uid)
		return ((ip->i_mode>>6)&07);
	if (gid == ip->i_gid)
		return ((ip->i_mode>>3)&07);
	return (ip->i_mode&07);
}
0707070064030103671006440000030000030000011777770507310727100004100000024166/newbits/kernel/USRSRC/coh/fs2.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Filesystem (disk inodes).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:50:55  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:13:51	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/fs2.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/04/29	Allan Cornish		/usr/src/sys/coh/fs2.c
 * Fsminit panic messages now specify the root major and minor device.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/fs2.c
 * setacct() initializes the (new) (IO).io_flag field to 0.
 *
 * 85/08/08	Allan Cornish
 * ialloc() erroneously did a brelease(NULL) if bclaim() returned NULL.
 * also, sbp->s_fmod was set BEFORE the in-core inode table was updated.
 * This created a critical race with msync() (called by sync system call).
 *
 * 85/04/17	Allan Cornish
 * eliminated test for rootdev in msync()
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Initialise filesystem.
 */
fsminit()
{
	register MOUNT *mp;

	/*
	 * Mount the root file system.
	 */
	if ( (mp = fsmount(rootdev, ronflag)) == NULL )
		panic(	"fsminit: no rootdev(%d,%d)",
			major(rootdev), minor(rootdev) );

	/*
	 * Set system time from the super block.
	 */
	timer.t_time = mp->m_super.s_time;

	/*
	 * Access the root directory.
	 */
	if ( (u.u_rdir = iattach(rootdev, ROOTIN)) == NULL )
		panic(	"fsminit: no / on rootdev(%d,%d)",
			major(rootdev), minor(rootdev) );

	/*
	 * Record current directory.
	 */
	u.u_cdir = u.u_rdir;
	u.u_cdir->i_refc++;
	iunlock(u.u_rdir);
}

/*
 * Mount the given device.
 */
MOUNT *
fsmount(dev, f)
register dev_t dev;
{
	register MOUNT *mp;
	register BUF *bp;

	if ((mp=kalloc(sizeof(MOUNT))) == NULL)
		return (NULL);
	dopen(dev, (f?IPR:IPR|IPW), DFBLK);
	if (u.u_error != 0) {
		kfree(mp);
		return (NULL);
	}
	if ((bp=bread(dev, (daddr_t)SUPERI, 1)) == NULL) {
		dclose(dev);
		kfree(mp);
		return (NULL);
	}
	kkcopy(FP_OFF(bp->b_faddr), &mp->m_super, sizeof(struct filsys));
	brelease(bp);
	cansuper(&mp->m_super);
	mp->m_ip = NULL;
	mp->m_dev = dev;
	mp->m_flag = f;
	mp->m_super.s_fmod = 0;
	mp->m_next = mountp;
	mountp = mp;
	return (mp);
}

/*
 * Canonize a super block.
 */
cansuper(fsp)
register struct filsys *fsp;
{
	register int i;

	canint(fsp->s_isize);
	candaddr(fsp->s_fsize);
	canshort(fsp->s_nfree);
	for (i=0; i<NICFREE; i++)
		candaddr(fsp->s_free[i]);
	canshort(fsp->s_ninode);
	for (i=0; i<NICINOD; i++)
		canino(fsp->s_inode[i]);
	cantime(fsp->s_time);
	candaddr(fsp->s_tfree);
	canino(fsp->s_tinode);
	canshort(fsp->s_m);
	canshort(fsp->s_n);
	canlong(fsp->s_unique);
}

/*
 * Given a pointer to a mount entry, write out all inodes on that device.
 */
msync(mp)
register MOUNT *mp;
{
	register struct filsys *sbp;
	register BUF *bp;

	if ((mp->m_flag&MFRON) != 0)
		return;
	isync(mp->m_dev);
	sbp = &mp->m_super;
	if (sbp->s_fmod==0)
		return;
	bp = bclaim(mp->m_dev, (daddr_t)SUPERI);
	sbp->s_time = timer.t_time;
	sbp->s_fmod = 0;
	kkcopy(sbp, FP_OFF(bp->b_faddr), sizeof(*sbp));
	cansuper(FP_OFF(bp->b_faddr));
	bwrite(bp, 1);
	brelease(bp);
}

/*
 * Return the mount entry for the given device.  If `f' is not set
 * and the device is read only, don't set the error status.
 */
MOUNT *
getment(dev, f)
register dev_t dev;
{
	register MOUNT *mp;

	for (mp=mountp; mp!=NULL; mp=mp->m_next) {
		if (mp->m_dev != dev)
			continue;
		if ((mp->m_flag&MFRON) != 0) {
			if (f != 0)
				u.u_error = EROFS;
			return (NULL);
		}
		return (mp);
	}
	panic("getment: dev=0x%x", dev);
}

/*
 * Allocate a new inode with the given mode.  The returned inode is locked.
 */
INODE *
ialloc(dev, mode)
dev_t dev;
unsigned mode;
{
	register struct dinode *dip;
	register struct filsys *sbp;
	register ino_t *inop;
	register ino_t ino;
	register BUF *bp;
	register daddr_t b;
	register struct dinode *dipe;
	register ino_t *inope;
	register MOUNT *mp;
	register INODE *ip;

	if ((mp=getment(dev, 1)) == NULL)
		return (NULL);
	sbp = &mp->m_super;
	for (;;) {
		lock(mp->m_ilock);
		if (sbp->s_ninode == 0) {
			ino = 1;
			inop = sbp->s_inode;
			inope = &sbp->s_inode[NICINOD];
			for (b=INODEI; b<sbp->s_isize; b++) {
				if (bad(dev, b)) {
					ino += INOPB;
					continue;
				}
				if ((bp=bread(dev, b, 1)) == NULL) {
					ino += INOPB;
					continue;
				}
				dip = FP_OFF(bp->b_faddr);
				dipe = &dip[INOPB];
				for (; dip<dipe; dip++, ino++) {
					if (dip->di_mode != 0)
						continue;
					if (inop >= inope)
						break;
					*inop++ = ino;
				}
				brelease(bp);
				if (inop >= inope)
					break;
			}
			sbp->s_ninode = inop - sbp->s_inode;
			if (sbp->s_ninode == 0) {
				sbp->s_tinode = 0;
				unlock(mp->m_ilock);
				devmsg(dev, "Out of inodes");
				u.u_error = ENOSPC;
				return (NULL);
			}
		}
		ino = sbp->s_inode[--sbp->s_ninode];
		--sbp->s_tinode;
		sbp->s_fmod = 1;
		unlock(mp->m_ilock);
		if ((ip=iattach(dev, ino)) != NULL) {
			if (ip->i_mode != 0) {
				devmsg(dev, "Inode %u busy", ino);
				idetach(ip);
				continue;
			}
			ip->i_flag = 0;
			ip->i_mode = mode;
			ip->i_nlink = 0;
			ip->i_uid = u.u_uid;
			ip->i_gid = u.u_gid;
		}
		return (ip);
	}
}

/*
 * Free the inode `ino' on device `dev'.
 */
ifree(dev, ino)
dev_t dev;
ino_t ino;
{
	register struct filsys *sbp;
	register MOUNT *mp;

	if ((mp=getment(dev, 1)) == NULL)
		return;
	lock(mp->m_ilock);
	sbp = &mp->m_super;
	sbp->s_fmod = 1;
	if (sbp->s_ninode < NICINOD)
		sbp->s_inode[sbp->s_ninode++] = ino;
	sbp->s_tinode++;
	unlock(mp->m_ilock);
}

/*
 * Free all blocks in the indirect block `b' on the device `dev'.
 * `l' is the level of indirection.
 */
indfree(dev, b, l)
dev_t dev;
daddr_t b;
register unsigned l;
{
	register int i;
	register BUF *bp;
	daddr_t * dp;
	daddr_t b1;

	if (b == 0)
		return;
	if (l-->0 && (bp=bread(dev, b, 1))!=NULL) {
		i = NBN;
		while (i-- > 0) {
			dp = FP_OFF(bp->b_faddr);

			if ((b1 = dp[i]) == 0)
				continue;
			candaddr(b1);
			if (l == 0)
				bfree(dev, b1);
			else
				indfree(dev, b1, l);
		}
		brelease(bp);
	}
	bfree(dev, b);
}

/*
 * Allocate a block from the filesystem mounted of device `dev'.
 */
daddr_t
balloc(dev)
dev_t dev;
{
	register struct filsys *sbp;
	register struct fblk *fbp;
	register daddr_t b;
	register BUF *bp;
	register MOUNT *mp;

	if ((mp=getment(dev, 1)) == NULL)
		return (0);
	lock(mp->m_flock);
	sbp = &mp->m_super;
	if (sbp->s_nfree == 0) {
enospc:
		sbp->s_nfree = 0;
		devmsg(dev, "Out of space");
		u.u_error = ENOSPC;
		b = 0;
	} else {
		sbp->s_fmod = 1;
		if ((b=sbp->s_free[--sbp->s_nfree]) == 0)
			goto enospc;
		if (sbp->s_nfree == 0) {
			if (b >= sbp->s_fsize
			 || b < sbp->s_isize
			 || (bp = bread(dev, b, 1)) == NULL) {
ebadflist:
				devmsg(dev, "Bad free list");
				goto enospc;
			}
			fbp = FP_OFF(bp->b_faddr);
			sbp->s_nfree = fbp->df_nfree;
			canshort(sbp->s_nfree);
			if ((unsigned)sbp->s_nfree > NICFREE)
				goto ebadflist;
			kkcopy(fbp->df_free, sbp->s_free, sizeof(sbp->s_free));
			canndaddr(sbp->s_free, sbp->s_nfree);
			brelease(bp);
		}
		--sbp->s_tfree;
		if (b >= sbp->s_fsize || b < sbp->s_isize)
			goto ebadflist;
	}
	unlock(mp->m_flock);
	return (b);
}

/*
 * Free the block `b' on the device `dev'.
 */
bfree(dev, b)
dev_t dev;
daddr_t b;
{
	register struct filsys *sbp;
	register struct fblk *fbp;
	register BUF *bp;
	register MOUNT *mp;

	if ((mp=getment(dev, 1)) == NULL)
		return;
	sbp = &mp->m_super;
	if (b>=sbp->s_fsize || b<sbp->s_isize) {
		devmsg(dev, "Bad block %u (free)", (unsigned)b);
		return;
	}
	lock(mp->m_flock);
	if (sbp->s_nfree == 0 || sbp->s_nfree == NICFREE) {
		bp = bclaim(dev, b);
		fbp = FP_OFF(bp->b_faddr);
		kclear(fbp, BSIZE);
		fbp->df_nfree = sbp->s_nfree;
		canshort(fbp->df_nfree);
		kkcopy(sbp->s_free, fbp->df_free, sizeof(fbp->df_free));
		canndaddr(fbp->df_free, sbp->s_nfree);
		bp->b_flag |= BFMOD;
		brelease(bp);
		sbp->s_nfree = 0;
	}
	sbp->s_free[sbp->s_nfree++] = b;
	sbp->s_tfree++;
	sbp->s_fmod = 1;
	unlock(mp->m_flock);
}

/*
 * Determine if the given block is bad.
 */
bad(dev, b)
dev_t dev;
daddr_t b;
{
	register INODE *ip;
	register BUF *bp;
	register int i;
	register int m;
	register int n;
	daddr_t l;

	if ((ip=iattach(dev, 1)) == NULL)
		panic("bad()");
	n = blockn(ip->i_size);
	if ((m=n) > ND)
		m = ND;
	for (i=0; i<m; i++) {
		--n;
		if (b == ip->i_a.i_addr[i]) {
			idetach(ip);
			return (1);
		}
	}
	l = ip->i_a.i_addr[ND];
	idetach(ip);
	if (n == 0)
		return (0);
	if ((bp=bread(dev, l, 1)) == NULL)
		return (0);
	if ((m=n) > NBN)
		m = NBN;
	for (i=0; i<m; i++) {
		l = ((daddr_t *)bp)[i];
		candaddr(l);
		if (b == l) {
			brelease(bp);
			return (1);
		}
	}
	brelease(bp);
	return (0);
}

/*
 * Canonize `n' disk addresses.
 */
canndaddr(dp, n)
register daddr_t *dp;
register int n;
{
	while (n--) {
		candaddr(*dp);
		dp++;
	}
}

/*
 * Write out an accounting record.
 */
setacct()
{
	register PROC *pp;
	struct acct acct;
	IO acctio;

	if (acctip == NULL)
		return;
	pp = SELF;
	kkcopy(u.u_comm, acct.ac_comm, 10);
	acct.ac_utime = ltoc(pp->p_utime);
	acct.ac_stime = ltoc(pp->p_stime);
	acct.ac_etime = ltoc(timer.t_time - u.u_btime);
	acct.ac_btime = u.u_btime;
	acct.ac_uid = u.u_uid;
	acct.ac_gid = u.u_gid;
	acct.ac_mem = 0;
	acct.ac_io = ltoc(u.u_block);
	acct.ac_tty = pp->p_ttdev;
	acct.ac_flag = u.u_flag;
	ilock(acctip);
	acctio.io_seek = acctip->i_size;
	acctio.io_ioc  = sizeof (acct);
	acctio.io_base = &acct;
	acctio.io_seg  = IOSYS;
	acctio.io_flag = 0;
	iwrite(acctip, &acctio);
	iunlock(acctip);
	u.u_error = 0;
}
0707070064030103331006440000030000030000011777770507310727300004100000022066/newbits/kernel/USRSRC/coh/fs3.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Filesystem (I/O).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:06  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:13:54	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/fs3.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 86/02/01	Allan Cornish
 * Added code to fwrite() to avoid needless writing of pipe blocks.
 * Throughput on 6 Mhz AT rose from 30 Kbytes/sec to 79 Kbytes/sec.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/mount.h>
#include <sys/io.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/uproc.h>
#include <sys/stat.h>

/*
 * Given an inode, open it.
 */
iopen(ip, mode)
register INODE *ip;
{
	register int type;

	type = ip->i_mode & IFMT;
	switch (type) {
	case IFCHR:
	case IFBLK:
		iunlock(ip);
		dopen(ip->i_a.i_rdev, mode, type==IFCHR ? DFCHR : DFBLK);
		ilock(ip);
		break;
	case IFDIR:
		if ((mode&IPW) != 0) {
			if (super() == 0)
				return;
			if (mode == IPW) {
				u.u_error = EISDIR;
				return;
			}
		}
		break;
	case IFPIPE:
		popen(ip, mode);
		break;
	}
}

/*
 * Given an inode, close it.
 */
iclose(ip)
register INODE *ip;
{
	ilock(ip);
	switch (ip->i_mode&IFMT) {
	case IFBLK:
		bflush(ip->i_a.i_rdev);
	case IFCHR:
		iunlock(ip);
		dclose(ip->i_a.i_rdev);
		ilock(ip);
		break;
	case IFPIPE:
		pclose(ip);
		break;
	}
	idetach(ip);
}

/*
 * Read from a file described by an inode and an io strucuture.
 */
iread(ip, iop)
register INODE *ip;
register IO *iop;
{
	if (iop->io_ioc == 0)
		return;
	switch (ip->i_mode&IFMT) {
	case IFCHR:
		dread(ip->i_a.i_rdev, iop);
		break;
	case IFBLK:
	case IFREG:
	case IFDIR:
		fread(ip, iop);
		break;
	case IFPIPE:
		pread(ip, iop);
		break;
	default:
		u.u_error = ENXIO;
		break;
	}
}

/*
 * Write to a file described by an inode and io structure.
 */
iwrite(ip, iop)
register INODE *ip;
register IO *iop;
{
	imod(ip);	/* write - mtime */
	icrt(ip);	/* write - ctime */
	if (iop->io_ioc == 0)
		return;
	switch (ip->i_mode&IFMT) {
	case IFCHR:
		dwrite(ip->i_a.i_rdev, iop);
		break;
	case IFBLK:
		fwrite(ip, iop);
		break;
	case IFREG:
	case IFDIR:
		if (getment(ip->i_dev, 1) == NULL)
			return;
		fwrite(ip, iop);
		break;
	case IFPIPE:
		pwrite(ip, iop);
		break;
	default:
		u.u_error = ENXIO;
		break;
	}
}

/*
 * Read from a regular or block special file.
 */
fread(ip, iop)
INODE *ip;
register IO *iop;
{
#ifdef TINY
	register unsigned n;
	register fsize_t res;
	register unsigned off;
	register daddr_t lbn;
	register BUF *bp;
	register int blk;

	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	blk = (ip->i_mode&IFMT) == IFBLK;
	res = ip->i_size - iop->io_seek;
	if (blk!=0 || res>iop->io_ioc)
		res = iop->io_ioc;
	while (res > 0) {
		bp = blk ? bread(ip->i_a.i_rdev, lbn, 1) : vread(ip, lbn);
		if (bp == NULL)
			return;
		n = BSIZE - off;
		if (n > res)
			n = res;
		iowrite(iop, FP_OFF(bp->b_faddr)+off, n);
		brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		res -= n;
	}
/*
 * Start of daring read ahead code.
 * Altered to not read ahead on block devices
 * due to 20% time penalty incurred for such.
 */
#if 0
	if ( ! blk) {
		lbn = vmap(ip, lbn);
		if (lbn > 0)
			bread(ip->i_dev, lbn, 0);
	}
#endif
/*
 * End of daring read ahead code.
 */
#else
	register unsigned n;
	register unsigned i;
	register fsize_t res;
	register unsigned off;
	register dev_t dev;
	register daddr_t lbn;
	register daddr_t pbn;
	register daddr_t abn;
	register daddr_t zbn;
	register BUF *bp;
	register int blk;
	daddr_t list[NEXREAD];

	if ((ip->i_mode&IFMT) == IFBLK) {
		blk = 1;
		dev = ip->i_a.i_rdev;
	} else {
		blk = 0;
		dev = ip->i_dev;
	}
	abn = 0;
	zbn = 0;
	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	res = ip->i_size - iop->io_seek;
	if (blk!=0 || res>iop->io_ioc)
		res = iop->io_ioc;
	if (res <= 0)
		return;
	if (res+off <= BSIZE) {
		bp = blk ? bread(dev, lbn, 1) : vread(ip, lbn);
		if (bp == NULL)
			return;
		iowrite(iop, FP_OFF(bp->b_faddr)+off, (unsigned)res);
		brelease(bp);
		return;
	}
	while (res > 0) {
		if (lbn >= zbn) {
			if ((n=blockn(res+BSIZE-1)) > NEXREAD)
				n = NEXREAD;
			if (n <= 0)
				n = 1;
			abn = lbn;
			for (i=0, zbn=lbn; i<n; i++, zbn++) {
				if (blk != 0)
					pbn = zbn;
				else {
					if ((pbn=vmap(ip, zbn)) < 0)
						return;
					if (pbn == 0) {
						list[i] = -1;
						continue;
					}
				}
				list[i] = pbn;
				bread(dev, pbn, 0);
			}
		}
		if ((pbn=list[lbn-abn]) < 0) {
			bp = bclaim(NODEV, (daddr_t)0);
			kclear(FP_OFF(bp->b_faddr), BSIZE);
		} else {
			if ((bp=bread(dev, pbn, 1)) == NULL)
				return;
		}
		n = BSIZE - off;
		n = res>n ? n : res;
		iowrite(iop, FP_OFF(bp->b_faddr)+off, n);
		brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		res -= n;
	}
#endif
}

/*
 * Write to a regular or block special file.
 */
fwrite(ip, iop)
INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned off;
	register daddr_t lbn;
	register BUF *bp;
	register int blk;
	register int com;

	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	blk = (ip->i_mode&IFMT) == IFBLK;
	while (iop->io_ioc > 0) {
		n = BSIZE - off;
		n = iop->io_ioc>n ? n : iop->io_ioc;
		com = off==0 && n==BSIZE;
		if (blk == 0)
			bp = aread(ip, lbn, com);
		else {
			if (com)
				bp = bclaim(ip->i_a.i_rdev, lbn);
			else
				bp = bread(ip->i_a.i_rdev, lbn, 1);
		}
		if (bp == NULL)
			return;
		ioread(iop, FP_OFF(bp->b_faddr)+off, n);
		bp->b_flag |= BFMOD;
		if (com && ((ip->i_mode&IFMT) != IFPIPE) )
			bwrite(bp, 0);
		else
			brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		if ((iop->io_seek+=n) > ip->i_size)
			if (blk == 0)
				ip->i_size = iop->io_seek;
	}
}

/*
 * Given an inode pointer, read the requested virtual block and return
 * a buffer with the data.
 */
BUF *
vread(ip, lb)
register INODE *ip;
daddr_t lb;
{
	register daddr_t pb;
	register BUF *bp;

	if ((pb=vmap(ip, lb)) < 0)
		return (NULL);
	if (pb != 0)
		return (bread(ip->i_dev, pb, 1));
	bp = bclaim(NODEV, (daddr_t)0);
	kclear(FP_OFF(bp->b_faddr), BSIZE);
	return (bp);
}

/*
 * Convert the given virtual block to a physical block for the given inode.
 * If the block does not map onto a physical block because the file is sparse
 * but it does exist, 0 is returned.  If an error is encountered, -1 is
 * returned.
 */
daddr_t
vmap(ip, lb)
register INODE *ip;
daddr_t lb;
{
	register BUF *bp;
	register int *lp;
	daddr_t * dp;
	daddr_t pb;
	int list[1+NI];

	if ((lp=lmap(lb, list)) == NULL)
		return (-1);
	pb = ip->i_a.i_addr[*--lp];
	for (;;) {
		if (pb==0 || lp==list)
			return (pb);
		if ((bp=bread(ip->i_dev, pb, 1)) == NULL)
			return (0);
		dp = FP_OFF(bp->b_faddr);
		pb = dp[*--lp];
		brelease(bp);
		candaddr(pb);
	}
}

/*
 * Given an inode pointer, read the requested virtual block and return a
 * buffer with the data.  In sparse files, the necessary blocks are allocated.
 * If the flag, `fflag' is set, the final buffer is just claimed rather than
 * read as we are going to change it's contents completely.
 */
BUF *
aread(ip, lb, fflag)
register INODE *ip;
daddr_t lb;
{
	register BUF *bp;
	register int *lp;
	register dev_t dev;
	register int l;
	register int aflag;
	register int lflag;
	daddr_t * dp;
	daddr_t pb;
	int list[1+NI];

	if ((lp=lmap(lb, list)) == NULL)
		return (NULL);
	aflag = 0;
	dev = ip->i_dev;
	pb = ip->i_a.i_addr[l=*--lp];
	if (pb == 0) {
		aflag = 1;
		if ((pb=balloc(dev)) == 0)
			return (NULL);
		ip->i_a.i_addr[l] = pb;
	}
	for (;;) {
		lflag = lp==list;
		if (aflag==0  &&  (fflag==0 || lflag==0)) {
			if ((bp=bread(dev, pb, 1)) == NULL)
				return (NULL);
		} else {
			bp = bclaim(dev, pb);
			kclear(FP_OFF(bp->b_faddr), BSIZE);
			bp->b_flag |= BFMOD;
		}
		if (lflag)
			return (bp);

		aflag = 0;
		dp = FP_OFF(bp->b_faddr);
		pb = dp[l=*--lp];
		candaddr(pb);
		if (pb == 0) {
			aflag = 1;
			if ((pb=balloc(dev)) == 0) {
				brelease(bp);
				return (NULL);
			}
			dp[l] = pb;
			candaddr( dp[l] );
			bp->b_flag |= BFMOD;
		}
		brelease(bp);
	}
}

/*
 * Given a block number, `b', store the offsets for the indirect blocks
 * backwards in the array, `lp', and return a pointer just after the
 * position where the first offset is stored.
 */
int *
lmap(b, lp)
register daddr_t b;
register int *lp;
{
	register int n;

	if (b < ND) {
		*lp++ = b;
		return (lp);
	}
	b -= ND;
	n = NI;
	do {
		if (n-- == 0) {
			u.u_error = EFBIG;
			return (NULL);
		}
		*lp = nbnrem(b);
		++lp;
		b = nbndiv(b);
	} while (b--);
	*lp++ = ND+NI-1-n;
	return (lp);
}
0707070064030103321006440000030000030000011777770507310727500004200000003553/newbits/kernel/USRSRC/coh/main.c/*
 * Coherent.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:15  bin
 * update prov by hal
 * 
 * 
 * Revision 1.2	88/06/29  12:00:29 	src
 * Real/Protected mode status now printed during boot sequence.
 * Three part serial numbers now supported, moved to optional fourth line.
 * 
 * Revision 1.1	88/03/24  16:13:58	src
 * Initial revision
 * 
 * 87/04/09	Allan Cornish		/usr/src/sys/coh/main.c
 * Serial numbers changed to support group.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/main.c
 * Copyright notice revised to include 1987.
 */
#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <sys/uproc.h>

#ifndef VERSION		/* This should be specified at compile time */
#define VERSION	"..."
#endif

unsigned long	_entry = 0;		/* really the serial number */
unsigned long	__ = 0;			/* really the serial number also */

/*
 * Initialise various things.  When we return we will return to user mode.
 */
char version[] = VERSION;
char copyright[] = "\
Copyright (c) 1982, 1991 by Mark Williams Company\n\
";

main()
{
	register SEG *sp;
	extern int realmode;	/* real addressing mode - as2.s */

	u.u_error = 0;
	bufinit();
	cltinit();
	pcsinit();
	seginit();
	devinit();
	printf("\Mark Williams COHERENT Version %s - %s Mode (mem=%u Kbytes)\n",
		version, (realmode ? "Real" : "Protected"), msize );
	printf(copyright);

	if ( _entry ) {
		printf("Serial Number ");
		printf("%U\n", _entry);
	}

	/*
	 * Verify correct serial number
	 */
	if (_entry != __)
		panic("Verification error - call Mark Williams Company at 1-800-MARK-WMS\n");

	/*
	 * Turn on clock, start off processes, mount root device
	 * and return.
	 */
	batflag = 1;
	if ((sp=salloc((fsize_t)UPASIZE, SFNCLR|SFNSWP)) == NULL)
		panic("Cannot allocate user area");
	if ((iprocp=process(idle))==NULL || (eprocp=process(NULL))==NULL)
		panic("Cannot create process");
	eveinit(sp);
	fsminit();
}
0707070064030103311006440000030000030000011777770507310727600004200000004403/newbits/kernel/USRSRC/coh/misc.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Miscellaneous routines.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:19  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:01	src
 * Initial revision
 * 
 * 87/05/08	Allan Cornish		/usr/src/sys/coh/misc.c
 * System code and data segments no longer reported in panic messages.
 *
 * 87/02/17	Allan Cornish		/usr/src/sys/coh/misc.c
 * Panic message now includes system code and data segments.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <errno.h>
#include <sys/ino.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Copy `n' bytes from `bp1' to `bp2'.
 */
kkcopy(bp1, bp2, n)
register char *bp1;
register char *bp2;
unsigned n;
{
	register unsigned n1;

	n1 = n;
	if (n1) {
		do {
			*bp2++ = *bp1++;
		} while (--n1);
	}
	return (n);
}

/*
 * Clear the next `n' bytes starting at `bp'.
 */
kclear(bp, n)
register char *bp;
register unsigned n;
{
	if (n) {
		do {
			*bp++ = 0;
		} while (--n);
	}
}

/*
 * Make sure we are the super user.
 */
super()
{
	if (u.u_uid) {
		u.u_error = EPERM;
		return (0);
	}
	u.u_flag |= ASU;
	return (1);
}

/*
 * Make sure we are the gived `uid' or the super user.
 */
owner(uid)
{
	if (u.u_uid == uid)
		return (1);
	if (u.u_uid == 0) {
		u.u_flag |= ASU;
		return (1);
	}
	u.u_error = EPERM;
	return (0);
}

/*
 * Panic.
 */
panic(a1)
char *a1;
{
	static panflag;

	if (panflag++ == 0) {
		printf("Panic: %r", &a1);
		putchar('\n');
		usync();
	}
	halt();
	--panflag;
}

/*
 * Print a message from a device driver.
 */
devmsg(dev, a1)
dev_t dev;
char *a1;
{
	printf("(%d,%d): %r", major(dev), minor(dev), &a1);
	printf("\n");
}
0707070064030103301006440000030000030000011777770507310727700004200000004536/newbits/kernel/USRSRC/coh/null.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Null and memory driver.
 *  Minor device 0 is /dev/null
 *  Minor device 1 is physical memory
 *  Minor device 2 is kernel data
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:24  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:04	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Functions for configuration.
 */
int	nlread();
int	nlwrite();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON nlcon ={
	DFCHR,				/* Flags */
	0,				/* Major index */
	nulldev,			/* Open */
	nulldev,			/* Close */
	nulldev,			/* Block */
	nlread,				/* Read */
	nlwrite,			/* Write */
	nonedev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	nulldev,			/* Load */
	nulldev				/* Unload */
};

/*
 * Null/memory read routine.
 */
nlread(dev, iop)
dev_t dev;
register IO *iop;
{
	register unsigned n;

	switch (minor(dev)) {
	case 0:
		n = 0;
		break;

	case 1:
		n = pucopy((long)iop->io_seek, iop->io_base, iop->io_ioc);
		break;

	case 2:
		n = kucopy((vaddr_t)iop->io_seek, iop->io_base, iop->io_ioc);
		break;

	default:
		u.u_error = ENXIO;
		return;
	}
	iop->io_ioc -= n;
	if (u.u_error == EFAULT)
		u.u_error = 0;
}

/*
 * Null/memory write routine.
 */
nlwrite(dev, iop)
dev_t dev;
register IO *iop;
{
	register unsigned n;

	switch (minor(dev)) {
	case 0:
		n = iop->io_ioc;
		break;

	case 1:
		n = upcopy(iop->io_base, (long)iop->io_seek, iop->io_ioc);
		break;

	case 2:
		n = ukcopy(iop->io_base, (vaddr_t)iop->io_seek, iop->io_ioc);
		break;

	default:
		u.u_error = ENXIO;
		return;
	}
	iop->io_ioc -= n;
	if (u.u_error == EFAULT)
		u.u_error = 0;
}
0707070064030103271006440000030000030000011777770507310727700004200000010753/newbits/kernel/USRSRC/coh/pipe.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Pipes.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:27  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:07	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/pipe.c
 * Added check for non-blocking read and write if (io_flag & IPNDLY) set.
 * Eliminated use of i_a inode field since now included in inode macros.
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Create and return a locked pipe inode.  This is called from the
 * pipe system call.
 */
INODE *
pmake(mode)
{
	register INODE *ip;

	if ((ip=ialloc(pipedev, IFPIPE|mode)) != NULL) {
		iclear(ip);
		ip->i_pnc = 0;
		ip->i_prx = 0;
		ip->i_pwx = 0;
	}
	return (ip);
}

/*
 * Open a pipe given the inode pointer.
 */
popen(ip, mode)
{
}

/*
 * Close a pipe inode.
 */
pclose(ip)
register INODE *ip;
{
	if (ip->i_refc == 2) {
		pevent(ip);
		ip->i_flag |= IFEOF;
	}
}

/*
 * Only one end of the pipe is going to be left.
 */
pevent(ip)
register INODE *ip;
{
	if ((ip->i_flag&IFWFR) != 0) {
		ip->i_flag &= ~IFWFR;
		wakeup((char *)&ip->i_pwx);
	}
	if ((ip->i_flag&IFWFW) != 0) {
		ip->i_flag &= ~IFWFW;
		wakeup((char *)&ip->i_prx);
	}
}

/*
 * Read from a pipe.  The given inode is locked.
 */
pread(ip, iop)
register INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned ioc;

	while (ip->i_pnc == 0) {

		/*
		 * Logical End of File.
		 */
		if ((ip->i_flag&IFEOF) != 0) {
			ip->i_flag &= ~IFEOF;
			break;
		}

		/*
		 * Nobody left to write.
		 */
		if (ip->i_nlink==0 && ip->i_refc<2)
			break;

		/*
		 * Non-blocking read.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			return;
		}

		/*
		 * Wait for pipe data.
		 */
		ip->i_flag |= IFWFW;
		iunlock(ip);
		sleep((char *)&ip->i_prx, CVPIPE, IVPIPE, SVPIPE);
		ilock(ip);
	}

	/*
	 * Clear EOF flag.
	 */
	if ((ip->i_flag&IFEOF)!=0 && ip->i_pnc==0)
		ip->i_flag &= ~IFEOF;

	ioc = iop->io_ioc;
	while (u.u_error==0 && ioc>0 && ip->i_pnc>0) {

		/*
		 * Calculate length of data to be read.
		 */
		if ((n=PIPSIZE-ip->i_prx) > ioc)
			n = ioc;
		if (n > ip->i_pnc)
			n = ip->i_pnc;

		/*
		 * Read data.
		 */
		iop->io_ioc = n;
		iop->io_seek = ip->i_prx;
		fread(ip, iop);
		n -= iop->io_ioc;
		if ((ip->i_prx+=n) == PIPSIZE)
			ip->i_prx = 0;
		ip->i_pnc -= n;
		ioc -= n;
	}
	iop->io_ioc = ioc;

	/*
	 * Wake processes waiting to write.
	 */
	if ((ip->i_flag&IFWFR)!=0 && ip->i_pnc<PIPSIZE) {
		ip->i_flag &= ~IFWFR;
		wakeup((char *)&ip->i_pwx);
	}
}

/*
 * Write to a pipe.  The given inode is locked.
 */
pwrite(ip, iop)
register INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned ioc;

	ioc = iop->io_ioc;
	while (u.u_error==0 && ioc>0) {

		/*
		 * Nobody left to read.
		 */
		if ( (ip->i_refc < 2) && (ip->i_nlink == 0) ) {
			u.u_error = EPIPE;
			sendsig(SIGPIPE, SELF);
			return;
		}

		/*
		 * Calculate free space in pipe.
		 */
		if ( (n=PIPSIZE-ip->i_pwx) > ioc )
			n = ioc;
		if (n > PIPSIZE-ip->i_pnc)
			n = PIPSIZE - ip->i_pnc;

		/*
		 * Non-blocking write.
		 */
		if ( iop->io_flag & IONDLY ) {
			if ( (n != ioc) || (ip->i_flag & IFEOF) ) {
				u.u_error = EAGAIN;
				return;
			}
		}

		/*
		 * Insufficent space or EOF still pending.
		 */
		if (n==0 || (ip->i_flag&IFEOF)!=0) {
			ip->i_flag |= IFWFR;
			iunlock(ip);
			sleep((char *)&ip->i_pwx, CVPIPE, IVPIPE, SVPIPE);
			ilock(ip);
			continue;
		}
		iop->io_ioc = n;
		iop->io_seek = ip->i_pwx;
		fwrite(ip, iop);
		n -= iop->io_ioc;
		if ((ip->i_pwx+=n) == PIPSIZE)
			ip->i_pwx = 0;
		ip->i_pnc += n;
		ioc -= n;

		/*
		 * Wait processes waiting to read.
		 */
		if ((ip->i_flag&IFWFW) && ip->i_pnc>0) {
			ip->i_flag &= ~IFWFW;
			wakeup((char *)&ip->i_prx);
		}
	}
	iop->io_ioc = ioc;
}
0707070064030103261006440000030000030000011777770507310730000004200000010447/newbits/kernel/USRSRC/coh/poll.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1986
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * [Stream] Polling.
 *
 *	void pollinit( ) -- allocate polling buffers
 *	int pollopen(qp) -- enable polling  by current process  on given queue
 *	int pollwake(qp) -- wake all processes waiting for poll on given queue
 *	int pollexit(  ) -- terminate all polls enabled by current process
 *	event_t * ep;
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:32  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:10	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/poll.c
 * Ported to Coherent from RTX.
 */

#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/uproc.h>

/*
 * Patchable data.
 */
int	NPOLL  = 0;

/*
 * Private data.
 */
static	event_t	* efreep;

/**
 *
 * event_t *
 * pollinit()		-- allocate event buffers.
 */
event_t *
pollinit()
{
	register event_t * ep;
	register event_t * ap;
	static int first = 1;

	/*
	 * If dynamically growing event pool is specified [NPOLL == 0],
	 * try to allocate an additional cluster of 32 on each call.
	 */
	if ( NPOLL == 0 ) {
		if ( ep = kalloc( 32 * sizeof(event_t) ) )
			ap = ep + 32;
	}

	/*
	 * If statically sized event pool is specified [NPOLL != 0],
	 * try to allocate the pool on the first call.
	 */
	else if ( first ) {
		first = 0;
		if ( ep = kalloc( NPOLL * sizeof(event_t) ) )
			ap = ep + NPOLL;
	}

	/*
	 * If event cluster was allocated, insert into free event queue.
	 */
	if ( ep ) {
		do {
			ep->e_pnext = efreep;
			efreep = ep;
		} while ( ++ep < ap );
	}

	return efreep;
}

/**
 *
 * int
 * pollopen(qp) -- enable polling by current process on given event queue
 * event_t * qp;
 */
pollopen( qp )
register event_t * qp;
{
	register event_t * ep;

	/*
	 * Initialize device queue if required.
	 */
	if ( qp->e_dnext == 0 )
		qp->e_dnext = qp->e_dlast = qp;

	/*
	 * Obtain a free event buffer, or return.
	 */
	if ( ((ep = efreep) == 0) && ((ep = pollinit()) == 0) ) {
		printf("out of poll buffers\n");
		return;
	}

	/*
	 * Remove event buffer from free queue.
	 */
	efreep = ep->e_pnext;

	/*
	 * Record process pointer in event buffer.
	 */
	ep->e_procp = cprocp;

	/*
	 * Insert event at head of process event singularly-linked queue.
	 */
	ep->e_pnext = cprocp->p_polls;
	cprocp->p_polls = ep;

	/*
	 * Insert event at tail of circularly-linked device queue.
	 * This ensures that processes are first-in first-out.
	 */
	ep->e_dnext  = qp;
	(ep->e_dlast = qp->e_dlast)->e_dnext = ep;
	qp->e_dlast  = ep;

	/*
	 * Record last process to enable polling on device.
	 */
	qp->e_procp = cprocp;
}

/**
 *
 * int
 * pollwake( qp ) -- wake all processes waiting for poll on given queue
 * event_t * qp;
 */
pollwake( qp )
event_t * qp;
{
	register event_t * ep = qp;
	register PROC    * pp;

	/*
	 * Clear device process pointer, indicating poll completed.
	 * NOTE: interrupt handlers may have already cleared it.
	 */
	qp->e_procp = 0;

	if ( ep = qp->e_dnext ) {

		/*
		 * Service circularly-linked polls on device queue.
		 */
		while ( ep != qp ) {
			/*
			 * Wake process if it is sleeping.
			 */
			if ( (pp = ep->e_procp) && (pp->p_state == PSSLEEP) )
				wakeup( &pp->p_polls );

			ep = ep->e_dnext;
		}
	}
}

/**
 *
 * int
 * pollexit() -- terminate all polls opened by current process
 */
int
pollexit()
{
	register PROC    * pp = cprocp;
	register event_t * ep;

	/*
	 * Service all polling event buffers enabled by current process.
	 */
	while ( ep = pp->p_polls ) {

		/*
		 * Remove event buffer from circularly-linked device queue.
		 */
		(ep->e_dnext->e_dlast = ep->e_dlast)->e_dnext = ep->e_dnext;

		/*
		 * Remove event buffer from singularly-linked process queue.
		 */
		pp->p_polls = ep->e_pnext;

		/*
		 * Insert event buffer at head of free event buffer queue.
		 */
		ep->e_pnext = efreep;
		efreep = ep;
	}
}
0707070064030103251006440000030000030000011777770507310730100004400000005260/newbits/kernel/USRSRC/coh/printf.c/*
 * Coherent.
 * Print formatted.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:37  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:13	src
 * Initial revision
 * 
 * 87/09/20	Allan Cornish		/usr/src/sys/coh/printf.c
 * %U now correctly displays in base 10 rather than base 16.
 *
 * 86/12/16	Allan Cornish		/usr/src/sys/coh/printf.c
 * Added '%D' and '%X options to printf().
 */
#include <sys/coherent.h>

/*
 * For indirecting and incrementing argument pointer.
 */
#define ind(p, t)	(*((t *) p))
#define inc(t1, t2)	((sizeof(t2 *)+sizeof(t1)-1) / sizeof(t1))

/*
 * Table for printing out digits.
 */
char digtab[] ={
	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
	'8',	'9',	'A',	'B',	'C',	'D',	'E',	'F'
};

/*
 * A simple printf.
 */
printf(fp, a1)
register char *fp;
{
	char * cp;
	register int c;
	register unsigned *ap;
	int lflag;

	ap = (char *)&a1;
	for (;;) {
		while ((c=*fp++) != '%') {
			if (c == '\0')
				return;
			putchar(c);
		}

		lflag = 0;
		if ( *fp == 'l' ) {
			lflag = 1;
			fp++;
		}

		switch ( c = *fp++ ) {

		case 'c':
			putchar(*ap++);
			continue;

		case 'd':
			if ( lflag == 0 ) {
				if ( ((int)(*ap)) < 0 ) {
					putchar('-');
					printn( -((long) ((int)(*ap))), 10 );
				}
				else
					printn( ((long)(*ap)), 10 );
				ap++;
				continue;
			}
			/* fall through */
		case 'D':
			if ( *((long *)(ap)) < 0 ) {
				putchar('-');
				printn( - *((long *)(ap)), 10 );
			}
			else
				printn(   *((long *)(ap)), 10 );

			((long *)(ap))++;
			continue;

		case 'o':
			if ( lflag == 0 ) {
				printn( ((long)(*ap)), 8);
				ap++;
				continue;
			}
			/* fall through */
		case 'O':
			printf( *((long *)(ap)), 8 );
			((long *)(ap))++;
			continue;

		case 'r':
			ap = *((int **) ap);
			fp = ind(ap, char *);
			ap += inc(int, char *);
			continue;

		case 's':
			cp = ind(ap, char *);
			ap += inc(int, char *);
			while ((c=*cp++) != '\0')
				putchar(c);
			continue;

		case 'x':
			if ( lflag == 0 ) {
				printn( ((long)(*ap)), 16 );
				ap++;
				continue;
			}
			/* fall through */
		case 'X':
			printn( *((long *)(ap)), 16 );
			((long *)(ap))++;
			continue;

		case 'u':
			if ( lflag == 0 ) {
				printn( ((long)(*ap)), 10);
				ap++;
				continue;
			}
			/* fall through */
		case 'U':
			printn( *((long *)(ap)), 10 );
			((long *)(ap))++;
			continue;

		case 'p':
			if (sizeof(char *) > sizeof(int)) {
				printn( ((long)(*ap)), 16);
				putchar(':');
				ap++;
			}
			printn( ((long)(*ap)), 16);
			ap++;
			continue;

		default:
			putchar(c);
			continue;
		}
	}
}

/*
 * Print out the unsigned long `v' in the base `b'.
 */
printn( v, b )
unsigned long v;
{
	unsigned long n;

	if ((n=v/b) != 0)
		printn(n, b);

	putchar(digtab[v%b]);
}
0707070064030103241006440000030000030000011777770507310730200004200000026363/newbits/kernel/USRSRC/coh/proc.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Process handling and scheduling.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:40  bin
 * update prov by hal
 * 
 * 
 * Revision 1.2	88/08/05  15:30:01	src
 * pfork() made more rigorous, supports loadable driver forks, etc.
 * lock/unlock more efficient, since know wakeup is synchronous.
 * 
 * Revision 1.1	88/03/24  16:14:16	src
 * Initial revision
 * 
 * 88/03/10	Allan Cornish		/usr/src/sys/coh/proc.c
 * Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
 * These partial fixes will be removed once all CPU's are replaced.
 *
 * 88/01/21	Allan Cornish		/usr/src/sys/coh/proc.c
 * Race condition caused by pexit() calling sfree() on the user-area
 * when the segmentation gate is locked is now prevented.
 * Release of the user area now deferred until relproc() invoked by uwait().
 *
 * 87/11/13	Allan Cornish		/usr/src/sys/coh/proc.c
 * pexit() now sets uasa to 0 before dispatching processor.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/proc.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/coh/proc.c
 * pexit() now cancels poll/alarm timed functions before terminating.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/proc.c
 * pexit() now wakes the swapper before terminating.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Initialisation.
 * Set up the hash table queues.
 */
pcsinit()
{
	register PROC *pp;
	register PLINK *lp;

	pp = &procq;
	SELF = pp;
	procq.p_nforw = pp;
	procq.p_nback = pp;
	procq.p_lforw = pp;
	procq.p_lback = pp;
	for (lp=&linkq[0]; lp<&linkq[NHPLINK]; lp++) {
		lp->p_lforw = lp;
		lp->p_lback = lp;
	}
}

/*
 * Initiate a process.  `f' is a kernel function that is associated with
 * the process.
 */
PROC *
process(f)
int (*f)();
{
	register PROC *pp1;
	register PROC *pp;
	register SEG *sp;
	MCON mcon;

	if ((pp=kalloc(sizeof(PROC))) == NULL)
		return (NULL);

	pp->p_flags = PFCORE;
	pp->p_state = PSRUN;
	pp->p_ttdev = NODEV;

	if (f != NULL) {
		pp->p_flags |= PFKERN;
		sp = salloc((fsize_t)UPASIZE, SFSYST|SFHIGH|SFNSWP);
		if (sp == NULL) {
			kfree(pp);
			return (NULL);
		}
		pp->p_segp[SIUSERP] = sp;
		msetsys( &mcon, f, FP_SEL(sp->s_faddr) );
		kfcopy(	(char *)&mcon,
			sp->s_faddr + offset(uproc, u_syscon),
			sizeof(mcon) );
	}
	lock(pnxgate);
next:
	pp->p_pid = cpid++;
	if (cpid >= NPID)
		cpid = 2;
	pp1 = &procq;
	while ((pp1=pp1->p_nforw) != &procq) {
		if (pp1->p_pid < pp->p_pid)
			break;
		if (pp1->p_pid == pp->p_pid)
			goto next;
	}
	pp->p_nback = pp1->p_nback;
	pp1->p_nback->p_nforw = pp;
	pp->p_nforw = pp1;
	pp1->p_nback = pp;
	unlock(pnxgate);
	return (pp);
}

/*
 * Remove a process from the next queue and release and space.
 */
relproc(pp)
register PROC *pp;
{
	register SEG * sp;

	/*
	 * Child process still has a user-area.
	 */
	if ( (sp = pp->p_segp[SIUSERP]) != NULL ) {

		/*
		 * Detach user-area from child process.
		 */
		pp->p_segp[SIUSERP] = NULL;

		/*
		 * Child process is swapped out.
		 */
		if ( pp->p_flags & PFSWAP )
			sp->s_lrefc++;

		/*
		 * Release child's user-area.
		 */
		sfree( sp );
	}

	/*
	 * Remove process from doubly-linked list of all processes.
	 * Release space allocated for proc structure.
	 */
	lock(pnxgate);
	pp->p_nback->p_nforw = pp->p_nforw;
	pp->p_nforw->p_nback = pp->p_nback;
	unlock(pnxgate);
	kfree(pp);
}

/*
 * Create a clone of ourselves.
 *	N.B. - consave(&mcon) returns twice; anything not initialized
 *	in automatic storage before the call to segadup() will not be
 *	initialized when the second return from consave() commences.
 */
pfork()
{
	register PROC *cpp;
	register PROC *pp;
	register int s;
	MCON mcon;

	if ((cpp=process(NULL)) == NULL) {
		u.u_error = EAGAIN;
		return;
	}

	s = sphi();	/* Make usave a null macro if unnecessary */
	usave();	/* Put the current copy of uarea into its segment */
	spl(s);

	if (segadup(cpp) == 0) {
		u.u_error = EAGAIN;
		relproc(cpp);
		return;
	}
	if ( u.u_rdir != NULL )
		u.u_rdir->i_refc++;
	if ( u.u_cdir != NULL )
		u.u_cdir->i_refc++;
	fdadupl();
	pp = SELF;
	cpp->p_uid   = pp->p_uid;
	cpp->p_ruid  = pp->p_ruid;
	cpp->p_rgid  = pp->p_rgid;
	cpp->p_ppid  = pp->p_pid;
	cpp->p_ttdev = pp->p_ttdev;
	cpp->p_group = pp->p_group;
	cpp->p_ssig  = pp->p_ssig;
	cpp->p_isig  = pp->p_isig;
	cpp->p_cval  = CVCHILD;
	cpp->p_ival  = IVCHILD;
	cpp->p_sval  = SVCHILD;
	cpp->p_rval  = RVCHILD;

	s = sphi();
	consave(&mcon);
	spl( s );

	/*
	 * Parent process.
	 */
	if ( (pp = SELF) != cpp ) {
		segfinm(cpp->p_segp[SIUSERP]);
		kfcopy( (char *)&mcon,
			cpp->p_segp[SIUSERP]->s_faddr + offset(uproc,u_syscon),
			sizeof(mcon) );
		mfixcon(cpp);
		s = sphi();
		setrun(cpp);
		spl(s);
		return( cpp->p_pid );
	}

	/*
	 * Child process.
	 */
	else {
		u.u_btime = timer.t_time;
		u.u_flag = AFORK;
		/* for (i=0; i<NUSEG; i++) done in sproto */
			/* u.u_segl[i].sr_segp = pp->p_segp[i]; ditto */
		sproto();
		segload();
		return( 0 );
	}
}

/*
 * Die.
 */
pexit(s)
{
	register PROC *pp1;
	register PROC *pp;
	register SEG  *sp;
	register int n;

	pp = SELF;

	/*
	 * Cancel alarm and poll timers [if any].
	 */
	timeout( &pp->p_alrmtim, 0, NULL, 0 );
	timeout( &pp->p_polltim, 0, NULL, 0 );

	/*
	 * Write out accounting directory and close all files associated with
	 * this process.
	 */
	setacct();
	if ( u.u_rdir )
		ldetach(u.u_rdir);
	if ( u.u_cdir )
		ldetach(u.u_cdir);
	fdaclose();

	/*
	 * Free all segments in reverse order, except for user-area.
	 */
	for ( n = NUSEG; --n > 0; ) {
		if ( (sp = pp->p_segp[n]) != NULL ) {
			pp->p_segp[n] = NULL;
			sfree( sp );
		}
	}

	/*
	 * Wakeup our parent.  If we have any children, init will become the
	 * new parent.  If there are any children we are tracing who are
	 * waiting for us, we wake them up.
	 */
	pp1 = &procq;
	while ((pp1=pp1->p_nforw) != &procq) {
		if (pp1->p_pid == pp->p_ppid) {
			if (pp1->p_state==PSSLEEP && pp1->p_event==(char *)pp1)
				wakeup((char *)pp1);
		}
		if (pp1->p_ppid == pp->p_pid) {
			pp1->p_ppid = 1;
			if (pp1->p_state == PSDEAD)
				wakeup((char *)eprocp);
			if ((pp1->p_flags&PFTRAC) != 0)
				wakeup((char *)&pts.pt_req);
		}
	}

	/*
	 * Wake up swapper if swap timer is active.
	 */
	if ( stimer.t_last != 0 )
		wakeup( (char *) &stimer );

	/*
	 * And finally mark us as dead and give up the processor forever.
	 */
	pp->p_exit = s;
	pp->p_state = PSDEAD;
	uasa = 0;
	dispatch();
}

/*
 * Sleep on the event `e'.  This gives up the processor until someone
 * wakes us up.  Since it is possible for many people to sleep on the
 * same event, the caller when awakened should make sure that what he
 * was waiting for has completed and if not, go to sleep again.  `cl'
 * is the cpu value we get to get the cpu as soon as we are woken up.
 * `sl' is the swap value we get to keep us in memory for the duration
 * of the sleep.  `sr' is the swap value that allows us to get swapped
 * in if we have been swapped out.
 */
sleep(e, cl, sl, sr)
char *e;
{
	register PROC *bp;
	register PROC *fp;
	register PROC *pp;
	register int s;

	pp = SELF;

	/*
	 * See if we have a signal awaiting.
	 */
	if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
		sphi();
		envrest(&u.u_sigenv);
	}

	/*
	 * Get ready to go to sleep and do so.
	 */
	s = sphi();
	pp->p_state = PSSLEEP;
	pp->p_event = e;
	pp->p_lctim = utimer;
	addu(pp->p_cval, cl);
	pp->p_ival = sl;
	pp->p_rval = sr;
	fp = &linkq[hash(e)];
	bp = fp->p_lback;
	pp->p_lforw = fp;
	fp->p_lback = pp;
	pp->p_lback = bp;
	bp->p_lforw = pp;
	spl(s);
	dispatch();

	/*
	 * We have just woken up.  Get ready to return.
	 */
	subu(pp->p_cval, cl);
	pp->p_ival = 0;
	pp->p_rval = 0;

	/*
	 * Check for an interrupted system call.
	 */
	if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
		sphi();
		envrest(&u.u_sigenv);
	}
}

/*
 * Defer function to wake up all processes sleeping on the event `e'.
 */
wakeup(e)
char *e;
{
	extern void dwakeup();

	defer( dwakeup, e );
}

/*
 * Wake up all processes sleeping on the event `e'.
 */
static void
dwakeup( e )
char *e;
{
	register PROC *pp;
	register PROC *pp1;
	register int s;

	/*
	 * Identify event queue to check.
	 * Disable interrupts.
	 */
	pp1 = &linkq[hash(e)];
	pp = pp1;
	s = sphi();

	/*
	 * Traverse doubly-linked circular event-queue.
	 */
	while ( (pp = pp->p_lforw) != pp1 ) {

		/*
		 * Process is waiting on event 'e'.
		 */
		if ( pp->p_event == e ) {
			/*
			 * Remove process from event queue.
			 * Update process priority.
			 * Insert process into run queue.
			 */
			pp->p_lback->p_lforw = pp->p_lforw;
			pp->p_lforw->p_lback = pp->p_lback;
			addu( pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK );
			setrun( pp );

			/*
			 * Enable interrupts.
			 * Restart search at start of event queue.
			 * Disable interrupts.
			 */
			spl( s );
			pp = pp1;
			s = sphi();
		}
	}
	spl(s);
}

/*
 * Reschedule the processor.
 */
dispatch()
{
	register PROC *pp1;
	register PROC *pp2;
	register unsigned v;
	register int s;

	s = sphi();
	pp1 = iprocp;
	pp2 = &procq;
	v = 0;
	while ((pp2=pp2->p_lforw) != &procq) {
		v -= pp2->p_cval;
		if ((pp2->p_flags&PFCORE) == 0)
			continue;
		pp1 = pp2->p_lforw;
		pp1->p_cval += pp2->p_cval;
		pp2->p_cval = v;
		pp1->p_lback = pp2->p_lback;
		pp1->p_lback->p_lforw = pp1;
		pp1 = pp2;
		break;
	}
	spl(s);

	quantum = NCRTICK;
	disflag = 0;
	if ( pp1 != SELF ) {
		/*
		 * Consave() returns twice.
		 * 1st time is after our context is saved in u.u_syscon,
		 *	whereupon we should restore other proc's context.
		 * 2nd time is after our context is restored by another proc.
		 * Conrest() forces a context switch to a new process.
		 */
		s = sphi();
		SELF = pp1;
		if (consave(&u.u_syscon) == 0)
			conrest( FP_SEL(pp1->p_u->s_faddr),
				 offset(uproc,u_syscon) );
		if ( SELF->p_pid != 0 )
			segload();
		spl(s);
	}
}

/*
 * Add a process to the run queue.
 * This routine must be called at high priority.
 */
setrun(pp1)
register PROC *pp1;
{
	register PROC *pp2;
	register unsigned v;

	v = 0;
	pp2 = &procq;
	for (;;) {
		pp2 = pp2->p_lback;
		if ((v+=pp2->p_lforw->p_cval) >= pp1->p_cval)
			break;
		if (pp2 == &procq)
			break;
	}
	pp2->p_lforw->p_lback = pp1;
	pp1->p_lforw = pp2->p_lforw;
	pp2->p_lforw = pp1;
	pp1->p_lback = pp2;
	v -= pp1->p_cval;
	pp1->p_cval = v;
	pp1->p_lforw->p_cval -= v;
	pp1->p_state = PSRUN;
}

/*
 * Wait for the gate `g' to unlock, and then lock it.
 */
lock(g)
register GATE g;
{
	register int s;

	s = sphi();
	while (g[0]) {
		g[1] = 1;
		sleep((char *)g, CVGATE, IVGATE, SVGATE);
	}
	g[0] = 1;
	spl(s);
}

/*
 * Unlock the gate `g'.
 */
unlock(g)
register GATE g;
{
	g[0] = 0;
	if (g[1]) {
		g[1] = 0;
		disflag = 1;
		wakeup((char *)g);
	}
}
0707070064030103231006440000030000030000011777770507310730400004100000041425/newbits/kernel/USRSRC/coh/seg.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Segment manipulation.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:51:50  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:20	src
 * Initial revision
 * 
 * 88/02/26	Allan Cornish	/usr/src/sys/coh/seg.c
 * swapio() now avoids 64 Kbyte page [dma] straddles.
 *
 * 88/01/22	Allan Cornish	/usr/src/sys/coh/seg.c
 * salloc() now invokes krunch(1000) if initial allocation fails.
 * sfree() now invokes krunch(0).
 *
 * 88/01/21	Allan Cornish	/usr/src/sys/coh/seg.c
 * sfree() modified to eliminate critical race on ref cnts and segment gate.
 * segfinm() now properly maintains segment reference counts.
 *
 * 87/11/13	Allan Cornish	/usr/src/sys/coh/seg.c
 * Support for protected mode segmentation added.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <errno.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/uproc.h>

/*
 * Initialisation code.
 */
seginit()
{
	/*
	 * Create empty circular-list of memory segments.
	 */
	segmq.s_forw = &segmq;
	segmq.s_back = &segmq;

	/*
	 * Create empty circular-list of disk segments.
	 */
	segdq.s_forw = &segdq;
	segdq.s_back = &segdq;

	if ( holebot != holetop ) {
		/*
		 * Define the I/O mem hole between low memory and extended mem.
		 * NOTE: Setting lrefc to urefc+1 stopx segment from moving.
		 */
		segiom.s_paddr = holebot;
		segiom.s_size  = holetop - holebot;
		segiom.s_flags = SFCORE | SFSYST;
		segiom.s_urefc = 1;
		segiom.s_lrefc = 2;

		/*
		 * Insert I/O memory segment into memory list.
		 */
		segiom.s_forw = &segmq;
		segiom.s_back = &segmq;
		segmq.s_forw  = &segiom;
		segmq.s_back  = &segiom;
	}
}

/*
 * Given an inode, `ip', and flags, `ff', describing a segment associated
 * with the inode, see if the segment already exists and if so, return a
 * copy.  If the segment does not exists, allocate the segment having size
 * `ss', and read the segment using the inode at seek offset `dq' with a
 * size of `ds'.
 */
SEG *
ssalloc(rp, ip, ff, ss, dq, ds)
int *rp;
register INODE *ip;
fsize_t ss;
fsize_t dq;
fsize_t ds;
{
	register SEG *sp;
	register int f;

	*rp = -1;
	if (ss == 0) {
		*rp = 1;
		return (NULL);
	}
	lock(seglink);
	f = ff & (SFSHRX|SFTEXT);

	/*
	 * Look for the segment in the memory queue.
	 */
	for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) {
		if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) {
			unlock(seglink);
			if ((sp = segdupl(sp)) != NULL) {
				segfinm(sp);
				*rp = 1;
			}
			return (sp);
		}
	}

	/*
	 * Look for the segment on the disk queue.
	 */
	for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) {
		if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) {
			unlock(seglink);
			if ((sp = segdupl(sp)) != NULL) {
				segfinm(sp);
				*rp = 1;
			}
			return (sp);
		}
	}
	unlock(seglink);

	/*
	 * Allocate and create the segment.
	 */
	if ((sp=salloc(ss, ff)) == NULL)
		return (NULL);
	if (exsread(sp, ip, ds, dq, (fsize_t)0) == 0) {
		sfree(sp);
		return (NULL);
	}
	if ((ff&SFSHRX) != 0) {
		sp->s_ip = ip;
		ip->i_refc++;
	}
	*rp = 0;
	return (sp);
}

/*
 * Given a pointer to a newly created process, copy all of our segments
 * into the given process.
 */
segadup(cpp)
register PROC *cpp;
{
	register SEG *sp;
	register int n;
	register PROC *pp;

	pp = SELF;
	cpp->p_flags |= PFSWIO;
	for (n=0; n<NUSEG; n++) {
		if ((sp=pp->p_segp[n]) == NULL)
			continue;
		if ((sp=segdupl(sp)) == NULL)
			break;
		cpp->p_segp[n] = sp;
		if ((sp->s_flags&SFCORE) == 0)
			cpp->p_flags &= ~PFCORE;
	}
	if (n < NUSEG) {
		while (n > 0) {
			if ((sp=cpp->p_segp[--n]) != NULL) {
				cpp->p_segp[n] = NULL;
				sfree(sp);
			}
		}
	}
	cpp->p_flags &= ~PFSWIO;
	return (n);
}

/*
 * Duplicate a segment.
 */
SEG *
segdupl(sp)
register SEG *sp;
{
	register SEG *sp1;

	if ((sp->s_flags&SFSHRX) != 0) {
		sp->s_urefc++;
		sp->s_lrefc++;
		return (sp);
	}
	if ((sp->s_flags&SFCORE) == 0)
		panic("Cannot duplicate non shared swapped segment");
	if ((sp1=salloc(sp->s_size, sp->s_flags|SFNSWP|SFNCLR)) == NULL)
		sp1 = segdupd(sp);
	else {
		sp1->s_flags = sp->s_flags;
		plrcopy( sp->s_paddr, sp1->s_paddr, sp->s_size );
	}
	return (sp1);
}

/*
 * Allocate a segment `n' bytes long.  `f' contains some pseudo flags.
 */
SEG *
salloc(n, f)
fsize_t n;
{
	register SEG *sp;
	register int r;

	r = (f&(SFSYST|SFHIGH|SFTEXT|SFSHRX|SFDOWN)) | SFCORE;
	n +=  (BSIZE-1);
	n &= ~(BSIZE-1);

	lock(seglink);
	sp = sxalloc(n, f);
	unlock(seglink);

	if ( sp == NULL ) {
		krunch(1000);
		lock(seglink);
		sp = sxalloc(n, f);
		unlock(seglink);
	}

	if (sp != NULL) {
		sp->s_flags = r;
		vremap( sp );
	}
	else {
		if ((f&SFNSWP) != 0)
			return (NULL);
		if ((sp=kalloc(sizeof(SEG))) == NULL)
			return (NULL);
		sp->s_forw = sp;
		sp->s_back = sp;
		sp->s_flags = r;
		sp->s_urefc = 1;
		sp->s_lrefc = 1;
		if (segsext(sp, n) == NULL) {
			kfree(sp);
			return (NULL);
		}
	}
	if ((f&SFNCLR) == 0)
		pclear( sp->s_paddr, n );
	return (sp);
}

/*
 * Free the given segment pointer.
 */
sfree(sp)
register SEG *sp;
{
	register INODE *ip;

	if ( sp->s_urefc != 1 ) {
		sp->s_urefc--;
		sp->s_lrefc--;
		return;
	}

	lock(seglink);
	--sp->s_lrefc;
	if (--sp->s_urefc != 0) {
		unlock(seglink);
		return;
	}

	sp->s_back->s_forw = sp->s_forw;
	sp->s_forw->s_back = sp->s_back;
	unlock(seglink);

	if (sp->s_lrefc != 0)
		panic("Bad segment count");
	if ((ip=sp->s_ip) != NULL)
		ldetach(ip);
	vrelse( sp->s_faddr );
	kfree(sp);
	krunch(0);
}

/*
 * Grow or shrink the segment `sp' so that it has size `n'.
 */
seggrow(sp, n)
register SEG *sp;
fsize_t n;
{
	register SEG *sp1;
	register fsize_t  d;
	register paddr_t pb;
	register paddr_t nb;
	register int dowflag;

	dowflag = sp->s_flags&SFDOWN;

	/*
	 * Size of new segment is smaller or the same size as the old
	 * segment.
	 */
	lock(seglink);
	d = n - sp->s_size;
	if (n <= sp->s_size) {
		sp->s_size = n;
		if (dowflag)
			sp->s_paddr -= d;

		vremap( sp );
		unlock(seglink);
		return (1);
	}

	if ((sp1=sp->s_back) == &segmq)
		pb = corebot;
	else
		pb = sp1->s_paddr + sp1->s_size;

	if ((sp1=sp->s_forw) == &segmq)
		nb = coretop;
	else
		nb = sp1->s_paddr;

	/*
	 * If the segment does not grow down, see if there is enough
	 * space after the segment.
	 */
	if (dowflag==0 && nb-sp->s_paddr>=n) {
		pclear(sp->s_paddr+sp->s_size, d);
		sp->s_size = n;
		vremap( sp );
		unlock(seglink);
		return (1);
	}

	/*
	 * If the segment grows down, see if there is enough space
	 * before the segment.
	 */
	if (dowflag!=0 && sp->s_paddr+sp->s_size-pb>=n) {
		sp->s_paddr -= d;
		sp->s_size   = n;
		pclear( sp->s_paddr, d );
		vremap( sp );
		unlock(seglink);
		return (1);
	}

	/*
	 * Is there enough space in total counting the gaps on either
	 * side of us?
	 */
	if (nb-pb >= n) {
		if (dowflag == 0) {
			plrcopy(sp->s_paddr, pb, sp->s_size);
			pclear(pb+sp->s_size, d);
			sp->s_paddr = pb;
		} else {
			prlcopy( sp->s_paddr, nb-sp->s_size, sp->s_size );
			pclear(nb-n, d);
			sp->s_paddr = nb-n;
		}
		sp->s_size  = n;
		vremap( sp );
		unlock(seglink);
		return (1);
	}

	/*
	 * Try to allocate a segment somewhere else on the segment queue
	 * and copy ourselves there.
	 */
	unlock(seglink);
	if ((sp1=salloc((fsize_t)n, sp->s_flags|SFNSWP|SFNCLR)) != NULL) {
		if (dowflag == 0) {
			plrcopy(sp->s_paddr, sp1->s_paddr, sp->s_size);
			pclear(sp1->s_paddr+sp->s_size, d);
		} else {
			plrcopy(sp->s_paddr, sp1->s_paddr+d, sp->s_size);
			pclear(sp1->s_paddr, d);
		}
		lock(seglink);
		satcopy(sp, sp1);
		unlock(seglink);
		return (1);
	}

	/*
	 * Last chance.  Extend the segment by swapping it.
	 */
	if (segsext(sp, n) != NULL) {
		if (dowflag == 0)
			pclear(sp->s_paddr+n-d, d);
		else {
			prlcopy(sp->s_paddr, sp->s_paddr+d, n-d);
			pclear(sp->s_paddr, d);
		}
		return (1);
	}

	/*
	 * At least we tried.
	 */
	return (0);
}

/*
 * Given a segment pointer, `sp' and a segment size, grow the given segment
 * to the given size.
 */
segsize(sp, s2)
register SEG *sp;
vaddr_t s2;
{
	register vaddr_t s1;

	s1 = (vaddr_t) sp->s_size;
	if (seggrow(sp, (fsize_t)s2) == 0) {
		u.u_error = ENOMEM;
		return;
	}
	if (sproto() == 0)
		if (seggrow(sp, (fsize_t)s1)==0 || sproto()==0)
			sendsig(SIGSEGV, SELF);
	segload();
}

/*
 * Grow the segment `sp1' to the size `s' in bytes by swapping it out
 * and back in.  The segment may not be locked.
 */
SEG *
segsext(sp1, s)
register SEG *sp1;
register fsize_t s;
{
	register SEG *sp2;

#ifndef NOMONITOR
	if (swmflag)
		printf("Segsext(%p, %u)\n", SELF, SELF->p_pid);
#endif
	if (sexflag == 0) {
		u.u_error = ENOMEM;
		return (NULL);
	}
	lock(seglink);
	if ((sp2=sdalloc(s)) == NULL) {
		unlock(seglink);
		return (NULL);
	}
	unlock(seglink);
	sp1->s_lrefc++;
	if (sp1->s_size != 0)
		swapio(1, sp1->s_paddr, sp2->s_daddr, sp1->s_size);
	lock(seglink);
	satcopy(sp1, sp2);
	unlock(seglink);
	sp1->s_flags &= ~SFCORE;
	sp1->s_lrefc--;
	vremap(sp1);
	segfinm(sp1);
	return (sp1);
}

/*
 * Force the given segment to be in memory.  One can only force
 * one segment to be in memory at a time.
 */
segfinm(sp)
register SEG *sp;
{
	register PROC *pp;
	register int s;

	if ((sp->s_flags&SFCORE) != 0)
		return;
	pp = SELF;
	sp->s_urefc++;
	sp->s_lrefc++;
	pp->p_segp[SIAUXIL] = sp;
	pp->p_flags &= ~PFCORE;
#ifndef QWAKEUP
	s = sphi();
#endif
	setrun(pp);
	dispatch();
#ifndef QWAKEUP
	spl(s);
#endif
	pp->p_segp[SIAUXIL] = NULL;
	sfree(sp);
}

/*
 * Make a copy of the segment `sp1' which is in memory by writing
 * it out to disk.
 */
SEG *
segdupd(sp1)
register SEG *sp1;
{
	register SEG *sp2;

	if (sexflag == 0)
		return (NULL);
	lock(seglink);
	if ((sp2=sdalloc(sp1->s_size)) == NULL) {
		unlock(seglink);
		return (NULL);
	}
	sp1->s_lrefc++;
	unlock(seglink);
	swapio(1, sp1->s_paddr, sp2->s_daddr, sp1->s_size);
	sp1->s_lrefc--;
	sp2->s_flags = sp1->s_flags & ~SFCORE;
	sp2->s_size  = sp1->s_size;
	vremap( sp2 );
	return (sp2);
}

/*
 * Given a flag, a physical core address, a disk address and a count in
 * bytes, perform an I/O operation between core and disk.  If `flag' is
 * set, the transfer is to the disk otherwise it is to memory.  As you may
 * have guessed, this is used by the swapper.
 */
swapio(f, p, d, n)
paddr_t p;
daddr_t d;
fsize_t  n;
{
	register BUF * bp;
	register SEG * sp;
	register int s;
	register int nb;
	static SEG swapseg;	/* NOTE: FP_SEL(swapseg.s_faddr) must stay */

#ifndef NOMONITOR
	if (swmflag > 1)
		printf("swapio(%s,%x,%x,%x)\n",f?"out":"in",(int)p,(int)d,n);
#endif
	if (d < swapbot || d+(n/BSIZE) > swaptop
	 || p < corebot || p+n > coretop)
		panic("Swapio bad parameter");

	bp = &swapbuf;
	sp = &swapseg;
	lock(bp->b_gate);
	SELF->p_flags |= PFSWIO;
	sp->s_flags = SFCORE;
	sp->s_paddr = p;
	sp->s_size  = n;
	vremap( sp );
	bp->b_faddr = sp->s_faddr;

	while (n != 0) {
		nb = (n > SCHUNK) ? SCHUNK : n;
		/*
		 * Prevent I/O transfer from crossing 64 Kbyte boundary.
		 */
		if ( (p & 0xFFFF0000L) != ((p+nb) & 0xFFFF0000L) )
			nb = 0x10000L - (p & 0x0000FFFFL);
		bp->b_flag  = BFNTP;
		bp->b_req   = f ? BWRITE : BREAD;
		bp->b_dev   = swapdev;
		bp->b_bno   = d;
		bp->b_paddr = p;
		bp->b_count = nb;
		s = sphi();
		dblock(swapdev, bp);
		while ((bp->b_flag&BFNTP) != 0)
			sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
		spl(s);
		if ((bp->b_flag&BFERR) != 0)
			panic("Swapio error");
		FP_OFF(bp->b_faddr) += nb;
		p += nb;
		d += nb / BSIZE;
		n -= nb;
	}
	sp->s_flags = 0;
	vremap( sp );
	unlock(bp->b_gate);
	SELF->p_flags &= ~PFSWIO;
}

/*
 * Make the segment descriptor pointed to by `sp1' have the attributes
 * of `sp2' including it's position in the segment queue and release
 * `sp2'.  `seglink' must be locked when this routine is called.
 */
satcopy(sp1, sp2)
register SEG *sp1;
register SEG *sp2;
{
	if ( FP_SEL(sp2->s_faddr) != 0 )
		vrelse( sp2->s_faddr );

	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw  = sp2->s_forw;
	sp1->s_size  = sp2->s_size;
	sp1->s_paddr = sp2->s_paddr;
	sp1->s_daddr = sp2->s_daddr;
	vremap(sp1);
	kfree(sp2);
}

/*
 * Allocate a segment on disk that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 */
SEG *
sdalloc( s )
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register daddr_t d;
	register daddr_t d1;
	register daddr_t d2;

	d  = s / BSIZE;
	d1 = swapbot;
	sp1 = &segdq;
	do {
		if (d1 >= swaptop)
			return (NULL);
		if ((sp1=sp1->s_forw) != &segdq)
			d2 = sp1->s_daddr;
		else
			d2 = swaptop;
		if (d2-d1 >= d) {
			if ((sp2=kalloc(sizeof(SEG))) == NULL)
				return (NULL);
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_daddr = d1;
			return (sp2);
		}
		d1 = sp1->s_daddr + (sp1->s_size / BSIZE);
	} while (sp1 != &segdq);
	return (NULL);
}

/*
 * Allocate a segment in memory that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 */
SEG *
smalloc(s)
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	paddr_t p1;
	paddr_t p2;

	p1  = corebot;
	sp1 = &segmq;
	do {
		if ((sp1=sp1->s_forw) != &segmq)
			p2 = sp1->s_paddr;
		else
			p2 = coretop;

		if (p2-p1 >= s) {
			if ((sp2=kalloc(sizeof (SEG))) == NULL)
				return (NULL);
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_paddr = p1;
			/*   s_faddr = 0; */
			/*   s_flags = 0; */
			vremap( sp2 );
			return (sp2);
		}
		p1 = sp1->s_paddr + sp1->s_size;
	} while (sp1 != &segmq);
	return (NULL);
}

/*
 * Allocate a segment from the high end of memory that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 */
SEG *
shalloc( s )
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	paddr_t p1;
	paddr_t p2;

	sp1 = &segmq;
	p2  = coretop;
	do {
		if ((sp1=sp1->s_back) != &segmq)
			p1 = sp1->s_paddr + sp1->s_size;
		else
			p1 = corebot;

		if (p2-p1 >= s) {
			if ((sp2=kalloc(sizeof (SEG))) == NULL)
				return (NULL);
			sp1->s_forw->s_back = sp2;
			sp2->s_forw = sp1->s_forw;
			sp1->s_forw = sp2;
			sp2->s_back = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_paddr = p2-s;
			/*   s_faddr = 0; */
			/*   s_flags = 0; */
			vremap( sp2 );
			return (sp2);
		}
		p2 = sp1->s_paddr;
	} while (sp1 != &segmq);
	return (NULL);
}

/*
 * Set up `SR' structure in user area from segments descriptors in
 * process structure.  Also set up the user segmentation registers.
 */
sproto()
{
	register int n;
	register SEG *sp;

	kclear(u.u_segl, sizeof(u.u_segl));
	for (n=0; n<NUSEG; n++) {
		if ((sp=SELF->p_segp[n]) == NULL)
			continue;
		if (n == SIUSERP)
			u.u_segl[n].sr_base = &u;
		else
			u.u_segl[n].sr_flag |= SRFPMAP;
		if (n!=SISTEXT && n!=SISDATA)
			u.u_segl[n].sr_flag |= SRFDUMP;
		if (n!=SIUSERP && n!=SISTEXT && n!=SIPTEXT)
			u.u_segl[n].sr_flag |= SRFDATA;
		u.u_segl[n].sr_size = sp->s_size;
		u.u_segl[n].sr_segp = sp;
	}
	return (mproto());
}

/*
 * Search for a busy text inode.
 */
sbusy(ip)
register INODE *ip;
{
	register SEG *sp;

	lock(seglink);
	/*
	 * Look for the segment in the memory queue.
	 */
	for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) {
		if (sp->s_ip==ip
		 && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) {
			unlock(seglink);
			return (1);
		}
	}

	/*
	 * Look for the segment on the disk queue.
	 */
	for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) {
		if (sp->s_ip==ip
		 && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) {
			unlock(seglink);
			return (1);
		}
	}
	unlock(seglink);
	return (0);
}

/*
 * Segment consistency checks for the paranoid.
segchk()
{
	register SEG *sp;
	register int nbad;
	fsize_t s;
	daddr_t d;

	nbad = 0;
	sp = &segmq;
	s = corebot;
	while ((sp=sp->s_forw) != &segmq) {
		if (sp->s_paddr < s)
			nbad += badseg("mem", sp->s_paddr, 0);
		s = sp->s_paddr + sp->s_size;
	}
	if (coretop < s)
		nbad += badseg("mem", sp->s_back->s_paddr, sp->s_back->s_size);
	sp = &segdq;
	d = swapbot;
	while ((sp=sp->s_forw) != &segdq) {
		if (sp->s_daddr < d)
			nbad += badseg("disk", (int)sp->s_daddr, 0);
		d = sp->s_daddr + (sp->s_size / BSIZE);
	}
	if (swaptop < d)
		nbad += badseg("disk", sp->s_back->s_daddr, sp->s_back->s_size);
}

badseg(t, b, s)
char *t;
daddr_t b;
fsize_t s;
{
	printf( "Bad %s segment at %X of len %X\n", t, b, s );
	return (1);
}
*/
0707070064030103221006440000030000030000011777770507310731000004100000014435/newbits/kernel/USRSRC/coh/sig.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Signal handling.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:52:13  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:24	src
 * Initial revision
 * 
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/sig.c
 * New seg struct now used to allow extended addressing.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/sig.c
 * sigdump() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Send a signal to the process `pp'.
 */
sendsig(sig, pp)
register unsigned sig;
register PROC *pp;
{
	register sig_t f;
	register int s;

	f = ((sig_t)1) << (sig-1);
	if ((pp->p_isig&f) != 0)
		return;
	pp->p_ssig |= f;
	if (pp->p_state == PSSLEEP) {
		s = sphi();
		pp->p_lback->p_lforw = pp->p_lforw;
		pp->p_lforw->p_lback = pp->p_lback;
		addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK);
		setrun(pp);
		spl(s);
	}
}

/*
 * Return signal number if we have a non ignored signal, else zero.
 */
nondsig()
{
	register PROC *pp;
	register sig_t mask;
	register int signo;

	pp = SELF;
	signo = 0;
	pp->p_ssig &= ~pp->p_isig;
	if (pp->p_ssig != 0) {
		mask = (sig_t) 1;
		signo += 1;
		while ((pp->p_ssig&mask) == 0) {
			mask <<= 1;
			signo += 1;
		}
	}
	return (signo);
}

/*
 * If we have a signal that isn't ignored, activate it.
 */
actvsig()
{
	register int n;
	register PROC *pp;
	register int (*f)();

#if EBUG_VM > 0
	printf("actvsig ");	/** DEBUG **/
#endif

	if ((n = nondsig()) == 0)
		return;
	pp = SELF;
	--n;
	pp->p_ssig &= ~((sig_t)1<<n);
	f = u.u_sfunc[n];
	u.u_signo = ++n;
	if (f != SIG_DFL) {
		msigint(n, f);
		return;
	}
	msysgen(&u.u_sysgen);
	if ((pp->p_flags&PFTRAC) != 0) {
		pp->p_flags |= PFWAIT;
		n = ptret();
		pp->p_flags &= ~(PFWAIT|PFSTOP);
		if (n == 0)
			return;
	}
	if (n>SIGKILL || n==SIGQUIT || n==SIGSYS) {
		if (sigdump())
			n |= 0200;
	}
	pexit(n);
}

/*
 * Create a dump of ourselves onto the file `core'.
 */
sigdump()
{
	register INODE *ip;
	register SR *srp;
	register SEG * sp;
	register int n;
	register paddr_t ssize;

	if ((SELF->p_flags&PFNDMP) != 0)
		return (0);
	u.u_io.io_seg  = IOSYS;
	u.u_io.io_flag = 0;
	/* Make the core with the real owners */
	schizo();
	if (ftoi("core", 'c') != 0) {
		schizo();
		return (0);
	}
	if ((ip=u.u_cdiri) == NULL) {
		if ((ip=imake(IFREG|0644, 0)) == NULL) {
			schizo();
			return (0);
		}
	} else {
		if ((ip->i_mode&IFMT)!=IFREG
		 || iaccess(ip, IPW)==0
		 || getment(ip->i_dev, 1)==NULL) {
			idetach(ip);
			schizo();
			return (0);
		}
		iclear(ip);
	}
	schizo();
	u.u_error = 0;
	u.u_io.io_seek = 0;
	for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) {
		if ((sp = srp->sr_segp)==NULL || (srp->sr_flag&SRFDUMP)==0)
			continue;
		u.u_io.io_seg = IOPHY;
		u.u_io.io_phys = sp->s_paddr;
		u.u_io.io_flag = 0;
		ssize = sp->s_size;
		sp->s_lrefc++;
		while (u.u_error == 0 && ssize != 0) {
			n = ssize > SCHUNK ? SCHUNK : ssize;
			u.u_io.io_ioc = n;
			iwrite(ip, &u.u_io);
			u.u_io.io_phys += (paddr_t)n;
			ssize -= (paddr_t)n;
		}
		sp->s_lrefc--;
	}
	idetach(ip);
	return (u.u_error==0);
}

/*
 * Send a ptrace command to the child.
 */
ptset(req, pid, addr, data)
unsigned req;
int *addr;
{
#ifdef TINY
	sendsig(SELF, SIGSYS);
	return (0);
#else
	register PROC *pp;

	lock(pnxgate);
	for (pp=procq.p_nforw; pp!=&procq; pp=pp->p_nforw)
		if (pp->p_pid == pid)
			break;
	unlock(pnxgate);
	if (pp==&procq || (pp->p_flags&PFSTOP)==0 || pp->p_ppid!=SELF->p_pid) {
		u.u_error = ESRCH;
		return;
	}
	lock(pts.pt_gate);
	pts.pt_req = req;
	pts.pt_pid = pid;
	pts.pt_addr = addr;
	pts.pt_data = data;
	pts.pt_errs = 0;
	pts.pt_rval = 0;
	pts.pt_busy = 1;
	wakeup((char *)&pts.pt_req);
	while (pts.pt_busy != 0)
		sleep((char *)&pts.pt_busy, CVPTSET, IVPTSET, SVPTSET);
	u.u_error = pts.pt_errs;
	unlock(pts.pt_gate);
	return (pts.pt_rval);
#endif
}

/*
 * This routine is called when a child that is being traced receives a signal
 * that is not caught or ignored.  It follows up on any requests by the parent
 * and returns when done.
 */
ptret()
{
#ifdef TINY
	return (SIGKILL);
#else
	register PROC *pp;
	register PROC *pp1;
	register int sign;

	pp = SELF;
next:
	u.u_error = 0;
	if (pp->p_ppid == 1)
		return (SIGKILL);
	sign = -1;
	lock(pnxgate);
	pp1 = &procq;
	for (;;) {
		if ((pp1=pp1->p_nforw) == &procq) {
			sign = SIGKILL;
			break;
		}
		if (pp1->p_pid != pp->p_ppid)
			continue;
		if (pp1->p_state == PSSLEEP)
			wakeup((char *)pp1);
		break;
	}
	unlock(pnxgate);
	while (sign < 0) {
		if (pts.pt_busy==0 || pp->p_pid!=pts.pt_pid) {
			sleep((char *)&pts.pt_req, CVPTRET, IVPTRET, SVPTRET);
			goto next;
		}
		switch (pts.pt_req) {
		case 1:
			pts.pt_rval = getuwi(pts.pt_addr);
			break;
		case 2:
			pts.pt_rval = getuwd(pts.pt_addr);
			break;
		case 3:
			if ((unsigned)pts.pt_addr < UPASIZE)
				pts.pt_rval = *(int *)((char *)&u+pts.pt_addr);
			else
				u.u_error = EINVAL;
			break;
		case 4:
			putuwi(pts.pt_addr, pts.pt_data);
			break;
		case 5:
			putuwd(pts.pt_addr, pts.pt_data);
			break;
		case 6:
			if (msetuof(pts.pt_addr, pts.pt_data) == 0)
				u.u_error = EINVAL;
			break;
		case 7:
			goto sig;
		case 8:
			sign = SIGKILL;
			break;
		case 9:
			msigsin();
		sig:
			if (pts.pt_data<0 || pts.pt_data>NSIG) {
				u.u_error = EINVAL;
				break;
			}
			sign = pts.pt_data;
			if (pts.pt_addr != SIG_IGN)
				msetppc((vaddr_t)pts.pt_addr);
			break;
		default:
			u.u_error = EINVAL;
		}
		if ((pts.pt_errs=u.u_error) == EFAULT)
			pts.pt_errs = EINVAL;
		pts.pt_busy = 0;
		wakeup((char *)&pts.pt_busy);
	}
	return (sign);
#endif
}
0707070064030103211006440000030000030000011777770507310731100004200000024362/newbits/kernel/USRSRC/coh/sys1.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * General system calls.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:52:21  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	88/03/24  16:14:27	src
 * Initial revision
 * 
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/sys1.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/10/21	Allan Cornish		/usr/src/sys/coh/sys1.c
 * ukill() no longer signals kernel processes if pid is -1.
 * usload() changed to new loadable driver format.
 *
 * 87/08/14	Allan Cornish		/usr/src/sys/coh/sys1.c
 * utick() system call added. Returns elapsed clock ticks since system startup.
 *
 * 87/07/23	Allan Cornish		/usr/src/sys/coh/sys1.c
 * ualarm2() now takes the delay interval as a long instead of an unsigned.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/coh/sys1.c
 * ualarm() modified to use timed functions to send alarm signal.
 * ualarm2() added to allow alarm times in clock ticks rather than seconds.
 *
 * 85/07/25	Allan Cornish
 * ukill() modified to allow a signal of 0 to check process existence.
 *
 * 85/07/9	Allan Cornish
 * ukill() modified to allow signals to be sent to other process groups.
 * usetpgrp() modified to be System V compatible (group set to pid).
 * ugetpgrp() system call added.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/timeb.h>
#include <sys/times.h>
#include <sys/uproc.h>

/*
 * Send alarm signal to specified process - function timed by ualarm()
 */
static
sigalrm( pp )
register PROC * pp;
{
	sendsig( SIGALRM, pp );
}

/*
 * Send a SIGALARM signal in `n' seconds.
 */
ualarm(n)
unsigned n;
{
	register PROC * pp = SELF;
	register unsigned s;

	/*
	 * Calculate time left before current alarm timeout.
	 */
	s = 0;
	if ( pp->p_alrmtim.t_last != NULL )
		s = (pp->p_alrmtim.t_lbolt - lbolt + HZ - 1) / HZ;

	/*
	 * Cancel previous alarm [if any], start new alarm [if n != 0].
	 */
	timeout2( &pp->p_alrmtim, (long) n * HZ, sigalrm, pp );

	/*
	 * Return time left before previous alarm timeout.
	 */
	return( s );
}

/*
 * Send a SIGALARM signal in `n' clock ticks.
 */
long
ualarm2(n)
long n;
{
	register PROC * pp = SELF;
	long s;

	/*
	 * Calculate time left before current alarm timeout.
	 */
	s = 0;
	if ( pp->p_alrmtim.t_last != NULL )
		s = pp->p_alrmtim.t_lbolt - lbolt;

	/*
	 * Cancel previous alarm [if any], start new alarm [if n != 0].
	 */
	timeout2( &pp->p_alrmtim, (long) n, sigalrm, pp );

	/*
	 * Return time left before previous alarm timeout.
	 */
	return( s );
}

/*
 * Change the size of our data segment.
 */
char *
ubrk(cp)
char *cp;
{
	register SEG *sp;
	register vaddr_t sb;

	sp = SELF->p_segp[SIPDATA];
	sb = u.u_segl[SIPDATA].sr_base;
	if (cp != NULL)
		segsize(sp, (vaddr_t)cp-sb);
#ifdef	OLD
	return (0);
#else
	sb += sp->s_size;
	return ((char *)sb);
#endif
}

/*
 * Execute a l.out.
 */
uexece(np, argp, envp)
char *np;
char *argp[];
char *envp[];
{
	pexece(np, argp, envp);
}

/*
 * Exit.
 */
uexit(s)
{
	pexit(s<<8);
}

/*
 * Fork.
 */
ufork()
{
	return (pfork());
}

/*
 * Return date and time.
 */
uftime(tbp)
struct timeb *tbp;
{
	register int s;
	struct timeb timeb;

	timeb.time = timer.t_time;
	/* This should be a machine.h macro to avoid
	 * unnecessary long arithmetic and roundoff errors
	 */
	timeb.millitm = timer.t_tick*(1000/HZ);
	timeb.timezone = timer.t_zone;
	timeb.dstflag = timer.t_dstf;
	s = sphi();
	kucopy(&timeb, tbp, sizeof(timeb));
	spl(s);
}

/*
 * Get effective group id.
 */
ugetegid()
{
	return (u.u_gid);
}

/*
 * Get effective user id.
 */
ugeteuid()
{
	return (u.u_uid);
}

/*
 * Get group id.
 */
ugetgid()
{
	return (u.u_rgid);
}

/*
 * Get process id.
 */
ugetpid()
{
	return (SELF->p_pid);
}

/*
 * Get user id.
 */
ugetuid()
{
	return (u.u_ruid);
}

/*
 * Get process group.
 */
ugetpgrp()
{
	return (SELF->p_group);
}

/*
 * Set the process group.
 * When process group is 0 and a terminal is
 * opened, this process is made the base of
 * processes associated with that terminal.
 */
usetpgrp()
{
	register PROC * pp = SELF;

	return (pp->p_group = pp->p_pid);
}

/*
 * Send the signal `sig' to the process with id `pid'.
 */
ukill(pid, sig)
int pid;
register unsigned sig;
{
	register PROC *pp;
	register int sigflag;

	if ( sig > NSIG ) {
		u.u_error = EINVAL;
		return;
	}
	sigflag = 0;
	lock(pnxgate);
	if (pid > 0) {	/* send to matching process */
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_pid == pid) {
				sigflag = 1;
				if ( sig ) {
					if (sigperm(sig, pp))
						sendsig(sig, pp);
					else
						u.u_error = EPERM;
				}
				break;
			}
		}
	}
	else if (pid < -1) {
		pid = -pid;
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_group == pid) {
				sigflag = 1;
				if (sig) {
					if (sigperm(sig, pp))
						sendsig(sig,pp);
					else
						u.u_error = EPERM;
				}
			}
		}
	}
	else if (pid == 0) {
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_group == SELF->p_group) {
				sigflag = 1;
				if (sig && sigperm(sig, pp))
					sendsig(sig, pp);
			}
		}
	}
	else if (pid == -1) {
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_pid == 0)
				continue;
			if (pp->p_pid == 1)
				continue;
			if ( pp->p_flags & PFKERN )
				continue;
			sigflag = 1;
			if (sig && super())
				sendsig(sig, pp);
		}
	}
	unlock(pnxgate);
	if (sigflag == 0)
		u.u_error = ESRCH;
	return (0);
}

/*
 * See if we have permission to send the signal, `sig' to the process, `pp'.
 */
sigperm(sig, pp)
register PROC *pp;
{
	if (u.u_uid == pp->p_uid)
		return (1);
	if (u.u_ruid == pp->p_ruid) {
		if (sig == SIGHUP
		||  sig == SIGINT
		||  sig == SIGQUIT
		||  sig == SIGTERM)
			return (1);
	}
	if (u.u_uid == 0) {
		u.u_flag |= ASU;
		return (1);
	}
	return (0);
}

/*
 * Lock a process in core.
 */
ulock(f)
{
	if (super() == 0)
		return;
	if (f)
		SELF->p_flags |= PFLOCK;
	else
		SELF->p_flags &= ~PFLOCK;
	return (0);
}

/*
 * Change priority by the given increment.
 */
unice(n)
register int n;
{
	n += SELF->p_nice;
	if (n < MINNICE)
		n = MINNICE;
	if (n > MAXNICE)
		n = MAXNICE;
	if (n<SELF->p_nice && super()==0)
		return;
	SELF->p_nice = n;
	return (0);
}

/*
 * Non existant system call.
 */
unone()
{
	u.u_error = EFAULT;
}

/*
 * Null system call.
 */
unull()
{
}

/*
 * Pause.  Go to sleep on a channel that nobody will wakeup so that only
 * signals will wake us up.
 */
upause()
{
	for (;;)
		sleep((char *)&u, CVPAUSE, IVPAUSE, SVPAUSE);
}

/*
 * Start profiling.  `bp' is the profile buffer, `n' is the size, `off'
 * is the offset in the users programme and `scale' is the scaling
 * factor.
 */
uprofil(bp, n, off, scale)
register char *bp;
{
	u.u_pbase = bp;
	u.u_pbend = bp + n;
	u.u_pofft = off;
	u.u_pscale = scale;
}

/*
 * Process trace.
 */
uptrace(req, pid, add, data)
int *add;
{
	if (req == 0) {
		SELF->p_flags |= PFTRAC;
		return (0);
	}
	return (ptset(req, pid, add, data));
}

/*
 * Set group id.
 */
usetgid(gid)
register int gid;
{
	if (u.u_gid!=gid && super()==0)
		return;
	u.u_gid = gid;
	u.u_rgid = gid;
	SELF->p_rgid = gid;
	return (0);
}

/*
 * Set user id.
 */
usetuid(uid)
register int uid;
{
	if (uid!=u.u_ruid && super()==0)
		return;
	u.u_uid = uid;
	u.u_ruid = uid;
	SELF->p_uid = uid;
	SELF->p_ruid = uid;
	return (0);
}

/*
 * Set up the action to be taken on a signal.
 */
int *
usignal(sig, f)
register int sig;
int (*f)();
{
	register PROC *pp;
	register sig_t s;
	register int (*o)();

	pp = SELF;
	if (sig<=0 || sig>NSIG || sig==SIGKILL) {
		u.u_error = EINVAL;
		return;
	}
	s = (sig_t)1 << --sig;
	o = u.u_sfunc[sig];
	/* This order is critical to isig's use */
	if (f == SIG_IGN) {
		pp->p_isig |= s;
		u.u_sfunc[sig] = f;
	} else {
		u.u_sfunc[sig] = f;
		pp->p_isig &= ~s;
	}
	pp->p_ssig &= ~s;
	return (o);
}

/*
 * Load a device driver.
 */
usload( np )
char *np;
{
	return( pload( np ) );
}

/*
 * Set time and date.
 */
ustime(tp)
register time_t *tp;
{
	register int s;

	if (super() == 0)
		return;
	s = sphi();
	ukcopy(tp, &timer.t_time, sizeof(*tp));
	spl(s);
	return (0);
}

/*
 * Return elapsed ticks since system startup.
 */
long
utick()
{
	return( lbolt );
}

/*
 * Return process times.
 */
utimes(tp)
struct tbuffer *tp;
{
	register PROC *pp;
	struct tbuffer tbuffer;

	pp = SELF;
	tbuffer.tb_utime = pp->p_utime;
	tbuffer.tb_stime = pp->p_stime;
	tbuffer.tb_cutime = pp->p_cutime;
	tbuffer.tb_cstime = pp->p_cstime;
	kucopy(&tbuffer, tp, sizeof(tbuffer));
	return (0);
}

/*
 * Unload a device driver.
 */
usuload(m)
register int m;
{
	if (super() == 0)
		return;
	puload(m);
	return (0);
}


/*
 * Wait for a child to terminate.
 */
uwait(stp)
int *stp;
{
	register PROC *pp;
	register PROC *ppp;
	register PROC *cpp;
	register int pid;

	ppp = SELF;
	for (;;) {
		lock(pnxgate);
		cpp = NULL;
		pp = &procq;
		while ((pp=pp->p_nforw) != &procq) {
			if (pp == ppp)
				continue;
			if (pp->p_ppid != ppp->p_pid)
				continue;
			if ((pp->p_flags&PFSTOP) != 0)
				continue;
			if ((pp->p_flags&PFWAIT) != 0) {
				pp->p_flags &= ~PFWAIT;
				pp->p_flags |= PFSTOP;
				unlock(pnxgate);
				if (stp != NULL)
					putuwd(stp, 0177);
				return (pp->p_pid);
			}
			if (pp->p_state == PSDEAD) {
				ppp->p_cutime += pp->p_utime + pp->p_cutime;
				ppp->p_cstime += pp->p_stime + pp->p_cstime;
				if (stp != NULL)
					putuwd(stp, pp->p_exit);
				pid = pp->p_pid;
				unlock(pnxgate);
				relproc(pp);
				return (pid);
			}
			cpp = pp;
		}
		unlock(pnxgate);
		if (cpp == NULL) {
			u.u_error = ECHILD;
			return;
		}
		sleep((char *)ppp, CVWAIT, IVWAIT, SVWAIT);
	}
}
0707070064030103201006440000030000030000011777770507310731400004200000026673/newbits/kernel/USRSRC/coh/sys2.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */

/*
 * Coherent.
 * System calls (filesystem related).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.5  91/07/24  07:52:31  bin
 * update prov by hal
 * 
 * 
 * Revision 1.1	91/04/30  13:56:54	root
 * Shipped with COH 3.1.0.
 * 
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/fd.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/mount.h>
#include <sys/poll.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Determine accessibility of the given file.
 */
uaccess(np, mode)
char *np;
register int mode;
{
	register INODE *ip;
	register int r;

	schizo();
	r = ftoi(np, 'r');
	schizo();
	if (r != 0)
		return;
	ip = u.u_cdiri;
	if ((mode&imode(ip, u.u_ruid, u.u_rgid)) != mode)
		u.u_error = EACCES;
	idetach(ip);
	return (0);
}

/*
 * Schizo - swap real and effective id's.
 */
schizo()
{
	register int t;

	t = u.u_uid;
	u.u_uid = u.u_ruid;
	u.u_ruid = t;
	t = u.u_gid;
	u.u_gid = u.u_rgid;
	u.u_rgid = t;
}

/*
 * Turn accounting on or off.
 */
uacct(np)
register char *np;
{
	register INODE *ip;

	if (super() == 0)
		return;
	if (np == NULL) {
		if (acctip == NULL) {
			u.u_error = EINVAL;
			return;
		}
		ldetach(acctip);
		acctip = NULL;
	} else {
		if (acctip != NULL) {
			u.u_error = EINVAL;
			return;
		}
		if (ftoi(np, 'r') != 0)
			return;
		ip = u.u_cdiri;
		if ((ip->i_mode&IFMT) != IFREG) {
			u.u_error = EINVAL;
			idetach(ip);
			return;
		}
		iunlock(ip);
		acctip = ip;
	}
	return (0);
}

/*
 * Set current directory.
 */
uchdir(np)
char *np;
{
	setcdir(np, &u.u_cdir);
	return (0);
}

/*
 * Given a directory name and a pointer to a working directory pointer,
 * Save the inode associated with the directory name in the working
 * directory pointer and release the old one.  This is used to change
 * working and root directories.
 */
setcdir(np, ipp)
char *np;
register INODE **ipp;
{
	register INODE *ip;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if ((ip->i_mode&IFMT) != IFDIR) {
		u.u_error = ENOTDIR;
		idetach(ip);
		return;
	}
	if (iaccess(ip, IPE) == 0) {
		u.u_error = EACCES;
		idetach(ip);
		return;
	}
	iunlock(ip);
	ldetach(*ipp);
	*ipp = ip;
}

/*
 * Change the mode of a file.
 */
uchmod(np, mode)
char *np;
{
	register INODE *ip;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (owner(ip->i_uid)) {
		if (u.u_uid != 0)
			mode &= ~ISVTXT;
		ip->i_mode &= IFMT;
		ip->i_mode |= mode&~IFMT;
		icrt(ip);	/* chmod - ctime */
	}
	idetach(ip);
	return (0);
}

/*
 * Change owner and group of a file.
 */
uchown(np, uid, gid)
char *np;
{
	register INODE *ip;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (super()) {
		ip->i_mode &= ~(ISUID | ISGID);  /* clear any setuid/setgid */
		ip->i_uid = uid;
		ip->i_gid = gid;
		icrt(ip);	/* chown - ctime */
	}
	idetach(ip);
	return (0);
}

/*
 * Set root directory.
 */
uchroot(np)
register char *np;
{
	if (super())
		setcdir(np, &u.u_rdir);
	return (0);
}

/*
 * Close the given file descriptor.
 */
uclose(fd)
{
	fdclose(fd);
	return (0);
}

/*
 * Create a file with the given mode.
 */
ucreat(np, mode)
char *np;
register int mode;
{
	register INODE *ip;
	register int fd;
	register int cflag;

	cflag = 0;
	if (ftoi(np, 'c') != 0)
		return;
	if ((ip=u.u_cdiri) == NULL) {
		if ((ip=imake((mode&~IFMT)|IFREG, 0)) == NULL)
			return;
	} else {
		if (iaccess(ip, IPW)==0) {
			idetach(ip);
			return;
		}
		switch (ip->i_mode&IFMT) {
		case IFBLK:
		case IFCHR:
			break;
		case IFDIR:
			u.u_error = EISDIR;
			idetach(ip);
			return;
		default:
			if (getment(ip->i_dev, 1) == NULL) {
				idetach(ip);
				return;
			}
		}
		cflag = 1;
	}
	if ((fd=fdopen(ip, IPW)) < 0) {
		idetach(ip);
		return;
	}
	if (cflag)
		iclear(ip);
	iunlock(ip);
	return (fd);
}

/*
 * Duplicate a file descriptor.
 */
udup(ofd, nfd)
{
	return (fddup(ofd, nfd));
}

/*
 * Given a file descriptor, return a status structure.
 */
ufstat(fd, stp)
struct stat *stp;
{
	register INODE *ip;
	register FD *fdp;
	struct stat stat;

	if ((fdp=fdget(fd)) == NULL)
		return;
	ip = fdp->f_ip;
	istat(ip, &stat);
	kucopy(&stat, stp, sizeof(stat));
	return (0);
}

/*
 * File control.
 */
ufcntl( fd, cmd, arg )
int fd, cmd, arg;
{
	register FD * fdp;

	/*
	 * Validate file descriptor.
	 */
	if ( (fd < 0) || (fd >= NUFILE) || ((fdp = u.u_filep[fd]) == 0) ) {
		u.u_error = EBADF;
		return;
	}

	switch ( cmd ) {

	case F_DUPFD:
		/*
		 * Validate base file descriptor.
		 */
		if ( (arg < 0) || (arg >= NUFILE) ) {
			u.u_error = EINVAL;
			return;
		}

		/*
		 * Search for next available file descriptor.
		 */
		do {
			if ( u.u_filep[arg] == 0 ) {
				u.u_filep[arg] = fdp;
				fdp->f_refc++;
				return arg;
			}
		} while ( ++arg < NUFILE );

		u.u_error = EMFILE;
		return;

	case F_SETFL:
		fdp->f_flag &= ~IPNDLY;
		if ( arg & O_NDELAY )
			fdp->f_flag |= IPNDLY;
		if ( arg & O_APPEND )
			fdp->f_flag |= IPAPPEND;
		/* no break */

	case F_GETFL:
		switch ( fdp->f_flag & (IPR+IPW) ) {
		case IPR: arg = O_RDONLY; break;
		case IPW: arg = O_WRONLY; break;
		default:  arg = O_RDWR;   break;
		}
		if ( fdp->f_flag & IPNDLY )
			arg |= O_NDELAY;
		if ( fdp->f_flag & IPAPPEND )
			arg |= O_APPEND;
		return arg;

	default:
		u.u_error = EINVAL;
	}
}

/*
 * Device control information.
 */
uioctl(fd, r, argp)
struct sgttyb *argp;
{
	register FD *fdp;
	register INODE *ip;
	register int mode;

	if ((fdp=fdget(fd)) == NULL)
		return;
	ip = fdp->f_ip;
	mode = ip->i_mode&IFMT;
	if (mode!=IFCHR && mode!=IFBLK) {
		u.u_error = ENOTTY;
		return;
	}
	dioctl(ip->i_a.i_rdev, r, argp);
	return (0);
}

/*
 * Create a link, `np2' to the already existing file `np1'.
 */
ulink(np1, np2)
char *np1;
char *np2;
{
	register INODE *ip1;

	if (ftoi(np1, 'r') != 0)
		return;
	ip1 = u.u_cdiri;
	if ((ip1->i_mode&IFMT)==IFDIR && super()==0) {
		idetach(ip1);
		return;
	}
	iunlock(ip1);
	if (ftoi(np2, 'c') != 0) {
		ldetach(ip1);
		return;
	}
	if (u.u_cdiri != NULL) {
		u.u_error = EEXIST;
		idetach(u.u_cdiri);
		ldetach(ip1);
		return;
	}
	if (ip1->i_dev != u.u_pdiri->i_dev) {
		u.u_error = EXDEV;
		idetach(u.u_pdiri);
		ldetach(ip1);
		return;
	}
	if (iaccess(u.u_pdiri, IPW) == 0) {
		idetach(u.u_pdiri);
		ldetach(ip1);
		return;
	}
	idirent(ip1->i_ino);
	idetach(u.u_pdiri);
	ilock(ip1);
	ip1->i_nlink++;
	icrt(ip1);	/* link - ctime */
	idetach(ip1);
	return (0);
}

/*
 * Seek on the given file descriptor.
 */
fsize_t
ulseek(fd, off, w)
register fsize_t off;
{
	register FD *fdp;
	register INODE *ip;

	if ((fdp=fdget(fd)) == NULL)
		return;
	ip = fdp->f_ip;
	if ((ip->i_mode&IFMT) == IFPIPE) {
		u.u_error = ESPIPE;
		return;
	}
	switch (w) {
	case 0:
		break;
	case 1:
		off += fdp->f_seek;
		break;
	case 2:
		off += ip->i_size;
		break;
	default:
		u.u_error = EINVAL;
		return;
	}
	if (off < 0) {
		u.u_error = EINVAL;
		return;
	}
	fdp->f_seek = off;
	return (off);
}

/*
 * Create a special file.
 */
umknod(np, mode, rdev)
char *np;
dev_t rdev;
{
	register INODE *ip;
	register int type;

	type = mode&IFMT;
	if (type!=IFPIPE && super()==0)
		return;
	if (type!=IFBLK && type!=IFCHR)
		rdev = 0;
	if (ftoi(np, 'c') != 0)
		return;
	if ((ip=u.u_cdiri) != NULL) {
		u.u_error = EEXIST;
		idetach(ip);
		return;
	}
	if ((ip=imake(mode, rdev)) != NULL)
		idetach(ip);
	return (0);
}

/*
 * Mount the device `sp' on the pathname `np'.  The flag, `f',
 * indicates that the device is to be mounted read only.
 */
umount(sp, np, f)
char *sp;
char *np;
{
	register INODE *ip;
	register MOUNT *mp;
	register dev_t rdev;
	register int mode;

	if (ftoi(sp, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, IPR|IPW) == 0)
		goto err;
	mode = ip->i_mode;
	rdev = ip->i_a.i_rdev;
	if ((mode&IFMT) != IFBLK) {
		u.u_error = ENOTBLK;
		goto err;
	}
	idetach(ip);
	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, IPR) == 0)
		goto err;
	if ((ip->i_mode&IFMT) != IFDIR) {
		u.u_error = ENOTDIR;
		goto err;
	}
	/* Check for current directory, open, or mount directory */
	if (ip->i_refc > 1 || ip->i_ino == ROOTIN) {
		u.u_error = EBUSY;
		goto err;
	}
	for (mp=mountp; mp!=NULL; mp=mp->m_next) {
		if (mp->m_dev == rdev) {
			u.u_error = EBUSY;
			goto err;
		}
	}
	if ((mp=fsmount(rdev, f)) == NULL)
		goto err;
	mp->m_ip = ip;
	ip->i_flag |= IFMNT;
	ip->i_refc++;
err:
	idetach(ip);
	return (0);
}

/*
 * Poll devices for input/output events.
 */
int
upoll( pollfds, npoll, msec )
struct pollfd * pollfds;
unsigned long npoll;
int msec;
{
	register struct pollfd * pollp;	/* current poll pointer		 */
	register FD *	fdp;		/* current file descriptor ptr	 */
	auto	 int	fd;		/* current file descriptor	 */
	auto	 int	rev;		/* last event report received	 */
	auto	 int	nev;		/* number non-zero event reports */
	auto	 int	i;
	extern	 char *	udl;

	/*
	 * Validate number of polls.
	 */
	if ( (npoll < 0) || (npoll > NUFILE) ) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * Validate address of polling information.
	 */
	pollp = &pollfds[npoll];
	if ( (pollfds == NULL) || (pollp < pollfds) || (pollp > udl) ) {
		u.u_error = EFAULT;
		return;
	}

	do {
		/*
		 * Service each poll in turn.
		 */
		for ( nev=0, i=npoll, pollp = pollfds; i > 0; --i, pollp++ ) {

			/*
			 * Fetch file descriptor.
			 */
			fd = getuwd( &pollp->fd );

			/*
			 * Ignore negative file descriptors.
			 */
			if ( fd < 0 ) {
				rev = 0;
			}

			/*
			 * Poll message queue.
			 */
			else if ( fd >= NUFILE ) {
#ifdef MSGPOLL
/*
 * this code only good if msgpoll() is available to the kernel -
 * no good with loadable msg driver
 */
				rev = msgpoll(  fd,
						getuwd( &pollp->events),
						msec );
#else
				rev = POLLNVAL;
#endif
			}

			/*
			 * Validate file descriptor.
			 */
			else if ( (fdp = u.u_filep[fd]) == 0 ) {
				rev = POLLNVAL;
			}

			/*
			 * Non-character device.
			 */
			else if ( (fdp->f_ip->i_mode & IFMT) != IFCHR ) {
				rev = POLLNVAL;
			}

			/*
			 * Poll character device driver.
			 */
			else {
				rev = dpoll( fdp->f_ip->i_a.i_rdev,
						getuwd(&pollp->events),
						msec );
			}

			/*
			 * Remember reponses.
			 */
			putuwd( &pollp->revents, rev );

			/*
			 * Record number of non-zero responses.
			 */
			if ( rev != 0 ) {
				msec = 0;
				nev++;
			}
		}

		/*
		 * Non-blocking poll or poll response received.
		 */
		if ( msec == 0 ) {
			pollexit();
			return nev;
		}

		/*
		 * Schedule wakeup timer if positive delay interval given.
		 */
		if ( msec > 0 ) {
			/*
			 * Convert milliseconds to clock ticks.
			 */
			msec += (1000 / HZ) - 1;
			msec /= (1000 / HZ);
			timeout( &cprocp->p_polltim, msec,
				 wakeup, &cprocp->p_polls );
		}

		/*
		 * Wake for polled event, poll timeout, or signal.
		 */
		sleep( &cprocp->p_polls, CVTTOUT, IVTTOUT, SVTTOUT );

		/*
		 * Terminate event monitoring.
		 */
		pollexit();

		/*
		 * Perform non-blocking poll after first poll timeout.
		 */
		if ( msec > 0 ) {
			timeout( &cprocp->p_polltim, 0, NULL, NULL );
			msec = 0;
		}

		/*
		 * Signal woke us up.
		 */
		if ( nondsig() ) {
			u.u_error = EINTR;
			return -1;
		}

	} while ( msec != 0 );

	return 0;
}
0707070064030103171006440000030000030000011777770507310731600004200000017200/newbits/kernel/USRSRC/coh/sys3.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * System calls (more filesystem related calls).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:52:41  bin
 * update prov by hal
 * 
 * 
 * Revision 1.3	89/02/07  18:50:27	src
 * Bug:	Console driver did not validate user addresses before initiating a
 * 	transfer.  This resulted in a system trap in protected mode if a write
 * 	outside of user data space was attempted.
 * Fix:	Reads and writes now validate user addresses via 'useracc' prior to
 * 	calling drivers. (ABC)
 * 
 * Revision 1.2	88/08/02  15:01:04	src
 * O_APPEND flag now supported on open/fcntl system calls.
 * 
 * Revision 1.1	88/03/24  16:14:35	src
 * Initial revision
 * 
 * 88/01/22	Allan Cornish		/usr/src/sys/coh/sys3.c
 * sysio() inode lock extended to cover getting/modifying file seek offset.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/sys3.c
 * uopen() now checks mode for O_NDELAY and sets IPNDLY bit in fdp->f_flag.
 * sysio() now checks fdp->f_flag for IPNDLY and sets IONDLY bit in io_flag.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/fd.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Open the file `np' with the mode `mode'.
 */
uopen(np, mode)
char *np;
{
	register int f;
	register INODE *ip;
	register int fd;

	switch (mode & 3) {
	case O_RDONLY:
		f = IPR;
		break;
	case O_WRONLY:
		f = IPW;
		break;
	case O_RDWR:
		f = IPR|IPW;
		break;
	default:
		u.u_error = EINVAL;
		return;
	}
	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, f) == 0) {
		idetach(ip);
		return;
	}
	if ( mode & O_NDELAY )
		f |= IPNDLY;
	if ( mode & O_APPEND )
		f |= IPAPPEND;
	if ((fd=fdopen(ip, f)) < 0) {
		idetach(ip);
		return;
	}
	iunlock(ip);
	return (fd);
}

/*
 * Create a pipe.
 */
upipe(fdp)
int fdp[2];
{
	register INODE *ip;
	register int fd1;
	register int fd2;

	if ((ip=pmake(0)) == NULL)
		return;
	if ((fd1=fdopen(ip, IPR)) >= 0) {
		ip->i_refc++;
		if ((fd2=fdopen(ip, IPW)) >= 0) {
			putuwd(&fdp[0], fd1);
			putuwd(&fdp[1], fd2);
			iunlock(ip);
			return (0);
		}
		--ip->i_refc;
		iunlock(ip);
		fdclose(fd1);
		return (0);
	}
	idetach(ip);
	return (0);
}

/*
 * Read `n' bytes into the buffer `bp' from file number `fd'.
 */
uread(fd, bp, n)
char *bp;
unsigned n;
{
	return (sysio(fd, bp, n, 0));
}

/*
 * Read or write `n' bytes from the file number `fd' using the buffer
 * `bp'.  If `f' is 0, we read, else write.
 */
sysio(fd, bp, n, f)
char *bp;
unsigned n;
{
	register FD *fdp;
	register INODE *ip;
	register int type;

	if ((fdp=fdget(fd)) == NULL)
		return (0);
	if ((fdp->f_flag&(f?IPW:IPR)) == 0) {
		u.u_error = EBADF;
		return (0);
	}
	if ( ! useracc( bp, n ) ) {
		u.u_error = EFAULT;
		return(0);
	}

	ip = fdp->f_ip;
	type = ip->i_mode&IFMT;
	if (type != IFCHR)
		ilock(ip);
	if ( fdp->f_flag & IPAPPEND )
		fdp->f_seek = ip->i_size;
	u.u_io.io_seek = fdp->f_seek;
	u.u_io.io_base = bp;
	u.u_io.io_ioc  = n;
	u.u_io.io_flag = (fdp->f_flag & IPNDLY) ? IONDLY : 0;
	if (f == 0) {
		iread(ip, &u.u_io);
		iacc(ip);		/* read - atime */
	} else {
		iwrite(ip, &u.u_io);
	}
	n -= u.u_io.io_ioc;
	fdp->f_seek += n;
	if (type != IFCHR)
		iunlock(ip);
	return (n);
}

/*
 * Return a status structure for the given file name.
 */
ustat(np, stp)
char *np;
struct stat *stp;
{
	register INODE *ip;
	struct stat stat;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	istat(ip, &stat);
	idetach(ip);
	kucopy(&stat, stp, sizeof(stat));
	return (0);
}

/*
 * Write out all modified buffers, inodes and super blocks to disk.
 */
usync()
{
	register MOUNT *mp;
	static GATE syngate;

	lock(syngate);
	for (mp=mountp; mp!=NULL; mp=mp->m_next)
		msync(mp);
	bsync();
	unlock(syngate);
	return (0);
}

/*
 * Set the mask for file access.
 */
uumask(mask)
{
	register int omask;

	omask = u.u_umask;
	u.u_umask = mask & 0777;
	return (omask);
}

/*
 * Unmount the given device.
 */
uumount(sp)
char *sp;
{
	register INODE *ip;
	register MOUNT *mp;
	register MOUNT **mpp;
	register dev_t rdev;
	register int mode;

	if (ftoi(sp, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, IPR|IPW) == 0) {
		idetach(ip);
		return;
	}
	rdev = ip->i_a.i_rdev;
	mode = ip->i_mode;
	idetach(ip);
	if ((mode&IFMT) != IFBLK) {
		u.u_error = ENOTBLK;
		return;
	}
	for (mpp=&mountp; (mp=*mpp)!=NULL; mpp=&mp->m_next)
		if (mp->m_dev == rdev)
			break;
	if (mp == NULL) {
		u.u_error = EINVAL;
		return;
	}
	msync(mp);
	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_refc>0 && ip->i_dev==rdev) {
			u.u_error = EBUSY;
			return;
		}
	}
	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_dev == rdev)
			ip->i_ino = 0;
	}
	bflush(rdev);
	dclose(rdev);
	*mpp = mp->m_next;
	mp->m_ip->i_flag &= ~IFMNT;
	ldetach(mp->m_ip);
	kfree(mp);
	return (0);
}

/*
 * Return an unique number.
 */
long
uunique()
{
	register MOUNT *mp;
	register struct filsys *fsp;

	if ((mp=getment(rootdev, 1)) == NULL)
		return;
	fsp = &mp->m_super;
	fsp->s_fmod = 1;
	return (++fsp->s_unique);
}

/*
 * Unlink the given file.
 */
uunlink(np)
char *np;
{
	register INODE *ip;
	register dev_t dev;

	if (ftoi(np, 'u') != 0)
		return;
	ip = u.u_pdiri;
	if (iaccess(ip, IPW) == 0) {
		u.u_error = EACCES;
		goto err;
	}
	dev = ip->i_dev;
	if (iucheck(dev, u.u_cdirn) == 0)
		goto err;
	idirent(0);
	idetach(ip);
	if ((ip=iattach(dev, u.u_cdirn)) == NULL)
		return;
	if (ip->i_nlink > 0)
		--ip->i_nlink;
	icrt(ip);	/* unlink - ctime */
	if ((ip->i_mode&IFMT)==IFPIPE && ip->i_nlink==0 && ip->i_refc==2)
		pevent(ip);
err:
	idetach(ip);
	return (0);
}

/*
 * Set file times.
 */
uutime(np, utime)
char *np;
time_t utime[2];
{
	register INODE *ip;
	time_t stime[2];

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (owner(ip->i_uid)) {
		iamc(ip);	/* utime - atime/mtime/ctime */
		if (utime != NULL) {
			ukcopy(utime, stime, sizeof(time_t[2]));
			ip->i_atime = stime[0];
			ip->i_mtime = stime[1];
		}
	}
	idetach(ip);
	return (0);
}

/*
 * Write `n' bytes from buffer `bp' on file number `fd'.
 */
uwrite(fd, bp, n)
char *bp;
unsigned n;
{
	return (sysio(fd, bp, n, 1));
}

/**
 *
 * int
 * useracc( base, count, mode )	-- determine user accessibility
 * caddr_t base;
 * int count;
 * int mode;
 *
 *	Input:	base  = offset in user data space of the region to be accessed.
 *		count = size of access region in bytes.
 *		mode  = access mode desired [B_READ or B_WRITE].
 *
 *	Action:	Verify user has desired access mode into specified region.
 *
 *	Return:	0 = permission denied.
 *		1 = access allowed.
 *
 *	Notes:	Mode is ignored for now, but is required for compatibility
 *		with System V, and future protected mode extensions.
 */

int
useracc( base, count, mode )
register char * base;
int count;
int mode;
{
	register char * end;
	extern char * udl;

	if ( (count == 0) && (base <= udl) )
		return( 1 );

	/*
	 * Compute address of last byte to be accessed.
	 */
	end = base + count - 1;

	/*
	 * Address has wrapped, or is past legal limit.
	 */
	if ( (end < base) || (end > udl) )
		return( 0 );

	return( 1 );
}


0707070064030103161006440000030000030000011777770507310732000004500000006442/newbits/kernel/USRSRC/coh/timeout.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Timeout management.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:52:49  bin
 * update prov by hal
 * 
 * 
 * Revision 1.2	89/08/01  13:56:42 	src
 * Bug:	#include <timeout.h> not accurate; timeout.h now in /usr/include/sys.
 * Fix:	#include <sys/timeout.h> now used. (ABC)
 * 
 * Revision 1.1	88/03/24  08:14:38 	src
 * Initial revision
 * 
 * 87/07/23	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Timeout2 function now cancels timer if delay value is 0.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Timeout2 function added to support long timeouts.
 *
 * 87/07/07	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Support for multiple timing queues ported from RTX.
 *
 * 86/11/24	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Added support for new t_last field in tim struct.
 */
#include <sys/coherent.h>
#include <sys/timeout.h>
#include <sys/fun.h>

/*
 * Given a pointer to a timeout structure, `tp', call the function `f'
 * with integer argument `a' in `n' ticks of the clock. The list is
 * searched to see if the specified timeout structure is already in a
 * list, and it is removed if already there.
 */
timeout(tp, n, f, a)
register TIM *tp;
unsigned n;
int (*f)();
char *a;
{
	register TIM ** qp;
	int s;

	/*
	 * Already on a timing queue.
	 */
	s = sphi();
	if ( qp = tp->t_last ) {
		tp->t_last = NULL;
		if ( *qp = tp->t_next )
			tp->t_next->t_last = qp;
	}
	spl( s );

	if ( f == NULL )
		return;

	/*
	 * Calculate clock tick at which timeout is to occur.
	 * Record function and argument to be invoked upon timeout.
	 */
	tp->t_lbolt = lbolt + n;
	tp->t_func  = f;
	tp->t_farg  = a;

	/*
	 * Identify timeout queue.
	 */
	qp = &timq[ tp->t_lbolt % nel(timq) ];

	/*
	 * Insert at head of timeout queue.
	 */
	s = sphi();
	if ( tp->t_next = *qp )
		tp->t_next->t_last = tp;
	tp->t_last = qp;
	*qp = tp;
	spl(s);
}

timeout2(tp, n, f, a)
register TIM *tp;
long n;
int (*f)();
char *a;
{
	register TIM ** qp;
	int s;

	/*
	 * Already on a timing queue.
	 */
	s = sphi();
	if ( qp = tp->t_last ) {
		tp->t_last = NULL;
		if ( *qp = tp->t_next )
			tp->t_next->t_last = qp;
	}
	spl( s );

	/*
	 * Do not schedule new timer if no function or delay interval.
	 */
	if ( (f == NULL) || (n == 0) )
		return;

	/*
	 * Calculate clock tick at which timeout is to occur.
	 * Record function and argument to be invoked upon timeout.
	 */
	tp->t_lbolt = lbolt + n;
	tp->t_func  = f;
	tp->t_farg  = a;

	/*
	 * Identify timeout queue.
	 */
	qp = &timq[ tp->t_lbolt % nel(timq) ];

	/*
	 * Insert at head of timeout queue.
	 */
	s = sphi();
	if ( tp->t_next = *qp )
		tp->t_next->t_last = tp;
	tp->t_last = qp;
	*qp = tp;
	spl(s);
}
0707070064030103151006440000030000030000011777770507310732100004100000007544/newbits/kernel/USRSRC/coh/var.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Variables.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.4  91/07/24  07:52:52  bin
 * update prov by hal
 * 
 * 
 * Revision 1.2	89/08/01  13:57:35 	src
 * Bug:	#include <timeout.h> not accurate; timeout.h now in /usr/include/sys.
 * Fix:	#include <sys/timeout.h> now used. (ABC)
 * 
 * Revision 1.1	88/03/24  08:14:41 	src
 * Initial revision
 * 
 * 88/01/23	Allan Cornish		/usr/src/sys/coh/var.c
 * Default NSLOT increased from 10 to 64.
 *
 * 87/11/22	Allan Cornish		/usr/src/sys/coh/var.c
 * Holebot/holetop variables added to support extended memory.
 *
 * 87/11/14	Allan Cornish		/usr/src/sys/coh/var.c
 * Init code+data now split into icodep/icodes and idatap/idatas.
 *
 * 87/11/12	Allan Cornish		/usr/src/sys/coh/var.c
 * Corebot/coretop now paddr_t rather than saddr_t to support protected mode.
 *
 * 87/10/05	Allan Cornish		/usrs/rc/sys/coh/var.c
 * NSLOT, slotsz, and slotp variables added - loadable driver specific.
 *
 * 87/07/07	Allan Cornish		/usr/src/sys/coh/var.c
 * Lbolt variable added - clock ticks since startup - incremented by stand().
 * Timl variable replaced with timq variable.
 *
 * 87/02/01	Allan Cornish		/usr/src/sys/coh/var.c
 * ISTSIZE [stack size] changed from a define in /usr/include/sys/const.h to a
 * extern int in /usr/include/sys/param.h, with 4 Kbyte default set in var.c
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/con.h>
#include <sys/inode.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/seg.h>

int	 debflag = 0;			/* coherent.h */

int	 batflag;			/* coherent.h */
int	 outflag;			/* coherent.h */
int	 ttyflag;			/* coherent.h */
unsigned utimer;			/* coherent.h */
long	 lbolt;				/* coherent.h */
TIM	stimer;				/* coherent.h */
unsigned msize;				/* coherent.h */
unsigned asize;				/* coherent.h */
char	 *icodep;			/* coherent.h */
int	 icodes;			/* coherent.h */
char	 *idatap;			/* coherent.h */
int	 idatas;			/* coherent.h */
paddr_t	 corebot;			/* coherent.h */
paddr_t	 coretop;			/* coherent.h */
paddr_t	 holebot;			/* coherent.h */
paddr_t	 holetop;			/* coherent.h */
paddr_t	 blockp;			/* coherent.h */
paddr_t	 clistp;			/* coherent.h */
struct	 all *allkp;			/* coherent.h */
int	NSLOT	= 64;			/* coherent.h */
int	slotsz	= 64;			/* coherent.h */
int *	slotp;				/* coherent.h */

unsigned bufseqn;			/* buf.h */
int	 bufneed;			/* buf.h */
BUF	 swapbuf;			/* buf.h */
BUF	*bufl;				/* buf.h */

int	cltwant;			/* clist.h */
cmap_t	cltfree;			/* clist.h */

INODE	*inodep;			/* inode.h */
INODE	*acctip;			/* inode.h */

MOUNT	*mountp;			/* mount.h */

int	ISTSIZE	= 4096;			/* sys/param.h */

int	quantum;			/* proc.h */
int	disflag;			/* proc.h */
int	intflag;			/* proc.h */
int	cpid;				/* proc.h */
#ifdef QWAKEUP
int	ntowake;			/* proc.h */
#endif
GATE	pnxgate;			/* proc.h */
PROC	procq;				/* proc.h */
PROC	*iprocp;			/* proc.h */
PROC	*eprocp;			/* proc.h */
PROC	*cprocp;			/* proc.h */
PLINK	linkq[NHPLINK];			/* proc.h */

struct	ptrace pts;			/* ptrace.h */

int	sexflag;			/* seg.h */
GATE	seglink;			/* seg.h */
#ifndef NOMONITOR
int	swmflag;			/* seg.h */
#endif
SEG	segswap;			/* seg.h */
SEG	segmq;				/* seg.h */
SEG	segdq;				/* seg.h */
SEG	segiom;				/* seg.h */

TIM *	timq[256];			/* timeout.h */
0707070064030053140407550000030000030000011777770507310732200003700000000000/newbits/kernel/USRSRC/coh/RCS0707070064030053051004440000030000030000011777770507310732200004700000035353/newbits/kernel/USRSRC/coh/RCS/fs1.c,vhead     1.5;
branch   ;
access   ;
symbols  ;
locks    bin:1.5;
comment  @ * @;


1.5
date     91.07.24.07.50.40;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.07.15.14.32.16;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.20.14.30.01;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.10.14.37.05;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.04.12.14.02.18;  author root;  state Exp;
branches ;
next     ;


desc
@Part of kernel file system.
@


1.5
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Filesystem (mostly handling of in core inodes).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:47	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/fs1.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 86/12/13	Allan Cornish		/usr/src/sys/coh/fs1.c
 * isync() no longer updates the disk image of a character device inode.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/fs1.c
 * idirent() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/dir.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/mount.h>>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Get character for `ftoi' depending on what space the characters are
 * coming from.
 */
#define ftoic(p)	(u.u_io.io_seg==IOSYS ? *p : getubd(p))

/*
 * Map the given filename to an inode.  If an error is encountered,
 * `u.u_error' is set.  `u.u_error' is always returned.  As this routine
 * needs to set several things, depending on the type of access, `t',
 * there are places in the processes' user area reserved for this routine
 * to set.  These are defined in the user process structure.  The seek
 * position is always set to the position of the directory entry of the
 * child if the child exists or the first free position if it doesn't.
 *  'r' =>  Reference.  A pointer to the child's inode is returned locked.
 *  'c' =>  Create.  If the child exists, a pointer to the inode is returned
 *          locked.  Otherwise if the parent directory exists, a pointer to
 *          the parent directory is returned locked.  Otherwise, an error.
 *  'u' =>  Unlink.  The parent directory is returned unlocked.  The child's
 *          inode number is returned.  The seek position is also set.
 */
ftoi(np, t)
char *np;
{
	register INODE *cip;
	register char *cp;
	register int c;
	register struct direct *dp;
	register BUF *bp;
	fsize_t cseek, fseek, s;
	int fflag, mflag;
	dev_t dev;
	ino_t ino;
	daddr_t b;

	u.u_cdirn = 0;
	u.u_cdiri = NULL;
	u.u_pdiri = NULL;
	if ((c=ftoic(np++)) != '/')
		cip = u.u_cdir;
	else {
		c = ftoic(np++);
		cip = u.u_rdir;
	}
	while (c == '/')
		c = ftoic(np++);
	ilock(cip);
	cip->i_refc++;
	if (c == '\0') {
		if (t == 'r') {
			u.u_cdiri = cip;
			return (u.u_error);
		}
		u.u_error = ENOENT;
		idetach(cip);
		return (u.u_error);
	}
	for (;;) {
		cp = u.u_direct.d_name;
		while (c!='/' && c!='\0') {
			if (cp < &u.u_direct.d_name[DIRSIZ])
				*cp++ = c;
			c = ftoic(np++);
		}
		while (c == '/')
			c = ftoic(np++);
		while (cp < &u.u_direct.d_name[DIRSIZ])
			*cp++ = '\0';
		if ((cip->i_mode&IFMT) != IFDIR)
			u.u_error = ENOTDIR;
		else
			iaccess(cip, IPE);
		if (u.u_error) {
			idetach(cip);
			return (u.u_error);
		}
		cp = u.u_direct.d_name;
		if (cip->i_ino==ROOTIN && cip->i_dev!=rootdev)
			if (*cp++=='.' && *cp++=='.' && *cp++=='\0')
				cip = ftoim(cip);
		b = 0;
		fflag = 0;
		mflag = 0;
		cseek = 0;
		s = cip->i_size;
		while (s > 0) {
			if ((bp=vread(cip, b++)) == NULL) {
				idetach(cip);
				return (u.u_error);
			}
			dp = FP_OFF(bp->b_faddr);
			while (dp < FP_OFF(bp->b_faddr)+BSIZE) {
				if ((s-=sizeof(*dp)) < 0)
					break;
				if ((ino=dp->d_ino) == 0) {
					if (fflag == 0) {
						fflag++;
						fseek = cseek;
					}
				} else {
					if (direq(dp)) {
						canino(ino);
						mflag = 1;
						s = 0;
						break;
					}
				}
				cseek += sizeof(*dp);
				dp++;
			}
			brelease(bp);
		}
		dev = cip->i_dev;
		if (fflag == 0)
			fseek = cseek;
		if (mflag == 0) {
			if (c=='\0' && t=='c') {
				u.u_pdiri = cip;
				u.u_io.io_seek = fseek;
			} else {
				u.u_error = ENOENT;
				idetach(cip);
			}
			return (u.u_error);
		}
		if (c == '\0') {
			if (t == 'u') {
				u.u_cdirn = ino;
				u.u_pdiri = cip;
				u.u_io.io_seek = cseek;
				return (u.u_error);
			}
			idetach(cip);
			u.u_cdiri = iattach(dev, ino);
			return (u.u_error);
		}
		idetach(cip);
		if ((cip=iattach(dev, ino)) == NULL)
			return (u.u_error);
	}
}

/*
 * Given an inode which is the root of a file system, return the inode
 * on which the file system was mounted.
 */
INODE *
ftoim(ip)
register INODE *ip;
{
	register MOUNT *mp;

	for (mp=mountp; mp!=NULL; mp=mp->m_next) {
		if (mp->m_dev == ip->i_dev) {
			idetach(ip);
			ip = mp->m_ip;
			ilock(ip);
			ip->i_refc++;
			break;
		}
	}
	return (ip);
}

/*
 * Compare the string in `u.u_direct.d_name' with the name in the
 * given directory pointer.
 */
direq(dp)
struct direct *dp;
{
	register char *cp1, *cp2;
	register unsigned n;

	if (dp->d_ino == 0)
		return (0);
	cp1 = dp->d_name;
	cp2 = u.u_direct.d_name;
	n = DIRSIZ;
	do {
		if (*cp1++ != *cp2++)
			return (0);
	} while (--n);
	return (1);
}

/*
 * Make an inode of the given mode and device.  The parent directory,
 * name and such stuff is set by ftoi.
 */
INODE *
imake(mode, rdev)
unsigned mode;
dev_t rdev;
{
	register INODE *ip;

	ip = NULL;
	mode &= ~u.u_umask;
	if ((mode&ISVTXT)!=0 && super()==0)
		goto det;
	if (iaccess(u.u_pdiri, IPW) == 0)
		goto det;
	if ((ip=ialloc(u.u_pdiri->i_dev, mode)) == NULL)
		goto det;
	ip->i_nlink = 1;
	ip->i_a.i_rdev = rdev;
	idirent(ip->i_ino);
	iamc(ip);	/* creat/mknod - atime/mtime/ctime */
det:
	idetach(u.u_pdiri);
	return (ip);
}

/*
 * Write a directory entry out.  Everything necessary has been conveniently
 * set by `ftoi', except the new inode number of this directory entry.
 */
idirent(ino)
{
	u.u_direct.d_ino = ino;
	canino(u.u_direct.d_ino);
	u.u_io.io_ioc  = sizeof (struct direct);
	u.u_io.io_base = &u.u_direct;
	u.u_io.io_seg  = IOSYS;
	u.u_io.io_flag = 0;
	iwrite(u.u_pdiri, &u.u_io);
}

/*
 * Return a pointer to a locked inode in core containing the given
 * inode number and device.
 */
INODE *
iattach(dev, ino)
{
	register INODE *ip;
	register INODE *fip;
	register unsigned lrt;
	register MOUNT *mp;

	for (;;) {
		fip = NULL;
		for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
			if (ip->i_ino==ino && ip->i_dev==dev)
				break;
			if (ip->i_refc == 0) {
				if (fip==NULL || ip->i_lrt<lrt) {
					fip = ip;
					lrt = ip->i_lrt;
				}
			}
		}
		if (ip < inodep) {
			if ((ip=fip) == NULL) {
				devmsg(dev, "Inode table overflow");
/*DEBUG*/
{ char cmd[11];int i;
for(i=0;i<10&&u.u_comm[i];i++)
    cmd[i]=u.u_comm[i];
cmd[i]='\0';
printf("cmd=%s time=%lu\n",cmd, u.u_btime);
}
				u.u_error = ENFILE;
				return (NULL);
			}
			ilock(ip);
			if (ip->i_refc != 0) {
				iunlock(ip);
				continue;
			}
			ip->i_dev = dev;
			ip->i_ino = ino;
			ip->i_refc = 1;
			ip->i_lrt = timer.t_time;
			if (icopydm(ip) == 0) {
				ip->i_ino = 0;
				ip->i_refc = 0;
				iunlock(ip);
				return (NULL);
			}
			return (ip);
		}
		if ((ip->i_flag&IFMNT) != 0) {
			for (mp=mountp; mp!=NULL; mp=mp->m_next) {
				if (mp->m_ip == ip) {
					ino = ROOTIN;
					dev = mp->m_dev;
					break;
				}
			}
			continue;
		}
		ilock(ip);
		if (ip->i_ino!=ino || ip->i_dev!=dev) {
			iunlock(ip);
			continue;
		}
		if (ip->i_refc < 0)
			panic("ialloc(%p), ip");
		ip->i_refc++;
		ip->i_lrt = timer.t_time;
		return (ip);
	}
}

/*
 * Given a locked inode, deaccess it.
 */
idetach(ip)
register INODE *ip;
{
	if (ilocked(ip)==0 || ip->i_refc<=0)
		panic("idetach(%p)", ip);
	if (--ip->i_refc == 0) {
		if ((ip->i_flag&(IFACC|IFMOD|IFCRT)) != 0
		 || ip->i_nlink == 0)
			icopymd(ip);
	}
	iunlock(ip);
}

/*
 * Given a inode which isn't locked, lock it and then deaccess.
 */
ldetach(ip)
register INODE *ip;
{
	ilock(ip);
	idetach(ip);
}

/*
 * A specialized routine for finding whether the given inode may be unlinked.
 * Quite simple you say, but we already have an inode locked and could run
 * into gating problems if we were to lock another.  So we look through the
 * cache to see if the inode is there.  If it is, we can easily tell.  If it
 * isn't, `icopydm' is called with a static.  This routine is only used by
 * `uunlink'.
 */
iucheck(dev, ino)
register dev_t dev;
register ino_t ino;
{
	register INODE *ip;
	INODE inode;

	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_ino==ino && ip->i_dev==dev)
			break;
	}
	if (ip < inodep) {
		ip = &inode;
		ip->i_dev = dev;
		ip->i_ino = ino;
		if (icopydm(ip) == 0)
			return (0);
	}
	if ((ip->i_mode&IFMT) == IFDIR) {
		if (super() == 0)
			return (0);
	}
	return (1);
}

/*
 * Copy an inode from disk to memory performing canonization.
 */
icopydm(ip)
register INODE *ip;
{
	register struct dinode *dip;
	register BUF *bp;
	register ino_t ino;
	struct dinode dinode;
	vaddr_t v;

	ip->i_flag = 0;
	ino = ip->i_ino;

	if ((bp=bread(ip->i_dev, (daddr_t)iblockn(ino), 1)) == NULL)
		return (0);

	dip = &dinode;
	v = (char *)((struct dinode *)FP_OFF(bp->b_faddr) + iblocko(ino));
	kkcopy( v, dip, sizeof(dinode));
	brelease(bp);
	ip->i_mode = dip->di_mode;
	canshort(ip->i_mode);
	ip->i_nlink = dip->di_nlink;
	canshort(ip->i_nlink);
	ip->i_uid = dip->di_uid;
	canshort(ip->i_uid);
	ip->i_gid = dip->di_gid;
	canshort(ip->i_gid);
	ip->i_size = dip->di_size;
	cansize(ip->i_size);

	switch (ip->i_mode&IFMT) {
	case IFBLK:
	case IFCHR:
		ip->i_a.i_rdev = dip->di_a.di_rdev;
		candev(ip->i_a.i_rdev);
		break;
	case IFREG:
	case IFDIR:
		l3tol(ip->i_a.i_addr, dip->di_a.di_addb, NADDR);
		break;
	case IFPIPE:
		l3tol(ip->i_pipe, dip->di_addp, ND);
		ip->i_pnc = dip->di_pnc;
		canint(ip->i_pnc);
		ip->i_prx = dip->di_prx;
		canint(ip->i_prx);
		ip->i_pwx = dip->di_pwx;
		canint(ip->i_pwx);
		break;
	default:
		kclear(&ip->i_a, sizeof(ip->i_a));
		break;
	}

	ip->i_atime = dip->di_atime;
	cantime(ip->i_atime);
	ip->i_mtime = dip->di_mtime;
	cantime(ip->i_mtime);
	ip->i_ctime = dip->di_ctime;
	cantime(ip->i_ctime);
	return (1);
}

/*
 * Copy an inode from memory back on to disk performing canonization.
 */
icopymd(ip)
register INODE *ip;
{
	register struct dinode *dip;
	register BUF *bp;
	register ino_t ino;
	struct dinode dinode;
	vaddr_t v;

	if (getment(ip->i_dev, 0) == NULL)
		return;

	ino = ip->i_ino;
	if (ip->i_refc==0 && ip->i_nlink==0 && ino!=BADFIN && ino!=ROOTIN) {
		iclear(ip);
		ip->i_lrt = 0;
		ip->i_mode = 0;
		ifree(ip->i_dev, ino);
	}

	dip = &dinode;
	dip->di_mode = ip->i_mode;
	canshort(dip->di_mode);
	dip->di_nlink = ip->i_nlink;
	canshort(dip->di_nlink);
	dip->di_uid = ip->i_uid;
	canshort(dip->di_uid);
	dip->di_gid = ip->i_gid;
	canshort(dip->di_gid);
	dip->di_size = ip->i_size;
	cansize(dip->di_size);

	switch (ip->i_mode&IFMT) {
	case IFBLK:
	case IFCHR:
		dip->di_a.di_rdev = ip->i_a.i_rdev;
		candev(dip->di_a.di_rdev);
		break;
	case IFREG:
	case IFDIR:
		ltol3(dip->di_addr, ip->i_a.i_addr, NADDR);
		break;
	case IFPIPE:
		ltol3(dip->di_addp, ip->i_pipe, ND);
		dip->di_pnc = ip->i_pnc;
		canshort(dip->di_pnc);
		dip->di_prx = ip->i_prx;
		canshort(dip->di_prx);
		dip->di_pwx = ip->i_pwx;
		canshort(dip->di_pwx);
		break;
	default:
		kclear(&dip->di_a, sizeof(dip->di_a));
		break;
	}

	dip->di_atime = ip->i_atime;
	cantime(dip->di_atime);
	dip->di_mtime = ip->i_mtime;
	cantime(dip->di_mtime);
	dip->di_ctime = ip->i_ctime;
	cantime(dip->di_ctime);

	if ((bp=bread(ip->i_dev, (daddr_t)iblockn(ino), 1)) == NULL)
		return;

	v = (char *)((struct dinode *)FP_OFF(bp->b_faddr) + iblocko(ino));
	kkcopy(dip, v, sizeof(dinode));
	bp->b_flag |= BFMOD;
	brelease(bp);
	ip->i_flag &= ~(IFACC|IFMOD|IFCRT);
}

/*
 * Copy all relevant inodes out on device `dev'.
 */
isync(dev)
register dev_t dev;
{
	register INODE *ip;

	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_refc == 0)
			continue;
		if (ip->i_dev != dev)
			continue;
		if ( (ip->i_mode & IFMT) == IFCHR )
			continue;
		if ((ip->i_flag&(IFACC|IFMOD|IFCRT)) == 0)
			continue;
		icopymd(ip);
	}
}

/*
 * Clear the given inode and all space associated with it.
 */
iclear(ip)
register INODE *ip;
{
	register int n;
	register daddr_t b;

	switch (ip->i_mode&IFMT) {
	case IFPIPE:
		ip->i_pnc = 0;
		ip->i_prx = 0;
		ip->i_pwx = 0;
		n = ND;
		break;
	case IFDIR:
	case IFREG:
		n = NADDR;
		break;
	default:
		return;
	}
	while (n > ND) {
		if ((b=ip->i_a.i_addr[--n]) != 0)
			indfree(ip->i_dev, b, 1+n-ND);
	}
	while (n > 0) {
		if ((b=ip->i_a.i_addr[--n]) != 0)
			bfree(ip->i_dev, b);
	}
	ip->i_size = 0;
	kclear(ip->i_a.i_addr, sizeof(ip->i_a.i_addr));
	iamc(ip);	/* creat/pipe - atime/mtime/ctime */
}

/*
 * Copy the appropriate information from the inode to the stat buffer.
 */
istat(ip, sbp)
register INODE *ip;
register struct stat *sbp;
{
	sbp->st_dev = ip->i_dev;
	sbp->st_ino = ip->i_ino;
	sbp->st_mode = ip->i_mode;
	sbp->st_nlink = ip->i_nlink;
	sbp->st_uid = ip->i_uid;
	sbp->st_gid = ip->i_gid;
	sbp->st_rdev = NODEV;
	sbp->st_size = ip->i_size;
	sbp->st_atime = ip->i_atime;
	sbp->st_mtime = ip->i_mtime;
	sbp->st_ctime = ip->i_ctime;
	switch (ip->i_mode&IFMT) {
	case IFBLK:
	case IFCHR:
		sbp->st_rdev = ip->i_a.i_rdev;
		sbp->st_size = 0;
		break;
	case IFPIPE:
		sbp->st_size = ip->i_pnc;
		break;
	}
}

/*
 * See if it is possible to access the given inode with the bits in
 * the given mode.
 * If the mode includes writing, and i_refc is > 1, then check for
 * shared text problems.
 */
iaccess(ip, mode)
register INODE *ip;
register int mode;
{
	if ((imode(ip, u.u_uid, u.u_gid)&mode) != mode) {
		u.u_error = EACCES;
		return (0);
	}
	if ((mode&IPW) != 0 && ip->i_refc > 1 && sbusy(ip)) {
		u.u_error = ETXTBSY;
		return (0);
	}
	return (1);
}

/*
 * Get the maximum allowable mode on a file.
 */
imode(ip, uid, gid)
register INODE *ip;
{
	if (uid == 0)
		return (IPR|IPW|IPE);
	if (uid == ip->i_uid)
		return ((ip->i_mode>>6)&07);
	if (gid == ip->i_gid)
		return ((ip->i_mode>>3)&07);
	return (ip->i_mode&07);
}
@


1.4
log
@update by hal
@
text
@@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@initial version prov by hal
@
text
@d32 1
a32 1
#include <coherent.h>
@


1.1
log
@used in COH 3.0.0 and 3.1.0
@
text
@d301 7
@
0707070064030031751004440000030000030000011777770507310732600005000000030344/newbits/kernel/USRSRC/coh/RCS/sys2.c,vhead     1.5;
branch   ;
access   ;
symbols  ;
locks    bin:1.5;
comment  @ * @;


1.5
date     91.07.24.07.52.31;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.07.15.14.34.07;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.20.14.31.42;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.10.14.37.45;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.04.30.13.56.54;  author root;  state Exp;
branches ;
next     ;


desc
@File system system calls.
@


1.5
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */

/*
 * Coherent.
 * System calls (filesystem related).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	91/04/30  13:56:54	root
 * Shipped with COH 3.1.0.
 * 
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/fd.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/mount.h>
#include <sys/poll.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Determine accessibility of the given file.
 */
uaccess(np, mode)
char *np;
register int mode;
{
	register INODE *ip;
	register int r;

	schizo();
	r = ftoi(np, 'r');
	schizo();
	if (r != 0)
		return;
	ip = u.u_cdiri;
	if ((mode&imode(ip, u.u_ruid, u.u_rgid)) != mode)
		u.u_error = EACCES;
	idetach(ip);
	return (0);
}

/*
 * Schizo - swap real and effective id's.
 */
schizo()
{
	register int t;

	t = u.u_uid;
	u.u_uid = u.u_ruid;
	u.u_ruid = t;
	t = u.u_gid;
	u.u_gid = u.u_rgid;
	u.u_rgid = t;
}

/*
 * Turn accounting on or off.
 */
uacct(np)
register char *np;
{
	register INODE *ip;

	if (super() == 0)
		return;
	if (np == NULL) {
		if (acctip == NULL) {
			u.u_error = EINVAL;
			return;
		}
		ldetach(acctip);
		acctip = NULL;
	} else {
		if (acctip != NULL) {
			u.u_error = EINVAL;
			return;
		}
		if (ftoi(np, 'r') != 0)
			return;
		ip = u.u_cdiri;
		if ((ip->i_mode&IFMT) != IFREG) {
			u.u_error = EINVAL;
			idetach(ip);
			return;
		}
		iunlock(ip);
		acctip = ip;
	}
	return (0);
}

/*
 * Set current directory.
 */
uchdir(np)
char *np;
{
	setcdir(np, &u.u_cdir);
	return (0);
}

/*
 * Given a directory name and a pointer to a working directory pointer,
 * Save the inode associated with the directory name in the working
 * directory pointer and release the old one.  This is used to change
 * working and root directories.
 */
setcdir(np, ipp)
char *np;
register INODE **ipp;
{
	register INODE *ip;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if ((ip->i_mode&IFMT) != IFDIR) {
		u.u_error = ENOTDIR;
		idetach(ip);
		return;
	}
	if (iaccess(ip, IPE) == 0) {
		u.u_error = EACCES;
		idetach(ip);
		return;
	}
	iunlock(ip);
	ldetach(*ipp);
	*ipp = ip;
}

/*
 * Change the mode of a file.
 */
uchmod(np, mode)
char *np;
{
	register INODE *ip;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (owner(ip->i_uid)) {
		if (u.u_uid != 0)
			mode &= ~ISVTXT;
		ip->i_mode &= IFMT;
		ip->i_mode |= mode&~IFMT;
		icrt(ip);	/* chmod - ctime */
	}
	idetach(ip);
	return (0);
}

/*
 * Change owner and group of a file.
 */
uchown(np, uid, gid)
char *np;
{
	register INODE *ip;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (super()) {
		ip->i_mode &= ~(ISUID | ISGID);  /* clear any setuid/setgid */
		ip->i_uid = uid;
		ip->i_gid = gid;
		icrt(ip);	/* chown - ctime */
	}
	idetach(ip);
	return (0);
}

/*
 * Set root directory.
 */
uchroot(np)
register char *np;
{
	if (super())
		setcdir(np, &u.u_rdir);
	return (0);
}

/*
 * Close the given file descriptor.
 */
uclose(fd)
{
	fdclose(fd);
	return (0);
}

/*
 * Create a file with the given mode.
 */
ucreat(np, mode)
char *np;
register int mode;
{
	register INODE *ip;
	register int fd;
	register int cflag;

	cflag = 0;
	if (ftoi(np, 'c') != 0)
		return;
	if ((ip=u.u_cdiri) == NULL) {
		if ((ip=imake((mode&~IFMT)|IFREG, 0)) == NULL)
			return;
	} else {
		if (iaccess(ip, IPW)==0) {
			idetach(ip);
			return;
		}
		switch (ip->i_mode&IFMT) {
		case IFBLK:
		case IFCHR:
			break;
		case IFDIR:
			u.u_error = EISDIR;
			idetach(ip);
			return;
		default:
			if (getment(ip->i_dev, 1) == NULL) {
				idetach(ip);
				return;
			}
		}
		cflag = 1;
	}
	if ((fd=fdopen(ip, IPW)) < 0) {
		idetach(ip);
		return;
	}
	if (cflag)
		iclear(ip);
	iunlock(ip);
	return (fd);
}

/*
 * Duplicate a file descriptor.
 */
udup(ofd, nfd)
{
	return (fddup(ofd, nfd));
}

/*
 * Given a file descriptor, return a status structure.
 */
ufstat(fd, stp)
struct stat *stp;
{
	register INODE *ip;
	register FD *fdp;
	struct stat stat;

	if ((fdp=fdget(fd)) == NULL)
		return;
	ip = fdp->f_ip;
	istat(ip, &stat);
	kucopy(&stat, stp, sizeof(stat));
	return (0);
}

/*
 * File control.
 */
ufcntl( fd, cmd, arg )
int fd, cmd, arg;
{
	register FD * fdp;

	/*
	 * Validate file descriptor.
	 */
	if ( (fd < 0) || (fd >= NUFILE) || ((fdp = u.u_filep[fd]) == 0) ) {
		u.u_error = EBADF;
		return;
	}

	switch ( cmd ) {

	case F_DUPFD:
		/*
		 * Validate base file descriptor.
		 */
		if ( (arg < 0) || (arg >= NUFILE) ) {
			u.u_error = EINVAL;
			return;
		}

		/*
		 * Search for next available file descriptor.
		 */
		do {
			if ( u.u_filep[arg] == 0 ) {
				u.u_filep[arg] = fdp;
				fdp->f_refc++;
				return arg;
			}
		} while ( ++arg < NUFILE );

		u.u_error = EMFILE;
		return;

	case F_SETFL:
		fdp->f_flag &= ~IPNDLY;
		if ( arg & O_NDELAY )
			fdp->f_flag |= IPNDLY;
		if ( arg & O_APPEND )
			fdp->f_flag |= IPAPPEND;
		/* no break */

	case F_GETFL:
		switch ( fdp->f_flag & (IPR+IPW) ) {
		case IPR: arg = O_RDONLY; break;
		case IPW: arg = O_WRONLY; break;
		default:  arg = O_RDWR;   break;
		}
		if ( fdp->f_flag & IPNDLY )
			arg |= O_NDELAY;
		if ( fdp->f_flag & IPAPPEND )
			arg |= O_APPEND;
		return arg;

	default:
		u.u_error = EINVAL;
	}
}

/*
 * Device control information.
 */
uioctl(fd, r, argp)
struct sgttyb *argp;
{
	register FD *fdp;
	register INODE *ip;
	register int mode;

	if ((fdp=fdget(fd)) == NULL)
		return;
	ip = fdp->f_ip;
	mode = ip->i_mode&IFMT;
	if (mode!=IFCHR && mode!=IFBLK) {
		u.u_error = ENOTTY;
		return;
	}
	dioctl(ip->i_a.i_rdev, r, argp);
	return (0);
}

/*
 * Create a link, `np2' to the already existing file `np1'.
 */
ulink(np1, np2)
char *np1;
char *np2;
{
	register INODE *ip1;

	if (ftoi(np1, 'r') != 0)
		return;
	ip1 = u.u_cdiri;
	if ((ip1->i_mode&IFMT)==IFDIR && super()==0) {
		idetach(ip1);
		return;
	}
	iunlock(ip1);
	if (ftoi(np2, 'c') != 0) {
		ldetach(ip1);
		return;
	}
	if (u.u_cdiri != NULL) {
		u.u_error = EEXIST;
		idetach(u.u_cdiri);
		ldetach(ip1);
		return;
	}
	if (ip1->i_dev != u.u_pdiri->i_dev) {
		u.u_error = EXDEV;
		idetach(u.u_pdiri);
		ldetach(ip1);
		return;
	}
	if (iaccess(u.u_pdiri, IPW) == 0) {
		idetach(u.u_pdiri);
		ldetach(ip1);
		return;
	}
	idirent(ip1->i_ino);
	idetach(u.u_pdiri);
	ilock(ip1);
	ip1->i_nlink++;
	icrt(ip1);	/* link - ctime */
	idetach(ip1);
	return (0);
}

/*
 * Seek on the given file descriptor.
 */
fsize_t
ulseek(fd, off, w)
register fsize_t off;
{
	register FD *fdp;
	register INODE *ip;

	if ((fdp=fdget(fd)) == NULL)
		return;
	ip = fdp->f_ip;
	if ((ip->i_mode&IFMT) == IFPIPE) {
		u.u_error = ESPIPE;
		return;
	}
	switch (w) {
	case 0:
		break;
	case 1:
		off += fdp->f_seek;
		break;
	case 2:
		off += ip->i_size;
		break;
	default:
		u.u_error = EINVAL;
		return;
	}
	if (off < 0) {
		u.u_error = EINVAL;
		return;
	}
	fdp->f_seek = off;
	return (off);
}

/*
 * Create a special file.
 */
umknod(np, mode, rdev)
char *np;
dev_t rdev;
{
	register INODE *ip;
	register int type;

	type = mode&IFMT;
	if (type!=IFPIPE && super()==0)
		return;
	if (type!=IFBLK && type!=IFCHR)
		rdev = 0;
	if (ftoi(np, 'c') != 0)
		return;
	if ((ip=u.u_cdiri) != NULL) {
		u.u_error = EEXIST;
		idetach(ip);
		return;
	}
	if ((ip=imake(mode, rdev)) != NULL)
		idetach(ip);
	return (0);
}

/*
 * Mount the device `sp' on the pathname `np'.  The flag, `f',
 * indicates that the device is to be mounted read only.
 */
umount(sp, np, f)
char *sp;
char *np;
{
	register INODE *ip;
	register MOUNT *mp;
	register dev_t rdev;
	register int mode;

	if (ftoi(sp, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, IPR|IPW) == 0)
		goto err;
	mode = ip->i_mode;
	rdev = ip->i_a.i_rdev;
	if ((mode&IFMT) != IFBLK) {
		u.u_error = ENOTBLK;
		goto err;
	}
	idetach(ip);
	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, IPR) == 0)
		goto err;
	if ((ip->i_mode&IFMT) != IFDIR) {
		u.u_error = ENOTDIR;
		goto err;
	}
	/* Check for current directory, open, or mount directory */
	if (ip->i_refc > 1 || ip->i_ino == ROOTIN) {
		u.u_error = EBUSY;
		goto err;
	}
	for (mp=mountp; mp!=NULL; mp=mp->m_next) {
		if (mp->m_dev == rdev) {
			u.u_error = EBUSY;
			goto err;
		}
	}
	if ((mp=fsmount(rdev, f)) == NULL)
		goto err;
	mp->m_ip = ip;
	ip->i_flag |= IFMNT;
	ip->i_refc++;
err:
	idetach(ip);
	return (0);
}

/*
 * Poll devices for input/output events.
 */
int
upoll( pollfds, npoll, msec )
struct pollfd * pollfds;
unsigned long npoll;
int msec;
{
	register struct pollfd * pollp;	/* current poll pointer		 */
	register FD *	fdp;		/* current file descriptor ptr	 */
	auto	 int	fd;		/* current file descriptor	 */
	auto	 int	rev;		/* last event report received	 */
	auto	 int	nev;		/* number non-zero event reports */
	auto	 int	i;
	extern	 char *	udl;

	/*
	 * Validate number of polls.
	 */
	if ( (npoll < 0) || (npoll > NUFILE) ) {
		u.u_error = EINVAL;
		return;
	}

	/*
	 * Validate address of polling information.
	 */
	pollp = &pollfds[npoll];
	if ( (pollfds == NULL) || (pollp < pollfds) || (pollp > udl) ) {
		u.u_error = EFAULT;
		return;
	}

	do {
		/*
		 * Service each poll in turn.
		 */
		for ( nev=0, i=npoll, pollp = pollfds; i > 0; --i, pollp++ ) {

			/*
			 * Fetch file descriptor.
			 */
			fd = getuwd( &pollp->fd );

			/*
			 * Ignore negative file descriptors.
			 */
			if ( fd < 0 ) {
				rev = 0;
			}

			/*
			 * Poll message queue.
			 */
			else if ( fd >= NUFILE ) {
#ifdef MSGPOLL
/*
 * this code only good if msgpoll() is available to the kernel -
 * no good with loadable msg driver
 */
				rev = msgpoll(  fd,
						getuwd( &pollp->events),
						msec );
#else
				rev = POLLNVAL;
#endif
			}

			/*
			 * Validate file descriptor.
			 */
			else if ( (fdp = u.u_filep[fd]) == 0 ) {
				rev = POLLNVAL;
			}

			/*
			 * Non-character device.
			 */
			else if ( (fdp->f_ip->i_mode & IFMT) != IFCHR ) {
				rev = POLLNVAL;
			}

			/*
			 * Poll character device driver.
			 */
			else {
				rev = dpoll( fdp->f_ip->i_a.i_rdev,
						getuwd(&pollp->events),
						msec );
			}

			/*
			 * Remember reponses.
			 */
			putuwd( &pollp->revents, rev );

			/*
			 * Record number of non-zero responses.
			 */
			if ( rev != 0 ) {
				msec = 0;
				nev++;
			}
		}

		/*
		 * Non-blocking poll or poll response received.
		 */
		if ( msec == 0 ) {
			pollexit();
			return nev;
		}

		/*
		 * Schedule wakeup timer if positive delay interval given.
		 */
		if ( msec > 0 ) {
			/*
			 * Convert milliseconds to clock ticks.
			 */
			msec += (1000 / HZ) - 1;
			msec /= (1000 / HZ);
			timeout( &cprocp->p_polltim, msec,
				 wakeup, &cprocp->p_polls );
		}

		/*
		 * Wake for polled event, poll timeout, or signal.
		 */
		sleep( &cprocp->p_polls, CVTTOUT, IVTTOUT, SVTTOUT );

		/*
		 * Terminate event monitoring.
		 */
		pollexit();

		/*
		 * Perform non-blocking poll after first poll timeout.
		 */
		if ( msec > 0 ) {
			timeout( &cprocp->p_polltim, 0, NULL, NULL );
			msec = 0;
		}

		/*
		 * Signal woke us up.
		 */
		if ( nondsig() ) {
			u.u_error = EINTR;
			return -1;
		}

	} while ( msec != 0 );

	return 0;
}
@


1.4
log
@update by hal
@
text
@@


1.3
log
@update provided by hal
@
text
@@


1.2
log
@
@
text
@d25 1
a25 1
#include <coherent.h>
@


1.1
log
@Shipped with COH 3.1.0.
@
text
@d1 1
a1 1
/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
d20 4
a23 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d32 1
d598 5
d606 3
@
0707070064030053111005550000030000030000011777770507310733200004500000000441/newbits/kernel/USRSRC/coh/RCS/RCS,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.36.00;  author bin;  state Exp;
branches ;
next	;


desc
@@



1.1
log
@Initial revision
@
text
@.3..fs1.c,vsys2.c,v#,RCS,',RCSnew00380a@
0707070064030076111004440000030000030000011777770507310733200005100000005612/newbits/kernel/USRSRC/coh/RCS/alloc.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.48.16;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.31.20;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.29.04;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.36.03;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@initial version prov by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Storage allocator.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:25	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/alloc.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/uproc.h>

/*
 * Create an arena.
 */
ALL *
setarena(cp, n)
register char *cp;
{
	register ALL *ap1;
	register ALL *ap2;

	if ((char *)(ap1=align(cp)) < (char *)cp)
		ap1++;
	if ((ap2=align(&cp[n])-1) < ap1)
		panic("Arena %o too small", (int) cp);
	ap1->a_link = (char *)ap2;
	ap2->a_link = (char *)ap1;
	setused(ap2);
	return (ap1);
}

/*
 * Allocate `l' bytes of memory.
 */
char *
alloc(apq, l)
ALL *apq;
unsigned l;
{
	register ALL *ap;
	register ALL *ap1;
	register ALL *ap2;
	register unsigned i;
	register unsigned n;
	register unsigned s;

	n = 1 + (l + sizeof(ALL) - 1) / sizeof(ALL);
	for (i=0; i<2; i++) {
		for (ap1=apq; link(ap1)!=apq; ap1=link(ap1)) {
			if (ap1 == NULL)
				panic("Corrupt arena");
			if (tstfree(ap1)) {
			       for (ap2=link(ap1); tstfree(ap2); ap2=link(ap2))
					if (ap2 == apq)
						break;
				ap1->a_link = (char *)ap2;
				if ((s=ap2-ap1) >= n) {
					if (s > n) {
						if (i == 0)
							continue;
						ap = &ap1[n];
						ap->a_link = (char *)ap2;
						ap1->a_link = (char *)ap;
					}
					setused(ap1);
					kclear((char *)ap1->a_data, l);
					return (ap1->a_data);
				}
			}
		}
	}
	u.u_error = EKSPACE;
	return (NULL);
}

/*
 * Free memory.
 */
free(cp)
char *cp;
{
	register ALL *ap;
	extern char end;

	ap = ((ALL *)cp) - 1;
	if (ap<(ALL *)&end || tstfree(ap))
		panic("Bad free %o\n", (unsigned)cp);
	setfree(ap);
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d24 2
a25 2
#include <coherent.h>
#include <alloc.h>
@
0707070064030113641004440000030000030000011777770507310733300004700000033005/newbits/kernel/USRSRC/coh/RCS/bio.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.49.45;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.31.29;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.29.21;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.36.13;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Buffered I/O.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:29	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/bio.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/bio.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/bio.c
 * ioreq() now only wakes &stimer if the swap timer is active.
 *
 * 86/12/12	Allan Cornish		/usr/src/sys/coh/bio.c
 * Added 3rd arg to dpoll() to specify blocking poll if non-zero.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/bio.c
 * Added dpoll() routine to perform device polls [System V.3 compatible].
 *
 * 86/07/24	Allan Cornish		/usr/src/sys/coh/bio.c
 * Added check in devinit() for null dp->d_conp->c_load function pointer.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Initialise buffer headers.
 */
bufinit()
{
	register BUF *bp;
	faddr_t f;
	paddr_t p;

	FP_SEL(f) = sds;
	FP_OFF(f) = 0;
	p = blockp;
	FP_OFF(f) = blockp - vtop(f);

	bufl = kalloc(NBUF * sizeof(BUF));
	if (bufl == NULL)
		panic("bufinit: no space for BUF's");

	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		bp->b_dev = NODEV;
		bp->b_faddr = f;
		bp->b_paddr = p;
		FP_OFF(f) += BSIZE;
		p += BSIZE;
	}
}

/*
 * Synchronise the buffer cache.
 */
bsync()
{
	register BUF *bp;

	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		if ((bp->b_flag&BFMOD) == 0)
			continue;
		lock(bp->b_gate);
		if ((bp->b_flag&BFMOD) != 0)
			bwrite(bp, 1);
		unlock(bp->b_gate);
	}
}

/*
 * Synchronise all block for a particular device in the buffer cache
 * and invalidate all references.
 */
bflush(dev)
register dev_t dev;
{
	register BUF *bp;

	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		if (bp->b_dev != dev)
			continue;
		lock(bp->b_gate);
		if (bp->b_dev == dev) {
			if ((bp->b_flag&BFMOD) != 0)
				bwrite(bp, 1);
			bp->b_dev = NODEV;
		}
		unlock(bp->b_gate);
	}
}

/*
 * Return a buffer containing the given block from the given device.
 * If `f' is not set, the read is asynchronous and no buffer is returned.
 */
BUF *
bread(dev, bno, f)
dev_t dev;
daddr_t bno;
register int f;
{
	register BUF *bp;
	register int s;

	bp = bclaim(dev, bno);
	if ((bp->b_flag&BFNTP) != 0) {
		if (f != 0)
			bp->b_flag &= ~BFASY;
		else {
			bp->b_flag |= BFASY;
			bumap(bp);
		}
		bp->b_req = BREAD;
		bp->b_count = BSIZE;
		s = sphi();
		dblock(dev, bp);
		if (f == 0) {
			spl(s);
			return (NULL);
		}
		while ((bp->b_flag&BFNTP) != 0)
			sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
		spl(s);
		if ((bp->b_flag&BFERR) != 0) {
			u.u_error = bp->b_err ? bp->b_err : EIO;
			brelease(bp);
			return (NULL);
		}
		if (bp->b_resid == BSIZE) {
			brelease(bp);
			return (NULL);
		}
	}
	if (f == 0) {
		brelease(bp);
		return (NULL);
	}
	u.u_block++;
	return (bp);
}

/*
 * If the requested buffer is in the buffer cache, return a pointer to
 * it.  If not, pick an empty buffer, set it up and return it.
 */
BUF *
bclaim(dev, bno)
dev_t dev;
daddr_t bno;
{
	register BUF *bp;
	register BUF *bp1;
	register unsigned seqn;
	register int s;

again:
	bp1 = NULL;
	seqn = 0;
	for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
		if (bp->b_bno == bno  &&  bp->b_dev == dev) {
			lock(bp->b_gate);
			if (bp->b_bno != bno  ||  bp->b_dev != dev) {
				unlock(bp->b_gate);
				goto again;
			}
			if ((bp->b_flag&BFERR) != 0)
				bp->b_flag |= BFNTP;
			bsmap(bp);
			return (bp);
		}
		if (locked(bp->b_gate) == 0) {
			if (bufseqn-bp->b_seqn >= seqn) {
				bp1 = bp;
				seqn = bufseqn - bp->b_seqn;
			}
		}
	}
	if (bp1 == NULL) {
		s = sphi();
		for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
			if (locked(bp->b_gate) == 0) {
				if (bufseqn-bp->b_seqn >= seqn) {
					bp1 = bp;
					seqn = bufseqn - bp->b_seqn;
				}
			}
		}
		if (bp1 == NULL) {
			bufneed = 1;
			sleep((char *)&bufneed, CVBLKIO, IVBLKIO, SVBLKIO);
			spl(s);
			goto again;
		}
		spl(s);
	}
	bp = bp1;
	lock(bp->b_gate);
	if ((bp->b_flag&BFMOD) != 0) {
		bwrite(bp, 0);
		goto again;
	}
	bp->b_flag = BFNTP;
	bp->b_dev = dev;
	bp->b_bno = bno;
	bsmap(bp);
	return (bp);
}

/*
 * Write the given buffer out.  If `f' is set, the write is synchronous,
 * otherwise asynchronous.  This routine must be called with the buffer
 * gate locked.
 */
bwrite(bp, f)
register BUF *bp;
{
	register int s;

	if (f != 0)
		bp->b_flag &= ~BFASY;
	else {
		bp->b_flag |= BFASY;
		bumap(bp);
	}
	bp->b_flag |= BFNTP;
	bp->b_req = BWRITE;
	bp->b_count = BSIZE;
	s = sphi();
	dblock(bp->b_dev, bp);
	if (f == 0) {
		spl(s);
		return;
	}
	while ((bp->b_flag&BFNTP) != 0)
		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
	spl(s);
}

/*
 * This is called by the driver when I/O has completed on a buffer.
 */
bdone(bp)
register BUF *bp;
{
	if (bp->b_req == BWRITE)
		bp->b_flag &= ~BFMOD;
	if (bp->b_req == BREAD) {
		if ((bp->b_flag&BFERR) != 0)
			bp->b_dev = NODEV;
	}
	if ((bp->b_flag&BFASY) != 0) {
		bp->b_flag &= ~BFASY;
		brelease(bp);
	}
	bp->b_flag &= ~BFNTP;
	wakeup((char *)bp);
}

/*
 * Release the given buffer.
 */
brelease(bp)
register BUF *bp;
{
	if ((bp->b_flag&BFERR) == 0)
		bp->b_seqn = bufseqn++;
	else {
		bp->b_flag &= ~BFERR;
		bp->b_dev = NODEV;
	}
	bp->b_flag &= ~BFNTP;
	bumap(bp);
	unlock(bp->b_gate);
	if (bufneed != 0) {
		bufneed = 0;
		wakeup((char *)&bufneed);
	}
}

/*
 * Map the given buffer.
 */
bsmap(bp)
register BUF *bp;
{
	bsave(bp->b_map);
	bp->b_flag |= BFMAP;
	bmapv(bconv(bp->b_paddr));
}

/*
 * Unmap the given buffer.
 */
bumap(bp)
register BUF *bp;
{
	if ((bp->b_flag&BFMAP) == 0)
		return;
	bp->b_flag &= ~BFMAP;
	brest(bp->b_map);
}

/*
 * Read data from the I/O segment into kernel space.
 */
ioread(iop, v, n)
register IO *iop;
register char *v;
register unsigned n;
{
	switch (iop->io_seg) {
	case IOSYS:
		iop->io_base += kkcopy(iop->io_base, v, n);
		break;
	case IOUSR:
		iop->io_base += ukcopy(iop->io_base, v, n);
		break;
	case IOPHY:
		iop->io_phys += pkcopy(iop->io_phys, v, n);
		break;
	}
	iop->io_ioc -= n;
}

/*
 * Write data from kernel space to the I/O segment.
 */
iowrite(iop, v, n)
register IO *iop;
register char *v;
register unsigned n;
{
	switch (iop->io_seg) {
	case IOSYS:
		iop->io_base += kkcopy(v, iop->io_base, n);
		break;
	case IOUSR:
		iop->io_base += kucopy(v, iop->io_base, n);
		break;
	case IOPHY:
		iop->io_phys += kpcopy(v, iop->io_phys, n);
		break;
	}
	iop->io_ioc -= n;
}

/*
 * Get a character from the I/O segment.
 */
iogetc(iop)
register IO *iop;
{
	register int c;

	if (iop->io_ioc == 0)
		return (-1);
	--iop->io_ioc;
	if (iop->io_seg == IOSYS)
		c = *iop->io_base++ & 0377;
	else {
		c = getubd(iop->io_base++);
		if (u.u_error)
			return (-1);
	}
	return (c);
}

/*
 * Put a character using the I/O segment.
 */
ioputc(c, iop)
register IO *iop;
{
	if (iop->io_ioc == 0)
		return (-1);
	--iop->io_ioc;
	if (iop->io_seg == IOSYS)
		*iop->io_base++ = c;
	else {
		putubd(iop->io_base++, c);
		if (u.u_error)
			return (-1);
	}
	return (c);
}

/*
 * Given a buffer pointer, an I/O structure, a device, request type, and
 * a flags word, check the I/O structure and perform the I/O request.
 */
ioreq(bp, iop, dev, req, f)
register BUF *bp;
register IO *iop;
dev_t dev;
{
	register SEG *sp;
	register int n;
	register int s;
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	lock(bp->b_gate);
	n = cp->c_flag;	/* n should do something with that flag */
	drest(dold);
	sp = NULL;
	if (iop != NULL) {
		if ((f&BFBLK) != 0) {
			if (blocko(iop->io_seek) != 0) {
				u.u_error = EIO;
				goto out;
			}
		}
		if ((f&BFIOC) != 0) {
			if ((sp=iomapvp(iop, bp)) == NULL) {
				u.u_error = EIO;
				goto out;
			}
		}
	}
	bp->b_flag = f|BFNTP;
	bp->b_req = req;
	bp->b_dev = dev;
	if (iop != NULL) {
		bp->b_bno = blockn(iop->io_seek);
		bp->b_count = iop->io_ioc;
	}
	if (sp != NULL) {
		bp->b_faddr = ptov( bp->b_paddr, (fsize_t) bp->b_count );
		sp->s_lrefc++;
	}
	s = sphi();
	dblock(dev, bp);
	while ((bp->b_flag&BFNTP) != 0)
		sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
	spl(s);
	if (sp != NULL) {
		vrelse( bp->b_faddr );
		sp->s_lrefc--;
	}
	if (stimer.t_last != 0)
		wakeup((char *)&stimer);
	if ((bp->b_flag&BFERR) != 0) {
		u.u_error = bp->b_err ? bp->b_err : EIO;
		goto out;
	}
	if (iop != NULL) {
		n = iop->io_ioc - bp->b_resid;
		iop->io_seek += n;
		iop->io_ioc -= n;
	}
out:
	unlock(bp->b_gate);
}

/*
 * Given an I/O structure and a buffer header, see if the addresses
 * in the I/O structure are valid and set up the buffer header.
 */
SEG *
iomapvp(iop, bp)
register IO *iop;
register BUF *bp;
{
	register SR *srp;
	register SEG *sp;
	register vaddr_t b;

	if (iop->io_seg != IOUSR)
		panic("Raw I/O from non user");
	for (srp=u.u_segl; srp<&u.u_segl[NUSEG]; srp++) {
		if ((sp=srp->sr_segp) == NULL)
			continue;
		if ((srp->sr_flag&SRFDATA) == 0)
			continue;
/* Yet another bug in the 8000 C compiler
		if ((long)(b=iop->io_base) < (long)srp->sr_base)
*/
		if ((b=iop->io_base) < srp->sr_base)
			continue;
		if ((long)b+iop->io_ioc > (long)srp->sr_base + sp->s_size)
			continue;
		bp->b_paddr = sp->s_paddr + (vaddr_t) (b - srp->sr_base);
		return (sp);
	}
	return (NULL);
}

/*
 * Initialise devices.
 */
devinit()
{
	register DRV *dp;
	register int mind;

	for ( dp = drvl, mind = 0; mind < drvn; mind++, dp++ ) {
		if ((dp->d_conp != NULL) && (dp->d_conp->c_load != NULL)) {
			(*dp->d_conp->c_load)();
		}
	}
}

/*
 * Open a device.
 */
dopen(dev, m, f)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	if ((cp->c_flag&f) == 0) {
		u.u_error = ENXIO;
		return;
	}
	(*cp->c_open)(dev, m);
	drest(dold);
}

/*
 * Close a device.
 */
dclose(dev)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_close)(dev);
	drest(dold);
}

/*
 * Call the block entry point of a device.
 */
dblock(dev, bp)
dev_t dev;
BUF *bp;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_block)(bp);
	drest(dold);
}

/*
 * Read from a device.
 */
dread(dev, iop)
register dev_t dev;
register IO *iop;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_read)(dev, iop);
	drest(dold);
}

/*
 * Write to a device.
 */
dwrite(dev, iop)
register dev_t dev;
register IO *iop;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_write)(dev, iop);
	drest(dold);
}

/*
 * Call the ioctl function for a device.
 */
dioctl(dev, com, vec)
register dev_t dev;
union ioctl *vec;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_ioctl)(dev, com, vec);
	drest(dold);
}

/*
 * Call the powerfail entry point of a device.
 */
dpower(dev)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_power)(dev);
	drest(dold);
}

/*
 * Call the timeout entry point of a device.
 */
dtime(dev)
register dev_t dev;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return;
	(*cp->c_timer)(dev);
	drest(dold);
}

/*
 * Poll a device.
 */
dpoll(dev, ev, msec)
register dev_t dev;
int ev;
int msec;
{
	register CON *cp;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return POLLNVAL;

	if ( cp->c_flag & DFPOL )
		ev = (*cp->c_poll)(dev, ev, msec);
	else
		ev = POLLNVAL;

	drest(dold);
	return ev;
}

/*
 * Given a device, return the flags word.
 */
dflag(dev)
dev_t dev;
{
	register CON *cp;
	register int f;
	dold_t dold;

	if ((cp=drvmap(dev, &dold)) == NULL)
		return (DFERR);
	f = cp->c_flag;
	drest(dold);
	return (f);
}

/*
 * Given a device, and a pointer to a driver map save area, save the
 * current map in the driver map save area and map in the new device,
 * returning a pointer to the configuration entry for that device.
 */
CON *
drvmap(dev, doldp)
dev_t dev;
dold_t *doldp;
{
	register DRV *dp;
	register unsigned m;

	if ((m=major(dev)) >= drvn) {
		u.u_error = ENXIO;
		return (NULL);
	}
	dp = &drvl[m];
	if (locked(dp->d_gate)) {
		u.u_error = ENXIO;
		return (NULL);
	}
	if (dp->d_conp == NULL) {
		u.u_error = ENXIO;
		return (NULL);
	}
	dsave(*doldp);
	if (dp->d_map != 0)
		dmapv(dp->d_map);
	return (dp->d_conp);
}

/*
 * Non existant device.
 */
nonedev()
{
	u.u_error = ENXIO;
}

/*
 * Null device.
 */
nulldev()
{
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d41 1
a41 1
#include <coherent.h>
d47 1
a47 1
#include <sched.h>
@
0707070064030000521004440000030000030000011777770507310733600005100000006714/newbits/kernel/USRSRC/coh/RCS/clist.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.50.03;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.31.43;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.29.34;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.36.53;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Character list management.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:33	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <clist.h>
#include <sched.h>

/*
 * Initialise character list queues.
 */
cltinit()
{
	register cmap_t cm;
	register cmap_t lm;
	register paddr_t p;
	register int s;
	cold_t om;

	s = sphi();
	csave(om);
	lm = 0;
	for (p = clistp+NCLIST*sizeof(CLIST); (p-=sizeof(CLIST)) >= clistp; ) {
		cm = cconv(p);
		cmapv(cm);
		cvirt(cm)->cl_fp = lm;
		lm = cm;
	}
	cltfree = lm;
	crest(om);
	spl(s);
}

/*
 * Get a character from the given queue.
 */
getq(cqp)
register CQUEUE *cqp;
{
	register cmap_t op;
	register cmap_t np;
	register int ox;
	register int c;
	register int s;
	cold_t om;

	if (cqp->cq_cc == 0)
		return (-1);
	s = sphi();
	op = cqp->cq_op;
	ox = cqp->cq_ox;
	csave(om);
	cmapv(op);
	c = cvirt(op)->cl_ch[ox]&0377;
	crest(om);
	if (--cqp->cq_cc==0 || ++cqp->cq_ox==NCPCL) {
		cqp->cq_ox = 0;
		cmapv(op);
		np = cvirt(op)->cl_fp;
		cvirt(op)->cl_fp = cltfree;
		crest(om);
		cqp->cq_op = np;
		cltfree = op;
		if (np == 0) {
			cqp->cq_ip = 0;
			cqp->cq_ix = 0;
		}
		if (cltwant) {
			cltwant = 0;
			wakeup((char *)&cltwant);
		}
	}
	spl(s);
	return (c);
}

/*
 * Put a character on the given queue.
 */
putq(cqp, c)
register CQUEUE *cqp;
{
	register cmap_t ip;
	register int ix;
	register int s;
	register cmap_t np;
	cold_t om;

	s = sphi();
	ip = cqp->cq_ip;
	csave(om);
	if ((ix=cqp->cq_ix) == 0) {
		if ((ip=cltfree) == 0) {
			spl(s);
			return (-1);
		}
		cmapv(ip);
		cltfree = cvirt(ip)->cl_fp;
		cvirt(ip)->cl_fp = 0;
		crest(om);
		if ((np=cqp->cq_ip) == 0)
			cqp->cq_op = ip;
		else {
			cmapv(np);
			cvirt(np)->cl_fp = ip;
			crest(om);
		}
		cqp->cq_ip = ip;
	}
	cmapv(ip);
	cvirt(ip)->cl_ch[ix] = c;
	crest(om);
	if (++cqp->cq_ix == NCPCL)
		cqp->cq_ix = 0;
	cqp->cq_cc++;
	spl(s);
	return (c);
}

/*
 * Clear a character queue.
 */
clrq(cqp)
register CQUEUE *cqp;
{
	register int s;

	s = sphi();
	while (getq(cqp) >= 0)
		;
	spl(s);
}

/*
 * Wait for more character queues to become available.
 */
waitq()
{
	while (cltfree == 0) {
		cltwant = 1;
		sleep((char *)&cltwant, CVCLIST, IVCLIST, SVCLIST);
	}
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d24 1
a24 1
#include <coherent.h>
@
0707070064030053061004440000030000030000011777770507310733700005100000015375/newbits/kernel/USRSRC/coh/RCS/clock.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2;
comment  @ * @;


1.2
date     91.06.20.14.29.38;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.36.56;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Clock.
 * The clock comes in two parts.  There is the routine `clock' which
 * gets called every tick at high priority.  It does the minimum it
 * can and returns as soon as possible.  The second routine, `stand',
 * gets called whenever we are about to return from an interrupt to
 * user mode a low priority.  It can look at flags that the clock set
 * and do the things the clock really wanted to do but didn't have time.
 * Stand is truly the kernel of the system.
 *
 * 90/08/13	Hal Snyder		/usr/src/sys/coh/clock.c
 * Add external altclk to allow polled device drivers.
 * (extern'ed in coherent.h)
 * 
 * 87/10/26	Allan cornish		/usr/src/sys/coh/clock.c
 * Timed functions are now invoked with TIM * tp as second argument.
 * This facilitates the use of timed functions within loadable drivers.
 *
 * 87/07/07	Allan Cornish		/usr/src/sys/coh/clock.c
 * Clocks static variable added - incremented by clock, decremented by stand().
 * Lbolt variable added - clock ticks since startup - incremented by stand().
 * Support for multiple timing queues ported from RTX.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/clock.c
 * stand() now only wakes &stimer if swap timer is active.
 *
 * 86/11/24	Allan Cornish		/usr/src/sys/coh/clock.c
 * Added support for new t_last field in tim struct.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/clock.c
 * Stand() calls defend() to execute functions deferred from interrupt level.
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <sys/timeout.h>
#include <sys/uproc.h>
#include <sys/mdata.h>

int (*altclk)();	/* pointer to higher-speed clock function */
int altsel;	/* if nonzero, CS for LOADABLE driver owning altclk() */

static int clocks;

/*
 * This routine is called once every tick (1/HZ seconds).
 * It gets called with the programme counter that was interrupted
 * a flag telling whether we were in user or kernel mode and the
 * previous priority we were in.
 */
clock(pc, umode)
vaddr_t pc;
{
	register PROC *pp;
	/*
	 * Ignore clock interrupts till we are ready.
	 */
	if (batflag == 0)
		return;

	/*
	 * Hook for alternate clock interrupt;
	 * Call polling function ("altclk") if there is one.
	 *
	 * For near function, "altsel" is 0 and "altclk" is offset.
	 * For far function, "altsel" is the CS selector and "altclk"
	 * is the offset.
	 *
	 * Since the polling function ends with a near rather than
	 * far return, far invocation is via ld_call() (ldas.s) which uses
	 * the despatch routine at CS:4 (ld.s) in any loadable driver.
	 */
	if (altclk) {
		if (altsel) {	/* will do far call to altclk fn */
			if (ld_call(altsel, altclk))
				return;
		} else
			if ((*altclk)())
				return;
	}

	/*
	 * Update timers.  Decrement time slice.
	 */
	utimer += 1;
	clocks += 1;
	timer.t_tick += 1;
	quantum -= 1;

	/*
	 * Give processes their schedule values per tick.
	 */
	if (procq.p_lforw->p_cval > CVCLOCK) {
		procq.p_lforw->p_cval -= CVCLOCK;
		procq.p_cval += CVCLOCK;
	}

	/*
	 * Tax current process and update his times.
	 */
	pp = SELF;
	pp->p_cval >>= 1;
	if (umode == 0)
		pp->p_stime++;
	else {
		pp->p_utime++;
		u.u_ppc = pc;
	}
}

/*
 * Do everything the clock wanted to do but couldn't as it would have
 * taken too long.
 * Also perform any system bookkeeping required at regular intervals.
 */
stand()
{
	int s;

	u.u_error = 0;

	/*
	 * Update the clock.
	 */
	while (timer.t_tick >= HZ) {
		timer.t_time++;
		timer.t_tick -= HZ;
		outflag = 1;
	}

	/*
	 * Check expiration of quantum.
	 */
	if (quantum <= 0) {
		quantum = 0;
		disflag = 1;
	}

	/*
	 * Check the timed function queue if necessary.
	 */
	if ( clocks > 0 )
	do {
		register TIM * np;
		register TIM * tp;

		/*
		 * Update [serviced] clock ticks since startup.
		 */
		lbolt++;

		/*
		 * Remove timing list from queue, creating new temporary queue.
		 */
		tp = (TIM *) &timq[ lbolt % nel(timq) ];
		s  = sphi();

		/*
		 * Scan timing list.
		 */
		for ( np = tp->t_next; tp = np; ) {

			/*
			 * Remember next function in timing list.
			 * NOTE: Must be done before function is invoked,
			 *	 since it may start a new timer.
			 */
			np = tp->t_next;

			/*
			 * Function has not timed out: leave it on timing list.
			 */
			if ( tp->t_lbolt != lbolt )
				continue;

			/*
			 * Remove function from timing list.
			 */
			if ( tp->t_last->t_next = tp->t_next )
				tp->t_next->t_last = tp->t_last;
			tp->t_last = NULL;

			/*
			 * Invoke function.
			 */
			spl(s);
			(*tp->t_func)( tp->t_farg, tp );
			sphi();
		}

		spl( s );

	} while ( --clocks > 0 );

	/*
	 * Timeout any devices.
	 */
	if (outflag) {
		register int n;

		outflag = 0;
		for (n=0; n<drvn; n++) {
			if (drvl[n].d_time == 0)
				continue;
			s = sphi();
			dtime((dev_t)makedev(n, 0));
			spl(s);
		}
	}

	/*
	 * Do profiling.
	 */
	if (u.u_pscale != 0) {
		register unsigned p;
		register vaddr_t a;

		p = u.u_pscale;
		a = (int *)u.u_pbase +
		    pscale(u.u_ppc-u.u_pofft, p/sizeof (int));
		if (a < u.u_pbend)
			putuwd(a, getuwd(a)+1);
	}

	/*
	 * Check for signals and execute them.
	 */
	if (SELF->p_ssig)
		actvsig();

	/*
	 * Execute deferred functions.
	 */
	defend();

	/*
	 * Should we dispatch?
	 */
	if ((SELF->p_flags&PFDISP) != 0) {
		SELF->p_flags &= ~PFDISP;
		disflag = 1;
		if ( stimer.t_last != 0 )
			wakeup((char *)&stimer);
	}

#ifdef QWAKEUP
	/*
	 * Dispatch pending wakeups.
	 */
	while (ntowake)
		wakeup2();

#endif
	/*
	 * Redispatch.
	 * This used to be a function call in tsave,
	 * expanded in line here.
	 */
	if (disflag) {
		register PROC *pp;

#ifndef QWAKEUP
		s=sphi();
#endif
		if ((pp=SELF)!=iprocp)
			setrun(pp);
		dispatch();
#ifndef QWAKEUP
		spl(s);
#endif
	}
}
@


1.1
log
@Initial revision
@
text
@d1 1
a1 1
/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
d28 1
a28 1
 * (extern'ed in /usr/src/sys/sys/coherent.h)
@
0707070064030031551004440000030000030000011777770507310734100005000000032525/newbits/kernel/USRSRC/coh/RCS/exec.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.50.20;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.31.51;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.29.45;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.36.59;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Exec and driver load code.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:39	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/exec.c
 * Exsread() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <l.out.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Sizes.
 */
#define	sh	((fsize_t)sizeof(struct ldheader))
#define si	lssize[L_SHRI]
#define pi	lssize[L_PRVI]
#define bi	lssize[L_BSSI]
#define sd	lssize[L_SHRD]
#define pd	lssize[L_PRVD]
#define bd	lssize[L_BSSD]

/*
 * Segments.
 */
#define upsp	pp->p_segp[SIUSERP]
#define sssp	pp->p_segp[SISTACK]
#define	sisp	pp->p_segp[SISTEXT]
#define pisp	pp->p_segp[SIPTEXT]
#define sdsp	pp->p_segp[SISDATA]
#define pdsp	pp->p_segp[SIPDATA]

/*
 * Set up the first process, a small programme which will exec
 * the init programme.
 */
eveinit(sp)
SEG *sp;
{
	register PROC *pp;

	SELF = pp = eprocp;
	pp->p_segp[SIUSERP] = sp;
	if ((sp=salloc((fsize_t)icodes, 0)) == NULL)
		panic("eveinit()");
	pp->p_segp[SIPDATA] = sp;
	kscopy(icodep, sp, 0, icodes);
	if ((sp=salloc((fsize_t)UPASIZE, SFDOWN)) == NULL)
		panic("eveinit()");
	pp->p_segp[SISTACK] = sp;
	u.u_argp = 0;
	if (sproto() == 0)
		panic("eveinit()");
	segload();
}

/*
 * Given a major number, a file containing a device driver and a configuration
 * pointer, load the driver on the major number.
 */
pload(m, np, cp)
char *np;
CON *cp;
{
	register INODE *ip;
	register SEG *sp;
	register DRV *dp;
	register fsize_t ss;
	dold_t dold;
	int lflag;
	int r;
	vaddr_t pc;
	fsize_t lssize[NUSEG];

	if (m >= drvn) {
		u.u_error = ENXIO;
		return;
	}
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL)
		return;
	ss = pi+si+pd+sd;
	sp = ssalloc(&r, ip, SFSHRX, ss+bi+bd, sh, ss);
	idetach(ip);
	if (r < 0)
		return;
	dp = &drvl[m];
	lock(dp->d_gate);
	if (dp->d_conp != NULL) {
		unlock(dp->d_gate);
		sfree(sp);
		u.u_error = EDBUSY;
		return;
	}
	dp->d_time = 0;
	dp->d_conp = cp;
	dp->d_segp = sp;
	dp->d_map = sp->s_mbase;
	dsave(dold);
	dmapv(dp->d_map);
	(*cp->c_load)();
	drest(dold);
	unlock(dp->d_gate);
}

/*
 * Given a major number, undo the previous function.
 */
puload(m)
int m;
{
	register CON *cp;
	register DRV *dp;
	dold_t dold;

	dp = &drvl[m];
	lock(dp->d_gate);
	if (m>=drvn || dp->d_segp==NULL || (cp=dp->d_conp)==NULL) {
		u.u_error = ENXIO;
		goto ret;
	}
	dsave(dold);
	dmapv(dp->d_map);
	(*cp->c_uload)();
	drest(dold);
	if (u.u_error)
		goto ret;
	sfree(dp->d_segp);
	dp->d_conp = NULL;
	dp->d_segp = NULL;
	dp->d_map = 0;
ret:
	unlock(dp->d_gate);
	return (0);
}

/*
 * Given the name of an executable l.out, a null terminated argument
 * list and a null terminated environment list, execute the l.out with the
 * given arguments and environments.
 */
pexece(np, argp, envp)
char	*np;
char	*argp[];
char	*envp[];
{
	register INODE	*ip;			/* Load file INODE */
	register PROC	*pp;			/* A cheap copy of SELF */
	register SEG	*ssp;			/* New stack segment */
	register fsize_t	ss;			/* Segment size temp. */
	register int	kprocflag;		/* Set if kernal process */
	register int	i;			/* For looping over segments */
	int		r;			/* Flag for "exload" */
	int		lflag;			/* l_flags from l.out */
	vaddr_t		pc;			/* l_entry from l.out */
	vaddr_t		sp;			/* Initial stack pointer */
	fsize_t		lssize[NUSEG];		/* Segment sizes */

	pp = SELF;
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL)
		return;
	if ((lflag&LF_KER) != 0) {
		pp->p_flags |= PFKERN;
		kprocflag = 1;
		ssp = NULL;
		if (super() == 0) {
			idetach(ip);
			return;
		}
	} else {
		kprocflag = 0;
		if ((ssp=exstack(&sp, argp, envp)) == NULL) {
			idetach(ip);
			return;
		}
	}
	/*
	 * At this point the file has been
	 * validated as an object module, and the
	 * argument list has been build. Release all of
	 * the original segments. At this point we have
	 * committed to the new image. A "sys exec" that
	 * gets an I/O error is doomed.
	 */
	for (i=1; i<NUSEG; ++i) {
		if (pp->p_segp[i] != NULL) {
			sfree(pp->p_segp[i]);
			pp->p_segp[i] = NULL;
		}
	}
	sssp = ssp;
	/*
	 * Read in load module.
	 */
	switch (lflag&(LF_SHR|LF_SEP)) {
	case 0:
		ss = si+pi+sd+pd;
		pdsp = ssalloc(&r, ip, kprocflag?SFHIGH:0, ss+bi+bd, sh, ss);
		if (r < 0)
			goto out;
		break;

	case LF_SHR:
		sdsp = ssalloc(&r, ip, SFSHRX, si+sd, sh, si);
		if (r < 0)
			goto out;
		if (r == 0) {
			if (exsread(sdsp, ip, sd, sh+si+pi, si) == 0)
				goto out;
		}
		pdsp = ssalloc(&r, ip, 0, pi+pd+bi+bd, sh+si, pi);
		if (r < 0)
			goto out;
		if (r == 0) {
			if (exsread(pdsp, ip, pd, sh+si+pi+sd, pi) == 0)
				goto out;
		}
		break;

	case LF_SEP:
		pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+bi, sd+pd);
		if (r < 0)
			goto out;
		break;

	case LF_SHR|LF_SEP:
		sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si);
		if (r < 0)
			goto out;
		pisp = ssalloc(&r, ip, SFTEXT, pi+bi, sh+si, pi);
		if (r < 0)
			goto out;
		sdsp = ssalloc(&r, ip, SFSHRX, sd, sh+si+pi, sd);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, pd+bd, sh+si+pi+pd, pd);
		if (r < 0)
			goto out;
	}
	if (sproto() == 0)
		goto out;
	/*
	 * The new image is read in
	 * and mapped. Perform the final grunge
	 * (set-uid stuff, accounting, loading up
	 * registers, etc).
	 */
	u.u_flag &= ~AFORK;
	kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
	if (iaccess(ip, IPR) == 0)
		pp->p_flags |= PFNDMP;
	if ((ip->i_mode&ISUID) != 0)
		pp->p_uid = u.u_uid = ip->i_uid;
	if ((ip->i_mode&ISGID) != 0)
		u.u_gid = ip->i_gid;
	for (i=0; i<NSIG; ++i) {
		if (u.u_sfunc[i] != SIG_IGN)
			u.u_sfunc[i] = SIG_DFL;
	}
	if ((pp->p_flags&PFTRAC) != 0)
		sendsig(SIGTRAP, pp);
	idetach(ip);
	msetusr(pc, sp);
	segload();
	return (0);

	/*
	 * We did not make it.
	 * Release the INODE for the load
	 * file, and return through the "sys exit"
 	 * code. A better exit status should be
	 * chosen!
	 */
out:
	idetach(ip);
	pexit(0);
}

/*
 * Open an l.out, make sure it is an l.out and executable and return the
 * appropriate information.
 */
INODE *
exlopen(np, ssizep, flagp, pcp)
char *np;
fsize_t *ssizep;
int *flagp;
vaddr_t *pcp;
{
	register INODE *ip;
	register struct ldheader *ldp;
	register int n;
	register BUF *bp;
	int m;

	/*
	 * Make sure the file is really an executable l.out and read the
	 * header in.
	 */
	if (ftoi(np, 'r') != 0)
		return (NULL);
	ip = u.u_cdiri;
	if (iaccess(ip, IPE) == 0) {
		idetach(ip);
		return (NULL);
	}
	if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
		u.u_error = EACCES;
		idetach(ip);
		return (NULL);
	}
	if ((bp=vread(ip, (daddr_t)0)) == NULL) {
		u.u_error = EBADFMT;
		idetach(ip);
		return (NULL);
	}

	/*
	 * Copy everything we need from the l.out header and check magic
	 * number and machine type.
	 */
	ldp = bp->b_vaddr;
	m = ldp->l_magic;
	canint(m);
	if (m != L_MAGIC) {
		u.u_error = ENOEXEC;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	m = ldp->l_machine;
	canint(m);
	if (m != mactype) {
		u.u_error = EBADFMT;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(fsize_t));
	for (n=0; n<NXSEG; n++)
		cansize(ssizep[n]);
	*flagp = ldp->l_flag;
	canint(*flagp);
	*pcp = ldp->l_entry;
	canvaddr(*pcp);
	brelease(bp);
	return (ip);
}

/*
 * Given a segment `sp', read `ss' bytes from the inode `ip' starting
 * at seek address `sa' into offset `so' in the segment.
 */
SEG *
exsread(sp, ip, ss, sa, so)
register SEG *sp;
INODE *ip;
fsize_t sa;
fsize_t ss;
fsize_t so;
{
	u.u_io.io_seg = IOPHY;
	u.u_io.io_ioc = ss;
	u.u_io.io_seek = sa;
	u.u_io.io_phys = ctob((paddr_t)sp->s_mbase) + so;
	u.u_io.io_flag = 0;
	iread(ip, &u.u_io);
	return (u.u_error==0);
}

/*
 * Given a pointer to a list of arguments and a pointer to a list of
 * environments, return a stack with the arguments and environments on it.
 */
SEG *
exstack(iusp, argp, envp)
char **iusp;		/* Back patch sp value */
char *argp[];		/* Arguments for new process */
char *envp[];		/* Environments for new process */
{
	SEG *sp;		/* Stack segment pointer */
	struct adata {		/* Storage for arg and env data */
		char	**up;		/* User vector pointer */
		int	np;		/* Number of pointers in vector */
		int	nc;		/* Number of characters in strings */
	} arg, env;
	struct sdata {		/* To keep segment pointers */
		vaddr_t	base;		/* Top of segment virtual */
		vaddr_t	ap;		/* Argc, argv, envp pointer */
		vaddr_t	vp;		/* Argv[i], envp[i] pointer */
		vaddr_t	cp;		/* Argv[i][j], envp[i][j] pointer */
	} aux, stk;
	aold_t aold;			/* Auxiliary map storage */
	register char **usrvp;		/* Vector pointer into user seg */
	register char *usrcp;		/* Character pointer into user seg */
	register int c;			/* Character fetched from user */
	register int chrsz;		/* Size of strings */
	register struct adata *adp;	/* Arg and env scanner */
	register int vecsz;		/* Size of vectors */
	register int stksz;		/* Size of stack argument region */

	/* Validate and evaluate size of args and envs */
	arg.up = argp;
	env.up = envp;
	chrsz = 0;
	vecsz = 0;
	for (adp = &arg; ; adp = &env) {
		adp->np = 0;
		adp->nc = 0;
		if (excount(adp->up, &adp->np, &adp->nc) == 0)
			return (NULL);
		chrsz += adp->nc * sizeof(char);
		vecsz += adp->np * sizeof(char *);
		if (adp == &env)
			break;
	}

	/* Calculate stack size and allocate it */
	chrsz = roundu(chrsz, sizeof(int));
	stksz = sizeof(int)		/* argc */
		+ sizeof(char **)	/* argv */
		+ sizeof(char **)	/* envp */
		+ vecsz			/* argv[i] and envp[i] */
		+ chrsz			/* *argv[i] and *envp[i] */
		+ sizeof(int)		/* Mystery zero word */
		+ sizeof(char *)	/* Splimit for z8000 */
		+ sizeof(int);		/* errno */
	stksz += ISTSIZE;
	if (stksz > MADSIZE) {
		u.u_error = E2BIG;
		return (NULL);
	}
	if ((sp=salloc((fsize_t)stksz, SFDOWN)) == NULL)
		return (NULL);
	stksz -= ISTSIZE;

	/*
	 * Initialize segment data.
	 */
	asave(aold);

	aux.base = abase(sp->s_mbase) + ctob(sp->s_size);
	aux.ap = aux.base - stksz;
	aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **);
	aux.cp = aux.vp + vecsz;

	stk.base = ISTVIRT;
	stk.ap = stk.base - stksz;
	stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **);
	stk.cp = stk.vp + vecsz;

	/*
	 * Write argc.
	 */
	aputi((int *)aux.ap, arg.np-1);
	aux.ap += sizeof(int);

	/*
	 * Arguments and environments.
	 */
	for (adp = &arg; ; adp = &env) {

		/* Write argv or envp */
		aputp((char ***)aux.ap, (char **)stk.vp);
		aux.ap += sizeof(char **);
		if ((usrvp = adp->up) != NULL) {

			/* Write argv[i] or envp[i] */
			while ((usrcp = getupd(usrvp++)) != NULL) {
				aputp((char **)aux.vp, (char *)stk.cp);
				aux.vp += sizeof(char *);
				stk.vp += sizeof(char *);

				/* Write argv[i][j] or envp[i][j] */
				do {
					c = getubd(usrcp++);
					aputc((char *)aux.cp, c);
					aux.cp += sizeof(char);
					stk.cp += sizeof(char);
				} while (c != '\0');
			}
		}

		/* Write argv[argc] or envp[envc] */
		aputp((char **)aux.vp, NULL);
		aux.vp += sizeof(char *);
		stk.vp += sizeof(char *);
		if (adp == &env)
			break;
	}

	/*
	 * Clear out the slop.
	 */
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* errno */
	aux.base -= sizeof(char *);
	aputp((char **) aux.base, (char *)stk.base-ctob(sp->s_size)+SOVSIZE);
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* mystery word */

	arest(aold);

	/*
	 * Patch some values and return.
	 */
	*iusp = stk.ap;		/* Patch initial usp */
	u.u_argc = arg.np-1;
	u.u_argp = stk.vp;	/* Points after NULL of envs */
	return (sp);
}

/*
 * Given a pointer to a list of arguments, a pointer to an argument count
 * and a pointer to a byte count, update incrementally the argument count
 * and the byte count.
 */
excount(usrvp, nap, nbp)
register char **usrvp;
int *nap;
int *nbp;
{
	register char *usrcp;
	register int c;
	register unsigned nb;
	register unsigned na;

	na = 1;
	nb = 0;
	if (usrvp != NULL) {
		for (;;) {
			usrcp = getupd(usrvp++);
			if (u.u_error)
				return (0);
			if (usrcp == NULL)
				break;
			na++;
			for (;;) {
				c = getubd(usrcp++);
				if (u.u_error)
					return (0);
				nb++;
				if (c == '\0')
					break;
			}
		}
	}
	*nap += na;
	*nbp += nb;
	return (1);
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d26 1
a26 1
#include <coherent.h>
@
0707070064030053071004440000030000030000011777770507310734400004600000007516/newbits/kernel/USRSRC/coh/RCS/fd.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.50.35;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.32.09;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.29.57;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.04;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * File descriptor routines.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:43	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/fd.h>
#include <sys/inode.h>
#include <sys/uproc.h>

/*
 * Given a file number, return the file descriptor.
 */
FD *
fdget(fd)
register unsigned fd;
{
	register FD *fdp;

	if (fd>=NUFILE || (fdp=u.u_filep[fd])==NULL) {
		u.u_error = EBADF;
		return (NULL);
	}
	return (fdp);
}

/*
 * Duplicate a file descriptor number.  This has the same calling
 * sequence as the dup2 system call and even uses the silly DUP2 bit.
 */
fddup(ofd, nfd)
register unsigned ofd;
register unsigned nfd;
{
	register FD *fdp;

	if ((fdp=fdget(ofd&~DUP2)) == NULL)
		return (-1);
	if ((ofd&DUP2) != 0) {
		if (nfd >= NUFILE) {
			u.u_error = EBADF;
			return (-1);
		}
		ofd &= ~DUP2;
		if (ofd == nfd)
			return (nfd);
		if (u.u_filep[nfd] != NULL) {
			fdclose(nfd);
			if (u.u_error)
				return (-1);
		}
	} else {
		for (nfd=0; nfd<NUFILE; nfd++)
			if (u.u_filep[nfd] == NULL)
				break;
		if (nfd == NUFILE) {
			u.u_error = EMFILE;
			return (-1);
		}
	}
	u.u_filep[nfd] = fdp;
	fdp->f_refc++;
	return (nfd);
}

/*
 * Given an inode, and a mode containing permission flags, open the
 * inode with the appropriate permissions and return a file descriptor
 * containing it.
 */
fdopen(ip, mode)
register INODE *ip;
{
	register FD **fdpp;
	register FD *fdp;

	for (fdpp=u.u_filep; fdpp<&u.u_filep[NUFILE]; fdpp++) {
		if (*fdpp != NULL)
			continue;
		if ((fdp=kalloc(sizeof(FD))) == NULL)
			return (-1);
		iopen(ip, mode);
		if (u.u_error) {
			kfree(fdp);
			return (-1);
		}
		fdp->f_flag = mode;
		fdp->f_refc = 1;
		fdp->f_seek = 0;
		fdp->f_ip = ip;
		*fdpp = fdp;
		return (fdpp-u.u_filep);
	}
	u.u_error = EMFILE;
	return (-1);
}

/*
 * Close the given file number.
 */
fdclose(fd)
register unsigned fd;
{
	register FD *fdp;

	if (fd>=NUFILE || (fdp=u.u_filep[fd])==NULL) {
		u.u_error = EBADF;
		return;
	}
	u.u_filep[fd] = NULL;
	if (fdp->f_refc == 0)
		panic("fdclose()");
	if (--fdp->f_refc == 0) {
		iclose(fdp->f_ip);
		kfree(fdp);
	}
}

/*
 * Assuming we have made a copy of the user area, increment the reference
 * of all open files.  (used in fork).
 */
fdadupl()
{
	register FD **fdpp;
	register FD *fdp;

	for (fdpp=u.u_filep; fdpp<&u.u_filep[NUFILE]; fdpp++) {
		if ((fdp=*fdpp) == NULL)
			continue;
		fdp->f_refc++;
	}
}

/*
 * Close all open files in the current process.
 */
fdaclose()
{
	register int fd;

	for (fd=0; fd<NUFILE; fd++) {
		if (u.u_filep[fd] == NULL)
			continue;
		fdclose(fd);
	}
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d24 1
a24 1
#include <coherent.h>
@
0707070064030053041004440000030000030000011777770507310734500004700000025257/newbits/kernel/USRSRC/coh/RCS/fs2.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.50.55;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.32.31;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.16;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.16;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Filesystem (disk inodes).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:51	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/fs2.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 87/04/29	Allan Cornish		/usr/src/sys/coh/fs2.c
 * Fsminit panic messages now specify the root major and minor device.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/fs2.c
 * setacct() initializes the (new) (IO).io_flag field to 0.
 *
 * 85/08/08	Allan Cornish
 * ialloc() erroneously did a brelease(NULL) if bclaim() returned NULL.
 * also, sbp->s_fmod was set BEFORE the in-core inode table was updated.
 * This created a critical race with msync() (called by sync system call).
 *
 * 85/04/17	Allan Cornish
 * eliminated test for rootdev in msync()
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Initialise filesystem.
 */
fsminit()
{
	register MOUNT *mp;

	/*
	 * Mount the root file system.
	 */
	if ( (mp = fsmount(rootdev, ronflag)) == NULL )
		panic(	"fsminit: no rootdev(%d,%d)",
			major(rootdev), minor(rootdev) );

	/*
	 * Set system time from the super block.
	 */
	timer.t_time = mp->m_super.s_time;

	/*
	 * Access the root directory.
	 */
	if ( (u.u_rdir = iattach(rootdev, ROOTIN)) == NULL )
		panic(	"fsminit: no / on rootdev(%d,%d)",
			major(rootdev), minor(rootdev) );

	/*
	 * Record current directory.
	 */
	u.u_cdir = u.u_rdir;
	u.u_cdir->i_refc++;
	iunlock(u.u_rdir);
}

/*
 * Mount the given device.
 */
MOUNT *
fsmount(dev, f)
register dev_t dev;
{
	register MOUNT *mp;
	register BUF *bp;

	if ((mp=kalloc(sizeof(MOUNT))) == NULL)
		return (NULL);
	dopen(dev, (f?IPR:IPR|IPW), DFBLK);
	if (u.u_error != 0) {
		kfree(mp);
		return (NULL);
	}
	if ((bp=bread(dev, (daddr_t)SUPERI, 1)) == NULL) {
		dclose(dev);
		kfree(mp);
		return (NULL);
	}
	kkcopy(FP_OFF(bp->b_faddr), &mp->m_super, sizeof(struct filsys));
	brelease(bp);
	cansuper(&mp->m_super);
	mp->m_ip = NULL;
	mp->m_dev = dev;
	mp->m_flag = f;
	mp->m_super.s_fmod = 0;
	mp->m_next = mountp;
	mountp = mp;
	return (mp);
}

/*
 * Canonize a super block.
 */
cansuper(fsp)
register struct filsys *fsp;
{
	register int i;

	canint(fsp->s_isize);
	candaddr(fsp->s_fsize);
	canshort(fsp->s_nfree);
	for (i=0; i<NICFREE; i++)
		candaddr(fsp->s_free[i]);
	canshort(fsp->s_ninode);
	for (i=0; i<NICINOD; i++)
		canino(fsp->s_inode[i]);
	cantime(fsp->s_time);
	candaddr(fsp->s_tfree);
	canino(fsp->s_tinode);
	canshort(fsp->s_m);
	canshort(fsp->s_n);
	canlong(fsp->s_unique);
}

/*
 * Given a pointer to a mount entry, write out all inodes on that device.
 */
msync(mp)
register MOUNT *mp;
{
	register struct filsys *sbp;
	register BUF *bp;

	if ((mp->m_flag&MFRON) != 0)
		return;
	isync(mp->m_dev);
	sbp = &mp->m_super;
	if (sbp->s_fmod==0)
		return;
	bp = bclaim(mp->m_dev, (daddr_t)SUPERI);
	sbp->s_time = timer.t_time;
	sbp->s_fmod = 0;
	kkcopy(sbp, FP_OFF(bp->b_faddr), sizeof(*sbp));
	cansuper(FP_OFF(bp->b_faddr));
	bwrite(bp, 1);
	brelease(bp);
}

/*
 * Return the mount entry for the given device.  If `f' is not set
 * and the device is read only, don't set the error status.
 */
MOUNT *
getment(dev, f)
register dev_t dev;
{
	register MOUNT *mp;

	for (mp=mountp; mp!=NULL; mp=mp->m_next) {
		if (mp->m_dev != dev)
			continue;
		if ((mp->m_flag&MFRON) != 0) {
			if (f != 0)
				u.u_error = EROFS;
			return (NULL);
		}
		return (mp);
	}
	panic("getment: dev=0x%x", dev);
}

/*
 * Allocate a new inode with the given mode.  The returned inode is locked.
 */
INODE *
ialloc(dev, mode)
dev_t dev;
unsigned mode;
{
	register struct dinode *dip;
	register struct filsys *sbp;
	register ino_t *inop;
	register ino_t ino;
	register BUF *bp;
	register daddr_t b;
	register struct dinode *dipe;
	register ino_t *inope;
	register MOUNT *mp;
	register INODE *ip;

	if ((mp=getment(dev, 1)) == NULL)
		return (NULL);
	sbp = &mp->m_super;
	for (;;) {
		lock(mp->m_ilock);
		if (sbp->s_ninode == 0) {
			ino = 1;
			inop = sbp->s_inode;
			inope = &sbp->s_inode[NICINOD];
			for (b=INODEI; b<sbp->s_isize; b++) {
				if (bad(dev, b)) {
					ino += INOPB;
					continue;
				}
				if ((bp=bread(dev, b, 1)) == NULL) {
					ino += INOPB;
					continue;
				}
				dip = FP_OFF(bp->b_faddr);
				dipe = &dip[INOPB];
				for (; dip<dipe; dip++, ino++) {
					if (dip->di_mode != 0)
						continue;
					if (inop >= inope)
						break;
					*inop++ = ino;
				}
				brelease(bp);
				if (inop >= inope)
					break;
			}
			sbp->s_ninode = inop - sbp->s_inode;
			if (sbp->s_ninode == 0) {
				sbp->s_tinode = 0;
				unlock(mp->m_ilock);
				devmsg(dev, "Out of inodes");
				u.u_error = ENOSPC;
				return (NULL);
			}
		}
		ino = sbp->s_inode[--sbp->s_ninode];
		--sbp->s_tinode;
		sbp->s_fmod = 1;
		unlock(mp->m_ilock);
		if ((ip=iattach(dev, ino)) != NULL) {
			if (ip->i_mode != 0) {
				devmsg(dev, "Inode %u busy", ino);
				idetach(ip);
				continue;
			}
			ip->i_flag = 0;
			ip->i_mode = mode;
			ip->i_nlink = 0;
			ip->i_uid = u.u_uid;
			ip->i_gid = u.u_gid;
		}
		return (ip);
	}
}

/*
 * Free the inode `ino' on device `dev'.
 */
ifree(dev, ino)
dev_t dev;
ino_t ino;
{
	register struct filsys *sbp;
	register MOUNT *mp;

	if ((mp=getment(dev, 1)) == NULL)
		return;
	lock(mp->m_ilock);
	sbp = &mp->m_super;
	sbp->s_fmod = 1;
	if (sbp->s_ninode < NICINOD)
		sbp->s_inode[sbp->s_ninode++] = ino;
	sbp->s_tinode++;
	unlock(mp->m_ilock);
}

/*
 * Free all blocks in the indirect block `b' on the device `dev'.
 * `l' is the level of indirection.
 */
indfree(dev, b, l)
dev_t dev;
daddr_t b;
register unsigned l;
{
	register int i;
	register BUF *bp;
	daddr_t * dp;
	daddr_t b1;

	if (b == 0)
		return;
	if (l-->0 && (bp=bread(dev, b, 1))!=NULL) {
		i = NBN;
		while (i-- > 0) {
			dp = FP_OFF(bp->b_faddr);

			if ((b1 = dp[i]) == 0)
				continue;
			candaddr(b1);
			if (l == 0)
				bfree(dev, b1);
			else
				indfree(dev, b1, l);
		}
		brelease(bp);
	}
	bfree(dev, b);
}

/*
 * Allocate a block from the filesystem mounted of device `dev'.
 */
daddr_t
balloc(dev)
dev_t dev;
{
	register struct filsys *sbp;
	register struct fblk *fbp;
	register daddr_t b;
	register BUF *bp;
	register MOUNT *mp;

	if ((mp=getment(dev, 1)) == NULL)
		return (0);
	lock(mp->m_flock);
	sbp = &mp->m_super;
	if (sbp->s_nfree == 0) {
enospc:
		sbp->s_nfree = 0;
		devmsg(dev, "Out of space");
		u.u_error = ENOSPC;
		b = 0;
	} else {
		sbp->s_fmod = 1;
		if ((b=sbp->s_free[--sbp->s_nfree]) == 0)
			goto enospc;
		if (sbp->s_nfree == 0) {
			if (b >= sbp->s_fsize
			 || b < sbp->s_isize
			 || (bp = bread(dev, b, 1)) == NULL) {
ebadflist:
				devmsg(dev, "Bad free list");
				goto enospc;
			}
			fbp = FP_OFF(bp->b_faddr);
			sbp->s_nfree = fbp->df_nfree;
			canshort(sbp->s_nfree);
			if ((unsigned)sbp->s_nfree > NICFREE)
				goto ebadflist;
			kkcopy(fbp->df_free, sbp->s_free, sizeof(sbp->s_free));
			canndaddr(sbp->s_free, sbp->s_nfree);
			brelease(bp);
		}
		--sbp->s_tfree;
		if (b >= sbp->s_fsize || b < sbp->s_isize)
			goto ebadflist;
	}
	unlock(mp->m_flock);
	return (b);
}

/*
 * Free the block `b' on the device `dev'.
 */
bfree(dev, b)
dev_t dev;
daddr_t b;
{
	register struct filsys *sbp;
	register struct fblk *fbp;
	register BUF *bp;
	register MOUNT *mp;

	if ((mp=getment(dev, 1)) == NULL)
		return;
	sbp = &mp->m_super;
	if (b>=sbp->s_fsize || b<sbp->s_isize) {
		devmsg(dev, "Bad block %u (free)", (unsigned)b);
		return;
	}
	lock(mp->m_flock);
	if (sbp->s_nfree == 0 || sbp->s_nfree == NICFREE) {
		bp = bclaim(dev, b);
		fbp = FP_OFF(bp->b_faddr);
		kclear(fbp, BSIZE);
		fbp->df_nfree = sbp->s_nfree;
		canshort(fbp->df_nfree);
		kkcopy(sbp->s_free, fbp->df_free, sizeof(fbp->df_free));
		canndaddr(fbp->df_free, sbp->s_nfree);
		bp->b_flag |= BFMOD;
		brelease(bp);
		sbp->s_nfree = 0;
	}
	sbp->s_free[sbp->s_nfree++] = b;
	sbp->s_tfree++;
	sbp->s_fmod = 1;
	unlock(mp->m_flock);
}

/*
 * Determine if the given block is bad.
 */
bad(dev, b)
dev_t dev;
daddr_t b;
{
	register INODE *ip;
	register BUF *bp;
	register int i;
	register int m;
	register int n;
	daddr_t l;

	if ((ip=iattach(dev, 1)) == NULL)
		panic("bad()");
	n = blockn(ip->i_size);
	if ((m=n) > ND)
		m = ND;
	for (i=0; i<m; i++) {
		--n;
		if (b == ip->i_a.i_addr[i]) {
			idetach(ip);
			return (1);
		}
	}
	l = ip->i_a.i_addr[ND];
	idetach(ip);
	if (n == 0)
		return (0);
	if ((bp=bread(dev, l, 1)) == NULL)
		return (0);
	if ((m=n) > NBN)
		m = NBN;
	for (i=0; i<m; i++) {
		l = ((daddr_t *)bp)[i];
		candaddr(l);
		if (b == l) {
			brelease(bp);
			return (1);
		}
	}
	brelease(bp);
	return (0);
}

/*
 * Canonize `n' disk addresses.
 */
canndaddr(dp, n)
register daddr_t *dp;
register int n;
{
	while (n--) {
		candaddr(*dp);
		dp++;
	}
}

/*
 * Write out an accounting record.
 */
setacct()
{
	register PROC *pp;
	struct acct acct;
	IO acctio;

	if (acctip == NULL)
		return;
	pp = SELF;
	kkcopy(u.u_comm, acct.ac_comm, 10);
	acct.ac_utime = ltoc(pp->p_utime);
	acct.ac_stime = ltoc(pp->p_stime);
	acct.ac_etime = ltoc(timer.t_time - u.u_btime);
	acct.ac_btime = u.u_btime;
	acct.ac_uid = u.u_uid;
	acct.ac_gid = u.u_gid;
	acct.ac_mem = 0;
	acct.ac_io = ltoc(u.u_block);
	acct.ac_tty = pp->p_ttdev;
	acct.ac_flag = u.u_flag;
	ilock(acctip);
	acctio.io_seek = acctip->i_size;
	acctio.io_ioc  = sizeof (acct);
	acctio.io_base = &acct;
	acctio.io_seg  = IOSYS;
	acctio.io_flag = 0;
	iwrite(acctip, &acctio);
	iunlock(acctip);
	u.u_error = 0;
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d40 1
a40 1
#include <coherent.h>
@
0707070064030053031004440000030000030000011777770507310735000004700000023157/newbits/kernel/USRSRC/coh/RCS/fs3.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.06;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.32.42;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.26;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.19;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Filesystem (I/O).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:13:54	src
 * Initial revision
 * 
 * 87/11/25	Allan Cornish		/usr/src/sys/coh/fs3.c
 * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
 *
 * 86/02/01	Allan Cornish
 * Added code to fwrite() to avoid needless writing of pipe blocks.
 * Throughput on 6 Mhz AT rose from 30 Kbytes/sec to 79 Kbytes/sec.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <canon.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/mount.h>
#include <sys/io.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/uproc.h>
#include <sys/stat.h>

/*
 * Given an inode, open it.
 */
iopen(ip, mode)
register INODE *ip;
{
	register int type;

	type = ip->i_mode & IFMT;
	switch (type) {
	case IFCHR:
	case IFBLK:
		iunlock(ip);
		dopen(ip->i_a.i_rdev, mode, type==IFCHR ? DFCHR : DFBLK);
		ilock(ip);
		break;
	case IFDIR:
		if ((mode&IPW) != 0) {
			if (super() == 0)
				return;
			if (mode == IPW) {
				u.u_error = EISDIR;
				return;
			}
		}
		break;
	case IFPIPE:
		popen(ip, mode);
		break;
	}
}

/*
 * Given an inode, close it.
 */
iclose(ip)
register INODE *ip;
{
	ilock(ip);
	switch (ip->i_mode&IFMT) {
	case IFBLK:
		bflush(ip->i_a.i_rdev);
	case IFCHR:
		iunlock(ip);
		dclose(ip->i_a.i_rdev);
		ilock(ip);
		break;
	case IFPIPE:
		pclose(ip);
		break;
	}
	idetach(ip);
}

/*
 * Read from a file described by an inode and an io strucuture.
 */
iread(ip, iop)
register INODE *ip;
register IO *iop;
{
	if (iop->io_ioc == 0)
		return;
	switch (ip->i_mode&IFMT) {
	case IFCHR:
		dread(ip->i_a.i_rdev, iop);
		break;
	case IFBLK:
	case IFREG:
	case IFDIR:
		fread(ip, iop);
		break;
	case IFPIPE:
		pread(ip, iop);
		break;
	default:
		u.u_error = ENXIO;
		break;
	}
}

/*
 * Write to a file described by an inode and io structure.
 */
iwrite(ip, iop)
register INODE *ip;
register IO *iop;
{
	imod(ip);	/* write - mtime */
	icrt(ip);	/* write - ctime */
	if (iop->io_ioc == 0)
		return;
	switch (ip->i_mode&IFMT) {
	case IFCHR:
		dwrite(ip->i_a.i_rdev, iop);
		break;
	case IFBLK:
		fwrite(ip, iop);
		break;
	case IFREG:
	case IFDIR:
		if (getment(ip->i_dev, 1) == NULL)
			return;
		fwrite(ip, iop);
		break;
	case IFPIPE:
		pwrite(ip, iop);
		break;
	default:
		u.u_error = ENXIO;
		break;
	}
}

/*
 * Read from a regular or block special file.
 */
fread(ip, iop)
INODE *ip;
register IO *iop;
{
#ifdef TINY
	register unsigned n;
	register fsize_t res;
	register unsigned off;
	register daddr_t lbn;
	register BUF *bp;
	register int blk;

	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	blk = (ip->i_mode&IFMT) == IFBLK;
	res = ip->i_size - iop->io_seek;
	if (blk!=0 || res>iop->io_ioc)
		res = iop->io_ioc;
	while (res > 0) {
		bp = blk ? bread(ip->i_a.i_rdev, lbn, 1) : vread(ip, lbn);
		if (bp == NULL)
			return;
		n = BSIZE - off;
		if (n > res)
			n = res;
		iowrite(iop, FP_OFF(bp->b_faddr)+off, n);
		brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		res -= n;
	}
/*
 * Start of daring read ahead code.
 * Altered to not read ahead on block devices
 * due to 20% time penalty incurred for such.
 */
#if 0
	if ( ! blk) {
		lbn = vmap(ip, lbn);
		if (lbn > 0)
			bread(ip->i_dev, lbn, 0);
	}
#endif
/*
 * End of daring read ahead code.
 */
#else
	register unsigned n;
	register unsigned i;
	register fsize_t res;
	register unsigned off;
	register dev_t dev;
	register daddr_t lbn;
	register daddr_t pbn;
	register daddr_t abn;
	register daddr_t zbn;
	register BUF *bp;
	register int blk;
	daddr_t list[NEXREAD];

	if ((ip->i_mode&IFMT) == IFBLK) {
		blk = 1;
		dev = ip->i_a.i_rdev;
	} else {
		blk = 0;
		dev = ip->i_dev;
	}
	abn = 0;
	zbn = 0;
	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	res = ip->i_size - iop->io_seek;
	if (blk!=0 || res>iop->io_ioc)
		res = iop->io_ioc;
	if (res <= 0)
		return;
	if (res+off <= BSIZE) {
		bp = blk ? bread(dev, lbn, 1) : vread(ip, lbn);
		if (bp == NULL)
			return;
		iowrite(iop, FP_OFF(bp->b_faddr)+off, (unsigned)res);
		brelease(bp);
		return;
	}
	while (res > 0) {
		if (lbn >= zbn) {
			if ((n=blockn(res+BSIZE-1)) > NEXREAD)
				n = NEXREAD;
			if (n <= 0)
				n = 1;
			abn = lbn;
			for (i=0, zbn=lbn; i<n; i++, zbn++) {
				if (blk != 0)
					pbn = zbn;
				else {
					if ((pbn=vmap(ip, zbn)) < 0)
						return;
					if (pbn == 0) {
						list[i] = -1;
						continue;
					}
				}
				list[i] = pbn;
				bread(dev, pbn, 0);
			}
		}
		if ((pbn=list[lbn-abn]) < 0) {
			bp = bclaim(NODEV, (daddr_t)0);
			kclear(FP_OFF(bp->b_faddr), BSIZE);
		} else {
			if ((bp=bread(dev, pbn, 1)) == NULL)
				return;
		}
		n = BSIZE - off;
		n = res>n ? n : res;
		iowrite(iop, FP_OFF(bp->b_faddr)+off, n);
		brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		res -= n;
	}
#endif
}

/*
 * Write to a regular or block special file.
 */
fwrite(ip, iop)
INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned off;
	register daddr_t lbn;
	register BUF *bp;
	register int blk;
	register int com;

	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	blk = (ip->i_mode&IFMT) == IFBLK;
	while (iop->io_ioc > 0) {
		n = BSIZE - off;
		n = iop->io_ioc>n ? n : iop->io_ioc;
		com = off==0 && n==BSIZE;
		if (blk == 0)
			bp = aread(ip, lbn, com);
		else {
			if (com)
				bp = bclaim(ip->i_a.i_rdev, lbn);
			else
				bp = bread(ip->i_a.i_rdev, lbn, 1);
		}
		if (bp == NULL)
			return;
		ioread(iop, FP_OFF(bp->b_faddr)+off, n);
		bp->b_flag |= BFMOD;
		if (com && ((ip->i_mode&IFMT) != IFPIPE) )
			bwrite(bp, 0);
		else
			brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		if ((iop->io_seek+=n) > ip->i_size)
			if (blk == 0)
				ip->i_size = iop->io_seek;
	}
}

/*
 * Given an inode pointer, read the requested virtual block and return
 * a buffer with the data.
 */
BUF *
vread(ip, lb)
register INODE *ip;
daddr_t lb;
{
	register daddr_t pb;
	register BUF *bp;

	if ((pb=vmap(ip, lb)) < 0)
		return (NULL);
	if (pb != 0)
		return (bread(ip->i_dev, pb, 1));
	bp = bclaim(NODEV, (daddr_t)0);
	kclear(FP_OFF(bp->b_faddr), BSIZE);
	return (bp);
}

/*
 * Convert the given virtual block to a physical block for the given inode.
 * If the block does not map onto a physical block because the file is sparse
 * but it does exist, 0 is returned.  If an error is encountered, -1 is
 * returned.
 */
daddr_t
vmap(ip, lb)
register INODE *ip;
daddr_t lb;
{
	register BUF *bp;
	register int *lp;
	daddr_t * dp;
	daddr_t pb;
	int list[1+NI];

	if ((lp=lmap(lb, list)) == NULL)
		return (-1);
	pb = ip->i_a.i_addr[*--lp];
	for (;;) {
		if (pb==0 || lp==list)
			return (pb);
		if ((bp=bread(ip->i_dev, pb, 1)) == NULL)
			return (0);
		dp = FP_OFF(bp->b_faddr);
		pb = dp[*--lp];
		brelease(bp);
		candaddr(pb);
	}
}

/*
 * Given an inode pointer, read the requested virtual block and return a
 * buffer with the data.  In sparse files, the necessary blocks are allocated.
 * If the flag, `fflag' is set, the final buffer is just claimed rather than
 * read as we are going to change it's contents completely.
 */
BUF *
aread(ip, lb, fflag)
register INODE *ip;
daddr_t lb;
{
	register BUF *bp;
	register int *lp;
	register dev_t dev;
	register int l;
	register int aflag;
	register int lflag;
	daddr_t * dp;
	daddr_t pb;
	int list[1+NI];

	if ((lp=lmap(lb, list)) == NULL)
		return (NULL);
	aflag = 0;
	dev = ip->i_dev;
	pb = ip->i_a.i_addr[l=*--lp];
	if (pb == 0) {
		aflag = 1;
		if ((pb=balloc(dev)) == 0)
			return (NULL);
		ip->i_a.i_addr[l] = pb;
	}
	for (;;) {
		lflag = lp==list;
		if (aflag==0  &&  (fflag==0 || lflag==0)) {
			if ((bp=bread(dev, pb, 1)) == NULL)
				return (NULL);
		} else {
			bp = bclaim(dev, pb);
			kclear(FP_OFF(bp->b_faddr), BSIZE);
			bp->b_flag |= BFMOD;
		}
		if (lflag)
			return (bp);

		aflag = 0;
		dp = FP_OFF(bp->b_faddr);
		pb = dp[l=*--lp];
		candaddr(pb);
		if (pb == 0) {
			aflag = 1;
			if ((pb=balloc(dev)) == 0) {
				brelease(bp);
				return (NULL);
			}
			dp[l] = pb;
			candaddr( dp[l] );
			bp->b_flag |= BFMOD;
		}
		brelease(bp);
	}
}

/*
 * Given a block number, `b', store the offsets for the indirect blocks
 * backwards in the array, `lp', and return a pointer just after the
 * position where the first offset is stored.
 */
int *
lmap(b, lp)
register daddr_t b;
register int *lp;
{
	register int n;

	if (b < ND) {
		*lp++ = b;
		return (lp);
	}
	b -= ND;
	n = NI;
	do {
		if (n-- == 0) {
			u.u_error = EFBIG;
			return (NULL);
		}
		*lp = nbnrem(b);
		++lp;
		b = nbndiv(b);
	} while (b--);
	*lp++ = ND+NI-1-n;
	return (lp);
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d30 1
a30 1
#include <coherent.h>
@
0707070064030053151004440000030000030000011777770507310735200005000000004672/newbits/kernel/USRSRC/coh/RCS/main.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.15;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.32.53;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.36;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.22;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/*
 * Coherent.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	88/06/29  12:00:29 	src
 * Real/Protected mode status now printed during boot sequence.
 * Three part serial numbers now supported, moved to optional fourth line.
 * 
 * Revision 1.1	88/03/24  16:13:58	src
 * Initial revision
 * 
 * 87/04/09	Allan Cornish		/usr/src/sys/coh/main.c
 * Serial numbers changed to support group.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/main.c
 * Copyright notice revised to include 1987.
 */
#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <sys/uproc.h>

#ifndef VERSION		/* This should be specified at compile time */
#define VERSION	"..."
#endif

unsigned long	_entry = 0;		/* really the serial number */
unsigned long	__ = 0;			/* really the serial number also */

/*
 * Initialise various things.  When we return we will return to user mode.
 */
char version[] = VERSION;
char copyright[] = "\
Copyright (c) 1982, 1991 by Mark Williams Company\n\
";

main()
{
	register SEG *sp;
	extern int realmode;	/* real addressing mode - as2.s */

	u.u_error = 0;
	bufinit();
	cltinit();
	pcsinit();
	seginit();
	devinit();
	printf("\Mark Williams COHERENT Version %s - %s Mode (mem=%u Kbytes)\n",
		version, (realmode ? "Real" : "Protected"), msize );
	printf(copyright);

	if ( _entry ) {
		printf("Serial Number ");
		printf("%U\n", _entry);
	}

	/*
	 * Verify correct serial number
	 */
	if (_entry != __)
		panic("Verification error - call Mark Williams Company at 1-800-MARK-WMS\n");

	/*
	 * Turn on clock, start off processes, mount root device
	 * and return.
	 */
	batflag = 1;
	if ((sp=salloc((fsize_t)UPASIZE, SFNCLR|SFNSWP)) == NULL)
		panic("Cannot allocate user area");
	if ((iprocp=process(idle))==NULL || (eprocp=process(NULL))==NULL)
		panic("Cannot create process");
	eveinit(sp);
	fsminit();
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d18 1
a18 1
#include <coherent.h>
@
0707070064030053021004440000030000030000011777770507310735300005000000005474/newbits/kernel/USRSRC/coh/RCS/misc.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.19;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.32.56;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.39;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.23;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Miscellaneous routines.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:01	src
 * Initial revision
 * 
 * 87/05/08	Allan Cornish		/usr/src/sys/coh/misc.c
 * System code and data segments no longer reported in panic messages.
 *
 * 87/02/17	Allan Cornish		/usr/src/sys/coh/misc.c
 * Panic message now includes system code and data segments.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <errno.h>
#include <sys/ino.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Copy `n' bytes from `bp1' to `bp2'.
 */
kkcopy(bp1, bp2, n)
register char *bp1;
register char *bp2;
unsigned n;
{
	register unsigned n1;

	n1 = n;
	if (n1) {
		do {
			*bp2++ = *bp1++;
		} while (--n1);
	}
	return (n);
}

/*
 * Clear the next `n' bytes starting at `bp'.
 */
kclear(bp, n)
register char *bp;
register unsigned n;
{
	if (n) {
		do {
			*bp++ = 0;
		} while (--n);
	}
}

/*
 * Make sure we are the super user.
 */
super()
{
	if (u.u_uid) {
		u.u_error = EPERM;
		return (0);
	}
	u.u_flag |= ASU;
	return (1);
}

/*
 * Make sure we are the gived `uid' or the super user.
 */
owner(uid)
{
	if (u.u_uid == uid)
		return (1);
	if (u.u_uid == 0) {
		u.u_flag |= ASU;
		return (1);
	}
	u.u_error = EPERM;
	return (0);
}

/*
 * Panic.
 */
panic(a1)
char *a1;
{
	static panflag;

	if (panflag++ == 0) {
		printf("Panic: %r", &a1);
		putchar('\n');
		usync();
	}
	halt();
	--panflag;
}

/*
 * Print a message from a device driver.
 */
devmsg(dev, a1)
dev_t dev;
char *a1;
{
	printf("(%d,%d): %r", major(dev), minor(dev), &a1);
	printf("\n");
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d29 1
a29 1
#include <coherent.h>
@
0707070064030053011004440000030000030000011777770507310735300005000000005627/newbits/kernel/USRSRC/coh/RCS/null.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.24;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.00;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.43;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.25;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Null and memory driver.
 *  Minor device 0 is /dev/null
 *  Minor device 1 is physical memory
 *  Minor device 2 is kernel data
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:04	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Functions for configuration.
 */
int	nlread();
int	nlwrite();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON nlcon ={
	DFCHR,				/* Flags */
	0,				/* Major index */
	nulldev,			/* Open */
	nulldev,			/* Close */
	nulldev,			/* Block */
	nlread,				/* Read */
	nlwrite,			/* Write */
	nonedev,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	nulldev,			/* Load */
	nulldev				/* Unload */
};

/*
 * Null/memory read routine.
 */
nlread(dev, iop)
dev_t dev;
register IO *iop;
{
	register unsigned n;

	switch (minor(dev)) {
	case 0:
		n = 0;
		break;

	case 1:
		n = pucopy((long)iop->io_seek, iop->io_base, iop->io_ioc);
		break;

	case 2:
		n = kucopy((vaddr_t)iop->io_seek, iop->io_base, iop->io_ioc);
		break;

	default:
		u.u_error = ENXIO;
		return;
	}
	iop->io_ioc -= n;
	if (u.u_error == EFAULT)
		u.u_error = 0;
}

/*
 * Null/memory write routine.
 */
nlwrite(dev, iop)
dev_t dev;
register IO *iop;
{
	register unsigned n;

	switch (minor(dev)) {
	case 0:
		n = iop->io_ioc;
		break;

	case 1:
		n = upcopy(iop->io_base, (long)iop->io_seek, iop->io_ioc);
		break;

	case 2:
		n = ukcopy(iop->io_base, (vaddr_t)iop->io_seek, iop->io_ioc);
		break;

	default:
		u.u_error = ENXIO;
		return;
	}
	iop->io_ioc -= n;
	if (u.u_error == EFAULT)
		u.u_error = 0;
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d26 1
a26 1
#include <coherent.h>
@
0707070064030053001004440000030000030000011777770507310735400005000000012103/newbits/kernel/USRSRC/coh/RCS/pipe.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.27;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.03;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.46;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.26;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Pipes.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:07	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/pipe.c
 * Added check for non-blocking read and write if (io_flag & IPNDLY) set.
 * Eliminated use of i_a inode field since now included in inode macros.
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Create and return a locked pipe inode.  This is called from the
 * pipe system call.
 */
INODE *
pmake(mode)
{
	register INODE *ip;

	if ((ip=ialloc(pipedev, IFPIPE|mode)) != NULL) {
		iclear(ip);
		ip->i_pnc = 0;
		ip->i_prx = 0;
		ip->i_pwx = 0;
	}
	return (ip);
}

/*
 * Open a pipe given the inode pointer.
 */
popen(ip, mode)
{
}

/*
 * Close a pipe inode.
 */
pclose(ip)
register INODE *ip;
{
	if (ip->i_refc == 2) {
		pevent(ip);
		ip->i_flag |= IFEOF;
	}
}

/*
 * Only one end of the pipe is going to be left.
 */
pevent(ip)
register INODE *ip;
{
	if ((ip->i_flag&IFWFR) != 0) {
		ip->i_flag &= ~IFWFR;
		wakeup((char *)&ip->i_pwx);
	}
	if ((ip->i_flag&IFWFW) != 0) {
		ip->i_flag &= ~IFWFW;
		wakeup((char *)&ip->i_prx);
	}
}

/*
 * Read from a pipe.  The given inode is locked.
 */
pread(ip, iop)
register INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned ioc;

	while (ip->i_pnc == 0) {

		/*
		 * Logical End of File.
		 */
		if ((ip->i_flag&IFEOF) != 0) {
			ip->i_flag &= ~IFEOF;
			break;
		}

		/*
		 * Nobody left to write.
		 */
		if (ip->i_nlink==0 && ip->i_refc<2)
			break;

		/*
		 * Non-blocking read.
		 */
		if ( iop->io_flag & IONDLY ) {
			u.u_error = EAGAIN;
			return;
		}

		/*
		 * Wait for pipe data.
		 */
		ip->i_flag |= IFWFW;
		iunlock(ip);
		sleep((char *)&ip->i_prx, CVPIPE, IVPIPE, SVPIPE);
		ilock(ip);
	}

	/*
	 * Clear EOF flag.
	 */
	if ((ip->i_flag&IFEOF)!=0 && ip->i_pnc==0)
		ip->i_flag &= ~IFEOF;

	ioc = iop->io_ioc;
	while (u.u_error==0 && ioc>0 && ip->i_pnc>0) {

		/*
		 * Calculate length of data to be read.
		 */
		if ((n=PIPSIZE-ip->i_prx) > ioc)
			n = ioc;
		if (n > ip->i_pnc)
			n = ip->i_pnc;

		/*
		 * Read data.
		 */
		iop->io_ioc = n;
		iop->io_seek = ip->i_prx;
		fread(ip, iop);
		n -= iop->io_ioc;
		if ((ip->i_prx+=n) == PIPSIZE)
			ip->i_prx = 0;
		ip->i_pnc -= n;
		ioc -= n;
	}
	iop->io_ioc = ioc;

	/*
	 * Wake processes waiting to write.
	 */
	if ((ip->i_flag&IFWFR)!=0 && ip->i_pnc<PIPSIZE) {
		ip->i_flag &= ~IFWFR;
		wakeup((char *)&ip->i_pwx);
	}
}

/*
 * Write to a pipe.  The given inode is locked.
 */
pwrite(ip, iop)
register INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned ioc;

	ioc = iop->io_ioc;
	while (u.u_error==0 && ioc>0) {

		/*
		 * Nobody left to read.
		 */
		if ( (ip->i_refc < 2) && (ip->i_nlink == 0) ) {
			u.u_error = EPIPE;
			sendsig(SIGPIPE, SELF);
			return;
		}

		/*
		 * Calculate free space in pipe.
		 */
		if ( (n=PIPSIZE-ip->i_pwx) > ioc )
			n = ioc;
		if (n > PIPSIZE-ip->i_pnc)
			n = PIPSIZE - ip->i_pnc;

		/*
		 * Non-blocking write.
		 */
		if ( iop->io_flag & IONDLY ) {
			if ( (n != ioc) || (ip->i_flag & IFEOF) ) {
				u.u_error = EAGAIN;
				return;
			}
		}

		/*
		 * Insufficent space or EOF still pending.
		 */
		if (n==0 || (ip->i_flag&IFEOF)!=0) {
			ip->i_flag |= IFWFR;
			iunlock(ip);
			sleep((char *)&ip->i_pwx, CVPIPE, IVPIPE, SVPIPE);
			ilock(ip);
			continue;
		}
		iop->io_ioc = n;
		iop->io_seek = ip->i_pwx;
		fwrite(ip, iop);
		n -= iop->io_ioc;
		if ((ip->i_pwx+=n) == PIPSIZE)
			ip->i_pwx = 0;
		ip->i_pnc += n;
		ioc -= n;

		/*
		 * Wait processes waiting to read.
		 */
		if ((ip->i_flag&IFWFW) && ip->i_pnc>0) {
			ip->i_flag &= ~IFWFW;
			wakeup((char *)&ip->i_prx);
		}
	}
	iop->io_ioc = ioc;
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d27 1
a27 1
#include <coherent.h>
d34 1
a34 1
#include <sched.h>
@
0707070064030052771004440000030000030000011777770507310735500005000000011540/newbits/kernel/USRSRC/coh/RCS/poll.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.32;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.09;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.50;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.27;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1986
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * [Stream] Polling.
 *
 *	void pollinit( ) -- allocate polling buffers
 *	int pollopen(qp) -- enable polling  by current process  on given queue
 *	int pollwake(qp) -- wake all processes waiting for poll on given queue
 *	int pollexit(  ) -- terminate all polls enabled by current process
 *	event_t * ep;
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:10	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/poll.c
 * Ported to Coherent from RTX.
 */

#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/uproc.h>

/*
 * Patchable data.
 */
int	NPOLL  = 0;

/*
 * Private data.
 */
static	event_t	* efreep;

/**
 *
 * event_t *
 * pollinit()		-- allocate event buffers.
 */
event_t *
pollinit()
{
	register event_t * ep;
	register event_t * ap;
	static int first = 1;

	/*
	 * If dynamically growing event pool is specified [NPOLL == 0],
	 * try to allocate an additional cluster of 32 on each call.
	 */
	if ( NPOLL == 0 ) {
		if ( ep = kalloc( 32 * sizeof(event_t) ) )
			ap = ep + 32;
	}

	/*
	 * If statically sized event pool is specified [NPOLL != 0],
	 * try to allocate the pool on the first call.
	 */
	else if ( first ) {
		first = 0;
		if ( ep = kalloc( NPOLL * sizeof(event_t) ) )
			ap = ep + NPOLL;
	}

	/*
	 * If event cluster was allocated, insert into free event queue.
	 */
	if ( ep ) {
		do {
			ep->e_pnext = efreep;
			efreep = ep;
		} while ( ++ep < ap );
	}

	return efreep;
}

/**
 *
 * int
 * pollopen(qp) -- enable polling by current process on given event queue
 * event_t * qp;
 */
pollopen( qp )
register event_t * qp;
{
	register event_t * ep;

	/*
	 * Initialize device queue if required.
	 */
	if ( qp->e_dnext == 0 )
		qp->e_dnext = qp->e_dlast = qp;

	/*
	 * Obtain a free event buffer, or return.
	 */
	if ( ((ep = efreep) == 0) && ((ep = pollinit()) == 0) ) {
		printf("out of poll buffers\n");
		return;
	}

	/*
	 * Remove event buffer from free queue.
	 */
	efreep = ep->e_pnext;

	/*
	 * Record process pointer in event buffer.
	 */
	ep->e_procp = cprocp;

	/*
	 * Insert event at head of process event singularly-linked queue.
	 */
	ep->e_pnext = cprocp->p_polls;
	cprocp->p_polls = ep;

	/*
	 * Insert event at tail of circularly-linked device queue.
	 * This ensures that processes are first-in first-out.
	 */
	ep->e_dnext  = qp;
	(ep->e_dlast = qp->e_dlast)->e_dnext = ep;
	qp->e_dlast  = ep;

	/*
	 * Record last process to enable polling on device.
	 */
	qp->e_procp = cprocp;
}

/**
 *
 * int
 * pollwake( qp ) -- wake all processes waiting for poll on given queue
 * event_t * qp;
 */
pollwake( qp )
event_t * qp;
{
	register event_t * ep = qp;
	register PROC    * pp;

	/*
	 * Clear device process pointer, indicating poll completed.
	 * NOTE: interrupt handlers may have already cleared it.
	 */
	qp->e_procp = 0;

	if ( ep = qp->e_dnext ) {

		/*
		 * Service circularly-linked polls on device queue.
		 */
		while ( ep != qp ) {
			/*
			 * Wake process if it is sleeping.
			 */
			if ( (pp = ep->e_procp) && (pp->p_state == PSSLEEP) )
				wakeup( &pp->p_polls );

			ep = ep->e_dnext;
		}
	}
}

/**
 *
 * int
 * pollexit() -- terminate all polls opened by current process
 */
int
pollexit()
{
	register PROC    * pp = cprocp;
	register event_t * ep;

	/*
	 * Service all polling event buffers enabled by current process.
	 */
	while ( ep = pp->p_polls ) {

		/*
		 * Remove event buffer from circularly-linked device queue.
		 */
		(ep->e_dnext->e_dlast = ep->e_dlast)->e_dnext = ep->e_dnext;

		/*
		 * Remove event buffer from singularly-linked process queue.
		 */
		pp->p_polls = ep->e_pnext;

		/*
		 * Insert event buffer at head of free event buffer queue.
		 */
		ep->e_pnext = efreep;
		efreep = ep;
	}
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d32 1
a32 1
#include <coherent.h>
@
0707070064030052761004440000030000030000011777770507310735600005200000006377/newbits/kernel/USRSRC/coh/RCS/printf.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.37;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.14;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.54;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.29;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/*
 * Coherent.
 * Print formatted.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:13	src
 * Initial revision
 * 
 * 87/09/20	Allan Cornish		/usr/src/sys/coh/printf.c
 * %U now correctly displays in base 10 rather than base 16.
 *
 * 86/12/16	Allan Cornish		/usr/src/sys/coh/printf.c
 * Added '%D' and '%X options to printf().
 */
#include <sys/coherent.h>

/*
 * For indirecting and incrementing argument pointer.
 */
#define ind(p, t)	(*((t *) p))
#define inc(t1, t2)	((sizeof(t2 *)+sizeof(t1)-1) / sizeof(t1))

/*
 * Table for printing out digits.
 */
char digtab[] ={
	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
	'8',	'9',	'A',	'B',	'C',	'D',	'E',	'F'
};

/*
 * A simple printf.
 */
printf(fp, a1)
register char *fp;
{
	char * cp;
	register int c;
	register unsigned *ap;
	int lflag;

	ap = (char *)&a1;
	for (;;) {
		while ((c=*fp++) != '%') {
			if (c == '\0')
				return;
			putchar(c);
		}

		lflag = 0;
		if ( *fp == 'l' ) {
			lflag = 1;
			fp++;
		}

		switch ( c = *fp++ ) {

		case 'c':
			putchar(*ap++);
			continue;

		case 'd':
			if ( lflag == 0 ) {
				if ( ((int)(*ap)) < 0 ) {
					putchar('-');
					printn( -((long) ((int)(*ap))), 10 );
				}
				else
					printn( ((long)(*ap)), 10 );
				ap++;
				continue;
			}
			/* fall through */
		case 'D':
			if ( *((long *)(ap)) < 0 ) {
				putchar('-');
				printn( - *((long *)(ap)), 10 );
			}
			else
				printn(   *((long *)(ap)), 10 );

			((long *)(ap))++;
			continue;

		case 'o':
			if ( lflag == 0 ) {
				printn( ((long)(*ap)), 8);
				ap++;
				continue;
			}
			/* fall through */
		case 'O':
			printf( *((long *)(ap)), 8 );
			((long *)(ap))++;
			continue;

		case 'r':
			ap = *((int **) ap);
			fp = ind(ap, char *);
			ap += inc(int, char *);
			continue;

		case 's':
			cp = ind(ap, char *);
			ap += inc(int, char *);
			while ((c=*cp++) != '\0')
				putchar(c);
			continue;

		case 'x':
			if ( lflag == 0 ) {
				printn( ((long)(*ap)), 16 );
				ap++;
				continue;
			}
			/* fall through */
		case 'X':
			printn( *((long *)(ap)), 16 );
			((long *)(ap))++;
			continue;

		case 'u':
			if ( lflag == 0 ) {
				printn( ((long)(*ap)), 10);
				ap++;
				continue;
			}
			/* fall through */
		case 'U':
			printn( *((long *)(ap)), 10 );
			((long *)(ap))++;
			continue;

		case 'p':
			if (sizeof(char *) > sizeof(int)) {
				printn( ((long)(*ap)), 16);
				putchar(':');
				ap++;
			}
			printn( ((long)(*ap)), 16);
			ap++;
			continue;

		default:
			putchar(c);
			continue;
		}
	}
}

/*
 * Print out the unsigned long `v' in the base `b'.
 */
printn( v, b )
unsigned long v;
{
	unsigned long n;

	if ((n=v/b) != 0)
		printn(n, b);

	putchar(digtab[v%b]);
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d15 1
a15 1
#include <coherent.h>
@
0707070064030050701004440000030000030000011777770507310735700005000000027537/newbits/kernel/USRSRC/coh/RCS/proc.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.40;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.19;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.30.58;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.30;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Process handling and scheduling.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	88/08/05  15:30:01	src
 * pfork() made more rigorous, supports loadable driver forks, etc.
 * lock/unlock more efficient, since know wakeup is synchronous.
 * 
 * Revision 1.1	88/03/24  16:14:16	src
 * Initial revision
 * 
 * 88/03/10	Allan Cornish		/usr/src/sys/coh/proc.c
 * Numerous temporary fixes due to AMD 286 chip being buggy in protected mode.
 * These partial fixes will be removed once all CPU's are replaced.
 *
 * 88/01/21	Allan Cornish		/usr/src/sys/coh/proc.c
 * Race condition caused by pexit() calling sfree() on the user-area
 * when the segmentation gate is locked is now prevented.
 * Release of the user area now deferred until relproc() invoked by uwait().
 *
 * 87/11/13	Allan Cornish		/usr/src/sys/coh/proc.c
 * pexit() now sets uasa to 0 before dispatching processor.
 *
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/proc.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/coh/proc.c
 * pexit() now cancels poll/alarm timed functions before terminating.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/coh/proc.c
 * pexit() now wakes the swapper before terminating.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <errno.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Initialisation.
 * Set up the hash table queues.
 */
pcsinit()
{
	register PROC *pp;
	register PLINK *lp;

	pp = &procq;
	SELF = pp;
	procq.p_nforw = pp;
	procq.p_nback = pp;
	procq.p_lforw = pp;
	procq.p_lback = pp;
	for (lp=&linkq[0]; lp<&linkq[NHPLINK]; lp++) {
		lp->p_lforw = lp;
		lp->p_lback = lp;
	}
}

/*
 * Initiate a process.  `f' is a kernel function that is associated with
 * the process.
 */
PROC *
process(f)
int (*f)();
{
	register PROC *pp1;
	register PROC *pp;
	register SEG *sp;
	MCON mcon;

	if ((pp=kalloc(sizeof(PROC))) == NULL)
		return (NULL);

	pp->p_flags = PFCORE;
	pp->p_state = PSRUN;
	pp->p_ttdev = NODEV;

	if (f != NULL) {
		pp->p_flags |= PFKERN;
		sp = salloc((fsize_t)UPASIZE, SFSYST|SFHIGH|SFNSWP);
		if (sp == NULL) {
			kfree(pp);
			return (NULL);
		}
		pp->p_segp[SIUSERP] = sp;
		msetsys( &mcon, f, FP_SEL(sp->s_faddr) );
		kfcopy(	(char *)&mcon,
			sp->s_faddr + offset(uproc, u_syscon),
			sizeof(mcon) );
	}
	lock(pnxgate);
next:
	pp->p_pid = cpid++;
	if (cpid >= NPID)
		cpid = 2;
	pp1 = &procq;
	while ((pp1=pp1->p_nforw) != &procq) {
		if (pp1->p_pid < pp->p_pid)
			break;
		if (pp1->p_pid == pp->p_pid)
			goto next;
	}
	pp->p_nback = pp1->p_nback;
	pp1->p_nback->p_nforw = pp;
	pp->p_nforw = pp1;
	pp1->p_nback = pp;
	unlock(pnxgate);
	return (pp);
}

/*
 * Remove a process from the next queue and release and space.
 */
relproc(pp)
register PROC *pp;
{
	register SEG * sp;

	/*
	 * Child process still has a user-area.
	 */
	if ( (sp = pp->p_segp[SIUSERP]) != NULL ) {

		/*
		 * Detach user-area from child process.
		 */
		pp->p_segp[SIUSERP] = NULL;

		/*
		 * Child process is swapped out.
		 */
		if ( pp->p_flags & PFSWAP )
			sp->s_lrefc++;

		/*
		 * Release child's user-area.
		 */
		sfree( sp );
	}

	/*
	 * Remove process from doubly-linked list of all processes.
	 * Release space allocated for proc structure.
	 */
	lock(pnxgate);
	pp->p_nback->p_nforw = pp->p_nforw;
	pp->p_nforw->p_nback = pp->p_nback;
	unlock(pnxgate);
	kfree(pp);
}

/*
 * Create a clone of ourselves.
 *	N.B. - consave(&mcon) returns twice; anything not initialized
 *	in automatic storage before the call to segadup() will not be
 *	initialized when the second return from consave() commences.
 */
pfork()
{
	register PROC *cpp;
	register PROC *pp;
	register int s;
	MCON mcon;

	if ((cpp=process(NULL)) == NULL) {
		u.u_error = EAGAIN;
		return;
	}

	s = sphi();	/* Make usave a null macro if unnecessary */
	usave();	/* Put the current copy of uarea into its segment */
	spl(s);

	if (segadup(cpp) == 0) {
		u.u_error = EAGAIN;
		relproc(cpp);
		return;
	}
	if ( u.u_rdir != NULL )
		u.u_rdir->i_refc++;
	if ( u.u_cdir != NULL )
		u.u_cdir->i_refc++;
	fdadupl();
	pp = SELF;
	cpp->p_uid   = pp->p_uid;
	cpp->p_ruid  = pp->p_ruid;
	cpp->p_rgid  = pp->p_rgid;
	cpp->p_ppid  = pp->p_pid;
	cpp->p_ttdev = pp->p_ttdev;
	cpp->p_group = pp->p_group;
	cpp->p_ssig  = pp->p_ssig;
	cpp->p_isig  = pp->p_isig;
	cpp->p_cval  = CVCHILD;
	cpp->p_ival  = IVCHILD;
	cpp->p_sval  = SVCHILD;
	cpp->p_rval  = RVCHILD;

	s = sphi();
	consave(&mcon);
	spl( s );

	/*
	 * Parent process.
	 */
	if ( (pp = SELF) != cpp ) {
		segfinm(cpp->p_segp[SIUSERP]);
		kfcopy( (char *)&mcon,
			cpp->p_segp[SIUSERP]->s_faddr + offset(uproc,u_syscon),
			sizeof(mcon) );
		mfixcon(cpp);
		s = sphi();
		setrun(cpp);
		spl(s);
		return( cpp->p_pid );
	}

	/*
	 * Child process.
	 */
	else {
		u.u_btime = timer.t_time;
		u.u_flag = AFORK;
		/* for (i=0; i<NUSEG; i++) done in sproto */
			/* u.u_segl[i].sr_segp = pp->p_segp[i]; ditto */
		sproto();
		segload();
		return( 0 );
	}
}

/*
 * Die.
 */
pexit(s)
{
	register PROC *pp1;
	register PROC *pp;
	register SEG  *sp;
	register int n;

	pp = SELF;

	/*
	 * Cancel alarm and poll timers [if any].
	 */
	timeout( &pp->p_alrmtim, 0, NULL, 0 );
	timeout( &pp->p_polltim, 0, NULL, 0 );

	/*
	 * Write out accounting directory and close all files associated with
	 * this process.
	 */
	setacct();
	if ( u.u_rdir )
		ldetach(u.u_rdir);
	if ( u.u_cdir )
		ldetach(u.u_cdir);
	fdaclose();

	/*
	 * Free all segments in reverse order, except for user-area.
	 */
	for ( n = NUSEG; --n > 0; ) {
		if ( (sp = pp->p_segp[n]) != NULL ) {
			pp->p_segp[n] = NULL;
			sfree( sp );
		}
	}

	/*
	 * Wakeup our parent.  If we have any children, init will become the
	 * new parent.  If there are any children we are tracing who are
	 * waiting for us, we wake them up.
	 */
	pp1 = &procq;
	while ((pp1=pp1->p_nforw) != &procq) {
		if (pp1->p_pid == pp->p_ppid) {
			if (pp1->p_state==PSSLEEP && pp1->p_event==(char *)pp1)
				wakeup((char *)pp1);
		}
		if (pp1->p_ppid == pp->p_pid) {
			pp1->p_ppid = 1;
			if (pp1->p_state == PSDEAD)
				wakeup((char *)eprocp);
			if ((pp1->p_flags&PFTRAC) != 0)
				wakeup((char *)&pts.pt_req);
		}
	}

	/*
	 * Wake up swapper if swap timer is active.
	 */
	if ( stimer.t_last != 0 )
		wakeup( (char *) &stimer );

	/*
	 * And finally mark us as dead and give up the processor forever.
	 */
	pp->p_exit = s;
	pp->p_state = PSDEAD;
	uasa = 0;
	dispatch();
}

/*
 * Sleep on the event `e'.  This gives up the processor until someone
 * wakes us up.  Since it is possible for many people to sleep on the
 * same event, the caller when awakened should make sure that what he
 * was waiting for has completed and if not, go to sleep again.  `cl'
 * is the cpu value we get to get the cpu as soon as we are woken up.
 * `sl' is the swap value we get to keep us in memory for the duration
 * of the sleep.  `sr' is the swap value that allows us to get swapped
 * in if we have been swapped out.
 */
sleep(e, cl, sl, sr)
char *e;
{
	register PROC *bp;
	register PROC *fp;
	register PROC *pp;
	register int s;

	pp = SELF;

	/*
	 * See if we have a signal awaiting.
	 */
	if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
		sphi();
		envrest(&u.u_sigenv);
	}

	/*
	 * Get ready to go to sleep and do so.
	 */
	s = sphi();
	pp->p_state = PSSLEEP;
	pp->p_event = e;
	pp->p_lctim = utimer;
	addu(pp->p_cval, cl);
	pp->p_ival = sl;
	pp->p_rval = sr;
	fp = &linkq[hash(e)];
	bp = fp->p_lback;
	pp->p_lforw = fp;
	fp->p_lback = pp;
	pp->p_lback = bp;
	bp->p_lforw = pp;
	spl(s);
	dispatch();

	/*
	 * We have just woken up.  Get ready to return.
	 */
	subu(pp->p_cval, cl);
	pp->p_ival = 0;
	pp->p_rval = 0;

	/*
	 * Check for an interrupted system call.
	 */
	if (cl<CVNOSIG && pp->p_ssig && nondsig()) {
		sphi();
		envrest(&u.u_sigenv);
	}
}

/*
 * Defer function to wake up all processes sleeping on the event `e'.
 */
wakeup(e)
char *e;
{
	extern void dwakeup();

	defer( dwakeup, e );
}

/*
 * Wake up all processes sleeping on the event `e'.
 */
static void
dwakeup( e )
char *e;
{
	register PROC *pp;
	register PROC *pp1;
	register int s;

	/*
	 * Identify event queue to check.
	 * Disable interrupts.
	 */
	pp1 = &linkq[hash(e)];
	pp = pp1;
	s = sphi();

	/*
	 * Traverse doubly-linked circular event-queue.
	 */
	while ( (pp = pp->p_lforw) != pp1 ) {

		/*
		 * Process is waiting on event 'e'.
		 */
		if ( pp->p_event == e ) {
			/*
			 * Remove process from event queue.
			 * Update process priority.
			 * Insert process into run queue.
			 */
			pp->p_lback->p_lforw = pp->p_lforw;
			pp->p_lforw->p_lback = pp->p_lback;
			addu( pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK );
			setrun( pp );

			/*
			 * Enable interrupts.
			 * Restart search at start of event queue.
			 * Disable interrupts.
			 */
			spl( s );
			pp = pp1;
			s = sphi();
		}
	}
	spl(s);
}

/*
 * Reschedule the processor.
 */
dispatch()
{
	register PROC *pp1;
	register PROC *pp2;
	register unsigned v;
	register int s;

	s = sphi();
	pp1 = iprocp;
	pp2 = &procq;
	v = 0;
	while ((pp2=pp2->p_lforw) != &procq) {
		v -= pp2->p_cval;
		if ((pp2->p_flags&PFCORE) == 0)
			continue;
		pp1 = pp2->p_lforw;
		pp1->p_cval += pp2->p_cval;
		pp2->p_cval = v;
		pp1->p_lback = pp2->p_lback;
		pp1->p_lback->p_lforw = pp1;
		pp1 = pp2;
		break;
	}
	spl(s);

	quantum = NCRTICK;
	disflag = 0;
	if ( pp1 != SELF ) {
		/*
		 * Consave() returns twice.
		 * 1st time is after our context is saved in u.u_syscon,
		 *	whereupon we should restore other proc's context.
		 * 2nd time is after our context is restored by another proc.
		 * Conrest() forces a context switch to a new process.
		 */
		s = sphi();
		SELF = pp1;
		if (consave(&u.u_syscon) == 0)
			conrest( FP_SEL(pp1->p_u->s_faddr),
				 offset(uproc,u_syscon) );
		if ( SELF->p_pid != 0 )
			segload();
		spl(s);
	}
}

/*
 * Add a process to the run queue.
 * This routine must be called at high priority.
 */
setrun(pp1)
register PROC *pp1;
{
	register PROC *pp2;
	register unsigned v;

	v = 0;
	pp2 = &procq;
	for (;;) {
		pp2 = pp2->p_lback;
		if ((v+=pp2->p_lforw->p_cval) >= pp1->p_cval)
			break;
		if (pp2 == &procq)
			break;
	}
	pp2->p_lforw->p_lback = pp1;
	pp1->p_lforw = pp2->p_lforw;
	pp2->p_lforw = pp1;
	pp1->p_lback = pp2;
	v -= pp1->p_cval;
	pp1->p_cval = v;
	pp1->p_lforw->p_cval -= v;
	pp1->p_state = PSRUN;
}

/*
 * Wait for the gate `g' to unlock, and then lock it.
 */
lock(g)
register GATE g;
{
	register int s;

	s = sphi();
	while (g[0]) {
		g[1] = 1;
		sleep((char *)g, CVGATE, IVGATE, SVGATE);
	}
	g[0] = 1;
	spl(s);
}

/*
 * Unlock the gate `g'.
 */
unlock(g)
register GATE g;
{
	g[0] = 0;
	if (g[1]) {
		g[1] = 0;
		disflag = 1;
		wakeup((char *)g);
	}
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d48 1
a48 1
#include <coherent.h>
d53 2
a54 2
#include <ptrace.h>
#include <sched.h>
@
0707070064030050671004440000030000030000011777770507310736200004700000042555/newbits/kernel/USRSRC/coh/RCS/seg.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.51.50;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.31;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.31.08;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.34;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Segment manipulation.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:20	src
 * Initial revision
 * 
 * 88/02/26	Allan Cornish	/usr/src/sys/coh/seg.c
 * swapio() now avoids 64 Kbyte page [dma] straddles.
 *
 * 88/01/22	Allan Cornish	/usr/src/sys/coh/seg.c
 * salloc() now invokes krunch(1000) if initial allocation fails.
 * sfree() now invokes krunch(0).
 *
 * 88/01/21	Allan Cornish	/usr/src/sys/coh/seg.c
 * sfree() modified to eliminate critical race on ref cnts and segment gate.
 * segfinm() now properly maintains segment reference counts.
 *
 * 87/11/13	Allan Cornish	/usr/src/sys/coh/seg.c
 * Support for protected mode segmentation added.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <errno.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/uproc.h>

/*
 * Initialisation code.
 */
seginit()
{
	/*
	 * Create empty circular-list of memory segments.
	 */
	segmq.s_forw = &segmq;
	segmq.s_back = &segmq;

	/*
	 * Create empty circular-list of disk segments.
	 */
	segdq.s_forw = &segdq;
	segdq.s_back = &segdq;

	if ( holebot != holetop ) {
		/*
		 * Define the I/O mem hole between low memory and extended mem.
		 * NOTE: Setting lrefc to urefc+1 stopx segment from moving.
		 */
		segiom.s_paddr = holebot;
		segiom.s_size  = holetop - holebot;
		segiom.s_flags = SFCORE | SFSYST;
		segiom.s_urefc = 1;
		segiom.s_lrefc = 2;

		/*
		 * Insert I/O memory segment into memory list.
		 */
		segiom.s_forw = &segmq;
		segiom.s_back = &segmq;
		segmq.s_forw  = &segiom;
		segmq.s_back  = &segiom;
	}
}

/*
 * Given an inode, `ip', and flags, `ff', describing a segment associated
 * with the inode, see if the segment already exists and if so, return a
 * copy.  If the segment does not exists, allocate the segment having size
 * `ss', and read the segment using the inode at seek offset `dq' with a
 * size of `ds'.
 */
SEG *
ssalloc(rp, ip, ff, ss, dq, ds)
int *rp;
register INODE *ip;
fsize_t ss;
fsize_t dq;
fsize_t ds;
{
	register SEG *sp;
	register int f;

	*rp = -1;
	if (ss == 0) {
		*rp = 1;
		return (NULL);
	}
	lock(seglink);
	f = ff & (SFSHRX|SFTEXT);

	/*
	 * Look for the segment in the memory queue.
	 */
	for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) {
		if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) {
			unlock(seglink);
			if ((sp = segdupl(sp)) != NULL) {
				segfinm(sp);
				*rp = 1;
			}
			return (sp);
		}
	}

	/*
	 * Look for the segment on the disk queue.
	 */
	for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) {
		if (sp->s_ip==ip && (sp->s_flags&(SFSHRX|SFTEXT))==f) {
			unlock(seglink);
			if ((sp = segdupl(sp)) != NULL) {
				segfinm(sp);
				*rp = 1;
			}
			return (sp);
		}
	}
	unlock(seglink);

	/*
	 * Allocate and create the segment.
	 */
	if ((sp=salloc(ss, ff)) == NULL)
		return (NULL);
	if (exsread(sp, ip, ds, dq, (fsize_t)0) == 0) {
		sfree(sp);
		return (NULL);
	}
	if ((ff&SFSHRX) != 0) {
		sp->s_ip = ip;
		ip->i_refc++;
	}
	*rp = 0;
	return (sp);
}

/*
 * Given a pointer to a newly created process, copy all of our segments
 * into the given process.
 */
segadup(cpp)
register PROC *cpp;
{
	register SEG *sp;
	register int n;
	register PROC *pp;

	pp = SELF;
	cpp->p_flags |= PFSWIO;
	for (n=0; n<NUSEG; n++) {
		if ((sp=pp->p_segp[n]) == NULL)
			continue;
		if ((sp=segdupl(sp)) == NULL)
			break;
		cpp->p_segp[n] = sp;
		if ((sp->s_flags&SFCORE) == 0)
			cpp->p_flags &= ~PFCORE;
	}
	if (n < NUSEG) {
		while (n > 0) {
			if ((sp=cpp->p_segp[--n]) != NULL) {
				cpp->p_segp[n] = NULL;
				sfree(sp);
			}
		}
	}
	cpp->p_flags &= ~PFSWIO;
	return (n);
}

/*
 * Duplicate a segment.
 */
SEG *
segdupl(sp)
register SEG *sp;
{
	register SEG *sp1;

	if ((sp->s_flags&SFSHRX) != 0) {
		sp->s_urefc++;
		sp->s_lrefc++;
		return (sp);
	}
	if ((sp->s_flags&SFCORE) == 0)
		panic("Cannot duplicate non shared swapped segment");
	if ((sp1=salloc(sp->s_size, sp->s_flags|SFNSWP|SFNCLR)) == NULL)
		sp1 = segdupd(sp);
	else {
		sp1->s_flags = sp->s_flags;
		plrcopy( sp->s_paddr, sp1->s_paddr, sp->s_size );
	}
	return (sp1);
}

/*
 * Allocate a segment `n' bytes long.  `f' contains some pseudo flags.
 */
SEG *
salloc(n, f)
fsize_t n;
{
	register SEG *sp;
	register int r;

	r = (f&(SFSYST|SFHIGH|SFTEXT|SFSHRX|SFDOWN)) | SFCORE;
	n +=  (BSIZE-1);
	n &= ~(BSIZE-1);

	lock(seglink);
	sp = sxalloc(n, f);
	unlock(seglink);

	if ( sp == NULL ) {
		krunch(1000);
		lock(seglink);
		sp = sxalloc(n, f);
		unlock(seglink);
	}

	if (sp != NULL) {
		sp->s_flags = r;
		vremap( sp );
	}
	else {
		if ((f&SFNSWP) != 0)
			return (NULL);
		if ((sp=kalloc(sizeof(SEG))) == NULL)
			return (NULL);
		sp->s_forw = sp;
		sp->s_back = sp;
		sp->s_flags = r;
		sp->s_urefc = 1;
		sp->s_lrefc = 1;
		if (segsext(sp, n) == NULL) {
			kfree(sp);
			return (NULL);
		}
	}
	if ((f&SFNCLR) == 0)
		pclear( sp->s_paddr, n );
	return (sp);
}

/*
 * Free the given segment pointer.
 */
sfree(sp)
register SEG *sp;
{
	register INODE *ip;

	if ( sp->s_urefc != 1 ) {
		sp->s_urefc--;
		sp->s_lrefc--;
		return;
	}

	lock(seglink);
	--sp->s_lrefc;
	if (--sp->s_urefc != 0) {
		unlock(seglink);
		return;
	}

	sp->s_back->s_forw = sp->s_forw;
	sp->s_forw->s_back = sp->s_back;
	unlock(seglink);

	if (sp->s_lrefc != 0)
		panic("Bad segment count");
	if ((ip=sp->s_ip) != NULL)
		ldetach(ip);
	vrelse( sp->s_faddr );
	kfree(sp);
	krunch(0);
}

/*
 * Grow or shrink the segment `sp' so that it has size `n'.
 */
seggrow(sp, n)
register SEG *sp;
fsize_t n;
{
	register SEG *sp1;
	register fsize_t  d;
	register paddr_t pb;
	register paddr_t nb;
	register int dowflag;

	dowflag = sp->s_flags&SFDOWN;

	/*
	 * Size of new segment is smaller or the same size as the old
	 * segment.
	 */
	lock(seglink);
	d = n - sp->s_size;
	if (n <= sp->s_size) {
		sp->s_size = n;
		if (dowflag)
			sp->s_paddr -= d;

		vremap( sp );
		unlock(seglink);
		return (1);
	}

	if ((sp1=sp->s_back) == &segmq)
		pb = corebot;
	else
		pb = sp1->s_paddr + sp1->s_size;

	if ((sp1=sp->s_forw) == &segmq)
		nb = coretop;
	else
		nb = sp1->s_paddr;

	/*
	 * If the segment does not grow down, see if there is enough
	 * space after the segment.
	 */
	if (dowflag==0 && nb-sp->s_paddr>=n) {
		pclear(sp->s_paddr+sp->s_size, d);
		sp->s_size = n;
		vremap( sp );
		unlock(seglink);
		return (1);
	}

	/*
	 * If the segment grows down, see if there is enough space
	 * before the segment.
	 */
	if (dowflag!=0 && sp->s_paddr+sp->s_size-pb>=n) {
		sp->s_paddr -= d;
		sp->s_size   = n;
		pclear( sp->s_paddr, d );
		vremap( sp );
		unlock(seglink);
		return (1);
	}

	/*
	 * Is there enough space in total counting the gaps on either
	 * side of us?
	 */
	if (nb-pb >= n) {
		if (dowflag == 0) {
			plrcopy(sp->s_paddr, pb, sp->s_size);
			pclear(pb+sp->s_size, d);
			sp->s_paddr = pb;
		} else {
			prlcopy( sp->s_paddr, nb-sp->s_size, sp->s_size );
			pclear(nb-n, d);
			sp->s_paddr = nb-n;
		}
		sp->s_size  = n;
		vremap( sp );
		unlock(seglink);
		return (1);
	}

	/*
	 * Try to allocate a segment somewhere else on the segment queue
	 * and copy ourselves there.
	 */
	unlock(seglink);
	if ((sp1=salloc((fsize_t)n, sp->s_flags|SFNSWP|SFNCLR)) != NULL) {
		if (dowflag == 0) {
			plrcopy(sp->s_paddr, sp1->s_paddr, sp->s_size);
			pclear(sp1->s_paddr+sp->s_size, d);
		} else {
			plrcopy(sp->s_paddr, sp1->s_paddr+d, sp->s_size);
			pclear(sp1->s_paddr, d);
		}
		lock(seglink);
		satcopy(sp, sp1);
		unlock(seglink);
		return (1);
	}

	/*
	 * Last chance.  Extend the segment by swapping it.
	 */
	if (segsext(sp, n) != NULL) {
		if (dowflag == 0)
			pclear(sp->s_paddr+n-d, d);
		else {
			prlcopy(sp->s_paddr, sp->s_paddr+d, n-d);
			pclear(sp->s_paddr, d);
		}
		return (1);
	}

	/*
	 * At least we tried.
	 */
	return (0);
}

/*
 * Given a segment pointer, `sp' and a segment size, grow the given segment
 * to the given size.
 */
segsize(sp, s2)
register SEG *sp;
vaddr_t s2;
{
	register vaddr_t s1;

	s1 = (vaddr_t) sp->s_size;
	if (seggrow(sp, (fsize_t)s2) == 0) {
		u.u_error = ENOMEM;
		return;
	}
	if (sproto() == 0)
		if (seggrow(sp, (fsize_t)s1)==0 || sproto()==0)
			sendsig(SIGSEGV, SELF);
	segload();
}

/*
 * Grow the segment `sp1' to the size `s' in bytes by swapping it out
 * and back in.  The segment may not be locked.
 */
SEG *
segsext(sp1, s)
register SEG *sp1;
register fsize_t s;
{
	register SEG *sp2;

#ifndef NOMONITOR
	if (swmflag)
		printf("Segsext(%p, %u)\n", SELF, SELF->p_pid);
#endif
	if (sexflag == 0) {
		u.u_error = ENOMEM;
		return (NULL);
	}
	lock(seglink);
	if ((sp2=sdalloc(s)) == NULL) {
		unlock(seglink);
		return (NULL);
	}
	unlock(seglink);
	sp1->s_lrefc++;
	if (sp1->s_size != 0)
		swapio(1, sp1->s_paddr, sp2->s_daddr, sp1->s_size);
	lock(seglink);
	satcopy(sp1, sp2);
	unlock(seglink);
	sp1->s_flags &= ~SFCORE;
	sp1->s_lrefc--;
	vremap(sp1);
	segfinm(sp1);
	return (sp1);
}

/*
 * Force the given segment to be in memory.  One can only force
 * one segment to be in memory at a time.
 */
segfinm(sp)
register SEG *sp;
{
	register PROC *pp;
	register int s;

	if ((sp->s_flags&SFCORE) != 0)
		return;
	pp = SELF;
	sp->s_urefc++;
	sp->s_lrefc++;
	pp->p_segp[SIAUXIL] = sp;
	pp->p_flags &= ~PFCORE;
#ifndef QWAKEUP
	s = sphi();
#endif
	setrun(pp);
	dispatch();
#ifndef QWAKEUP
	spl(s);
#endif
	pp->p_segp[SIAUXIL] = NULL;
	sfree(sp);
}

/*
 * Make a copy of the segment `sp1' which is in memory by writing
 * it out to disk.
 */
SEG *
segdupd(sp1)
register SEG *sp1;
{
	register SEG *sp2;

	if (sexflag == 0)
		return (NULL);
	lock(seglink);
	if ((sp2=sdalloc(sp1->s_size)) == NULL) {
		unlock(seglink);
		return (NULL);
	}
	sp1->s_lrefc++;
	unlock(seglink);
	swapio(1, sp1->s_paddr, sp2->s_daddr, sp1->s_size);
	sp1->s_lrefc--;
	sp2->s_flags = sp1->s_flags & ~SFCORE;
	sp2->s_size  = sp1->s_size;
	vremap( sp2 );
	return (sp2);
}

/*
 * Given a flag, a physical core address, a disk address and a count in
 * bytes, perform an I/O operation between core and disk.  If `flag' is
 * set, the transfer is to the disk otherwise it is to memory.  As you may
 * have guessed, this is used by the swapper.
 */
swapio(f, p, d, n)
paddr_t p;
daddr_t d;
fsize_t  n;
{
	register BUF * bp;
	register SEG * sp;
	register int s;
	register int nb;
	static SEG swapseg;	/* NOTE: FP_SEL(swapseg.s_faddr) must stay */

#ifndef NOMONITOR
	if (swmflag > 1)
		printf("swapio(%s,%x,%x,%x)\n",f?"out":"in",(int)p,(int)d,n);
#endif
	if (d < swapbot || d+(n/BSIZE) > swaptop
	 || p < corebot || p+n > coretop)
		panic("Swapio bad parameter");

	bp = &swapbuf;
	sp = &swapseg;
	lock(bp->b_gate);
	SELF->p_flags |= PFSWIO;
	sp->s_flags = SFCORE;
	sp->s_paddr = p;
	sp->s_size  = n;
	vremap( sp );
	bp->b_faddr = sp->s_faddr;

	while (n != 0) {
		nb = (n > SCHUNK) ? SCHUNK : n;
		/*
		 * Prevent I/O transfer from crossing 64 Kbyte boundary.
		 */
		if ( (p & 0xFFFF0000L) != ((p+nb) & 0xFFFF0000L) )
			nb = 0x10000L - (p & 0x0000FFFFL);
		bp->b_flag  = BFNTP;
		bp->b_req   = f ? BWRITE : BREAD;
		bp->b_dev   = swapdev;
		bp->b_bno   = d;
		bp->b_paddr = p;
		bp->b_count = nb;
		s = sphi();
		dblock(swapdev, bp);
		while ((bp->b_flag&BFNTP) != 0)
			sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
		spl(s);
		if ((bp->b_flag&BFERR) != 0)
			panic("Swapio error");
		FP_OFF(bp->b_faddr) += nb;
		p += nb;
		d += nb / BSIZE;
		n -= nb;
	}
	sp->s_flags = 0;
	vremap( sp );
	unlock(bp->b_gate);
	SELF->p_flags &= ~PFSWIO;
}

/*
 * Make the segment descriptor pointed to by `sp1' have the attributes
 * of `sp2' including it's position in the segment queue and release
 * `sp2'.  `seglink' must be locked when this routine is called.
 */
satcopy(sp1, sp2)
register SEG *sp1;
register SEG *sp2;
{
	if ( FP_SEL(sp2->s_faddr) != 0 )
		vrelse( sp2->s_faddr );

	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw  = sp2->s_forw;
	sp1->s_size  = sp2->s_size;
	sp1->s_paddr = sp2->s_paddr;
	sp1->s_daddr = sp2->s_daddr;
	vremap(sp1);
	kfree(sp2);
}

/*
 * Allocate a segment on disk that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 */
SEG *
sdalloc( s )
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register daddr_t d;
	register daddr_t d1;
	register daddr_t d2;

	d  = s / BSIZE;
	d1 = swapbot;
	sp1 = &segdq;
	do {
		if (d1 >= swaptop)
			return (NULL);
		if ((sp1=sp1->s_forw) != &segdq)
			d2 = sp1->s_daddr;
		else
			d2 = swaptop;
		if (d2-d1 >= d) {
			if ((sp2=kalloc(sizeof(SEG))) == NULL)
				return (NULL);
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_daddr = d1;
			return (sp2);
		}
		d1 = sp1->s_daddr + (sp1->s_size / BSIZE);
	} while (sp1 != &segdq);
	return (NULL);
}

/*
 * Allocate a segment in memory that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 */
SEG *
smalloc(s)
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	paddr_t p1;
	paddr_t p2;

	p1  = corebot;
	sp1 = &segmq;
	do {
		if ((sp1=sp1->s_forw) != &segmq)
			p2 = sp1->s_paddr;
		else
			p2 = coretop;

		if (p2-p1 >= s) {
			if ((sp2=kalloc(sizeof (SEG))) == NULL)
				return (NULL);
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_paddr = p1;
			/*   s_faddr = 0; */
			/*   s_flags = 0; */
			vremap( sp2 );
			return (sp2);
		}
		p1 = sp1->s_paddr + sp1->s_size;
	} while (sp1 != &segmq);
	return (NULL);
}

/*
 * Allocate a segment from the high end of memory that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 */
SEG *
shalloc( s )
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	paddr_t p1;
	paddr_t p2;

	sp1 = &segmq;
	p2  = coretop;
	do {
		if ((sp1=sp1->s_back) != &segmq)
			p1 = sp1->s_paddr + sp1->s_size;
		else
			p1 = corebot;

		if (p2-p1 >= s) {
			if ((sp2=kalloc(sizeof (SEG))) == NULL)
				return (NULL);
			sp1->s_forw->s_back = sp2;
			sp2->s_forw = sp1->s_forw;
			sp1->s_forw = sp2;
			sp2->s_back = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_paddr = p2-s;
			/*   s_faddr = 0; */
			/*   s_flags = 0; */
			vremap( sp2 );
			return (sp2);
		}
		p2 = sp1->s_paddr;
	} while (sp1 != &segmq);
	return (NULL);
}

/*
 * Set up `SR' structure in user area from segments descriptors in
 * process structure.  Also set up the user segmentation registers.
 */
sproto()
{
	register int n;
	register SEG *sp;

	kclear(u.u_segl, sizeof(u.u_segl));
	for (n=0; n<NUSEG; n++) {
		if ((sp=SELF->p_segp[n]) == NULL)
			continue;
		if (n == SIUSERP)
			u.u_segl[n].sr_base = &u;
		else
			u.u_segl[n].sr_flag |= SRFPMAP;
		if (n!=SISTEXT && n!=SISDATA)
			u.u_segl[n].sr_flag |= SRFDUMP;
		if (n!=SIUSERP && n!=SISTEXT && n!=SIPTEXT)
			u.u_segl[n].sr_flag |= SRFDATA;
		u.u_segl[n].sr_size = sp->s_size;
		u.u_segl[n].sr_segp = sp;
	}
	return (mproto());
}

/*
 * Search for a busy text inode.
 */
sbusy(ip)
register INODE *ip;
{
	register SEG *sp;

	lock(seglink);
	/*
	 * Look for the segment in the memory queue.
	 */
	for (sp=segmq.s_forw; sp!=&segmq; sp=sp->s_forw) {
		if (sp->s_ip==ip
		 && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) {
			unlock(seglink);
			return (1);
		}
	}

	/*
	 * Look for the segment on the disk queue.
	 */
	for (sp=segdq.s_forw; sp!=&segdq; sp=sp->s_forw) {
		if (sp->s_ip==ip
		 && (sp->s_flags&(SFSHRX|SFTEXT))==(SFSHRX|SFTEXT)) {
			unlock(seglink);
			return (1);
		}
	}
	unlock(seglink);
	return (0);
}

/*
 * Segment consistency checks for the paranoid.
segchk()
{
	register SEG *sp;
	register int nbad;
	fsize_t s;
	daddr_t d;

	nbad = 0;
	sp = &segmq;
	s = corebot;
	while ((sp=sp->s_forw) != &segmq) {
		if (sp->s_paddr < s)
			nbad += badseg("mem", sp->s_paddr, 0);
		s = sp->s_paddr + sp->s_size;
	}
	if (coretop < s)
		nbad += badseg("mem", sp->s_back->s_paddr, sp->s_back->s_size);
	sp = &segdq;
	d = swapbot;
	while ((sp=sp->s_forw) != &segdq) {
		if (sp->s_daddr < d)
			nbad += badseg("disk", (int)sp->s_daddr, 0);
		d = sp->s_daddr + (sp->s_size / BSIZE);
	}
	if (swaptop < d)
		nbad += badseg("disk", sp->s_back->s_daddr, sp->s_back->s_size);
}

badseg(t, b, s)
char *t;
daddr_t b;
fsize_t s;
{
	printf( "Bad %s segment at %X of len %X\n", t, b, s );
	return (1);
}
*/
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d37 1
a37 1
#include <coherent.h>
d43 1
a43 1
#include <sched.h>
@
0707070064030045771004440000030000030000011777770507310736600004700000015611/newbits/kernel/USRSRC/coh/RCS/sig.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.52.13;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.48;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.31.25;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Signal handling.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:24	src
 * Initial revision
 * 
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/sig.c
 * New seg struct now used to allow extended addressing.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/sig.c
 * sigdump() initializes the (new) (IO).io_flag field to 0.
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/uproc.h>

/*
 * Send a signal to the process `pp'.
 */
sendsig(sig, pp)
register unsigned sig;
register PROC *pp;
{
	register sig_t f;
	register int s;

	f = ((sig_t)1) << (sig-1);
	if ((pp->p_isig&f) != 0)
		return;
	pp->p_ssig |= f;
	if (pp->p_state == PSSLEEP) {
		s = sphi();
		pp->p_lback->p_lforw = pp->p_lforw;
		pp->p_lforw->p_lback = pp->p_lback;
		addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK);
		setrun(pp);
		spl(s);
	}
}

/*
 * Return signal number if we have a non ignored signal, else zero.
 */
nondsig()
{
	register PROC *pp;
	register sig_t mask;
	register int signo;

	pp = SELF;
	signo = 0;
	pp->p_ssig &= ~pp->p_isig;
	if (pp->p_ssig != 0) {
		mask = (sig_t) 1;
		signo += 1;
		while ((pp->p_ssig&mask) == 0) {
			mask <<= 1;
			signo += 1;
		}
	}
	return (signo);
}

/*
 * If we have a signal that isn't ignored, activate it.
 */
actvsig()
{
	register int n;
	register PROC *pp;
	register int (*f)();

#if EBUG_VM > 0
	printf("actvsig ");	/** DEBUG **/
#endif

	if ((n = nondsig()) == 0)
		return;
	pp = SELF;
	--n;
	pp->p_ssig &= ~((sig_t)1<<n);
	f = u.u_sfunc[n];
	u.u_signo = ++n;
	if (f != SIG_DFL) {
		msigint(n, f);
		return;
	}
	msysgen(&u.u_sysgen);
	if ((pp->p_flags&PFTRAC) != 0) {
		pp->p_flags |= PFWAIT;
		n = ptret();
		pp->p_flags &= ~(PFWAIT|PFSTOP);
		if (n == 0)
			return;
	}
	if (n>SIGKILL || n==SIGQUIT || n==SIGSYS) {
		if (sigdump())
			n |= 0200;
	}
	pexit(n);
}

/*
 * Create a dump of ourselves onto the file `core'.
 */
sigdump()
{
	register INODE *ip;
	register SR *srp;
	register SEG * sp;
	register int n;
	register paddr_t ssize;

	if ((SELF->p_flags&PFNDMP) != 0)
		return (0);
	u.u_io.io_seg  = IOSYS;
	u.u_io.io_flag = 0;
	/* Make the core with the real owners */
	schizo();
	if (ftoi("core", 'c') != 0) {
		schizo();
		return (0);
	}
	if ((ip=u.u_cdiri) == NULL) {
		if ((ip=imake(IFREG|0644, 0)) == NULL) {
			schizo();
			return (0);
		}
	} else {
		if ((ip->i_mode&IFMT)!=IFREG
		 || iaccess(ip, IPW)==0
		 || getment(ip->i_dev, 1)==NULL) {
			idetach(ip);
			schizo();
			return (0);
		}
		iclear(ip);
	}
	schizo();
	u.u_error = 0;
	u.u_io.io_seek = 0;
	for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) {
		if ((sp = srp->sr_segp)==NULL || (srp->sr_flag&SRFDUMP)==0)
			continue;
		u.u_io.io_seg = IOPHY;
		u.u_io.io_phys = sp->s_paddr;
		u.u_io.io_flag = 0;
		ssize = sp->s_size;
		sp->s_lrefc++;
		while (u.u_error == 0 && ssize != 0) {
			n = ssize > SCHUNK ? SCHUNK : ssize;
			u.u_io.io_ioc = n;
			iwrite(ip, &u.u_io);
			u.u_io.io_phys += (paddr_t)n;
			ssize -= (paddr_t)n;
		}
		sp->s_lrefc--;
	}
	idetach(ip);
	return (u.u_error==0);
}

/*
 * Send a ptrace command to the child.
 */
ptset(req, pid, addr, data)
unsigned req;
int *addr;
{
#ifdef TINY
	sendsig(SELF, SIGSYS);
	return (0);
#else
	register PROC *pp;

	lock(pnxgate);
	for (pp=procq.p_nforw; pp!=&procq; pp=pp->p_nforw)
		if (pp->p_pid == pid)
			break;
	unlock(pnxgate);
	if (pp==&procq || (pp->p_flags&PFSTOP)==0 || pp->p_ppid!=SELF->p_pid) {
		u.u_error = ESRCH;
		return;
	}
	lock(pts.pt_gate);
	pts.pt_req = req;
	pts.pt_pid = pid;
	pts.pt_addr = addr;
	pts.pt_data = data;
	pts.pt_errs = 0;
	pts.pt_rval = 0;
	pts.pt_busy = 1;
	wakeup((char *)&pts.pt_req);
	while (pts.pt_busy != 0)
		sleep((char *)&pts.pt_busy, CVPTSET, IVPTSET, SVPTSET);
	u.u_error = pts.pt_errs;
	unlock(pts.pt_gate);
	return (pts.pt_rval);
#endif
}

/*
 * This routine is called when a child that is being traced receives a signal
 * that is not caught or ignored.  It follows up on any requests by the parent
 * and returns when done.
 */
ptret()
{
#ifdef TINY
	return (SIGKILL);
#else
	register PROC *pp;
	register PROC *pp1;
	register int sign;

	pp = SELF;
next:
	u.u_error = 0;
	if (pp->p_ppid == 1)
		return (SIGKILL);
	sign = -1;
	lock(pnxgate);
	pp1 = &procq;
	for (;;) {
		if ((pp1=pp1->p_nforw) == &procq) {
			sign = SIGKILL;
			break;
		}
		if (pp1->p_pid != pp->p_ppid)
			continue;
		if (pp1->p_state == PSSLEEP)
			wakeup((char *)pp1);
		break;
	}
	unlock(pnxgate);
	while (sign < 0) {
		if (pts.pt_busy==0 || pp->p_pid!=pts.pt_pid) {
			sleep((char *)&pts.pt_req, CVPTRET, IVPTRET, SVPTRET);
			goto next;
		}
		switch (pts.pt_req) {
		case 1:
			pts.pt_rval = getuwi(pts.pt_addr);
			break;
		case 2:
			pts.pt_rval = getuwd(pts.pt_addr);
			break;
		case 3:
			if ((unsigned)pts.pt_addr < UPASIZE)
				pts.pt_rval = *(int *)((char *)&u+pts.pt_addr);
			else
				u.u_error = EINVAL;
			break;
		case 4:
			putuwi(pts.pt_addr, pts.pt_data);
			break;
		case 5:
			putuwd(pts.pt_addr, pts.pt_data);
			break;
		case 6:
			if (msetuof(pts.pt_addr, pts.pt_data) == 0)
				u.u_error = EINVAL;
			break;
		case 7:
			goto sig;
		case 8:
			sign = SIGKILL;
			break;
		case 9:
			msigsin();
		sig:
			if (pts.pt_data<0 || pts.pt_data>NSIG) {
				u.u_error = EINVAL;
				break;
			}
			sign = pts.pt_data;
			if (pts.pt_addr != SIG_IGN)
				msetppc((vaddr_t)pts.pt_addr);
			break;
		default:
			u.u_error = EINVAL;
		}
		if ((pts.pt_errs=u.u_error) == EFAULT)
			pts.pt_errs = EINVAL;
		pts.pt_busy = 0;
		wakeup((char *)&pts.pt_busy);
	}
	return (sign);
#endif
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d29 1
a29 1
#include <coherent.h>
d35 2
a36 2
#include <ptrace.h>
#include <sched.h>
@
0707070064030031761004440000030000030000011777770507310737000005000000025512/newbits/kernel/USRSRC/coh/RCS/sys1.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.52.21;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.33.56;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.31.32;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.41;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * General system calls.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:14:27	src
 * Initial revision
 * 
 * 87/11/05	Allan Cornish		/usr/src/sys/coh/sys1.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/10/21	Allan Cornish		/usr/src/sys/coh/sys1.c
 * ukill() no longer signals kernel processes if pid is -1.
 * usload() changed to new loadable driver format.
 *
 * 87/08/14	Allan Cornish		/usr/src/sys/coh/sys1.c
 * utick() system call added. Returns elapsed clock ticks since system startup.
 *
 * 87/07/23	Allan Cornish		/usr/src/sys/coh/sys1.c
 * ualarm2() now takes the delay interval as a long instead of an unsigned.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/coh/sys1.c
 * ualarm() modified to use timed functions to send alarm signal.
 * ualarm2() added to allow alarm times in clock ticks rather than seconds.
 *
 * 85/07/25	Allan Cornish
 * ukill() modified to allow a signal of 0 to check process existence.
 *
 * 85/07/9	Allan Cornish
 * ukill() modified to allow signals to be sent to other process groups.
 * usetpgrp() modified to be System V compatible (group set to pid).
 * ugetpgrp() system call added.
 */
#include <sys/coherent.h>
#include <acct.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <signal.h>
#include <sys/timeb.h>
#include <sys/times.h>
#include <sys/uproc.h>

/*
 * Send alarm signal to specified process - function timed by ualarm()
 */
static
sigalrm( pp )
register PROC * pp;
{
	sendsig( SIGALRM, pp );
}

/*
 * Send a SIGALARM signal in `n' seconds.
 */
ualarm(n)
unsigned n;
{
	register PROC * pp = SELF;
	register unsigned s;

	/*
	 * Calculate time left before current alarm timeout.
	 */
	s = 0;
	if ( pp->p_alrmtim.t_last != NULL )
		s = (pp->p_alrmtim.t_lbolt - lbolt + HZ - 1) / HZ;

	/*
	 * Cancel previous alarm [if any], start new alarm [if n != 0].
	 */
	timeout2( &pp->p_alrmtim, (long) n * HZ, sigalrm, pp );

	/*
	 * Return time left before previous alarm timeout.
	 */
	return( s );
}

/*
 * Send a SIGALARM signal in `n' clock ticks.
 */
long
ualarm2(n)
long n;
{
	register PROC * pp = SELF;
	long s;

	/*
	 * Calculate time left before current alarm timeout.
	 */
	s = 0;
	if ( pp->p_alrmtim.t_last != NULL )
		s = pp->p_alrmtim.t_lbolt - lbolt;

	/*
	 * Cancel previous alarm [if any], start new alarm [if n != 0].
	 */
	timeout2( &pp->p_alrmtim, (long) n, sigalrm, pp );

	/*
	 * Return time left before previous alarm timeout.
	 */
	return( s );
}

/*
 * Change the size of our data segment.
 */
char *
ubrk(cp)
char *cp;
{
	register SEG *sp;
	register vaddr_t sb;

	sp = SELF->p_segp[SIPDATA];
	sb = u.u_segl[SIPDATA].sr_base;
	if (cp != NULL)
		segsize(sp, (vaddr_t)cp-sb);
#ifdef	OLD
	return (0);
#else
	sb += sp->s_size;
	return ((char *)sb);
#endif
}

/*
 * Execute a l.out.
 */
uexece(np, argp, envp)
char *np;
char *argp[];
char *envp[];
{
	pexece(np, argp, envp);
}

/*
 * Exit.
 */
uexit(s)
{
	pexit(s<<8);
}

/*
 * Fork.
 */
ufork()
{
	return (pfork());
}

/*
 * Return date and time.
 */
uftime(tbp)
struct timeb *tbp;
{
	register int s;
	struct timeb timeb;

	timeb.time = timer.t_time;
	/* This should be a machine.h macro to avoid
	 * unnecessary long arithmetic and roundoff errors
	 */
	timeb.millitm = timer.t_tick*(1000/HZ);
	timeb.timezone = timer.t_zone;
	timeb.dstflag = timer.t_dstf;
	s = sphi();
	kucopy(&timeb, tbp, sizeof(timeb));
	spl(s);
}

/*
 * Get effective group id.
 */
ugetegid()
{
	return (u.u_gid);
}

/*
 * Get effective user id.
 */
ugeteuid()
{
	return (u.u_uid);
}

/*
 * Get group id.
 */
ugetgid()
{
	return (u.u_rgid);
}

/*
 * Get process id.
 */
ugetpid()
{
	return (SELF->p_pid);
}

/*
 * Get user id.
 */
ugetuid()
{
	return (u.u_ruid);
}

/*
 * Get process group.
 */
ugetpgrp()
{
	return (SELF->p_group);
}

/*
 * Set the process group.
 * When process group is 0 and a terminal is
 * opened, this process is made the base of
 * processes associated with that terminal.
 */
usetpgrp()
{
	register PROC * pp = SELF;

	return (pp->p_group = pp->p_pid);
}

/*
 * Send the signal `sig' to the process with id `pid'.
 */
ukill(pid, sig)
int pid;
register unsigned sig;
{
	register PROC *pp;
	register int sigflag;

	if ( sig > NSIG ) {
		u.u_error = EINVAL;
		return;
	}
	sigflag = 0;
	lock(pnxgate);
	if (pid > 0) {	/* send to matching process */
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_pid == pid) {
				sigflag = 1;
				if ( sig ) {
					if (sigperm(sig, pp))
						sendsig(sig, pp);
					else
						u.u_error = EPERM;
				}
				break;
			}
		}
	}
	else if (pid < -1) {
		pid = -pid;
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_group == pid) {
				sigflag = 1;
				if (sig) {
					if (sigperm(sig, pp))
						sendsig(sig,pp);
					else
						u.u_error = EPERM;
				}
			}
		}
	}
	else if (pid == 0) {
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_group == SELF->p_group) {
				sigflag = 1;
				if (sig && sigperm(sig, pp))
					sendsig(sig, pp);
			}
		}
	}
	else if (pid == -1) {
		for ( pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw ) {
			if (pp->p_state == PSDEAD)
				continue;
			if (pp->p_pid == 0)
				continue;
			if (pp->p_pid == 1)
				continue;
			if ( pp->p_flags & PFKERN )
				continue;
			sigflag = 1;
			if (sig && super())
				sendsig(sig, pp);
		}
	}
	unlock(pnxgate);
	if (sigflag == 0)
		u.u_error = ESRCH;
	return (0);
}

/*
 * See if we have permission to send the signal, `sig' to the process, `pp'.
 */
sigperm(sig, pp)
register PROC *pp;
{
	if (u.u_uid == pp->p_uid)
		return (1);
	if (u.u_ruid == pp->p_ruid) {
		if (sig == SIGHUP
		||  sig == SIGINT
		||  sig == SIGQUIT
		||  sig == SIGTERM)
			return (1);
	}
	if (u.u_uid == 0) {
		u.u_flag |= ASU;
		return (1);
	}
	return (0);
}

/*
 * Lock a process in core.
 */
ulock(f)
{
	if (super() == 0)
		return;
	if (f)
		SELF->p_flags |= PFLOCK;
	else
		SELF->p_flags &= ~PFLOCK;
	return (0);
}

/*
 * Change priority by the given increment.
 */
unice(n)
register int n;
{
	n += SELF->p_nice;
	if (n < MINNICE)
		n = MINNICE;
	if (n > MAXNICE)
		n = MAXNICE;
	if (n<SELF->p_nice && super()==0)
		return;
	SELF->p_nice = n;
	return (0);
}

/*
 * Non existant system call.
 */
unone()
{
	u.u_error = EFAULT;
}

/*
 * Null system call.
 */
unull()
{
}

/*
 * Pause.  Go to sleep on a channel that nobody will wakeup so that only
 * signals will wake us up.
 */
upause()
{
	for (;;)
		sleep((char *)&u, CVPAUSE, IVPAUSE, SVPAUSE);
}

/*
 * Start profiling.  `bp' is the profile buffer, `n' is the size, `off'
 * is the offset in the users programme and `scale' is the scaling
 * factor.
 */
uprofil(bp, n, off, scale)
register char *bp;
{
	u.u_pbase = bp;
	u.u_pbend = bp + n;
	u.u_pofft = off;
	u.u_pscale = scale;
}

/*
 * Process trace.
 */
uptrace(req, pid, add, data)
int *add;
{
	if (req == 0) {
		SELF->p_flags |= PFTRAC;
		return (0);
	}
	return (ptset(req, pid, add, data));
}

/*
 * Set group id.
 */
usetgid(gid)
register int gid;
{
	if (u.u_gid!=gid && super()==0)
		return;
	u.u_gid = gid;
	u.u_rgid = gid;
	SELF->p_rgid = gid;
	return (0);
}

/*
 * Set user id.
 */
usetuid(uid)
register int uid;
{
	if (uid!=u.u_ruid && super()==0)
		return;
	u.u_uid = uid;
	u.u_ruid = uid;
	SELF->p_uid = uid;
	SELF->p_ruid = uid;
	return (0);
}

/*
 * Set up the action to be taken on a signal.
 */
int *
usignal(sig, f)
register int sig;
int (*f)();
{
	register PROC *pp;
	register sig_t s;
	register int (*o)();

	pp = SELF;
	if (sig<=0 || sig>NSIG || sig==SIGKILL) {
		u.u_error = EINVAL;
		return;
	}
	s = (sig_t)1 << --sig;
	o = u.u_sfunc[sig];
	/* This order is critical to isig's use */
	if (f == SIG_IGN) {
		pp->p_isig |= s;
		u.u_sfunc[sig] = f;
	} else {
		u.u_sfunc[sig] = f;
		pp->p_isig &= ~s;
	}
	pp->p_ssig &= ~s;
	return (o);
}

/*
 * Load a device driver.
 */
usload( np )
char *np;
{
	return( pload( np ) );
}

/*
 * Set time and date.
 */
ustime(tp)
register time_t *tp;
{
	register int s;

	if (super() == 0)
		return;
	s = sphi();
	ukcopy(tp, &timer.t_time, sizeof(*tp));
	spl(s);
	return (0);
}

/*
 * Return elapsed ticks since system startup.
 */
long
utick()
{
	return( lbolt );
}

/*
 * Return process times.
 */
utimes(tp)
struct tbuffer *tp;
{
	register PROC *pp;
	struct tbuffer tbuffer;

	pp = SELF;
	tbuffer.tb_utime = pp->p_utime;
	tbuffer.tb_stime = pp->p_stime;
	tbuffer.tb_cutime = pp->p_cutime;
	tbuffer.tb_cstime = pp->p_cstime;
	kucopy(&tbuffer, tp, sizeof(tbuffer));
	return (0);
}

/*
 * Unload a device driver.
 */
usuload(m)
register int m;
{
	if (super() == 0)
		return;
	puload(m);
	return (0);
}


/*
 * Wait for a child to terminate.
 */
uwait(stp)
int *stp;
{
	register PROC *pp;
	register PROC *ppp;
	register PROC *cpp;
	register int pid;

	ppp = SELF;
	for (;;) {
		lock(pnxgate);
		cpp = NULL;
		pp = &procq;
		while ((pp=pp->p_nforw) != &procq) {
			if (pp == ppp)
				continue;
			if (pp->p_ppid != ppp->p_pid)
				continue;
			if ((pp->p_flags&PFSTOP) != 0)
				continue;
			if ((pp->p_flags&PFWAIT) != 0) {
				pp->p_flags &= ~PFWAIT;
				pp->p_flags |= PFSTOP;
				unlock(pnxgate);
				if (stp != NULL)
					putuwd(stp, 0177);
				return (pp->p_pid);
			}
			if (pp->p_state == PSDEAD) {
				ppp->p_cutime += pp->p_utime + pp->p_cutime;
				ppp->p_cstime += pp->p_stime + pp->p_cstime;
				if (stp != NULL)
					putuwd(stp, pp->p_exit);
				pid = pp->p_pid;
				unlock(pnxgate);
				relproc(pp);
				return (pid);
			}
			cpp = pp;
		}
		unlock(pnxgate);
		if (cpp == NULL) {
			u.u_error = ECHILD;
			return;
		}
		sleep((char *)ppp, CVWAIT, IVWAIT, SVWAIT);
	}
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d48 1
a48 1
#include <coherent.h>
d53 1
a53 1
#include <sched.h>
@
0707070064030031171004440000030000030000011777770507310737200005000000020271/newbits/kernel/USRSRC/coh/RCS/sys3.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.52.41;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.34.20;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.31.54;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.53;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * System calls (more filesystem related calls).
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.3	89/02/07  18:50:27	src
 * Bug:	Console driver did not validate user addresses before initiating a
 * 	transfer.  This resulted in a system trap in protected mode if a write
 * 	outside of user data space was attempted.
 * Fix:	Reads and writes now validate user addresses via 'useracc' prior to
 * 	calling drivers. (ABC)
 * 
 * Revision 1.2	88/08/02  15:01:04	src
 * O_APPEND flag now supported on open/fcntl system calls.
 * 
 * Revision 1.1	88/03/24  16:14:35	src
 * Initial revision
 * 
 * 88/01/22	Allan Cornish		/usr/src/sys/coh/sys3.c
 * sysio() inode lock extended to cover getting/modifying file seek offset.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/sys3.c
 * uopen() now checks mode for O_NDELAY and sets IPNDLY bit in fdp->f_flag.
 * sysio() now checks fdp->f_flag for IPNDLY and sets IONDLY bit in io_flag.
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/fd.h>
#include <sys/filsys.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/io.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Open the file `np' with the mode `mode'.
 */
uopen(np, mode)
char *np;
{
	register int f;
	register INODE *ip;
	register int fd;

	switch (mode & 3) {
	case O_RDONLY:
		f = IPR;
		break;
	case O_WRONLY:
		f = IPW;
		break;
	case O_RDWR:
		f = IPR|IPW;
		break;
	default:
		u.u_error = EINVAL;
		return;
	}
	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, f) == 0) {
		idetach(ip);
		return;
	}
	if ( mode & O_NDELAY )
		f |= IPNDLY;
	if ( mode & O_APPEND )
		f |= IPAPPEND;
	if ((fd=fdopen(ip, f)) < 0) {
		idetach(ip);
		return;
	}
	iunlock(ip);
	return (fd);
}

/*
 * Create a pipe.
 */
upipe(fdp)
int fdp[2];
{
	register INODE *ip;
	register int fd1;
	register int fd2;

	if ((ip=pmake(0)) == NULL)
		return;
	if ((fd1=fdopen(ip, IPR)) >= 0) {
		ip->i_refc++;
		if ((fd2=fdopen(ip, IPW)) >= 0) {
			putuwd(&fdp[0], fd1);
			putuwd(&fdp[1], fd2);
			iunlock(ip);
			return (0);
		}
		--ip->i_refc;
		iunlock(ip);
		fdclose(fd1);
		return (0);
	}
	idetach(ip);
	return (0);
}

/*
 * Read `n' bytes into the buffer `bp' from file number `fd'.
 */
uread(fd, bp, n)
char *bp;
unsigned n;
{
	return (sysio(fd, bp, n, 0));
}

/*
 * Read or write `n' bytes from the file number `fd' using the buffer
 * `bp'.  If `f' is 0, we read, else write.
 */
sysio(fd, bp, n, f)
char *bp;
unsigned n;
{
	register FD *fdp;
	register INODE *ip;
	register int type;

	if ((fdp=fdget(fd)) == NULL)
		return (0);
	if ((fdp->f_flag&(f?IPW:IPR)) == 0) {
		u.u_error = EBADF;
		return (0);
	}
	if ( ! useracc( bp, n ) ) {
		u.u_error = EFAULT;
		return(0);
	}

	ip = fdp->f_ip;
	type = ip->i_mode&IFMT;
	if (type != IFCHR)
		ilock(ip);
	if ( fdp->f_flag & IPAPPEND )
		fdp->f_seek = ip->i_size;
	u.u_io.io_seek = fdp->f_seek;
	u.u_io.io_base = bp;
	u.u_io.io_ioc  = n;
	u.u_io.io_flag = (fdp->f_flag & IPNDLY) ? IONDLY : 0;
	if (f == 0) {
		iread(ip, &u.u_io);
		iacc(ip);		/* read - atime */
	} else {
		iwrite(ip, &u.u_io);
	}
	n -= u.u_io.io_ioc;
	fdp->f_seek += n;
	if (type != IFCHR)
		iunlock(ip);
	return (n);
}

/*
 * Return a status structure for the given file name.
 */
ustat(np, stp)
char *np;
struct stat *stp;
{
	register INODE *ip;
	struct stat stat;

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	istat(ip, &stat);
	idetach(ip);
	kucopy(&stat, stp, sizeof(stat));
	return (0);
}

/*
 * Write out all modified buffers, inodes and super blocks to disk.
 */
usync()
{
	register MOUNT *mp;
	static GATE syngate;

	lock(syngate);
	for (mp=mountp; mp!=NULL; mp=mp->m_next)
		msync(mp);
	bsync();
	unlock(syngate);
	return (0);
}

/*
 * Set the mask for file access.
 */
uumask(mask)
{
	register int omask;

	omask = u.u_umask;
	u.u_umask = mask & 0777;
	return (omask);
}

/*
 * Unmount the given device.
 */
uumount(sp)
char *sp;
{
	register INODE *ip;
	register MOUNT *mp;
	register MOUNT **mpp;
	register dev_t rdev;
	register int mode;

	if (ftoi(sp, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (iaccess(ip, IPR|IPW) == 0) {
		idetach(ip);
		return;
	}
	rdev = ip->i_a.i_rdev;
	mode = ip->i_mode;
	idetach(ip);
	if ((mode&IFMT) != IFBLK) {
		u.u_error = ENOTBLK;
		return;
	}
	for (mpp=&mountp; (mp=*mpp)!=NULL; mpp=&mp->m_next)
		if (mp->m_dev == rdev)
			break;
	if (mp == NULL) {
		u.u_error = EINVAL;
		return;
	}
	msync(mp);
	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_refc>0 && ip->i_dev==rdev) {
			u.u_error = EBUSY;
			return;
		}
	}
	for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
		if (ip->i_dev == rdev)
			ip->i_ino = 0;
	}
	bflush(rdev);
	dclose(rdev);
	*mpp = mp->m_next;
	mp->m_ip->i_flag &= ~IFMNT;
	ldetach(mp->m_ip);
	kfree(mp);
	return (0);
}

/*
 * Return an unique number.
 */
long
uunique()
{
	register MOUNT *mp;
	register struct filsys *fsp;

	if ((mp=getment(rootdev, 1)) == NULL)
		return;
	fsp = &mp->m_super;
	fsp->s_fmod = 1;
	return (++fsp->s_unique);
}

/*
 * Unlink the given file.
 */
uunlink(np)
char *np;
{
	register INODE *ip;
	register dev_t dev;

	if (ftoi(np, 'u') != 0)
		return;
	ip = u.u_pdiri;
	if (iaccess(ip, IPW) == 0) {
		u.u_error = EACCES;
		goto err;
	}
	dev = ip->i_dev;
	if (iucheck(dev, u.u_cdirn) == 0)
		goto err;
	idirent(0);
	idetach(ip);
	if ((ip=iattach(dev, u.u_cdirn)) == NULL)
		return;
	if (ip->i_nlink > 0)
		--ip->i_nlink;
	icrt(ip);	/* unlink - ctime */
	if ((ip->i_mode&IFMT)==IFPIPE && ip->i_nlink==0 && ip->i_refc==2)
		pevent(ip);
err:
	idetach(ip);
	return (0);
}

/*
 * Set file times.
 */
uutime(np, utime)
char *np;
time_t utime[2];
{
	register INODE *ip;
	time_t stime[2];

	if (ftoi(np, 'r') != 0)
		return;
	ip = u.u_cdiri;
	if (owner(ip->i_uid)) {
		iamc(ip);	/* utime - atime/mtime/ctime */
		if (utime != NULL) {
			ukcopy(utime, stime, sizeof(time_t[2]));
			ip->i_atime = stime[0];
			ip->i_mtime = stime[1];
		}
	}
	idetach(ip);
	return (0);
}

/*
 * Write `n' bytes from buffer `bp' on file number `fd'.
 */
uwrite(fd, bp, n)
char *bp;
unsigned n;
{
	return (sysio(fd, bp, n, 1));
}

/**
 *
 * int
 * useracc( base, count, mode )	-- determine user accessibility
 * caddr_t base;
 * int count;
 * int mode;
 *
 *	Input:	base  = offset in user data space of the region to be accessed.
 *		count = size of access region in bytes.
 *		mode  = access mode desired [B_READ or B_WRITE].
 *
 *	Action:	Verify user has desired access mode into specified region.
 *
 *	Return:	0 = permission denied.
 *		1 = access allowed.
 *
 *	Notes:	Mode is ignored for now, but is required for compatibility
 *		with System V, and future protected mode extensions.
 */

int
useracc( base, count, mode )
register char * base;
int count;
int mode;
{
	register char * end;
	extern char * udl;

	if ( (count == 0) && (base <= udl) )
		return( 1 );

	/*
	 * Compute address of last byte to be accessed.
	 */
	end = base + count - 1;

	/*
	 * Address has wrapped, or is past legal limit.
	 */
	if ( (end < base) || (end > udl) )
		return( 0 );

	return( 1 );
}


@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d40 1
a40 1
#include <coherent.h>
@
0707070064030031061004440000030000030000011777770507310737400005300000007567/newbits/kernel/USRSRC/coh/RCS/timeout.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.52.49;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.34.29;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.32.13;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.55;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Timeout management.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	89/08/01  13:56:42 	src
 * Bug:	#include <timeout.h> not accurate; timeout.h now in /usr/include/sys.
 * Fix:	#include <sys/timeout.h> now used. (ABC)
 * 
 * Revision 1.1	88/03/24  08:14:38 	src
 * Initial revision
 * 
 * 87/07/23	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Timeout2 function now cancels timer if delay value is 0.
 *
 * 87/07/08	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Timeout2 function added to support long timeouts.
 *
 * 87/07/07	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Support for multiple timing queues ported from RTX.
 *
 * 86/11/24	Allan Cornish		/usr/src/sys/coh/timeout.c
 * Added support for new t_last field in tim struct.
 */
#include <sys/coherent.h>
#include <sys/timeout.h>
#include <sys/fun.h>

/*
 * Given a pointer to a timeout structure, `tp', call the function `f'
 * with integer argument `a' in `n' ticks of the clock. The list is
 * searched to see if the specified timeout structure is already in a
 * list, and it is removed if already there.
 */
timeout(tp, n, f, a)
register TIM *tp;
unsigned n;
int (*f)();
char *a;
{
	register TIM ** qp;
	int s;

	/*
	 * Already on a timing queue.
	 */
	s = sphi();
	if ( qp = tp->t_last ) {
		tp->t_last = NULL;
		if ( *qp = tp->t_next )
			tp->t_next->t_last = qp;
	}
	spl( s );

	if ( f == NULL )
		return;

	/*
	 * Calculate clock tick at which timeout is to occur.
	 * Record function and argument to be invoked upon timeout.
	 */
	tp->t_lbolt = lbolt + n;
	tp->t_func  = f;
	tp->t_farg  = a;

	/*
	 * Identify timeout queue.
	 */
	qp = &timq[ tp->t_lbolt % nel(timq) ];

	/*
	 * Insert at head of timeout queue.
	 */
	s = sphi();
	if ( tp->t_next = *qp )
		tp->t_next->t_last = tp;
	tp->t_last = qp;
	*qp = tp;
	spl(s);
}

timeout2(tp, n, f, a)
register TIM *tp;
long n;
int (*f)();
char *a;
{
	register TIM ** qp;
	int s;

	/*
	 * Already on a timing queue.
	 */
	s = sphi();
	if ( qp = tp->t_last ) {
		tp->t_last = NULL;
		if ( *qp = tp->t_next )
			tp->t_next->t_last = qp;
	}
	spl( s );

	/*
	 * Do not schedule new timer if no function or delay interval.
	 */
	if ( (f == NULL) || (n == 0) )
		return;

	/*
	 * Calculate clock tick at which timeout is to occur.
	 * Record function and argument to be invoked upon timeout.
	 */
	tp->t_lbolt = lbolt + n;
	tp->t_func  = f;
	tp->t_farg  = a;

	/*
	 * Identify timeout queue.
	 */
	qp = &timq[ tp->t_lbolt % nel(timq) ];

	/*
	 * Insert at head of timeout queue.
	 */
	s = sphi();
	if ( tp->t_next = *qp )
		tp->t_next->t_last = tp;
	tp->t_last = qp;
	*qp = tp;
	spl(s);
}
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d39 1
a39 1
#include <coherent.h>
@
0707070064030056261004440000030000030000011777770507310737500004700000010734/newbits/kernel/USRSRC/coh/RCS/var.c,vhead     1.4;
branch   ;
access   ;
symbols  ;
locks    bin:1.4;
comment  @ * @;


1.4
date     91.07.24.07.52.52;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.15.14.34.33;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.32.17;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.37.59;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.4
log
@update prov by hal

@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Variables.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	89/08/01  13:57:35 	src
 * Bug:	#include <timeout.h> not accurate; timeout.h now in /usr/include/sys.
 * Fix:	#include <sys/timeout.h> now used. (ABC)
 * 
 * Revision 1.1	88/03/24  08:14:41 	src
 * Initial revision
 * 
 * 88/01/23	Allan Cornish		/usr/src/sys/coh/var.c
 * Default NSLOT increased from 10 to 64.
 *
 * 87/11/22	Allan Cornish		/usr/src/sys/coh/var.c
 * Holebot/holetop variables added to support extended memory.
 *
 * 87/11/14	Allan Cornish		/usr/src/sys/coh/var.c
 * Init code+data now split into icodep/icodes and idatap/idatas.
 *
 * 87/11/12	Allan Cornish		/usr/src/sys/coh/var.c
 * Corebot/coretop now paddr_t rather than saddr_t to support protected mode.
 *
 * 87/10/05	Allan Cornish		/usrs/rc/sys/coh/var.c
 * NSLOT, slotsz, and slotp variables added - loadable driver specific.
 *
 * 87/07/07	Allan Cornish		/usr/src/sys/coh/var.c
 * Lbolt variable added - clock ticks since startup - incremented by stand().
 * Timl variable replaced with timq variable.
 *
 * 87/02/01	Allan Cornish		/usr/src/sys/coh/var.c
 * ISTSIZE [stack size] changed from a define in /usr/include/sys/const.h to a
 * extern int in /usr/include/sys/param.h, with 4 Kbyte default set in var.c
 */
#include <sys/coherent.h>
#include <sys/buf.h>
#include <sys/con.h>
#include <sys/inode.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/seg.h>

int	 debflag = 0;			/* coherent.h */

int	 batflag;			/* coherent.h */
int	 outflag;			/* coherent.h */
int	 ttyflag;			/* coherent.h */
unsigned utimer;			/* coherent.h */
long	 lbolt;				/* coherent.h */
TIM	stimer;				/* coherent.h */
unsigned msize;				/* coherent.h */
unsigned asize;				/* coherent.h */
char	 *icodep;			/* coherent.h */
int	 icodes;			/* coherent.h */
char	 *idatap;			/* coherent.h */
int	 idatas;			/* coherent.h */
paddr_t	 corebot;			/* coherent.h */
paddr_t	 coretop;			/* coherent.h */
paddr_t	 holebot;			/* coherent.h */
paddr_t	 holetop;			/* coherent.h */
paddr_t	 blockp;			/* coherent.h */
paddr_t	 clistp;			/* coherent.h */
struct	 all *allkp;			/* coherent.h */
int	NSLOT	= 64;			/* coherent.h */
int	slotsz	= 64;			/* coherent.h */
int *	slotp;				/* coherent.h */

unsigned bufseqn;			/* buf.h */
int	 bufneed;			/* buf.h */
BUF	 swapbuf;			/* buf.h */
BUF	*bufl;				/* buf.h */

int	cltwant;			/* clist.h */
cmap_t	cltfree;			/* clist.h */

INODE	*inodep;			/* inode.h */
INODE	*acctip;			/* inode.h */

MOUNT	*mountp;			/* mount.h */

int	ISTSIZE	= 4096;			/* sys/param.h */

int	quantum;			/* proc.h */
int	disflag;			/* proc.h */
int	intflag;			/* proc.h */
int	cpid;				/* proc.h */
#ifdef QWAKEUP
int	ntowake;			/* proc.h */
#endif
GATE	pnxgate;			/* proc.h */
PROC	procq;				/* proc.h */
PROC	*iprocp;			/* proc.h */
PROC	*eprocp;			/* proc.h */
PROC	*cprocp;			/* proc.h */
PLINK	linkq[NHPLINK];			/* proc.h */

struct	ptrace pts;			/* ptrace.h */

int	sexflag;			/* seg.h */
GATE	seglink;			/* seg.h */
#ifndef NOMONITOR
int	swmflag;			/* seg.h */
#endif
SEG	segswap;			/* seg.h */
SEG	segmq;				/* seg.h */
SEG	segdq;				/* seg.h */
SEG	segiom;				/* seg.h */

TIM *	timq[256];			/* timeout.h */
@


1.3
log
@update by hal
@
text
@@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@d50 1
a50 1
#include <coherent.h>
d56 1
a56 1
#include <ptrace.h>
a57 1
#include <sys/timeout.h>
@
0707070064030103110407550000030000030000011777770507310737600003600000000000/newbits/kernel/USRSRC/ttydrv0707070064030103131004440000030000030000011777770507310737600004300000004203/newbits/kernel/USRSRC/ttydrv/ct.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent
 * Console terminal driver.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:18:09	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/drv/ct.c
 * Added support for System V.3 compatible polls.
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Functions for configuration.
 */
int	ctopen();
int	ctclose();
int	ctread();
int	ctwrite();
int	ctioctl();
int	ctpoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON ctcon ={
	DFCHR|DFPOL,			/* Flags */
	1,				/* Major index */
	ctopen,				/* Open */
	ctclose,			/* Close */
	nulldev,			/* Block */
	ctread,				/* Read */
	ctwrite,			/* Write */
	ctioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	nulldev,			/* Load */
	nulldev,			/* Unload */
	ctpoll				/* Poll */
};

/*
 * Open.
 */
ctopen(dev, m)
dev_t dev;
{
	register dev_t ttdev;

	if ((ttdev=SELF->p_ttdev) == NODEV) {
		u.u_error = ENXIO;
		return;
	}
	dopen(ttdev, m, DFCHR);
}

/*
 * Close.
 */
ctclose(dev)
dev_t dev;
{
	dclose(SELF->p_ttdev);
}

/*
 * Read.
 */
ctread(dev, iop)
dev_t dev;
IO *iop;
{
	dread(SELF->p_ttdev, iop);
}

/*
 * Write.
 */
ctwrite(dev, iop)
dev_t dev;
IO *iop;
{
	dwrite(SELF->p_ttdev, iop);
}

/*
 * Ioctl.
 */
ctioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	dioctl(SELF->p_ttdev, com, vec);
}

/*
 * Poll.
 */
ctpoll(dev, ev)
dev_t dev;
int ev;
{
	return dpoll(SELF->p_ttdev, ev);
}
0707070064030066271006440000030000030000011777770507310737700004400000042737/newbits/kernel/USRSRC/ttydrv/tty.c/*
 * File:	$USRSRC/ttydrv/tty.c
 *
 * Purpose:	COHERENT line discipline module.
 *	This is the common part of typewriter service. It handles all device-
 *	independent aspects of a typewriter, including tandem flow control,
 *	erase and kill, stop and start, and common ioctl functions.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.9  91/09/17  06:06:42  bin
 * updated by hal
 * 
 * Revision 1.8  91/09/13  18:01:39  piggy
 * Only do XON/XOFF flow control if TANDEM is set.
 * 
 * Revision 1.7  91/09/13  17:58:00  hal
 * Drop 3rd arg (was writing PSW directly from it!) for ttread/ttwrite.
 * General face lift.
 *
 *
 * Bug: no support for 8-bit characters.
 * Fix: don't strip keyboard input. 01/22/91.  (norm)
 *
 * Bug:	Switching modes between cooked and CBREAK/RAW left buffered input
 *	in the input buffer until returning to cooked mode. 05/13/91 norm
 *
 * Bug: setting speed to default in ttopen() was conditioned to
 *      use hard constants.  90/08/28.  hws
 *
 * Revision 1.5  91/06/06  18:28:53  norm
 * Restore 8-bit fix.
 *
 * Revision 1.2	89/07/17  11:51:20 	src
 * Bug:	Terminal could lock up when setting it to RAWIN mode, if
 * 	output was suspended due to X-OFF, and output data was present.
 * Fix:	Setting terminal to RAWIN mode now clears X-OFF, starts output
 * 	BEFORE waiting for output to drain.  Received signals now cause
 * 	operation to complete without waiting for drain. (ABC)
 *
 * Revision 1.1	88/03/24  16:18:12	src
 * Initial revision
 *
 * 86/12/12	Allan Cornish		/usr/src/sys/drv/tty.c
 * Added 3rd argument to ttpoll() to support non-blocking polls.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/drv/tty.c
 * Made ttread() and ttwrite() recognize the IONDLY flag in iop->io_flag.
 * wakeup() and pollwake() now have delayed invocation by defer().
 * Added poll [System V.3] capability.
 *
 * 85/06/28	Allan Cornish
 * made ttioctl() clear T_STOP flag if ISRIN.
 *
 * 85/03/04	Allan Cornish
 * made ttread()  interruptible.
 *
 * 85/03/01	Allan Cornish
 * made ttclose() interruptible.
 */

/*
 * Includes.
 */
#include <sys/clist.h>
#include <sys/coherent.h>
#include <sys/con.h>
#include <sys/deftty.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <errno.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

/* NEAR_OR_FAR_CALL is for invoking t_param and t_start */
#define	 NEAR_OR_FAR_CALL(tp_fn)  {\
	if (tp->t_cs_sel) \
		ld_call(tp->t_cs_sel, tp->tp_fn, tp); \
	else \
		(*tp->tp_fn)(tp); }

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
void ttclose();
void ttflush();
void tthup();
void ttin();
void ttioctl();
void ttopen();
int  ttout();
int  ttpoll();
void ttread();
void ttsetgrp();
void ttsignal();
void ttstart();
void ttstash();
void ttwrite();

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
extern	int	wakeup();
extern	void	pollwake();

/*
 * ttopen()
 *
 *	Called by driver on first open.
 *	Set up defaults.
 */
void ttopen(tp)
register TTY *tp;
{
	tp->t_escape = 0;
	tp->t_sgttyb.sg_ispeed = tp->t_dispeed;
	tp->t_sgttyb.sg_ospeed = tp->t_dospeed;
	tp->t_sgttyb.sg_erase  = DEF_SG_ERASE;
	tp->t_sgttyb.sg_kill   = DEF_SG_KILL;
	tp->t_sgttyb.sg_flags  = DEF_SG_FLAGS;
	tp->t_tchars.t_intrc   = DEF_T_INTRC;
	tp->t_tchars.t_quitc   = DEF_T_QUITC;
	tp->t_tchars.t_startc  = DEF_T_STARTC;
	tp->t_tchars.t_stopc   = DEF_T_STOPC;
	tp->t_tchars.t_eofc    = DEF_T_EOFC;
	tp->t_tchars.t_brkc    = DEF_T_BRKC;
	if (tp->t_param != NULL) {
		NEAR_OR_FAR_CALL(t_param)
	}
}

/*
 * ttsetgrp()
 *
 *	Set process group when process does not have one.
 *	Also set up process's controlling terminal.
 */
void ttsetgrp(tp, ctdev)
register TTY *tp;
dev_t ctdev;
{
	register PROC *pp;

	pp = SELF;
	if (pp->p_group == 0) {
		if (tp->t_group == 0)
			tp->t_group = pp->p_pid;
		pp->p_group = tp->t_group;
	}
	if (pp->p_ttdev == NODEV)
		pp->p_ttdev = ctdev;
}

/*
 * ttyclose()
 *
 *	Called by driver on the last close.
 *	Wait for all pending output to go out.
 *	Kill input.
 */
void ttclose(tp)
register TTY *tp;
{
	register int s;

	while (tp->t_oq.cq_cc != 0) {
		s = sphi();
		if (tp->t_oq.cq_cc != 0) {
			tp->t_flags |= T_DRAIN;
			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
		}
		spl(s);
		if (SELF->p_ssig && nondsig())
			break;
	}
	ttflush(tp);
	tp->t_flags = tp->t_group = 0;
}

/*
 * ttread()
 *
 *	The read routine for a tty device driver will call this function.
 *
 *	Move data from tp->t_iq to io segment iop.
 *	Number of characters to copy is in iop->ioc.
 *
 *	In cooked mode, copy up to the first newline or break character, or
 *	until the count runs out.
 *	In CBREAK or RAW modes, return when count runs out or when input clist
 *	is empty and we're returning at least one byte.
 */
void ttread(tp, iop)
register TTY *tp;
register IO *iop;
{
	register c;
	int o;
	int sioc = iop->io_ioc;  /* number of bytes to read */

	while (iop->io_ioc) {
		o = sphi();
		while ((c = getq(&tp->t_iq)) < 0) {
			if ((tp->t_flags & T_CARR) == 0) {
			   u.u_error = EIO;  /* error since no carrier */
			   spl(o);
			   return;
			}

			/* If we're in CBREAK or RAW mode, and we don't */
			/* have the special "blocking read" bit set for */
			/* these modes, and we read at least one byte   */
		        /* of input, return immediately, since we have  */
			/* run out of characters from the clist.	*/

			if (ISBBYB && ((tp->t_flags & T_BRD) == 0)
			   && iop->io_ioc < sioc) {
			   spl(o);
			   return;
			}

			/*
			 * Non-blocking reads.
			 * Tell user process to try again later.
			 */
			if ( iop->io_flag & IONDLY ) {
				u.u_error = EAGAIN;
				spl(o);
				return;
			}

			tp->t_flags |= T_INPUT;  /* wait for more data */
			sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN);

			if (SELF->p_ssig && nondsig()) {
				if (iop->io_ioc == sioc)
					u.u_error = EINTR;
				spl(o);
				return;
			}
		}
		/*
		 * Flow control - can we turn on input from the driver yet?
		 */
		if (tp->t_iq.cq_cc <= ILOLIM) {
			if ((tp->t_flags&T_ISTOP) != 0)
				tp->t_flags &= ~T_ISTOP;
			if ((tp->t_flags&T_TSTOP) != 0) {
				tp->t_flags &= ~T_TSTOP;
				while (putq(&tp->t_oq, startc) < 0) {
					ttstart(tp);
					waitq();
				}
				ttstart(tp);
			}
		}
		spl(o);
		if (!ISBBYB && ISEOF)
			return;
		if (ioputc(c, iop) < 0)
			return;
		if (!ISBBYB && (c=='\n' || ISBRK))
			return;
	}
}

/*
 * ttwrite()
 *
 *	Write routine.
 *	Transfer stuff to the character list.
 */
void ttwrite(tp, iop)
register TTY *tp;
register IO *iop;
{
	register c;
	int o;

	/*
	 * Non-blocking writes which can fit.
	 * NOTE: exhaustion of clists can still cause blocking writes.
	 */
	if ( (iop->io_flag & IONDLY) && (OHILIM >= iop->io_ioc) ) {

		/*
		 * No room.
		 */
		if ( tp->t_oq.cq_cc >= OHILIM-iop->io_ioc ) {
			u.u_error = EAGAIN;
			return;
		}
	}

	while ((c = iogetc(iop)) >= 0) {
		if ((tp->t_flags & T_CARR) == 0) {
			u.u_error = EIO;  /* error since no carrier */
			return;
		}
		o = sphi();
		while (tp->t_oq.cq_cc >= OHILIM) {
			ttstart(tp);
			if (tp->t_oq.cq_cc < OHILIM)
				break;
			tp->t_flags |= T_HILIM;
			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
			if (SELF->p_ssig && nondsig()) {
				u.u_error = EINTR;
				spl(o);
				return;
			}
		}
		while (putq(&tp->t_oq, c) < 0) {
			ttstart(tp);
			waitq();
		}
		spl(o);
	}
	o = sphi();
	ttstart(tp);
	spl(o);
}

/*
 * ttioctl()
 *
 *	This routine handles common typewriter ioctl functions.
 *	Note that flushing the stream now means drain the output
 *	and clear the input.
 */
void ttioctl(tp, com, vec)
register TTY *tp;
register struct sgttyb *vec;
{
	register int	flush = 0;
	register int	drain = 0;
	register char	*p1, *p2;
		 int    rload = 0;
		 int	was_bbyb = 0;

	switch (com) {
	case TIOCQUERY:
		kucopy(&tp->t_iq.cq_cc, vec, sizeof(int));
		break;
	case TIOCGETP:
		kucopy(&tp->t_sgttyb, vec, sizeof (struct sgttyb));
		break;
	case TIOCSETP:
	        ++flush;          /* flush input */
		++drain;	  /* delay for output */
		++rload;
		ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
		break;
	case TIOCSETN:
		was_bbyb = ISBBYB;	/* previous mode */
		++rload;
		ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
		if (!was_bbyb && ISBBYB && tp->t_ibx != 0) {
			p1 = &tp->t_ib[0];
			p2 = &tp->t_ib[tp->t_ibx];
			while (p1 < p2)
#if NOT_8_BIT
				putq(&tp->t_iq, (*p1++) & 0177);
#else
				putq(&tp->t_iq, (*p1++));
#endif
			tp->t_ibx = 0;
		}
		break;
	case TIOCGETC:
		kucopy(&tp->t_tchars, vec, sizeof (struct tchars));
		break;
	case TIOCSETC:
		++rload;
		++drain;
		ukcopy(vec, &tp->t_tchars, sizeof (struct tchars));
		break;
	case TIOCEXCL:
		tp->t_flags |= T_EXCL;
		break;
	case TIOCNXCL:
		tp->t_flags &= ~T_EXCL;
		break;
	case TIOCHPCL:		/* set hangup on last close */
		tp->t_flags |= T_HPCL;
		break;
	case TIOCCHPCL:		/* don't hangup on last close */
		if (!super())   /* only superuser may do this */
		   u.u_error = EPERM;        /* not su */
		else
 	   	   tp->t_flags &= ~T_HPCL;   /* turn off hangup bit */
		break;
	case TIOCGETTF:		/* get tty flag word */
		kucopy(&tp->t_flags, (unsigned *) vec, sizeof(unsigned));
		break;
	case TIOCFLUSH:
		++flush;        /* flush both input and output */
		++drain;
		break;
	case TIOCBREAD:		/* blocking read for CBREAK/RAW mode */
		tp->t_flags |= T_BRD;
		break;
	case TIOCCBREAD:	/* turn off CBREAK/RAW blocking read mode */
		tp->t_flags &= ~T_BRD;
		break;
	default:
		u.u_error = EINVAL;
	}

	/*
	 * Ensure output is enabled BEFORE waiting for output to drain.
	 */
	if ( (ISRIN) && (tp->t_flags & T_STOP) ) {
		tp->t_flags &= ~T_STOP;
		ttstart( tp );
	}

	/*
	 * Wait for output to drain, or signal to arrive.
	 */
	if (drain != 0) {
		while (tp->t_oq.cq_cc != 0) {
			tp->t_flags |= T_DRAIN;
			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
			if (SELF->p_ssig && nondsig())
				break;
		}
	}

	/*
	 * Flush input.
	 */
	if (flush != 0)
		ttflush(tp);

	/*
	 * Re-initialize hardware.
	 */
	if ( (rload != 0) && (tp->t_param != NULL) )
		NEAR_OR_FAR_CALL(t_param)
}

/*
 * ttpoll()
 *
 *	Polling routine.
 *	[System V.3 Compatible]
 */
int ttpoll( tp, ev, msec )
register TTY * tp;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll with no data present.
	 */
	if ( (ev & POLLIN) && (tp->t_iq.cq_cc == 0) ) {

		/*
		 * Blocking input poll.
		 */
		if ( msec != 0 )
			pollopen( &tp->t_ipolls );

		/*
		 * Second look to avoid interrupt race.
		 */
		if ( tp->t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}

	/*
	 * Output poll with no space.
	 */
	if ( (ev & POLLOUT) && (tp->t_oq.cq_cc >= OLOLIM) ) {

		/*
		 * Blocking output poll.
		 */
		if ( msec != 0 )
			pollopen( &tp->t_opolls );

		/*
		 * Second look to avoid interrupt race.
		 */
		if ( tp->t_oq.cq_cc >= OLOLIM )
			ev &= ~POLLIN;
	}

	if ( ((ev & POLLIN) == 0) && ((tp->t_flags & T_CARR) == 0) )
		ev |= POLLHUP;

	return ev;
}

/*
 * ttout()
 *
 *	Pull a character from the output queues of the typewriter.
 *	Doing fills, newline insert, tab expansion, etc.
 *
 *	If the stream is empty return a -1.
 *	Called at high priority.
 */
int ttout(tp)
register TTY *tp;
{
	register c;

	if (tp->t_nfill) {
		--tp->t_nfill;
		c = tp->t_fillb;
	} else if ((tp->t_flags&T_INL) != 0) {
		tp->t_flags &= ~T_INL;
		c = '\n';
	} else {
		if ((c=getq(&tp->t_oq)) < 0)
			return -1;
		if (!ISROUT) {
			if (c=='\n' && ISCRMOD) {
				tp->t_flags |= T_INL;
				c = '\r';
			} else if (c=='\t' && ISXTABS) {
				tp->t_nfill = ~(tp->t_hpos|~07);
				tp->t_fillb = ' ';
				c = ' ';
			}
		}
	}
	if (!ISROUT) {
		if (c == '\b') {
			if (tp->t_hpos)
				--tp->t_hpos;
		} else if (c == '\r')
			tp->t_hpos = 0;
		else if (c == '\t')
			tp->t_hpos = (tp->t_hpos|07) + 1;
#if NOT_8_BIT
		else if (c >= ' ' && c <= '~')
#else
		else if ((c >= ' ' && c <= '~') || (c >= 0200 && c <= 0376))
#endif
			++tp->t_hpos;
	}
	return c;
}

/*
 * ttin()
 *
 *	Pass a character to the device independent typewriter routines.
 *	Handle erase and kill, tandem flow control, and other magic.
 *	Called at high priority from  the driver's interrupt processor.
 */
void ttin(tp, c)
register TTY *tp;
register c;
{
	int dc, i, n;

	if (!ISRIN) {
#if NOT_8_BIT
		c &= 0177;
#endif
		if (ISINTR) {
			ttsignal(tp, SIGINT);
			return;
		}
		if (ISQUIT) {
			ttsignal(tp, SIGQUIT);
			return;
		}

		/*
		 * Only do flow control if TANDEM is set.
		 */
		if (ISTAND) {
			if (ISSTOP) {
				if ((tp->t_flags&T_STOP) == 0)
					tp->t_flags |= T_STOP;
				return;
			}
			if (ISSTART) {
				tp->t_flags &= ~T_STOP;
				ttstart(tp);
				return;
			}
		}
	}
	if ((tp->t_flags&T_ISTOP) != 0)
		return;
	if (!ISRIN) {
		if (c=='\r' && ISCRMOD)
			c = '\n';
		if (tp->t_escape != 0) {
			if (c == ESC)
				++tp->t_escape;
			else {
				if (ISERASE || ISKILL) {
					c |= 0200;
					--tp->t_escape;
				}
				while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
					tp->t_ib[tp->t_ibx++] = ESC;
					--tp->t_escape;
				}
				ttstash(tp, c);
			}
			if (ISECHO) {
#if NOT_8_BIT
				putq(&tp->t_oq, c&0177);
#else
				putq(&tp->t_oq, c); /* no strip for 8-bit */
#endif
				ttstart(tp);
			}
			return;
		}
		if (ISERASE && !ISCBRK) {
			while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
				tp->t_ib[tp->t_ibx++] = ESC;
				--tp->t_escape;
			}
			if (tp->t_ibx == 0)
				return;
			dc = tp->t_ib[--tp->t_ibx];
			if (ISECHO) {
				if (!ISCRT)
					putq(&tp->t_oq, c);
				/* don't erase for bell, null, or rubout */
#if NOT_8_BIT
				else if (((c = dc&0177) == '\007')
					|| c == 0 || c == 0177)
#else
				else if (((c = dc) == '\007')
					|| c == 0 || c == 0177 || c == 0377)
#endif
				        return;
				else if (c != '\b' && c != '\t') {
					putq(&tp->t_oq, '\b');
					putq(&tp->t_oq,  ' ');
					putq(&tp->t_oq, '\b');
				} else if (c == '\t') {
					n = tp->t_opos + tp->t_escape;
					for (i=0; i<tp->t_ibx; ++i) {
						c = tp->t_ib[i];
#if NOT_8_BIT
						if ((c&0200) != 0) {
							++n;
							c &= 0177;
						}
#endif
						if (c == '\b')
							--n;
						else {
							if (c == '\t')
								n |= 07;
							++n;
						}
					}
					while (n++ < tp->t_hpos)
						putq(&tp->t_oq, '\b');
				}
#if NOT_8_BIT
				if ((dc&0200) != 0) {
					if ((dc&0177) != '\b')
						putq(&tp->t_oq, '\b');
					putq(&tp->t_oq,  ' ');
					putq(&tp->t_oq, '\b');
				}
#endif
				ttstart(tp);
			}
			return;
		}
		if (ISKILL && !ISCBRK) {
			tp->t_ibx = 0;
			tp->t_escape = 0;
			if (ISECHO) {
				if (c < 0x20) {
					putq(&tp->t_oq, '^');
					c += 0x40;
				}
				putq(&tp->t_oq, c);
				putq(&tp->t_oq, '\n');
				ttstart(tp);
			}
			return;
		}
	}
	if (ISBBYB) {
		putq(&tp->t_iq, c);
		if ((tp->t_flags&T_INPUT) != 0) {
			tp->t_flags &= ~T_INPUT;
			defer( wakeup, (char *) &tp->t_iq );
		}
		if ( tp->t_ipolls.e_procp ) {
			tp->t_ipolls.e_procp = 0;
			defer( pollwake, (char *) &tp->t_ipolls );
		}
	} else {
		if (tp->t_ibx == 0)
			tp->t_opos = tp->t_hpos;
		if (c == ESC)
			++tp->t_escape;
		else
			ttstash(tp, c);
	}
	if (ISECHO) {
		if (ISRIN || !ISEOF) {
			putq(&tp->t_oq, c);
			ttstart(tp);
		}
	}
	if ((n=tp->t_iq.cq_cc)>=IHILIM)
		tp->t_flags |= T_ISTOP;
	else if (ISTAND && (tp->t_flags&T_TSTOP)==0 && n>=ITSLIM) {
		tp->t_flags |= T_TSTOP;
		putq(&tp->t_oq, stopc);
		ttstart(tp);
	}
}

/*
 * ttstash()
 *
 *	Cooked mode.
 *	Put character in the buffer and check for end of line.
 *	Only a legal end of line can take the last character position.
 */
void ttstash(tp, c)
register TTY *tp;
{
	register char *p1, *p2;

	if (c=='\n' || ISEOF || ISBRK) {
		p1 = &tp->t_ib[0];
		p2 = &tp->t_ib[tp->t_ibx];
		*p2++ = c;			/* Always room */
		while (p1 < p2)
#if NOT_8_BIT
			putq(&tp->t_iq, (*p1++)&0177);
#else
			putq(&tp->t_iq, (*p1++));
#endif
		tp->t_ibx = 0;
		tp->t_escape = 0;

		if ( tp->t_flags & T_INPUT ) {
			tp->t_flags &= ~T_INPUT;
			defer( wakeup, (char *) &tp->t_iq );
		}

		if ( tp->t_ipolls.e_procp ) {
			tp->t_ipolls.e_procp = 0;
			defer( pollwake, (char *) &tp->t_ipolls );
		}

	} else if (tp->t_ibx < NCIB-1)
		tp->t_ib[tp->t_ibx++] = c;
}

/*
 * ttstart()
 *
 *	Start output on a tty.
 *	Duck out if stopped.  Do wakeups.
 */
void ttstart(tp)
register TTY *tp;
{
	register int n;

	n = tp->t_flags;
	if ( n & T_STOP )
		return;

	if ((n&T_DRAIN)!=0 && tp->t_oq.cq_cc==0
	   && (n&T_INL)==0 && tp->t_nfill==0)
	{	tp->t_flags &= ~T_DRAIN;
		defer( wakeup, (char *) &tp->t_oq );
		return;
	}

	NEAR_OR_FAR_CALL(t_start)

	if ( tp->t_oq.cq_cc > OLOLIM )
		return;

	if ( n & T_HILIM ) {
	   	tp->t_flags &= ~T_HILIM;
		defer( wakeup, (char *) &tp->t_oq );
	}

	if ( tp->t_opolls.e_procp ) {
		tp->t_opolls.e_procp = 0;
		defer( pollwake, (char *) &tp->t_opolls );
	}
}

/*
 * ttflush()
 *
 *	Flush a tty.
 *	Called to clear out queues.
 */
void ttflush(tp)
register TTY *tp;
{
	clrq(&tp->t_iq);
	clrq(&tp->t_oq);

	if ( tp->t_flags & T_INPUT )
		defer( wakeup, (char *) &tp->t_iq );

	if ( tp->t_flags & (T_DRAIN|T_HILIM) )
		defer( wakeup, (char *) &tp->t_oq );

	if ( tp->t_ipolls.e_procp != 0 ) {
		tp->t_ipolls.e_procp = 0;
		defer( pollwake, (char *) &tp->t_ipolls );
	}

	if ( tp->t_opolls.e_procp != 0 ) {
		tp->t_opolls.e_procp = 0;
		defer( pollwake, (char *) &tp->t_opolls );
	}

	tp->t_ibx = 0;
	tp->t_escape = 0;
	tp->t_flags &= T_SAVE;  /* reset most flag bits */
}

/*
 * ttsignal()
 *
 *	Send a signal to every process in the given process group.
 */
void ttsignal(tp, sig)
TTY *tp;
int sig;
{
	register int g;
	register PROC *pp;

	g = tp->t_group;
	if (g == 0)
		return;
	ttflush(tp);
	pp = &procq;
	while ((pp=pp->p_nforw) != &procq)
		if (pp->p_group == g)
			sendsig(sig, pp);
}

/*
 * tthup()
 *
 *	Flag hangup internally to force errors on tty read/write, flush tty,
 *	then send hangup signal.
 */
void tthup(tp)
register TTY *tp;
{
	tp->t_flags &= ~T_CARR;  /* indicate no carrier */
	ttflush(tp);
	ttsignal(tp, SIGHUP);
}
0707070064030000770407550000030000030000011777770507310740300004200000000000/newbits/kernel/USRSRC/ttydrv/RCS0707070064030066241004440000030000030000011777770507310740300005200000061511/newbits/kernel/USRSRC/ttydrv/RCS/tty.c,vhead     1.9;
branch   ;
access   ;
symbols  ;
locks    bin:1.9;
comment  @ * @;


1.9
date     91.09.17.06.06.42;  author bin;  state Exp;
branches ;
next     1.8;

1.8
date     91.08.01.13.49.39;  author bin;  state Exp;
branches ;
next     1.7;

1.7
date     91.07.15.14.36.29;  author bin;  state Exp;
branches ;
next     1.6;

1.6
date     91.06.20.14.28.36;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.06.06.18.28.53;  author norm;  state Exp;
branches ;
next     1.4;

1.4
date     91.06.04.14.24.20;  author hal;  state Exp;
branches ;
next     1.3;

1.3
date     91.04.05.15.43.29;  author root;  state Exp;
branches ;
next     1.2;

1.2
date     91.04.05.15.24.35;  author root;  state Exp;
branches ;
next     1.1;

1.1
date     91.04.05.15.23.07;  author root;  state Exp;
branches ;
next     ;


desc
@Line discipline module for character devices.
@


1.9
log
@updated by hal
@
text
@/*
 * File:	$USRSRC/ttydrv/tty.c
 *
 * Purpose:	COHERENT line discipline module.
 *	This is the common part of typewriter service. It handles all device-
 *	independent aspects of a typewriter, including tandem flow control,
 *	erase and kill, stop and start, and common ioctl functions.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.8  91/09/13  18:01:39  piggy
 * Only do XON/XOFF flow control if TANDEM is set.
 * 
 * Revision 1.7  91/09/13  17:58:00  hal
 * Drop 3rd arg (was writing PSW directly from it!) for ttread/ttwrite.
 * General face lift.
 *
 *
 * Bug: no support for 8-bit characters.
 * Fix: don't strip keyboard input. 01/22/91.  (norm)
 *
 * Bug:	Switching modes between cooked and CBREAK/RAW left buffered input
 *	in the input buffer until returning to cooked mode. 05/13/91 norm
 *
 * Bug: setting speed to default in ttopen() was conditioned to
 *      use hard constants.  90/08/28.  hws
 *
 * Revision 1.5  91/06/06  18:28:53  norm
 * Restore 8-bit fix.
 *
 * Revision 1.2	89/07/17  11:51:20 	src
 * Bug:	Terminal could lock up when setting it to RAWIN mode, if
 * 	output was suspended due to X-OFF, and output data was present.
 * Fix:	Setting terminal to RAWIN mode now clears X-OFF, starts output
 * 	BEFORE waiting for output to drain.  Received signals now cause
 * 	operation to complete without waiting for drain. (ABC)
 *
 * Revision 1.1	88/03/24  16:18:12	src
 * Initial revision
 *
 * 86/12/12	Allan Cornish		/usr/src/sys/drv/tty.c
 * Added 3rd argument to ttpoll() to support non-blocking polls.
 *
 * 86/11/19	Allan Cornish		/usr/src/sys/drv/tty.c
 * Made ttread() and ttwrite() recognize the IONDLY flag in iop->io_flag.
 * wakeup() and pollwake() now have delayed invocation by defer().
 * Added poll [System V.3] capability.
 *
 * 85/06/28	Allan Cornish
 * made ttioctl() clear T_STOP flag if ISRIN.
 *
 * 85/03/04	Allan Cornish
 * made ttread()  interruptible.
 *
 * 85/03/01	Allan Cornish
 * made ttclose() interruptible.
 */

/*
 * Includes.
 */
#include <sys/clist.h>
#include <sys/coherent.h>
#include <sys/con.h>
#include <sys/deftty.h>
#include <sys/io.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/uproc.h>
#include <errno.h>

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */

/* NEAR_OR_FAR_CALL is for invoking t_param and t_start */
#define	 NEAR_OR_FAR_CALL(tp_fn)  {\
	if (tp->t_cs_sel) \
		ld_call(tp->t_cs_sel, tp->tp_fn, tp); \
	else \
		(*tp->tp_fn)(tp); }

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
void ttclose();
void ttflush();
void tthup();
void ttin();
void ttioctl();
void ttopen();
int  ttout();
int  ttpoll();
void ttread();
void ttsetgrp();
void ttsignal();
void ttstart();
void ttstash();
void ttwrite();

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
extern	int	wakeup();
extern	void	pollwake();

/*
 * ttopen()
 *
 *	Called by driver on first open.
 *	Set up defaults.
 */
void ttopen(tp)
register TTY *tp;
{
	tp->t_escape = 0;
	tp->t_sgttyb.sg_ispeed = tp->t_dispeed;
	tp->t_sgttyb.sg_ospeed = tp->t_dospeed;
	tp->t_sgttyb.sg_erase  = DEF_SG_ERASE;
	tp->t_sgttyb.sg_kill   = DEF_SG_KILL;
	tp->t_sgttyb.sg_flags  = DEF_SG_FLAGS;
	tp->t_tchars.t_intrc   = DEF_T_INTRC;
	tp->t_tchars.t_quitc   = DEF_T_QUITC;
	tp->t_tchars.t_startc  = DEF_T_STARTC;
	tp->t_tchars.t_stopc   = DEF_T_STOPC;
	tp->t_tchars.t_eofc    = DEF_T_EOFC;
	tp->t_tchars.t_brkc    = DEF_T_BRKC;
	if (tp->t_param != NULL) {
		NEAR_OR_FAR_CALL(t_param)
	}
}

/*
 * ttsetgrp()
 *
 *	Set process group when process does not have one.
 *	Also set up process's controlling terminal.
 */
void ttsetgrp(tp, ctdev)
register TTY *tp;
dev_t ctdev;
{
	register PROC *pp;

	pp = SELF;
	if (pp->p_group == 0) {
		if (tp->t_group == 0)
			tp->t_group = pp->p_pid;
		pp->p_group = tp->t_group;
	}
	if (pp->p_ttdev == NODEV)
		pp->p_ttdev = ctdev;
}

/*
 * ttyclose()
 *
 *	Called by driver on the last close.
 *	Wait for all pending output to go out.
 *	Kill input.
 */
void ttclose(tp)
register TTY *tp;
{
	register int s;

	while (tp->t_oq.cq_cc != 0) {
		s = sphi();
		if (tp->t_oq.cq_cc != 0) {
			tp->t_flags |= T_DRAIN;
			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
		}
		spl(s);
		if (SELF->p_ssig && nondsig())
			break;
	}
	ttflush(tp);
	tp->t_flags = tp->t_group = 0;
}

/*
 * ttread()
 *
 *	The read routine for a tty device driver will call this function.
 *
 *	Move data from tp->t_iq to io segment iop.
 *	Number of characters to copy is in iop->ioc.
 *
 *	In cooked mode, copy up to the first newline or break character, or
 *	until the count runs out.
 *	In CBREAK or RAW modes, return when count runs out or when input clist
 *	is empty and we're returning at least one byte.
 */
void ttread(tp, iop)
register TTY *tp;
register IO *iop;
{
	register c;
	int o;
	int sioc = iop->io_ioc;  /* number of bytes to read */

	while (iop->io_ioc) {
		o = sphi();
		while ((c = getq(&tp->t_iq)) < 0) {
			if ((tp->t_flags & T_CARR) == 0) {
			   u.u_error = EIO;  /* error since no carrier */
			   spl(o);
			   return;
			}

			/* If we're in CBREAK or RAW mode, and we don't */
			/* have the special "blocking read" bit set for */
			/* these modes, and we read at least one byte   */
		        /* of input, return immediately, since we have  */
			/* run out of characters from the clist.	*/

			if (ISBBYB && ((tp->t_flags & T_BRD) == 0)
			   && iop->io_ioc < sioc) {
			   spl(o);
			   return;
			}

			/*
			 * Non-blocking reads.
			 * Tell user process to try again later.
			 */
			if ( iop->io_flag & IONDLY ) {
				u.u_error = EAGAIN;
				spl(o);
				return;
			}

			tp->t_flags |= T_INPUT;  /* wait for more data */
			sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN);

			if (SELF->p_ssig && nondsig()) {
				if (iop->io_ioc == sioc)
					u.u_error = EINTR;
				spl(o);
				return;
			}
		}
		/*
		 * Flow control - can we turn on input from the driver yet?
		 */
		if (tp->t_iq.cq_cc <= ILOLIM) {
			if ((tp->t_flags&T_ISTOP) != 0)
				tp->t_flags &= ~T_ISTOP;
			if ((tp->t_flags&T_TSTOP) != 0) {
				tp->t_flags &= ~T_TSTOP;
				while (putq(&tp->t_oq, startc) < 0) {
					ttstart(tp);
					waitq();
				}
				ttstart(tp);
			}
		}
		spl(o);
		if (!ISBBYB && ISEOF)
			return;
		if (ioputc(c, iop) < 0)
			return;
		if (!ISBBYB && (c=='\n' || ISBRK))
			return;
	}
}

/*
 * ttwrite()
 *
 *	Write routine.
 *	Transfer stuff to the character list.
 */
void ttwrite(tp, iop)
register TTY *tp;
register IO *iop;
{
	register c;
	int o;

	/*
	 * Non-blocking writes which can fit.
	 * NOTE: exhaustion of clists can still cause blocking writes.
	 */
	if ( (iop->io_flag & IONDLY) && (OHILIM >= iop->io_ioc) ) {

		/*
		 * No room.
		 */
		if ( tp->t_oq.cq_cc >= OHILIM-iop->io_ioc ) {
			u.u_error = EAGAIN;
			return;
		}
	}

	while ((c = iogetc(iop)) >= 0) {
		if ((tp->t_flags & T_CARR) == 0) {
			u.u_error = EIO;  /* error since no carrier */
			return;
		}
		o = sphi();
		while (tp->t_oq.cq_cc >= OHILIM) {
			ttstart(tp);
			if (tp->t_oq.cq_cc < OHILIM)
				break;
			tp->t_flags |= T_HILIM;
			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
			if (SELF->p_ssig && nondsig()) {
				u.u_error = EINTR;
				spl(o);
				return;
			}
		}
		while (putq(&tp->t_oq, c) < 0) {
			ttstart(tp);
			waitq();
		}
		spl(o);
	}
	o = sphi();
	ttstart(tp);
	spl(o);
}

/*
 * ttioctl()
 *
 *	This routine handles common typewriter ioctl functions.
 *	Note that flushing the stream now means drain the output
 *	and clear the input.
 */
void ttioctl(tp, com, vec)
register TTY *tp;
register struct sgttyb *vec;
{
	register int	flush = 0;
	register int	drain = 0;
	register char	*p1, *p2;
		 int    rload = 0;
		 int	was_bbyb = 0;

	switch (com) {
	case TIOCQUERY:
		kucopy(&tp->t_iq.cq_cc, vec, sizeof(int));
		break;
	case TIOCGETP:
		kucopy(&tp->t_sgttyb, vec, sizeof (struct sgttyb));
		break;
	case TIOCSETP:
	        ++flush;          /* flush input */
		++drain;	  /* delay for output */
		++rload;
		ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
		break;
	case TIOCSETN:
		was_bbyb = ISBBYB;	/* previous mode */
		++rload;
		ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
		if (!was_bbyb && ISBBYB && tp->t_ibx != 0) {
			p1 = &tp->t_ib[0];
			p2 = &tp->t_ib[tp->t_ibx];
			while (p1 < p2)
#if NOT_8_BIT
				putq(&tp->t_iq, (*p1++) & 0177);
#else
				putq(&tp->t_iq, (*p1++));
#endif
			tp->t_ibx = 0;
		}
		break;
	case TIOCGETC:
		kucopy(&tp->t_tchars, vec, sizeof (struct tchars));
		break;
	case TIOCSETC:
		++rload;
		++drain;
		ukcopy(vec, &tp->t_tchars, sizeof (struct tchars));
		break;
	case TIOCEXCL:
		tp->t_flags |= T_EXCL;
		break;
	case TIOCNXCL:
		tp->t_flags &= ~T_EXCL;
		break;
	case TIOCHPCL:		/* set hangup on last close */
		tp->t_flags |= T_HPCL;
		break;
	case TIOCCHPCL:		/* don't hangup on last close */
		if (!super())   /* only superuser may do this */
		   u.u_error = EPERM;        /* not su */
		else
 	   	   tp->t_flags &= ~T_HPCL;   /* turn off hangup bit */
		break;
	case TIOCGETTF:		/* get tty flag word */
		kucopy(&tp->t_flags, (unsigned *) vec, sizeof(unsigned));
		break;
	case TIOCFLUSH:
		++flush;        /* flush both input and output */
		++drain;
		break;
	case TIOCBREAD:		/* blocking read for CBREAK/RAW mode */
		tp->t_flags |= T_BRD;
		break;
	case TIOCCBREAD:	/* turn off CBREAK/RAW blocking read mode */
		tp->t_flags &= ~T_BRD;
		break;
	default:
		u.u_error = EINVAL;
	}

	/*
	 * Ensure output is enabled BEFORE waiting for output to drain.
	 */
	if ( (ISRIN) && (tp->t_flags & T_STOP) ) {
		tp->t_flags &= ~T_STOP;
		ttstart( tp );
	}

	/*
	 * Wait for output to drain, or signal to arrive.
	 */
	if (drain != 0) {
		while (tp->t_oq.cq_cc != 0) {
			tp->t_flags |= T_DRAIN;
			sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
			if (SELF->p_ssig && nondsig())
				break;
		}
	}

	/*
	 * Flush input.
	 */
	if (flush != 0)
		ttflush(tp);

	/*
	 * Re-initialize hardware.
	 */
	if ( (rload != 0) && (tp->t_param != NULL) )
		NEAR_OR_FAR_CALL(t_param)
}

/*
 * ttpoll()
 *
 *	Polling routine.
 *	[System V.3 Compatible]
 */
int ttpoll( tp, ev, msec )
register TTY * tp;
int ev;
int msec;
{
	/*
	 * Priority polls not supported.
	 */
	ev &= ~POLLPRI;

	/*
	 * Input poll with no data present.
	 */
	if ( (ev & POLLIN) && (tp->t_iq.cq_cc == 0) ) {

		/*
		 * Blocking input poll.
		 */
		if ( msec != 0 )
			pollopen( &tp->t_ipolls );

		/*
		 * Second look to avoid interrupt race.
		 */
		if ( tp->t_iq.cq_cc == 0 )
			ev &= ~POLLIN;
	}

	/*
	 * Output poll with no space.
	 */
	if ( (ev & POLLOUT) && (tp->t_oq.cq_cc >= OLOLIM) ) {

		/*
		 * Blocking output poll.
		 */
		if ( msec != 0 )
			pollopen( &tp->t_opolls );

		/*
		 * Second look to avoid interrupt race.
		 */
		if ( tp->t_oq.cq_cc >= OLOLIM )
			ev &= ~POLLIN;
	}

	if ( ((ev & POLLIN) == 0) && ((tp->t_flags & T_CARR) == 0) )
		ev |= POLLHUP;

	return ev;
}

/*
 * ttout()
 *
 *	Pull a character from the output queues of the typewriter.
 *	Doing fills, newline insert, tab expansion, etc.
 *
 *	If the stream is empty return a -1.
 *	Called at high priority.
 */
int ttout(tp)
register TTY *tp;
{
	register c;

	if (tp->t_nfill) {
		--tp->t_nfill;
		c = tp->t_fillb;
	} else if ((tp->t_flags&T_INL) != 0) {
		tp->t_flags &= ~T_INL;
		c = '\n';
	} else {
		if ((c=getq(&tp->t_oq)) < 0)
			return -1;
		if (!ISROUT) {
			if (c=='\n' && ISCRMOD) {
				tp->t_flags |= T_INL;
				c = '\r';
			} else if (c=='\t' && ISXTABS) {
				tp->t_nfill = ~(tp->t_hpos|~07);
				tp->t_fillb = ' ';
				c = ' ';
			}
		}
	}
	if (!ISROUT) {
		if (c == '\b') {
			if (tp->t_hpos)
				--tp->t_hpos;
		} else if (c == '\r')
			tp->t_hpos = 0;
		else if (c == '\t')
			tp->t_hpos = (tp->t_hpos|07) + 1;
#if NOT_8_BIT
		else if (c >= ' ' && c <= '~')
#else
		else if ((c >= ' ' && c <= '~') || (c >= 0200 && c <= 0376))
#endif
			++tp->t_hpos;
	}
	return c;
}

/*
 * ttin()
 *
 *	Pass a character to the device independent typewriter routines.
 *	Handle erase and kill, tandem flow control, and other magic.
 *	Called at high priority from  the driver's interrupt processor.
 */
void ttin(tp, c)
register TTY *tp;
register c;
{
	int dc, i, n;

	if (!ISRIN) {
#if NOT_8_BIT
		c &= 0177;
#endif
		if (ISINTR) {
			ttsignal(tp, SIGINT);
			return;
		}
		if (ISQUIT) {
			ttsignal(tp, SIGQUIT);
			return;
		}

		/*
		 * Only do flow control if TANDEM is set.
		 */
		if (ISTAND) {
			if (ISSTOP) {
				if ((tp->t_flags&T_STOP) == 0)
					tp->t_flags |= T_STOP;
				return;
			}
			if (ISSTART) {
				tp->t_flags &= ~T_STOP;
				ttstart(tp);
				return;
			}
		}
	}
	if ((tp->t_flags&T_ISTOP) != 0)
		return;
	if (!ISRIN) {
		if (c=='\r' && ISCRMOD)
			c = '\n';
		if (tp->t_escape != 0) {
			if (c == ESC)
				++tp->t_escape;
			else {
				if (ISERASE || ISKILL) {
					c |= 0200;
					--tp->t_escape;
				}
				while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
					tp->t_ib[tp->t_ibx++] = ESC;
					--tp->t_escape;
				}
				ttstash(tp, c);
			}
			if (ISECHO) {
#if NOT_8_BIT
				putq(&tp->t_oq, c&0177);
#else
				putq(&tp->t_oq, c); /* no strip for 8-bit */
#endif
				ttstart(tp);
			}
			return;
		}
		if (ISERASE && !ISCBRK) {
			while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
				tp->t_ib[tp->t_ibx++] = ESC;
				--tp->t_escape;
			}
			if (tp->t_ibx == 0)
				return;
			dc = tp->t_ib[--tp->t_ibx];
			if (ISECHO) {
				if (!ISCRT)
					putq(&tp->t_oq, c);
				/* don't erase for bell, null, or rubout */
#if NOT_8_BIT
				else if (((c = dc&0177) == '\007')
					|| c == 0 || c == 0177)
#else
				else if (((c = dc) == '\007')
					|| c == 0 || c == 0177 || c == 0377)
#endif
				        return;
				else if (c != '\b' && c != '\t') {
					putq(&tp->t_oq, '\b');
					putq(&tp->t_oq,  ' ');
					putq(&tp->t_oq, '\b');
				} else if (c == '\t') {
					n = tp->t_opos + tp->t_escape;
					for (i=0; i<tp->t_ibx; ++i) {
						c = tp->t_ib[i];
#if NOT_8_BIT
						if ((c&0200) != 0) {
							++n;
							c &= 0177;
						}
#endif
						if (c == '\b')
							--n;
						else {
							if (c == '\t')
								n |= 07;
							++n;
						}
					}
					while (n++ < tp->t_hpos)
						putq(&tp->t_oq, '\b');
				}
#if NOT_8_BIT
				if ((dc&0200) != 0) {
					if ((dc&0177) != '\b')
						putq(&tp->t_oq, '\b');
					putq(&tp->t_oq,  ' ');
					putq(&tp->t_oq, '\b');
				}
#endif
				ttstart(tp);
			}
			return;
		}
		if (ISKILL && !ISCBRK) {
			tp->t_ibx = 0;
			tp->t_escape = 0;
			if (ISECHO) {
				if (c < 0x20) {
					putq(&tp->t_oq, '^');
					c += 0x40;
				}
				putq(&tp->t_oq, c);
				putq(&tp->t_oq, '\n');
				ttstart(tp);
			}
			return;
		}
	}
	if (ISBBYB) {
		putq(&tp->t_iq, c);
		if ((tp->t_flags&T_INPUT) != 0) {
			tp->t_flags &= ~T_INPUT;
			defer( wakeup, (char *) &tp->t_iq );
		}
		if ( tp->t_ipolls.e_procp ) {
			tp->t_ipolls.e_procp = 0;
			defer( pollwake, (char *) &tp->t_ipolls );
		}
	} else {
		if (tp->t_ibx == 0)
			tp->t_opos = tp->t_hpos;
		if (c == ESC)
			++tp->t_escape;
		else
			ttstash(tp, c);
	}
	if (ISECHO) {
		if (ISRIN || !ISEOF) {
			putq(&tp->t_oq, c);
			ttstart(tp);
		}
	}
	if ((n=tp->t_iq.cq_cc)>=IHILIM)
		tp->t_flags |= T_ISTOP;
	else if (ISTAND && (tp->t_flags&T_TSTOP)==0 && n>=ITSLIM) {
		tp->t_flags |= T_TSTOP;
		putq(&tp->t_oq, stopc);
		ttstart(tp);
	}
}

/*
 * ttstash()
 *
 *	Cooked mode.
 *	Put character in the buffer and check for end of line.
 *	Only a legal end of line can take the last character position.
 */
void ttstash(tp, c)
register TTY *tp;
{
	register char *p1, *p2;

	if (c=='\n' || ISEOF || ISBRK) {
		p1 = &tp->t_ib[0];
		p2 = &tp->t_ib[tp->t_ibx];
		*p2++ = c;			/* Always room */
		while (p1 < p2)
#if NOT_8_BIT
			putq(&tp->t_iq, (*p1++)&0177);
#else
			putq(&tp->t_iq, (*p1++));
#endif
		tp->t_ibx = 0;
		tp->t_escape = 0;

		if ( tp->t_flags & T_INPUT ) {
			tp->t_flags &= ~T_INPUT;
			defer( wakeup, (char *) &tp->t_iq );
		}

		if ( tp->t_ipolls.e_procp ) {
			tp->t_ipolls.e_procp = 0;
			defer( pollwake, (char *) &tp->t_ipolls );
		}

	} else if (tp->t_ibx < NCIB-1)
		tp->t_ib[tp->t_ibx++] = c;
}

/*
 * ttstart()
 *
 *	Start output on a tty.
 *	Duck out if stopped.  Do wakeups.
 */
void ttstart(tp)
register TTY *tp;
{
	register int n;

	n = tp->t_flags;
	if ( n & T_STOP )
		return;

	if ((n&T_DRAIN)!=0 && tp->t_oq.cq_cc==0
	   && (n&T_INL)==0 && tp->t_nfill==0)
	{	tp->t_flags &= ~T_DRAIN;
		defer( wakeup, (char *) &tp->t_oq );
		return;
	}

	NEAR_OR_FAR_CALL(t_start)

	if ( tp->t_oq.cq_cc > OLOLIM )
		return;

	if ( n & T_HILIM ) {
	   	tp->t_flags &= ~T_HILIM;
		defer( wakeup, (char *) &tp->t_oq );
	}

	if ( tp->t_opolls.e_procp ) {
		tp->t_opolls.e_procp = 0;
		defer( pollwake, (char *) &tp->t_opolls );
	}
}

/*
 * ttflush()
 *
 *	Flush a tty.
 *	Called to clear out queues.
 */
void ttflush(tp)
register TTY *tp;
{
	clrq(&tp->t_iq);
	clrq(&tp->t_oq);

	if ( tp->t_flags & T_INPUT )
		defer( wakeup, (char *) &tp->t_iq );

	if ( tp->t_flags & (T_DRAIN|T_HILIM) )
		defer( wakeup, (char *) &tp->t_oq );

	if ( tp->t_ipolls.e_procp != 0 ) {
		tp->t_ipolls.e_procp = 0;
		defer( pollwake, (char *) &tp->t_ipolls );
	}

	if ( tp->t_opolls.e_procp != 0 ) {
		tp->t_opolls.e_procp = 0;
		defer( pollwake, (char *) &tp->t_opolls );
	}

	tp->t_ibx = 0;
	tp->t_escape = 0;
	tp->t_flags &= T_SAVE;  /* reset most flag bits */
}

/*
 * ttsignal()
 *
 *	Send a signal to every process in the given process group.
 */
void ttsignal(tp, sig)
TTY *tp;
int sig;
{
	register int g;
	register PROC *pp;

	g = tp->t_group;
	if (g == 0)
		return;
	ttflush(tp);
	pp = &procq;
	while ((pp=pp->p_nforw) != &procq)
		if (pp->p_group == g)
			sendsig(sig, pp);
}

/*
 * tthup()
 *
 *	Flag hangup internally to force errors on tty read/write, flush tty,
 *	then send hangup signal.
 */
void tthup(tp)
register TTY *tp;
{
	tp->t_flags &= ~T_CARR;  /* indicate no carrier */
	ttflush(tp);
	ttsignal(tp, SIGHUP);
}
@


1.8
log
@updated by hal to include rts/cts handshaking.
@
text
@d9 7
a15 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d17 1
d29 1
a29 1
 * 
d36 1
a36 1
 * 
d39 1
a39 1
 * 
d80 1
a80 1
 
d218 1
a218 1
			   spl(o);  
d226 1
a226 1
			/* run out of characters from the clist.	*/ 
d228 1
a228 1
			if (ISBBYB && ((tp->t_flags & T_BRD) == 0) 
d230 1
a230 1
			   spl(o);  
d347 1
a347 1
	register int	flush = 0;  
d398 1
a398 1
		break;	
d401 1
a401 1
		   u.u_error = EPERM;        /* not su */ 
d407 2
a408 2
		break;	
	case TIOCFLUSH: 
d410 1
a410 1
		++drain;	
d413 1
a413 1
		tp->t_flags |= T_BRD;		
d416 1
a416 1
		tp->t_flags &= ~T_BRD;		
d590 15
a604 9
		if (ISSTOP) {
			if ((tp->t_flags&T_STOP) == 0)
				tp->t_flags |= T_STOP;
			return;
		} 
		if (ISSTART) {
			tp->t_flags &= ~T_STOP;
			ttstart(tp);
			return;
@


1.7
log
@update by hal
@
text
@d1 2
a2 7
/*	     
 * This is the common part of
 * typewriter service. It handles all
 * device independent aspects of
 * a typewriter, including tandem flow
 * control, erase and kill, stop and
 * start and common ioctl functions.
d4 7
a19 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d50 5
d56 3
a58 1
#include <sys/clist.h>
d60 3
a64 6
#include <sys/sched.h>
#include <sys/io.h>
#include <sys/tty.h>
#include <sys/deftty.h>
#include <sys/stat.h>
#include <sys/con.h>
d67 5
a71 1
 * NEAR_OR_FAR_CALL is for invoking t_param and t_start
d73 2
d81 27
d112 4
a115 3
 * Tty open.
 * Called by driver on first open.
 * Set up defaults.
d117 1
a117 1
ttopen(tp)
d138 4
a141 3
 * ttsetgrp - set process group when process
 * does not have one.
 * Also set up process's controlling terminal.
d143 1
a143 1
ttsetgrp(tp, ctdev)
d160 5
a164 4
 * Tty close.
 * Called by driver on the last
 * close. Wait for all pending output
 * to go out. Kill input.
d166 1
a166 1
ttclose(tp)
d186 11
a196 6
 * Read routine.
 * In cooked mode, copy up to the first newline or
 * break character, or until the count runs out.
 * In CBREAK or RAW modes, return when count runs out
 * or when input clist is empty and we're returning
 * at least one byte.
d198 1
a198 1
ttread(tp, iop, s)
d207 1
a207 1
		o = spl(s);
d222 2
a223 2
			   && iop->io_ioc < sioc)
			{  spl(o);  
d229 1
d247 3
d273 4
a276 3
 * Write routine.
 * Transfer stuff to the character
 * list.
d278 1
a278 1
ttwrite(tp, iop, s)
d305 1
a305 1
		o = spl(s);
d324 1
a324 1
	o = spl(s);
d330 5
a334 4
 * This routine handles common
 * typewriter ioctl functions. Note that
 * flushing the stream now means drain the
 * output and clear the input.
d336 1
a336 1
ttioctl(tp, com, vec)
d449 4
a452 2
 * Polling routine.
 * [System V.3 Compatible]
d454 1
a454 1
ttpoll( tp, ev, msec )
d507 7
a513 7
 * Pull a character from the
 * output queues of the typewriter.
 * Doing fills, newline insert,
 * tab expansion and all other good
 * things. If the stream is empty
 * return a -1.
 * Called at high priority.
d515 1
a515 1
ttout(tp)
d528 1
a528 1
			return (-1);
d555 1
a555 1
	return (c);
d559 5
a563 7
 * Pass a character to the
 * device independent typewriter
 * routines. Handle erase and
 * kill, tandem flow control things
 * and other magic.
 * Called at high priority from 
 * the driver's interrupt processor.
d565 1
a565 1
ttin(tp, c)
d729 5
a733 5
 * Cooked mode.
 * Put character in the buffer and
 * check for end of line. Only a legal
 * end of line can take the last character
 * position.
d735 1
a735 1
ttstash(tp, c)
d768 4
a771 3
 * Start output on a tty.
 * Duck out if stopped.
 * Do wakeups.
d773 1
a773 1
ttstart(tp)
d806 4
a809 2
 * Flush a tty.
 * Called to clear out queues.
d811 1
a811 1
ttflush(tp)
d839 3
a841 1
 * Send a signal to every process in the given process group.
d843 1
a843 1
ttsignal(tp, sig)
d861 4
a864 2
 * Flag hangup internally to force errors
 * on tty read/write, flush tty, then send hangup signal.
d866 1
a866 1
tthup(tp)
@


1.6
log
@update provided by hal
@
text
@@


1.5
log
@Restore 8-bit fix.
@
text
@d18 4
a21 1
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
d49 4
a52 4
#include <coherent.h>
#include <clist.h>
#include <proc.h>
#include <uproc.h>
d54 6
a59 6
#include <sched.h>
#include <io.h>
#include <tty.h>
#include <deftty.h>
#include <stat.h>
#include <con.h>
@


1.4
log
@Fix loss of chars when switching between raw & cooked.
@
text
@d9 3
d312 1
d314 3
d491 5
a495 1
		else if (c>=' ' && c<='~')
d517 1
d519 1
d559 1
d561 3
d580 1
d583 4
d596 1
d601 1
d613 1
d620 1
d690 1
d692 3
@


1.3
log
@COH 3.1.0 version with Norm's 8bit mods added.
@
text
@d9 2
a10 2
 * Bug: no support for 8-bit characters.
 * Fix: don't strip keyboard input. 01/22/91.  norm
d284 1
d286 1
d298 3
d302 1
d305 7
d484 1
a484 1
		else if ((c >= ' ' && c <= '~') || c >= 0200)
d506 1
a534 1
#if 0
a538 1
#endif
d546 1
a546 1
				putq(&tp->t_oq, c);	/* not stripped */
d563 2
a564 2
				else if (((c = dc) == '\007')
					|| c == 0 || c == 0177 || c == 0377)
a573 1
#if 0
a577 1
#endif
a588 1
#if 0
a594 1
#endif
d664 1
a664 1
			putq(&tp->t_iq, (*p1++));
@


1.2
log
@Changes for 3.1.0, but before moving commons to support.c
@
text
@a0 14
/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
d9 3
a43 1
#include <al.h>
d55 3
a57 8
/* the following are shared by loadable serial drivers */
/*   (see al.h and poll_clk.h) */
int	com_usage[NUM_COM_PORTS];	/* COM_UNUSED/COM_IRQ/COM_POLLED */
int	poll_rate;
int	poll_owner;
TTY	*(tp_table[NUM_COM_PORTS]);	/* table of pointers for polling */

/* NEAR_OR_FAR_CALL is for invoking t_param and t_start */
d471 1
a471 1
		else if (c>=' ' && c<='~')
a492 1
		c &= 0177;
d521 1
d526 1
d534 1
a534 1
				putq(&tp->t_oq, c&0177);
d551 2
a552 2
				else if (((c = dc&0177) == '\007')
					|| c == 0 || c == 0177)
d562 1
d567 1
d579 1
d586 1
d656 1
a656 1
			putq(&tp->t_iq, (*p1++)&0177);
@


1.1
log
@Used in COHERENT 3.0.0
@
text
@d23 3
d55 1
d67 14
a92 1
#ifdef	OLD	/* How old? */
a94 4
#else
	tp->t_sgttyb.sg_ispeed = DEF_SG_ISPEED;	 /* default speed settings */
	tp->t_sgttyb.sg_ospeed = DEF_SG_OSPEED;
#endif
d104 3
a106 2
	if (tp->t_param != NULL)
		(*tp->t_param)(tp);
d387 1
a387 1
		(*tp->t_param)(tp);
d707 1
a707 1
	(*tp->t_start)(tp);
@
0707070064030020701004440000030000030000011777770507310741100005100000005156/newbits/kernel/USRSRC/ttydrv/RCS/ct.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3; strict;
comment  @ * @;


1.3
date     91.07.15.14.36.20;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.28.18;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.48.01;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.3
log
@update by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent
 * Console terminal driver.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:18:09	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/drv/ct.c
 * Added support for System V.3 compatible polls.
 */
#include <sys/coherent.h>
#include <sys/con.h>
#include <errno.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/uproc.h>

/*
 * Functions for configuration.
 */
int	ctopen();
int	ctclose();
int	ctread();
int	ctwrite();
int	ctioctl();
int	ctpoll();
int	nulldev();
int	nonedev();

/*
 * Configuration table.
 */
CON ctcon ={
	DFCHR|DFPOL,			/* Flags */
	1,				/* Major index */
	ctopen,				/* Open */
	ctclose,			/* Close */
	nulldev,			/* Block */
	ctread,				/* Read */
	ctwrite,			/* Write */
	ctioctl,			/* Ioctl */
	nulldev,			/* Powerfail */
	nulldev,			/* Timeout */
	nulldev,			/* Load */
	nulldev,			/* Unload */
	ctpoll				/* Poll */
};

/*
 * Open.
 */
ctopen(dev, m)
dev_t dev;
{
	register dev_t ttdev;

	if ((ttdev=SELF->p_ttdev) == NODEV) {
		u.u_error = ENXIO;
		return;
	}
	dopen(ttdev, m, DFCHR);
}

/*
 * Close.
 */
ctclose(dev)
dev_t dev;
{
	dclose(SELF->p_ttdev);
}

/*
 * Read.
 */
ctread(dev, iop)
dev_t dev;
IO *iop;
{
	dread(SELF->p_ttdev, iop);
}

/*
 * Write.
 */
ctwrite(dev, iop)
dev_t dev;
IO *iop;
{
	dwrite(SELF->p_ttdev, iop);
}

/*
 * Ioctl.
 */
ctioctl(dev, com, vec)
dev_t dev;
struct sgttyb *vec;
{
	dioctl(SELF->p_ttdev, com, vec);
}

/*
 * Poll.
 */
ctpoll(dev, ev)
dev_t dev;
int ev;
{
	return dpoll(SELF->p_ttdev, ev);
}
@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030103060407550000030000030000011777770507310741100003300000000000/newbits/kernel/USRSRC/ker0707070064030103101006440000030000030000011777770507310741100004200000002276/newbits/kernel/USRSRC/ker/elog.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent - event/error logging facility.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:19:48	src
 * Initial revision
 * 
 */
#include <coherent.h>

#define NEVENT 256
typedef struct {
	char	*e_event;	/* Function pointer or whatever */
	int	e_time;		/* Timer tick of event */
} EVENT;

EVENT events[NEVENT];
unsigned curevent = 0;
unsigned totevent = 0;

elog(eventp)
char *eventp;
{
	register EVENT *ep;

	totevent += 1;
	ep = &events[curevent++];
	curevent %= NEVENT;
	ep->e_event = eventp;
	ep->e_time = timer.t_time;
}
0707070064030104701006440000030000030000011777770507310741200004200000021036/newbits/kernel/USRSRC/ker/swap.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Swapper.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:19:51	src
 * Initial revision
 * 
 * 87/01/05	Allan Cornish		/usr/src/sys/ker/swap.c
 * Swap() now waits for all processes to be swapped in before exit on signal.
 */
#include <coherent.h>
#include <proc.h>
#include <sched.h>
#include <sys/seg.h>
#include <sys/uproc.h>
#include <sys/buf.h>

/*
 * Functions.
 */
SEG	*xmalloc();
SEG	*xdalloc();

swap()
{
	register SEG *sp;
	register PROC *pp1;
	register PROC *pp2;
	register PROC *pp3;
	register unsigned s;
	register unsigned n;
	register unsigned t;
	register unsigned v;
	register unsigned m;
	register int i;
	static unsigned ltimer;

	if (sexflag != 0)
		uexit(1);
	sexflag++;
	while (1) {
		lock(pnxgate);
		t = (utimer-ltimer)/NSUTICK;
		v = t*SVCLOCK;
		ltimer += t*NSUTICK;
		m = 0;
		pp2 = NULL;
		for (pp1=procq.p_nback; pp1!=&procq; pp1=pp1->p_nback) {
			if ((pp1->p_flags&PFCORE) != 0) {
				pp1->p_sval >>= t;
				pp1->p_ival -= t;
				if (pp1->p_ival < -30000)
					pp1->p_ival = -30000;
				continue;
			}
			addu(pp1->p_sval, v);
			if (pp1->p_state != PSRUN)
				continue;
			s = 0;
			for (i=0; i<NUSEG+1; i++)
				if ((sp=pp1->p_segp[i]) != NULL)
					if ((sp->s_flags&SFCORE) == 0)
						s += sp->s_size;
			if ((s=ctokrd(s)) == 0)
				s = 1;
			n = (pp1->p_sval+pp1->p_rval)/s;
			if (n > m) {
				m = n;
				pp2 = pp1;
			}
		}
		unlock(pnxgate);
		if (pp2 == NULL) {
			if ( SELF->p_ssig != 0 )
				break;
			goto con;
		}
#ifndef	NOMONITOR
		if (swmflag)
			printf("Swapin(%p, %d)\n", pp2, pp2->p_pid);
#endif
	xxx:
		while (testcore(pp2)==0 || proccore(pp2)!=0) {
			if ((pp2->p_flags&PFAUXM) != 0) {
				auxmdisk(pp2);
				goto xxx;
			}
			procdisk(pp2);
			i = 32767;
			pp3 = NULL;
			lock(pnxgate);
			for (pp1=procq.p_nforw; pp1!=&procq; pp1=pp1->p_nforw){
				if (pp1->p_flags&(PFSWIO|PFLOCK|PFKERN))
					continue;
				if ((pp1->p_flags&PFAUXM) != 0) {
					auxmdisk(pp1);
					unlock(pnxgate);
					goto xxx;
				}
				if ((pp1->p_flags&PFCORE) == 0) {
					if (procdisk(pp1) != 0) {
						unlock(pnxgate);
						goto xxx;
					}
					continue;
				}
				if (pp1->p_ival>-64 && pp1->p_sval!=0)
					continue;
				if (pp1->p_ival < i) {
					i = pp1->p_ival;
					pp3 = pp1;
				}
			}
			unlock(pnxgate);
			if (pp3 == NULL) {
#ifndef NOMONITOR
				if (swmflag)
					printf("No one to swap out\n");
#endif
				break;
			}
			if (i > 0) {
#ifndef NOMONITOR
				if (swmflag)
					printf("Dispatch(%p, %d)\n",
						pp3, pp3->p_pid);
#endif
				pp3->p_flags |= PFDISP;
				break;
			}
#ifndef NOMONITOR
			if (swmflag)
				printf("Swapout(%p, %d)\n", pp3, pp3->p_pid);
#endif
			procdisk(pp3);
		}
#ifndef NOMONITOR
		if (swmflag)
			printf("Swapdone\n");
#endif
	con:
		timeout(&stimer, NSRTICK, wakeup, (char *)&stimer);
		sleep((char *)&stimer, CVSWAP, IVSWAP, SVSWAP);
	}
	--sexflag;
	uexit(1);
}

/*
 * See if the given process may fit in core.
 */
testcore(pp)
register PROC *pp;
{
	register SEG *sp;
	register saddr_t s;
	register saddr_t s1;
	register saddr_t s2;
	register int i;

	s = 0;
	for (i=0; i<NUSEG+1; i++) {
		if ((sp=pp->p_segp[i]) == NULL)
			continue;
		if ((sp->s_flags&SFCORE) != 0)
			continue;
		if (sp->s_size > s)
			s = sp->s_size;
	}
	s1 = corebot;
	sp = &segmq;
	do {
		sp = sp->s_forw;
		s2 = sp->s_mbase;
		if (s2-s1 >= s)
			return (1);
		s1 = sp->s_mbase + sp->s_size;
	} while (sp != &segmq);
	return (0);
}

/*
 * Swap all segments associated with a particular process into core.
 * The number of segments still swapped out is returned.
 */
proccore(pp)
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int n;
	register int f;

	n = 0;
	f = pp->p_flags&PFSWAP;
	for (i=0; i<NUSEG+1; i++) {
		if ((sp=pp->p_segp[i]) == NULL)
			continue;
		if (f != 0)
			sp->s_lrefc++;
		if ((sp->s_flags&SFCORE)==0 && segcore(sp)==0)
			n++;
	}
	if (n == 0)
		pp->p_flags |= PFCORE;
	pp->p_flags &= ~PFSWAP;
	return (n);
}

/*
 * Swap out all segments associated with a given process.
 */
procdisk(pp)
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int f;
	int n;

	n = 0;
	f = pp->p_flags&PFSWAP;
	pp->p_flags &= ~PFCORE;
	for (i=0; i<NUSEG+1; i++) {
		if ((sp=pp->p_segp[i]) == NULL)
			continue;
		if (f == 0)
			--sp->s_lrefc;
		if ((sp->s_flags&SFCORE) == 0)
			continue;
		if (sp->s_lrefc == 0)
			if (segdisk(sp) != 0)
				n++;
	}
	pp->p_flags |= PFSWAP;
	return (n);
}

/*
 * Swap out all auxiliary segments used by a process.
 */
auxmdisk(pp)
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int f;
	register int m;
	SEG *segl[NUSEG];

#ifndef NOMONITOR
	if (swmflag)
		printf("Auxiliary(%p, %d)\n", pp, pp->p_pid);
#endif
	sp = pp->p_segp[SIUSERP];
	if ((sp->s_flags&SFCORE) == 0) {
		panic("We may be in trouble");
		return;
	}
	m = pp->p_flags&PFCORE;
	f = pp->p_flags&PFAUXM;
	pp->p_flags &= ~(PFAUXM|PFCORE);
	skcopy(sp, offset(uproc, u_sege[0]), segl, sizeof(u.u_sege));
	for (i=0; i<NUSEG; i++) {
		if ((sp=segl[i]) == NULL)
			continue;
		if (f != 0)
			--sp->s_lrefc;
		if ((sp->s_flags&SFCORE) == 0)
			continue;
		if (sp->s_lrefc == 0)
			segdisk(sp);
	}
	pp->p_flags |= m;
}

/*
 * Swap the given segment into core.
 */
segcore(sp1)
register SEG *sp1;
{
	register SEG *sp2;

	lock(seglink);
	sp2 = xmalloc(sp1->s_size);
	unlock(seglink);
	if (sp2 == NULL)
		return (0);
	sp1->s_lrefc++;
	swapio(0, sp2->s_mbase, sp1->s_dbase, sp2->s_size);
	lock(seglink);
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;
	sp1->s_flags |= SFCORE;
	sp1->s_mbase = sp2->s_mbase;
	--sp1->s_lrefc;
	unlock(seglink);
	return (1);
}

/*
 * Swap the given segment out onto disk.
 */
segdisk(sp1)
register SEG *sp1;
{
	register SEG *sp2;

	lock(seglink);
	sp2 = xdalloc(sp1->s_size);
	unlock(seglink);
	if (sp2 == NULL)
		return (0);
	sp1->s_lrefc++;
	swapio(1, sp1->s_mbase, sp2->s_dbase, sp1->s_size);
	lock(seglink);
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;
	sp1->s_flags &= ~SFCORE;
	sp1->s_dbase = sp2->s_dbase;
	--sp1->s_lrefc;
	unlock(seglink);
	return (1);
}

/*
 * Allocate a segment on disk that is `n' clicks long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `sdalloc' except that we can't run out of
 * alloc space to allocate the segment and we allocate in high regions.
 */
SEG *
xdalloc(s)
saddr_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register daddr_t d;
	register daddr_t d1;
	register daddr_t d2;

	d = stod(s);
	d2 = swaptop;
	sp1 = &segdq;
	do {
		if ((sp1=sp1->s_back) != &segdq)
			d1 = sp1->s_dbase + stod(sp1->s_size);
		else
			d1 = swapbot;
		if (d2-d1 >= d) {
			sp2 = &segswap;
			kclear((char *)sp2, sizeof(SEG));
			sp1->s_forw->s_back = sp2;
			sp2->s_forw = sp1->s_forw;
			sp1->s_forw = sp2;
			sp2->s_back = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size = s;
			sp2->s_dbase = d2 - d;
			return (sp2);
		}
		d2 = sp1->s_dbase;
	} while (sp1 != &segdq);
	return (NULL);
}

/*
 * Allocate a segment in memory that is `n' clicks long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `smalloc' except that we can't run out of
 * alloc space to allocate the segment.
 */
SEG *
xmalloc(s)
register saddr_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register saddr_t s1;
	register saddr_t s2;

	s1 = corebot;
	sp1 = &segmq;
	do {
		if ((sp1=sp1->s_forw) != &segmq)
			s2 = sp1->s_mbase;
		else
			s2 = coretop;
		if (s2-s1 >= s) {
			sp2 = &segswap;
			kclear((char *)sp2, sizeof(SEG));
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size = s;
			sp2->s_mbase = s1;
			return (sp2);
		}
		s1 = sp1->s_mbase + sp1->s_size;
	} while (sp1 != &segmq);
	return (NULL);
}
0707070064030104760407550000030000030000011777770507310741400003700000000000/newbits/kernel/USRSRC/ker/RCS0707070064030105341004440000030000030000011777770507310741400005000000003262/newbits/kernel/USRSRC/ker/RCS/elog.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3; strict;
comment  @ * @;


1.3
date     91.07.15.14.38.03;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.37.26;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.42.07;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.3
log
@update by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent - event/error logging facility.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:19:48	src
 * Initial revision
 * 
 */
#include <coherent.h>

#define NEVENT 256
typedef struct {
	char	*e_event;	/* Function pointer or whatever */
	int	e_time;		/* Timer tick of event */
} EVENT;

EVENT events[NEVENT];
unsigned curevent = 0;
unsigned totevent = 0;

elog(eventp)
char *eventp;
{
	register EVENT *ep;

	totevent += 1;
	ep = &events[curevent++];
	curevent %= NEVENT;
	ep->e_event = eventp;
	ep->e_time = timer.t_time;
}
@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030104711004440000030000030000011777770507310741400005000000022022/newbits/kernel/USRSRC/ker/RCS/swap.c,vhead     1.3;
branch   ;
access   ;
symbols  ;
locks    bin:1.3; strict;
comment  @ * @;


1.3
date     91.07.15.14.38.09;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.37.37;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.42.08;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.3
log
@update by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Swapper.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:19:51	src
 * Initial revision
 * 
 * 87/01/05	Allan Cornish		/usr/src/sys/ker/swap.c
 * Swap() now waits for all processes to be swapped in before exit on signal.
 */
#include <coherent.h>
#include <proc.h>
#include <sched.h>
#include <sys/seg.h>
#include <sys/uproc.h>
#include <sys/buf.h>

/*
 * Functions.
 */
SEG	*xmalloc();
SEG	*xdalloc();

swap()
{
	register SEG *sp;
	register PROC *pp1;
	register PROC *pp2;
	register PROC *pp3;
	register unsigned s;
	register unsigned n;
	register unsigned t;
	register unsigned v;
	register unsigned m;
	register int i;
	static unsigned ltimer;

	if (sexflag != 0)
		uexit(1);
	sexflag++;
	while (1) {
		lock(pnxgate);
		t = (utimer-ltimer)/NSUTICK;
		v = t*SVCLOCK;
		ltimer += t*NSUTICK;
		m = 0;
		pp2 = NULL;
		for (pp1=procq.p_nback; pp1!=&procq; pp1=pp1->p_nback) {
			if ((pp1->p_flags&PFCORE) != 0) {
				pp1->p_sval >>= t;
				pp1->p_ival -= t;
				if (pp1->p_ival < -30000)
					pp1->p_ival = -30000;
				continue;
			}
			addu(pp1->p_sval, v);
			if (pp1->p_state != PSRUN)
				continue;
			s = 0;
			for (i=0; i<NUSEG+1; i++)
				if ((sp=pp1->p_segp[i]) != NULL)
					if ((sp->s_flags&SFCORE) == 0)
						s += sp->s_size;
			if ((s=ctokrd(s)) == 0)
				s = 1;
			n = (pp1->p_sval+pp1->p_rval)/s;
			if (n > m) {
				m = n;
				pp2 = pp1;
			}
		}
		unlock(pnxgate);
		if (pp2 == NULL) {
			if ( SELF->p_ssig != 0 )
				break;
			goto con;
		}
#ifndef	NOMONITOR
		if (swmflag)
			printf("Swapin(%p, %d)\n", pp2, pp2->p_pid);
#endif
	xxx:
		while (testcore(pp2)==0 || proccore(pp2)!=0) {
			if ((pp2->p_flags&PFAUXM) != 0) {
				auxmdisk(pp2);
				goto xxx;
			}
			procdisk(pp2);
			i = 32767;
			pp3 = NULL;
			lock(pnxgate);
			for (pp1=procq.p_nforw; pp1!=&procq; pp1=pp1->p_nforw){
				if (pp1->p_flags&(PFSWIO|PFLOCK|PFKERN))
					continue;
				if ((pp1->p_flags&PFAUXM) != 0) {
					auxmdisk(pp1);
					unlock(pnxgate);
					goto xxx;
				}
				if ((pp1->p_flags&PFCORE) == 0) {
					if (procdisk(pp1) != 0) {
						unlock(pnxgate);
						goto xxx;
					}
					continue;
				}
				if (pp1->p_ival>-64 && pp1->p_sval!=0)
					continue;
				if (pp1->p_ival < i) {
					i = pp1->p_ival;
					pp3 = pp1;
				}
			}
			unlock(pnxgate);
			if (pp3 == NULL) {
#ifndef NOMONITOR
				if (swmflag)
					printf("No one to swap out\n");
#endif
				break;
			}
			if (i > 0) {
#ifndef NOMONITOR
				if (swmflag)
					printf("Dispatch(%p, %d)\n",
						pp3, pp3->p_pid);
#endif
				pp3->p_flags |= PFDISP;
				break;
			}
#ifndef NOMONITOR
			if (swmflag)
				printf("Swapout(%p, %d)\n", pp3, pp3->p_pid);
#endif
			procdisk(pp3);
		}
#ifndef NOMONITOR
		if (swmflag)
			printf("Swapdone\n");
#endif
	con:
		timeout(&stimer, NSRTICK, wakeup, (char *)&stimer);
		sleep((char *)&stimer, CVSWAP, IVSWAP, SVSWAP);
	}
	--sexflag;
	uexit(1);
}

/*
 * See if the given process may fit in core.
 */
testcore(pp)
register PROC *pp;
{
	register SEG *sp;
	register saddr_t s;
	register saddr_t s1;
	register saddr_t s2;
	register int i;

	s = 0;
	for (i=0; i<NUSEG+1; i++) {
		if ((sp=pp->p_segp[i]) == NULL)
			continue;
		if ((sp->s_flags&SFCORE) != 0)
			continue;
		if (sp->s_size > s)
			s = sp->s_size;
	}
	s1 = corebot;
	sp = &segmq;
	do {
		sp = sp->s_forw;
		s2 = sp->s_mbase;
		if (s2-s1 >= s)
			return (1);
		s1 = sp->s_mbase + sp->s_size;
	} while (sp != &segmq);
	return (0);
}

/*
 * Swap all segments associated with a particular process into core.
 * The number of segments still swapped out is returned.
 */
proccore(pp)
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int n;
	register int f;

	n = 0;
	f = pp->p_flags&PFSWAP;
	for (i=0; i<NUSEG+1; i++) {
		if ((sp=pp->p_segp[i]) == NULL)
			continue;
		if (f != 0)
			sp->s_lrefc++;
		if ((sp->s_flags&SFCORE)==0 && segcore(sp)==0)
			n++;
	}
	if (n == 0)
		pp->p_flags |= PFCORE;
	pp->p_flags &= ~PFSWAP;
	return (n);
}

/*
 * Swap out all segments associated with a given process.
 */
procdisk(pp)
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int f;
	int n;

	n = 0;
	f = pp->p_flags&PFSWAP;
	pp->p_flags &= ~PFCORE;
	for (i=0; i<NUSEG+1; i++) {
		if ((sp=pp->p_segp[i]) == NULL)
			continue;
		if (f == 0)
			--sp->s_lrefc;
		if ((sp->s_flags&SFCORE) == 0)
			continue;
		if (sp->s_lrefc == 0)
			if (segdisk(sp) != 0)
				n++;
	}
	pp->p_flags |= PFSWAP;
	return (n);
}

/*
 * Swap out all auxiliary segments used by a process.
 */
auxmdisk(pp)
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int f;
	register int m;
	SEG *segl[NUSEG];

#ifndef NOMONITOR
	if (swmflag)
		printf("Auxiliary(%p, %d)\n", pp, pp->p_pid);
#endif
	sp = pp->p_segp[SIUSERP];
	if ((sp->s_flags&SFCORE) == 0) {
		panic("We may be in trouble");
		return;
	}
	m = pp->p_flags&PFCORE;
	f = pp->p_flags&PFAUXM;
	pp->p_flags &= ~(PFAUXM|PFCORE);
	skcopy(sp, offset(uproc, u_sege[0]), segl, sizeof(u.u_sege));
	for (i=0; i<NUSEG; i++) {
		if ((sp=segl[i]) == NULL)
			continue;
		if (f != 0)
			--sp->s_lrefc;
		if ((sp->s_flags&SFCORE) == 0)
			continue;
		if (sp->s_lrefc == 0)
			segdisk(sp);
	}
	pp->p_flags |= m;
}

/*
 * Swap the given segment into core.
 */
segcore(sp1)
register SEG *sp1;
{
	register SEG *sp2;

	lock(seglink);
	sp2 = xmalloc(sp1->s_size);
	unlock(seglink);
	if (sp2 == NULL)
		return (0);
	sp1->s_lrefc++;
	swapio(0, sp2->s_mbase, sp1->s_dbase, sp2->s_size);
	lock(seglink);
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;
	sp1->s_flags |= SFCORE;
	sp1->s_mbase = sp2->s_mbase;
	--sp1->s_lrefc;
	unlock(seglink);
	return (1);
}

/*
 * Swap the given segment out onto disk.
 */
segdisk(sp1)
register SEG *sp1;
{
	register SEG *sp2;

	lock(seglink);
	sp2 = xdalloc(sp1->s_size);
	unlock(seglink);
	if (sp2 == NULL)
		return (0);
	sp1->s_lrefc++;
	swapio(1, sp1->s_mbase, sp2->s_dbase, sp1->s_size);
	lock(seglink);
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;
	sp1->s_flags &= ~SFCORE;
	sp1->s_dbase = sp2->s_dbase;
	--sp1->s_lrefc;
	unlock(seglink);
	return (1);
}

/*
 * Allocate a segment on disk that is `n' clicks long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `sdalloc' except that we can't run out of
 * alloc space to allocate the segment and we allocate in high regions.
 */
SEG *
xdalloc(s)
saddr_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register daddr_t d;
	register daddr_t d1;
	register daddr_t d2;

	d = stod(s);
	d2 = swaptop;
	sp1 = &segdq;
	do {
		if ((sp1=sp1->s_back) != &segdq)
			d1 = sp1->s_dbase + stod(sp1->s_size);
		else
			d1 = swapbot;
		if (d2-d1 >= d) {
			sp2 = &segswap;
			kclear((char *)sp2, sizeof(SEG));
			sp1->s_forw->s_back = sp2;
			sp2->s_forw = sp1->s_forw;
			sp1->s_forw = sp2;
			sp2->s_back = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size = s;
			sp2->s_dbase = d2 - d;
			return (sp2);
		}
		d2 = sp1->s_dbase;
	} while (sp1 != &segdq);
	return (NULL);
}

/*
 * Allocate a segment in memory that is `n' clicks long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `smalloc' except that we can't run out of
 * alloc space to allocate the segment.
 */
SEG *
xmalloc(s)
register saddr_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register saddr_t s1;
	register saddr_t s2;

	s1 = corebot;
	sp1 = &segmq;
	do {
		if ((sp1=sp1->s_forw) != &segmq)
			s2 = sp1->s_mbase;
		else
			s2 = coretop;
		if (s2-s1 >= s) {
			sp2 = &segswap;
			kclear((char *)sp2, sizeof(SEG));
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size = s;
			sp2->s_mbase = s1;
			return (sp2);
		}
		s1 = sp1->s_mbase + sp1->s_size;
	} while (sp1 != &segmq);
	return (NULL);
}
@


1.2
log
@update provided by hal
@
text
@@


1.1
log
@Initial revision
@
text
@@
0707070064030103030407550000030000030000011777770507310741700003400000000000/newbits/kernel/USRSRC/ldrv0707070064030131121006440000030000030000011777770507310741700004500000020214/newbits/kernel/USRSRC/ldrv/Makefile# $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $(USRSRC)/ldrv/RCS/Makefile,v 1.2 91/04/30 18:38:22 root Exp $

# Loadable Drivers - Makefile
#

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

CC=exec /bin/cc
CFLAGS=

TARGETS=$(USRSYS)/lib/ldrts0.o	\
	$(USRSYS)/lib/ldmain.o	\
	$(USRSYS)/lib/ldswap.o	\
	$(USRSYS)/lib/ldlib.a

ld_support:	$(TARGETS)
	@sync

$(USRSYS)/lib/ldrts0.o:	ldrts0.s
	as -xo $@ $<

$(USRSYS)/lib/ldmain.o:	ldmain.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(USRSYS)/lib/ldswap.o:	ldswap.c
	$(CC) $(CFLAGS) -DNOMONITOR -c -o $@ $<

# The following script extracts a module from a library.
X_LIB=	OBJFIL=`basename $@ | sed 's/L//'` ;\
	ar x $< $$OBJFIL ;\
	mv $$OBJFIL $@

# The following modules are supported in loadable drivers.
# NOTE: Most of them are interface stubs to kernel code.
#	Some of them are entirely driver resident.
LIBOBJ1=$(LOBJ)/absL.o		\
	$(LOBJ)/allocL.o	\
	$(LOBJ)/bclaimL.o	\
	$(LOBJ)/bdoneL.o	\
	$(LOBJ)/blkmvL.o	\
	$(LOBJ)/bootL.o		\
	$(LOBJ)/breadL.o	\
	$(LOBJ)/breleaseL.o	\
	$(LOBJ)/clockedfL.o	\
	$(LOBJ)/clrqL.o		\
	$(LOBJ)/cs_selfL.o	\
	$(LOBJ)/dblockL.o	\
	$(LOBJ)/dcloseL.o	\
	$(LOBJ)/deferL.o	\
	$(LOBJ)/devmsgL.o	\
	$(LOBJ)/dmagoL.o	\
	$(LOBJ)/dmalockL.o	\
	$(LOBJ)/dmaoffL.o	\
	$(LOBJ)/dmaonL.o	\
	$(LOBJ)/dmareqL.o	\
	$(LOBJ)/dopenL.o	\
	$(LOBJ)/drvmapL.o	\
	$(LOBJ)/dwriteL.o	\
	$(LOBJ)/fclearL.o	\
	$(LOBJ)/fdiskL.o	\
	$(LOBJ)/ffbyteL.o	\
	$(LOBJ)/ffwordL.o	\
	$(LOBJ)/ffmemL.o	\
	$(LOBJ)/fkcopyL.o	\
	$(LOBJ)/fpxcopyL.o	\
	$(LOBJ)/freeL.o		\
	$(LOBJ)/fucopyL.o	\
	$(LOBJ)/getcsL.o	\
	$(LOBJ)/getqL.o		\
	$(LOBJ)/getubdL.o	\
	$(LOBJ)/getuwdL.o	\
	$(LOBJ)/inbL.o		\
	$(LOBJ)/int11L.o	\
	$(LOBJ)/iogetcL.o	\
	$(LOBJ)/iomapvpL.o	\
	$(LOBJ)/ioputcL.o	\
	$(LOBJ)/ioreadL.o	\
	$(LOBJ)/ioreqL.o	\
	$(LOBJ)/iowriteL.o	\
	$(LOBJ)/ipcaccessL.o	\
	$(LOBJ)/kcallL.o	\
	$(LOBJ)/kfcopyL.o	\
	$(LOBJ)/kclearL.o	\
	$(LOBJ)/kpcopyL.o	\
	$(LOBJ)/kucopyL.o	\
	$(LOBJ)/lockL.o		\
	$(LOBJ)/lxdivL.o	\
	$(LOBJ)/lxmulL.o	\
	$(LOBJ)/lxremL.o	\
	$(LOBJ)/lxsgnL.o	\
	$(LOBJ)/memsetL.o	\
	$(LOBJ)/memtestL.o	\
	$(LOBJ)/nmidisableL.o	\
	$(LOBJ)/nmienableL.o	\
	$(LOBJ)/nondsigL.o	\
	$(LOBJ)/nonedevL.o	\
	$(LOBJ)/nulldevL.o	\

LIBOBJ2=$(LOBJ)/outbL.o		\
	$(LOBJ)/panicL.o	\
	$(LOBJ)/pclearL.o	\
	$(LOBJ)/pkcopyL.o	\
	$(LOBJ)/plrcopyL.o	\
	$(LOBJ)/pollopenL.o	\
	$(LOBJ)/pollwakeL.o	\
	$(LOBJ)/printfL.o	\
	$(LOBJ)/prlcopyL.o	\
	$(LOBJ)/ptovL.o		\
	$(LOBJ)/pucopyL.o	\
	$(LOBJ)/putcharL.o	\
	$(LOBJ)/putqL.o		\
	$(LOBJ)/putubdL.o	\
	$(LOBJ)/putuwdL.o	\
	$(LOBJ)/rucopyL.o	\
	$(LOBJ)/s5_to_sgL.o	\
	$(LOBJ)/s5_to_tcL.o	\
	$(LOBJ)/sallocL.o	\
	$(LOBJ)/sclearL.o	\
	$(LOBJ)/sendsigL.o	\
	$(LOBJ)/setivecL.o	\
	$(LOBJ)/sfreeL.o	\
	$(LOBJ)/sfbyteL.o	\
	$(LOBJ)/sfwordL.o	\
	$(LOBJ)/sfmemL.o	\
	$(LOBJ)/sg_to_s5L.o	\
	$(LOBJ)/sleepL.o	\
	$(LOBJ)/slrcopyL.o	\
	$(LOBJ)/sphiL.o		\
	$(LOBJ)/splL.o		\
	$(LOBJ)/sploL.o		\
	$(LOBJ)/superL.o	\
	$(LOBJ)/swapioL.o	\
	$(LOBJ)/tc_to_s5L.o	\
	$(LOBJ)/timeoutL.o	\
	$(LOBJ)/ttcloseL.o	\
	$(LOBJ)/tthupL.o	\
	$(LOBJ)/ttflushL.o	\
	$(LOBJ)/ttinL.o		\
	$(LOBJ)/ttioctlL.o	\
	$(LOBJ)/ttopenL.o	\
	$(LOBJ)/ttoutL.o	\
	$(LOBJ)/ttpollL.o	\
	$(LOBJ)/ttreadL.o	\
	$(LOBJ)/ttsetgrpL.o	\
	$(LOBJ)/ttsignalL.o	\
	$(LOBJ)/ttstartL.o	\
	$(LOBJ)/ttwriteL.o	\
	$(LOBJ)/uexitL.o	\
	$(LOBJ)/ufcopyL.o	\
	$(LOBJ)/ukcopyL.o	\
	$(LOBJ)/unlockL.o	\
	$(LOBJ)/upcopyL.o	\
	$(LOBJ)/urcopyL.o	\
	$(LOBJ)/vprintL.o	\
	$(LOBJ)/vrelseL.o	\
	$(LOBJ)/vremapL.o	\
	$(LOBJ)/vtopL.o		\
	$(LOBJ)/vxdivL.o	\
	$(LOBJ)/vxmulL.o	\
	$(LOBJ)/vxremL.o	\
	$(LOBJ)/waitqL.o	\
	$(LOBJ)/wakeupL.o	\

$(USRSYS)/lib/ldlib.a:	mkstub.m4 $(LIBOBJ1) $(LIBOBJ2)
	rm -f  $@
	ar rc  $@ $(LIBOBJ1)
	ar rc  $@ $(LIBOBJ2)
	ranlib $@

# Here is mkstub.m4:
#define(sym, substr(basename, -2, ))dnl
#	.globl	sym`_'
#sym`_':	mov	ax,`$K'sym`_'
#	.byte	0x9A
#	.word	xcalled
#	.word	0x0060
#	ret

MKSTUB=	echo "define(basename, `basename $*`)dnl" | m4 - mkstub.m4 > $*.s ;\
	as -gxo $@ $*.s; rm $*.s

$(LOBJ)/absL.o:
	$(MKSTUB)

$(LOBJ)/allocL.o:
	$(MKSTUB)

$(LOBJ)/bclaimL.o:
	$(MKSTUB)

$(LOBJ)/bdoneL.o:
	$(MKSTUB)

$(LOBJ)/blkmvL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/bootL.o:
	$(MKSTUB)

$(LOBJ)/breadL.o:
	$(MKSTUB)

$(LOBJ)/breleaseL.o:
	$(MKSTUB)

$(LOBJ)/clockedfL.o:	clockedf.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LOBJ)/clrivecL.o:
	$(MKSTUB)

$(LOBJ)/clrqL.o:
	$(MKSTUB)

$(LOBJ)/cs_selfL.o:	cs_self.s
	as -gxo $@ $<

$(LOBJ)/dblockL.o:
	$(MKSTUB)

$(LOBJ)/dcloseL.o:
	$(MKSTUB)

$(LOBJ)/deferL.o:	defer.s
	as -gxo $@ $<

$(LOBJ)/devmsgL.o:
	$(MKSTUB)

$(LOBJ)/dmagoL.o:
	$(MKSTUB)

$(LOBJ)/dmalockL.o:	dmalock.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LOBJ)/dmaoffL.o:
	$(MKSTUB)

$(LOBJ)/dmaonL.o:
	$(MKSTUB)

$(LOBJ)/dmareqL.o:
	$(MKSTUB)

$(LOBJ)/dopenL.o:
	$(MKSTUB)

$(LOBJ)/drvmapL.o:
	$(MKSTUB)

$(LOBJ)/dwriteL.o:
	$(MKSTUB)

$(LOBJ)/fclearL.o:
	$(MKSTUB)

$(LOBJ)/fdiskL.o:
	$(MKSTUB)

$(LOBJ)/ffbyteL.o:	ffbyte.s
	as -gxo $@ $<

$(LOBJ)/ffwordL.o:	ffword.s
	as -gxo $@ $<

$(LOBJ)/ffmemL.o:	ffmem.s
	as -gxo $@ $<

$(LOBJ)/fkcopyL.o:
	$(MKSTUB)

$(LOBJ)/fpxcopyL.o:
	$(MKSTUB)

$(LOBJ)/freeL.o:
	$(MKSTUB)

$(LOBJ)/fucopyL.o:
	$(MKSTUB)

$(LOBJ)/getcsL.o:	getcs.s
	as -gxo $@ $<

$(LOBJ)/getqL.o:
	$(MKSTUB)

$(LOBJ)/getubdL.o:
	$(MKSTUB)

$(LOBJ)/getuwdL.o:
	$(MKSTUB)

$(LOBJ)/inbL.o:		inb.s
	as -gxo $@ $<

$(LOBJ)/int11L.o:
	$(MKSTUB)

$(LOBJ)/iogetcL.o:
	$(MKSTUB)

$(LOBJ)/iomapvpL.o:
	$(MKSTUB)

$(LOBJ)/ioputcL.o:
	$(MKSTUB)

$(LOBJ)/ioreadL.o:
	$(MKSTUB)

$(LOBJ)/ioreqL.o:
	$(MKSTUB)

$(LOBJ)/iowriteL.o:
	$(MKSTUB)

$(LOBJ)/ipcaccessL.o:
	$(MKSTUB)

$(LOBJ)/kcallL.o:	kcall.s
	as -gxo $@ $<

$(LOBJ)/kclearL.o:
	$(MKSTUB)

$(LOBJ)/kfcopyL.o:
	$(MKSTUB)

$(LOBJ)/kpcopyL.o:
	$(MKSTUB)

$(LOBJ)/kucopyL.o:
	$(MKSTUB)

$(LOBJ)/lockL.o:
	$(MKSTUB)

$(LOBJ)/lxdivL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/lxmulL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/lxremL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/lxsgnL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/memsetL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/memtestL.o:
	$(MKSTUB)

$(LOBJ)/nmidisableL.o:
	$(MKSTUB)

$(LOBJ)/nmienableL.o:
	$(MKSTUB)

$(LOBJ)/nondsigL.o:
	$(MKSTUB)

$(LOBJ)/nonedevL.o:	nonedev.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LOBJ)/nulldevL.o:	nulldev.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LOBJ)/outbL.o:		outb.s
	as -gxo $@ $<

$(LOBJ)/panicL.o:
	$(MKSTUB)

$(LOBJ)/pclearL.o:
	$(MKSTUB)

$(LOBJ)/plrcopyL.o:
	$(MKSTUB)

$(LOBJ)/pkcopyL.o:
	$(MKSTUB)

$(LOBJ)/pollopenL.o:
	$(MKSTUB)

$(LOBJ)/pollwakeL.o:
	$(MKSTUB)

$(LOBJ)/printfL.o:
	$(MKSTUB)

$(LOBJ)/prlcopyL.o:
	$(MKSTUB)

$(LOBJ)/ptovL.o:
	$(MKSTUB)

$(LOBJ)/pucopyL.o:
	$(MKSTUB)

$(LOBJ)/putcharL.o:
	$(MKSTUB)

$(LOBJ)/putqL.o:
	$(MKSTUB)

$(LOBJ)/putubdL.o:
	$(MKSTUB)

$(LOBJ)/putuwdL.o:
	$(MKSTUB)

$(LOBJ)/rucopyL.o:
	$(MKSTUB)

$(LOBJ)/s5_to_sgL.o:
	$(MKSTUB)

$(LOBJ)/s5_to_tcL.o:
	$(MKSTUB)

$(LOBJ)/sallocL.o:
	$(MKSTUB)

$(LOBJ)/sclearL.o:
	$(MKSTUB)

$(LOBJ)/sendsigL.o:
	$(MKSTUB)

$(LOBJ)/setivecL.o:	setivec.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LOBJ)/sfreeL.o:
	$(MKSTUB)

$(LOBJ)/sfbyteL.o:	sfbyte.s
	as -gxo $@ $<

$(LOBJ)/sfwordL.o:	sfword.s
	as -gxo $@ $<

$(LOBJ)/sfmemL.o:	sfmem.s
	as -gxo $@ $<

$(LOBJ)/sg_to_s5L.o:
	$(MKSTUB)

$(LOBJ)/sleepL.o:
	$(MKSTUB)

$(LOBJ)/slrcopyL.o:
	$(MKSTUB)

$(LOBJ)/sphiL.o:	sphi.s
	as -gxo $@ $<

$(LOBJ)/splL.o:	spl.s
	as -gxo $@ $<

$(LOBJ)/sploL.o:	splo.s
	as -gxo $@ $<

$(LOBJ)/superL.o:
	$(MKSTUB)

$(LOBJ)/swapioL.o:
	$(MKSTUB)

$(LOBJ)/tc_to_s5L.o:
	$(MKSTUB)

$(LOBJ)/timeoutL.o:	timeout.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(LOBJ)/ttcloseL.o:
	$(MKSTUB)

$(LOBJ)/ttflushL.o:
	$(MKSTUB)

$(LOBJ)/tthupL.o:
	$(MKSTUB)

$(LOBJ)/ttinL.o:
	$(MKSTUB)

$(LOBJ)/ttioctlL.o:
	$(MKSTUB)

$(LOBJ)/ttopenL.o:
	$(MKSTUB)

$(LOBJ)/ttoutL.o:
	$(MKSTUB)

$(LOBJ)/ttpollL.o:
	$(MKSTUB)

$(LOBJ)/ttreadL.o:
	$(MKSTUB)

$(LOBJ)/ttsetgrpL.o:
	$(MKSTUB)

$(LOBJ)/ttsignalL.o:
	$(MKSTUB)

$(LOBJ)/ttstartL.o:
	$(MKSTUB)

$(LOBJ)/ttwriteL.o:
	$(MKSTUB)

$(LOBJ)/uexitL.o:
	$(MKSTUB)

$(LOBJ)/ufcopyL.o:
	$(MKSTUB)

$(LOBJ)/ukcopyL.o:
	$(MKSTUB)

$(LOBJ)/unlockL.o:
	$(MKSTUB)

$(LOBJ)/upcopyL.o:
	$(MKSTUB)

$(LOBJ)/urcopyL.o:
	$(MKSTUB)

$(LOBJ)/vprintL.o:
	$(MKSTUB)

$(LOBJ)/vrelseL.o:
	$(MKSTUB)

$(LOBJ)/vremapL.o:
	$(MKSTUB)

$(LOBJ)/vtopL.o:
	$(MKSTUB)

$(LOBJ)/vxdivL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/vxmulL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/vxremL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/waitqL.o:
	$(MKSTUB)

$(LOBJ)/wakeupL.o:
	$(MKSTUB)
0707070064030103021004440000030000030000011777770507310742100004400000001545/newbits/kernel/USRSRC/ldrv/blkmv.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:25	src
/ Initial revision
/ 
/
////////

	.globl	blkmv

blkmv:	push	si
	push	di
	push	bp
	mov	bp, sp

	mov	di, 8(bp)
	mov	si, 10(bp)
	mov	cx, 12(bp)
	cld
	rep
	movsb

	mov	ax, 8(bp)
	mov	sp, bp
	pop	bp
	pop	di
	pop	si
	ret
0707070064030103011006440000030000030000011777770507310742100004700000003747/newbits/kernel/USRSRC/ldrv/clockedf.c/* clockedf.c - support routines for alternate clock rate
              - this is the FAR version of clocked.c for loadable drivers

  altclk_in(hz, fn) - install routine with specified rate
                          "hz" should be a multiple of system rate of 100 Hz

  altclk_out()      - uninstall alternate clock routine and restore system rate
			return old value of "altclk"

  altclk_rate(hz)   - set clock interrupt rate
			new rate must be an even multiple of system rate "HZ"
			return 0 if completed ok, -1 otherwise

  History:
    90/08/08 hws	initial version, works with hs.c modified for com[1-4]
    90/08/14 hws	make it more like a Unix system call
    90/09/12 hws	add far version
*/

#include	<sys/coherent.h>	/* altclk */
#include	<sys/const.h>	/* HZ */

#define	PIT	0x40	/* 8253 port */
#define	TMR0_M3	0x36	/* timer 0, mode 3 */
#if 0
/* nominal IBM rate is 1.1900 MHz */
#define	SYS_HZ	1190000L	/* rate of input clock to timer 0 */
#else
/* current kernel rate is 1.1932 MHz */
#define	SYS_HZ	1193200L	/* rate of input clock to timer 0 */
#endif

typedef int (*PFI)();	/* pointer to function returning int */

extern saddr_t ucs;

static int altclk_rate(hz)
unsigned int hz;
{
  int s;	/* to save CPU irpt flag */
  unsigned int interval;	/* period for hz, in units of 1.19 MHz ticks */
  int ret;

  if (hz >= HZ && hz % HZ == 0) {	/* can't go slower than HZ! */
    interval = SYS_HZ/hz;
    s = sphi();	/* disable irpts */
    outb(PIT+3, TMR0_M3);
    outb(PIT, interval & 0xff);
    outb(PIT, interval >> 8);	/* unsigned shift */
    spl(s);	/* restore previous irpt state */
    ret = 0;
  }
  else {
    ret = -1;
  }
  return ret;
}

int altclk_in(hz, fn)
int hz;
PFI fn;
{
  int ret;
  int s;

  if ((ret = altclk_rate(hz)) == 0) {
    s = sphi();
    altclk = fn;
    altsel = cs_sel();
    spl(s);
  }
  return ret;
}

PFI altclk_out()
{
  PFI ret;
  int s;

  ret = altclk;
  if (ret) {
    altclk_rate(HZ);
    s = sphi();
    altclk = 0;
    altsel = 0;
    spl(s);
  }
  return ret;
}
0707070064030102771004440000030000030000011777770507310742200004600000000375/newbits/kernel/USRSRC/ldrv/cs_self.s////////
/
/ Get cs selector - return 0 if in kernel, CS if not in kernel.
/
/ This version is for loadable drivers.
/ There is a different version (cs_sel.s) for resident drivers.
/
/ int	cs_sel();
/
////////

	.globl	cs_sel_
cs_sel_:
	mov	ax, cs
	ret
0707070064030103001004440000030000030000011777770507310742200004400000002401/newbits/kernel/USRSRC/ldrv/defer.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/04/04  16:40:21	src
/ Initial revision
/ 
/
////////

////////
/
/ void
/ defer( f, a )		- defer local function from loadable driver.
/ void (*f)();
/ int a;
/
/	Input:	f = pointer to function to be deferred.
/		a = argument to be passed to function.
/
/	Action:	Schedule local function 'f' to be invoked with argument 'a'
/		at next transition from kernel to user mode.
/
/	Return:	None.
/
////////

	.globl	defer_

defer_:	push	bp			/ defer( f, a )
	mov	bp, sp			/ void (*f)();
	push	6(bp)			/ int a;
	push	cs			/ {
	push	4(bp)			/	kcall( Kldefer, f, cs, a );
	mov	ax, $Kldefer		/
	push	ax			/
	call	kcall_			/
	mov	sp, bp			/
	pop	bp			/ }
	ret
0707070064030060261004440000030000030000011777770507310742300004600000004374/newbits/kernel/USRSRC/ldrv/dmalock.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, Ltd, and is  confidential information.   It is provided
 *	under a license agreement,  and may be copied or disclosed  only
 *	under  the  terms  of  that  agreement.    Any  reproduction  or
 *	disclosure  of  this   material   without  the  express  written
 *	authorization of INETCO Systems, Ltd. or persuant to the license
 *	agreement is unlawful.
 *
 *	Copyright (c) 1989
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 *
 * $Description: $
 *	Routines to lock/unlock the DMA controller chip from a loadable driver.
 *
 * $Author: root $
 *
 * $Creation: June 29, 1989 $
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	89/06/30  16:29:52 	src
 * Initial revision
 * 
 */

#include <sys/coherent.h>

typedef void (* vfp_t)();		/* Void function pointer type.	     */

/*
 * External functions.
 */
extern void Kdmalock();
extern void Kdmaunlock();
extern void Kldtimcall();
extern saddr_t getcs();

/*
 * int
 * dmalock( tp, fun, arg )
 * TIM * tp;
 * vfp_t fun;
 * int	 arg;
 *
 *	Inputs:	tp  = Deferred function structure pointer.
 *		fun = Function to call if request is deferred.
 *		arg = Argument to pass to function.
 *
 *	Action:	Calls kernel dmalock() routine.
 *
 *	Return:	0 = Lock granted or -1 = Lock deferred.
 *
 *	Notes:	DMA controller locking was introduced to cure a bug on the
 *		NCR DMA controller, where overlapped DMA caused problems.
 *		No action is taken if DMA locking is disabled.
 */

int
dmalock( tp, fun, arg )
register TIM  * tp;
vfp_t		fun;
int		arg;
{
	/*
	 * Define loadable driver interface.
	 * Kldtimcall will be invoked when a deferred function is executed.
	 * It will in turn invoke FP_SEL(tp->t_ldrv):4 (the calling drivers
	 * function call entry point), passing FP_OFF(tp->t_ldrv) (the function
	 * to call) in AX.
	 */
	FP_SEL(tp->t_ldrv) = getcs();
	FP_OFF(tp->t_ldrv) = fun;
	return( kcall( Kdmalock, tp, Kldtimcall, arg ) );
}

/*
 * void
 * dmaunlock( tp )
 * TIM * tp;
 *
 *	Inputs:	tp = Deferred function structure pointer.
 *
 *	Action:	Calls the kernel dmaunlock().
 */

void
dmaunlock( tp )
register TIM * tp;
{
	kcall( Kdmaunlock, tp );
}

0707070064030060251004440000030000030000011777770507310742300004500000001751/newbits/kernel/USRSRC/ldrv/ffbyte.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:28	src
/ Initial revision
/ 
/
////////

////////
/
/ ffbyte( fp )		-- fetch far byte
/ int far * fp;
/
////////

	.globl	ffbyte_

ffbyte_:push	es		/ ffbyte( fp )
	push	di		/ register char far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	sub	ax, ax		/
	movb	al, es:(di)	/	return( *fp );
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
0707070064030060241004440000030000030000011777770507310742300004400000002663/newbits/kernel/USRSRC/ldrv/ffmem.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:31	src
/ Initial revision
/ 
/
////////

////////
/
/ void
/ ffmem( fp, m, n )	-- fetch far memory
/ faddr_t fp;
/ char * m;
/ int n;
/
/	Input:	fp = far pointer [32 bit selector:offset] to source
/		m  = destination
/		n  = number of bytes to transfer.
/
/	Action:	Transfer 'n' bytes from far address 'fp' to offset 'm'
/		in the current data space.
/
/	Return:	None.
/
////////

	.globl	ffmem_

ffmem_:	push	si		/ void
	push	di		/ ffmem( fp, m, n )
	push	bp		/
	mov	bp, sp		/ register faddr_t fp;		/* DS:SI */
	push	ds		/ register char * m;		/* DI */
	lds	si, 8(bp)	/ register int n;		/* CX */
	mov	di, 12(bp)	/
	mov	cx, 14(bp)	/ {
				/
	cld			/
	clc			/	for ( ; n != 0; --n )
	rcr	cx, $1		/
	rep			/		*m++ = *fp++;
	movsw			/
	rcl	cx, $1		/
	rep			/
	movsb			/
				/
	pop	ds		/ }
	pop	bp
	pop	di
	pop	si
	ret
0707070064030060231004440000030000030000011777770507310742400004500000001725/newbits/kernel/USRSRC/ldrv/ffword.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:33	src
/ Initial revision
/ 
/
////////

////////
/
/ ffword( fp )		-- fetch far word
/ int far * fp;
/
////////

	.globl	ffword_

ffword_:push	es		/ ffword( fp )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	mov	ax, es:(di)	/	return *fp;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
0707070064030060221004440000030000030000011777770507310742400004400000001601/newbits/kernel/USRSRC/ldrv/getcs.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:36	src
/ Initial revision
/ 
/ 87/12/08	Allan Cornish	/usr/src/sys/ldrv/getcs.s
/ Getcs() function obtains current code segment.
/
////////

////////
/
/ Get code selector.
/
////////

	.globl	getcs_

getcs_:	mov	ax, cs			/ Return code selector.
	ret
0707070064030060211004440000030000030000011777770507310742400004200000001470/newbits/kernel/USRSRC/ldrv/inb.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:39	src
/ Initial revision
/ 
/
////////

////////
/
/ Basic port level I/O.
/
/ int	inb(port);
/
////////

	.globl	inb_

inb_:	mov	bx, sp
	mov	dx, 2(bx)
	sub	ax, ax
	inb	al, dx
	ret
0707070064030060201004440000030000030000011777770507310742400004400000002522/newbits/kernel/USRSRC/ldrv/kcall.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:41	src
/ Initial revision
/ 
/
////////

////////
/
/ kcall( func, arg, ... )
/
/	Input:	func = kernel function to be invoked.
/		arg  = optional argument(s) to be passed to kernel function.
/
/	Action:	Invoke kernel function.
/
////////
	.globl	kcall_

kcall_:
	pop	bx		/ Convert stack from (retIP dstIP arg ...)
	pop	ax		/		  to (      retIP arg ...)
	push	bx		/ Leaving dstIP in AX register.
				/
	.byte 0x9A		/ Request kernel to perform far call.
	.word xcalled		/
	.word 0x0060		/
				/
	pop	bx		/ Convert stack from (      retIP arg ...)
	push	bx		/		  to (retIP retIP arg ...)
	push	bx		/ This allows caller to cleanup normally.
				/ NOTE: DO NOT MODIFY DX:AX RETURN VALUE.
				/
	ret			/ Return to caller.
0707070064030060171006440000030000030000011777770507310742500004500000002043/newbits/kernel/USRSRC/ldrv/ldconfig: '$Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $'
:
:	configure a loadable driver
:
: usage: ldconfig [swap] [DRV ...]
:
BUILD=0
DEV=/tmp/dev
PATCH=""
UNDEF=""
LDMOD=""
PASS1=""

for ARG in $*
do
	case "${ARG}" in
	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "$ARG" in

	swap)
		/bin/echo "ldrv/swap: "
		ld -r -o ldrv/swap lib/ldrts0.o lib/ldswap.o lib/ldlib.a
		LDMOD=""
		;;

	*\=*)
		LDMOD="${LDMOD} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		/bin/echo "ldrv/${FILE}: "
		if /bin/test -r confdrv/${FILE}
		then
			UNDEF=""
			. confdrv/${FILE}
			/bin/ld -r -o ldrv/${FILE} lib/ldrts0.o \
				lib/ldmain.o ${UNDEF} \
				lib/ldlib.a || exit 1
			case "${LDMOD}" in
			"")	;;
			*)	/conf/patch ldrv/${FILE} ${LDMOD}
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		LDMOD=""
		;;
	esac
done
0707070064030104731004440000030000030000011777770507310742500004500000012013/newbits/kernel/USRSRC/ldrv/ldmain.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Loadable Driver - Process Handler.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	89/03/31  16:19:36 	src
 * Bug:	Did not cancel either attached timed functions or deferred functions
 * 	during an unload.  As a result, if a driver did not explicitly do
 * 	this, then unloading the driver could cause a system panic.
 * Fix:	Now cancels the functions. (ABC)
 * 
 * Revision 1.1	88/03/24  08:30:44 	src
 * Initial revision
 * 
 * 87/12/03	Allan Cornish		/usr/src/sys/ldrv/ldmain.c
 * Initial version.
 */
#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/con.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>

extern CON con;

extern	saddr_t	ldrvsel[NDRV];
extern	saddr_t ldrvics[16];
extern	void  (*ldrvipc[16])();
extern	CON *	ldrvcon[NDRV];
extern	CON	ldrvpsy;
extern	saddr_t	ucs;

/*
 * Local variable - keeps track of the number of opens.
 * The loadable driver can't terminate until after the last close.
 * Openf is the loadable driver open routine.
 * Closef points to the driver's close routine.
 * The configuration table entries are taken over
 */
static	int	nopen = 0;
static	void	(*openf)() = NULL;
static	void	(*closef)() = NULL;

main()
{
	register int mind = con.c_mind;
	register int level;
	extern	void myopen();
	extern	void myclose();
	extern	void Kdefend();

	/*
	 * Loadable devices must identify the desired major device.
	 */
	if ( (mind == 0) || (mind >= drvn) ) {
		printf("ldrv:%d: bad dev\n", mind );
		uexit( 1 );
	}

	/*
	 * Loadable devices must use a unique [not in use] major device.
	 */
	if ( (drvl[mind].d_conp != NULL) || (ldrvcon[mind] != NULL) ) {
		printf("ldrv:%d: dev bsy\n", mind );
		uexit( 0 );
	}

	/*
	 * Intercept driver open/close requests.
	 * This allows the driver process to terminate after the last close,
	 *	if one or more signals have been received.
	 */
	openf		= con.c_open;
	closef		= con.c_close;
	con.c_open	= myopen;
	con.c_close	= myclose;

	/*
	 * Install the loadable driver pseudo device interface.
	 * The O/S will call the pseudo-device, which will call us.
	 * Record our driver configuration and code segment.
	 */
	drvl[mind].d_conp = &ldrvpsy;
	ldrvcon[mind] = &con;
	ldrvsel[mind] = ucs;

	/*
	 * Load the device driver.
	 */
	if ( con.c_load != NULL )
		(*con.c_load)( makedev(mind,0) );

	/*
	 * Sleep until a kill signal has arrived, and no device is open.
	 */
	do {
		sleep( (char *)&nopen, CVSWAP, IVSWAP, SVSWAP );

	} while ( ((SELF->p_ssig & 0x0100) == 0) || (nopen != 0) );

	/*
	 * Unload the device driver.
	 */
	if ( con.c_uload != NULL )
		(*con.c_uload)( makedev(mind,0) );

	/*
	 * Erase references to our kernel process.
	 */
	drvl[mind].d_conp = NULL;
	ldrvcon[mind] = NULL;
	ldrvsel[mind] = 0;

	/*
	 * Scan looking for attached interrupts.
	 * NOTE: This is to prevent dangling interrupt vectors.
	 */
	for ( level = 0; level < 16; level++ ) {

		/*
		 * Interrupt is not attached to us.
		 */
		if ( ldrvics[level] != ucs )
			continue;

		/*
		 * Disable interrupt.
		 */
		clrivec( level );

		/*
		 * Release loadable driver interrupt.
		 */
		ldrvics[level] = 0;
		ldrvipc[level] = NULL;
	}

	/*
	 * Service deferred functions BEFORE scanning for timed functions.
	 * This is in case a deferred function schedules a timed function.
	 */
	kcall( Kdefend );

	/*
	 * Scan for attached timed functions which have to be terminated.
	 */
	for ( level = 0; level < nel(timq); level++ ) {
		register TIM * tp;

		/*
		 * Access a specific timing queue.
		 */
		for ( tp = timq[level]; tp != NULL; ) {

			/*
			 * Timed function is in our loadable driver.
			 * Restart search at start of timing queue.
			 */
			if ( FP_SEL(tp->t_ldrv) == getcs() ) {
			  	timeout( tp, 0, NULL, 0 );
				tp = timq[ level ];
			}

			/*
			 * Not one of our timed functions.
			 * Advance to next function in queue.
			 */
			else
				tp = tp->t_next;
		}
	}

	/*
	 * Terminate with extreme prejudice.
	 */
	uexit( 0 );
}

static void
myopen( dev, mode )
dev_t dev;
int mode;
{
	/*
	 * Invoke the true open routine for the loadable driver.
	 */
	if ( openf != NULL )
		(*openf)(dev, mode );

	/*
	 * Adjust reference count if open succeeded.
	 */
	if ( u.u_error == 0 )
		nopen++;
}

static void
myclose( dev )
dev_t dev;
{
	/*
	 * Invoke the true close routine for the loadable driver.
	 */
	if ( closef != NULL )
		(*closef)( dev );

	/*
	 * Wakeup driver process after last close.
	 * This allows it to terminate if appropriate.
	 */
	if ( --nopen == 0 )
		wakeup( (char*) &nopen );
}
0707070064030060151004440000030000030000011777770507310742600004500000002766/newbits/kernel/USRSRC/ldrv/ldrts0.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/ 
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/ 
/	Copyright (c) 1987
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/

////////
/
/ Loadable Driver Run Time Startup
/
/ Notes:	This function MUST be at offset 0 in driver code segment.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:47	src
/ Initial revision
/ 
/
////////

	.globl	main_
	call	main_
	xret

////////
/
/	Invocation mechanism for local driver functions by kernel code.
/
/	Input:	AX	= pointer to local function to be invoked.
/		4(BP)	= 1st parameter to be passed to local function.
/		6(BP)	= 2nd parameter to be passed to local function.
/		8(BP)	= 3rd parameter to be passed to local function.
/
/	Action:	Invoke local function whose address is given in register AX,
/		passing parameters at offset 4,6,8 relative to register BP.
/		Perform a far return to operating system.
/
/	Notes:	Parameter passing convention specified by kernel.
/		This function MUST be at offset 4 in driver code segment.
/
////////

	push	8(bp)
	push	6(bp)
	push	4(bp)
	icall	ax
	add	sp, $6
	xret
0707070064030060141004440000030000030000011777770507310742700004500000027440/newbits/kernel/USRSRC/ldrv/ldswap.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Swapper.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:30:50	src
 * Initial revision
 * 
 * 87/11/05	Allan Cornish		/usr/src/sys/ldrv/ldswap.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/10/26	Allan Cornish		/usr/src/sys/ldrv/ldswap.c
 * Modified to support loadable drivers - temporary modification.
 * Now requires SIGKILL signal in order to terminate.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/ker/swap.c
 * Swap() now waits for all processes to be swapped in before exit on signal.
 */
#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/uproc.h>
#include <sys/buf.h>

/*
 * Functions.
 */
SEG	*xmalloc();
SEG	*xdalloc();
void	Kwakeup();
void	Ktimeout();

main()
{
	register SEG *sp;
	register PROC *pp1;
	register PROC *pp2;
	register PROC *pp3;
	register unsigned s;
	register unsigned n;
	register unsigned t;
	register unsigned v;
	register unsigned m;
	register int i;
	static unsigned ltimer;

	if (sexflag != 0)
		uexit(1);
	sexflag++;

	while (1) {
		lock( pnxgate );
		t = (utimer - ltimer) / NSUTICK;
		v = t * SVCLOCK;
		ltimer += t * NSUTICK;

		/*
		 * Search for process to swap into memory.
		 */
		pp2 = NULL;
		m   = 0;
		s   = 0;
		for (pp1 = procq.p_nback; pp1 != &procq; pp1 = pp1->p_nback) {

			/*
			 * Process resides in memory.
			 */
			if ( (pp1->p_flags & PFCORE) != 0 ) {
				pp1->p_sval >>= t;
				pp1->p_ival  -= t;
				if (pp1->p_ival < -30000)
					pp1->p_ival = -30000;
				continue;
			}

			/*
			 * Update swap value - high values swapped in first.
			 */
			addu( pp1->p_sval, v );
			s = 1;

			/*
			 * Process is not runnable.
			 */
			if ( pp1->p_state != PSRUN )
				continue;

			/*
			 * Calculate disk usage in Kbytes.
			 */
			s = 0;
			for ( i = 0; i < NUSEG+1; i++ )
				if ( (sp = pp1->p_segp[i]) != NULL )
					if ( (sp->s_flags & SFCORE) == 0 )
						s += sp->s_size / 1024;
			if ( s == 0 )
				s = 1;

			/*
			 * Compute importance:
			 *
			 *	swap value + response value
			 *	---------------------------
			 *	  Kbytes to be swapped in
			 */
			n = (pp1->p_sval + pp1->p_rval) / s;

			/*
			 * More important.
			 */
			if ( n > m ) {
				m = n;
				pp2 = pp1;
			}
		}
		unlock( pnxgate );

		/*
		 * No runnable processes swapped out.
		 */
		if ( pp2 == NULL ) {
			/*
			 * No processes swapped out, and KILL signal received.
			 */
			if ( (s == 0) && (SELF->p_ssig & 0x0100) )
				break;
			goto con;
		}

#ifndef	NOMONITOR
		if (swmflag)
			printf("Swapin(%p, %d)\n", pp2, pp2->p_pid);
#endif
	xxx:
		/*
		 * Try to swap process into memory.
		 */
		while ( (testcore(pp2) == 0) || (proccore(pp2) != 0) ) {

			/*
			 * Swap process out.
			 */
			procdisk(pp2);
			i   = 32767;
			pp3 = NULL;

			/*
			 * Search for process to swap out.
			 */
			lock( pnxgate );
			for (pp1=procq.p_nforw; pp1!=&procq; pp1=pp1->p_nforw){

				if ( pp1->p_flags & (PFSWIO|PFLOCK|PFKERN) )
					continue;

				/*
				 * Process is not totally memory resident.
				 */
				if ( (pp1->p_flags&PFCORE) == 0 ) {
					/*
					 * Swap segments out to disk.
					 */
					if ( procdisk(pp1) != 0 ) {
						unlock( pnxgate );
						goto xxx;
					}
					continue;
				}

				/*
				 * Process too important to swap out.
				 */
				if ((pp1->p_ival > -64) && (pp1->p_sval != 0))
					continue;

				/*
				 * Less important.
				 */
				if ( pp1->p_ival < i ) {
					i = pp1->p_ival;
					pp3 = pp1;
				}
			}
			unlock( pnxgate );

			/*
			 * No processes to swap out.
			 */
			if ( pp3 == NULL ) {
#ifndef NOMONITOR
				if (swmflag)
					printf("No one to swap out\n");
#endif
				break;
			}

			/*
			 * Process is too important to swap out.
			 */
			if ( i > 0 ) {
#ifndef NOMONITOR
				if (swmflag)
					printf("Dispatch(%p, %d)\n",
						pp3, pp3->p_pid);
#endif
				pp3->p_flags |= PFDISP;
				break;
			}
#ifndef NOMONITOR
			if (swmflag)
				printf("Swapout(%p, %d)\n", pp3, pp3->p_pid);
#endif
			/*
			 * Swap process out to disk.
			 */
			procdisk( pp3 );
		}

#ifndef NOMONITOR
		if (swmflag)
			printf("Swapdone\n");
#endif
	con:
		kcall( Ktimeout, &stimer, NSRTICK, Kwakeup, (char *)&stimer );
		sleep( (char *)&stimer, CVSWAP, IVSWAP, SVSWAP );
	}
	sexflag--;
	uexit( 1 );
}

/*
 * See if the given process may fit in core.
 */
testcore( pp )
register PROC *pp;
{
	register SEG *sp;
	register fsize_t s;
	register paddr_t s1;
	register paddr_t s2;
	register int i;

	/*
	 * Find largest segment in process.
	 */
	s = 0;
	for ( i = 0; i < NUSEG+1; i++ ) {

		if ( (sp = pp->p_segp[i]) == NULL )
			continue;

		/*
		 * Segment is memory resident.
		 */
		if ( (sp->s_flags & SFCORE) != 0 )
			continue;

		/*
		 * Largest segment so far.
		 */
		if ( sp->s_size > s )
			s = sp->s_size;
	}

	/*
	 * See if largest segment will fit in memory.
	 */
	s1 = corebot;
	sp = &segmq;
	do {
		/*
		 * Advance to next memory segment.
		 */
		sp = sp->s_forw;
		s2 = sp->s_paddr;

		/*
		 * It fits!
		 */
		if ( s2 - s1 >= s )
			return (1);

		/*
		 * Compute start of next hole.
		 */
		s1 = sp->s_paddr + sp->s_size;

	} while ( sp != &segmq );

	return( 0 );
}

/*
 * Swap all segments associated with a particular process into core.
 * The number of segments still swapped out is returned.
 */
proccore( pp )
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int n;
	register int f;

	f = pp->p_flags & PFSWAP;

	/*
	 * Try to swap in all user segments and the auxiliary segment.
	 */
	for ( n = 0, i = 0; i < NUSEG+1; i++ ) {

		if ( (sp = pp->p_segp[i]) == NULL )
			continue;

		/*
		 * Process was swapped out.
		 */
		if ( f != 0 )
			sp->s_lrefc++;

		/*
		 * Segment is disk resident - try to swap it in.
		 */
		if ( (sp->s_flags & SFCORE) == 0 )
			if ( segcore(sp) == 0 )
				n++;
	}

	/*
	 * No segments left on disk - mark process as being memory resident.
	 */
	if ( n == 0 )
		pp->p_flags |= PFCORE;

	/*
	 * Mark process as no longer being disk resident.
	 */
	pp->p_flags &= ~PFSWAP;

	return( n );
}

/*
 * Swap out all segments associated with a given process.
 */
procdisk( pp )
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int f;
	int n;

	f = pp->p_flags & PFSWAP;

	/*
	 * Mark process as no longer being memory resident BEFORE swapping.
	 */
	pp->p_flags &= ~PFCORE;

	/*
	 * Try to swap out all user segments and the auxiliary segment.
	 */
	for ( n = 0, i = 0; i < NUSEG+1; i++ ) {

		if ( (sp = pp->p_segp[i]) == NULL )
			continue;

		/*
		 * Process not already swapped out.
		 */
		if ( f == 0 )
			sp->s_lrefc--;

		/*
		 * Segment already swapped out.
		 */
		if ( (sp->s_flags & SFCORE) == 0 )
			continue;

		/*
		 * Segment no longer referenced by a memory-resident process.
		 */
		if ( (sp->s_lrefc == 0) && (segdisk(sp) != 0) )
			n++;
	}

	/*
	 * Mark process as being disk resident.
	 */
	pp->p_flags |= PFSWAP;

	return( n );
}

/*
 * Swap the given segment into core.
 * NOTE: Although swapped out, the segment may have a descriptor table entry,
 *	 and therefore have a valid s_faddr field.
 */
segcore( sp1 )
register SEG *sp1;
{
	register SEG *sp2;

	/*
	 * Lock segmentation.
	 */
	lock( seglink );

	/*
	 * Segment has been moved to memory while we waited to lock.
	 */
	if ( (sp1->s_flags & SFCORE) != 0 ) {
		unlock(seglink);
		return( 1 );
	}

	/*
	 * Allocate a memory segment sp2.
	 */
	if ((sp2 = xmalloc( sp1->s_size )) == NULL ) {
		unlock( seglink );
		return( 0 );
	}

	/*
	 * Copy the disk segment sp1 into the memory segment sp2.
	 */
	sp1->s_lrefc++;
	swapio(0, sp2->s_paddr, sp1->s_daddr, sp2->s_size );
	sp1->s_lrefc--;

	/*
	 * Remove segment sp1 from the disk queue.
	 */
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;

	/*
	 * Insert segment sp1 into memory queue replacing segment sp2.
	 */
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;

	/*
	 * Enable access to memory segment sp1.
	 */
	sp1->s_flags |= SFCORE;
	sp1->s_paddr = sp2->s_paddr;
	vremap( sp1 );

	/*
	 * Unlock segmentation.
	 */
	unlock( seglink );

	return( 1 );
}

/*
 * Swap the given segment out onto disk.
 */
segdisk( sp1 )
register SEG *sp1;
{
	register SEG *sp2;

	/*
	 * Lock segmentation.
	 */
	lock( seglink );

	/*
	 * Verify segment sp1 did not become busy while we waited to lock.
	 * IE: raw disk i/o, or shared code fork.
	 */
	if ( sp1->s_lrefc != 0 ) {
		unlock( seglink );
		return( 0 );
	}

	/*
	 * Segment has been moved to disk while we waited to lock.
	 */
	if ( (sp1->s_flags & SFCORE) == 0 ) {
		unlock(seglink);
		return( 1 );
	}

	/*
	 * Allocate a disk segment sp2.
	 */
	if ( (sp2 = xdalloc( sp1->s_size )) == NULL ) {
		unlock( seglink );
		return( 0 );
	}

	/*
	 * Disable access to memory segment sp1.
	 */
	sp1->s_flags &= ~SFCORE;
	sp1->s_daddr = sp2->s_daddr;
	vremap( sp1 );

	/*
	 * Copy the memory segment sp1 into the disk segment sp2.
	 */
	sp1->s_lrefc++;
	swapio( 1, sp1->s_paddr, sp2->s_daddr, sp1->s_size );
	sp1->s_lrefc--;

	/*
	 * Remove segment sp1 from the memory queue.
	 */
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;

	/*
	 * Insert segment sp1 into disk queue replacing segment sp2.
	 */
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;

	/*
	 * Unlock segmentation.
	 */
	unlock( seglink );

	return( 1 );
}

/*
 * Allocate a segment on disk that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `sdalloc' except that we can't run out of
 * alloc space to allocate the segment and we allocate in high regions.
 * NOTE: descriptor table entries are not released.
 */
SEG *
xdalloc( s )
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register daddr_t d;
	register daddr_t d1;
	register daddr_t d2;

	d  = s / BSIZE;
	d2 = swaptop;
	sp1 = &segdq;
	do {
		if ( (sp1 = sp1->s_back) != &segdq )
			d1 = sp1->s_daddr + (sp1->s_size / BSIZE);
		else
			d1 = swapbot;

		if ( d2 - d1 >= d ) {
			sp2 = &segswap;
			kclear( (char *)sp2, sizeof(SEG) );
			sp1->s_forw->s_back = sp2;
			sp2->s_forw  = sp1->s_forw;
			sp1->s_forw  = sp2;
			sp2->s_back  = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_daddr = d2 - d;
			return( sp2 );
		}

		d2 = sp1->s_daddr;

	} while ( sp1 != &segdq );

	return( NULL );
}

/*
 * Allocate a segment in memory that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `smalloc' except that we can't run out of
 * alloc space to allocate the segment.
 * NOTE: Do NOT remap virtual descriptor table entry.
 *	 This is a scratch entry, and the s_faddr field is not retained.
 */
SEG *
xmalloc( s )
register fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register paddr_t s1;
	register paddr_t s2;

	s1  = corebot;
	sp1 = &segmq;
	do {
		if ( (sp1 = sp1->s_forw) != &segmq )
			s2 = sp1->s_paddr;
		else
			s2 = coretop;

		if ( s2 - s1 >= s ) {
			sp2 = &segswap;
			kclear( (char *)sp2, sizeof(SEG) );
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_paddr = s1;
			return( sp2 );
		}

		s1 = sp1->s_paddr + sp1->s_size;

	} while ( sp1 != &segmq );

	return( NULL );
}
0707070064030060131004440000030000030000011777770507310743100004600000000513/newbits/kernel/USRSRC/ldrv/nonedev.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */

/*
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:30:54	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/uproc.h>
#include <errno.h>

/*
 * Non existant device.
 */
nonedev()
{
	u.u_error = ENXIO;
}
0707070064030060121004440000030000030000011777770507310743100004600000000352/newbits/kernel/USRSRC/ldrv/nulldev.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:30:57	src
 * Initial revision
 * 
 */

/*
 * Null device.
 */
nulldev()
{
}
0707070064030060111004440000030000030000011777770507310743100004300000001507/newbits/kernel/USRSRC/ldrv/outb.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:00	src
/ Initial revision
/ 
/
////////

////////
/
/ Basic port level I/O.
/
/ int	outb(port, data);
/
////////

	.globl	outb_

outb_:	mov	bx, sp
	mov	dx, 2(bx)
	mov	ax, 4(bx)
	outb	dx, al
	ret
0707070064030060101004440000030000030000011777770507310743200004600000004313/newbits/kernel/USRSRC/ldrv/setivec.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Loadable Driver - Enable/Disable Interrupts.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:31:02	src
 * Initial revision
 * 
 * 87/12/03	Allan Cornish		/usr/src/sys/ldrv/setivec.c
 * Initial version.
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/con.h>
#include <sys/uproc.h>

/*
 * Interrupt entry points [within kernel] for loadable drivers.
 */
extern void (*ldrvint[16])();

/*
 * Interrupt handlers [within driver] for loadable drivers.
 *	ldrvics[n]:	Interrupt handler code segment.
 *	ldrvipc[n]:	Interrupt handler program counter.
 */
extern saddr_t ldrvics[16];
extern void  (*ldrvipc[16])();

setivec( level, func )
int level;
void (*func)();
{
	extern void Ksetivec();
	extern saddr_t ucs;

	u.u_error = 0;
	level &= 15;

	/*
	 * Ensure interrupt is not already in use.
	 */
	if ( (ldrvics[level] != 0) || (ldrvipc[level] != NULL) ) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Record interrupt function BEFORE enabling interrupt.
	 */
	ldrvipc[level] = func;
	ldrvics[level] = ucs;

	/*
	 * Attempt to enable interrupt.
	 */
	kcall( Ksetivec, level, ldrvint[level] );

	/*
	 * Interrupt is in use by a resident driver.
	 */
	if ( u.u_error ) {
		ldrvipc[level] = NULL;
		ldrvics[level] = 0;
	}
}

clrivec( level )
register int level;
{
	extern void Kclrivec();
	extern saddr_t ucs;

	level &= 15;

	/*
	 * Ensure interrupt belongs to our process.
	 */
	if ( ldrvics[level] != ucs ) {
		u.u_error = EPERM;
		return;
	}

	/*
	 * Disable interrupt.
	 */
	kcall( Kclrivec, level );

	/*
	 * Erase interrupt function AFTER disabling interrupt.
	 */
	ldrvipc[level] = NULL;
	ldrvics[level] = 0;
}
0707070064030060071004440000030000030000011777770507310743200004500000002017/newbits/kernel/USRSRC/ldrv/sfbyte.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:05	src
/ Initial revision
/ 
/
////////

////////
/
/ sfbyte( fp, b )	-- set far byte
/ char far * fp;
/ char b;
/
////////

	.globl	sfbyte_

sfbyte_:push	es		/ sfbyte( fp, c )
	push	di		/ register char far * fp;	/* ES:DI */
	push	bp		/ register char c;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	movb	es:(di), al	/	*fp = c;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
0707070064030060061004440000030000030000011777770507310743300004400000002663/newbits/kernel/USRSRC/ldrv/sfmem.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:08	src
/ Initial revision
/ 
/
////////

////////
/
/ void
/ sfmem( fp, m, n )	-- set far memory
/ char far * fp;
/ char * m;
/ int n;
/
/	Input:	fp = far pointer [32 bit selector:offset] to destination
/		m  = source
/		n  = number of bytes to transfer.
/
/	Action:	Transfer 'n' bytes from offset 'm' in the current data space
/		to far address 'fp'.
/
/	Return:	None.
/
////////

	.globl	sfmem_

sfmem_:	push	si		/ void
	push	di		/ sfmem( fp, m, n )
	push	bp		/
	mov	bp, sp		/ register char * fp;		/* ES:DI */
	push	es		/ register char * m;		/* SI */
	les	di, 8(bp)	/ register int n;		/* CX */
	mov	si, 12(bp)	/
	mov	cx, 14(bp)	/ {
				/
	cld			/
	clc			/	for ( ; n != 0; --n )
	rcr	cx, $1		/
	rep			/		*fp++ = *m++;
	movsw			/
	rcl	cx, $1		/
	rep			/
	movsb			/
				/
	pop	es		/ }
	pop	bp
	pop	di
	pop	si
	ret
0707070064030060051004440000030000030000011777770507310743300004500000002012/newbits/kernel/USRSRC/ldrv/sfword.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:11	src
/ Initial revision
/ 
/
////////

////////
/
/ sfword( fp, w )	-- set far word
/ int far * fp;
/ int w;
/
////////

	.globl	sfword_

sfword_:push	es		/ sfword( fp, w )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ register int w;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	mov	es:(di), ax	/	*fp = w;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
0707070064030060041004440000030000030000011777770507310743400004300000001567/newbits/kernel/USRSRC/ldrv/sphi.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:13	src
/ Initial revision
/ 
/
////////

////////
/
/ Disable interrupts.  Previous value is returned.
/
////////

	.globl	sphi_

sphi_:
	pushf				/ Save flags
	pop	ax			/ Return current value
	cli				/ Disable interrupts
	ret				/ And return
0707070064030057111004440000030000030000011777770507310743400004200000001616/newbits/kernel/USRSRC/ldrv/spl.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:16	src
/ Initial revision
/ 
/
////////

////////
/
/ Change interrupt flag.  Previous value is returned.
/
////////
	.globl	spl_

spl_:
	pop	ax			/ ip
	pop	bx			/ psw
	push	bx
	push	bx			/ push psw, cs, ip for iret
	push	cs
	push	ax
	pushf				/ old psw
	pop	ax
	iret
0707070064030057051004440000030000030000011777770507310743400004300000001445/newbits/kernel/USRSRC/ldrv/splo.s/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:19	src
/ Initial revision
/ 
/
////////

////////
/
/ Enable interrupts.  Previous value is returned.
/
////////

	.globl	splo_

splo_:
	pushf
	pop	ax
	sti
	ret
0707070064030057041004440000030000030000011777770507310743400004600000003424/newbits/kernel/USRSRC/ldrv/timeout.c/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Loadable Driver - Timed functions.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:31:21	src
 * Initial revision
 * 
 * 87/12/08	Allan Cornish	/usr/src/sys/ldrv/timeout.c
 * Timed loadable driver functions now supported.
 */
#include <sys/coherent.h>

/*
 * External functions.
 */
extern void Ktimeout();
extern void Kldtimcall();
extern saddr_t getcs();

/*
 * Given a pointer to a timeout structure, `tp', call the function `f'
 * with integer argument `a' in `n' ticks of the clock. The list is
 * searched to see if the specified timeout structure is already in a
 * list, and it is removed if already there.
 * This module is specific to loadable drivers.
 */
timeout( tp, n, f, a )
register TIM * tp;
int n;
void (*f)();
int a;
{
	register int s;

	/*
	 * Cancel existing timer.
	 */
	if ( (f == NULL) || (n <= 0) ) {
		kcall( Ktimeout, tp, 0, NULL, 0 );
		return;
	}

	/*
	 * Define loadable driver interface.
	 * Kldtimcall will be invoked when timeout occurs.
	 * It will in turn invoke FP_SEL(tp->t_ldrv):4,
	 *	passing FP_OFF(tp->t_ldrv) in AX.
	 */
	s = sphi();
	FP_SEL(tp->t_ldrv) = getcs();
	FP_OFF(tp->t_ldrv) = f;
	kcall( Ktimeout, tp, n, Kldtimcall, a );
	spl(s);
}
0707070064030105330407550000030000030000011777770507310743500004000000000000/newbits/kernel/USRSRC/ldrv/RCS0707070064030131011004440000030000030000011777770507310743500005300000055035/newbits/kernel/USRSRC/ldrv/RCS/Makefile,vhead     1.6;
branch   ;
access   ;
symbols  ;
locks    bin:1.6;
comment  @@;


1.6
date     91.09.26.17.13.55;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.07.15.14.39.54;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.06.20.14.33.18;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.10.10.42.41;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.04.30.18.38.22;  author root;  state Exp;
branches ;
next     1.1;

1.1
date     91.04.30.18.37.18;  author root;  state Exp;
branches ;
next     ;


desc
@Runtime support for loadable drivers, including ldlib.a.
@


1.6
log
@update by hal to fix problem with ttyflush() and loadable drivers.
@
text
@# $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $(USRSRC)/ldrv/RCS/Makefile,v 1.2 91/04/30 18:38:22 root Exp $

# Loadable Drivers - Makefile
#

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

CC=exec /bin/cc
CFLAGS=

TARGETS=$(USRSYS)/lib/ldrts0.o	\
	$(USRSYS)/lib/ldmain.o	\
	$(USRSYS)/lib/ldswap.o	\
	$(USRSYS)/lib/ldlib.a

ld_support:	$(TARGETS)
	@@sync

$(USRSYS)/lib/ldrts0.o:	ldrts0.s
	as -xo $@@ $<

$(USRSYS)/lib/ldmain.o:	ldmain.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(USRSYS)/lib/ldswap.o:	ldswap.c
	$(CC) $(CFLAGS) -DNOMONITOR -c -o $@@ $<

# The following script extracts a module from a library.
X_LIB=	OBJFIL=`basename $@@ | sed 's/L//'` ;\
	ar x $< $$OBJFIL ;\
	mv $$OBJFIL $@@

# The following modules are supported in loadable drivers.
# NOTE: Most of them are interface stubs to kernel code.
#	Some of them are entirely driver resident.
LIBOBJ1=$(LOBJ)/absL.o		\
	$(LOBJ)/allocL.o	\
	$(LOBJ)/bclaimL.o	\
	$(LOBJ)/bdoneL.o	\
	$(LOBJ)/blkmvL.o	\
	$(LOBJ)/bootL.o		\
	$(LOBJ)/breadL.o	\
	$(LOBJ)/breleaseL.o	\
	$(LOBJ)/clockedfL.o	\
	$(LOBJ)/clrqL.o		\
	$(LOBJ)/cs_selfL.o	\
	$(LOBJ)/dblockL.o	\
	$(LOBJ)/dcloseL.o	\
	$(LOBJ)/deferL.o	\
	$(LOBJ)/devmsgL.o	\
	$(LOBJ)/dmagoL.o	\
	$(LOBJ)/dmalockL.o	\
	$(LOBJ)/dmaoffL.o	\
	$(LOBJ)/dmaonL.o	\
	$(LOBJ)/dmareqL.o	\
	$(LOBJ)/dopenL.o	\
	$(LOBJ)/drvmapL.o	\
	$(LOBJ)/dwriteL.o	\
	$(LOBJ)/fclearL.o	\
	$(LOBJ)/fdiskL.o	\
	$(LOBJ)/ffbyteL.o	\
	$(LOBJ)/ffwordL.o	\
	$(LOBJ)/ffmemL.o	\
	$(LOBJ)/fkcopyL.o	\
	$(LOBJ)/fpxcopyL.o	\
	$(LOBJ)/freeL.o		\
	$(LOBJ)/fucopyL.o	\
	$(LOBJ)/getcsL.o	\
	$(LOBJ)/getqL.o		\
	$(LOBJ)/getubdL.o	\
	$(LOBJ)/getuwdL.o	\
	$(LOBJ)/inbL.o		\
	$(LOBJ)/int11L.o	\
	$(LOBJ)/iogetcL.o	\
	$(LOBJ)/iomapvpL.o	\
	$(LOBJ)/ioputcL.o	\
	$(LOBJ)/ioreadL.o	\
	$(LOBJ)/ioreqL.o	\
	$(LOBJ)/iowriteL.o	\
	$(LOBJ)/ipcaccessL.o	\
	$(LOBJ)/kcallL.o	\
	$(LOBJ)/kfcopyL.o	\
	$(LOBJ)/kclearL.o	\
	$(LOBJ)/kpcopyL.o	\
	$(LOBJ)/kucopyL.o	\
	$(LOBJ)/lockL.o		\
	$(LOBJ)/lxdivL.o	\
	$(LOBJ)/lxmulL.o	\
	$(LOBJ)/lxremL.o	\
	$(LOBJ)/lxsgnL.o	\
	$(LOBJ)/memsetL.o	\
	$(LOBJ)/memtestL.o	\
	$(LOBJ)/nmidisableL.o	\
	$(LOBJ)/nmienableL.o	\
	$(LOBJ)/nondsigL.o	\
	$(LOBJ)/nonedevL.o	\
	$(LOBJ)/nulldevL.o	\

LIBOBJ2=$(LOBJ)/outbL.o		\
	$(LOBJ)/panicL.o	\
	$(LOBJ)/pclearL.o	\
	$(LOBJ)/pkcopyL.o	\
	$(LOBJ)/plrcopyL.o	\
	$(LOBJ)/pollopenL.o	\
	$(LOBJ)/pollwakeL.o	\
	$(LOBJ)/printfL.o	\
	$(LOBJ)/prlcopyL.o	\
	$(LOBJ)/ptovL.o		\
	$(LOBJ)/pucopyL.o	\
	$(LOBJ)/putcharL.o	\
	$(LOBJ)/putqL.o		\
	$(LOBJ)/putubdL.o	\
	$(LOBJ)/putuwdL.o	\
	$(LOBJ)/rucopyL.o	\
	$(LOBJ)/s5_to_sgL.o	\
	$(LOBJ)/s5_to_tcL.o	\
	$(LOBJ)/sallocL.o	\
	$(LOBJ)/sclearL.o	\
	$(LOBJ)/sendsigL.o	\
	$(LOBJ)/setivecL.o	\
	$(LOBJ)/sfreeL.o	\
	$(LOBJ)/sfbyteL.o	\
	$(LOBJ)/sfwordL.o	\
	$(LOBJ)/sfmemL.o	\
	$(LOBJ)/sg_to_s5L.o	\
	$(LOBJ)/sleepL.o	\
	$(LOBJ)/slrcopyL.o	\
	$(LOBJ)/sphiL.o		\
	$(LOBJ)/splL.o		\
	$(LOBJ)/sploL.o		\
	$(LOBJ)/superL.o	\
	$(LOBJ)/swapioL.o	\
	$(LOBJ)/tc_to_s5L.o	\
	$(LOBJ)/timeoutL.o	\
	$(LOBJ)/ttcloseL.o	\
	$(LOBJ)/tthupL.o	\
	$(LOBJ)/ttflushL.o	\
	$(LOBJ)/ttinL.o		\
	$(LOBJ)/ttioctlL.o	\
	$(LOBJ)/ttopenL.o	\
	$(LOBJ)/ttoutL.o	\
	$(LOBJ)/ttpollL.o	\
	$(LOBJ)/ttreadL.o	\
	$(LOBJ)/ttsetgrpL.o	\
	$(LOBJ)/ttsignalL.o	\
	$(LOBJ)/ttstartL.o	\
	$(LOBJ)/ttwriteL.o	\
	$(LOBJ)/uexitL.o	\
	$(LOBJ)/ufcopyL.o	\
	$(LOBJ)/ukcopyL.o	\
	$(LOBJ)/unlockL.o	\
	$(LOBJ)/upcopyL.o	\
	$(LOBJ)/urcopyL.o	\
	$(LOBJ)/vprintL.o	\
	$(LOBJ)/vrelseL.o	\
	$(LOBJ)/vremapL.o	\
	$(LOBJ)/vtopL.o		\
	$(LOBJ)/vxdivL.o	\
	$(LOBJ)/vxmulL.o	\
	$(LOBJ)/vxremL.o	\
	$(LOBJ)/waitqL.o	\
	$(LOBJ)/wakeupL.o	\

$(USRSYS)/lib/ldlib.a:	mkstub.m4 $(LIBOBJ1) $(LIBOBJ2)
	rm -f  $@@
	ar rc  $@@ $(LIBOBJ1)
	ar rc  $@@ $(LIBOBJ2)
	ranlib $@@

# Here is mkstub.m4:
#define(sym, substr(basename, -2, ))dnl
#	.globl	sym`_'
#sym`_':	mov	ax,`$K'sym`_'
#	.byte	0x9A
#	.word	xcalled
#	.word	0x0060
#	ret

MKSTUB=	echo "define(basename, `basename $*`)dnl" | m4 - mkstub.m4 > $*.s ;\
	as -gxo $@@ $*.s; rm $*.s

$(LOBJ)/absL.o:
	$(MKSTUB)

$(LOBJ)/allocL.o:
	$(MKSTUB)

$(LOBJ)/bclaimL.o:
	$(MKSTUB)

$(LOBJ)/bdoneL.o:
	$(MKSTUB)

$(LOBJ)/blkmvL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/bootL.o:
	$(MKSTUB)

$(LOBJ)/breadL.o:
	$(MKSTUB)

$(LOBJ)/breleaseL.o:
	$(MKSTUB)

$(LOBJ)/clockedfL.o:	clockedf.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(LOBJ)/clrivecL.o:
	$(MKSTUB)

$(LOBJ)/clrqL.o:
	$(MKSTUB)

$(LOBJ)/cs_selfL.o:	cs_self.s
	as -gxo $@@ $<

$(LOBJ)/dblockL.o:
	$(MKSTUB)

$(LOBJ)/dcloseL.o:
	$(MKSTUB)

$(LOBJ)/deferL.o:	defer.s
	as -gxo $@@ $<

$(LOBJ)/devmsgL.o:
	$(MKSTUB)

$(LOBJ)/dmagoL.o:
	$(MKSTUB)

$(LOBJ)/dmalockL.o:	dmalock.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(LOBJ)/dmaoffL.o:
	$(MKSTUB)

$(LOBJ)/dmaonL.o:
	$(MKSTUB)

$(LOBJ)/dmareqL.o:
	$(MKSTUB)

$(LOBJ)/dopenL.o:
	$(MKSTUB)

$(LOBJ)/drvmapL.o:
	$(MKSTUB)

$(LOBJ)/dwriteL.o:
	$(MKSTUB)

$(LOBJ)/fclearL.o:
	$(MKSTUB)

$(LOBJ)/fdiskL.o:
	$(MKSTUB)

$(LOBJ)/ffbyteL.o:	ffbyte.s
	as -gxo $@@ $<

$(LOBJ)/ffwordL.o:	ffword.s
	as -gxo $@@ $<

$(LOBJ)/ffmemL.o:	ffmem.s
	as -gxo $@@ $<

$(LOBJ)/fkcopyL.o:
	$(MKSTUB)

$(LOBJ)/fpxcopyL.o:
	$(MKSTUB)

$(LOBJ)/freeL.o:
	$(MKSTUB)

$(LOBJ)/fucopyL.o:
	$(MKSTUB)

$(LOBJ)/getcsL.o:	getcs.s
	as -gxo $@@ $<

$(LOBJ)/getqL.o:
	$(MKSTUB)

$(LOBJ)/getubdL.o:
	$(MKSTUB)

$(LOBJ)/getuwdL.o:
	$(MKSTUB)

$(LOBJ)/inbL.o:		inb.s
	as -gxo $@@ $<

$(LOBJ)/int11L.o:
	$(MKSTUB)

$(LOBJ)/iogetcL.o:
	$(MKSTUB)

$(LOBJ)/iomapvpL.o:
	$(MKSTUB)

$(LOBJ)/ioputcL.o:
	$(MKSTUB)

$(LOBJ)/ioreadL.o:
	$(MKSTUB)

$(LOBJ)/ioreqL.o:
	$(MKSTUB)

$(LOBJ)/iowriteL.o:
	$(MKSTUB)

$(LOBJ)/ipcaccessL.o:
	$(MKSTUB)

$(LOBJ)/kcallL.o:	kcall.s
	as -gxo $@@ $<

$(LOBJ)/kclearL.o:
	$(MKSTUB)

$(LOBJ)/kfcopyL.o:
	$(MKSTUB)

$(LOBJ)/kpcopyL.o:
	$(MKSTUB)

$(LOBJ)/kucopyL.o:
	$(MKSTUB)

$(LOBJ)/lockL.o:
	$(MKSTUB)

$(LOBJ)/lxdivL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/lxmulL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/lxremL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/lxsgnL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/memsetL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/memtestL.o:
	$(MKSTUB)

$(LOBJ)/nmidisableL.o:
	$(MKSTUB)

$(LOBJ)/nmienableL.o:
	$(MKSTUB)

$(LOBJ)/nondsigL.o:
	$(MKSTUB)

$(LOBJ)/nonedevL.o:	nonedev.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(LOBJ)/nulldevL.o:	nulldev.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(LOBJ)/outbL.o:		outb.s
	as -gxo $@@ $<

$(LOBJ)/panicL.o:
	$(MKSTUB)

$(LOBJ)/pclearL.o:
	$(MKSTUB)

$(LOBJ)/plrcopyL.o:
	$(MKSTUB)

$(LOBJ)/pkcopyL.o:
	$(MKSTUB)

$(LOBJ)/pollopenL.o:
	$(MKSTUB)

$(LOBJ)/pollwakeL.o:
	$(MKSTUB)

$(LOBJ)/printfL.o:
	$(MKSTUB)

$(LOBJ)/prlcopyL.o:
	$(MKSTUB)

$(LOBJ)/ptovL.o:
	$(MKSTUB)

$(LOBJ)/pucopyL.o:
	$(MKSTUB)

$(LOBJ)/putcharL.o:
	$(MKSTUB)

$(LOBJ)/putqL.o:
	$(MKSTUB)

$(LOBJ)/putubdL.o:
	$(MKSTUB)

$(LOBJ)/putuwdL.o:
	$(MKSTUB)

$(LOBJ)/rucopyL.o:
	$(MKSTUB)

$(LOBJ)/s5_to_sgL.o:
	$(MKSTUB)

$(LOBJ)/s5_to_tcL.o:
	$(MKSTUB)

$(LOBJ)/sallocL.o:
	$(MKSTUB)

$(LOBJ)/sclearL.o:
	$(MKSTUB)

$(LOBJ)/sendsigL.o:
	$(MKSTUB)

$(LOBJ)/setivecL.o:	setivec.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(LOBJ)/sfreeL.o:
	$(MKSTUB)

$(LOBJ)/sfbyteL.o:	sfbyte.s
	as -gxo $@@ $<

$(LOBJ)/sfwordL.o:	sfword.s
	as -gxo $@@ $<

$(LOBJ)/sfmemL.o:	sfmem.s
	as -gxo $@@ $<

$(LOBJ)/sg_to_s5L.o:
	$(MKSTUB)

$(LOBJ)/sleepL.o:
	$(MKSTUB)

$(LOBJ)/slrcopyL.o:
	$(MKSTUB)

$(LOBJ)/sphiL.o:	sphi.s
	as -gxo $@@ $<

$(LOBJ)/splL.o:	spl.s
	as -gxo $@@ $<

$(LOBJ)/sploL.o:	splo.s
	as -gxo $@@ $<

$(LOBJ)/superL.o:
	$(MKSTUB)

$(LOBJ)/swapioL.o:
	$(MKSTUB)

$(LOBJ)/tc_to_s5L.o:
	$(MKSTUB)

$(LOBJ)/timeoutL.o:	timeout.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(LOBJ)/ttcloseL.o:
	$(MKSTUB)

$(LOBJ)/ttflushL.o:
	$(MKSTUB)

$(LOBJ)/tthupL.o:
	$(MKSTUB)

$(LOBJ)/ttinL.o:
	$(MKSTUB)

$(LOBJ)/ttioctlL.o:
	$(MKSTUB)

$(LOBJ)/ttopenL.o:
	$(MKSTUB)

$(LOBJ)/ttoutL.o:
	$(MKSTUB)

$(LOBJ)/ttpollL.o:
	$(MKSTUB)

$(LOBJ)/ttreadL.o:
	$(MKSTUB)

$(LOBJ)/ttsetgrpL.o:
	$(MKSTUB)

$(LOBJ)/ttsignalL.o:
	$(MKSTUB)

$(LOBJ)/ttstartL.o:
	$(MKSTUB)

$(LOBJ)/ttwriteL.o:
	$(MKSTUB)

$(LOBJ)/uexitL.o:
	$(MKSTUB)

$(LOBJ)/ufcopyL.o:
	$(MKSTUB)

$(LOBJ)/ukcopyL.o:
	$(MKSTUB)

$(LOBJ)/unlockL.o:
	$(MKSTUB)

$(LOBJ)/upcopyL.o:
	$(MKSTUB)

$(LOBJ)/urcopyL.o:
	$(MKSTUB)

$(LOBJ)/vprintL.o:
	$(MKSTUB)

$(LOBJ)/vrelseL.o:
	$(MKSTUB)

$(LOBJ)/vremapL.o:
	$(MKSTUB)

$(LOBJ)/vtopL.o:
	$(MKSTUB)

$(LOBJ)/vxdivL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/vxmulL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/vxremL.o:	/lib/libc.a
	$(X_LIB)

$(LOBJ)/waitqL.o:
	$(MKSTUB)

$(LOBJ)/wakeupL.o:
	$(MKSTUB)
@


1.5
log
@mods by hal for relocateable object directories
@
text
@d139 1
d484 3
@


1.4
log
@update provided by hal
@
text
@a1 12
#
#	The  information  contained herein  is a trade secret  of INETCO
#	Systems, Ltd, and is  confidential information.   It is provided
#	under a license agreement,  and may be copied or disclosed  only
#	under  the  terms  of  that  agreement.    Any  reproduction  or
#	disclosure  of  this   material   without  the  express  written
#	authorization of INETCO Systems, Ltd. or persuant to the license
#	agreement is unlawful.
#
#	Copyright (c) 1988
#	An unpublished work by INETCO Systems, Ltd.
#	All rights reserved.
a4 3
# $Log: updateprovbyha,v $
# Revision 1.1.1.1  2019/05/29 04:56:34  root
# coherent
#(USRSRC)/ldrv/RCS/Makefile,v $
# Revision 1.2	91/04/30  18:38:22	root
# Changes to support polled async driver "hs"
a5 17
# Revision 1.5	89/06/30  16:31:48 	src
# Bug:	Multiple simultaneous DMA transfers resulted in data being lost.
# Fix:	Added DMA lock routines to ensure single simultaneous DMA
# 	transfers. (JHB)
# 
# Revision 1.3	88/05/23  17:31:10	src
# Added vtop linkage routine (Jim had filed away in his directory) - ART
# 
# Revision 1.2	88/04/04  16:39:27	src
# defer() function now supported from loadable drivers.
# 
# Revision 1.1	88/03/24  16:30:21	src
# Initial revision
#
# 88/02/16	Jim Belton		$(USRSRC)/ldrv/Makefile
# Added vtop linkage routine to ldlib.a.

a9 13
# Source directories
COHSRC=$(USRSRC)/coh
DRVSRC=$(USRSRC)/i8086/drv
I86SRC=$(USRSRC)/i8086/src
IBMATSRC=$(USRSRC)/i8086/ibm_at
KERSRC=$(USRSRC)/ker
TTYSRC=$(USRSRC)/ttydrv

# Object directories
I86OBJ=$(USRSRC)/i8086/objects
DRVOBJ=$(USRSRC)/i8086/drv/objects
IBMATOBJ=$(USRSRC)/i8086/ibm_at/objects

d30 4
a33 2
# The following script creates a interface stub to a kernel function.
GEN_DRV=objects/mkstub.sh
a34 5
# The following script extracts a module from a library.
ARX_LIB=set -e; OBJFIL=`basename $@@` ;\
	eval ar x $< $${OBJFIL} ;\
	eval mv $${OBJFIL} $@@

d38 62
a99 62
LIBOBJ1=objects/abs.o		\
	objects/alloc.o		\
	objects/bclaim.o	\
	objects/bdone.o		\
	objects/blkmv.o		\
	objects/boot.o		\
	objects/bread.o		\
	objects/brelease.o	\
	objects/clockedf.o	\
	objects/clrq.o		\
	objects/cs_self.o	\
	objects/dblock.o	\
	objects/dclose.o	\
	objects/defer.o		\
	objects/devmsg.o	\
	objects/dmago.o		\
	objects/dmalock.o	\
	objects/dmaoff.o	\
	objects/dmaon.o		\
	objects/dmareq.o	\
	objects/dopen.o		\
	objects/drvmap.o	\
	objects/dwrite.o	\
	objects/fclear.o	\
	objects/fdisk.o		\
	objects/ffbyte.o	\
	objects/ffword.o	\
	objects/ffmem.o		\
	objects/fkcopy.o	\
	objects/fpxcopy.o	\
	objects/free.o		\
	objects/fucopy.o	\
	objects/getcs.o		\
	objects/getq.o		\
	objects/getubd.o	\
	objects/getuwd.o	\
	objects/inb.o		\
	objects/int11.o		\
	objects/iogetc.o	\
	objects/iomapvp.o	\
	objects/ioputc.o	\
	objects/ioread.o	\
	objects/ioreq.o		\
	objects/iowrite.o	\
	objects/ipcaccess.o	\
	objects/kcall.o		\
	objects/kfcopy.o	\
	objects/kclear.o	\
	objects/kpcopy.o	\
	objects/kucopy.o	\
	objects/lock.o		\
	objects/lxdiv.o		\
	objects/lxmul.o		\
	objects/lxrem.o		\
	objects/lxsgn.o		\
	objects/memset.o	\
	objects/memtest.o	\
	objects/nmidisable.o	\
	objects/nmienable.o	\
	objects/nondsig.o	\
	objects/nonedev.o	\
	objects/nulldev.o	\
d101 63
a163 63
LIBOBJ2=objects/outb.o		\
	objects/panic.o		\
	objects/pclear.o	\
	objects/pkcopy.o	\
	objects/plrcopy.o	\
	objects/pollopen.o	\
	objects/pollwake.o	\
	objects/printf.o	\
	objects/prlcopy.o	\
	objects/ptov.o		\
	objects/pucopy.o	\
	objects/putchar.o	\
	objects/putq.o		\
	objects/putubd.o	\
	objects/putuwd.o	\
	objects/rucopy.o	\
	objects/s5_to_sg.o	\
	objects/s5_to_tc.o	\
	objects/salloc.o	\
	objects/sclear.o	\
	objects/sendsig.o	\
	objects/setivec.o	\
	objects/sfree.o		\
	objects/sfbyte.o	\
	objects/sfword.o	\
	objects/sfmem.o		\
	objects/sg_to_s5.o	\
	objects/sleep.o		\
	objects/slrcopy.o	\
	objects/sphi.o		\
	objects/spl.o		\
	objects/splo.o		\
	objects/super.o		\
	objects/swapio.o	\
	objects/tc_to_s5.o	\
	objects/timeout.o	\
	objects/ttclose.o	\
	objects/tthup.o		\
	objects/ttin.o		\
	objects/ttioctl.o	\
	objects/ttopen.o	\
	objects/ttout.o		\
	objects/ttpoll.o	\
	objects/ttread.o	\
	objects/ttsetgrp.o	\
	objects/ttsignal.o	\
	objects/ttstart.o	\
	objects/ttwrite.o	\
	objects/uexit.o		\
	objects/ufcopy.o	\
	objects/ukcopy.o	\
	objects/unlock.o	\
	objects/upcopy.o	\
	objects/urcopy.o	\
	objects/vprint.o	\
	objects/vrelse.o	\
	objects/vremap.o	\
	objects/vtop.o		\
	objects/vxdiv.o		\
	objects/vxmul.o		\
	objects/vxrem.o		\
	objects/waitq.o		\
	objects/wakeup.o	\
d165 1
a165 3
$(USRSYS)/lib/ldlib.a:	$(GEN_DRV)	\
			$(LIBOBJ1)	\
			$(LIBOBJ2)
d171 8
a178 16
#
# Create the script to create an interface stub to a kernel function.
#
$(GEN_DRV):
	echo ": 'Created by Makefile - do not edit.';\
	set -e; ENTRY=\`basename \$$1\`;(\
	echo \".globl \$${ENTRY}_\";\
	echo \"\$${ENTRY}_: mov ax,\\\\\$$K\$${ENTRY}_\";\
	echo .byte 0x9A;\
	echo .word xcalled;\
	echo .word 0x0060;\
	echo ret;)>/tmp/\$$\$$.s;\
	as -gxo /tmp/\$$\$$.o /tmp/\$$\$$.s;\
	mv /tmp/\$$\$$.o \$$1.o;\
	rm -f /tmp/\$$\$$.s" > $@@
	chmod +x $@@
d180 2
a181 2
objects/abs.o:
	$(GEN_DRV) $*
d183 2
a184 2
objects/alloc.o:
	$(GEN_DRV) $*
d186 2
a187 2
objects/bclaim.o:
	$(GEN_DRV) $*
d189 2
a190 2
objects/bdone.o:
	$(GEN_DRV) $*
d192 2
a193 2
objects/blkmv.o:	/lib/libc.a
	$(ARX_LIB)
d195 2
a196 2
objects/boot.o:
	$(GEN_DRV) $*
d198 2
a199 2
objects/bread.o:
	$(GEN_DRV) $*
d201 2
a202 2
objects/brelease.o:
	$(GEN_DRV) $*
d204 4
a207 1
objects/clockedf.o:	clockedf.c
d210 2
a211 2
objects/clrivec.o:
	$(GEN_DRV) $*
d213 2
a214 2
objects/clrq.o:
	$(GEN_DRV) $*
d216 1
a216 1
objects/cs_self.o:	cs_self.s
d219 2
a220 2
objects/dblock.o:
	$(GEN_DRV) $*
d222 2
a223 2
objects/dclose.o:
	$(GEN_DRV) $*
d225 1
a225 1
objects/defer.o:	defer.s
d228 2
a229 2
objects/devmsg.o:
	$(GEN_DRV) $*
d231 2
a232 2
objects/dmago.o:
	$(GEN_DRV) $*
d234 1
a234 1
objects/dmalock.o:	dmalock.c
d237 2
a238 2
objects/dmaoff.o:
	$(GEN_DRV) $*
d240 2
a241 2
objects/dmaon.o:
	$(GEN_DRV) $*
d243 2
a244 2
objects/dmareq.o:
	$(GEN_DRV) $*
d246 2
a247 2
objects/dopen.o:
	$(GEN_DRV) $*
d249 2
a250 2
objects/drvmap.o:
	$(GEN_DRV) $*
d252 2
a253 2
objects/dwrite.o:
	$(GEN_DRV) $*
d255 2
a256 2
objects/fclear.o:
	$(GEN_DRV) $*
d258 2
a259 2
objects/fdisk.o:
	$(GEN_DRV) $*
d261 1
a261 1
objects/ffbyte.o:	ffbyte.s
d264 1
a264 1
objects/ffword.o:	ffword.s
d267 1
a267 1
objects/ffmem.o:	ffmem.s
d270 2
a271 2
objects/fkcopy.o:
	$(GEN_DRV) $*
d273 2
a274 2
objects/fpxcopy.o:
	$(GEN_DRV) $*
d276 2
a277 2
objects/free.o:
	$(GEN_DRV) $*
d279 2
a280 2
objects/fucopy.o:
	$(GEN_DRV) $*
d282 1
a282 1
objects/getcs.o:	getcs.s
d285 2
a286 2
objects/getq.o:
	$(GEN_DRV) $*
d288 2
a289 2
objects/getubd.o:
	$(GEN_DRV) $*
d291 2
a292 2
objects/getuwd.o:
	$(GEN_DRV) $*
d294 1
a294 1
objects/inb.o:		inb.s
d297 2
a298 2
objects/int11.o:
	$(GEN_DRV) $*
d300 2
a301 2
objects/iogetc.o:
	$(GEN_DRV) $*
d303 2
a304 2
objects/iomapvp.o:
	$(GEN_DRV) $*
d306 2
a307 2
objects/ioputc.o:
	$(GEN_DRV) $*
d309 2
a310 2
objects/ioread.o:
	$(GEN_DRV) $*
d312 2
a313 2
objects/ioreq.o:
	$(GEN_DRV) $*
d315 2
a316 2
objects/iowrite.o:
	$(GEN_DRV) $*
d318 2
a319 2
objects/ipcaccess.o:
	$(GEN_DRV) $*
d321 1
a321 1
objects/kcall.o:	kcall.s
d324 2
a325 2
objects/kclear.o:
	$(GEN_DRV) $*
d327 2
a328 2
objects/kfcopy.o:
	$(GEN_DRV) $*
d330 2
a331 2
objects/kpcopy.o:
	$(GEN_DRV) $*
d333 2
a334 2
objects/kucopy.o:
	$(GEN_DRV) $*
d336 2
a337 2
objects/lock.o:
	$(GEN_DRV) $*
d339 2
a340 2
objects/lxdiv.o:	/lib/libc.a
	$(ARX_LIB)
d342 2
a343 2
objects/lxmul.o:	/lib/libc.a
	$(ARX_LIB)
d345 2
a346 2
objects/lxrem.o:	/lib/libc.a
	$(ARX_LIB)
d348 2
a349 2
objects/lxsgn.o:	/lib/libc.a
	$(ARX_LIB)
d351 2
a352 2
objects/memset.o:	/lib/libc.a
	$(ARX_LIB)
d354 2
a355 2
objects/memtest.o:
	$(GEN_DRV) $*
d357 2
a358 2
objects/nmidisable.o:
	$(GEN_DRV) $*
d360 2
a361 2
objects/nmienable.o:
	$(GEN_DRV) $*
d363 2
a364 2
objects/nondsig.o:
	$(GEN_DRV) $*
d366 1
a366 1
objects/nonedev.o:	nonedev.c
d369 1
a369 1
objects/nulldev.o:	nulldev.c
d372 1
a372 1
objects/outb.o:		outb.s
d375 2
a376 2
objects/panic.o:
	$(GEN_DRV) $*
d378 2
a379 2
objects/pclear.o:
	$(GEN_DRV) $*
d381 2
a382 2
objects/plrcopy.o:
	$(GEN_DRV) $*
d384 2
a385 2
objects/pkcopy.o:
	$(GEN_DRV) $*
d387 2
a388 2
objects/pollopen.o:
	$(GEN_DRV) $*
d390 2
a391 2
objects/pollwake.o:
	$(GEN_DRV) $*
d393 2
a394 2
objects/printf.o:
	$(GEN_DRV) $*
d396 2
a397 2
objects/prlcopy.o:
	$(GEN_DRV) $*
d399 2
a400 2
objects/ptov.o:
	$(GEN_DRV) $*
d402 2
a403 2
objects/pucopy.o:
	$(GEN_DRV) $*
d405 2
a406 2
objects/putchar.o:
	$(GEN_DRV) $*
d408 2
a409 2
objects/putq.o:
	$(GEN_DRV) $*
d411 2
a412 2
objects/putubd.o:
	$(GEN_DRV) $*
d414 2
a415 2
objects/putuwd.o:
	$(GEN_DRV) $*
d417 2
a418 2
objects/rucopy.o:
	$(GEN_DRV) $*
d420 2
a421 2
objects/s5_to_sg.o:
	$(GEN_DRV) $*
d423 2
a424 2
objects/s5_to_tc.o:
	$(GEN_DRV) $*
d426 2
a427 2
objects/salloc.o:
	$(GEN_DRV) $*
d429 2
a430 2
objects/sclear.o:
	$(GEN_DRV) $*
d432 2
a433 2
objects/sendsig.o:
	$(GEN_DRV) $*
d435 1
a435 1
objects/setivec.o:	setivec.c
d438 2
a439 2
objects/sfree.o:
	$(GEN_DRV) $*
d441 1
a441 1
objects/sfbyte.o:	sfbyte.s
d444 1
a444 1
objects/sfword.o:	sfword.s
d447 1
a447 1
objects/sfmem.o:	sfmem.s
d450 2
a451 2
objects/sg_to_s5.o:
	$(GEN_DRV) $*
d453 2
a454 2
objects/sleep.o:
	$(GEN_DRV) $*
d456 2
a457 2
objects/slrcopy.o:
	$(GEN_DRV) $*
d459 1
a459 1
objects/sphi.o:	sphi.s
d462 1
a462 1
objects/spl.o:	spl.s
d465 1
a465 1
objects/splo.o:	splo.s
d468 2
a469 2
objects/super.o:
	$(GEN_DRV) $*
d471 2
a472 2
objects/swapio.o:
	$(GEN_DRV) $*
d474 2
a475 2
objects/tc_to_s5.o:
	$(GEN_DRV) $*
d477 1
a477 1
objects/timeout.o:	timeout.c
d480 2
a481 2
objects/ttclose.o:
	$(GEN_DRV) $*
d483 2
a484 2
objects/tthup.o:
	$(GEN_DRV) $*
d486 2
a487 2
objects/ttin.o:
	$(GEN_DRV) $*
d489 2
a490 2
objects/ttioctl.o:
	$(GEN_DRV) $*
d492 2
a493 2
objects/ttopen.o:
	$(GEN_DRV) $*
d495 2
a496 2
objects/ttout.o:
	$(GEN_DRV) $*
d498 2
a499 2
objects/ttpoll.o:
	$(GEN_DRV) $*
d501 2
a502 2
objects/ttread.o:
	$(GEN_DRV) $*
d504 2
a505 2
objects/ttsetgrp.o:
	$(GEN_DRV) $*
d507 2
a508 2
objects/ttsignal.o:
	$(GEN_DRV) $*
d510 2
a511 2
objects/ttstart.o:
	$(GEN_DRV) $*
d513 2
a514 2
objects/ttwrite.o:
	$(GEN_DRV) $*
d516 2
a517 2
objects/uexit.o:
	$(GEN_DRV) $*
d519 2
a520 2
objects/ufcopy.o:
	$(GEN_DRV) $*
d522 2
a523 2
objects/ukcopy.o:
	$(GEN_DRV) $*
d525 2
a526 2
objects/unlock.o:
	$(GEN_DRV) $*
d528 2
a529 2
objects/upcopy.o:
	$(GEN_DRV) $*
d531 2
a532 2
objects/urcopy.o:
	$(GEN_DRV) $*
d534 2
a535 2
objects/vprint.o:
	$(GEN_DRV) $*
d537 2
a538 2
objects/vrelse.o:
	$(GEN_DRV) $*
d540 2
a541 2
objects/vremap.o:
	$(GEN_DRV) $*
d543 2
a544 2
objects/vtop.o:
	$(GEN_DRV) $*
d546 2
a547 2
objects/vxdiv.o:	/lib/libc.a
	$(ARX_LIB)
d549 2
a550 2
objects/vxmul.o:	/lib/libc.a
	$(ARX_LIB)
d552 2
a553 2
objects/vxrem.o:	/lib/libc.a
	$(ARX_LIB)
d555 2
a556 2
objects/waitq.o:
	$(GEN_DRV) $*
d558 2
a559 2
objects/wakeup.o:
	$(GEN_DRV) $*
@


1.3
log
@initial version provided by stevesf 
@
text
@d1 1
a1 1
# $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
d17 1
a17 1
# $Log: updateprovbyha,v $
# Revision 1.1.1.1  2019/05/29 04:56:34  root
# coherent
#
d35 1
a35 1
# 88/02/16	Jim Belton		/usr/src/sys/ldrv/Makefile
a37 2
USRSYS=/usr/sys

a40 3
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
USSINC=/usr/src/sys
d43 6
a48 6
COHSRC=/usr/src/sys/coh
DRVSRC=/usr/src/sys/i8086/drv
I86SRC=/usr/src/sys/i8086/src
IBMATSRC=/usr/src/sys/i8086/ibm_at
KERSRC=/usr/src/sys/ker
TTYSRC=/usr/src/sys/ttydrv
d51 3
a53 3
I86OBJ=/usr/src/sys/i8086/objects
DRVOBJ=/usr/src/sys/i8086/drv/objects
IBMATOBJ=/usr/src/sys/i8086/ibm_at/objects
d56 1
a56 1
CFLAGS=-I$(DRVINC) -I$(KERINC) -I$(SYSINC)
d58 4
a61 4
TARGETS=objects/ldrts0.o	\
	objects/ldmain.o	\
	objects/ldswap.o	\
	objects/ldlib.a
d63 1
a63 1
all:		$(TARGETS)
d66 2
a67 4
install:	$(TARGETS)	\
		ldconfig
	cp $(TARGETS) /tmp/usr/sys/lib
	cp ldconfig /tmp/usr/sys
d69 2
a70 2
shrink:
	rm -f objects/*
d72 2
a73 3
objects/ldrts0.o:	ldrts0.s
	as -x ldrts0.s
	mv l.out $@@
a74 9
objects/ldmain.o:	ldmain.c
	$(CC) $(CFLAGS) -c ldmain.c
	mv ldmain.o $@@

#	$(CC) $(CFLAGS) -c ldswap.c
objects/ldswap.o:	ldswap.c
	$(CC) $(CFLAGS) -DNOMONITOR -c ldswap.c
	mv ldswap.o $@@

d213 1
a213 1
objects/ldlib.a:	$(GEN_DRV)	\
a219 1
	cp $@@ /usr/sys/lib
d272 1
a272 2
	as -gxo cs_self.o cs_self.s
	mv cs_self.o $@@
d281 1
a281 2
	as -gxo defer.o defer.s
	mv defer.o $@@
d290 1
a290 2
	$(CC) $(CFLAGS) -c dmalock.c
	mv dmalock.o $@@
d317 1
a317 2
	as -gxo ffbyte.o ffbyte.s
	mv ffbyte.o $@@
d320 1
a320 2
	as -gxo ffword.o ffword.s
	mv ffword.o $@@
d323 1
a323 2
	as -gxo ffmem.o ffmem.s
	mv ffmem.o $@@
d338 1
a338 2
	as -gxo getcs.o getcs.s
	mv getcs.o $@@
d350 1
a350 2
	as -gxo inb.o inb.s
	mv inb.o $@@
d377 1
a377 2
	as -gxo kcall.o kcall.s
	mv kcall.o $@@
d422 1
a422 2
	$(CC) $(CFLAGS) -c nonedev.c
	mv nonedev.o $@@
d425 1
a425 2
	$(CC) $(CFLAGS) -c nulldev.c
	mv nulldev.o $@@
d428 1
a428 2
	as -gxo outb.o outb.s
	mv outb.o $@@
d491 1
a491 2
	$(CC) $(CFLAGS) -c setivec.c
	mv setivec.o $@@
d496 2
a497 3
objects/sfbyte.o:
	as -gxo sfbyte.o sfbyte.s
	mv sfbyte.o $@@
d499 2
a500 3
objects/sfword.o:
	as -gxo sfword.o sfword.s
	mv sfword.o $@@
d502 2
a503 3
objects/sfmem.o:
	as -gxo sfmem.o sfmem.s
	mv sfmem.o $@@
d514 2
a515 3
objects/sphi.o:
	as -gxo sphi.o sphi.s
	mv sphi.o $@@
d517 2
a518 3
objects/spl.o:
	as -gxo spl.o spl.s
	mv spl.o $@@
d520 2
a521 3
objects/splo.o:
	as -gxo splo.o splo.s
	mv splo.o $@@
d533 1
a533 2
	$(CC) $(CFLAGS) -c timeout.c
	mv timeout.o $@@
a614 1

@


1.2
log
@Changes to support polled async driver "hs"
@
text
@d1 1
a1 1
# $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
d18 3
d220 1
d627 3
@


1.1
log
@Shipped with 3.0.0 COHERENT.
@
text
@d35 1
a35 4
CC=/bin/cc
#IFLAGS=-I/usr/include/sys -I/usr/src/sys/sys -I/usr/src/sys/i8086/sys
IFLAGS=-I/tmp/usr/include/sys -I/tmp/usr/src/sys/sys -I/tmp/usr/src/sys/i8086/sys
CFLAGS=$(IFLAGS)
d37 23
d108 1
a108 1
	objects/clocked.o	\
d110 1
d146 1
a147 1
	objects/kfcopy.o	\
d167 1
d171 1
d233 1
d276 2
a277 2
objects/clocked.o:
	$(GEN_DRV) $*
d285 4
d462 3
d477 3
@
0707070064030005001004440000030000030000011777770507310744200005200000002340/newbits/kernel/USRSRC/ldrv/RCS/blkmv.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.33.43;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.42.53;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:25	src
/ Initial revision
/ 
/
////////

	.globl	blkmv

blkmv:	push	si
	push	di
	push	bp
	mov	bp, sp

	mov	di, 8(bp)
	mov	si, 10(bp)
	mov	cx, 12(bp)
	cld
	rep
	movsb

	mov	ax, 8(bp)
	mov	sp, bp
	pop	bp
	pop	di
	pop	si
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105301004440000030000030000011777770507310744200005400000000772/newbits/kernel/USRSRC/ldrv/RCS/cs_self.s,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.42.57;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@



1.1
log
@Initial revision
@
text
@////////
/
/ Get cs selector - return 0 if in kernel, CS if not in kernel.
/
/ This version is for loadable drivers.
/ There is a different version (cs_sel.s) for resident drivers.
/
/ int	cs_sel();
/
////////

	.globl	cs_sel_
cs_sel_:
	mov	ax, cs
	ret
@
0707070064030105101004440000030000030000011777770507310744200005200000003174/newbits/kernel/USRSRC/ldrv/RCS/defer.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.33.52;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.42.59;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/04/04  16:40:21	src
/ Initial revision
/ 
/
////////

////////
/
/ void
/ defer( f, a )		- defer local function from loadable driver.
/ void (*f)();
/ int a;
/
/	Input:	f = pointer to function to be deferred.
/		a = argument to be passed to function.
/
/	Action:	Schedule local function 'f' to be invoked with argument 'a'
/		at next transition from kernel to user mode.
/
/	Return:	None.
/
////////

	.globl	defer_

defer_:	push	bp			/ defer( f, a )
	mov	bp, sp			/ void (*f)();
	push	6(bp)			/ int a;
	push	cs			/ {
	push	4(bp)			/	kcall( Kldefer, f, cs, a );
	mov	ax, $Kldefer		/
	push	ax			/
	call	kcall_			/
	mov	sp, bp			/
	pop	bp			/ }
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105071004440000030000030000011777770507310744300005300000002544/newbits/kernel/USRSRC/ldrv/RCS/ffbyte.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.34.01;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.00;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:28	src
/ Initial revision
/ 
/
////////

////////
/
/ ffbyte( fp )		-- fetch far byte
/ int far * fp;
/
////////

	.globl	ffbyte_

ffbyte_:push	es		/ ffbyte( fp )
	push	di		/ register char far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	sub	ax, ax		/
	movb	al, es:(di)	/	return( *fp );
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105261004440000030000030000011777770507310744300005200000003456/newbits/kernel/USRSRC/ldrv/RCS/ffmem.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.34.04;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.01;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:31	src
/ Initial revision
/ 
/
////////

////////
/
/ void
/ ffmem( fp, m, n )	-- fetch far memory
/ faddr_t fp;
/ char * m;
/ int n;
/
/	Input:	fp = far pointer [32 bit selector:offset] to source
/		m  = destination
/		n  = number of bytes to transfer.
/
/	Action:	Transfer 'n' bytes from far address 'fp' to offset 'm'
/		in the current data space.
/
/	Return:	None.
/
////////

	.globl	ffmem_

ffmem_:	push	si		/ void
	push	di		/ ffmem( fp, m, n )
	push	bp		/
	mov	bp, sp		/ register faddr_t fp;		/* DS:SI */
	push	ds		/ register char * m;		/* DI */
	lds	si, 8(bp)	/ register int n;		/* CX */
	mov	di, 12(bp)	/
	mov	cx, 14(bp)	/ {
				/
	cld			/
	clc			/	for ( ; n != 0; --n )
	rcr	cx, $1		/
	rep			/		*m++ = *fp++;
	movsw			/
	rcl	cx, $1		/
	rep			/
	movsb			/
				/
	pop	ds		/ }
	pop	bp
	pop	di
	pop	si
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105251004440000030000030000011777770507310744400005300000002520/newbits/kernel/USRSRC/ldrv/RCS/ffword.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.34.07;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.01;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:33	src
/ Initial revision
/ 
/
////////

////////
/
/ ffword( fp )		-- fetch far word
/ int far * fp;
/
////////

	.globl	ffword_

ffword_:push	es		/ ffword( fp )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ {
	mov	bp, sp		/
	les	di, 8(bp)	/
				/
	mov	ax, es:(di)	/	return *fp;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105241004440000030000030000011777770507310744400005200000002374/newbits/kernel/USRSRC/ldrv/RCS/getcs.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.34.10;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.02;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:36	src
/ Initial revision
/ 
/ 87/12/08	Allan Cornish	/usr/src/sys/ldrv/getcs.s
/ Getcs() function obtains current code segment.
/
////////

////////
/
/ Get code selector.
/
////////

	.globl	getcs_

getcs_:	mov	ax, cs			/ Return code selector.
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105231004440000030000030000011777770507310744400005000000002263/newbits/kernel/USRSRC/ldrv/RCS/inb.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.34.13;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.03;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:39	src
/ Initial revision
/ 
/
////////

////////
/
/ Basic port level I/O.
/
/ int	inb(port);
/
////////

	.globl	inb_

inb_:	mov	bx, sp
	mov	dx, 2(bx)
	sub	ax, ax
	inb	al, dx
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105221004440000030000030000011777770507310744500005200000003315/newbits/kernel/USRSRC/ldrv/RCS/kcall.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.34.16;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.04;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:41	src
/ Initial revision
/ 
/
////////

////////
/
/ kcall( func, arg, ... )
/
/	Input:	func = kernel function to be invoked.
/		arg  = optional argument(s) to be passed to kernel function.
/
/	Action:	Invoke kernel function.
/
////////
	.globl	kcall_

kcall_:
	pop	bx		/ Convert stack from (retIP dstIP arg ...)
	pop	ax		/		  to (      retIP arg ...)
	push	bx		/ Leaving dstIP in AX register.
				/
	.byte 0x9A		/ Request kernel to perform far call.
	.word xcalled		/
	.word 0x0060		/
				/
	pop	bx		/ Convert stack from (      retIP arg ...)
	push	bx		/		  to (retIP retIP arg ...)
	push	bx		/ This allows caller to cleanup normally.
				/ NOTE: DO NOT MODIFY DX:AX RETURN VALUE.
				/
	ret			/ Return to caller.
@


1.1
log
@Initial revision
@
text
@@
0707070064030105061004440000030000030000011777770507310744500005300000003561/newbits/kernel/USRSRC/ldrv/RCS/ldrts0.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.34.55;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.09;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/ 
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/ 
/	Copyright (c) 1987
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/

////////
/
/ Loadable Driver Run Time Startup
/
/ Notes:	This function MUST be at offset 0 in driver code segment.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:30:47	src
/ Initial revision
/ 
/
////////

	.globl	main_
	call	main_
	xret

////////
/
/	Invocation mechanism for local driver functions by kernel code.
/
/	Input:	AX	= pointer to local function to be invoked.
/		4(BP)	= 1st parameter to be passed to local function.
/		6(BP)	= 2nd parameter to be passed to local function.
/		8(BP)	= 3rd parameter to be passed to local function.
/
/	Action:	Invoke local function whose address is given in register AX,
/		passing parameters at offset 4,6,8 relative to register BP.
/		Perform a far return to operating system.
/
/	Notes:	Parameter passing convention specified by kernel.
/		This function MUST be at offset 4 in driver code segment.
/
////////

	push	8(bp)
	push	6(bp)
	push	4(bp)
	icall	ax
	add	sp, $6
	xret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105031004440000030000030000011777770507310744500005100000002302/newbits/kernel/USRSRC/ldrv/RCS/outb.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.35.16;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.12;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:00	src
/ Initial revision
/ 
/
////////

////////
/
/ Basic port level I/O.
/
/ int	outb(port, data);
/
////////

	.globl	outb_

outb_:	mov	bx, sp
	mov	dx, 2(bx)
	mov	ax, 4(bx)
	outb	dx, al
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105021004440000030000030000011777770507310744600005300000002612/newbits/kernel/USRSRC/ldrv/RCS/sfbyte.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.35.22;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.13;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:05	src
/ Initial revision
/ 
/
////////

////////
/
/ sfbyte( fp, b )	-- set far byte
/ char far * fp;
/ char b;
/
////////

	.globl	sfbyte_

sfbyte_:push	es		/ sfbyte( fp, c )
	push	di		/ register char far * fp;	/* ES:DI */
	push	bp		/ register char c;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	movb	es:(di), al	/	*fp = c;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105161004440000030000030000011777770507310744600005200000003456/newbits/kernel/USRSRC/ldrv/RCS/sfmem.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.35.25;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.14;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:08	src
/ Initial revision
/ 
/
////////

////////
/
/ void
/ sfmem( fp, m, n )	-- set far memory
/ char far * fp;
/ char * m;
/ int n;
/
/	Input:	fp = far pointer [32 bit selector:offset] to destination
/		m  = source
/		n  = number of bytes to transfer.
/
/	Action:	Transfer 'n' bytes from offset 'm' in the current data space
/		to far address 'fp'.
/
/	Return:	None.
/
////////

	.globl	sfmem_

sfmem_:	push	si		/ void
	push	di		/ sfmem( fp, m, n )
	push	bp		/
	mov	bp, sp		/ register char * fp;		/* ES:DI */
	push	es		/ register char * m;		/* SI */
	les	di, 8(bp)	/ register int n;		/* CX */
	mov	si, 12(bp)	/
	mov	cx, 14(bp)	/ {
				/
	cld			/
	clc			/	for ( ; n != 0; --n )
	rcr	cx, $1		/
	rep			/		*fp++ = *m++;
	movsw			/
	rcl	cx, $1		/
	rep			/
	movsb			/
				/
	pop	es		/ }
	pop	bp
	pop	di
	pop	si
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105151004440000030000030000011777770507310744700005300000002605/newbits/kernel/USRSRC/ldrv/RCS/sfword.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.35.28;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.15;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1986
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:11	src
/ Initial revision
/ 
/
////////

////////
/
/ sfword( fp, w )	-- set far word
/ int far * fp;
/ int w;
/
////////

	.globl	sfword_

sfword_:push	es		/ sfword( fp, w )
	push	di		/ register int far * fp;	/* ES:DI */
	push	bp		/ register int w;		/* AX */
	mov	bp, sp		/ {
	les	di, 8(bp)	/
	mov	ax, 12(bp)	/
				/
	mov	es:(di), ax	/	*fp = w;
				/
	pop	bp		/ }
	pop	di
	pop	es
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105141004440000030000030000011777770507310744700005100000002362/newbits/kernel/USRSRC/ldrv/RCS/sphi.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.35.30;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.16;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:13	src
/ Initial revision
/ 
/
////////

////////
/
/ Disable interrupts.  Previous value is returned.
/
////////

	.globl	sphi_

sphi_:
	pushf				/ Save flags
	pop	ax			/ Return current value
	cli				/ Disable interrupts
	ret				/ And return
@


1.1
log
@Initial revision
@
text
@@
0707070064030105131004440000030000030000011777770507310744700005000000002411/newbits/kernel/USRSRC/ldrv/RCS/spl.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.35.35;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.16;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:16	src
/ Initial revision
/ 
/
////////

////////
/
/ Change interrupt flag.  Previous value is returned.
/
////////
	.globl	spl_

spl_:
	pop	ax			/ ip
	pop	bx			/ psw
	push	bx
	push	bx			/ push psw, cs, ip for iret
	push	cs
	push	ax
	pushf				/ old psw
	pop	ax
	iret
@


1.1
log
@Initial revision
@
text
@@
0707070064030105121004440000030000030000011777770507310745000005100000002240/newbits/kernel/USRSRC/ldrv/RCS/splo.s,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @@;


1.2
date     91.06.20.14.35.41;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.17;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/ $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
/
/	The  information  contained herein  is a trade secret  of INETCO
/	Systems, and is confidential information.   It is provided under
/	a license agreement,  and may be copied or disclosed  only under
/	the terms of that agreement.   Any reproduction or disclosure of
/	this  material  without  the express  written  authorization  of
/	INETCO Systems or persuant to the license agreement is unlawful.
/
/	Copyright (c) 1988
/	An unpublished work by INETCO Systems, Ltd.
/	All rights reserved.
/
/ $Log: updateprovbyha,v $
/ Revision 1.1.1.1  2019/05/29 04:56:34  root
/ coherent
/
/ Revision 1.1	88/03/24  16:31:19	src
/ Initial revision
/ 
/
////////

////////
/
/ Enable interrupts.  Previous value is returned.
/
////////

	.globl	splo_

splo_:
	pushf
	pop	ax
	sti
	ret
@


1.1
log
@Initial revision
@
text
@@
0707070064030103121004440000030000030000011777770507310745000005500000004624/newbits/kernel/USRSRC/ldrv/RCS/clockedf.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.33.48;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.18;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* clockedf.c - support routines for alternate clock rate
              - this is the FAR version of clocked.c for loadable drivers

  altclk_in(hz, fn) - install routine with specified rate
                          "hz" should be a multiple of system rate of 100 Hz

  altclk_out()      - uninstall alternate clock routine and restore system rate
			return old value of "altclk"

  altclk_rate(hz)   - set clock interrupt rate
			new rate must be an even multiple of system rate "HZ"
			return 0 if completed ok, -1 otherwise

  History:
    90/08/08 hws	initial version, works with hs.c modified for com[1-4]
    90/08/14 hws	make it more like a Unix system call
    90/09/12 hws	add far version
*/

#include	<sys/coherent.h>	/* altclk */
#include	<sys/const.h>	/* HZ */

#define	PIT	0x40	/* 8253 port */
#define	TMR0_M3	0x36	/* timer 0, mode 3 */
#if 0
/* nominal IBM rate is 1.1900 MHz */
#define	SYS_HZ	1190000L	/* rate of input clock to timer 0 */
#else
/* current kernel rate is 1.1932 MHz */
#define	SYS_HZ	1193200L	/* rate of input clock to timer 0 */
#endif

typedef int (*PFI)();	/* pointer to function returning int */

extern saddr_t ucs;

static int altclk_rate(hz)
unsigned int hz;
{
  int s;	/* to save CPU irpt flag */
  unsigned int interval;	/* period for hz, in units of 1.19 MHz ticks */
  int ret;

  if (hz >= HZ && hz % HZ == 0) {	/* can't go slower than HZ! */
    interval = SYS_HZ/hz;
    s = sphi();	/* disable irpts */
    outb(PIT+3, TMR0_M3);
    outb(PIT, interval & 0xff);
    outb(PIT, interval >> 8);	/* unsigned shift */
    spl(s);	/* restore previous irpt state */
    ret = 0;
  }
  else {
    ret = -1;
  }
  return ret;
}

int altclk_in(hz, fn)
int hz;
PFI fn;
{
  int ret;
  int s;

  if ((ret = altclk_rate(hz)) == 0) {
    s = sphi();
    altclk = fn;
    altsel = cs_sel();
    spl(s);
  }
  return ret;
}

PFI altclk_out()
{
  PFI ret;
  int s;

  ret = altclk;
  if (ret) {
    altclk_rate(HZ);
    s = sphi();
    altclk = 0;
    altsel = 0;
    spl(s);
  }
  return ret;
}
@


1.1
log
@Initial revision
@
text
@d20 1
a20 1
#include	"coherent.h"	/* altclk */
@
0707070064030105271004440000030000030000011777770507310745100005400000005234/newbits/kernel/USRSRC/ldrv/RCS/dmalock.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.33.57;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.19;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, Ltd, and is  confidential information.   It is provided
 *	under a license agreement,  and may be copied or disclosed  only
 *	under  the  terms  of  that  agreement.    Any  reproduction  or
 *	disclosure  of  this   material   without  the  express  written
 *	authorization of INETCO Systems, Ltd. or persuant to the license
 *	agreement is unlawful.
 *
 *	Copyright (c) 1989
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 *
 * $Description: $
 *	Routines to lock/unlock the DMA controller chip from a loadable driver.
 *
 * $Author: root $
 *
 * $Creation: June 29, 1989 $
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	89/06/30  16:29:52 	src
 * Initial revision
 * 
 */

#include <sys/coherent.h>

typedef void (* vfp_t)();		/* Void function pointer type.	     */

/*
 * External functions.
 */
extern void Kdmalock();
extern void Kdmaunlock();
extern void Kldtimcall();
extern saddr_t getcs();

/*
 * int
 * dmalock( tp, fun, arg )
 * TIM * tp;
 * vfp_t fun;
 * int	 arg;
 *
 *	Inputs:	tp  = Deferred function structure pointer.
 *		fun = Function to call if request is deferred.
 *		arg = Argument to pass to function.
 *
 *	Action:	Calls kernel dmalock() routine.
 *
 *	Return:	0 = Lock granted or -1 = Lock deferred.
 *
 *	Notes:	DMA controller locking was introduced to cure a bug on the
 *		NCR DMA controller, where overlapped DMA caused problems.
 *		No action is taken if DMA locking is disabled.
 */

int
dmalock( tp, fun, arg )
register TIM  * tp;
vfp_t		fun;
int		arg;
{
	/*
	 * Define loadable driver interface.
	 * Kldtimcall will be invoked when a deferred function is executed.
	 * It will in turn invoke FP_SEL(tp->t_ldrv):4 (the calling drivers
	 * function call entry point), passing FP_OFF(tp->t_ldrv) (the function
	 * to call) in AX.
	 */
	FP_SEL(tp->t_ldrv) = getcs();
	FP_OFF(tp->t_ldrv) = fun;
	return( kcall( Kdmalock, tp, Kldtimcall, arg ) );
}

/*
 * void
 * dmaunlock( tp )
 * TIM * tp;
 *
 *	Inputs:	tp = Deferred function structure pointer.
 *
 *	Action:	Calls the kernel dmaunlock().
 */

void
dmaunlock( tp )
register TIM * tp;
{
	kcall( Kdmaunlock, tp );
}

@


1.1
log
@Initial revision
@
text
@d28 1
a28 1
#include <coherent.h>
@
0707070064030060161004440000030000030000011777770507310745100005300000012720/newbits/kernel/USRSRC/ldrv/RCS/ldmain.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.34.48;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.20;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Loadable Driver - Process Handler.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.2	89/03/31  16:19:36 	src
 * Bug:	Did not cancel either attached timed functions or deferred functions
 * 	during an unload.  As a result, if a driver did not explicitly do
 * 	this, then unloading the driver could cause a system panic.
 * Fix:	Now cancels the functions. (ABC)
 * 
 * Revision 1.1	88/03/24  08:30:44 	src
 * Initial revision
 * 
 * 87/12/03	Allan Cornish		/usr/src/sys/ldrv/ldmain.c
 * Initial version.
 */
#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/con.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>

extern CON con;

extern	saddr_t	ldrvsel[NDRV];
extern	saddr_t ldrvics[16];
extern	void  (*ldrvipc[16])();
extern	CON *	ldrvcon[NDRV];
extern	CON	ldrvpsy;
extern	saddr_t	ucs;

/*
 * Local variable - keeps track of the number of opens.
 * The loadable driver can't terminate until after the last close.
 * Openf is the loadable driver open routine.
 * Closef points to the driver's close routine.
 * The configuration table entries are taken over
 */
static	int	nopen = 0;
static	void	(*openf)() = NULL;
static	void	(*closef)() = NULL;

main()
{
	register int mind = con.c_mind;
	register int level;
	extern	void myopen();
	extern	void myclose();
	extern	void Kdefend();

	/*
	 * Loadable devices must identify the desired major device.
	 */
	if ( (mind == 0) || (mind >= drvn) ) {
		printf("ldrv:%d: bad dev\n", mind );
		uexit( 1 );
	}

	/*
	 * Loadable devices must use a unique [not in use] major device.
	 */
	if ( (drvl[mind].d_conp != NULL) || (ldrvcon[mind] != NULL) ) {
		printf("ldrv:%d: dev bsy\n", mind );
		uexit( 0 );
	}

	/*
	 * Intercept driver open/close requests.
	 * This allows the driver process to terminate after the last close,
	 *	if one or more signals have been received.
	 */
	openf		= con.c_open;
	closef		= con.c_close;
	con.c_open	= myopen;
	con.c_close	= myclose;

	/*
	 * Install the loadable driver pseudo device interface.
	 * The O/S will call the pseudo-device, which will call us.
	 * Record our driver configuration and code segment.
	 */
	drvl[mind].d_conp = &ldrvpsy;
	ldrvcon[mind] = &con;
	ldrvsel[mind] = ucs;

	/*
	 * Load the device driver.
	 */
	if ( con.c_load != NULL )
		(*con.c_load)( makedev(mind,0) );

	/*
	 * Sleep until a kill signal has arrived, and no device is open.
	 */
	do {
		sleep( (char *)&nopen, CVSWAP, IVSWAP, SVSWAP );

	} while ( ((SELF->p_ssig & 0x0100) == 0) || (nopen != 0) );

	/*
	 * Unload the device driver.
	 */
	if ( con.c_uload != NULL )
		(*con.c_uload)( makedev(mind,0) );

	/*
	 * Erase references to our kernel process.
	 */
	drvl[mind].d_conp = NULL;
	ldrvcon[mind] = NULL;
	ldrvsel[mind] = 0;

	/*
	 * Scan looking for attached interrupts.
	 * NOTE: This is to prevent dangling interrupt vectors.
	 */
	for ( level = 0; level < 16; level++ ) {

		/*
		 * Interrupt is not attached to us.
		 */
		if ( ldrvics[level] != ucs )
			continue;

		/*
		 * Disable interrupt.
		 */
		clrivec( level );

		/*
		 * Release loadable driver interrupt.
		 */
		ldrvics[level] = 0;
		ldrvipc[level] = NULL;
	}

	/*
	 * Service deferred functions BEFORE scanning for timed functions.
	 * This is in case a deferred function schedules a timed function.
	 */
	kcall( Kdefend );

	/*
	 * Scan for attached timed functions which have to be terminated.
	 */
	for ( level = 0; level < nel(timq); level++ ) {
		register TIM * tp;

		/*
		 * Access a specific timing queue.
		 */
		for ( tp = timq[level]; tp != NULL; ) {

			/*
			 * Timed function is in our loadable driver.
			 * Restart search at start of timing queue.
			 */
			if ( FP_SEL(tp->t_ldrv) == getcs() ) {
			  	timeout( tp, 0, NULL, 0 );
				tp = timq[ level ];
			}

			/*
			 * Not one of our timed functions.
			 * Advance to next function in queue.
			 */
			else
				tp = tp->t_next;
		}
	}

	/*
	 * Terminate with extreme prejudice.
	 */
	uexit( 0 );
}

static void
myopen( dev, mode )
dev_t dev;
int mode;
{
	/*
	 * Invoke the true open routine for the loadable driver.
	 */
	if ( openf != NULL )
		(*openf)(dev, mode );

	/*
	 * Adjust reference count if open succeeded.
	 */
	if ( u.u_error == 0 )
		nopen++;
}

static void
myclose( dev )
dev_t dev;
{
	/*
	 * Invoke the true close routine for the loadable driver.
	 */
	if ( closef != NULL )
		(*closef)( dev );

	/*
	 * Wakeup driver process after last close.
	 * This allows it to terminate if appropriate.
	 */
	if ( --nopen == 0 )
		wakeup( (char*) &nopen );
}
@


1.1
log
@Initial revision
@
text
@d31 3
a33 3
#include <coherent.h>
#include <proc.h>
#include <sched.h>
@
0707070064030105201004440000030000030000011777770507310745300005300000030345/newbits/kernel/USRSRC/ldrv/RCS/ldswap.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.34.58;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.21;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/* (lgl-
 *	The information contained herein is a trade secret of Mark Williams
 *	Company, and  is confidential information.  It is provided  under a
 *	license agreement,  and may be  copied or disclosed  only under the
 *	terms of  that agreement.  Any  reproduction or disclosure  of this
 *	material without the express written authorization of Mark Williams
 *	Company or persuant to the license agreement is unlawful.
 *
 *	COHERENT Version 2.3.37
 *	Copyright (c) 1982, 1983, 1984.
 *	An unpublished work by Mark Williams Company, Chicago.
 *	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Swapper.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:30:50	src
 * Initial revision
 * 
 * 87/11/05	Allan Cornish		/usr/src/sys/ldrv/ldswap.c
 * New seg struct now used to allow extended addressing.
 *
 * 87/10/26	Allan Cornish		/usr/src/sys/ldrv/ldswap.c
 * Modified to support loadable drivers - temporary modification.
 * Now requires SIGKILL signal in order to terminate.
 *
 * 87/01/05	Allan Cornish		/usr/src/sys/ker/swap.c
 * Swap() now waits for all processes to be swapped in before exit on signal.
 */
#include <sys/coherent.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/seg.h>
#include <sys/uproc.h>
#include <sys/buf.h>

/*
 * Functions.
 */
SEG	*xmalloc();
SEG	*xdalloc();
void	Kwakeup();
void	Ktimeout();

main()
{
	register SEG *sp;
	register PROC *pp1;
	register PROC *pp2;
	register PROC *pp3;
	register unsigned s;
	register unsigned n;
	register unsigned t;
	register unsigned v;
	register unsigned m;
	register int i;
	static unsigned ltimer;

	if (sexflag != 0)
		uexit(1);
	sexflag++;

	while (1) {
		lock( pnxgate );
		t = (utimer - ltimer) / NSUTICK;
		v = t * SVCLOCK;
		ltimer += t * NSUTICK;

		/*
		 * Search for process to swap into memory.
		 */
		pp2 = NULL;
		m   = 0;
		s   = 0;
		for (pp1 = procq.p_nback; pp1 != &procq; pp1 = pp1->p_nback) {

			/*
			 * Process resides in memory.
			 */
			if ( (pp1->p_flags & PFCORE) != 0 ) {
				pp1->p_sval >>= t;
				pp1->p_ival  -= t;
				if (pp1->p_ival < -30000)
					pp1->p_ival = -30000;
				continue;
			}

			/*
			 * Update swap value - high values swapped in first.
			 */
			addu( pp1->p_sval, v );
			s = 1;

			/*
			 * Process is not runnable.
			 */
			if ( pp1->p_state != PSRUN )
				continue;

			/*
			 * Calculate disk usage in Kbytes.
			 */
			s = 0;
			for ( i = 0; i < NUSEG+1; i++ )
				if ( (sp = pp1->p_segp[i]) != NULL )
					if ( (sp->s_flags & SFCORE) == 0 )
						s += sp->s_size / 1024;
			if ( s == 0 )
				s = 1;

			/*
			 * Compute importance:
			 *
			 *	swap value + response value
			 *	---------------------------
			 *	  Kbytes to be swapped in
			 */
			n = (pp1->p_sval + pp1->p_rval) / s;

			/*
			 * More important.
			 */
			if ( n > m ) {
				m = n;
				pp2 = pp1;
			}
		}
		unlock( pnxgate );

		/*
		 * No runnable processes swapped out.
		 */
		if ( pp2 == NULL ) {
			/*
			 * No processes swapped out, and KILL signal received.
			 */
			if ( (s == 0) && (SELF->p_ssig & 0x0100) )
				break;
			goto con;
		}

#ifndef	NOMONITOR
		if (swmflag)
			printf("Swapin(%p, %d)\n", pp2, pp2->p_pid);
#endif
	xxx:
		/*
		 * Try to swap process into memory.
		 */
		while ( (testcore(pp2) == 0) || (proccore(pp2) != 0) ) {

			/*
			 * Swap process out.
			 */
			procdisk(pp2);
			i   = 32767;
			pp3 = NULL;

			/*
			 * Search for process to swap out.
			 */
			lock( pnxgate );
			for (pp1=procq.p_nforw; pp1!=&procq; pp1=pp1->p_nforw){

				if ( pp1->p_flags & (PFSWIO|PFLOCK|PFKERN) )
					continue;

				/*
				 * Process is not totally memory resident.
				 */
				if ( (pp1->p_flags&PFCORE) == 0 ) {
					/*
					 * Swap segments out to disk.
					 */
					if ( procdisk(pp1) != 0 ) {
						unlock( pnxgate );
						goto xxx;
					}
					continue;
				}

				/*
				 * Process too important to swap out.
				 */
				if ((pp1->p_ival > -64) && (pp1->p_sval != 0))
					continue;

				/*
				 * Less important.
				 */
				if ( pp1->p_ival < i ) {
					i = pp1->p_ival;
					pp3 = pp1;
				}
			}
			unlock( pnxgate );

			/*
			 * No processes to swap out.
			 */
			if ( pp3 == NULL ) {
#ifndef NOMONITOR
				if (swmflag)
					printf("No one to swap out\n");
#endif
				break;
			}

			/*
			 * Process is too important to swap out.
			 */
			if ( i > 0 ) {
#ifndef NOMONITOR
				if (swmflag)
					printf("Dispatch(%p, %d)\n",
						pp3, pp3->p_pid);
#endif
				pp3->p_flags |= PFDISP;
				break;
			}
#ifndef NOMONITOR
			if (swmflag)
				printf("Swapout(%p, %d)\n", pp3, pp3->p_pid);
#endif
			/*
			 * Swap process out to disk.
			 */
			procdisk( pp3 );
		}

#ifndef NOMONITOR
		if (swmflag)
			printf("Swapdone\n");
#endif
	con:
		kcall( Ktimeout, &stimer, NSRTICK, Kwakeup, (char *)&stimer );
		sleep( (char *)&stimer, CVSWAP, IVSWAP, SVSWAP );
	}
	sexflag--;
	uexit( 1 );
}

/*
 * See if the given process may fit in core.
 */
testcore( pp )
register PROC *pp;
{
	register SEG *sp;
	register fsize_t s;
	register paddr_t s1;
	register paddr_t s2;
	register int i;

	/*
	 * Find largest segment in process.
	 */
	s = 0;
	for ( i = 0; i < NUSEG+1; i++ ) {

		if ( (sp = pp->p_segp[i]) == NULL )
			continue;

		/*
		 * Segment is memory resident.
		 */
		if ( (sp->s_flags & SFCORE) != 0 )
			continue;

		/*
		 * Largest segment so far.
		 */
		if ( sp->s_size > s )
			s = sp->s_size;
	}

	/*
	 * See if largest segment will fit in memory.
	 */
	s1 = corebot;
	sp = &segmq;
	do {
		/*
		 * Advance to next memory segment.
		 */
		sp = sp->s_forw;
		s2 = sp->s_paddr;

		/*
		 * It fits!
		 */
		if ( s2 - s1 >= s )
			return (1);

		/*
		 * Compute start of next hole.
		 */
		s1 = sp->s_paddr + sp->s_size;

	} while ( sp != &segmq );

	return( 0 );
}

/*
 * Swap all segments associated with a particular process into core.
 * The number of segments still swapped out is returned.
 */
proccore( pp )
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int n;
	register int f;

	f = pp->p_flags & PFSWAP;

	/*
	 * Try to swap in all user segments and the auxiliary segment.
	 */
	for ( n = 0, i = 0; i < NUSEG+1; i++ ) {

		if ( (sp = pp->p_segp[i]) == NULL )
			continue;

		/*
		 * Process was swapped out.
		 */
		if ( f != 0 )
			sp->s_lrefc++;

		/*
		 * Segment is disk resident - try to swap it in.
		 */
		if ( (sp->s_flags & SFCORE) == 0 )
			if ( segcore(sp) == 0 )
				n++;
	}

	/*
	 * No segments left on disk - mark process as being memory resident.
	 */
	if ( n == 0 )
		pp->p_flags |= PFCORE;

	/*
	 * Mark process as no longer being disk resident.
	 */
	pp->p_flags &= ~PFSWAP;

	return( n );
}

/*
 * Swap out all segments associated with a given process.
 */
procdisk( pp )
register PROC *pp;
{
	register SEG *sp;
	register int i;
	register int f;
	int n;

	f = pp->p_flags & PFSWAP;

	/*
	 * Mark process as no longer being memory resident BEFORE swapping.
	 */
	pp->p_flags &= ~PFCORE;

	/*
	 * Try to swap out all user segments and the auxiliary segment.
	 */
	for ( n = 0, i = 0; i < NUSEG+1; i++ ) {

		if ( (sp = pp->p_segp[i]) == NULL )
			continue;

		/*
		 * Process not already swapped out.
		 */
		if ( f == 0 )
			sp->s_lrefc--;

		/*
		 * Segment already swapped out.
		 */
		if ( (sp->s_flags & SFCORE) == 0 )
			continue;

		/*
		 * Segment no longer referenced by a memory-resident process.
		 */
		if ( (sp->s_lrefc == 0) && (segdisk(sp) != 0) )
			n++;
	}

	/*
	 * Mark process as being disk resident.
	 */
	pp->p_flags |= PFSWAP;

	return( n );
}

/*
 * Swap the given segment into core.
 * NOTE: Although swapped out, the segment may have a descriptor table entry,
 *	 and therefore have a valid s_faddr field.
 */
segcore( sp1 )
register SEG *sp1;
{
	register SEG *sp2;

	/*
	 * Lock segmentation.
	 */
	lock( seglink );

	/*
	 * Segment has been moved to memory while we waited to lock.
	 */
	if ( (sp1->s_flags & SFCORE) != 0 ) {
		unlock(seglink);
		return( 1 );
	}

	/*
	 * Allocate a memory segment sp2.
	 */
	if ((sp2 = xmalloc( sp1->s_size )) == NULL ) {
		unlock( seglink );
		return( 0 );
	}

	/*
	 * Copy the disk segment sp1 into the memory segment sp2.
	 */
	sp1->s_lrefc++;
	swapio(0, sp2->s_paddr, sp1->s_daddr, sp2->s_size );
	sp1->s_lrefc--;

	/*
	 * Remove segment sp1 from the disk queue.
	 */
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;

	/*
	 * Insert segment sp1 into memory queue replacing segment sp2.
	 */
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;

	/*
	 * Enable access to memory segment sp1.
	 */
	sp1->s_flags |= SFCORE;
	sp1->s_paddr = sp2->s_paddr;
	vremap( sp1 );

	/*
	 * Unlock segmentation.
	 */
	unlock( seglink );

	return( 1 );
}

/*
 * Swap the given segment out onto disk.
 */
segdisk( sp1 )
register SEG *sp1;
{
	register SEG *sp2;

	/*
	 * Lock segmentation.
	 */
	lock( seglink );

	/*
	 * Verify segment sp1 did not become busy while we waited to lock.
	 * IE: raw disk i/o, or shared code fork.
	 */
	if ( sp1->s_lrefc != 0 ) {
		unlock( seglink );
		return( 0 );
	}

	/*
	 * Segment has been moved to disk while we waited to lock.
	 */
	if ( (sp1->s_flags & SFCORE) == 0 ) {
		unlock(seglink);
		return( 1 );
	}

	/*
	 * Allocate a disk segment sp2.
	 */
	if ( (sp2 = xdalloc( sp1->s_size )) == NULL ) {
		unlock( seglink );
		return( 0 );
	}

	/*
	 * Disable access to memory segment sp1.
	 */
	sp1->s_flags &= ~SFCORE;
	sp1->s_daddr = sp2->s_daddr;
	vremap( sp1 );

	/*
	 * Copy the memory segment sp1 into the disk segment sp2.
	 */
	sp1->s_lrefc++;
	swapio( 1, sp1->s_paddr, sp2->s_daddr, sp1->s_size );
	sp1->s_lrefc--;

	/*
	 * Remove segment sp1 from the memory queue.
	 */
	sp1->s_back->s_forw = sp1->s_forw;
	sp1->s_forw->s_back = sp1->s_back;

	/*
	 * Insert segment sp1 into disk queue replacing segment sp2.
	 */
	sp2->s_back->s_forw = sp1;
	sp1->s_back = sp2->s_back;
	sp2->s_forw->s_back = sp1;
	sp1->s_forw = sp2->s_forw;

	/*
	 * Unlock segmentation.
	 */
	unlock( seglink );

	return( 1 );
}

/*
 * Allocate a segment on disk that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `sdalloc' except that we can't run out of
 * alloc space to allocate the segment and we allocate in high regions.
 * NOTE: descriptor table entries are not released.
 */
SEG *
xdalloc( s )
fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register daddr_t d;
	register daddr_t d1;
	register daddr_t d2;

	d  = s / BSIZE;
	d2 = swaptop;
	sp1 = &segdq;
	do {
		if ( (sp1 = sp1->s_back) != &segdq )
			d1 = sp1->s_daddr + (sp1->s_size / BSIZE);
		else
			d1 = swapbot;

		if ( d2 - d1 >= d ) {
			sp2 = &segswap;
			kclear( (char *)sp2, sizeof(SEG) );
			sp1->s_forw->s_back = sp2;
			sp2->s_forw  = sp1->s_forw;
			sp1->s_forw  = sp2;
			sp2->s_back  = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_daddr = d2 - d;
			return( sp2 );
		}

		d2 = sp1->s_daddr;

	} while ( sp1 != &segdq );

	return( NULL );
}

/*
 * Allocate a segment in memory that is `n' bytes long.
 * The `seglink' gate should be locked before this routine is called.
 * This routine is the same as `smalloc' except that we can't run out of
 * alloc space to allocate the segment.
 * NOTE: Do NOT remap virtual descriptor table entry.
 *	 This is a scratch entry, and the s_faddr field is not retained.
 */
SEG *
xmalloc( s )
register fsize_t s;
{
	register SEG *sp1;
	register SEG *sp2;
	register paddr_t s1;
	register paddr_t s2;

	s1  = corebot;
	sp1 = &segmq;
	do {
		if ( (sp1 = sp1->s_forw) != &segmq )
			s2 = sp1->s_paddr;
		else
			s2 = coretop;

		if ( s2 - s1 >= s ) {
			sp2 = &segswap;
			kclear( (char *)sp2, sizeof(SEG) );
			sp1->s_back->s_forw = sp2;
			sp2->s_back = sp1->s_back;
			sp1->s_back = sp2;
			sp2->s_forw = sp1;
			sp2->s_urefc = 1;
			sp2->s_lrefc = 1;
			sp2->s_size  = s;
			sp2->s_paddr = s1;
			return( sp2 );
		}

		s1 = sp1->s_paddr + sp1->s_size;

	} while ( sp1 != &segmq );

	return( NULL );
}
@


1.1
log
@Initial revision
@
text
@d33 3
a35 3
#include <coherent.h>
#include <proc.h>
#include <sched.h>
@
0707070064030105051004440000030000030000011777770507310745600005400000001351/newbits/kernel/USRSRC/ldrv/RCS/nonedev.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.35.11;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.25;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */

/*
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:30:54	src
 * Initial revision
 * 
 */
#include <sys/coherent.h>
#include <sys/uproc.h>
#include <errno.h>

/*
 * Non existant device.
 */
nonedev()
{
	u.u_error = ENXIO;
}
@


1.1
log
@Initial revision
@
text
@d9 1
a9 1
#include <coherent.h>
@
0707070064030105041004440000030000030000011777770507310745600005400000001150/newbits/kernel/USRSRC/ldrv/RCS/nulldev.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.35.14;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.26;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:30:57	src
 * Initial revision
 * 
 */

/*
 * Null device.
 */
nulldev()
{
}
@


1.1
log
@Initial revision
@
text
@@
0707070064030105171004440000030000030000011777770507310745600005400000005153/newbits/kernel/USRSRC/ldrv/RCS/setivec.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.35.19;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.27;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Loadable Driver - Enable/Disable Interrupts.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:31:02	src
 * Initial revision
 * 
 * 87/12/03	Allan Cornish		/usr/src/sys/ldrv/setivec.c
 * Initial version.
 */
#include <sys/coherent.h>
#include <errno.h>
#include <sys/con.h>
#include <sys/uproc.h>

/*
 * Interrupt entry points [within kernel] for loadable drivers.
 */
extern void (*ldrvint[16])();

/*
 * Interrupt handlers [within driver] for loadable drivers.
 *	ldrvics[n]:	Interrupt handler code segment.
 *	ldrvipc[n]:	Interrupt handler program counter.
 */
extern saddr_t ldrvics[16];
extern void  (*ldrvipc[16])();

setivec( level, func )
int level;
void (*func)();
{
	extern void Ksetivec();
	extern saddr_t ucs;

	u.u_error = 0;
	level &= 15;

	/*
	 * Ensure interrupt is not already in use.
	 */
	if ( (ldrvics[level] != 0) || (ldrvipc[level] != NULL) ) {
		u.u_error = EDBUSY;
		return;
	}

	/*
	 * Record interrupt function BEFORE enabling interrupt.
	 */
	ldrvipc[level] = func;
	ldrvics[level] = ucs;

	/*
	 * Attempt to enable interrupt.
	 */
	kcall( Ksetivec, level, ldrvint[level] );

	/*
	 * Interrupt is in use by a resident driver.
	 */
	if ( u.u_error ) {
		ldrvipc[level] = NULL;
		ldrvics[level] = 0;
	}
}

clrivec( level )
register int level;
{
	extern void Kclrivec();
	extern saddr_t ucs;

	level &= 15;

	/*
	 * Ensure interrupt belongs to our process.
	 */
	if ( ldrvics[level] != ucs ) {
		u.u_error = EPERM;
		return;
	}

	/*
	 * Disable interrupt.
	 */
	kcall( Kclrivec, level );

	/*
	 * Erase interrupt function AFTER disabling interrupt.
	 */
	ldrvipc[level] = NULL;
	ldrvics[level] = 0;
}
@


1.1
log
@Initial revision
@
text
@d25 1
a25 1
#include <coherent.h>
@
0707070064030105111004440000030000030000011777770507310745700005400000004264/newbits/kernel/USRSRC/ldrv/RCS/timeout.c,vhead     1.2;
branch   ;
access   ;
symbols  ;
locks    bin:1.2; strict;
comment  @ * @;


1.2
date     91.06.20.14.35.45;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.10.43.28;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@


1.2
log
@update provided by hal
@
text
@/* $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1987
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * Loadable Driver - Timed functions.
 *
 * $Log: updateprovbyha,v $
 * Revision 1.1.1.1  2019/05/29 04:56:34  root
 * coherent
 *
 * Revision 1.1	88/03/24  16:31:21	src
 * Initial revision
 * 
 * 87/12/08	Allan Cornish	/usr/src/sys/ldrv/timeout.c
 * Timed loadable driver functions now supported.
 */
#include <sys/coherent.h>

/*
 * External functions.
 */
extern void Ktimeout();
extern void Kldtimcall();
extern saddr_t getcs();

/*
 * Given a pointer to a timeout structure, `tp', call the function `f'
 * with integer argument `a' in `n' ticks of the clock. The list is
 * searched to see if the specified timeout structure is already in a
 * list, and it is removed if already there.
 * This module is specific to loadable drivers.
 */
timeout( tp, n, f, a )
register TIM * tp;
int n;
void (*f)();
int a;
{
	register int s;

	/*
	 * Cancel existing timer.
	 */
	if ( (f == NULL) || (n <= 0) ) {
		kcall( Ktimeout, tp, 0, NULL, 0 );
		return;
	}

	/*
	 * Define loadable driver interface.
	 * Kldtimcall will be invoked when timeout occurs.
	 * It will in turn invoke FP_SEL(tp->t_ldrv):4,
	 *	passing FP_OFF(tp->t_ldrv) in AX.
	 */
	s = sphi();
	FP_SEL(tp->t_ldrv) = getcs();
	FP_OFF(tp->t_ldrv) = f;
	kcall( Ktimeout, tp, n, Kldtimcall, a );
	spl(s);
}
@


1.1
log
@Initial revision
@
text
@d25 1
a25 1
#include <coherent.h>
@
0707070064030105001005550000030000030000011777770507310745700005700000001021/newbits/kernel/USRSRC/ldrv/RCS/mkstub.sh.ob,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.06.10.10.43.29;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@



1.1
log
@Initial revision
@
text
@: 'Created by Makefile - do not edit.'; set -e; ENTRY=`basename $1`;( echo ".globl ${ENTRY}_"; echo "${ENTRY}_: mov ax,\$K${ENTRY}_"; echo .byte 0x9A; echo .word xcalled; echo .word 0x0060; echo ret;)>/tmp/$$.s; as -gxo /tmp/$$.o /tmp/$$.s; mv /tmp/$$.o $1.o; rm -f /tmp/$$.s
@
0707070064030104771005550000030000030000011777770507310745700005400000001024/newbits/kernel/USRSRC/ldrv/RCS/mkstub.sh,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.10.10.43.30;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version provided by stevesf 
@



1.1
log
@Initial revision
@
text
@set -e
ENTRY=`basename $1`
(							\
	echo ".globl ${ENTRY}_";			\
	echo "${ENTRY}_: mov ax,\$K${ENTRY}_";		\
	echo .byte 0x9A;				\
	echo .word xcalled;				\
	echo .word 0x0060;				\
	echo ret;					\
) > /tmp/$$.s
as -gxo /tmp/$$.o /tmp/$$.s
mv /tmp/$$.o $1.o
rm -f /tmp/$$.s
@
0707070064030105211004440000030000030000011777770507310746000005300000002443/newbits/kernel/USRSRC/ldrv/RCS/ldconfig,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.06.20.14.34.20;  author bin;  state Exp;
branches ;
next     ;


desc
@provided by hal to use relative paths
@



1.1
log
@Initial revision
@
text
@: '$Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $'
:
:	configure a loadable driver
:
: usage: ldconfig [swap] [DRV ...]
:
BUILD=0
DEV=/tmp/dev
PATCH=""
UNDEF=""
LDMOD=""
PASS1=""

for ARG in $*
do
	case "${ARG}" in
	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "$ARG" in

	swap)
		/bin/echo "ldrv/swap: "
		ld -r -o ldrv/swap lib/ldrts0.o lib/ldswap.o lib/ldlib.a
		LDMOD=""
		;;

	*\=*)
		LDMOD="${LDMOD} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		/bin/echo "ldrv/${FILE}: "
		if /bin/test -r confdrv/${FILE}
		then
			UNDEF=""
			. confdrv/${FILE}
			/bin/ld -r -o ldrv/${FILE} lib/ldrts0.o \
				lib/ldmain.o ${UNDEF} \
				lib/ldlib.a || exit 1
			case "${LDMOD}" in
			"")	;;
			*)	/conf/patch ldrv/${FILE} ${LDMOD}
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		LDMOD=""
		;;
	esac
done
@
0707070064030111110407770000000000000000011777770507310746000004400000000000/newbits/kernel/USRSRC/ldrv/objects0707070064030114121006440000030000030000011777770507310746000004600000000176/newbits/kernel/USRSRC/ldrv/mkstub.m4define(sym, substr(basename, -2, ))dnl
	.globl	sym`_'
sym`_':	mov	ax,`$K'sym`_'
	.byte	0x9A
	.word	xcalled
	.word	0x0060
	ret
0707070064030057020407550000030000030000011777770507310746000002700000000000/newbits/kernel/USRSYS0707070064030110601006440000030000030000011777770507310746000004000000014223/newbits/kernel/USRSYS/Makefile# $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
#
# Makefile for ibm specific coherent sources and coherent images.
#
# Requires environment variables
#	USRSYS (e.g. /usr/sys)
#	USRSRC (e.g. /usr/src/sys)
#	KOBJ (e.g. /usr/kobj)
#
# $Log: updateprovbyha,v $
# Revision 1.1.1.1  2019/05/29 04:56:34  root
# coherent
#
# Revision 1.6  91/07/24  08:05:32  bin
# update prov by hal
#
# Revision 1.3	89/06/30  16:26:39 	src
# Bug:	Lack of DMA lock resulted in failed transfers between SCSI drive
# 	and floppy disk.
# Fix:	Added dma lock routines to insure single DMA transfer. (JHB)
# 
# Revision 1.1	88/03/24  17:33:15	src
# Initial revision
# 

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

# Source directories
COHSRC=$(USRSRC)/coh
DRVSRC=$(USRSRC)/i8086/drv
I86SRC=$(USRSRC)/i8086/src
IBMATSRC=$(USRSRC)/i8086/ibm_at
KERSRC=$(USRSRC)/ker
TTYSRC=$(USRSRC)/ttydrv

# Library directory
DRVLIB=$(USRSYS)/lib

# Compiler stuff
CC=exec /bin/cc
CFLAGS=

HERE=	$(KOBJ)/md2.o \
	$(KOBJ)/dmac.o \
	$(KOBJ)/pccon.o \
	$(KOBJ)/console.o \
	$(KOBJ)/dmareq.o \
	$(KOBJ)/mmu.o \
	$(KOBJ)/support.o

DOTDOT=	$(KOBJ)/alloc.o \
	$(KOBJ)/as1.o \
	$(KOBJ)/bio.o \
	$(KOBJ)/clist.o \
	$(KOBJ)/clock.o \
	$(KOBJ)/ct.o \
	$(KOBJ)/defer.o \
	$(KOBJ)/dmalock.o	\
	$(KOBJ)/exec.o \
	$(KOBJ)/fd.o \
	$(KOBJ)/fs1.o $(KOBJ)/fs2.o $(KOBJ)/fs3.o \
	$(KOBJ)/krunch.o \
	$(KOBJ)/ld.o $(KOBJ)/ldas.o \
	$(KOBJ)/main.o \
	$(KOBJ)/md1.o \
	$(KOBJ)/misc.o \
	$(KOBJ)/mmain.o \
	$(KOBJ)/null.o \
	$(KOBJ)/pipe.o \
	$(KOBJ)/poll.o \
	$(KOBJ)/printf.o \
	$(KOBJ)/proc.o \
	$(KOBJ)/seg.o \
	$(KOBJ)/sig.o \
	$(KOBJ)/sys1.o $(KOBJ)/sys2.o $(KOBJ)/sys3.o \
	$(KOBJ)/tab.o \
	$(KOBJ)/timeout.o \
	$(KOBJ)/trap.o \
	$(KOBJ)/var.o

kernel:	$(KOBJ) $(USRSYS)/atkernel.o $(DRVLIB)/support.a $(DRVLIB)/tty.a
	@exec /bin/sync

shrink:
	rm -f $(KOBJ)/* $(KOBJ)/* $(KOBJ)/*

$(KOBJ)/pccon.o: \
	$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
				$(SYSINC)/machine.h $(SYSINC)/param.h \
				$(SYSINC)/fun.h \
	$(SYSINC)/con.h		\
	$(USRINC)/mtype.h	\
	$(SYSINC)/stat.h	\
	$(DRVSRC)/pccon.c
	$(CC) $(CFLAGS) -c -o $@ $(DRVSRC)/pccon.c

$(KOBJ)/console.o:	\
	$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
				$(SYSINC)/machine.h $(SYSINC)/param.h \
				$(SYSINC)/fun.h \
	$(SYSINC)/con.h		\
	$(SYSINC)/inode.h	\
	$(SYSINC)/io.h		\
	$(SYSINC)/stat.h	\
	$(DRVSRC)/console.c
	$(CC) $(CFLAGS) -c -o $@ $(DRVSRC)/console.c

$(KOBJ)/dmareq.o:	\
	$(SYSINC)/buf.h		\
	$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
				$(SYSINC)/machine.h $(SYSINC)/param.h \
				$(SYSINC)/fun.h \
	$(SYSINC)/con.h		\
	$(SYSINC)/dmac.h	\
	$(USRINC)/errno.h	\
	$(SYSINC)/io.h		\
	$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
	$(SYSINC)/sched.h	\
	$(SYSINC)/seg.h		\
	$(SYSINC)/stat.h	\
	$(SYSINC)/uproc.h	\
	$(DRVSRC)/dmareq.c
	$(CC) $(CFLAGS) -c -o $@ $(DRVSRC)/dmareq.c

$(USRSYS)/atkernel.o: $(KOBJ)/as2.obj $(HERE) $(DOTDOT)
	exec /bin/ld -r -o $@ $<

$(KOBJ)/as2.obj: $(IBMATSRC)/as2.s
	exec as -go $@ $<

$(KOBJ)/dmac.o: $(IBMATSRC)/dmac.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(KOBJ)/dump.o: $(IBMATSRC)/dump.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(KOBJ)/md2.o: $(IBMATSRC)/md2.c
	$(CC) $(CFLAGS) -c -o $@ $<

# Define REAL_MODE if real mode is also required
$(KOBJ)/mmu.o: $(IBMATSRC)/mmu.c
	$(CC) $(CFLAGS) -DREAL_MODE -c -o $@ $<

$(KOBJ)/support.o: $(I86SRC)/support.c
	$(CC) $(CFLAGS) -c -o $@ $<

# this stuff was in the /usr/src/sys/i8086 Makefile before 90/08/08
C86FLAGS=-c -DNOMONITOR=1
#
$(KOBJ):
	mkdir $(KOBJ)

$(KOBJ)/alloc.o: $(COHSRC)/alloc.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/as1.o: $(I86SRC)/as1.s
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/bio.o: $(COHSRC)/bio.c
	$(CC) $(C86FLAGS) -DREADAHEAD=0 -o $@ $<

# Clists are assembly source on i8086
$(KOBJ)/clist.o: $(I86SRC)/clist.s $(SYSINC)/const.h
	/lib/cpp -E -Isys -o clist.i $(I86SRC)/clist.s
	as -go $@ clist.i
	rm clist.i

$(KOBJ)/clock.o: $(COHSRC)/clock.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/ct.o: $(TTYSRC)/ct.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/defer.o: $(I86SRC)/defer.s
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/dmalock.o: $(I86SRC)/dmalock.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/exec.o: $(I86SRC)/exec.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/fd.o: $(COHSRC)/fd.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/fs1.o: $(COHSRC)/fs1.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/fs2.o: $(COHSRC)/fs2.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/fs3.o: $(COHSRC)/fs3.c
	$(CC) $(C86FLAGS) -DTINY=1 -o $@ $<

$(KOBJ)/krunch.o: $(I86SRC)/krunch.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/ld.o: $(I86SRC)/ld.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/ldas.o: $(I86SRC)/ldas.s
	as -gxo $@ $<

$(KOBJ)/main.o: $(USRSYS)/version $(COHSRC)/main.c
	$(CC) $(C86FLAGS) `$(USRSYS)/version` -o $@ $(COHSRC)/main.c

$(KOBJ)/md1.o: $(I86SRC)/md1.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/misc.o: $(COHSRC)/misc.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/mmain.o: $(I86SRC)/mmain.c $(SYSINC)/const.h
	$(CC) $(C86FLAGS) -o $@ $(I86SRC)/mmain.c

$(KOBJ)/null.o: $(COHSRC)/null.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/pipe.o: $(COHSRC)/pipe.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/poll.o: $(COHSRC)/poll.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/printf.o: $(COHSRC)/printf.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/proc.o: $(COHSRC)/proc.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/seg.o: $(COHSRC)/seg.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/sig.o: $(COHSRC)/sig.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/swap.o: $(KERSRC)/swap.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/elog.o: $(KERSRC)/elog.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/sys1.o: $(COHSRC)/sys1.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/sys2.o: $(COHSRC)/sys2.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/sys3.o: $(COHSRC)/sys3.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/tab.o: $(I86SRC)/tab.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/timeout.o: $(COHSRC)/timeout.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/trap.o: $(I86SRC)/trap.c
	$(CC) $(C86FLAGS) -o $@ $<

$(KOBJ)/var.o: $(COHSRC)/var.c
	$(CC) $(C86FLAGS) -o $@ $<

# Additional libraries searched when "config" runs.

$(DRVLIB)/support.a:	$(KOBJ)/cs_sel.o $(KOBJ)/clocked.o
	rm -f $@
	ar rc $@ $<

$(KOBJ)/cs_sel.o: $(I86SRC)/cs_sel.s
	as -gxo $@ $<

$(KOBJ)/clocked.o: $(I86SRC)/clocked.c
	$(CC) $(CFLAGS) -c -o $@ $<

$(DRVLIB)/tty.a:	$(KOBJ)/tty.o
	rm -f $@
	ar rc $@ $<

$(KOBJ)/tty.o: $(TTYSRC)/tty.c
	$(CC) $(CFLAGS) -c -o $@ $<
0707070064030112171007550000030000030000011777770507310746200003300000003532/newbits/kernel/USRSYS/bld:
:  Build a Coherent executable with a host adapter driver linked in.
:
if [ $USRSYS ]
then
if [ $USRSRC ]
then
if [ $KOBJ ]
then
if [ $LOBJ ]
then
DRIVERS="rm fl lp mm"
COH_TYPE=fl
HD=""
KB=nkb
for ARG
do
	case $ARG in
	at|aha|ss)
		HD=$ARG
		COH_TYPE=$ARG
		;;
	kb|nkb|gkb)
		KB=$ARG
		;;
	*)		echo "Usage: $0 { at | ss | aha } { kb | nkb | gkb }"
			exit 0
			;;
	esac
done
DRIVERS="$KB $HD $DRIVERS"
echo "Kernel:    /coh.$COH_TYPE"
echo "Version:   `version ID`"
echo "Devices:   $DRIVERS"

: default root/pipe device
BOOTDEV="fva0"
echo "Default root/pipe device is $BOOTDEV."

( cd $USRSRC/ldrv; make ld_support )			|| exit 1
( cd $USRSRC/i8086/drv; make -f Mf.mwc install )	|| exit 1
( make kernel )						|| exit 1
./config.mwc ibm-at $DRIVERS root=$BOOTDEV			|| exit 1
cp coherent /tmp/coh					|| exit 1
strip /tmp/coh						|| exit 1
set `ls -s /tmp/coh`
SIZE=$1
rm /tmp/coh						|| exit 1
echo "Coherent bootable limit is 138 blocks.  This kernel is $SIZE"
if [ $SIZE -gt 138 ] ;then
	echo 
	echo Your Coherent image exceeds the bootable limit of 138 blocks
	echo by `expr $SIZE - 138` 'block(s).'  You will need to decrease the
	echo size of your kernel in order to make it bootable.
	echo
	echo We suggest removing some of the non critical drivers from the
	echo default list of drivers linked into Coherent.  These additional
	echo drivers may then be linked as loadable drivers using the
	echo ldconfig script located in this directory.
fi
mv coherent /coh.$COH_TYPE
chown sys /coh.$COH_TYPE
chgrp sys /coh.$COH_TYPE
chmod 400 /coh.$COH_TYPE
echo "New kernel in /coh.$COH_TYPE"
ls -l /coh.$COH_TYPE
# the rest is error exits
else
echo "Error - LOBJ not defined - (e.g. /usr/lobj)"
fi
else
echo "Error - KOBJ not defined - (e.g. /usr/kobj)"
fi
else
echo "Error - USRSRC not defined - (e.g. /usr/src/sys)"
fi
else
echo "Error - USRSYS not defined - (e.g. /usr/sys)"
fi
0707070064030056771005440000030000030000011777770507310746200003600000013733/newbits/kernel/USRSYS/config:
:	configure a Coherent kernel for the AT
:
: usage: config [help]
:	 config [stand=fha0]
:	 config [stand=fva0]
:	 config [stand=fha0] [standard] [root=DRV] [DRV ...]
:	 config [stand=fva0] [standard] [root=DRV] [DRV ...]

:	initialize variables
:
ATSTANDARD=" fl lp mm "
ATKERNEL=atkernel.o

STANDARD="${ATSTANDARD}"
KERNEL="${ATKERNEL}"
LIBS="lib/tty.a lib/support.a"
BUILD=0
DEV=/tmp/dev
PASS1=""
PASS2=""
UNDEF=""
PATCH=""
ROOTDEV=""
INSTALL=""

case "$#" in
0)	/bin/echo
	/bin/echo	"The following can be used as arguments to config:"
	/bin/echo
	/bin/cat doc/*
	exit 0
	;;
esac

for ARG in $*
do
	case "${ARG}" in
	help)
		/bin/echo
		/bin/echo "The following can be used as arguments to config:"
		/bin/echo
		/bin/cat doc/*
		exit 0
		;;
	ibm-at)
		STANDARD="${ATSTANDARD}"
		KERNEL="${ATKERNEL}"
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "${ARG}" in
	standard)
		PASS2="${STANDARD} ${PASS2}"
		;;
	stand\=fha0)
		/etc/umount /dev/fha0 2> /dev/null
		echo -n "Insert 5.25 high capacity floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fha0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fha0 2400		|| exit 1
		/bin/cp /conf/boot.fha /dev/fha0	|| exit 1
		/etc/mount /dev/fha0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,14)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,14)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fha0 ; /bin/df /dev/fha0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	stand\=fva0)
		/etc/umount /dev/fva0 2> /dev/null
		echo -n "Insert high density 3.5 floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fva0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fva0 2880		|| exit 1
		/bin/cp /conf/boot.fva /dev/fva0	|| exit 1
		/etc/mount /dev/fva0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,15)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,15)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fva0 ; /bin/df /dev/fva0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS2="${PASS2} ${ARG}"
		;;
	esac
done

:	get the proper driver information
:

for ARG in ${PASS2}
do
	case "$ARG" in

	root\=fva0)
		ROOTDEV="makedev(4,15)"
		. confdrv/fl
		;;
	root\=fha0)
		ROOTDEV="makedev(4,14)"
		. confdrv/fl
		;;
	root\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			ROOTDEV="${MAKEDEV}"
/bin/echo "'confdrv/${FILE}' executing"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	swap)
		;;

	swap\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			if [ -d "${DEV-/dev}" ]
			then
				/bin/ln -f ${DEV-/dev}/${ARG} ${DEV-/dev}/swap
			fi
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			PATCH="${PATCH} swapdev_=${MAKEDEV}"
			/bin/echo "Swap device will be ${DEV-/dev}/${ARG}"
			/bin/echo "See documentation before enabling"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	*\=*)
		PATCH="${PATCH} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			case "${ROOTDEV}" in
			?*)	;;
			*)	ROOTDEV="${MAKEDEV}" ;;
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;
	esac
done
ROOTDEV="${ROOTDEV-makedev(4,14)}"

:	include stub drivers
:
UNDEF="${UNDEF} ${LIBS}"

:	make the proper root and pipe devices
:
PATCH="${PATCH} rootdev_=${ROOTDEV} pipedev_=${ROOTDEV}"

set -ex
:
:	create a kernel with the desired device drivers
:
/bin/ld -i -x -o coherent ${KERNEL} ${UNDEF} -lc
:
:	enable the desired device drivers
:
/conf/patch coherent ALLSIZE_=16384 NBUF_=32 NCLIST_=24 ${PATCH}
/bin/chmod 644 coherent
/bin/chown sys coherent
/bin/chgrp sys coherent
/bin/sync
:
eval ${INSTALL}
0707070064030056761005440000030000030000011777770507310746400004000000001721/newbits/kernel/USRSYS/ldconfig:
:	configure a loadable driver
:
: usage: ldconfig [swap] [DRV ...]
:
BUILD=0
DEV=/dev
PATCH=""
UNDEF=""
LDMOD=""
PASS1=""

for ARG in $*
do
	case "${ARG}" in
	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "$ARG" in

	swap)
		/bin/echo "ldrv/swap: "
		ld -r -o ldrv/swap lib/ldrts0.o lib/ldswap.o lib/ldlib.a
		LDMOD=""
		;;

	*\=*)
		LDMOD="${LDMOD} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		/bin/echo "ldrv/${FILE}: "
		if /bin/test -r confdrv/${FILE}
		then
			UNDEF=""
			. confdrv/${FILE}
			/bin/ld -r -o ldrv/${FILE} lib/ldrts0.o \
				lib/ldmain.o ${UNDEF} \
				lib/ldlib.a || exit 1
			case "${LDMOD}" in
			"")	;;
			*)	/conf/patch ldrv/${FILE} ${LDMOD}
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		LDMOD=""
		;;
	esac
done
0707070064030110561007550000030000030000011777770507310746400003700000000250/newbits/kernel/USRSYS/versionversion=1
release=2
revision=0.DK
arg=${1-foo}
if [ $arg = "ID" ]
then
	echo "$version.$release.$revision"
else
	echo -n '-DVERSION="'$version.$release.$revision'"'
fi
0707070064030055230407550000030000030000011777770507310746500003300000000000/newbits/kernel/USRSYS/RCS0707070064030103141004440000030000030000011777770507310746500004600000027602/newbits/kernel/USRSYS/RCS/Makefile,vhead     1.6;
branch   ;
access   ;
symbols  ;
locks    bin:1.6;
comment  @@;


1.6
date     91.07.24.08.05.32;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.07.15.14.06.55;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.06.20.14.24.40;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.18.07.52.10;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.43.51;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.15.04;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.6
log
@update prov by hal
@
text
@# $Header: /var/lib/cvsd/repos/coherent/coherent/a/usr/src/updateprovbyha,v 1.1.1.1 2019/05/29 04:56:34 root Exp $
#
# Makefile for ibm specific coherent sources and coherent images.
#
# Requires environment variables
#	USRSYS (e.g. /usr/sys)
#	USRSRC (e.g. /usr/src/sys)
#	KOBJ (e.g. /usr/kobj)
#
# $Log: updateprovbyha,v $
# Revision 1.1.1.1  2019/05/29 04:56:34  root
# coherent
#
# Revision 1.3	89/06/30  16:26:39 	src
# Bug:	Lack of DMA lock resulted in failed transfers between SCSI drive
# 	and floppy disk.
# Fix:	Added dma lock routines to insure single DMA transfer. (JHB)
# 
# Revision 1.1	88/03/24  17:33:15	src
# Initial revision
# 

# Include directories
USRINC=/usr/include
SYSINC=/usr/include/sys

# Source directories
COHSRC=$(USRSRC)/coh
DRVSRC=$(USRSRC)/i8086/drv
I86SRC=$(USRSRC)/i8086/src
IBMATSRC=$(USRSRC)/i8086/ibm_at
KERSRC=$(USRSRC)/ker
TTYSRC=$(USRSRC)/ttydrv

# Library directory
DRVLIB=$(USRSYS)/lib

# Compiler stuff
CC=exec /bin/cc
CFLAGS=

HERE=	$(KOBJ)/md2.o \
	$(KOBJ)/dmac.o \
	$(KOBJ)/pccon.o \
	$(KOBJ)/console.o \
	$(KOBJ)/dmareq.o \
	$(KOBJ)/mmu.o \
	$(KOBJ)/support.o

DOTDOT=	$(KOBJ)/alloc.o \
	$(KOBJ)/as1.o \
	$(KOBJ)/bio.o \
	$(KOBJ)/clist.o \
	$(KOBJ)/clock.o \
	$(KOBJ)/ct.o \
	$(KOBJ)/defer.o \
	$(KOBJ)/dmalock.o	\
	$(KOBJ)/exec.o \
	$(KOBJ)/fd.o \
	$(KOBJ)/fs1.o $(KOBJ)/fs2.o $(KOBJ)/fs3.o \
	$(KOBJ)/krunch.o \
	$(KOBJ)/ld.o $(KOBJ)/ldas.o \
	$(KOBJ)/main.o \
	$(KOBJ)/md1.o \
	$(KOBJ)/misc.o \
	$(KOBJ)/mmain.o \
	$(KOBJ)/null.o \
	$(KOBJ)/pipe.o \
	$(KOBJ)/poll.o \
	$(KOBJ)/printf.o \
	$(KOBJ)/proc.o \
	$(KOBJ)/seg.o \
	$(KOBJ)/sig.o \
	$(KOBJ)/sys1.o $(KOBJ)/sys2.o $(KOBJ)/sys3.o \
	$(KOBJ)/tab.o \
	$(KOBJ)/timeout.o \
	$(KOBJ)/trap.o \
	$(KOBJ)/var.o

kernel:	$(KOBJ) $(USRSYS)/atkernel.o $(DRVLIB)/support.a $(DRVLIB)/tty.a
	@@exec /bin/sync

shrink:
	rm -f $(KOBJ)/* $(KOBJ)/* $(KOBJ)/*

$(KOBJ)/pccon.o: \
	$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
				$(SYSINC)/machine.h $(SYSINC)/param.h \
				$(SYSINC)/fun.h \
	$(SYSINC)/con.h		\
	$(USRINC)/mtype.h	\
	$(SYSINC)/stat.h	\
	$(DRVSRC)/pccon.c
	$(CC) $(CFLAGS) -c -o $@@ $(DRVSRC)/pccon.c

$(KOBJ)/console.o:	\
	$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
				$(SYSINC)/machine.h $(SYSINC)/param.h \
				$(SYSINC)/fun.h \
	$(SYSINC)/con.h		\
	$(SYSINC)/inode.h	\
	$(SYSINC)/io.h		\
	$(SYSINC)/stat.h	\
	$(DRVSRC)/console.c
	$(CC) $(CFLAGS) -c -o $@@ $(DRVSRC)/console.c

$(KOBJ)/dmareq.o:	\
	$(SYSINC)/buf.h		\
	$(SYSINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
				$(SYSINC)/machine.h $(SYSINC)/param.h \
				$(SYSINC)/fun.h \
	$(SYSINC)/con.h		\
	$(SYSINC)/dmac.h	\
	$(USRINC)/errno.h	\
	$(SYSINC)/io.h		\
	$(SYSINC)/proc.h	$(SYSINC)/types.h $(SYSINC)/poll.h \
	$(SYSINC)/sched.h	\
	$(SYSINC)/seg.h		\
	$(SYSINC)/stat.h	\
	$(SYSINC)/uproc.h	\
	$(DRVSRC)/dmareq.c
	$(CC) $(CFLAGS) -c -o $@@ $(DRVSRC)/dmareq.c

$(USRSYS)/atkernel.o: $(KOBJ)/as2.obj $(HERE) $(DOTDOT)
	exec /bin/ld -r -o $@@ $<

$(KOBJ)/as2.obj: $(IBMATSRC)/as2.s
	exec as -go $@@ $<

$(KOBJ)/dmac.o: $(IBMATSRC)/dmac.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(KOBJ)/dump.o: $(IBMATSRC)/dump.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(KOBJ)/md2.o: $(IBMATSRC)/md2.c
	$(CC) $(CFLAGS) -c -o $@@ $<

# Define REAL_MODE if real mode is also required
$(KOBJ)/mmu.o: $(IBMATSRC)/mmu.c
	$(CC) $(CFLAGS) -DREAL_MODE -c -o $@@ $<

$(KOBJ)/support.o: $(I86SRC)/support.c
	$(CC) $(CFLAGS) -c -o $@@ $<

# this stuff was in the /usr/src/sys/i8086 Makefile before 90/08/08
C86FLAGS=-c -DNOMONITOR=1
#
$(KOBJ):
	mkdir $(KOBJ)

$(KOBJ)/alloc.o: $(COHSRC)/alloc.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/as1.o: $(I86SRC)/as1.s
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/bio.o: $(COHSRC)/bio.c
	$(CC) $(C86FLAGS) -DREADAHEAD=0 -o $@@ $<

# Clists are assembly source on i8086
$(KOBJ)/clist.o: $(I86SRC)/clist.s $(SYSINC)/const.h
	/lib/cpp -E -Isys -o clist.i $(I86SRC)/clist.s
	as -go $@@ clist.i
	rm clist.i

$(KOBJ)/clock.o: $(COHSRC)/clock.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/ct.o: $(TTYSRC)/ct.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/defer.o: $(I86SRC)/defer.s
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/dmalock.o: $(I86SRC)/dmalock.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/exec.o: $(I86SRC)/exec.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/fd.o: $(COHSRC)/fd.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/fs1.o: $(COHSRC)/fs1.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/fs2.o: $(COHSRC)/fs2.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/fs3.o: $(COHSRC)/fs3.c
	$(CC) $(C86FLAGS) -DTINY=1 -o $@@ $<

$(KOBJ)/krunch.o: $(I86SRC)/krunch.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/ld.o: $(I86SRC)/ld.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/ldas.o: $(I86SRC)/ldas.s
	as -gxo $@@ $<

$(KOBJ)/main.o: $(USRSYS)/version $(COHSRC)/main.c
	$(CC) $(C86FLAGS) `$(USRSYS)/version` -o $@@ $(COHSRC)/main.c

$(KOBJ)/md1.o: $(I86SRC)/md1.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/misc.o: $(COHSRC)/misc.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/mmain.o: $(I86SRC)/mmain.c $(SYSINC)/const.h
	$(CC) $(C86FLAGS) -o $@@ $(I86SRC)/mmain.c

$(KOBJ)/null.o: $(COHSRC)/null.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/pipe.o: $(COHSRC)/pipe.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/poll.o: $(COHSRC)/poll.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/printf.o: $(COHSRC)/printf.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/proc.o: $(COHSRC)/proc.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/seg.o: $(COHSRC)/seg.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/sig.o: $(COHSRC)/sig.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/swap.o: $(KERSRC)/swap.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/elog.o: $(KERSRC)/elog.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/sys1.o: $(COHSRC)/sys1.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/sys2.o: $(COHSRC)/sys2.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/sys3.o: $(COHSRC)/sys3.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/tab.o: $(I86SRC)/tab.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/timeout.o: $(COHSRC)/timeout.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/trap.o: $(I86SRC)/trap.c
	$(CC) $(C86FLAGS) -o $@@ $<

$(KOBJ)/var.o: $(COHSRC)/var.c
	$(CC) $(C86FLAGS) -o $@@ $<

# Additional libraries searched when "config" runs.

$(DRVLIB)/support.a:	$(KOBJ)/cs_sel.o $(KOBJ)/clocked.o
	rm -f $@@
	ar rc $@@ $<

$(KOBJ)/cs_sel.o: $(I86SRC)/cs_sel.s
	as -gxo $@@ $<

$(KOBJ)/clocked.o: $(I86SRC)/clocked.c
	$(CC) $(CFLAGS) -c -o $@@ $<

$(DRVLIB)/tty.a:	$(KOBJ)/tty.o
	rm -f $@@
	ar rc $@@ $<

$(KOBJ)/tty.o: $(TTYSRC)/tty.c
	$(CC) $(CFLAGS) -c -o $@@ $<
@


1.5
log
@update prov. by hal (moves objects to relocatable directories)
@
text
@d8 1
a8 1
#	KOBJ (e.g. /tmp/kobj)
@


1.4
log
@another hal update
@
text
@d5 5
a31 6
# Object directories
I86OBJ=$(USRSRC)/i8086/objects
DRVOBJ=$(USRSRC)/i8086/drv/objects
SRCOBJ=$(USRSRC)/i8086/src/objects
IBMATOBJ=$(USRSRC)/i8086/ibm_at/objects

d39 7
a45 7
HERE=	$(IBMATOBJ)/md2.o \
	$(IBMATOBJ)/dmac.o \
	$(DRVOBJ)/pccon.o \
	$(DRVOBJ)/console.o \
	$(DRVOBJ)/dmareq.o \
	$(IBMATOBJ)/mmu.o \
	$(SRCOBJ)/support.o
d47 29
a75 29
DOTDOT=	$(I86OBJ)/alloc.o \
	$(I86OBJ)/as1.o \
	$(I86OBJ)/bio.o \
	$(I86OBJ)/clist.o \
	$(I86OBJ)/clock.o \
	$(I86OBJ)/ct.o \
	$(I86OBJ)/defer.o \
	$(I86OBJ)/dmalock.o	\
	$(I86OBJ)/exec.o \
	$(I86OBJ)/fd.o \
	$(I86OBJ)/fs1.o $(I86OBJ)/fs2.o $(I86OBJ)/fs3.o \
	$(I86OBJ)/krunch.o \
	$(I86OBJ)/ld.o $(I86OBJ)/ldas.o \
	$(I86OBJ)/main.o \
	$(I86OBJ)/md1.o \
	$(I86OBJ)/misc.o \
	$(I86OBJ)/mmain.o \
	$(I86OBJ)/null.o \
	$(I86OBJ)/pipe.o \
	$(I86OBJ)/poll.o \
	$(I86OBJ)/printf.o \
	$(I86OBJ)/proc.o \
	$(I86OBJ)/seg.o \
	$(I86OBJ)/sig.o \
	$(I86OBJ)/sys1.o $(I86OBJ)/sys2.o $(I86OBJ)/sys3.o \
	$(I86OBJ)/tab.o \
	$(I86OBJ)/timeout.o \
	$(I86OBJ)/trap.o \
	$(I86OBJ)/var.o
d77 1
a77 1
kernel:	$(IBMATOBJ) $(USRSYS)/atkernel.o $(DRVLIB)/support.a $(DRVLIB)/tty.a
d81 1
a81 1
	rm -f $(IBMATOBJ)/* $(I86OBJ)/* $(DRVOBJ)/*
d83 1
a83 4
$(IBMATOBJ):
	mkdir $(IBMATOBJ)

$(DRVOBJ)/pccon.o: \
d93 1
a93 1
$(DRVOBJ)/console.o:	\
d104 1
a104 1
$(DRVOBJ)/dmareq.o:	\
d121 1
a121 1
$(USRSYS)/atkernel.o: $(IBMATOBJ)/as2.obj $(HERE) $(DOTDOT)
d124 1
a124 1
$(IBMATOBJ)/as2.obj: $(IBMATSRC)/as2.s
d127 1
a127 1
$(IBMATOBJ)/dmac.o: $(IBMATSRC)/dmac.c
d130 1
a130 1
$(IBMATOBJ)/dump.o: $(IBMATSRC)/dump.c
d133 1
a133 1
$(IBMATOBJ)/md2.o: $(IBMATSRC)/md2.c
d137 1
a137 1
$(IBMATOBJ)/mmu.o: $(IBMATSRC)/mmu.c
d140 1
a140 1
$(SRCOBJ)/support.o: $(I86SRC)/support.c
d146 2
a147 2
$(I86OBJ):
	mkdir $(I86OBJ)
d149 1
a149 1
$(I86OBJ)/alloc.o: $(COHSRC)/alloc.c
d152 1
a152 1
$(I86OBJ)/as1.o: $(I86SRC)/as1.s
d155 1
a155 1
$(I86OBJ)/bio.o: $(COHSRC)/bio.c
d159 1
a159 1
$(I86OBJ)/clist.o: $(I86SRC)/clist.s $(SYSINC)/const.h
d164 1
a164 1
$(I86OBJ)/clock.o: $(COHSRC)/clock.c
d167 1
a167 1
$(I86OBJ)/ct.o: $(TTYSRC)/ct.c
d170 1
a170 1
$(I86OBJ)/defer.o: $(I86SRC)/defer.s
d173 1
a173 1
$(I86OBJ)/dmalock.o: $(I86SRC)/dmalock.c
d176 1
a176 1
$(I86OBJ)/exec.o: $(I86SRC)/exec.c
d179 1
a179 1
$(I86OBJ)/fd.o: $(COHSRC)/fd.c
d182 1
a182 1
$(I86OBJ)/fs1.o: $(COHSRC)/fs1.c
d185 1
a185 1
$(I86OBJ)/fs2.o: $(COHSRC)/fs2.c
d188 1
a188 1
$(I86OBJ)/fs3.o: $(COHSRC)/fs3.c
d191 1
a191 1
$(I86OBJ)/krunch.o: $(I86SRC)/krunch.c
d194 1
a194 1
$(I86OBJ)/ld.o: $(I86SRC)/ld.c
d197 1
a197 1
$(I86OBJ)/ldas.o: $(I86SRC)/ldas.s
d200 1
a200 1
$(I86OBJ)/main.o: $(USRSYS)/version $(COHSRC)/main.c
d203 1
a203 1
$(I86OBJ)/md1.o: $(I86SRC)/md1.c
d206 1
a206 1
$(I86OBJ)/misc.o: $(COHSRC)/misc.c
d209 1
a209 1
$(I86OBJ)/mmain.o: $(I86SRC)/mmain.c $(SYSINC)/const.h
d212 1
a212 1
$(I86OBJ)/null.o: $(COHSRC)/null.c
d215 1
a215 1
$(I86OBJ)/pipe.o: $(COHSRC)/pipe.c
d218 1
a218 1
$(I86OBJ)/poll.o: $(COHSRC)/poll.c
d221 1
a221 1
$(I86OBJ)/printf.o: $(COHSRC)/printf.c
d224 1
a224 1
$(I86OBJ)/proc.o: $(COHSRC)/proc.c
d227 1
a227 1
$(I86OBJ)/seg.o: $(COHSRC)/seg.c
d230 1
a230 1
$(I86OBJ)/sig.o: $(COHSRC)/sig.c
d233 1
a233 1
$(I86OBJ)/swap.o: $(KERSRC)/swap.c
d236 1
a236 1
$(I86OBJ)/elog.o: $(KERSRC)/elog.c
d239 1
a239 1
$(I86OBJ)/sys1.o: $(COHSRC)/sys1.c
d242 1
a242 1
$(I86OBJ)/sys2.o: $(COHSRC)/sys2.c
d245 1
a245 1
$(I86OBJ)/sys3.o: $(COHSRC)/sys3.c
d248 1
a248 1
$(I86OBJ)/tab.o: $(I86SRC)/tab.c
d251 1
a251 1
$(I86OBJ)/timeout.o: $(COHSRC)/timeout.c
d254 1
a254 1
$(I86OBJ)/trap.o: $(I86SRC)/trap.c
d257 1
a257 1
$(I86OBJ)/var.o: $(COHSRC)/var.c
d262 1
a262 1
$(DRVLIB)/support.a:	$(SRCOBJ)/cs_sel.o $(SRCOBJ)/clocked.o
d266 1
a266 1
$(SRCOBJ)/cs_sel.o: $(I86SRC)/cs_sel.s
d269 1
a269 1
$(SRCOBJ)/clocked.o: $(I86SRC)/clocked.c
d272 1
a272 1
$(DRVLIB)/tty.a:	$(DRVOBJ)/tty.o
d276 1
a276 1
$(DRVOBJ)/tty.o: $(TTYSRC)/tty.c
@


1.3
log
@provided by hal
@
text
@a17 2
KERINC=/usr/src/sys/sys
DRVINC=/usr/src/sys/i8086/sys
d38 1
a38 1
CFLAGS= -I$(DRVINC) -I$(KERINC) -I$(SYSINC)
d88 1
a88 1
	$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d98 1
a98 1
	$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d110 1
a110 1
	$(KERINC)/coherent.h	$(SYSINC)/types.h $(SYSINC)/timeout.h \
d114 1
a114 1
	$(DRVINC)/dmac.h	\
d148 1
a148 1
C86FLAGS=-c -DNOMONITOR=1 -I$(DRVINC) -I$(KERINC) -I$(SYSINC)
@


1.2
log
@new version provided by hal to handle environmental variable
for src box and to allow generic copies of this source to be distributed
with relative paths.
@
text
@@


1.1
log
@Initial revision
@
text
@a14 2
USRSYS=/usr/sys

a19 1
USSINC=/usr/src/sys
d22 6
a27 6
COHSRC=/usr/src/sys/coh
DRVSRC=/usr/src/sys/i8086/drv
I86SRC=/usr/src/sys/i8086/src
IBMATSRC=/usr/src/sys/i8086/ibm_at
KERSRC=/usr/src/sys/ker
TTYSRC=/usr/src/sys/ttydrv
d30 4
a33 4
I86OBJ=/usr/src/sys/i8086/objects
DRVOBJ=/usr/src/sys/i8086/drv/objects
SRCOBJ=/usr/src/sys/i8086/src/objects
IBMATOBJ=/usr/src/sys/i8086/ibm_at/objects
d36 1
a36 1
DRVLIB=/usr/sys/lib
d150 1
a150 1
C86FLAGS=-c -DNOMONITOR=1 -I$(DRVINC) -I$(KERINC) -I$(SYSINC) -I$(USSINC)
@
0707070064030054761005550000030000030000011777770507310746700004100000000422/newbits/kernel/USRSYS/RCS/RCS,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.15.08;  author bin;  state Exp;
branches ;
next	;


desc
@
@



1.1
log
@Initial revision
@
text
@ .&..#,RCS,-,RCSnew00318cGMakefile,v@
0707070064030106221005550000030000030000011777770507310747000004100000010404/newbits/kernel/USRSYS/RCS/bld,vhead     1.6;
branch   ;
access   ;
symbols  ;
locks    bin:1.6;
comment  @@;


1.6
date     91.07.24.08.05.48;  author bin;  state Exp;
branches ;
next     1.5;

1.5
date     91.07.15.14.07.50;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.07.03.13.16.54;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.06.20.14.24.52;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.17.12.44.48;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.15.11;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.6
log
@update prov by hal
@
text
@:
:  Build a Coherent executable with a host adapter driver linked in.
:
if [ $USRSYS ]
then
if [ $USRSRC ]
then
if [ $KOBJ ]
then
if [ $LOBJ ]
then
DRIVERS="rm fl lp mm"
COH_TYPE=fl
HD=""
KB=nkb
for ARG
do
	case $ARG in
	at|aha|ss)
		HD=$ARG
		COH_TYPE=$ARG
		;;
	kb|nkb|gkb)
		KB=$ARG
		;;
	*)		echo "Usage: $0 { at | ss | aha } { kb | nkb | gkb }"
			exit 0
			;;
	esac
done
DRIVERS="$KB $HD $DRIVERS"
echo "Kernel:    /coh.$COH_TYPE"
echo "Version:   `version ID`"
echo "Devices:   $DRIVERS"

: default root/pipe device
BOOTDEV="fva0"
echo "Default root/pipe device is $BOOTDEV."

( cd $USRSRC/ldrv; make ld_support )			|| exit 1
( cd $USRSRC/i8086/drv; make -f Mf.mwc install )	|| exit 1
( make kernel )						|| exit 1
./config.mwc ibm-at $DRIVERS root=$BOOTDEV			|| exit 1
cp coherent /tmp/coh					|| exit 1
strip /tmp/coh						|| exit 1
set `ls -s /tmp/coh`
SIZE=$1
rm /tmp/coh						|| exit 1
echo "Coherent bootable limit is 138 blocks.  This kernel is $SIZE"
if [ $SIZE -gt 138 ] ;then
	echo 
	echo Your Coherent image exceeds the bootable limit of 138 blocks
	echo by `expr $SIZE - 138` 'block(s).'  You will need to decrease the
	echo size of your kernel in order to make it bootable.
	echo
	echo We suggest removing some of the non critical drivers from the
	echo default list of drivers linked into Coherent.  These additional
	echo drivers may then be linked as loadable drivers using the
	echo ldconfig script located in this directory.
fi
mv coherent /coh.$COH_TYPE
chown sys /coh.$COH_TYPE
chgrp sys /coh.$COH_TYPE
chmod 400 /coh.$COH_TYPE
echo "New kernel in /coh.$COH_TYPE"
ls -l /coh.$COH_TYPE
# the rest is error exits
else
echo "Error - LOBJ not defined - (e.g. /usr/lobj)"
fi
else
echo "Error - KOBJ not defined - (e.g. /usr/kobj)"
fi
else
echo "Error - USRSRC not defined - (e.g. /usr/src/sys)"
fi
else
echo "Error - USRSYS not defined - (e.g. /usr/sys)"
fi
@


1.5
log
@update prov. by hal (moves objects to relocatable directories)
@
text
@d12 23
a34 17
HDDR=${1-"at"}
case $HDDR in
at)
	DRIVERS="at rm fl lp mm"
	;;
ss)
	DRIVERS="ss rm fl lp mm"
	;;
aha)
	DRIVERS="aha154x rm fl lp mm"
	;;
*)
	echo "Usage: $0 { at | ss | aha }"
	exit 0
	;;
esac
echo "Building kernel /coh.$HDDR Version `version ID` with drivers ($DRIVERS)."
d40 9
a48 10
( cd $USRSRC/ldrv; make ld_support )				|| exit 1
( cd $USRSRC/i8086/drv; make install )				|| exit 1
( make kernel )							|| exit 1
./config ibm-at $DRIVERS root=$BOOTDEV				|| exit 1
cp coherent /tmp/coh						|| exit 1
strip /tmp/coh							|| exit 1
: the SIZE expression needs fewer backslashes since Steve fixed sh
:SIZE=`ls -s /tmp/coh | sed -n -e 's/^\\\(....\\\).*$/\\\1/p'`
SIZE=`ls -s /tmp/coh | sed -n -e 's/^\(....\).*$/\1/p'`
rm /tmp/coh							|| exit 1
d61 6
a66 6
mv coherent /coh.$HDDR
chown sys /coh.$HDDR
chgrp sys /coh.$HDDR
chmod 400 /coh.$HDDR
echo "New kernel in /coh.$HDDR"
ls -l /coh.$HDDR
d69 1
a69 1
echo "Error - LOBJ not defined - (e.g. /tmp/lobj)"
d72 1
a72 1
echo "Error - KOBJ not defined - (e.g. /tmp/kobj)"
@


1.4
log
@updates provided by hal
@
text
@d8 4
d64 1
a64 1
echo "Error - USRSRC not defined - (was /usr/src/sys)"
d67 1
a67 1
echo "Error - USRSYS not defined - (was /usr/sys)"
d69 6
@


1.3
log
@another hal update
@
text
@d24 1
a24 1
echo "Building kernel /coh.$HDDR with drivers ($DRIVERS)."
d30 1
a31 1
( cd $USRSRC/ldrv; make ld_support )				|| exit 1
@


1.2
log
@new version provided by hal to handle environmental variable
for src box and to allow generic copies of this source to be distributed
with relative paths.
@
text
@d31 1
@


1.1
log
@Initial revision
@
text
@d2 1
a2 1
:	Build a Coherent executable
d4 4
d30 1
a30 1
( cd /usr/src/sys/i8086/drv; make install )			|| exit 1
d57 7
@
0707070064030054621005550000030000030000011777770507310747100004500000001355/newbits/kernel/USRSYS/RCS/confdrv,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.15.13;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�.&..|aha154xzal0yal1xatwativdgufltgmsgrrhsqlppmmomsnmsgmqqlrmkrpjrs0irs1hsdgsemfshmesscss.cp340bss.futass.real`ss.short_st^tn�RCS,RCSt300307^@
0707070064030053241005440000030000030000011777770507310747100004400000014270/newbits/kernel/USRSYS/RCS/config,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.15.15;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
:	configure a Coherent kernel for the AT
:
: usage: config [help]
:	 config [stand=fha0]
:	 config [stand=fva0]
:	 config [stand=fha0] [standard] [root=DRV] [DRV ...]
:	 config [stand=fva0] [standard] [root=DRV] [DRV ...]

:	initialize variables
:
ATSTANDARD=" fl lp mm "
ATKERNEL=atkernel.o

STANDARD="${ATSTANDARD}"
KERNEL="${ATKERNEL}"
LIBS="lib/tty.a lib/support.a"
BUILD=0
DEV=/tmp/dev
PASS1=""
PASS2=""
UNDEF=""
PATCH=""
ROOTDEV=""
INSTALL=""

case "$#" in
0)	/bin/echo
	/bin/echo	"The following can be used as arguments to config:"
	/bin/echo
	/bin/cat doc/*
	exit 0
	;;
esac

for ARG in $*
do
	case "${ARG}" in
	help)
		/bin/echo
		/bin/echo "The following can be used as arguments to config:"
		/bin/echo
		/bin/cat doc/*
		exit 0
		;;
	ibm-at)
		STANDARD="${ATSTANDARD}"
		KERNEL="${ATKERNEL}"
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "${ARG}" in
	standard)
		PASS2="${STANDARD} ${PASS2}"
		;;
	stand\=fha0)
		/etc/umount /dev/fha0 2> /dev/null
		echo -n "Insert 5.25 high capacity floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fha0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fha0 2400		|| exit 1
		/bin/cp /conf/boot.fha /dev/fha0	|| exit 1
		/etc/mount /dev/fha0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,14)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,14)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fha0 ; /bin/df /dev/fha0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	stand\=fva0)
		/etc/umount /dev/fva0 2> /dev/null
		echo -n "Insert high density 3.5 floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fva0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fva0 2880		|| exit 1
		/bin/cp /conf/boot.fva /dev/fva0	|| exit 1
		/etc/mount /dev/fva0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,15)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,15)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fva0 ; /bin/df /dev/fva0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS2="${PASS2} ${ARG}"
		;;
	esac
done

:	get the proper driver information
:

for ARG in ${PASS2}
do
	case "$ARG" in

	root\=fva0)
		ROOTDEV="makedev(4,15)"
		. confdrv/fl
		;;
	root\=fha0)
		ROOTDEV="makedev(4,14)"
		. confdrv/fl
		;;
	root\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			ROOTDEV="${MAKEDEV}"
/bin/echo "'confdrv/${FILE}' executing"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	swap)
		;;

	swap\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			if [ -d "${DEV-/dev}" ]
			then
				/bin/ln -f ${DEV-/dev}/${ARG} ${DEV-/dev}/swap
			fi
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			PATCH="${PATCH} swapdev_=${MAKEDEV}"
			/bin/echo "Swap device will be ${DEV-/dev}/${ARG}"
			/bin/echo "See documentation before enabling"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	*\=*)
		PATCH="${PATCH} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			case "${ROOTDEV}" in
			?*)	;;
			*)	ROOTDEV="${MAKEDEV}" ;;
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;
	esac
done
ROOTDEV="${ROOTDEV-makedev(4,14)}"

:	include stub drivers
:
UNDEF="${UNDEF} ${LIBS}"

:	make the proper root and pipe devices
:
PATCH="${PATCH} rootdev_=${ROOTDEV} pipedev_=${ROOTDEV}"

set -ex
:
:	create a kernel with the desired device drivers
:
/bin/ld -i -x -o coherent ${KERNEL} ${UNDEF} -lc
:
:	enable the desired device drivers
:
/conf/patch coherent ALLSIZE_=16384 NBUF_=32 NCLIST_=24 ${PATCH}
/bin/chmod 644 coherent
/bin/chown sys coherent
/bin/chgrp sys coherent
/bin/sync
:
eval ${INSTALL}
@
0707070064030053231005550000030000030000011777770507310747300004100000001135/newbits/kernel/USRSYS/RCS/doc,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.15.18;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@[.&..[aha154xZalYatXatiWflVgmUgrThsSlpRmmQmsPmsgOrmNrpMrsLsemKshmJstIswapHtnRCS,RCSt300314L@
0707070064030053221004440000030000030000011777770507310747300004500000000446/newbits/kernel/USRSYS/RCS/ker.inc,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.15.19;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/usr/include
/usr/include/sys
/usr/src/sys/sys
/usr/src/sys/i8086/sys
@
0707070064030053211004440000030000030000011777770507310747300004500000000601/newbits/kernel/USRSYS/RCS/ker.src,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @ * @;


1.1
date     91.06.10.14.15.20;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@/usr/src/sys/coh
/usr/src/sys/i8086/drv
/usr/src/sys/i8086/src
/usr/src/sys/i8086/ibm_at
/usr/src/sys/ker
/usr/src/sys/ttydrv
/usr/src/sys/ldrv
/usr/src/cmd/etc
@
0707070064030053201005440000030000030000011777770507310747300004600000002256/newbits/kernel/USRSYS/RCS/ldconfig,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.15.20;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
:	configure a loadable driver
:
: usage: ldconfig [swap] [DRV ...]
:
BUILD=0
DEV=/dev
PATCH=""
UNDEF=""
LDMOD=""
PASS1=""

for ARG in $*
do
	case "${ARG}" in
	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "$ARG" in

	swap)
		/bin/echo "ldrv/swap: "
		ld -r -o ldrv/swap lib/ldrts0.o lib/ldswap.o lib/ldlib.a
		LDMOD=""
		;;

	*\=*)
		LDMOD="${LDMOD} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		/bin/echo "ldrv/${FILE}: "
		if /bin/test -r confdrv/${FILE}
		then
			UNDEF=""
			. confdrv/${FILE}
			/bin/ld -r -o ldrv/${FILE} lib/ldrts0.o \
				lib/ldmain.o ${UNDEF} \
				lib/ldlib.a || exit 1
			case "${LDMOD}" in
			"")	;;
			*)	/conf/patch ldrv/${FILE} ${LDMOD}
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		LDMOD=""
		;;
	esac
done
@
0707070064030053171004440000030000030000011777770507310747300004600000000337/newbits/kernel/USRSYS/RCS/makedisk,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.15.21;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@c
@
0707070064030053161005550000030000030000011777770507310747400004600000000600/newbits/kernel/USRSYS/RCS/makefind,vhead     1.1;
access   ;
symbols  ;
locks    bin:1.1;
comment  @@;


1.1
date     91.06.10.14.15.22;  author bin;  state Exp;
branches ;
next	;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@# makefind - search kernel and driver Makefiles for a pattern
for f in `cat /usr/sys/ker.src`
do
  if grep -n $1 $f/M* 2> /dev/null
  then
  	echo $f/M*
  fi
done
@
0707070064030110631005550000030000030000011777770507310747400004500000002046/newbits/kernel/USRSYS/RCS/version,vhead     1.5;
branch   ;
access   ;
symbols  ;
locks    bin:1.5;
comment  @@;


1.5
date     91.07.24.08.06.21;  author bin;  state Exp;
branches ;
next     1.4;

1.4
date     91.07.15.14.08.36;  author bin;  state Exp;
branches ;
next     1.3;

1.3
date     91.07.03.13.17.03;  author bin;  state Exp;
branches ;
next     1.2;

1.2
date     91.06.20.14.25.05;  author bin;  state Exp;
branches ;
next     1.1;

1.1
date     91.06.10.14.15.23;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@


1.5
log
@update prov by hal
@
text
@version=1
release=2
revision=0.DK
arg=${1-foo}
if [ $arg = "ID" ]
then
	echo "$version.$release.$revision"
else
	echo -n '-DVERSION="'$version.$release.$revision'"'
fi
@


1.4
log
@changes by hal
@
text
@d1 1
a1 1
version=3
d3 1
a3 1
revision=0.G
@


1.3
log
@updates provided by hal
@
text
@d3 1
a3 1
revision=0xx
@


1.2
log
@another hal update
@
text
@d3 8
a10 2
revision=0
echo -n '-DVERSION="'$version.$release.$revision'"'
@


1.1
log
@Initial revision
@
text
@d3 1
a3 1
revision=0_beta
@
0707070064030112211005550000030000030000011777770507310747400004400000001153/newbits/kernel/USRSYS/RCS/usrsrc,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.08.20;  author bin;  state Exp;
branches ;
next     ;


desc
@init ver prov by hal
@



1.1
log
@Initial revision
@
text
@# back up USRSRC directories
TMPFILE=/tmp/usrsrc.$$
rm -f $TMPFILE
cd $USRSRC
for DIR in i8086/drv i8086/drv/tools i8086/ibm_at i8086/src coh ttydrv ker ldrv
do
	for FILE in `ls $USRSRC/$DIR`
	do
		echo $DIR/$FILE >> $TMPFILE
	done
done
echo "$TMPFILE created"
echo -n "Insert 3-1/2\" formatted diskette and press <Enter> "
read JUNK
cpio -ocv < $TMPFILE > /dev/rfva1
rm $TMPFILE
@
0707070064030112221005550000030000030000011777770507310747400004400000001075/newbits/kernel/USRSYS/RCS/usrsys,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.08.31;  author bin;  state Exp;
branches ;
next     ;


desc
@init ver prov by hal
@



1.1
log
@Initial revision
@
text
@# back up USRSYS directories
TMPFILE=/tmp/usrsys.$$
rm -f $TMPFILE
cd $USRSYS
for DIR in . ldrv doc confdrv lib
do
	for FILE in `ls $USRSYS/$DIR`
	do
		echo $DIR/$FILE >> $TMPFILE
	done
done
echo "$TMPFILE created"
echo -n "Insert 3-1/2\" formatted diskette and press <Enter> "
read JUNK
cpio -ocv < $TMPFILE > /dev/rfva1
rm $TMPFILE
@
0707070064030110621005550000030000030000011777770507310747400004300000003204/newbits/kernel/USRSYS/RCS/Build,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.24.08.05.17;  author bin;  state Exp;
branches ;
next     ;


desc
@build script for scsi kernels
@



1.1
log
@Initial revision
@
text
@:
:  Build a Coherent executable with a host adapter driver linked in.
:
DRIVERS="rm fl lp mm"
COH_TYPE=fl
HD=""
KB=nkb
for ARG
do
	case $ARG in
	at|aha|ss)
		HD=$ARG
		COH_TYPE=$ARG
		;;
	kb|nkb)
		KB=$ARG
		;;
	*)		echo "Usage: $0 { at | ss | aha } { kb | nkb }"
			exit 0
			;;
	esac
done
DRIVERS="$KB $HD $DRIVERS"
echo "Kernel:    /coh.$COH_TYPE"
echo "Devices:   $DRIVERS"

: default root/pipe device
BOOTDEV="fva0"
echo "Default root/pipe device is $BOOTDEV."

( cd /usr/src/sys/i8086/drv; make -f Makefile install )	|| exit 1
./config ibm-at $DRIVERS root=$BOOTDEV			|| exit 1
cp coherent /tmp/coh					|| exit 1
strip /tmp/coh						|| exit 1
set `ls -s /tmp/coh`
SIZE=$1
rm /tmp/coh						|| exit 1
echo "Coherent bootable limit is 138 blocks.  This kernel is $SIZE"
if [ $SIZE -gt 138 ] ;then
	echo 
	echo Your Coherent image exceeds the bootable limit of 138 blocks
	echo by `expr $SIZE - 138` 'block(s).'  You will need to decrease the
	echo size of your kernel in order to make it bootable.
	echo
	echo We suggest removing some of the non critical drivers from the
	echo default list of drivers linked into Coherent.  These additional
	echo drivers may then be linked as loadable drivers using the
	echo ldconfig script located in this directory.
fi
mv coherent /coh.$COH_TYPE
chown sys /coh.$COH_TYPE
chgrp sys /coh.$COH_TYPE
chmod 400 /coh.$COH_TYPE
echo "New kernel in /coh.$COH_TYPE"
ls -l /coh.$COH_TYPE
@
0707070064030053131005440000030000030000011777770507310747500005000000014263/newbits/kernel/USRSYS/RCS/config.mwc,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.07.24.08.06.00;  author bin;  state Exp;
branches ;
next     ;


desc
@@



1.1
log
@Initial revision
@
text
@:
:	configure a Coherent kernel for the AT
:
: usage: config [help]
:	 config [stand=fha0]
:	 config [stand=fva0]
:	 config [stand=fha0] [standard] [root=DRV] [DRV ...]
:	 config [stand=fva0] [standard] [root=DRV] [DRV ...]

:	initialize variables
:
ATSTANDARD=" fl lp mm "
ATKERNEL=atkernel.o

STANDARD="${ATSTANDARD}"
KERNEL="${ATKERNEL}"
LIBS="lib/tty.a lib/support.a"
BUILD=0
DEV=/tmp/dev
PASS1=""
PASS2=""
UNDEF=""
PATCH=""
ROOTDEV=""
INSTALL=""

case "$#" in
0)	/bin/echo
	/bin/echo	"The following can be used as arguments to config:"
	/bin/echo
	/bin/cat doc/*
	exit 0
	;;
esac

for ARG in $*
do
	case "${ARG}" in
	help)
		/bin/echo
		/bin/echo "The following can be used as arguments to config:"
		/bin/echo
		/bin/cat doc/*
		exit 0
		;;
	ibm-at)
		STANDARD="${ATSTANDARD}"
		KERNEL="${ATKERNEL}"
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "${ARG}" in
	standard)
		PASS2="${STANDARD} ${PASS2}"
		;;
	stand\=fha0)
		/etc/umount /dev/fha0 2> /dev/null
		echo -n "Insert 5.25 high capacity floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fha0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fha0 2400		|| exit 1
		/bin/cp /conf/boot.fha /dev/fha0	|| exit 1
		/etc/mount /dev/fha0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,14)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,14)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fha0 ; /bin/df /dev/fha0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	stand\=fva0)
		/etc/umount /dev/fva0 2> /dev/null
		echo -n "Insert high density 3.5 floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fva0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fva0 2880		|| exit 1
		/bin/cp /conf/boot.fva /dev/fva0	|| exit 1
		/etc/mount /dev/fva0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,15)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,15)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fva0 ; /bin/df /dev/fva0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS2="${PASS2} ${ARG}"
		;;
	esac
done

:	get the proper driver information
:

for ARG in ${PASS2}
do
	case "$ARG" in

	root\=fva0)
		ROOTDEV="makedev(4,15)"
		. confdrv/fl
		;;
	root\=fha0)
		ROOTDEV="makedev(4,14)"
		. confdrv/fl
		;;
	root\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			ROOTDEV="${MAKEDEV}"
/bin/echo "'confdrv/${FILE}' executing"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	swap)
		;;

	swap\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			if [ -d "${DEV-/dev}" ]
			then
				/bin/ln -f ${DEV-/dev}/${ARG} ${DEV-/dev}/swap
			fi
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			PATCH="${PATCH} swapdev_=${MAKEDEV}"
			/bin/echo "Swap device will be ${DEV-/dev}/${ARG}"
			/bin/echo "See documentation before enabling"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	*\=*)
		PATCH="${PATCH} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			case "${ROOTDEV}" in
			?*)	;;
			*)	ROOTDEV="${MAKEDEV}" ;;
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;
	esac
done
ROOTDEV="${ROOTDEV-makedev(4,14)}"

:	include stub drivers
:
UNDEF="${UNDEF} ${LIBS}"

:	make the proper root and pipe devices
:
PATCH="${PATCH} rootdev_=${ROOTDEV} pipedev_=${ROOTDEV}"

set -ex
:
:	create a kernel with the desired device drivers
:
/bin/ld -i -x -o coherent ${KERNEL} ${UNDEF} -lc
:
:	enable the desired device drivers
:
/conf/patch coherent ALLSIZE_=16384 NBUF_=32 NCLIST_=24 ${PATCH}
/bin/chmod 644 coherent
/bin/chown sys coherent
/bin/chgrp sys coherent
/bin/sync
:
eval ${INSTALL}
@
0707070064030115001005550000030000030000011777770507310747600004500000001517/newbits/kernel/USRSYS/RCS/newkers,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.24.08.06.10;  author bin;  state Exp;
branches ;
next     ;


desc
@@



1.1
log
@Initial revision
@
text
@# newkers - copy kernels to floppy
VOL=${1-foo}
case $VOL in
f0 | 5)
	VOL=f0
	PATCH="rootdev_=0x40E"
	;;
f1 | 3)
	PATCH="rootdev_=0x40F"
	VOL=f1
	;;
*)
	echo "Usage: $0 { f0 | 5 | f1 | 3 }"
	exit 0
esac
echo -n "Place boot diskette in $1 drive and press <Enter> "
read JUNK
mount $VOL || exit 1
cp /coh.at /$VOL/begin
ln -f /$VOL/begin /$VOL/coherent
chmog 400 sys sys /$VOL/coherent	
/conf/patch /$VOL/coherent $PATCH pipedev_=0x883 ronflag_=1 || exit 1
cp /coh.ss /$VOL/coherent.ss
chmog 400 sys sys /$VOL/coherent.ss
cp /coh.aha /$VOL/coherent.aha
chmog 400 sys sys /$VOL/coherent.aha
ls -l /$VOL/begin /$VOL/coh*
umount $VOL
@
0707070064030107700407550000030000030000011777770507310747700003300000000000/newbits/kernel/USRSYS/lib0707070064030107671006440000000000000000011777770507310747700004500000016423/newbits/kernel/USRSYS/lib/aha154x.a]�scsi.o�(l����p��VWU����h��6��6�j������}��_^�VWU��>�~
�6�h������6�����+��� }���烽jt������j����F���_^�VW��F%���%�F�~���jP�6�h�����j�~��狅j�F�j%�6�L����F��~�t�~��烽juh�.����#+��jP�~�����j�����F�F��F��F��F��6�v�������F��V����F�%�F�+�;v�}��~��F���F�P������F�P�����^��G*�Ȋ*�������+҉F�V���������F�V�^��G*�ȊG*�������+�	F�	V�~��E*�ȊE*�����F�S�L����F�V�~�EL�UN���~�����j�~����F��%����
�P�����_^�VW��v�ƀt#��t�h"V�������������%���%�F���%���^��ヿjuV�)����u��n�^��㋇j�F��^��GL�WN�F�V�����^��G�W�F��V�����^��G�W
F�V�;V�wr;F�v�%�����^��GGt�Y���_^�VWU�������_^�VWU��h@�j�v�v
h��
���
�_^�VWU��h@�j�v�v
h������
�_^�VW��v�F���%���%�F��F
�J�CC.;��t�.�gHHT���d��~��烽ju �F�V������~��烽ju����~��狅j�F졺�.����ǙRP�~��uN�uL�J����F�F����F��F�j�v�F�P�)����~�t�~�����j�����~���Džj+��l�~��狅j�F�j�F�P�v������F�*䣺�F�*䣼���RP���RP�����RP�F�RP�����~�EL�UN��v�v
����������_^�VW��v�D%�F��D%���%�F��D�t�F��D�D�^��㋇j�F��^��ヿjt��~�t��D
Dt���|t��j
�6�������uhK�
�����u�F��E
�E�~�t�^���^��D
�TGW
��D
�T�E�U�E����F��>�u�>�����?�>��v��������>h.덋^���^��D��	�ȋ�+�D
T;Ww
s�O�;Gw�G��LV�d����_^�VWU���U�����N�����_^�@ 0
��n���+aha154x: sdunload() athough %d active
aha154x: out of kernel memory
No tape yetaha154x: no partition table
aha154x: out of kernel memory
free_aha_ioctl_sdgetpartitions_uaha_command_aha_load_sdclose_�SD_SPT_�sdwatch_�kclear_SDBASE_�sphi_u_aha_start_drvl_nulldev_SDIRQ_�aha_completed_devmsg_bdone_vtop_sds_alloc_vrdivaha_unload_lrmulspl_fdisk_printf_allkp_SD_HDS_�sdcon_�ukcopy_kucopy_ioreq_ � � � � � �'� � � �%%$$7'$%2%9$<7?$F7I%[%f7i'�7�%�%�'�7�%�$�7�'�0�%�7�'7
'
7<7F7�'�
%�7�'$70'
%"0%%C0J'U%a'�0�'�'�
%�%�7�!%7! 70F X Z \ ^ ` b%k0w%�'�0�%�$�$�7�$�$�7� %�7�%�%7$$'$*$0767D7['d%�%�0�0�0�0�'�7�$�7�0�77
%>%E%K%Q7W7]$b0�0�7�7�7�aha.o�(l��>	pX�VWU��Y	�_^�VWU��ht	������_^�VWU��6�
�F��
���_^�VWU�졲
�_^�VW��~�u;�^�;u
��v���o�|�^�u�tD�L�^�u/�u)�y��F���
�?t�_�7��
�w�v��[������#�M��EW�C���V�<����v�3����_^�VWU���6�
� ���%���t��u��
@@P��������tӸ����v��
@P�����+��_^�VWU���6�
�����%���u��u��
@@P��������tӸ�����
@P����%��_^�VW��F	�H	�F��V��n��^��F��V��x"u�t�6�
�f���������t��v�'��h�	�K����_^�VWU��J	��O~��
@@P�.����ȋ���t��u	h�	�����6�
�
�����j �6�
��������_^�VWU���N
|
�~�F��������_^�VW��6�
�����=�u�����B	�D	�F��V��n��^��F��V��xu�t�6�
�������ǀu֋F�F�u����G�6�
�r�������@t����0�6�
�[������� t���6�
�D�������t+������_^�VWU��N|)��~�F�V
%�+҈��F�V
�������F�V
���_^�VW��~�*䙉F��V���������F��V��v�D*�ȊD*�������+�	F�	V���
��
)F�V��F��_^�VWU��j
�����jh�
����+���}���
t���
�PVh�	�l���F��h�	�`����_^�VWU��>�
t �>�
t�6�
�?�����
�v�0����_^�VW��v�;����>�
u0�>	����P�6������
�u	��������>	���
��
+�;6>	}�����
����>�
+��*�F���6j������
��
�F�P�6�6�
����RP�f����>	�F�h��v
����h�h��v���jh��k���h��6�
�^������}h�	�N����6�
h
�A����E�j����+���}����E�*�P�����F��F��
��
�>	�_^�VW��v�D�F���T�F��V�j>�6������F��~�u	�������v�^��G;��D�%���G�D�%G�D
��^��G*�=*u�O��^��O�^��G�F��G�V���������^��G�F��V���������^��G�F��G�G�F��.�><	�G�F��G�G�G
�G�F�P�D
�RP������F�P�t�t�������
@P�6�v������RP�������
�j�����^��?ujh�h�S�������^��uO�tI�D�%P�D���Ph 
����+��^��G�;�~�߃�
^��G*�PhE
����G��hI
�w����^��G��ȊG����S�_������_^�VWU��vj>�6�E������u;��D
�%���E�D
�%E�\�u
�M�E(��M�E*�E�D�T��������E�D�T��������E�D�E�E�\�G+ҹ�������E�\�G��	�E�E�E
�E�EP�G+�RP�n����EP�\�w�w����RP�S������_^�VW��F��j����>�t
W�]������W�O�����
��F��u��;6>	|������
�?uq�F��v�������F������
@P�6�v������RP����������
�j��������F��^����
��F��~�u�G�v������~�tF�t�;6>	t�X����F��_^�VWU��+�+�;6>	}9�����
�?t(�����
@P�x���Ph?�d��������
�GF�����_^�VWU�졲
@@P�=��������ǀu
VhK
�)�����%H=w+����.���	�						jh��������Y��	hg
�����j �6�
������_^�VWU��h�
������_^�N	no messageerror messages not verboseaha154x: out of kernel memory
aha154x: timeout sending cmd byte
aha154x: aha_poll timed out
[%d] %x 
aha154x: initialization error or host adaptor not found at 0x%x
aha: SCSI ID %d LUN %d. SCSI sense = %x
aha: spurious interrupt %x
aha: multiple interrupts not yet handled
aha_ioctl: Not implemented
free_aha_ioctl_)	drive_info_ aha_command_�clrivec_aha_load_�setivec_sphi_aha_start_�buildccb_�inb_outb_aha_get_base_3aha_device_info_adefer_aha_completed_gaha_intr_�bdone_aha_process_?vtop_sds_alloc_aha_unload_�wakeup_spl_aha_set_base_MAX_MAILBOX_>	printf_allkp_sleep_$@	$$7%%%+%97Z7�%�%�7�0�7�7�7�%�7�
%�7�
%7%&7)
%>7D
%W7\
$o$s%�7�
0�$�7�$�%�7�
$�7�%�7�
%�7�00"%073
0A$D$H%j7m
%�7�
%�7�
%�7�
%N%R0i%q0t%�%�$�7�$�7�%�%�%�7�%�7�0�%�$�'�7�%00$%%$!%,%5'D7I%O%S'[%_7b0j$p v7|7�7�%�7�0�$�7�%�$�7�0�0�0�%�%�$�'70(0. �0�0�%�'�7�0%07-$T7W$x7{$�7�7�'�7�0b7u0}7�%�7�0�%�7�%�0�$�0�%�0�%�'�70%07"%.7D0Q$U0Z%^$r%}%�0� �7�%�%�7�
$�7� � � � � � � � � � 	7	0	$	7	%	7 	$/	72	fdisk.o�(m�����(VW��v
�F�����F�jj�v������>uejjj�v������F��tF�^�����U�u/�F��~�}j�F�����P�ƃ�P�����F����F��v������v�v����v��m����F��_^�sphi_u_dclose_blkmvbread_brelease_spl_fdisk_dopen_77'#727l77�7�0707070064030107631006440000000000000000011777770507310750100004000000021464/newbits/kernel/USRSYS/lib/al.a]�com1.o�(�i�� ��VW��>:t�i2^P�6������6�u�k2P�6������4�u�xi2^P�66����k2P�64���������:�.�>6�E��E�4�E�6��>4���E�>2~0�0�>6��y���x�4��r�6^��>4�E��E�F��F�;2|��iF�^��>6�E��F�iF�^��>6�}��F�j@P������F�@P������uXj�F�P�����h��F�P������~������v������~��狅��P�F�@P����j�F�P����iF�^��>6�EiF�^��>6�EiF�^��>6�_���\�F��&�hj�M���V�F����_^�VW��F��F�;2}[iF�^��>6�}��F�j@P����j�F�P����jjj��jiF�^6HP��P�����������F��j������66������64�����_^�VWU��F%?;2s:���~��?i�^6P����h8�~��?i�^6P�v
�v�j������_^�VWU��N��?i�^��>6�Mu(�>����~��?i�^6P�v
�v�#���V�����_^�VWU���v
�~��?i�^6P������_^�VWU��v
�<tV�N��?i�^6P������|V��������|o�^��?i�^��6�_�P�������� t؋^��?i�^��6�_�P�{������� t�W�N��?i�^��6�_�7�V�����_^�VWU��~��?i�^6P�v�v
�v�,����_^�VWU���v�v
�~��?i�^6P�����_^�VWU���68������_^�
P��
���free_alxtimer_clrivec_albaud_kclear_setivec_alxstart_sphi_u_alxopen_cs_sel_inb_outb_nulldev_iogetc_blkmvalxintr_ttread_timeout_tp_table_alloc_spl_C1BAUD_.a0con_C3BAUD_0ttwrite_allkp_alxcycle_alxparam_A0CNT_2alxclose_ttpoll_alxioctl_  '
    "'$
'& ( * ,%0$'7%"0)$-'376%<0C$G%N7Q$X%^7a7g%m$p%t%~%�'�%�$�$�%�%�%�'�%�$�0�%�%�777%75'A7G'S7_7n%|'�%�'�%�7�
0� �7�7�$�%�7�7�%7 7&73%:7=%D7G$]0b%q7u%{%�7�	'�%�7�%�7�7�%7%(7,75%O7[%w7�%�7�%�7� %�7�%7
com2.o�(�i�� ��VW��>:t�i2^P�6������6�u�k2P�6������4�u�xi2^P�66����k2P�64���������:�.�>6�E��E�4�E�6��>4���E�>2~0�0�>6��y���x�4��r�6^��>4�E��E�F��F�;2|��iF�^��>6�E��F�iF�^��>6�}��F�j@P������F�@P������uXj�F�P�����h��F�P������~������v������~��狅��P�F�@P����j�F�P����iF�^��>6�EiF�^��>6�EiF�^��>6�_���\�F��&�hj�M���V�F����_^�VW��F��F�;2}[iF�^��>6�}��F�j@P����j�F�P����jjj��jiF�^6HP��P�����������F��j������66������64�����_^�VWU��F%?;2s:���~��?i�^6P����h8�~��?i�^6P�v
�v�j������_^�VWU��N��?i�^��>6�Mu(�>����~��?i�^6P�v
�v�#���V�����_^�VWU���v
�~��?i�^6P������_^�VWU��v
�<tV�N��?i�^6P������|V��������|o�^��?i�^��6�_�P�������� t؋^��?i�^��6�_�P�{������� t�W�N��?i�^��6�_�7�V�����_^�VWU��~��?i�^6P�v�v
�v�,����_^�VWU���v�v
�~��?i�^6P�����_^�VWU���68������_^�
P��
���free_alxtimer_clrivec_albaud_kclear_setivec_alxstart_sphi_u_alxopen_cs_sel_inb_outb_nulldev_iogetc_blkmvalxintr_ttread_timeout_tp_table_alloc_spl_C2BAUD_.a1con_ttwrite_C4BAUD_0allkp_alxcycle_alxparam_A1CNT_2alxclose_ttpoll_alxioctl_  '
    "'$
'& ( * ,%0$'7%"0)$-'376%<0C$G%N7Q$X%^7a7g%m$p%t%~%�'�%�$�$�%�%�%�'�%�$�0�%�%�777%75'A7G'S7_7n%|'�%�'�%�7�
0� �7�7�$�%�7�7�%7 7&73%:7=%D7G$]0b%q7u%{%�7�	'�%�7�%�7�7�%7%(7,75%O7[%w7�%�7�%�7� %�7�%7
alx.o�(�i���
TH�VW��v�~�F%��F��\��F�@P�����������t��&�D�t
����u��F���ȁ��k�
��t�'���F@t���u��F@u��\�G����㋇=t˃|t��\�tjjh�DP�L������D��F��F@tj��\�G����㋇�j�F�P����j�F�@P�����F��t��L $�F�P������F��F�*�\G�F��u`jjh�DP�������G$G&t����t��F�P����%P�F�P����j�F�@P������v��������d���F�t�d����d���LV�Y�����
	�,��
��!�,V����v��9����D�vV�,����F@t�\�G�����LJ�_�g�\�G�����LJ�T�\�G����㋇=u�>��\�G��؁��㋇=t�X�� ��F��u	�Du��
�Du�t���_^�VW��^�w�_�G�v�����^�G�F��^��?�F��~�tU�^�GPhj
�GP�S���jjh�^�GP�<����^��[*�F���Z*�:F�u��~�t��N���� uj��@P������^�G$��@tQ��P�����%P��P������F��%��F�k^�
LJjjhkF�
P����k^�
LJ��P����%��P��P�����^�_�G�����LJ���^�_�G�^�GP�Z����_^�VWU��v�����k�
������=~�~�����k�
P�����_^�VW��v�����\��F�@P������F��F�P������F��F�P������F��F
�A�	CC.;��t��.�g������������g~����F�
@P�F�P������F�%����F�
P�F��ߋF�%����F�
��F�%���ߋF�
�P�F�P�B����v�v��6����F��P�F�@P�$����v�늋N���F�%����w��F�P�����F��F�*�\G�F�*����F�j�v�F�P����
�v�v
V������F�*�P�F�@P����W�����_^�VW��^�G�F��^��7�^��)��F���(�:F�t����^��(����㋇�
���u+�^�Gt!�g����P�N���%P��P�>����t}�4��F���@P�*����F�h���P����WV��������P��@P�����^��,%�=t	=tj�j�j
��P������F�*�P��@P������v�������_^�VW��v�Du����F��\�P�����F��F�*�\G�v��w����\�Gt>�g��|u	�DP�Z��(�F��u%�O��F���X*䈄YƄY�v��7���V�0����\�Gt�g��F�t�d����L ��Y*�=�w"�\�P�����
P�\�P������Dt�Du=��Yt6��Y*�ȋ�ي�Z*�PV������Y*�=�s��Y�ƄY��Y���F����Z*�Ȋ�[*�+�F��F��.�>�
�V��N�|7V�i������|*��Z*�ȋ�ًLj�\��Z*�=�rƄZ����Z��V�2���VhMj
��HP�!����_^�VW��v���F��\�P���������t
Vhg������� t>��Z*�:�[t2��[*�ȋ�ي�\*�P�\�7������[��[*�=rƄ[�v������_^�VWU��j�v�����_^�VW��v�\��F��F�@@P�k���=v�`����.����	
�	
�
��F�P�?�������t�Vhg�-�����v��"������|t���,@u-�ρ���1�;�u�L 녋ρ���0�;�u�d���n���Y*�=�s,��X*�ȋ�ًLj�Z��X*�=�s��X�ƄX��Y�Du�-���Y*�=�w���F�P����%��P�F�P�x��H���Z*�:�[u����D t�����[*�ȋ�ي�\*�P�v��C�����[��[*�=rƄ[��[*�:�Zt��VhM����F�P�����\G���_^�VW��F��~�}"�~��狅=u�~������L����F����B�B;@|�B�B�_^�VW����t��F��F��~�}:�~��狅=u'�~��狽��(����狅�F��F�;F�}�F��F��F����F�;t.��.�>�
�@�<��&���~�t�h
�6� ����_^�d	Y@��`@:0 dddddddd�,��X �@ttsignal_alxtimer_�al_sg_clr_�
albaud_�
super_altclk_in_al_sg_set_�
altclk_out_nondsig_alxstart_�com_usage_sphi_tthup_u_alxopen_drvl_inb_outb_ttsetgrp_ttclose_ttin_ttout_poll_owner_poll_rate_alxintr_{ttioctl_defer_timeout_cprocp_alp_rate_alxbreak_gtp_table_wakeup_spl_alxcycle_Mttstart_alxparam_Ssleep_ttopen_kucopy_alxclose__alxioctl_�7 '/
037=0D'W'^
0b'm0{'�
0�7�%7�'�7�7�0�773%':7E7S7d7q'x
7!0�7�&$�$�0�7�!7�'�
0�'
'
0'/
070:0T'X
7v'� 7�7�%7�77"'9'I7M%'X7c7s'�
0�7� '�'�'�7� 7�777" .0= U W Y [ ] _ a c e7v0|7�7�7�0�7�7&'727C7J!'~
0�$�7�7�7�7�7�7�7�7(787A!0G0^7a7p7�!7� 7�7�!7�777I �7�7�# �7�7�7� 77A7^!7r7�0� � � � � � � � �7� �7�7�0	0]	0k	7u	7�	0�	0�	0�	7�	0�	 �	0�	7�	0�	'

'*
0-
%9
%<
%@
%F
%K
'Y
0`
'y

'�
$�
'�
'�
 �
%�
7�
'�
'�
 �
'�
7�
0707070064030107601006440000000000000000011777770507310750300004000000014722/newbits/kernel/USRSYS/lib/at.a]�at.o�(ҳ������ZVW�jjp�����jq������������z��%�{j�F�Pjh�����+�����|��=u,jW�F�+҉F��V��F�+ҹ������F�V�RP�����@��zuƄz�}u�E�E*�P�u�E*�P�E*�P�u�E*�P�5Vh*
�J���j�F�Pjh�9�����F�o�+�����}I��zu��F������F��E*�RP�E*�RP�����RP�+�RP������^���������Ph�j�������h�6���������h�6�����������_^�VWU��j�����_^�VWU��jh��|����dNu��
*�%Ph��d���j���h��S���=t	hk
�E���+�����|���zu��F��V��
���E*�Ph������E��Ph������E*�Ph������jh��������Ph����������Ph�������E*�ȋ�����Ph�����h�h�����V�U
��jh�����V�C
���Z��_^�VW�
�v��%�F��ƀt
��%���F��
��%�������}��zu���ƀt��^��������u#�����P�ρ������%����P�	����߃����������F��V��^����������F��V��^���������F�V�;V�wr;F�v�%��^��������u��_^�VWU��h@�j�v�v
h�����
�_^�VWU��h@�j�v�v
h��i���
�_^�VW��v�ƀt��%���%����F��F
=Ht=Ht"�����j�v�F����P�����nj�F����P�v�����~�ƅz�F����F�����
*�RP�~�����
*�RP�����RP�~������+�RP�����~���������+��_^�VWU��6b�����tH�6t�6r�t�t
�D�tjx�
�x%aP�6ph�
�]����p���r���t�����oW�>����_^�VW��v�D%�F��D�D�D�t�F��F�������|u�D
�T;Uu;Eu	V������^�D��	�ȋ�+�D
T;Urw;Ew
�D�u�|u�L����>bu�6b��d�7�6d�>}u
��t��_^�VW��~�|�b���u+���D%�x�D�t
�x�D%�	�D%����p�p����
*�F��x������D
�TEU
�j�l�D��	�n�D�T�f�h�|uE�>nv
������	�j�l;�u	;�u���j�l;�t��;�t���ǃ>nt���*�;pu:�j�l;�u-;�u'h�t�t�6��z�����b�DV�i��������*�;pu"�j�l;�u;�uh�t�t�6�빃<uW�F�+�RP�6l�6j�����F��V��N������+�+F�V��~�~*�=r
�~����>~t�~*�n����_^�VW��p������D*�RP�D*�RP�6l�6j����RP�����t�D*�RP�D*�RP�6l�6j�~���RP�v����r�D*�RP�6l�6j�]������v�p;�u]�t;�uT�r;�uK�b�F��6t�6r�~��u�u
�E�tjx�
�x%aP�6ph�
�����~��MW�y�����6p����D*�Ph�������D��Ph�������6nh������6vh������6th������t��Ph������p��r�Ph��w����>b�}u3j0h��b����\��u�6ph 
�N����6h�6f�A����}�j h��/����}�t�_^�VWU��jh������_^�VWU��6b�}*�H=v�����.��		#	�	�
����t�}������u
�6ph 
�����~*�;nu�6�>n����������6h�6f������u��~*�;nu*�>n������j�l�������p�>n��~�~��f�l�|�j�l�nuWV����N�O�t�K��f�l�|�j�l�nt�����u�6ph 
��������6h�6f������_^�VW�
�6bh�������ȋ���!u�Gh������F��}*�=u�~*�;nu�|d�3�F��u��|d�p���r���t���6t�6r�n+҉F��V��~*䙉F��V��D��	�ȋ�+�D
TF�V�+F�V�RP�D�tjx�
�x%aP�6ph�
������@u	h������ t	h-�����F�t	h<�����F�t	hQ�����F�t	hf�����F�@t	hv����F�t	h�����F��t	h�����|*�=s	h����h��w���+���|�|*�=r�����_^�VW��6b�p�t�F��|*�H=w9����.��������N�}'�F��!�p���F��F�;��r�n����F��|*�=sP��u����t�v�h������F���Ph������p���Ph����Wh�����}�!�}*�=u�~*�;nt�LV����_^�VWU��v�t�}��bV�\������t�|��_^�VWU��6
�~�;���t���N���vh 
�%��+��_^�|�d��bf2at%d: TO
at%d: ncyl=%d nhead=%d wpcc=%d eccl=%d ctrl=%d landc=%d nspt=%d
at: AT disk controller not present (reset)
at%d%c: bno=%U head=%u cyl=%u <Watchdog Timeout>
at%d%c: bno=%U head=%u cyl=%u <Track Flagged Bad>
at%d%c: bno=%U head=%u cyl=%u <Drive Not Ready> <Write Fault> <No Data Addr Mark> <Track 0 Not Found> <ID Not Found> <Bad Data Checksum> <Command Aborted> <Block Flagged Bad> retrying...
clrivec_setivec_sphi_u_drvl_inb_outb_nulldev_atsend_myatbsyw_�atrecv_atparm_�defer_bdone_sds_alloc_vrdivvrremspl_fdisk_atdrqw_printf_allkp_atcon_�kpcopy_pkcopy_vrmulatbsyw_ATBSYW_
ukcopy_kucopy_ioreq_ �'� � � � �'� � � �77% %(76$>0F7r%{%�$�7�7�0�$�%�77%% 0% (7-%4'<7?%E%I'Q7T%Z%^7n7�$�7�0�7�$�7�$�0�%�0�7�7�777 707K7W0^7i0p0v%�'�0�0�%�%�%�7�%%%%%,%0'F%S%W']%u7x%�7�'�0�$�7�$�7�%$$+73$B7I%S%W0Z%i7l'r%x%|%�%�$�7�%�%�%�%�%�%�0�0�7�%�7
%N%U%[%a%e0k0r%�%�%�0�%�%�%�%�$�%�%�%�%�%�%�%%%%0%%"%&%,01%4%8%<0A%E0J%P0V%Y%_%d%h%l%r%�7�%�7�
0�%�%�%�%�%�%�%�%�%�7�%�%�%	%%%%%#%4$:%P%T7W7_%e%y%}7�7�%�%�%�7�%�%�%�%�%�%�%�%�%�%�%�%�$�7�0
0%07)79%@7F%M7S%Z7`%f7p%v%}7�%�7�7�%�$�7�%�%�7�%�7�%�'� �7�%�%	0	 	 	 	 	0	0!	0$	0+	0.	71	%9	$<	7?	%E	%K	'Q	%U	%^	%d	%h	7k	
0q	%x	%~	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	0�	0�	0�	%�	%�	%�	%�	%�	7
%
$
7
%
%
7
%/
75
0E
7K
%T
%^
%d
%j
0n
0x
%|
%�
%�
%�
%�
%�
%�
%�
%�
%�
%�
%�
%�
$�
7�
$�
7�
$7$7$(7+$87;$H7K$X7[$h7k%q${7~$�7�%�%�0�%�%�%� � � � � � � �%�$�%
'!7*7:%@7M7W%^%d%n%t0'�%�%�7�
0�0�$�7�$�7�atas.o�(ӳ�V�VU���v�����o]^�WU���~�����m]_ú�����쨀��tKu��ú��������uKu���atsend_atrecv_CSR_REG	�DRQ_ST	atdrqw_@BSY_ST	�atbsyw_*fdisk.o�(ӳ����(VW��v
�F�����F�jj�v������>uejjj�v������F��tF�^�����U�u/�F��~�}j�F�����P�ƃ�P�����F����F��v������v�v����v��m����F��_^�sphi_u_dclose_blkmvbread_brelease_spl_fdisk_dopen_77'#727l77�7�0707070064030107541006440000000000000000011777770507310750500004100000021556/newbits/kernel/USRSYS/lib/ati.a]�mm.o�(�������VW��v�D u2V������F��|$�F��F��F��F��F��F�Ph�����ǃ>�u��Vh`j
h�����_^�VWU�������>}2�h�jC����h�jB�w���j
jB�m���ja�e���
��>~�uja�K���%��Pja�?����>t��P�-����V�!����v�����vh`j
h�����_^�VWU��>�~�>�~	��u����_^�VW��v
�D�F��<uV������u����Dup� t'���F��jjhh�����v������ы>�E$E&t&�w��t�p��F�;Du��6V�]����t+��V�P����|u��� t��V�2����u��_^��ismmfunc_mmtim_mmbeeps_mm_voff_mmcrtsav_�mmgo_mmwatch_nondsig_sphi_u_inb_outb_istty_kbunscroll_ttout_mmwrite_ cprocp_timeout_mmstart_mmtime_`spl_mmvcnt_�mmesc_ttstart_sleep_70;%D%K O'T7W7f'l's7|7�7�7�
'�'�7�
7�'�'�7�'�7�7� �'�7�$$$7760@'M7T'['g7j7s'|7�7�
'�	7�7�'�'�	7�ati.o�(���X�Xt	~8(-
qPZ
aPR
���
���
VWU����^�w�O�?t��
�V���t���F�v�V�F�~+ۊf
�f[�f
�^�v�V�~�V��^���B���J��B���V���F��,��^���O+OO]_^�6�c�FP�F!�F��������$0<0u�F �F��F��F�Q+���6�FF����
r�V��B*��J�
�B*��V��*���F��f
�v�v
�^�^+��F��V���F�~��V���.�B�JK}�Á~�u�F(�F �F��������n��~�u�FP�F!�F�������M��FP�F �F!�������3��~�u�F0�F��F!�l��������F��F!�F@�R��������6��p6���h*���:vvK�vVQ�^�^
��6���6�������6���Q+����� _�N�Y^����.�������6���	������.���*�����6���<I�����.������:Vs
�'I�����.���*���:v
�I�����.����v�f�����I�����.���*Ҋ���6�����I�����.�������s�V����:v
}*Ҋv
����6����I�����.����[���I��~�~����s�b�.����@���I�<;t!�؀�0��	w9�f�F����FÈF������I��؀�0��	w�f�F����FÈF�ފ���.���	�����I��؀�0��	w�f�F����FÈF�ފ���.���
���€�s*����~
u6����~
u6����V
�t��:Vr�V���r�Q+Ɋʀ���*�Ѱ �Y:Vr*V��:vv�v���[�*���:v
s�v
�^�5���:vv�v�(���:Vr*V��:vv�v�V�����v
�t��v
:vr�v�V
�t��:Vr�V�������:v
}�v
���VQ�^����6���6����^��6���+�~���6����N� �*Ҋ���6���Y^����6����F<u�^�~<u�^
�]*Ҋv
����6����^*��8�F<u�^�T<u*��4*Ҋv
+��^��F��<t7<t��6���*�*�Q� �N���}�Y��Q����6���+�|� ���Y���Q��6���+�|� ���Y���6����VQ�^�^��6����΃�6���������6+��~����6����N� ��*Ҋ���6���Y^�����V
�t��:Vr�V���v��F
�u���:Vr�V���^��v
�t��:vv�v�V
�t��:Vr�V���7���:v�-��v����V�v�2��V�v����:v
}�v
�.����Nt

�F�
��F�����F<u����<u����<u�~�t�䈀���<u�̀��<u�p�~�u��$w����������
�븁~�u�,|<<�؀��.
���,,
|(<�؀�.
���,
|<��.���R�V���Z�g��F��}*�:Fw�^��}*�:^w:�w
�F
�^��*��&��v��*�:vv�v���F
�u���:vr�v����������.6S���������������6�����������������������������������������������������������������������������������������������������������������������������������������������������������cl����((�����S6�������u�������������Q������������������������((����������������������������������������������������������������������������Ub6C~0P������Su��������������dx,~����������7���������������������������������������������������������������������������������������������������������������������������������������������
 "$&(*,.02468:<>@BDFHJLNPRTVXZ\^`bdfhjlnprtvxz|~����������������������������������������������������������������@ `P0p� 
���8
�Ë 
���8
��,��@�� �`�@�� �`	
�
@�� 
�
`�@�� �`�@�� �`�@����P!mm_vpadZERO	bcolor�mm_scr�mm_cup~mreg132@AZERO	0csival�mm_ed0MM_INVIS	mm_newcmm_hprMM_SROW	fcolor�mm_sgr�mmspec(creg40mm_cuu�mm_hvp,scrolldown�mmbeeps_mm_voff_�mm_dl�creg80mm_elPreinit mmcrtsav_int11_CLOWER	cmm_il�mm_e0�mm_cr�mminit�mm_e1xmm_132�rowend
rowtab�mmgo_Pmm_e2hmm_vprxmm_ssr7IOUSR	IO_BASE	IO_IOC	newcrtqmreg80 MM_DATA	NCB	mm_riuMM_BASE	mm_si�mmputc�IO_SEG	INTENSE	MM_COL	IOSYS	NHB	�ewait�mm_so�REVERSE	pMM_MODE	COL	
NRB	�NCR	islock_mm_chaMM_NCOL	MM_FUNC	eval�repos�MM_SCOL	mm_von_�mm_cgh�uds_MM_POS	SPACE	 asctab�mm_cgl�BLINK	�SEMIC	;MM_ROW	mm_hpa�mm_cbt�esctab�POS	mm_dmi�mm_cubMM_BROW	
mm_indSmm_emi�csgtab�
mm_esc6scrollupBmmesc_mmvcnt_mmdata
MM_ATTR	
mm_cudUcoltab�csitab�	mm_cnl6MM_EROW	mm_cufbcreg1320mm_oldlmm_cplCmm_chtMM_N1	ROW	csi_gt�mmbell.MM_N2	exit�ATTR	MM_IBROW	csi_n1QMM_LROW	csi_n2zMM_PORT	mm_eaMM_IEROW	 
 6
'hI$k'�^'�] �7 0###30o �0�0� �0�0� �0�0� �00 00&'*]'1#P#U#^ z#�0� �#� � � �0�0� �#� #$ 1040G L0O0x �0� �0�'�0�'�000>0A0P0S0`0|0�0�#�#�#�#�#�0�0�'�@00#'#b0v#�0�#�0�'�@0�#�#�#�#�#�0�0�00*0Q0[0a0j0s0�0�0�0�0�   )050b0v0� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 	 	 	 	 	 
	 	 	 	 	 	 	 	 	 	 	  	 "	 $	 &	 (	 *	 ,	 .	 0	 2	 4	 6	 8	 :	 <	 >	 @	 B	 D	 F	 H	 J	 L	 N	 P	 R	 T	 V	 X	 Z	 \	 ^	 `	 b	 d	 f	 h	 j	 l	 n	 p	 r	 t	 v	 x	 z	 |	 ~	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
  
 "
 $
 &
 (
 *
 ,
 .
 0
 2
 4
 6
 8
 :
 <
 >
 @
 B
 D
 F
 H
 J
 L
 N
 P
 R
 T
 V
 X
 Z
 \
 ^
 `
 b
 d
 f
 h
 j
 l
 n
 p
 r
 t
 v
 x
 z
 |
 ~
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
      
             " $ & ( * , . 0 2 4 6 8 : < > @ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � �$�$�$�$�'�^0707070064030107521006440000000000000000011777770507310750700004000000012502/newbits/kernel/USRSYS/lib/fl.a]�fl.o�(��$v��X.VWU��j�����jjp�����jq��������ƈu7�v
�x������
��%��
��
���t,��
��t"��
�������
��t����%@��
�>�
tt�|���jh��r���h�j�g���jh��\���jh��Q�����
�=t��
�Ph��:���j�!	���v��zP�	���x��P�	��W�����_^�VWU��>�
tj�����jjjh�
������.jh�������_^�VWU�젔
����F%���;�s�v�������~��������u��_^�VWU��j�v�v
h�
�}����_^�VWU��j�v�v
h�
�c����_^�VW��~
@t���F%������v�4����F��F@P�&����F��~�wʋF�;Es��Ft�E�f�F��	�E�f�F������e����+ҹ	�����������F���E����j@�vh�h�
�����_^�VW��v�D��	�ȋ�+�D
T-���F��\�����D
;��v�LV�v��c�|@t"�\�����F�;��r�D�D�D@t����D�t�|@u���8����>r
u�6r
��t
�7�6t
�>�
u�W�����_^�VW��6r
��
�=v�����.��#<�#a�.�u��j�D%���Ph~
�����D%�����
�D%��
��
��ظ���࢖
�D�T�v
�x
�D
�|
��
���Ƈ�
�D��	�z
�u�z
��
��
��F��t����F�;F�t��
�Ph��:�����
��Ƞ�
�#�uG��
��
��
��Ƞ�
��
Ph������;jh jdh�
�������
���Ƈ�
��
����
���Ƈ�
��
��Ƞ�
��
Ph����������
��؀��
u%��
������
j�����
�P�����
��|
��>�
B��
�>�
t!�|
��>�
��
��>�
��
��
��>�
��
��|
��>�
��
��>�
��
��
��>�
��
j�����
��ȡ�
���P�
���>�
Pt"��
��؀��
u��
��P���
��؀��
t��6�
������
���|tjh jh�
����������
���Ƈ�
���
jh�h�
�����t���
���Ƈ�
�f��
�|t�|uP��
�E�6�
h�6x
�6v
j�b���
�u>�6x
�6v
h�t�J���h�
�A����LV�N���+���
�M�6�
�t�j����W�����
��ȡ�
���P�����|@u%��
�P�����6�
������
�P����h��H�6�
����6�
����6�
�����
�P����6�
�����
��؊��
�P�{��h��r����
���
���Ƈ�
j�h���h�
�_�����
������t+��
��
�=}
��
���Ƈ�
�-�X�LV�C���!�z
u�D���|
�v
�x
��
�>�
u�����
�Ph j��h5������_^�VW�����F���
�=u	�F��
���v������_^�VWU��v���%����؀��
uO�ށ������=u O���%����؀��
u��%=u+����_^�VW��W��F�+����}H��
�#�uF����
|����
���
�=|���� �
��
�;�uր>�
t��?�>�
u��������
��Ƞ�
��
Ph�������>�
u�.�v�������_^�VWU��j�����h�
����jh�����jh�������
�=t��
�Ph�����j�v���v��zP�e���x��P�Y��+���
���
���
���
�r
���t+��
�Ph9�B����|�LV�L���r
���t;|t�jh jh�
������
�_^�VWU�������2�>�
t���V������_^�VWU��v��r
��
V������_^�VW��F����F�+�h������ȋ����u�N�u�hL������@th���������sɋ�G�ƈ��
뾉>�
jh��i���+�h��^����ȋ����u�N�u�h]�F�����@th��7�������sɋ�G�ƈ��
뾉>�
�v������_^�VWU��+�h�����%�=�tNu�ho�������vh�������_^�VWU���6�
�6�
��
�%Ph������>�
|*��
�����t	h�������
�����t	h������>�
|~��
�����t	h��s�����
�����t	h��^�����
�����t	h��I�����
�����t	h��4�����
����� t	h�������
����ǀt	h
�
����>�
|i��
�����t	h
������
�����t	h.
������
�����t	h>
������
����� t	hP
�����
�����@t	h`
���hp
����_^�1Jp����@(#*P�(#*PP#*Ph(	#*P�(	#*P�P	#*P`	PT@PTfd: DMA page straddle at %x:%xfdsfd%d: <Door Open>
flintr: timeout
flsense: timeout
flput: timeout
fd%d: head=%u cyl=%u <Not Ready> <Equipment Check> <Missing Address Mark> <Write Protected> <No Data> <Overrun> <Data Error> <End of Cyl> <Missing Data Address Mark> <Bad Cylinder> <Wrong Cylinder> <Bad Data CRC> <Data Deleted>
clrivec_int11_dmaoff_flrecov_1setivec_sphi_u_fldone_	drvl_inb_fl_hlt_xdmareq_outb_nulldev_getubd_blkmvdmaunlock_fl_hut_zdevmsg_timeout_dmago_bdone_fl_srt_vpanic_dmaon_spl_flcon_|printf_flunload_�dmalock_ �'�
 � � � �'�
 � � �777	$)$/%9%A%E%P%Z7_%e%x%|7�7� �7�7�7�%�%�7�0�$�$�0�$�0�7�%7%7'7(%70M$b'i%~7�%�7�'�0�$�7�7�' '$'*'3';%>7A$}7�$�7�%�%�%�%�%�0�7�%�%0
        !'%0.$<%@7C%R%[%^%k%t%x%~%�%�%�%�%�%�0�%�7�%�%�%�%�%�%�7�0� �%7%%%0%%&%*%07=0C%F%M%S%Z0_%e0j%q0u%x%}%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�0�%�%�0�%�%�%�%�%%%0%0! ,%1740:%=%D%I O%R7U0_%b%i%q%�%�%�%�7�%�%�$�7�%�7�0�0�%�%�7�0�%�%�0%0%0%#0(%407%>0A%H0K%Q0V%]0`%f%m0r0{%�0�%�%�7�%�7�%�%�%�%�%�0�0�%�%�%�%�%�%�0% 0$77'%-%90<7B%b$s%�7�%�%�%�%�%�%�%�0�%�0�%�%7%' 7(79%?7B7M7X%^%g7o0w$}$�0�$�0�%�%�%�%�%�%�$�7�0�%� �%�7�%�7�0	%	0	7	%$	%(	7-	7B	7M		$b	7e	7t		%�	%�	7�	7�		$�	7�	7�		%�	%�	7�	7�		$
7
7
%,
%0
%3
$;
7>
%E
%K
$W
7Z
%`
$l
7o
%v
%|
$�
7�
%�
$�
7�
%�
$�
7�
%�
$�
7�
%�
$�
7�
%�
$�
7�
%�
%$
7%$"7%%+$77:%@$L7O%U$a7d$j7m0707070064030066661006440000000000000000011777770507310751000004000000040012/newbits/kernel/USRSYS/lib/gr.a]�mm.o�(�������VW��v�D u2V������F��|$�F��F��F��F��F��F�Ph�����ǃ>�u��Vh`j
h�����_^�VWU�������>}2�h�jC����h�jB�w���j
jB�m���ja�e���
��>~�uja�K���%��Pja�?����>t��P�-����V�!����v�����vh`j
h�����_^�VWU��>�~�>�~	��u����_^�VW��v
�D�F��<uV������u����Dup� t'���F��jjhh�����v������ы>�E$E&t&�w��t�p��F�;Du��6V�]����t+��V�P����|u��� t��V�2����u��_^��ismmfunc_mmtim_mmbeeps_mm_voff_mmcrtsav_�mmgo_mmwatch_nondsig_sphi_u_inb_outb_istty_kbunscroll_ttout_mmwrite_ cprocp_timeout_mmstart_mmtime_`spl_mmvcnt_�mmesc_ttstart_sleep_70;%D%K O'T7W7f'l's7|7�7�7�
'�'�7�
7�'�'�7�'�7�7� �'�7�$$$7760@'M7T'['g7j7s'|7�7�
'�	7�7�'�'�	7�gr.o�(����d2nonedev_grread_nulldev_grwrite_grcon_''''
''''''gras.o�(����T
 (
�8(+dp VWU����^�w�O�?t��۽T
�v�V�F�~�F#F&1��&1�� +��f����.����ڀ~(u����F#F&1��&1�� [�^�v�V�~��������^���O+OO]_^�6�c����Q��V���B.���JK}�Y��������$t������F���F���F�F�F��F�FP*Ҋv�v
�^�^+��F�6���y6��s*���:v~U�vVQ�^�^
��.���.�������.���Q+���VWQ�Y_^�� �� �F#F_W���_�� ���Y^�D����.����ڀ~(u����I�����.�������I�����.����~(t�V*������������Ȏػ��3F#F�W�3F#F&���N�3F#F��3F#F&���N�3F#F��3F#F&���N�3F#F��F3F#F&�_^+���:V}
�I�����.���*���:v�3��v����oV*�������n�����ػ��3F�W&�!��O�3F�&�!��O�3F�&�!��O�
f3F�&�!_^+���:V}
�I�����.���*���:v����v�j�����I�����.���*Ҋ���.�����I�����.�����}�V����:v
}*Ҋv
�|��H���I��~�~����.���	�2���I�<;t!�؀�0��	w9�f�F����FÈF���	���I��؀�0��	w�f�F����FÈF�ފ���.���
�����I��؀�0��	w�f�F����FÈF��<htL<ltX�������I��؀�0��	w�f�F����FÈF��<hu��<lu�������€�*����~
u6����~
u6����V��}*�:Vr�V���d�� QV+Ɋʀ���*�ыv�~Pu���A��F#ƫ&�A�&�EN&�AN&���&���&���F#�&�����+�^Y:V|*V��:v~�v�����*���:v
s�v
�����~u�F����~u�F�����:vv�v�����:Vr*V��:vv�v�V�����v��*�v
:vr�v�V��*�:Vr�V���{���:v
}�v
�n�VQ�^����.���.����^��.���+�~1��VWQ�Y_^�� �� �.���W���F#F�_�� ���*�Y^��6�� ��F<u�^�<u�^
�r*Ҋv
����.����^*��<�F<u�^��<u*��H*Ҋv
+��^��F��<u�<t,��.���*�*�Q�F#F��������� ��}�Y��RQW�F#F��.�������.���+�~��WQ�Y_�� �Y����.���+�~x�׋���P������P������P������������P������P������P�����+�YZ���RQW�F#F��.�������.���+�~��WQ�Y_�� �_+ɊN*ʀ~(u��׋���P������P������P������������P������P������P�����+�YZ�t�6���VQ�^�^��.����΃�.���������.+��~3��VWQ��Y_^�� �� �.���W���F#F��_�� ���*�Y^�	��V��*�:Vr�V������F
�u���:Vr�V������v��*�:vv�v�V��*�:Vr�V������:v���v�R��V�v���V�v����:v
}�v
�����Nt

�F�����F���F<u�F���F�F�!<u�F���<u�F���<u�F����D��~Pu�F(�����F�����~(u�FP���F����F��}*�:Fw�^��}*�:^w:�w
�F
�^��*�����v��*�:vv�v����F
�u���:vr�v����������#���Rh����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#�������������������������l�
�����������������������������������������������������������������������������������������u�����#�����v����������������x����������������|�������������@��@��
@��
@��@��@��@� �!#@$�%�&(@)�*�+-@.�/�02@3�4�57@8�9�:<@=�>�?VWU��n
�~t����~���؋FF=@wW�F+ҹP������������u�P+�;N~�N�-)NNV�^�� �P+�;N~�N�)NN�� +���]_^�VWU��n
�~t��؋v�����FF=@wҋF+ҹP�������������u�P+�;N~�N�)NNW�_�� �P+�;N~�N�)NN�� +��ĺ���ú���6��ä�����Pmm_vpa�ZERO	mm_scr�mm_cup�AZERO	0csivalimm_ed�mm_new�mm_hpr�MM_SROW	mm_sgrmmspecmm_cuumm_hvp�scrolldownmmbeeps_mm_voff_?
mm_dlBANKSZ	 mm_el�ewait0�XMSR	�ewait1Tmmcrtsav_CLOWER	cread1~fontw_page1
read2�mm_ilmm_e0�mm_cr�mminit�page2
mm_e1�csi_q�rowtab�mmgo_mm_e2�mm_vpr�mm_ssr|HLOWER	hIO_BASE	IO_IOC	mm_ri�MM_BASE	NRB2	@grread_;mm_sihNCR2	mmputc�IO_SEG	NRB4	�MM_COL	IOSYS	NCR4	NHB	Pewait�mm_soRCOL	
IO_SEEK	NRB	�putc16�crtdataNCR	grwrite_�islock_MM_FLIP	mm_chaMM_NCOL	MM_MASK	MM_FUNC	done�eval�CSR	�repos�MM_SCOL	mm_von_F
mm_cgh�uds_MM_VIS	MM_POS	asctab�mm_cgl�SEMIC	;MM_ROW	mm_hpaxmm_cbt�esctab�	MSR	�POS	mm_dmilmm_cub�MM_WRAP	MM_BROW	
mm_ind�mm_emi
mm_escputc8Vscrollup/mmesc_mmvcnt_mmdataT
MM_ATTR	
mm_cud�mm_cqh�VSEG	�csitab�
mm_cnl#MM_ULINE	MM_EROW	mm_cuf�mm_old�mm_cpl�mm_chtMM_N1	ROW	mm_cql�csi_gtummbellMM_N2	exitPMM_CURSE	MM_IBROW	csi_n1MM_LROW	csi_n2GMM_PORT	mm_eavMM_IEROW	 T
'(O$- W'�e'�d �0''d = B K0 � �0� �0�'� @0L0R �0�0�0� � � �00 00E p0s0�0�0�0�0�0�'�0�'000�0�0�0�0�0�0�0�00   % / L0j'oB0t0�0� �0�0� �0� 
  20� � �0'B0 % / ; W0v0�0�0�0�0�0�0�0�0�000P0f0z0�0�0� � � � � � � � � � � � � � � � � � � � � � � � 	 	 	 	 		 	 
	 	 	 	 	 	 	 	 	 	 !	 #	 %	 '	 )	 +	 -	 /	 1	 3	 5	 7	 9	 ;	 =	 ?	 A	 C	 E	 G	 I	 K	 M	 O	 Q	 S	 U	 W	 Y	 [	 ]	 _	 a	 c	 e	 g	 i	 k	 m	 o	 q	 s	 u	 w	 y	 {	 }	 	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 
 
 
 
 	
 
 
 
 
 
 
 
 
 
 
 
 !
 #
 %
 '
 )
 +
 -
 /
 1
 3
 5
 7
 9
 ;
 =
 ?
 A
 C
 E
 G
 I
 K
 M
 O
 Q
 S
 U
 W
 Y
 [
 ]
 _
 a
 c
 e
 g
 i
 k
 m
 o
 q
 s
 u
 w
 y
 {
 }
 
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
     	  
          ! # % ' ) + - / 1 3 5 7 9 ; = ? A C E G I K M O Q S U W Y [ ] _ a c e g i k m o q s u w y { }  � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �'LO'�O'O
efontw.o�(���@�0�3�����0��?�������??��00������?���?���?��������������?���?�������������������?�0000?����������������???�������?�?�������?�����?���<?�<<<?�<�������?�?���������������<������<?�����?�<�<�<�<�<�<�?�������?����<�<<<<�<���������?��?���?�?�����?�������<��<����00��00�?���������?��������������<<���<���<����?��?�<����<��<<�<�<��?����?<<���������<�����<���?�����?���<��<�?������<�<�<?�������?�?��<<�?�<��?��<<�<�<?���<������������<<�<?��<����<�<?����<��?��<�<?��<�<?�?��<�<?�<�?�����������<��?�?���<���<<<���?��<�������?��<��<�<���<�<��<�<<?�<<<����<���<���<�<<<<<<<�����<<?�<<����<<?�<<��<����<<��<�<�<���<�<�<��������������?��<<<<�?�?�<��<�<<<<<<���<�����<�<�<�<�<�<�<�������<?��<�<�<�<�<?���<<<<?�<<�?��<�<�<��?�<��<<<<?�?�<��<?��<����<?�?�3������<<<<<<<<<<<<�<<<<<<<<<<���<�<�<�<�����<�<<���<��<�<<<<<<<���������<�<������<��<���������<<�������?���?<<<<?�<<<<��?��0��0?����?�����?<?������?��<�<��<<�?<����?��?��<<?�<<<<<<?���������?��<<<<�?�<�<<?������<�<�<��<<<<<<<<�<<<<<<���<<<<?�<�?<����?�����?<<<<?��?��?�?�0����������<<<<<<<���<�<�<��<���?�?���������?��?����<�����?���?�����??<���<��<�<�<��BXXXXXXXX	��BXXXXXXX_	��BXXXXXX_X	��BXXXXX_XX	��BXXXX_XXX	�?BXXX_XXXX	��BXX_XXXXX	��BX_XXXXXX	��B_XXXXXXX	?�fontw_BXXXXXX__	��BXXXXX_X_	��BXXXXX__X	��BXXXX_XX_	�<BXXXX_X_X	�3BXXXX__XX	�BXXX_XXX_	��BXXX_XX_X	��BXXX_X_XX	��BXXX__XXX	�?BXX_XXXX_	��BXX_XXX_X	��BXX_XX_XX	��BXX_X_XXX	�?BXX__XXXX	��BX_XXXXX_	��BX_XXXX_X	��BX_XXX_XX	��BX_XX_XXX	�?BX_X_XXXX	��BX__XXXXX	��B_XXXXXX_	?�B_XXXXX_X	?�B_XXXX_XX	?�B_XXX_XXX	??B_XX_XXXX	<�B_X_XXXXX	3�B__XXXXXX	�BXXXXX___	��BXXXX_X__	�0BXXXX__X_	�BXXXX___X	�BXXX_XX__	��BXXX_X_X_	��BXXX_X__X	��BXXX__XX_	�<BXXX__X_X	�3BXXX___XX	�BXX_XXX__	��BXX_XX_X_	��BXX_XX__X	��BXX_X_XX_	�<BXX_X_X_X	�3BXX_X__XX	�BXX__XXX_	��BXX__XX_X	��BXX__X_XX	��BXX___XXX	�?BX_XXXX__	��BX_XXX_X_	��BX_XXX__X	��BX_XX_XX_	�<BX_XX_X_X	�3BX_XX__XX	�BX_X_XXX_	��BX_X_XX_X	��BX_X_X_XX	��BX_X__XXX	�?BX__XXXX_	��BX__XXX_X	��BX__XX_XX	��BX__X_XXX	�?BX___XXXX	��B_XXXXX__	?�B_XXXX_X_	?�B_XXXX__X	?�B_XXX_XX_	?<B_XXX_X_X	?3B_XXX__XX	?B_XX_XXX_	<�B_XX_XX_X	<�B_XX_X_XX	<�B_XX__XXX	<?B_X_XXXX_	3�B_X_XXX_X	3�B_X_XX_XX	3�B_X_X_XXX	3?B_X__XXXX	0�B__XXXXX_	�B__XXXX_X	�B__XXX_XX	�B__XX_XXX	?B__X_XXXX	�B___XXXXX	�BXXXX____	�BXXX_X___	��BXXX__X__	�0BXXX___X_	�BXXX____X	�BXX_XX___	��BXX_X_X__	�0BXX_X__X_	�BXX_X___X	�BXX__XX__	��BXX__X_X_	��BXX__X__X	��BXX___XX_	�<BXX___X_X	�3BXX____XX	�BX_XXX___	��BX_XX_X__	�0BX_XX__X_	�BX_XX___X	�BX_X_XX__	��BX_X_X_X_	��BX_X_X__X	��BX_X__XX_	�<BX_X__X_X	�3BX_X___XX	�BX__XXX__	��BX__XX_X_	��BX__XX__X	��BX__X_XX_	�<BX__X_X_X	�3BX__X__XX	�BX___XXX_	��BX___XX_X	��BX___X_XX	��BX____XXX	�?B_XXXX___	?�B_XXX_X__	?0B_XXX__X_	?B_XXX___X	?B_XX_XX__	<�B_XX_X_X_	<�B_XX_X__X	<�B_XX__XX_	<<B_XX__X_X	<3B_XX___XX	<B_X_XXX__	3�B_X_XX_X_	3�B_X_XX__X	3�B_X_X_XX_	3<B_X_X_X_X	33B_X_X__XX	3B_X__XXX_	0�B_X__XX_X	0�B_X__X_XX	0�B_X___XXX	0?B__XXXX__	�B__XXX_X_	�B__XXX__X	�B__XX_XX_	<B__XX_X_X	3B__XX__XX	B__X_XXX_	�B__X_XX_X	�B__X_X_XX	�B__X__XXX	?B___XXXX_	�B___XXX_X	�B___XX_XX	�B___X_XXX	?B____XXXX	�BXXX_____	�BXX_X____	�BXX__X___	��BXX___X__	�0BXX____X_	�BXX_____X	�BX_XX____	�BX_X_X___	��BX_X__X__	�0BX_X___X_	�BX_X____X	�BX__XX___	��BX__X_X__	�0BX__X__X_	�BX__X___X	�BX___XX__	��BX___X_X_	��BX___X__X	��BX____XX_	�<BX____X_X	�3BX_____XX	�B_XXX____	?B_XX_X___	<�B_XX__X__	<0B_XX___X_	<B_XX____X	<B_X_XX___	3�B_X_X_X__	30B_X_X__X_	3B_X_X___X	3B_X__XX__	0�B_X__X_X_	0�B_X__X__X	0�B_X___XX_	0<B_X___X_X	03B_X____XX	0B__XXX___	�B__XX_X__	0B__XX__X_	B__XX___X	B__X_XX__	�B__X_X_X_	�B__X_X__X	�B__X__XX_	<B__X__X_X	3B__X___XX	B___XXX__	�B___XX_X_	�B___XX__X	�B___X_XX_	<B___X_X_X	3B___X__XX	B____XXX_	�B____XX_X	�B____X_XX	�B_____XXX	?BXX______	�BX_X_____	�BX__X____	�BX___X___	��BX____X__	�0BX_____X_	�BX______X	�B_XX_____	<B_X_X____	3B_X__X___	0�B_X___X__	00B_X____X_	0B_X_____X	0B__XX____	B__X_X___	�B__X__X__	0B__X___X_	B__X____X	B___XX___	�B___X_X__	0B___X__X_	B___X___X	B____XX__	�B____X_X_	�B____X__X	�B_____XX_	<B_____X_X	3B______XX	BX_______	�B_X______	0B__X_____	B___X____	B____X___	�B_____X__	0B______X_	B_______X	B________	0707070064030066621006440000000000000000011777770507310751400004000000006445/newbits/kernel/USRSYS/lib/hs.a]�hs.o�(���
����VW�i�^P�6������b�uhD�������i�^P�6b������F��F�;�|���^������iF�^b��j��P����j��@P������@P�~����t��q���\�D��D��^�������D��D���(���)�|��)����㋇��F�h���P�)����v�W�����F���P��@P����j��P�����6d�F��3��_^�VWU��>bt
�6b������_^�VW��~��i�^b���|t�D@P����������t�����t�'�r�D�D=uZV�����F�t;�r��F��DP�e������L ��t�d���� t�L�v��?����
�d���LV����vV�"����2�_^�VW��~��i�^b���|uJV������F��~�t8hfhj
hf�����jjhhf�������Z*�:�[u̓~�t��N����L���_^�VWU��v
jV�~��i�^bP�����_^�VWU��v
jV�~��i�^bP�d����_^�VWU���v�v
�~��i�^bP�?����_^�VWU���v�v
�~��i�^bP�����_^�VW��v��X*�:�Yt2��Y*�ȋ�ي�Z*�PV�������Y*�=�rƄY����Y�¿���Z*�؊�[*��+���Ǚ.�>���O|9V�����F��|+��Z*�ȋ�ًF���\��Z*�=�rƄZ����Z��V�k����|tVh�j
��HP�T����_^�VW��6b�|u��DtL�DP�)�������t7��t��t�d����L ��t�� t�L��d��V������DP���������t�Dt	jV�������t:��X*�ȋ���F��t�����^���Z�Dt��X��X*�=rƄX�� tC�D u<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�P�����[��[*�=rƄ[��^��;dw����_^�VW��v���F�+���)t��W�DP�������)����㋇����t+h��DP�����W�t���������P�D@P�������,%�=t=t���
��W�DP����j�D@P�����v�������_^�VWU��v�j����DP�^������� t<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�.�����[��[*�=rƄ[W�����_^�VWU�����x�x;v|�x�x�_^�VW����t��F��F��F�;�}?iF�^��>b�}t)iF�^��>b��(����狅�F��F�;F�}�F��F��F�븋F�;t.��.�>��v�o��&���~�th��6�Y�����_^�d����
+�Y~��	Y@��`@:0 dddddddd�,��X �@hsload: can't allocate tty's
free_ttsignal_hscycle_�hsparam_�altclk_in_hsclose_�altclk_out_kclear_sphi_tthup_u_hsioctl_�hsread_Ypoll_hz_cs_sel_inb_outb_nulldev_ttsetgrp_ttclose_ttin_ttout_poll_owner_poll_rate_ttioctl_ttread_hswrite_~timeout_hsstart_�alloc_HSNUM_�wakeup_hsopen_+spl_hspoll_�HS_PORTS_�ttwrite_printf_allkp_ttstart_hsintr_�sleep_ttopen_hscon_�ttpoll_ � �'� � � �'�'� � � �$'&7%$7"%0($,%376$E0J$T%]7j7v7�0�7� � �$�$�7�7�7�7�%0%%7"%>7N']
0a'e'm
7*7�7�7�!0�7�0�%�7%'% 7#%073)0S%q7u%�7�$%�7�%�7�,7 Q7Z7�' �7�%�0�7�7	7!797W7�%�0�7�7�$7"7,7=7i7v7!0�7�7�7�7�!0�%�%%%%'0%$6%C%T$a'~'� �%�7�'� �'�7�'�0707070064030066421006440000000000000000011777770507310751400004000000003037/newbits/kernel/USRSYS/lib/lp.a]�lp.o�(״�:h%VWU��>Ht��H�t�2�t�8�t�>�0�<tQ�Du$h��4�����>Ou��4����=�u�Lj�@@P�����>Ou�j�@@P�p�������_^�VWU����_^�VWU��F%=r��s�~��k�0���Du�(��Dt��Dt�'�E�>t�@P��������u�&�%�d��F%�
	D�>t
�>�}t�v�_^�VWU��v��k�����2���_^�VWU��N��k�0���^
�?uI�v
�������}��@P�z��������t�W�4�i���j
�@@P�\���j�@@P�O�����v
�D������|u�D�uN��-=wA����.����j V�M���D�L��u��j
V�6���D��L��DWV�����G$G&t�����t���_^�VWU��v�>�@P���������u#Ou������LjjjV����W�������v
�4�y���j
�@@P�l���j�@@P�_����_^�VW��F��0�<t6�Du�����F��Dt�@P�(������ǀt߁d��V�����у~�thJh��6hJ������_^���6Q��xxnonedev_nondsig_sphi_u_inb_outb_nulldev_iogetc_LP0_OK_timeout_cprocp_LPTIME_wakeup_spl_LPWAIT_sleep_lpcon_LPTEST_  ''  "'$'&'( * ,%0
%$$$%$-$3$;$@7T$[7c7z$�7�0�'�$�0�'�$�7�'' 
''
00$I$a7q0}7�7�7�7�7� � � � � � � �0�00'$
7/'7$H7O7`7q7x
7�7�7�$�7�7�%� �$�%7	0707070064030066221006440000000000000000011777770507310751500004000000017452/newbits/kernel/USRSYS/lib/mm.a]�mm.o�(������VW��v�D u2V������F��|$�F��F��F��F��F��F�Ph�����ǃ>�u��Vh`j
h�����_^�VWU�������>}2�h�jC����h�jB�w���j
jB�m���ja�e���
��>~�uja�K���%��Pja�?����>t��P�-����V�!����v�����vh`j
h�����_^�VWU��>�~�>�~	��u����_^�VW��v
�D�F��<uV������u����Dup� t'���F��jjhh�����v������ы>�E$E&t&�w��t�p��F�;Du��6V�]����t+��V�P����|u��� t��V�2����u��_^��ismmfunc_mmtim_mmbeeps_mm_voff_mmcrtsav_�mmgo_mmwatch_nondsig_sphi_u_inb_outb_istty_kbunscroll_ttout_mmwrite_ cprocp_timeout_mmstart_mmtime_`spl_mmvcnt_�mmesc_ttstart_sleep_70;%D%K O'T7W7f'l's7|7�7�7�
'�'�7�
7�'�'�7�'�7�7� �'�7�$$$7760@'M7T'['g7j7s'|7�7�
'�	7�7�'�'�	7�mmas.o�(�����VWU����^�w�O�?t��۽�V���t�~t���t����%�v�V�F�~+ۊf
�f[�f
�^�v�V�~�V��^���B���J��B���V���)��X��^���O+OO]_^�6�c�Y�%0=0t
�F��F��F�V���!�V��B*��J�
�B*��V��*��B��F��f
�F�v�v
�^�^+��F�6��n6���f*���:vvK�vVQ�^�^
��.���
.���
����.���
Q+����� _�P�Y^����.��
����.��
��������.��
����.��
�\I�����r.����€�P}�EI�����r�.���~u�����+I�����r�.��*���:v�I�����r�.���v�H��v���I�����r�.��*Ҋ���.���
��I�����r�.������}�O��:v
}*Ҋv
����.���
�I�����s�Z�.������I��~�~����s�?�.�������I�<;t!�؀�0��	w9�f�F����FÈF�������I��؀�0��	w�f�F����FÈF�ފ���s���.��	����I��؀�0��	w�f�F����FÈF��<htL<ltX���s���I��؀�0��	w�f�F����FÈF��<hu�<lu��i����€�*��H��~
u6��J��~
u6��:��V��}*Ҁ�Pr�O��Q+Ɋʀ���*�Ѱ �Y��Pr��P��:vv�v�����*���:v
s�v
�����~u�F�~u�F����~u�F�~u�F����:vv�v���€�Pr��P��:vv�v�O���v��*�v
:vr�v�V��*Ҁ�Pr�O�]���:v
}�v
�P�VQ�^����.���
.���
�^��.���
+�~���.���
�P� �*Ҋ���.���
Y^�����6����F<u�^�~<u�^
�]*Ҋv
����.���
�^*��8�F<u�^�T<u*��4*Ҋv
+��^��F��<t7<t��.���
*�*�Q� �P���}�Y��Q����.���
+�|� ���Y�u�Q��.���
+�|� ���Y�_�6��g�VQ�^�^��.���
�΃�.���
������.+��
~����.���
�P� ��*Ҋ���.���
Y^������V��*Ҁ�Pr�O����F
�u��Ѐ�Pr�O����v��*�:vv�v�V��*Ҁ�Pr�O����:v���v�c��V�v���V�v����:v
}�v
�7����Nt

�F���F�����F<u��x�<u����<u�~�t�䈀���<u�̀��<u�p�~�u��$w����������
��<u�~�u��p����������
�뜀�뗁~�u�,|<<�؀��.
��
�,,
|(<�؀�.
��
�,
|<��.���
R�V���Z����F��}*�:Fw�^��}*�:^w:�w
�F
�^��*����v��*�:vv�v�u��F
�u���:vr�v�_�yyyyyyyR�y�yyyyyyyyyyyyy6yyyy��������������������������������������������������������������������������������������������������������������������������������yyyyyyyyyyyyyyyyyyyyyyy��yyyyyyyyy�yyyyyyy�yyyyyyyyyyyyyQyyyy]y�yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy��y
��}?�R��ygyyy��yyyyyyyyyy`syy����yyyyy�yyyy�yyy�yyyyyyyyy
 "$&(*,.02468:<>@BDFHJLNPRTVXZ\^`bdfhjlnprtvxz|~�����������������@�� �`�@�� �`	
�
@�� 
�
`�@�� �`@ `P0p����!����)�����mm_vpa�ZERO	bcolor�
mm_scr�mm_cup�AZERO	0csival�mm_ed�MM_INVIS	mm_new�mm_hprsMM_SROW	fcolor�
mm_sgr�mmspecmm_cuu
mm_hvp�scrolldownVIDSLOW_*mmbeeps_mm_voff_�
mm_dlmm_el�mmcrtsav_int11_CLOWER	cmm_ilmm_e0�mm_cr�mminit�mm_e1�csi_q�rowtab�
mmgo_mm_e2�mm_vpr�mm_ssr�HLOWER	hIOUSR	IO_BASE	IO_IOC	NCB	mm_ri�MM_BASE	mmputc�IO_SEG	INTENSE	MM_COL	IOSYS	NHB	�ewait�REVERSE	pCOL	
NRB	�NCR	islock_mm_cha?MM_FUNC	evalyreposgMM_SCOL	mm_von_mm_cghuds_MM_POS	SPACE	 NCOL	Pasctabmm_cgl/BLINK	�SEMIC	;MM_ROW	mm_hpa`mm_cbtesctabPOS	mm_dmi]mm_cubMM_WRAP	MM_BROW	
mm_ind�mm_emimm_esc6scrollupmmesc_mmvcnt_mmdataMM_ATTR	
mm_cud�mm_cqh�coltab
csitab	mm_cnlMM_EROW	mm_cuf�mm_old�mm_cpl}mm_chtRMM_N1	ROW	mm_cql�csi_gt�mmbellMM_N2	exitPATTR	MM_IBROW	csi_n1QMM_LROW	csi_n2zMM_SLOW	MM_PORT	mm_eagMM_IEROW	 '?$'�U'�T7�0'T' - 2 ; W `0c n w � � � �0�0� � �  0, 1040G L0O0x0� �0�0�0�0000'(0-'80=0P0x0{0�0�0�0�0�0�00 $ ) 3 @ R0X0['`70e0r � �0� �0� �0'70   * 6 B U0[0^0q0�0�0�0�0�0�0�0�0�0�0� ~ � �0�0�0�0  
             " $ & ( * , . 0 2 4 6 8 : < > @ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 	 	 	 	 	 
	 	 	 	 	 	 	 	 	 	 	  	 "	 $	 &	 (	 *	 ,	 .	 0	 2	 4	 6	 8	 :	 <	 >	 @	 B	 D	 F	 H	 J	 L	 N	 P	 R	 T	 V	 X	 Z	 \	 ^	 `	 b	 d	 f	 h	 j	 l	 n	 p	 r	 t	 v	 x	 z	 |	 ~	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 
 
 
 
$�
$'U0707070064030064551006440000000000000000011777770507310751700004000000006256/newbits/kernel/USRSYS/lib/ms.a]�ms.o�(���hD��VW���p�@�r�@@�t��v����F�h��6v�����j�6t�����hr�6
�����v�����+��_^�VWU���6
����h��6v����j�6t�|����_^�VW��v��i����F��>jt�'P�S��������h��6v�@���jZ�6r�4����6r�*���=Zt
��v���h��6t�����6p����h��6t������6p�����h��6t������6p�����h��6t������6p����j�6t����jh:h�����jjhHh�����Ph�����jhLh��}���jhPh��o���+����6�j�v��W���+��_^�VW��E��F�j�6t�9���+����j�v��'���+��_^�VW����F��~
|�~
s�v�^
����&������v�������>t����+��_^�VWU��f
���f
���8#6u�~t	hx�����8#6u�f
���F
�_^�VWU��jh��v�����>�u���>�u���_^�VWU��jh��v�S����&6���_^�VWU��j�vh��6����&6���_^�VWU��jh��v�����_^�VWU��j�vh������_^�VWU��j�vh�������&6���_^�VWU��j�vh6������_^�VWU��jh8�v�����6#8ujh�h�h6�������8�_^�VW��>ju��{��F�h��6t�n����6p�d����F�h��6t�T����6p�J����F��~����F�%ǘ�F�h��6t�(����6p�����F�h��6t�����6p�����F��~����F�%ǘ�F�j�6t�����+��F��F��F��u�F���%3F�t�~�tjj�jj�I���F� u�F���%3F�t�~�tjj�jj����F�F��~�u	�~�u���F���F���v��A��;��v��2��;�~�f��f��~�t7�F���l�F���>��l�F���>���F��6��6�P�������~�t7�F���n�F���>��n�F���>���F��6��6�P�������;�u	��;�t�6jh�h������6#8th6�����>~t	hx�u����v��l����_^�VWU��k^�����jh�kF�P�F����F
	6�_^�VWU��F;F
}�F
��F;F~�F�F�F�_^�VWU��~}�F����F�_^�<

���_0l����"9������@d@d@d@d@dms_readcrs_�msunload__MSPORT_clrivec_pollopen_ms_setmick_�nonedev_ms_setup_lsetivec_sphi_ms_wait_9u_abs_�msclose_�inb_outb_nulldev_msioctl_�blkmvms_readmick_�msload_MSIRQ_
wakeup_ioctls_&c_range_�spl_ms_readbtns_msopen_�ms_setcrs_�ms_readstat_"mspoll_0sleep_kucopy_ukcopy_button_�msintr_rpollwake_mscon_  ''' ''   " $ & ( * , . 0 2 4$%
$
%$%$%"7%	%/72%;7> D$H7K7T$f7i%s7v%7�7�	$�'�7�0�%�7�%�7�%�7�'�%�7�%�7�%7%7%7%%7(%275%<7?%H7K$S%V7Y$c%f7i%p7s${%~7�$�%�7�'�$�$�7�7�	%�7�'�$�7�7�	$''7' $@$D%O7R$X$\%t7z!%�%�%�%�%�7�!$�%�7� $�%�7�!%�7� %7 $$-70 $A7G!$M$Q$^7a$j$z0�7�	%�7�%�7�%�7�%�7�%�7�%�7�%�7�%�7�%7%50P%b0}%�0�%�%�0�%�0�%�$�%�$�%�%�%�%�0%$%$#%+%/%6%:0>%D%G%K%P%T$Z%a%d7g$m$q$v7y%�%�7�$7�%�%�%�7�$�0707070064030064521006440000000000000000011777770507310752000004000000002245/newbits/kernel/USRSYS/lib/rm.a]�rm.o�(C����X�{VWU���_^�VW��F��~�}%k^�,�����tk^�,���� ������F����_^�VW��F%�����k�,���N����+҉F��V���T�F��V��~
u�t0�F�F�t�F�F�t�F��V�;V�u;F�u�F�F�u�F�F�u��o�F�F�td�F�F�u\h0��F��V��	�������������RP�����D���u��,�F��V���T�E�U�D�T�D*jhRP������D*�_^�VW��~�����k�,���~����+҉F��V���T�F��V��t�F�F�t�F��V�;V�u;F�u�|*u��*�L*�F�F�u�|*t�'��t�Y�����D�_^�VW��v�D�F�%�����k�,���N�����+҉F��V���U�F�V��t�F��V�;V�u;F�t�L��F��V���������F�V��D��	�ȋ�+�D
T-��;V�w�r;F�s��D
�T�	������EU�F��V��|u�D+�RP�t�t�v��v���D+�RP�v��v��t�t�m���V�f����_^�VWU��v��%�����k�,"��h@�jV�v
W�8���
�_^�VWU��v��%�����k�,"��h@�jV�v
W�
���
�_^�C,���	nonedev_u_pclear_nulldev_salloc_bdone_plrcopy_sfree_rmcon_�ioreq_     
'''  %"%&%275%X'�7�'�7 %@'�'�7�%�07�7�%�7�	%�7�	0707070064030064441006440000000000000000011777770507310752000004000000022006/newbits/kernel/USRSYS/lib/rs.a]�rs0.o�(w��#n	<�YVWU����	�����Kh�������uhDj��������_^�VWU��jjjh�����j����jh�����jh������_^�VWU��6�Ft���h��y���������t����|2�u�F�D2�|0u�D�D0�
�
*�=uF�D0;Du��
u-��� ���	�
�F�t�&
���_�����F�tM�uE�jjhh�������>�E$E&t�����t��
u��
�
��_^�VWU��
*�=uc�
t[��	;�	t5�jjhh�q�����
*�=u0�>�E$E&t��Q��t���
�+���	��	�����
�_^�VWU��v
�|Vh�����;|u>�Dt��0�jjhh��������G$G&t�����t���_^�VWU��v
�Dt��	+�	�	��#>�	;|w��CVh�	�����P�|t0�jjhh�|������G$G&t��f��t���_^�VWU��v
������t%��;�u�~t	h�2�����;�u������t%��	;�t�~t	h������	;�	t�������_^�VWU��h�����������t��>tNh������C�t;�
u3�&���>
t&����t�6��t;|0u	Vj�����t�硲;�t �>t	h�j����>t	h�Z����>t&�u h��D�������%��Ph��3����&���>uS��	;�	t���>t��	;�	u7h���,��	+�	%�=�s �>t	h������> t	h�����jhj
h�������_^�VWU��h���������-=v�X����.��j��.�th���������t)h��u����>�����&���u
���&����t��t��th��6����y��t7�6���Fƅ�������Fƅ������Fh������������6��:�h�������>���ƅ��&����h��������� t���t*��u	������u	�&������t�&���>����ƈ���&�����t���%=t���>����ƈ���r�����_^�VWU���t��
uh��%�������u��������	;�	u��h��������� u����	���	*���u��� |���
u��t{�
�v��
u,�t�>tb���	�
�T� tL��E��u
�>t9��3��	u.�%=u� ��*����t��	�	����	�&�	�Vh��5���W�.����_^�VW��F
-T=v�H����.�����<��	;�	t3�jjhh�������>�E$E&t�����t����~
Tu@h��������~u����@���&�����Vh�������j�F�P�v�m����>t��F��F��
;F�t	�F�
��u�&���~
Tt������~jj�F�P�����
�F��F��F�j�v�F�P������M�F=w����.���%-��	��	�.���������F�t=t
���	�&���b��_^�VWU�������
uj��>
u�
u�jh��t����
���㋇�	���t%h�h��T���Vh��J�������Ph��;����
%0���CC.;��u%.�g 0����+��
������
%=t=t�
������
@t���t��@Vh������+��
t��
�t��Vh�����W�����_^�
i^�4�3��	Y@��`@0procq_clrivec_pollopen_sendsig_nondsig_RS0CFLAG_�	setivec_sphi_u_rs0tty_"inb_outb_nulldev_rsin_rsout_cprocp_timeout_memset_wakeup_spl_rs0con_n	sleep_kucopy_ukcopy_pollwake_ r	 t	'v	 x	 z	 |	'~	'�	 �	 �	 �	%%
07
 "7'0-%?7B7J7U7`'p'{07�
'�0�'�	'�	'�	'�	'�	'�	'�	'�	$�'�	'�	0�%%'	'	'!	7$'+	'/7:'B	'H	'N	0S'W'd	'o	%v%z'�	'�	7�'�	'�	'�7�'�	'�	0�%�%�%�%�'�	%�7�
'�'	'	7'	'7%'-%D%H%L%R'[%b7e0k'u	'	7�'�	'�7�'�%�%�'�	7�%�%�%�%�'�	7�%�%7
''	'-	'3	76'?	'G	'O	'U	'[	'e'i7v%�%�'�	'�	7�'�	'�	7�'�	'�	7�
7�'�	'�	%�%�0�'�	%�%�'�	7�%%'	'	7'"	'(	7+ 3%87;7M
0_ h j l n p r7x
7�
%�%�'�	'�	%�%�'�	'�	7�
0�'�	%�%�%�7�
%%
0
7
%%%"%'0,72
';	'G	'T	0Y'b	0g'k	's	%y%}%�%�0�'�	0�%�%�%�0�0�0�'�	0�'�	7�
0�7�%�%�0�7�
0%%'	0#0+'4	'9	'K	'S	'Z	%_'h	'p	'|	'�	'�	'�	'�	%�'�	'�	%�%�7�7�0� � � � � � �  %%	'	'	7'#	''72':0>7K
'Z	'`	'l	'r	70�7�'�0�'�	'�	'�	'�	0�'�	'�	0�%�%�7�'�	'�	'�	7   ! #%&%)%.%1'7'L	'T	0Y7e'k	'w	'~	7�'�	$�7�7�7�'�	 � � � � �'		' 		',		7;	'D		'O		7^	7e	rs1.o�(w��#n	<�YVWU����	�����Kh�������uhDj��������_^�VWU��jjjh�����j����jh�����jh������_^�VWU��6�Ft���h��y���������t����|2�u�F�D2�|0u�D�D0�
�
*�=uF�D0;Du��
u-��� ���	�
�F�t�&
���_�����F�tM�uE�jjhh�������>�E$E&t�����t��
u��
�
��_^�VWU��
*�=uc�
t[��	;�	t5�jjhh�q�����
*�=u0�>�E$E&t��Q��t���
�+���	��	�����
�_^�VWU��v
�|Vh�����;|u>�Dt��0�jjhh��������G$G&t�����t���_^�VWU��v
�Dt��	+�	�	��#>�	;|w��CVh�	�����P�|t0�jjhh�|������G$G&t��f��t���_^�VWU��v
������t%��;�u�~t	h�2�����;�u������t%��	;�t�~t	h������	;�	t�������_^�VWU��h�����������t��>tNh������C�t;�
u3�&���>
t&����t�6��t;|0u	Vj�����t�硲;�t �>t	h�j����>t	h�Z����>t&�u h��D�������%��Ph��3����&���>uS��	;�	t���>t��	;�	u7h���,��	+�	%�=�s �>t	h������> t	h�����jhj
h�������_^�VWU��h���������-=v�X����.��j��.�th���������t)h��u����>�����&���u
���&����t��t��th��6����y��t7�6���Fƅ�������Fƅ������Fh������������6��:�h�������>���ƅ��&����h��������� t���t*��u	������u	�&������t�&���>����ƈ���&�����t���%=t���>����ƈ���r�����_^�VWU���t��
uh��%�������u��������	;�	u��h��������� u����	���	*���u��� |���
u��t{�
�v��
u,�t�>tb���	�
�T� tL��E��u
�>t9��3��	u.�%=u� ��*����t��	�	����	�&�	�Vh��5���W�.����_^�VW��F
-T=v�H����.�����<��	;�	t3�jjhh�������>�E$E&t�����t����~
Tu@h��������~u����@���&�����Vh�������j�F�P�v�m����>t��F��F��
;F�t	�F�
��u�&���~
Tt������~jj�F�P�����
�F��F��F�j�v�F�P������M�F=w����.���%-��	��	�.���������F�t=t
���	�&���b��_^�VWU�������
uj��>
u�
u�jh��t����
���㋇�	���t%h�h��T���Vh��J�������Ph��;����
%0���CC.;��u%.�g 0����+��
������
%=t=t�
������
@t���t��@Vh������+��
t��
�t��Vh�����W�����_^�
i^�4�3��	Y@��`@0procq_clrivec_pollopen_sendsig_nondsig_setivec_RS1CFLAG_�	sphi_u_rs1tty_"inb_outb_nulldev_rsin_rsout_cprocp_timeout_memset_wakeup_spl_rs1con_n	sleep_kucopy_ukcopy_pollwake_ r	 t	'v	 x	 z	 |	'~	'�	 �	 �	 �	%%
07
 "7'0-%?7B7J7U7`'p'{07�
'�0�'�	'�	'�	'�	'�	'�	'�	'�	$�'�	'�	0�%%'	'	'!	7$'+	'/7:'B	'H	'N	0S'W'd	'o	%v%z'�	'�	7�'�	'�	'�7�'�	'�	0�%�%�%�%�'�	%�7�
'�'	'	7'	'7%'-%D%H%L%R'[%b7e0k'u	'	7�'�	'�7�'�%�%�'�	7�%�%�%�%�'�	7�%�%7
''	'-	'3	76'?	'G	'O	'U	'[	'e'i7v%�%�'�	'�	7�'�	'�	7�'�	'�	7�
7�'�	'�	%�%�0�'�	%�%�'�	7�%%'	'	7'"	'(	7+ 3%87;7M
0_ h j l n p r7x
7�
%�%�'�	'�	%�%�'�	'�	7�
0�'�	%�%�%�7�
%%
0
7
%%%"%'0,72
';	'G	'T	0Y'b	0g'k	's	%y%}%�%�0�'�	0�%�%�%�0�0�0�'�	0�'�	7�
0�7�%�%�0�7�
0%%'	0#0+'4	'9	'K	'S	'Z	%_'h	'p	'|	'�	'�	'�	'�	%�'�	'�	%�%�7�7�0� � � � � � �  %%	'	'	7'#	''72':0>7K
'Z	'`	'l	'r	70�7�'�0�'�	'�	'�	'�	0�'�	'�	0�%�%�7�'�	'�	'�	7   ! #%&%)%.%1'7'L	'T	0Y7e'k	'w	'~	7�'�	$�7�7�7�'�	 � � � � �'		' 		',		7;	'D		'O		7^	7e	rsas.o�(x��j��
VWU���^
����O�#�^�w;wt�@F#7�;w��w�^
��O]_^�VWU���^
���O�(�^�w&�G�@F#7;w��uON#7A�w�^
��O]_^�Q_IX	IO_BASE	IO_IOC	Q_OX	rsin_Q_MASK	rsout_>uds_Q_CC	''L0707070064030064411006440000000000000000011777770507310752200004000000012557/newbits/kernel/USRSYS/lib/st.a]�st.o�(���Q�
�DCVWU���6�
�����h���
@P�����j�
��j ��
@P�����h��6�
������_^�VWU���6�
�����6�
����j��
@P�����_^�VW��v�~
�>u���>t�'���t
��t��u��	�}��f�E��F�j��
P�6���j ��
@P�)����v�� ���h�����	�|��2�����`t�&���u�2�����t����΁���+ң*�,�u�*�,�
�*�,�������*�,�*,t%h ��6,�6*�����0�u
�.*�,�҃>0u���0�G�.��u��+���0�G�W�"�$��u	�*�,�+��У&�(��u�@�����>��� �:�<�3�����tj�^���_^�VWU��v�>t��>t&j`��>t�ƀt�2�����u	h�����ƀu��|�j!���j�����60�{����0��_^�VW��v
�D�F��|u��&(u,�>t�F�;Dum��e� ���t��U��ˋ|�Ǚ;(|;&v�&��W�t�6$�6"�������;�u|)|�Ǚ)&(�Ǚ"$�r��_^�VWU��v
�|tg�|�Ǚ;(|;&v�&��W�6$�6"�t������;�u6|)|�Ǚ"$�Ǚ)&(�&(u�1� ���t��L�_^�VWU��>t�� �F
���CC.;��t�.�g
de"9��j"����dj$��>t�>tj`�d���j!�ԃ>t9j`�K����)�>u"�>u	h��,����&�(� ��_^�VWU��>0�E�U�"�$�*�,�&�(�l�>0�E�U�"�$�*�,+&(�&�(�> t�&�(�_^�VWU��&�(;,u	;*u�jh�6(�6&�����t)j�6$�6"h�������"�$�.&�(���>0�E�U�"�$�*�,+&(�&�(��>0�E�U�"�$�*�,�&�(�_^�VWU�������>t,�>}�>���F���Pjjhh�O������~�� �:jd����F�P�6�
����j`��
@P����V�����_^�VWU��������>tjjhh��������~�� �:jd����;u�D���P�6�
����j`��
@P�����>tjjhh�~�����V�u����_^�VWU���f�����
@P�\������� u���:�-=v������.����	&��bj ��
@P�����>�u�����8��>t�����LJ��j0��
@P������6h�6$�6"�6�
����
�>�u��
@P����%=u��j��
@@P�����6�
�~����9��u�0�6�
�h����.&�(�>(x/u�>&t&�"�$�6h�6$�6"�6�
�)���
�j ��
@P��������&2��&3�����
@P�����%H����u��6�
������8��2j`��
@P�����j���j ��
@P�����8�8=ug��_�2�����tj��
P������9�2�����fu�3�����`t� ��>@u�2�����t� �rW�;����_^�VWU��j ��
@P�%���jd�����;u
�6�
�
������P�6�
�����j`��
@P������~�� �:�_^�VWU��j ��
@P�����~�jd�~���>tC��>�狅�P�6�
����j`��
@P�z����~�� �:�	h�W����_^�VWU���H�����
@P�>������� u������@t�:��:�:=|��W�
����_^�VWU��2����� th������n�2�����@th��3����� th1�֠2�����thG�Š2�����thb봠3�����@th�룠2����3����Ph������_^�VW��o��F��>t*jjhh�X����>�E$E&t��v��C��������v��5���+��_^�VWU��vN}��_^�m"�9��	Cst: Unselected Drive
st: Cartridge missing
st: No data detected
st: Bad block not located
st: Unrecoverable data error
st: Illegal command
st: %x
st_>stcon_�
clrivec_STPORT_�
dmaoff_nonedev_setivec_sphi_u_drvl_inb_STDMA_�
outb_nulldev_stuload_Csalloc_lrremcprocp_dmago_wakeup_dmaon_spl_printf_STIRQ_�
sfree_kpcopy_sleep_upcopy_pucopy_ �
 �
'�
 �
 �
 �
'�

 �
 �
 $7
$70 $(7- 3$77:$J7M$T7W$_7d'{'�0�'�'�0�'�0�0�'�0�7�$�7�$�7�7�0�0�'�'0'
'0'+'/'7'='E'I'R'V'Y']'f'j7m's'{'�'�'�0�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'''0',02'6'A'M0\0h0q0y'�7�'�'�0�'�'�'�'�'�'�0�0�'�'�'�''7'!'%','003'O'W'\'c'g7m'�'�'�'�'�'�0�'�'�0�'�0�'� �0� � � � � �0�''0''$0,'3';'B0K'R'X'^'c'f's'|'�'�'�'�'�0�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�0�'�'�7�''%7'''"'''.'7';'>'B'F'J'M'Q0T'X'a'e'h'l'o's7'�'�'�'�'�'�7�'�	'�'�'�0�'�$�7�$�7�7�7''7'$	'*'0'60='C'G0L'Q'T$Y7\$d7i'p'}7�7�7�$�7�
0�0�'�'�0� � � � � � � � �$�7�'�'�'0'0'''0$$)7.'5'<'@$D7G'N$U7Z
'i$p7v$}7�0�0�$�7�'�'�'�'�'�'�'�'�'�$�7�$�7�'�0�'�'�'�0$7
$7
'&'*$/740<$D7I'P'S'\'c$q7x''�'�'�'�'�'�0�7�$�7�0�'�'�$�7�'�$	7	$
	7	'		'	'%	'+	$;	7@	'G		'M	0T	'[	'b	'f	'l	'o	$t	7w	$	7�	'�		'�	'�	'�	'�	7�	7�	$�	7�	
0�	'�	'�	'�	0�	7�	'
$
7
'
$#
'(
$4
'9
$E
'J
$V
'[
$g
'l
'r
$|
7
7�
'�
'�
7�
'�
7�
7�
0707070064030064351006440000000000000000011777770507310752300004000000015626/newbits/kernel/USRSYS/lib/tn.a]�tn.o�(���H�b�VW���F��~�|�w�^��ヿ"t�^��ヿ*t�^��ヿu*�^���LJ*�^���LJ"�^���LJ�F����멋^��㋇*�Dyj@P�����ty��������t�Dy�ɋ^��㋇"+ҹ�������F��V�jhRP�I����F��V�h4��RP�2����F��V���RP����=4t�v��v��
����j0jh �����������u�v�h<������̋F��D,�D�D�D�D�D�D"��D0��D�D�D$�D2�tD�D�D�D�D@�D*�D ���W����=�t+j�DyP�x����F���F��n��^��F��V��u��W�Q���=�u
W�E����D{����G�W���F��V��F��~�}j�v��v�h�����F�F� �V���j j����P�����j j���P������Dw�j�ty�����j�Dy@P�����j
�Dy@P����j�Dy@P�����\@�w�Dy@P�����^�����
�^����������tw�ty�x���������_^�VW����+���}M�|yuG�����j�ty�=����������/����D�F��t
P�v��������t�����
�����_^�VW��F%�F��F%����F��~��~�i^������yu��$�~�~�~��烽2t�iF������~��Es�_^�VW��~��i�������F%0���F�����Osu6�^���ދG8���t&�]��F��^���ދE�G8WV����v��?������_^�VW����yv���|yu��������F����t]��+�����؋ʃ�|C���v=���t+����G�W�F��V�j��RP�}�����DŽ�����DŽ����t���u
j�Dy@P�����v��������t�c�DŽ�+���|�S������ȋ�كLt�����FP�R���G���_^�VW�6�v�N��i�����F
=Nt
=Nt���DP�����F�������ȋ��GW�F��V�����F��.�>��ڊ�*�ȋF��.�>���ߊ��*�#�tj�j�DP����j�DP���P����j �F�P�v��v�����j �DP�F�P����j�F�P�F��V���RP�n�����+F�V��F��V�j�D(P�F�P�K����~
Nu9j �v��v��6���j�F��V���RPh�����~�uDž�Dž���+��_^�VW��~��i�����F%0���F��F��F
t���t�N��F
t�~�����}8t�N��F
t�|Du���t�N��~�uT�~tN�F
t$�F����FP�q����~�����}8t��&�F
t�DfP�N����|Du���t���F��_^�VWU��h�=���_^�VWU��h��+���_^�VWU��h�����_^�VWU��hy����_^�VW��v�ty������F��Dwj�ty������F�u�j�Dy@P������+������k�
�F����������������~��|�~��~���t�������D�D��N������=uA���u:����G�W�F�V�j��RP����j j����P�������D��F�tM�f�~�j
�Dy@P�����j�Dy@P������D@���t�u�Dy@P������DB���t�u�Dy@P�����DB���u���Lw�F�u���E@�W�����F�W�����ȸ+��F��~�uW�h����ȸ+��F��F�tx����G�W�F�V�j��RP�����v��F�V���RP�����F����ȋ��F�V�j�F�V���RP����v��F�V���RP�����~�u�����G�W�F�V�j��RP�l���F����ȋ��F�V�j�F�V���RP�E��j�F�V���RP�/���F��.�>��ڊ�*�F��F��.�>���ދF����F��.�>���ދF���DŽ��E�DB�DD�E�|D�DB���t�u�Dy@P�����:�����dw��DŽ��|rt�Dr�DrPh������|lt
�DfPh������D@���u���Lw��F��u���E�D@�t�]�w�Dy@P�����E��dw��E�W�����F�W�{����F��t	�|{u�D{W�d����F��uW�V���E����t�������DŽ��F��.�>��ڊ�*�F��F��.�>���ފ��*�#F�tw����G�W�F�V�j��RP����F����ȋ��F�V�j�F�V���RP�}���F��.�>���ދF��� ���F��.�>���ދF���DŽ�W����F��F��~�~�^��㋇2;F�t�N����^��str�^���ރ8t�^���ދ_8��
�^���މ8��^��nt��^��Gn��F�nPh����F����ȋ�كLt�F����FPh����WV�K���tw�ty�����_^�VW��v
�N��i�����F%0���F��|BwmVj���V�E{�P����|@u8��j ���PV���j ���PV�u��j ���P�h��Dž��\����| t�j ���PV�E����<�F�^���ߋG8�F��u�D�F���ljF�^��G�^�G8�^��G�v�����^��G�VS�����F�P����V�v�����P�����v������F��t�^��G�F�F�F���$�v�����F��t�^��G�F�F�F��+F��F��~�t#�D;F�s�F��v��t�v��f���F�)DD���tf����G�W�F��V�j��RP�����v��v��v������F����ȋ�+�F�V�j�F��V���RP����v��v��v�����v�W�G���O�Dt��v������8��^��Gnh�jh���F�nP����v�������u�X���_^�VW��v
�N��i�����|r�|�v��V�\��V�U���F��F��.�>��ڸ�����ȋF��.�>���ߊ��*�#�t�&�y��F��ED�F��u���^��G�ED�G�v�������^��G�jS������v��v�������D�F��~��vj�v���������+F��F�P�v������^��G�F�F�F��v�S�t�����F�D)D�D�^��G�r��}Bu2�F��EB�^��w�Ey@P�X����Mw�EwP�uy�F����:����	�F��]B�G�v��+�����DtN����G�W�F�V�j��RP����F����ȋ��F�V�j�F�V���RP������Erjjh�ErP����v�������u�Y���_^�VW��v�~
��F��|@u%�|@�u�Dy@P�y���Lw��DwP�ty�g����\@��E�v��Q���_^�VW�j�F�P�v
�v�5���F�F�V�j�v
�v�F�P����_^�
�c)r������ @��� @�tn%d: out of memory
tncon_�utcopy_tucopy_TNPORT_*clrivec_pollopen_fclear_nonedev_TNPREFIX_2nondsig_kclear_tncycle_�setivec_sphi_u_tnuload_�drvl_tnclose_cinb_outb_nulldev_iogetc_getubd_tnet_Lsplo_salloc_tnread_)tnload_iowrite_tngetc_defer_TNSEL_"ffword_ptov_memset_fkcopy_kfcopy_wakeup_tnwrite_rTNIRQ_spl_tn0intr_�tn1intr_�vrelse_TNTIME_:tn2intr_�tn3intr_printf_tnintf_
ioputc_putubd_tnopen_�sfree_sfword_sleep_kucopy_lbolt_tnputc_tnintr_pollwake_tn_rxena_a � �'� � � �'     
   '0$$*$6$B$M$X$l7v7$�7�!7�57� 7�+7$7/7r7�7�7�'�87�$7"7"7*777D7Q7b$n$w7z7�0�'�'�'�7�$�7�7�+7�4'/'6$H'S'u7�
0�7�('�'�0�7�
'�8'�8077g7p(0}0�7�;'�'�0�7�7
 $ (7C27T77f#7v77�#'�8'�87�77�'�87�$7�'7�7�'�0�'�0�'�0�'
0
7#760C7M'S8'W8'j8'n80�7�"77757L0[0j7t7~7�0�0�0	0	0"	0+	0H	0o	0�	 �	$�	 �	 �	7�	$�	'
%7
'(
;7+
0:
0I
7a
7y
7�
7�
7�
 �
$�
 �
007 C Y7n$�'�%7�'
;7
07 '>7X17d17p
7{7�7�
7�0�0�7�0�7�
0�7�(7

7
17!
7(
171
7W
7�
0�
0�
0�
00'(7/(7Q67Z(7`	0g'k'�'�0�7�7� � �'�0�7�
0�7	(797&97>97V97t7�
7�7�$�7�(0�0�0$'+7@67I(7O	0V'Z7n
7�7�7�(7�#7�$tnas.o�(���zd
VU��^�7���7*�]^�WU��F�^�?���?]_�VWU���^
�?�v��N���������?]_^�VWU���^�~
��7�N���������7]_^�utcopy_)tucopy_Qtngetc_uds_tnputc_':'`0707070064030064341006440000030000030000011777770507310752500004400000000131/newbits/kernel/USRSYS/lib/ldrts0.o�����v�v�v�Ѓ��main_70707070064030064321006440000030000030000011777770507310752500004400000002315/newbits/kernel/USRSYS/lib/ldmain.o�*��VW��6�t;6|Vh������j�����k�
��u���ヿtVh�����j�����������y��k�
LJ����LJ�������>t
����P���jjhh��\�����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W���������LJ����LJ��h�����+���s=���㋇�F��~�t)�^��G�F���;F�ujjj�v������͋^����G�j�����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h��=����_^�ldrv:%d: bad dev
ldrv:%d: dev bsy
main_clrivec_uexit_Kdefend_ldrvipc_u_ldrvics_ldrvcon_drvl_drvn_timq_ldrvsel_con_timeout_kcall_cprocp_ucs_wakeup_printf_ldrvpsy_getcs_sleep_''	$77!'+'6$=7@7H'N$Q'T$W'[ ]'a c'j'l't'v'}'�'�'�$�7�'�$�'�'�'�'�'�'�'�7''' 7#'6
7K7\
7p$�$�'�$�$�$�$�$�7�0707070064030064271006440000030000030000011777770507310752600004400000005305/newbits/kernel/USRSYS/lib/ldswap.oj��VW��>tj������h������+j���F����F�F���j�F��F��F��>��u��E"t�N��m8�F�)E:�}:Њ}�E:Њ�}�ӋF�E8�F�;E8s����E8�F��} u��F��F��~�}0�^���ߋG���t�Dujh�t�t�-���F��F��ʃ~�u�F��E8E<+��v��F�;F�w�{��F�~��r�h������~�u�~�t����G$u����v������t�v�����u��v������F���F�h�����>��tE�E"�t�}���E"uW����t�h�h���딃}:�~�}8uҋE:;F�}ʉF��~���h�A����~�t�~�~
�^��O"��v��T�hhj2hh����
jjhh��������j������_^�VW��v�F��F��F��~�}<�^���ދG���u�F����Eu�E�U;V�|�;F�v�E�U�F��V��ԡ��F��V���=�E�U�F�V�+F�V�;V�|
;F�r���E�UEU�F��V���u�+��_^�VW��v�D"%�F��F��F��~�}5�^���ދG���u�F���~�t�E
�Eu�W����u��F��ۃ~�u�L"�d"���F��_^�VW��v�D"%�F��d"���F��F��~�};�^���ދG���u�F���~�u�M
�Et�}
u�W����t��F��ՁL"�F��_^�VWU��vh�R����Duz�t�t������u
h�0���+��g�D
�u�u�t�t�u�uj�����L
��\��D��G�]�7�E�D��w���L�E�U�D�TV�����h�������_^�VWU��vh�����|
th����+���Dtm�t�t�t�����tفd���E�U�D�TV�k����D
�t�t�u�u�t�tj�N����L
��\��D��G�]�7�E�D��w��h������_^�VW�jh�v
�v�����F��V����F�V���D��=tjh�t�t�����DT����F��V��F�V�+F�V�;V�|K;F�rF�jW���������<�u�E�E
�F�V
�E�U�F�V�+F�V��E�U����D�T�F�V���t�]�+��_^�VW����F��V�����=t�D�T����F��V�+F�V�;V
|G;FrB�jW������\�?�D�E�|�5�E�E
�F�V
�E�U�F��V��E�U����D�TDT�F��V���t�s�+��_^�procq_main_xdalloc_�segcore_�testcore_lock_segdisk_Bsexflag_seglink_corebot_uexit_xmalloc_�kclear_pnxgate_segswap_coretop_swapbot_lrdivkcall_cprocp_vremap_unlock_swaptop_Ktimeout_swapio_segdq_stimer_utimer_Kwakeup_sleep_segmq_proccore_�procdisk_2'7
''
7'#%'%='P'T0Y7�0�0'	
70'"0,0/050B0L0R'b
7e'l'p0�'�
7�'�
7�0�'�'�'�'�7�'�7�0'	7
'r	'v	''�0
0�'�7�0�'�7�7�7-'376'K7N'Z7]0e0u7�7�'�7�7�'	'
''7.'<'@'a7g'�0�'�	'�	'�'�'�'�'7']0b0707070064030111361006440000000000000000011777770507310752600004500000001106/newbits/kernel/USRSYS/lib/support.a]�cs_sel.o�(���D+��cs_sel_clocked.o�(������6VW��~dra�F+�.�6��uS�F+�RPjh�4������F�����F�j6jC������F�%�Pj@�����F���Pj@�����v������F���F����F��_^�VW��v�{����F��u�F
��F��_^�VW���F��~�tjd�M�����F��_^�daltclk_in_yaltclk_out_�sphi_outb_altclk_altclk_rate_vrdivspl_ 7'707:7I7X7a0�'�'�0�'�0707070064030111341006440000000000000000011777770507310752600004100000010376/newbits/kernel/USRSYS/lib/tty.a]�tty.o�(�i��p�tVWU��vDŽ6�D���(�D���)Ƅ*Ƅ+DŽ,Ƅ.Ƅ/Ƅ0Ƅ1Ƅ2Ƅ3��|t��\tV�t��\�����V�T���_^�VWU��v�>�}0u��4u�E��4��4�E0�}2�u�F
�E2�_^�VWU��v�<t7�E����<t�LjjhV�.���W�'�����G$G&t����t�V�	��+���4�D�_^�VW��v�~
�E�F��}u�����F��D
P������F��}v�Du��v���������,`t�Du�E;F�r��Et��ρLh�jh��D
P�z�����G$G&t��h��t��E;F�u��떃|
(<�Dt�d���Dt)�d����0�PV�-����}V�&������V����v��
�����,`u
��2�;F�t,W�v�������|��,`t����~�
t
��3�;F�t����_^�VW��v�~
�Et�}�w��+E;w��W�����F��|{�Du���|��F��<�|:V�s���<�|-�LjjhV�V�����G$G&t��D��t���3�v�V�2����}V�+���!����v������w����F�V�
���v������_^�VW��v�~�F��F��F��F��F
-@=v�2����.��>yp�%,Q3HY`ggg`jW�D
P������jW��(���F��F��F�j��(PW�s�����,`t��+��F��F�j��(PW�Q����~�t���,`u��|"u��D$�F���D"$�F��F�;F�s�^��F���P�D
P�������D"�gjW��.�W��F��F�j��.�j��L��G�d��@�L@�9����u��+�d���$jW�D���F��F���L��d������,@t�D t�d��V����~�t+�<t&�LjjhV�^�����G$G&t��L��tՃ~�tV�����~�t$�|t��\tV�t��\�����V�T���_^�VWU��v�f
���F
t"�|
u�~t��8P������|
u�f
���F
t �<(|�~t��@P�����<(|�f
���F
u�Du�N
�F
�_^�VWU��v�| t�L �D!����c�Dt
�d���
�RV�h������}������,�u7��
u��,t
�L�
� ��	u��,t��$
���ЈD �D! � ��,�uL��u
��$t@��$�:��
uDŽ$�-��	u��$
@��$��� |��~~���|
�����$���_^�VW��v�~
��,@uV��.���;�ujV�������/���;�uj�犄1���;�u�D t���L ���0���;�u�d����Dt���,@t����
u��,t�
��6t\��\u��6�B��*���;�t��+���;�u�π��6��6t�|"�}�\"�D"��G$\��WV�6����,u�$W���*���;�t����, t����6t�|"�}�\"�D"��G$\��6���|"u���L"�\"ފG$��F���,u����,t���=u��u���u����u���t��	tjV�8���j V�/���j�k��	t�j��&�6�F��F��F�;D"}&��؊G$�����u�N��
��	u�N��F��F��ҋF��F�;�$|�jV������抄+���;�u<��, u4�D"DŽ6��,u���� }j^V������@WV����j
����,`t>W�D
P�p����Dt�d���D
Ph�W�����>t4DŽ>��8Ph�<���|"u��$��&��\u��6�WV�r����,t"��,@u��2���;�tWV�����V�����D
�F�=|�L�/��,t'�Du �~��|�L��1�PV����V����_^�VW��v�~

t��2�;F
t
��3�;F
ur�|$��D"$�F��^��F��F
�;~�s��G��P�D
P�[������D"DŽ6�Dt�d���D
Ph�5�����>t+DŽ>��8Ph������|"�}�\"�D"ދF
�G$�_^�VWU��v�|�� uu��t�<u��u�| u�d��Vh�M��\tV�t��\�����V�T���<(0��t�d��Vh������FtDŽF��@Ph�y����_^�VWU��v�D
P�c���V�\����Dt
�D
Ph�H����Dt
Vh�7�����>tDŽ>��8Ph������FtDŽF��@Ph�����D"DŽ6�d�<�_^�VWU��^��4�t%S�d�����E��=t;u0u�W�v
������_^�VWU��v�d��V�.���jV�����_^�procq_ttsignal_waitq_pollopen_sendsig_super_getq_clrq_nondsig_sphi_tthup_Ou_iogetc_ttsetgrp_tttclose_�ttin_@ttout_jttioctl_ttread_defer_cprocp_putq_ttflush_�
ttstash_V	ld_call_wakeup_spl_ttwrite_8ioputc_ttstart_
sleep_ttopen_ukcopy_kucopy_pollwake_ttpoll_�7b'~7�	7�7�'�7�0�07	7)'>7E0K'm7�'�7�'�7�0�7�0�7�7
002'^0b7f'{07�	0�7�'�7�'�7�0�7�7�0�7�	0�7�03 < > @ B D F H J L N P R T V X Z \ ^7h!0n7� 7� 0�0�0�7�0
074'<0O'i0�7�'�7�0�7�77A7�0�0c0i0�0�0�0�0�00,000>0I0r0�0�0�0�0�7�7�0�0�0,720`7k7v0~7�'�7�'�"7�0�7	0	7F	0M	7�	'�	7�	'�	"7�	'3
7G
'g
7j
'�
"7�
7�
7�
'�
7�
'�
7�
'�
"7�
'�
"7�
0('.'67D0^0g0707070064030111331006440000000000000000011777770507310752700004300000055321/newbits/kernel/USRSYS/lib/ldlib.a]�__.SYMDEF�(�[��
abs_alloc_�bclaim_0bdone_�blkmv`boot_�bread_pbrelease_altclk_in_�altclk_out_�clrq_�cs_sel_{dblock_�dclose_sdefer_	devmsg_�	dmago_G
dmaunlock_�
dmalock_�
dmaoff_dmaon_�dmareq_?
dopen_�
drvmap_odwrite_fclear_�fdisk_7ffbyte_�ffword_=ffmem_�fkcopy_#fpxcopy_�free_Sfucopy_�getcs_�getq_�getubd_{getuwd_inb_�int11_iogetc_�iomapvp_Aioputc_�ioread_qioreq_	iowrite_�ipcaccess_9kcall_�kfcopy_Rkclear_�kpcopy_�kucopy_lock_�lldivJlrdivJllmul lrmul llrem� lrrem� llmod�!lrmod�!llsgn�!lrsgn�!memset_�#memtest_V$nmidisable_�$nmienable_�%nondsig_&nonedev_�&nulldev_9'outb_�'panic_(pclear_�(pkcopy_5)plrcopy_�)pollopen_e*pollwake_�*printf_�+prlcopy_-,ptov_�,pucopy_]-putchar_�-putq_�.putubd_%/putuwd_�/rucopy_U0s5_to_sg_�0s5_to_tc_�1salloc_2sclear_�2sendsig_M3clrivec_�3setivec_�3sfree_6sfbyte_�6sfword_7sfmem_�7sg_to_s5_8sleep_�8slrcopy_79sphi_�9spl_/:splo_�:super_�:swapio_�;tc_to_s5_%<timeout_�<ttclose_>tthup_�>ttflush_??ttin_�?ttioctl_o@ttopen_Attout_�Attpoll_7Bttread_�Bttsetgrp_gCttsignal_�Cttstart_�Dttwrite_/Euexit_�Eufcopy__Fukcopy_�Funlock_�Gupcopy_'Hurcopy_�Hvprint_WIvrelse_�Ivremap_�Jvtop_Kvldiv�Kvrdiv�Kvlmul�Lvrmul�Lvlrem�Mvrrem�Mwaitq_�Nwakeup_SOabsL.o�(�[�|
<
��`�abs_xcalledKabs_''allocL.o�(�[�|
<
��`�xcalledalloc_Kalloc_''bclaimL.o�(�[�|
<
��`�bclaim_Kbclaim_xcalled''bdoneL.o�(�[�|
<
��`�xcalledbdone_Kbdone_''blkmvL.o�(�[�\VWU��N�	�v
�~��F��]_^�blkmvbootL.o�(�[�|
<
��`�boot_xcalledKboot_''breadL.o�(�[�|
<
��`�xcalledbread_Kbread_''breleaseL.o�(�[�|
<
��`�xcalledbrelease_Kbrelease_''clockedfL.o�(�[�'��YVW��~dra�F+�.�6��uS�F+�RPjh�4������F�����F�j6jC������F�%�Pj@�����F���Pj@�����v������F���F����F��_^�VW��v�{����F��u�n��F��F
��b���v��Y����F��_^�VW���F��~�t!jd�8����2��F���P�����F��_^�daltclk_in_yaltclk_out_�sphi_cs_sel_outb_altclk_altsel_vrdivspl_ 7'707:7I7X7a0�7�'�7�'�7�'�0�7�'�'�7�clrqL.o�(�[�|
<
��`�clrq_Kclrq_xcalled''cs_selfL.o�(�[�D���cs_sel_dblockL.o�(�[�|
<
��`�dblock_Kdblock_xcalled''dcloseL.o�(�[�|
<
��`�dclose_xcalledKdclose_''deferL.o�(�[��<
U���v�v�P�����]�defer_kcall_Kldefer'7devmsgL.o�(�[�|
<
��`�xcalleddevmsg_Kdevmsg_''dmagoL.o�(�[�|
<
��`�xcalleddmago_Kdmago_''dmalockL.o�(�[�>�VWU��v����D�F
�D�vhVh������_^�VWU��vVh������_^�Kdmalock_dmaunlock_(Kldtimcall_kcall_Kdmaunlock_getcs_dmalock_7	''7'275dmaoffL.o�(�[�|
<
��`�dmaoff_Kdmaoff_xcalled''dmaonL.o�(�[�|
<
��`�xcalleddmaon_Kdmaon_''dmareqL.o�(�[�|
<
��`�dmareq_xcalledKdmareq_''dopenL.o�(�[�|
<
��`�Kdopen_xcalleddopen_''drvmapL.o�(�[�|
<
��`�xcalleddrvmap_Kdrvmap_''dwriteL.o�(�[�|
<
��`�xcalleddwrite_Kdwrite_''fclearL.o�(�[�|
<
��`�fclear_Kfclear_xcalled''fdiskL.o�(�[�|
<
��`�xcalledfdisk_Kfdisk_''ffbyteL.o�(�[�RWU���~+�&�]_�ffbyte_ffwordL.o�(�[�PWU���~&�]_�ffword_ffmemL.o�(�[�^VWU���v�~�N��������]_^�ffmem_fkcopyL.o�(�[�|
<
��`�xcalledfkcopy_Kfkcopy_''fpxcopyL.o�(�[�|
<
��`�xcalledfpxcopy_Kfpxcopy_''freeL.o�(�[�|
<
��`�free_Kfree_xcalled''fucopyL.o�(�[�|
<
��`�Kfucopy_xcalledfucopy_''getcsL.o�(�[�D���getcs_getqL.o�(�[�|
<
��`�getq_Kgetq_xcalled''getubdL.o�(�[�|
<
��`�getubd_xcalledKgetubd_''getuwdL.o�(�[�|
<
��`�xcalledgetuwd_Kgetuwd_''inbL.o�(�[�J
�܋W+���inb_int11L.o�(�[�|
<
��`�int11_Kint11_xcalled''iogetcL.o�(�[�|
<
��`�iogetc_xcalledKiogetc_''iomapvpL.o�(�[�|
<
��`�iomapvp_xcalledKiomapvp_''ioputcL.o�(�[�|
<
��`�xcalledioputc_Kioputc_''ioreadL.o�(�[�|
<
��`�ioread_xcalledKioread_''ioreqL.o�(�[�|
<
��`�Kioreq_xcalledioreq_''iowriteL.o�(�[�|
<
��`�xcallediowrite_Kiowrite_''ipcaccessL.o�(�[�|
<
��`�ipcaccess_Kipcaccess_xcalled''kcallL.o�(�[�e([XS�`[SS�xcalledkcall_'kfcopyL.o�(�[�|
<
��`�xcalledkfcopy_Kkfcopy_''kclearL.o�(�[�|
<
��`�kclear_Kkclear_xcalled''kpcopyL.o�(�[�|
<
��`�Kkpcopy_xcalledkpcopy_''kucopyL.o�(�[�|
<
��`�Kkucopy_xcalledkucopy_''lockL.o�(�[�|
<
��`�lock_Klock_xcalled''lxdivL.o�(�[��d��������lldivllsgnlrdivlrsgnvrdiv'7'7
lxmulL.o�(�[��d��������llsgnlrsgnllmullrmulvrmul'7'7
lxremL.o�(�[��d��������llmodllremlrmodlrremvrrem'7'7
lxsgnL.o�(�[��p@��+�������VWU��S�؋�S+��y
�^�W���V�F�y���؃���rFRP�V
�F�y���؃�FRP�V���
��s���؃�[��]_^�ahigh	
bhigh	llmod	l0l1,l22lrmodl3Bl4Vllsgnl5ilrsgnalow	blow	bptr	fptr	��memsetL.o�(�[��PVWU��N�F
�~��F]_^�Count	memset_String	Char	
memtestL.o�(�[�|
<
��`�xcalledmemtest_Kmemtest_''nmidisableL.o�(�[�|
<
��`�Knmidisable_xcallednmidisable_''nmienableL.o�(�[�|
<
��`�nmienable_Knmienable_xcalled''nondsigL.o�(�[�|
<
��`�nondsig_Knondsig_xcalled''nonedevL.o�(�[�g(VWU����_^�nonedev_u_'nulldevL.o�(�[�J
VWU���_^�nulldev_outbL.o�(�[�J
�܋W�G��outb_panicL.o�(�[�|
<
��`�xcalledpanic_Kpanic_''pclearL.o�(�[�|
<
��`�pclear_xcalledKpclear_''pkcopyL.o�(�[�|
<
��`�Kpkcopy_xcalledpkcopy_''plrcopyL.o�(�[�|
<
��`�xcalledplrcopy_Kplrcopy_''pollopenL.o�(�[�|
<
��`�pollopen_Kpollopen_xcalled''pollwakeL.o�(�[�|
<
��`�Kpollwake_xcalledpollwake_''printfL.o�(�[�|
<
��`�xcalledprintf_Kprintf_''prlcopyL.o�(�[�|
<
��`�xcalledprlcopy_Kprlcopy_''ptovL.o�(�[�|
<
��`�xcalledptov_Kptov_''pucopyL.o�(�[�|
<
��`�Kpucopy_xcalledpucopy_''putcharL.o�(�[�|
<
��`�putchar_xcalledKputchar_''putqL.o�(�[�|
<
��`�xcalledputq_Kputq_''putubdL.o�(�[�|
<
��`�xcalledputubd_Kputubd_''putuwdL.o�(�[�|
<
��`�putuwd_Kputuwd_xcalled''rucopyL.o�(�[�|
<
��`�rucopy_Krucopy_xcalled''s5_to_sgL.o�(�[�|
<
��`�s5_to_sg_Ks5_to_sg_xcalled''s5_to_tcL.o�(�[�|
<
��`�Ks5_to_tc_xcalleds5_to_tc_''sallocL.o�(�[�|
<
��`�xcalledsalloc_Ksalloc_''sclearL.o�(�[�|
<
��`�sclear_xcalledKsclear_''sendsigL.o�(�[�|
<
��`�sendsig_Ksendsig_xcalled''setivecL.o�(�[���dVWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh�\�������Dž����Dž�_^�clrivec_|Kclrivec_setivec_ldrvipc_u_ldrvics_Ksetivec_ldrvint_kcall_ucs_'''"')'8'@	'D'M'S7V']'i't'�'�	'�'�7�'�'�sfreeL.o�(�[�|
<
��`�xcalledsfree_Ksfree_''sfbyteL.o�(�[�RWU���~�F&�]_�sfbyte_sfwordL.o�(�[�RWU���~�F&�]_�sfword_sfmemL.o�(�[�^VWU���~�v�N��������]_^�sfmem_sg_to_s5L.o�(�[�|
<
��`�sg_to_s5_Ksg_to_s5_xcalled''sleepL.o�(�[�|
<
��`�Ksleep_xcalledsleep_''slrcopyL.o�(�[�|
<
��`�xcalledslrcopy_Kslrcopy_''sphiL.o�(�[�D�X��sphi_splL.o�(�[�J
X[SSP�X�spl_sploL.o�(�[�D�X��splo_superL.o�(�[�|
<
��`�super_Ksuper_xcalled''swapioL.o�(�[�|
<
��`�xcalledswapio_Kswapio_''tc_to_s5L.o�(�[�|
<
��`�Ktc_to_s5_xcalledtc_to_s5_''timeoutL.o�(�[�6V�(VWU��v�~t�~
jjjVh�����
�+���������D�F�D�vh�v
Vh����
W�����_^�sphi_Kldtimcall_kcall_timeout_spl_Ktimeout_getcs_'77'7,';'B7E7LttcloseL.o�(�[�|
<
��`�xcalledttclose_Kttclose_''tthupL.o�(�[�|
<
��`�tthup_xcalledKtthup_''ttflushL.o�(�[�|
<
��`�xcalledttflush_Kttflush_''ttinL.o�(�[�|
<
��`�xcalledttin_Kttin_''ttioctlL.o�(�[�|
<
��`�xcalledttioctl_Kttioctl_''ttopenL.o�(�[�|
<
��`�Kttopen_xcalledttopen_''ttoutL.o�(�[�|
<
��`�xcalledttout_Kttout_''ttpollL.o�(�[�|
<
��`�Kttpoll_xcalledttpoll_''ttreadL.o�(�[�|
<
��`�xcalledttread_Kttread_''ttsetgrpL.o�(�[�|
<
��`�ttsetgrp_xcalledKttsetgrp_''ttsignalL.o�(�[�|
<
��`�ttsignal_Kttsignal_xcalled''ttstartL.o�(�[�|
<
��`�Kttstart_xcalledttstart_''ttwriteL.o�(�[�|
<
��`�xcalledttwrite_Kttwrite_''uexitL.o�(�[�|
<
��`�uexit_Kuexit_xcalled''ufcopyL.o�(�[�|
<
��`�Kufcopy_xcalledufcopy_''ukcopyL.o�(�[�|
<
��`�Kukcopy_xcalledukcopy_''unlockL.o�(�[�|
<
��`�xcalledunlock_Kunlock_''upcopyL.o�(�[�|
<
��`�Kupcopy_xcalledupcopy_''urcopyL.o�(�[�|
<
��`�urcopy_Kurcopy_xcalled''vprintL.o�(�[�|
<
��`�vprint_Kvprint_xcalled''vrelseL.o�(�[�|
<
��`�xcalledvrelse_Kvrelse_''vremapL.o�(�[�|
<
��`�xcalledvremap_Kvremap_''vtopL.o�(�[�|
<
��`�xcalledvtop_Kvtop_''vxdivL.o�(�[��Fx�Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@��[��]_^�ahigh	
bhigh	vldivvrdiv	alow	blow	vxmulL.o�(�[��:x�Ë܋_��Ë܍_VWU��P�F�'����F�g��F
�'��֋�[��]_^�ahigh	
bhigh	vlmulalow	blow	vrmul	vxremL.o�(�[��Dx�Ë܋_��Ë܍_VWU��P�v
�~+�+�� ��������;Wrw;r+W��[��]_^�ahigh	
bhigh	vlremvrrem	alow	blow	waitqL.o�(�[�|
<
��`�waitq_Kwaitq_xcalled''wakeupL.o�(�[�|
<
��`�xcalledwakeup_Kwakeup_''0707070064030111131006440000000000000000011777770507310753500004000000031053/newbits/kernel/USRSYS/lib/ss.a]�ss.o�(M��o+\jbqVW�
�F��F����F��z+ҹ����������jh RP���������������hZ�RP����h�<������RP����hZ��������-��RP�w���h�<�������-��RP�Y����6��6��K���=Z�uZ������RP�1���=�<u@�������-��RP����=Z�u �������-��RP�����=�<th�������F��v���?�CC.;��t�.�g@�M�|��������������������� ��a��������������������� @�2��������������������� @� � *���!v�~�uj�F��~�}�>v�N�����t	�F��F��F��F��݃~�uh�������F��,iF��P�6������ �uh���iF��P�6 �����~�u6� �F��F��~�}%�>v�N�����t�~���F��F���� �F���h��6x�b����& ���F�@P�Q���� 5�~�u&�F��~�}�>v�N�����tQ�����F����  N�_^�VWU��> t
�6 ���������6��6�������6x������_^�VW��v����%�F���%�F�����%�F��~��狅 �F�"�F�������u��N���#vu�F���v�V�z������ƀt
�~�t�F����ƀt�F��~�tX�~����uM��
�%���F��v�P�3����t,�~���U�~��EL�UN�EH�EJ�~�����������F�.�r��~�tE�~��EL�UN�F��V�^���ߋ~���~��E�U
GW;V�wr;F�v
�F�B�%�,��~�t�~���~��EEu
�F�c������~��E�_^�VW��F��%�F��~��狅 �F����~��M�_^�VWU��h@�j�v�v
h��9���
�_^�VWU��h@�j�v�v
h�����
�_^�VW��v�F�����%�F�~��狅 �F�"�F�F
=Ht=HtU��F�����F�"�F�~�����|�F�F��~�����~*�F��~�����*�F�j�v�F�P�����C�F�"�F�j�F�P�v�s����~����F|�~����F�*䈅~�~����F�*䈅�F��F��_^�VW��v�F��D�F�%�F��F���%�F��F���%�F��~��狅 �F��F��t�F��F�"�F��D�D�~����u>�~�u1�D
Du�|tt�F�w�L�~�t�v��v�����V���w�F��܀|u�~���~��D
�T;Uu;Et‹^���^��|��	��+�D
T;Wwr;Gv�F���D�u�|u�F��|�V�v��0����v��Q
���_^�VW���	�F��~��t!�v��拼 �}ruPh*��v�h������_^�VW��F��v�拼 �}ru�vh*��������@�u�����F��F�P�%���u���~�u��6��6�����%�F��F�*�P���=w�����.���PPPPPPP�P�P��6��6��?����F��t=u�j`�6��6��#����m�j�6��6�����h����6��6�������F��D��F��<��6��6�������+��v�������_^�VW��F��~�},�~��狅 �F��~�t�~��}t�v�h*�����F����_^�VW��F��F��~��}7�6��6��k����F��v����F�*���F��#�;�u�F���F��‹F��_^�VW�j�F��~�狅 �F��~���^���
��F��vh������~�t6�F�P�vhw�R���t�F��~�u�F��h��h��v�������~�u���F�P�vh3����u���F��F�*䙹�������F��V��F�*䙹�������F��V��F�*����ȊF�*����+�F�V�F�V��~���U�F�*䙹�������F��V��F�*䙹�������F��V��F�*����ȊF�*����+�F�V�F�V��~��E�URP�u�5h������
�h!�v�������~�u��F�P�vh��%���u���F�*���F�*���ljF��F�*�ȊF�*�����F�*�������Ǚ�F��V��F�*�F�R�v�h6�i����F�*�PhP�Z����v�hZ�N����~����|u+�~���F���|�~���F�*䈅~�~���F����J�~����|hb�����~����~*�Phz�����~����*�Ph�����	h��v������F��_^�VW��~�狅 �F��~��E �F��F��v�~�E+D�F��F��~��E�E���F��F�P�����u���~�u��6��6��W��%�F��~�u�E�F��F��F�*�P�Z��=w�����.���(
���������e�z���6��6������F��F�*�%�CC.;��t�a�.�g��G��G�����F�*�~��Ej`�6��6������j�6��6����h����6��6��{���~��E����v��~��E+D�F��~�~F�|�D��E*�P�6��6��A���~�t���~�}t���~�u���v�������F����~�u�~�}u��F�h�F�EURP�6��6�����
�\��~�u��~�}u��F�h�6��6��F�EURP���
�{��~�t	�v�����~�t+����_^�VW�	�{�F��~��F��F��F�� +�;V�wr:;F�v5�6��6��F���F��F�t�F���F��V����F�u��~��v�����F��_^�VW��F��F��F��F��F��F��F��?�tRj�v����tCjjj�F�Pj�F�P����t)�F�*�]�CC.;��u.�gkkk�F��F��_^�VW��F��F��F��F��F��F�6�F���t-j�v�<���tjjj6�v
j�F�P����t�F��F��_^�VW��F��F��F��F�?�F��F�\�F��^�t-j�v�����tjjj\�v
j�F�P�3���t�F��F��_^�VW��F��F�%�F��F��F��F��F��F��F��F��F����t-j�v�p���tjjj�v
j
�F�P��
���t�F��F��_^�VW��F��~���^���
��F��~�tFj �6��6��-���� *�P�6��6�����j0�6��6��	���h���s����u�F��~�tA��N�� *��P�6��6�����h��6��6�����h�,����u�F��~�t#h��6��6����h�����u�F��~�t3h��6��6��p��j�6��6��`��h�������u�F��F��_^�VW��F����6��6��.���F��F�$tE�6��6�����F�� *���F�*�#�t$�F�*�#vt� *��� F��F��n�t�F����F��_^�VW��~�狅 �F��
 �>
 u���~��E �F��Er*�-=v�����.��ntj��6��6�������ǀt6�~���������j�v�D���t�v�!���j�v����낋~����t��������j���
 �^��6��6��������$tT��N�� *����6��6�����#�t1�~����������>& �u�F�& ��& ;F�?�t�]��e��~����t���������j�K��~�u
�~��Er����>& �uj�6��6��t������!uT�6��6��^������!u>�~����������v�����t�F�& j�v����d�j
�v���������F�=��t�vh����~�����~����drj��j�Ƌ~����t���v��{��_^�VW�
�~�狅 �F��~��E �F��Er*�=v������.��h�z��UUU3�v�!����t�
 j�v�4���~��Er�j�v����v�M���u��~����t����������v�#���F��~��E �~��E�F�%�F��F��t�F��F�"�F��~�t�v�����~��E
�UDT
�	�~��E
�U�~��E�U
�~��}u	�~��E(��~��E*�~��E�E�U
��������~��E�E�U
��������~��E�E�U
��������~��E�E�E�E�E�E�E�E
�v����~�ƅ�ƅ�ƅ��Er�|�
 �t�& ;Ft�>& �uZ�F�& h��6��6������~��Er�:�& ;Fu�& ���v������u�t��~��j �6��6������~��Erj(�v�w���_^�VW��F�j �6��6����� *�P�6��6��{��j0�6��6��k���F��~��}:�6��6��Q�����ǀt�F���F������=��t�j �6��6��%���F��_^�VW��F���N�� *��P�6��6�����h��6��6�����h�N���tPh��6��6�����h�0���t2�~
th��h��6��6����h��6��6�����F��F��_^�VW��F�h��6��6��d��h �����th��6��6��F���F��F��_^�VW��~�狅 �F��~������������������
 �vh�v
sP�����_^�VW��~�狅 �F��~����t�����������������v������_^�VW��~�狅 �F��~��E �F��E���Eƅ��_^�VW��~�狅 �F��~��E �F�����~����
su�F
=v�����.������~�����~����s�Erj�v�������~��Er�z�~��Er�q�~�����~����r��Er�Z�~��Er�Q�~�tB�~��M�E%�P�E��%�Ph�����~��u�u
�}uh��h�h�����v����_^�VW��~�狅 �F��~��E �F��F��& ;Fu�& ���~����������~�t5�~��Eu�m�~��Eu�}u�~��E �v�����F��~�te�~��Erƅ�ƅ�ƅ��E�U
�E�U
��������~��E�E�U
��������~��E�E�U
��������~��E�E�E��
 �~��Er�v����_^�VW��F�F��F��~�|�F��~��烽 t*�~��狽 �}ru
�v��R���t�v�h*�B����F�;Fu��_^�VW��~�狅 �F��v�W���F��~�tQ�~��E=u�Erj2�v���@�~��}u�}u�v�U����)�~��E=uj��~��E=uj�j�v�7����_^�VW��F��F��F��F��F��F����F�����F��F�P�����u�3�~�u�*�6��6��Y��%�F��F�*�P�m��=w�����.�����������>��*���6��6��
���F��t=u�j`�6��6������m�j�6��6�����h����6��6������F��D��F�;F
s3�~��F�~�*�P�6��6�����F�;F
t���v�������F����F�;Fs��~��F�~�6��6��c�������F�;Fs��6��6��~��F�~�*�P�F��v��4���~�u�~�t�~�u�F��F��_^�VW��
�F�h��6��6�����j2�(��j �6��6�����j2����v������_^�VW��F��F�;F}�F��~�0u}�F����F����_^�VW��F���F��F��~�|��6�F��~��t	�v
����v�v
�V���un�v
�F���v�v
�V���uU�v
�����t!j2�d����v
����v�v
�V���u'����v
������v�v
�V���u�F��i��F��v������F��_^�VW��F�F��> t�f���Ft�N��Ft�N��F�*��_^�
#�����2��Error - host failed memory test
Error - ss has no valid target id's
Error - ss can't allocate structs
bad LUN or SCSI idbad special partitionbad partition tablepartition exceeds drive capacitypartition not foundinvalid requestno partition tablepartition overruninvalid byte countSCSI ID %d  LUN 0
Not Direct Access DeviceInquiry FailedCapacity=%ld blocks  Block length=%ld
Read Capacity FailedPhysical:  cylinders=%ld heads=%d spt=%d
Logical:  cylinders=%d heads=%d spt=%d
Mode Sense Failed(%d,%d): %s error bno=%ld
readwritefree_sscon_\clrivec_SS_INT_xkclear_setivec_sphi_u_drvl_nulldev_splo_bufq_wr_tail_ffbyte_bufq_init_bufq_rlse_defer_devmsg_timeout_ffcopy_bdone_ffword_ptov_alloc_sfbyte_spl_fdisk_vrelse_printf_bufq_rd_head_allkp_sfword_ukcopy_kucopy_drv_parm_|NSDRIVE_vbufq_rm_head_ss_mach_*ioreq_SS_BASE_z ` b d f h j'l	 n p r't	$%$%(72%8%<%E%I7Q%Z%^7i%r%v7�%�%�7�%�%�7�%�%�7�%�%�7�%�%�7
$7$& ,0; G I K%N%R%[%_%b%f%o%s%w%}%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�%�$�$�$7 '477%=$D%P7S%_$q%� �$�7�%�7�
%�$�0�%�%�%�7�7%	%
7$7%Q$q$x'|7�0�$�7�$0$I'M0Q$m'q0u'y%�'�%�7�%%�7�%%'%0.$A$Q$`7q 7�$�$�$�%$C7W7^$e$�$�0�7�0�0�%�  7%) 5780>0A0H7K0U0_0h%l%p7s0� � � � � � � � � � � � � � � � �%�%�7�%�%�7�0�%�%�7�%�%�70
0%%70#7)%J b7e%�%�7�%�$�$�7� 
	0	$+	$0	76	0B	 L	0O	0Y	$
7
$
7$
00
 :
0=
0G
$�
7�
$�
7�
$�
7�
$�
$�
$�
$�
$�
$�
7�
$$7$$$7'$,72%K0�0�0�%�%�7�7�0� � � � � � � � � � � � � � � � �%�%7 0! 7 9 ; = ? A C E%V%Z7]0c%i%m7p%|%�7�0�%�%�7�0�0�0�7�0�0�%
%
7 
0&
%A
%E
7T
0Z
7f
7�
%�
%�
%�
7�
7�
00$0> M e g i0�0�0�0�000g0s0�$�%�%�7�%�%�%�7�%�%�7�0�%%$%(7+%5%97<0E%^%b7e0n%�%�7�%�%�7�0�%�%�7�%�%�7�%�$%%7%>%D0J0c l n p r%v%z7}0�0�0�%�0�%�%�7�%%
%7%.%7%<0B0I0L0h0x%|%�%�7�%�%�7�0�0�%�0�0�0�0�0� �7�00(0.01%D0] f h j l n p r t v x0~%�0�0�0�0�7�0�0�7�#0�%�%�%�%�%�%�7%%0"0,%7%;7>0P%h%l7o%u%|%�7�%�%�7�%�%�7�0�%�%�7�%�%%7	%%70#%1%5780A%Z%^7a%k%o7r%�%�7�0�%�%�7�%�%� 7
% 0L%b%�0� � � � � � � �0�0�$A7D$Y$^$a7d0m%�%�%�7�%[0j%�%�7� �7�%�0�000J7}0�0�0�%�%�7�0� � � � � � � � � � � � � � � � �%�%�7�%%
7
0%%7 %,%0730<%V%Z7]0k7q0w0%�%�7�0�%�%�0�7�7�
%�%70
%%70%7.7p0�0�0�0�0�0�0�0�0�07%4ssas.o�(O���z,U��WV�v�ށ��~������uHu������^_]�U��WV�v�~�߁����&���uHu������^_]�U��WV�v�~�N�^_]�ss_getb_ss_putb_0CSR_OFF	ffcopy_aG01G02REQ_LIM	�G03%G04(RS_REQUEST	P01FP02IP03VP04YBSIZE	bufq.o�(O���~�LVW��~~2kFP�6��������t�F�kFP�6�������F�~��F��F��_^�VWU���~�>�t
�6������_^�VW��F;~}dkF��F��y��F��~��}u�F
�E�+��~
�E��'�~��}�F
��~
��~��E�~
�E�F
�~��E�~��E�v��&����_^�VW��F;~}kF��F��~���+��_^�VW��F;~}[kF��F�����F��~��}~1��F��E=u	+��E���~��=��~���=�E�~��M��F��v�������F��F��_^�free_kclear_sphi_bufq_wr_tail_jbufq_init_bufq_rlse_Jalloc_spl_bufq_rd_head_�allkp_bufq_rm_head_'	7%%.71%:%Q%W%^7a%u%7�7�%�%�%%7#7kfdisk.o�(O�����(VW��v
�F�����F�jj�v������>uejjj�v������F��tF�^�����U�u/�F��~�}j�F�����P�ƃ�P�����F����F��v������v�v����v��m����F��_^�sphi_u_dclose_blkmvbread_brelease_spl_fdisk_dopen_77'#727l77�7�0707070064030114661006440000030000030000011777770507310754000004000000010407/newbits/kernel/USRSYS/lib/dg.a]�dg.o�'�����6:�VWU��P�QP�6�������������������
�P�PR�6��������P�6������P�:���6������F��F��%=u���s�P�6��y����6��o����F��F��%=u�
	�F�*	P�P����P�6��B����dP�����6��.���%=t�>,t�:	��
P��ոP�6������Y	P������Z�P�6�6�������<P����RP������Z�P������RP������<P������RP�����6�6����=Z�uN����RP�s���=�<u4������RP�Y���=Z�u������RP�?���=�<t�m	�!��	P�+����P�6������6��	P�
�����]_^�VWU��>4t�4+�P����RP������P�6�������6�������6�6����]_^�VWU���F�t#�>.t�'�7�>6t+�.�2�"�F@t�>0uփ>8t�0���]_^�VWU���F�t&�.�>2uB�7�t;�6�8��	�#�F@t#�0��t�8�4��	P����]_^�VWU��v
]_^�VWU��P�v
�F�t7V������F��|_�>2}WP�2����RP�����2���F@t/V�����F��|!P�2� ��RP�{����2�ы�]_^�VWU��P�P�v�P�U���+�P���P+�P�P�A���]_^�VWU���,�P��P�v�P����]_^�VWU��F�,]_^�VWU��+�P����RP������P�6��������P��������RP�����=GDt�>,t��	P����+���
P�0��Ÿ
P�����]_^�VWU��P�P��@��RP�m�����P��B��RP�T���+�P��D��RP�<����P��F��RP�#���+�P��H��RP����� P��J��RP������
P�6�������P�6�������dP������@��RP�����t�>,t
�-
P�������
P�)��ǸN
P�����P��@��RP�s����P��B��RP�Z����P��D��RP�A���+�P�� 
��RP�)����
P�6������P�6��
�����P������� 
��RP�����=OSt?�>,t/�q
P�������@��RP�����P��
P����+����
P�=�뤸�
P������"��RP�����:�P����RP�o�����
��RP�Z����F����P�F����RP�9������P�F����RP�����F�%�P��
��RP������dP�����<�><t �>,t
��
P��������
P�[����ٸ�
P�������]_^�VWU�����
��RP�����F���
��RP�}����F���
��RP�e����F���
��RP�M����F��>4u����
��RP�+�������
��RP����;�u����
��RP������F��F��~�}3��~�F�؋ʋF������RP�����E��F��NJF�*�P�F�*�P�F�*�P�F�*�P��
P����
�F�%�P��
��RP�v����3��><t1�<��
��RP�Q���P��
��RP�;�����]_^�P��Error - board type is PC/Xi
Error - board type is PC/Xm
PC/Xe ID found
Error - PC/Xe failed to reset
PC/Xe passed reset
Error - PC/Xe failed memory test
PC/Xe passed memory test
PC/Xe waiting for BIOS load
PC/Xe waiting for FEPOS load
PC/Xe ready for use
Error - PC/Xe BIOS won't start
PC/Xe BIOS started
Error - PC/Xe FEPOS move failed
PC/Xe FEPOS relocated to host RAM
Error - PC/Xe FEPOS won't start
Failure code (%x)
PC/Xe FEPOS started
Error - PC/Xe no FEPOS interrupts
PC/Xe interrupts working
%x %x %x %x
clrivec_setivec_u_inb_outb_nulldev_iogetc_ffbyte_DG_IOB_�timeout_ffword_ptov_DG_RAM_�dgcon_�wakeup_sfbyte_vrelse_printf_sfword_DG_INT_�sleep_ � �'� � �'�'�'� � �'� $7$$%%%)%679%?%C$K7N0X$_7b$w0z$�7�$�7�$�0�$�7�$�7�0�$�7�%�$�0�0�$�7�$7%%7%"%&71%;%?7J%T%X7c%j%n7q
%|%�7�
%�%�7�
%�%�7�
$�$�7�$�7�%�$�7�%%
%%7!$,7/$679%@%D7G%^'e%l%s%y%�%�%�'�%�%�0�%�%�$�%�0�%�%�$�7�7#%1%9%>%B7M%T7a%o%t%x7�%�%�'�%�7�	%�7�%� �%�7�	%�%%7$70)%/%37>
%J$P7T0b$g7k%�%�7�%�%�7�%�%�7�%�%�7�%�%�7�%�%7$7$%7(02%8%<7G
%R$X7\0b0i$n7r%|%�7�%�%�7�%�%�7�%�%�7�$�7�$�7�0�%%7
%$"7&%,%07;
$B7F0N0U$Z7^%d%h7s%y%�%�7�%�%�7�
%�%�7�%�%�7�%�%�70%%% $&7*0007$?7C%Z%^7i
%r%v7�
%�%�7�
%�%�7�
%�0�%�%�7�
%�%�7�
0�%�%�7
%,%07?$e7i%y%}7�0�%�%�%�%�7�
%�%�7�0707070064030114701006440000030000030000011777770507310754100004000000035235/newbits/kernel/USRSYS/lib/gm.a]�mm.o�&�Q�����VWU����v�D u3V������F��|%�F��F��F��F��F��F�P�P�����ƃ>u�V�iP�
P�P������]_^�VWU�������>}>���P�CP�v�����P�BP�h����
P�BP�Z����aP�P���
��>~�u�aP�4���%��P�aP�&����>t��P�����V�����v������v�iP�
P�P�����]_^�VWU��>�~�>�~	��u���]_^�VWU����v
�D�F��<uV�����u����Dur� t)���F��+�PP�P�P�s����v��j����ϋ>�E$E&t&�V��t�O��F�;Du��6V�<����t+��V�/����|u��� t��V�����u���]_^��ismmfunc_mmtim_mmbeeps_mm_voff_mmcrtsav_�mmgo_mmwatch_nondsig_sphi_u_inb_outb_istty_kbunscroll_ttout_mmwrite_=cprocp_timeout_mmstart_mmtime_ispl_mmvcnt_�mmesc_ttstart_sleep_70>%G%N R'Z7^7o'u'|7�7�7�7�
'�'�7�
7�'�'�7�'�7�7� '7$$$+$2777U0_'l7s'z'�7�7�'�7�7�
'�	7�7�'�'�	7�gr.o�&�Q��d2nonedev_grread_nulldev_grwrite_grcon_''''
''''''gmas.o�&�Q�hN ��8(+dp VWU����^�w�O�?t��۽N�v�V�F�~�F#F&1��&1���&1�0&1�0�+��f����.����ڀ~(u����F#F&1��&1���&1�0&1�0�[�^�v�V�~��������^���O+OO]_^�6�c����Q��V���B.���JK}�Y��������$t������F���F���F�F�F��F�FP*Ҋv�v
�^�^+��F��6���y6��s*���:v~U�vVQ�^�^
��.���.�������.���Q+���VWQ�Y_^�������F#F_W�@�_����@�Y^�����.����ڀ~(u����I�����.���	����I�����.���	�~(t�V*������������Ȏػ��3F#F�W&���N�3F#F�&���N�3F#F�&���N�3F#F�&���N�3F#F�&���N�3F#F�&���N�3F#F�&���N�F3F#F�&�_^+���:V}
�I�����.���	*���:v���v���V*�������n�����ػ��3F�W&�&�eO&�aP�ǟ�3F�&�&�eO&�aP�ǟ�3F�&�&�eO&�aP�ǟ�
f3F�&�&�eO&�aP_^+���:V}
�I�����.���	*���:v���v�*��>���I�����.���	*Ҋ���.�����I�����.���	��}�V����:v
}*Ҋv
�<������I��~�~����.���
�����I�<;t!�؀�0��	w9�f�F����FÈF������I��؀�0��	w�f�F����FÈF�ފ���.�������I��؀�0��	w�f�F����FÈF��<htL<ltX���a���I��؀�0��	w�f�F����FÈF��<hu��<lu���~����€�*��Z��~
u6��_��~
u6��O��V��}*�:Vr�V���$���QV+Ɋʀ���*�ыv�~Pu���A��F#ƫ&�A�&�EN&�AN&���&���&���&���&��>&��>&���&���&���&���F#�&��.&��.�+�^Y:V|*V��:v~�v�C���*���:v
s�v
����~u�F���~u�F�{���:vv�v�Y���:Vr*V��:vv�v�V���=��v��*�v
:vr�v�V��*�:Vr�V������:v
}�v
��VQ�^����.���.����^��.���+�~1��VWQ�Y_^�������.���W�@�F#F�_����@�*�Y^��6����F<u�^�M<u�^
�r*Ҋv
����.����^*��<�F<u�^�!<u*��H*Ҋv
+��^��F��<u�<t,��.���*�*�Q�F#F�@�ǀ}�@�����}�Y��RQW�F#F��.�������.���+�~��WQ�Y_����Y����.���+����׋���P������P������P������P������P������P������P�������}������P������P������P������P������P������P������P�����+�YZ�I�RQW�F#F��.�������.���+�~��WQ�Y_����_+ɊN*ʀ~(u��׋���P������P������P������P������P������P������P�������}������P������P������P������P������P������P������P�����+�YZ�y�6���VQ�^�^��.����΃�.���������.+��~3��VWQ��Y_^�������.���W�@�F#F��_����@�*�Y^���V��*�:Vr�V������F
�u���:Vr�V������v��*�:vv�v�V��*�:Vr�V������:v���v�W��V�v���V�v����:v
}�v
�����Nt

�F�����F���F<u�F���F�F�!<u�F���<u�F���<u�F����I��~Pu�F(�����F�����~(u�FP���F��
��F��}*�:Fw�^��}*�:^w:�w
�F
�^��*�����v��*�:vv�v����F
�u���:vr�v���������)Aq7��)a	w	�����������\�����������������������������������������������������������������������������������������������������������������������������������������������������������������11������7���������������������r�����������������������11����������������������������������������������������������������������������/<A7[Xq?&�������������,����������	�	�X�����%	�����	���	�����������
����� #�%(�*-�/2�47�9<�>A�CF�HK�MP�RU�WZ�\_�ad�fi�kn�ps�ux�z}�VWU��n
�~t����~���؋F+ҹP������������u�P+�;N~�N�-)NNV�^����P+�;N~�N�)NN���+���]_^�VWU��n
�~t��؋v�����F+ҹP�������������u�P+�;N~�N�)NNW�_����P+�;N~�N�)NN���+��ĺ���ú���6���������Pmmbeeps_mm_voff_8mmcrtsav_fontw_mmgo_grread_J
grwrite_�
islock_mm_von_?uds_mmesc_mmvcnt_ N'(	$- a'�'�
 �0'','3
 Q V _0� � �0� �0�'� p0|0�0� 000 ' 2 ?0W0Z m0p0� �0�0�0�0 0'0*09'D0I'T0Y0o0�0000 0-0:0V0�0� � � � �0�'�0�0�0 0)0I T0y � � �0�0J Z c0'0$ 4 > J f0�0�0�0�0�0�0�0�0		0	0	0#	0_	0u	0�	0�	0�	0�	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 
 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
  
 "
 $
 &
 (
 *
 ,
 .
 0
 2
 4
 6
 8
 :
 <
 >
 @
 B
 D
 F
 H
 J
 L
 N
 P
 R
 T
 V
 X
 Z
 \
 ^
 `
 b
 d
 f
 h
 j
 l
 n
 p
 r
 t
 v
 x
 z
 |
 ~
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
      
             " $ & ( * , . 0 2 4 6 8 : < > @ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �'[
	'�
	'Hfontw.o�&�Q�@�0�3��3��0�?���������?��?�?�����?����?���?���30��30?�����?�������������?���?�����0000����������������3?��������<<<<��?�����?��?�<?�<<<?�<���3���?�?�3�������������<��?���<��������<�<�<�<�<�<�?����������<<?�0�<<������?��?��������������������<?�<��?������0<<��<<0��?�����?���<<<<<<<<?�<?�<<�?��?�<���<�<���<<�<�<���<<�<����?�����?<<����<<��?�����?���<��<�?��<�����<�<?��?�����?��<<<�<<?�?��<<�<�<?���<�������?�<?�<<<<��<�������?����<��?��<�<?��<�<?�?�����?���?�������<��?�?���<��?��<��?��<�<�<���?�?�������������<<<<?�<<<<���<<���<<���?�<<<<<<?�����<<0?�<0<����<<0?�<0<��<<����<<��<�<�<���<�<�<���������������?��<<�?�??�<��<�<<<<<���<�������<�<�<�<�<�<�����<�<?��<�<�<�<�<?���<<<<?�<<�?���������?����<<<<?�?�<��<?���<���?����0?�<<<<<<<<<<<<�<<<<<<<<<<���<�<�<�<�����<�<�<<��<��<�<������?�?��?�<���<<�??�<<<<<?��<��<?������?��<��<��<��<�<��<<�?<<<<<���<<<��<<�<<<<�?������?��<?�?�<�������?���������������������������?��<<<<�?�?��<��������������<�<?�?<<<<<�<?��<�<�<?���<<<<?�<�<�������<��?��<�<?���<����������<<<<<<<���<�<����<��<<��<��<�<<<<<�<?����<���<�?�����?0�0<���<<<?�fontw_kb.o�&�Q������oVWU��>�uO�P�aP������V)N}���P�aP�����+�Nu��`P��������P�aP�����MP�aP������P�P������P����]_^�VWU��P�w���]_^�VWU���F�t��P���t�R��u��:�v��P�=����7�������u�����P����V�����W]_^�VWU���+���}
����LJF���F�^+���}9����F������㋿
�F��F��F���G���^���=��t	�~�r��F�‹�]_^�VWU��������u����P����V����]_^�VWU��+�P�v
��P�f����>�t
��P�U���]_^�VWU��F
���CC.;��u.�gMN��	.��� ����v�v
��P����V�
����V�v�v
�Q���H�*�1\�2���|���������#�)�1��2\�����|�����]_^�VWU��P�~�u�^��sc��P�F
�F
P����F��+���}
����LJG��^+���}1���㉷��F�F��F
�F
P�K����^���=��t��r��G�ʋ�]_^�VWU��f
���F
t#�>�u�~t
��	P�����>�u�f
���F
]_^�VWU����F��>u��P��P�������`P�����%��F��aP��������
�P�aP����V�aP�����>FtG�F�~��t���\�%��Z����� t���Z�����t��V�`P�J������>H~�H��~��u	�H��~��u��F�%H���F��u��Ru�Z�%=u������*���ǀu��F��t:��5u�&Z��W��;�u�&Z��G��u�&Z��:��7t�2�&Z��*��;�u�Z���5u�Z�
��u�Z���7u�Z����9u�6Z�����Dt���6Z ���F��t���>�u���Z�����t,��u��
u��I�
�D��t��t���\*�%�,�Z�#�t�Z�����t��0u��\�
��0u�*�����tT���t�Z�����t�΀V�#����v��5��F��~�t#���F���P�`P�����F�v�������]_^�VWU��P�F�+��F-=Dv�=����.���8�������������������������������������������>>>>>>>>>>�a��������������U��Z�����t�^��1�㋷��^��;��J��	@uv�F��� t��	��J�\�]��	��J�\�O�N�N+��Z����� t��Z�����t���Z�����@t������ȋF-G.�.���ً�,
�t�<t�<�t��F��%�P�p����F���]_^�VWU��v�ƻ&�CC.;��uE.�g
=>ctuJQX<C�Z �#�&Z���Z@��&Z����Z����]_^�VWU��v�
*���ƈ�
�
�
*�=r�
]_^�VWU��v�\����X*�:�Yu���Y*�ȋ�ي�Z*����Y*�=�rƄY���Y�>t��.���;�t��/���;�u
WV������5��bu�>Lu��6LV������׃�cu�>Lt�P������>L�d�]_^�VWU��P���F���P�`P�����F�v�������]_^�VWU���\���]_^�
�^��}�)1234567890-=	qwertyuiop[]
�asdfghjkl;'`�\zxcvbnm,./�*� ����������������-���+�����!@#$%^&*()_+�QWERTYUIOP{}
�ASDFGHJKL:"~�|ZXCVBNM<>?�*� ����������������-���+�����������ccccccccccccn
t
z
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�

!')-137;=AEGKOQ��������������������7?w8?x9?y4?t75?u6?v1?q2?r3?s[@0?p.?nismmfunc_clrivec_pollopen_super_initkeys_�updleds_Jisuload_}mmwatch_isclose_^setivec_boot_sphi_u_putchar_isioctl_�drvl_isread_�inb_outb_nulldev_getubd_isload_isspecial_�ttsetgrp_istty_�ttclose_kbunscroll_yttin_isfunction_Uttioctl_ttread_islock_mmwrite_defer_mmstart_isturbo_�mmtime_mm_von_isopen_�spl_ispoll_�putubd_isrint_ttopen_iscon_�isbusy_ � �'� �'�  �'�'� � � �'�"$77)787H7V'] b7j	$p7t"7�$
$
$
$

$
$
$
$
$
$
$
$
$
$
$ 
$"
$$
$&
$(
$*
'�$�7�'�$�7�7�$�$�0�$�$�7�+7�'0�%%%($0%O7d$j7o$t7x7'$�7�$�$�7�$ � � � � �7�$�7�7�'0$$$$$$$$)$0$5$:$?$D$I$N%c%g7w)%�%�%�7�%�$�$�7�$�'-$$ (7,!'3-7<7L7^7i%p%w0�%�%�%�7�0�%�%�0�%�0�0�%�7
$
0%'0+$.%70;%D0H0P%T0X$[%d0h%q0u%~0�%�0�%�0�0�0�%�0�$�0�%�0�$�%�%$$$%70H0S7b7p%w7'$,
$.
$0
$2
$4
$6
$8
$:
$<
$>
$@
$B
$D
$F
$H
$J
$L
$N
$P
$R
$T
$V
$X
$Z
$\
$^
$`
$b
$d
$f
$h
$j
$l
0� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6$90<%?%T0W%b$f$q$x%|%�$�%�%�%�%�%� �$�0�  2 4 6 8 :%>%E%L%S'Z%`0d0g$v$�$�$�$�7�%'�-0�'�7%'%7"%07:
%A0D7Q7_%f7n'%�0�0707070064030114471006440000030000030000011777770507310754400004100000012750/newbits/kernel/USRSYS/lib/msg.a]�msgcon.o'>6�$&��VWU��>u����>u�]_^�VWU��v�F
-M=v������.��>Fx���DP����P�DP����P�DP����P����PV������DP����P�DP�v���P�DP�k���P�d��̍DP�[���P�DP�P���P�DP�E���P�DP�:���P�3���뛍DP�'���P�D
P����P�DP����P�DP����P�DP�����P�DP�����P������P��]_^�putuwd_nonedev_u_nulldev_msginit_umsgget_umsgctl_umsgsnd_msqs_umsgrcv_msgcon_&getuwd_ *','.'0'2 4'6'8':'<'7
''03 < > @ B D7K7V7a7h7p0v7}7�7�7�7�7�7�7�7�7�7�7�7�777	0'msg.o'>6��
��VWU���
�>$
u� 
�>&
u� 
�> 
u+���> 
�v� 
��P�
P�$
+�RP�����F��V��P�:P� 
+�RP����F�V��F��V��~�	|�~�@v
�(
P�r����$�F�P�6�a����
�u���F�P+�P�6
�F���� 
.�.

�
�&
+�RP�$
RP�%����F��V��~�|)�~��v#�P
P�����6
������ 
�
���P�v��v��������
�>�
u�6$
�v
P�����뽋6
�F��F�; 
s!����D
�D*�D.�D,�D2�D6�D4�F���:�֋6
�$
.�.

����
��;
r/�&
+�)F�V��F��E�D��|���6 
��
P�K���� 
��]_^�VWU��P�~~�F�.�>
; 
s�>
u������F�.�>
.�.

���t��D�tփ~
t�D
;FuȋF
=v�����.��2G�8V���������u�
��*P�vV�����|,t*�΃�*�D,;�t�FP����
P�FP�v����|4t*�΃�2�D4;�t�FP�W���
P�FP�F����D
;Fu�,��$�>t�;t���FP�����F��>t���>t;Dw��v�������F@@P������D�d��FP�����%�	D�F��D��>t�;u��D���t��D�
�G����
�Gt�g��S�{����
�0t
�
*P�d����D�D�D�D
%�=�u�d
�D
�DtV�4����|0t
�D*P�$����|8t
�D2P�����D�>t���+���]_^�VWU��P+��>
u����>
u���F%��F�� 
.�.

����:��;
vg�D�u�t�E&�U(;T(|�;D&v؋��ԋFF
t̋F�V
;Tu�;Du��Ft�Ft������D#F�;F�u��
���Fu��׋Nj��u����D�D�D�D�"
�D�D�D�D�D �D"�D$���D&�T(���D��D�D�F�
��D�F�V
�D�T�D
��]_^�VWU��~~�F�.�>
; 
s�F;&
w�>
u�����e�F�.�>
.�.

���D
;Fu��D�t�V�c��������u�
���
�t�D;Dwi�Ft�롋D;Dw�L+�PP�PV��
�O+�PP�PS������G$G&t����t��V��F;D
t��!�F��
��F�E�P�EP�v
�����v��
�w�u�F
P����;Ft��>t�����
�G��|t�\�?��|�|�FD�D��G�D���D�T �Dt�d��V�:����|0t
�D*P�*���+�]_^�VWU����~~�F�.�>
; 
s�>
u�����B�F�.�>
.�.

���D
;Fu��D�t�V���������u�
���|�F��~y~�F��F��F�V���؃��F�V�t?�E�U;V|;Fv�~��=��~�t�^��E�U;W|�;Gsމ~��F��F��Ӌ~��F��F��F�V���؃��F�V�)�~x#u�~t�t�E�U;Vu;Ft�~��=���uQ�Ft�����L+�PP�PV�������G$G&t����t�����F;D
u����!���F;Es�Fu����F;Ev�E�F�P�v
�EP�|����v�F
P��
�w�u�b���;Ft��>t�S��~�t	��^�����D;|u�F��D�E)D�L��G�D���D"�T$�Dt�d��V������|8t
�D2P������6
�D��|�Dt�d��V������
�0t
�
*P�����F��]_^�VWU��~~�F�.�>
; 
s�>
u� ��F�.�>
.�.

���D�t�D
;Ft��m�f
���F
t"�|u�~t
�D*P�<����f
����F�F
t5�D;Dr�~t"�D2��>
�}u�~t
�
*P������f
���F
]_^�:
	
�invalid NMSQID or NMSG kernel variable
invalid NMSG or NMSC kernel variable
could not salloc %u messages
could not kalloc %u message ids
timer_free_pollopen_putuwd_ipcaccess_NMSC_&
nondsig_u_NMSG_$
msgs_
msginit_umsgget_msgpoll_V	salloc_umsgctl_�umsgsnd_ANMSQB_"
msqs_
umsgrcv_�cprocp_memset_alloc_NMSQID_ 
wakeup_getuwd_printf_allkp_fucopy_ufcopy_vrmulsleep_ukcopy_kucopy_pollwake_$
$$$$$0,$0$8$E7L$`7g$�7�0�'�7�$�0�$�7�$� �$�$�$�$�7�$�7�$�7$$07 
%&%*$1$478$A$M$t$w |$�$�$�$�$�7�$� �$�$�'�0� � �$0' 0 2 4 67:'I0M7X 7w7�7�7�0�'�0�'�'�'�0�7�'�0�'77730E'I'O$e$s7�$�$�7�!7�7�!7�!'�0�$0$'!0%$1 6$:$E'�0�0�'�'�'�$�''
'' S$W$`$f'm0t } �$�7�'�$�'�$�7�'7'0'$0($,7C%M7]'i'n0t$z'�'�'�7�7�! �$�$�'0  $73'B'	0
7'%70'80<0G'K0O'b0f7� %�7�'�'�0�'�'�'�7	7	!$	71	$8	$A	7H	! h	$l	$r	0{	 �	 �	$�	7�	$�	$�	7
ipc.o'?6��H(VWU��v�>u���/�;t;Du�D��;Dt;Du�D���D���%�]_^�ipcaccess_u_'
''&ipcas.o'?6�vPVWU���FHFr(;w"��ۋv�~
�N��������F]_^�+�]_^�VWU���FHFr�;w��~�v�N��������F]_^�udl_uds_fucopy_@ufcopy_'''R'X0707070064030114461006440000030000030000011777770507310754500004000000001300/newbits/kernel/USRSYS/lib/qq.a]�qq.o!(�����
�|VWU�����P�P�6�6������
�]_^�VWU���6�6
����]_^�VWU��]_^�VWU��]_^�VWU��P�v
�|t8��
RP�����F�VP�z���=��t���.�>���‹�]_^�VWU����v
�F�V�D����F��|"�~�}P�F��
RP�!����F��Ћ�]_^�IR[�2qqcon_�qqclose_Rnulldev_iogetc_qqread_[ffbyte_ptov_sfbyte_qqwrite_�vrelse_ioputc_qqopen_I � �'� � �'�''  '%%
%%7"%(%,%9%=7@	%k%p%t7y7�
%�%� �%�7�%�%�7�0707070064030114451006440000030000030000011777770507310754500004000000004410/newbits/kernel/USRSYS/lib/rp.a]�rp.o'Z�����zVWU����>�v���>�u��0�P��+ҹ������RP������\�>\u����f�>\�E�U�F��V���������;�vC�P�P�v��v������F��V���D��D�T�F��V��D�T
�� �F��V��+���]_^�VWU�쾜������;�v�DDt�t�t�%����� �ك>\t�6\�����\��P+�P��P�����]_^�VWU��P����F��>�u����}��v�������F%�;�r���]_^�VWU��F
�g�CC.;��uD.�gHPQT�yy��~����������v�r�����F%�����P�K����]_^�VWU����v
�F%��������1��F��}u	��F��uJ�Dt���E
+�PP�P�EP������M
��G$G&t�����t��v��������e�E�v�������F�;Dv�D�F��v��tW�����F�D)D�}t
�EP�����}t
�EP�����E�}
t
�EP�s�����]_^�VWU����v
�F%��������M��F��}u
�+�F�=sJ�Dt���E+�PP�P�EP�����M��G$G&t����t��v��������n�E�v�������F�;Dv�D�F��v�W�t������F�D)D�E�}
t
�EP�����}t
�EP�����|t�?��}t
�EP������]_^�VWU��F%��������f
���F
t�D;Du�~t
�DP�D����f
���F
t�D;Dt�~t
�DP� ����f
���F
]_^�VWU��v�����<t?�|t9�D
+�PP�P�DP������L
��G$G&t�����t�W�������<�<t�D�T�D�T
�W�����|t
�DP�����|t
�DP����]_^�
��N��urcopy_rucopy_rpcon_�pollopen_putuwd_nonedev_NRP_�nondsig_sphi_u_nulldev_salloc_cprocp_ptov_memset_wakeup_spl_vrelse_sfree_sleep_rppoll_�pollwake_ �'�
'� � � �'�
'�
'�
 � �$
$$0$$74%:%>%J%Y$\%c7x
%�$�%�7�%�%�7�%�%77%0#'+	72$?'E	 W q s u w%�7�%�0�'�	%�7�'�	0�7'
77'&	737N7g7w7�%�7�'�	0�7�'�7�7'	7767S7c0o7|%�7�7�7�7'!7,74';	7W7g7wrpas.o'Z��b<
VWU���v�^
�N�W����#����F���]_^�VWU���^�~
�N�W��w��#����F��w)�]_^�rucopy_1urcopy_uds_''G0707070064030114441006440000030000030000011777770507310754600004100000007621/newbits/kernel/USRSYS/lib/sem.a]�semcon.o'M6�a���VWU��v�F
-S=v�����.��%a��DP�����P�DP�����P�DP����P�DP����P����PV�����_�DP����P�DP����P�DP����P�DP�w���P�p��DP�g���P�DP�\���P�DP�Q���P�J�����]_^�putuwd_nonedev_u_seminit_usemget_nulldev_usemctl_semcon_�getuwd_usemop_'�'�'�'�'� �'�'�'�'�0   ! #7*757@7K7R7Z7f7q7|7�7�7�7�7�7�	'�sem.o'M6�
�,�GVWU���.�&�P�6��������t ��.�.��������;�r�D���6���P������]_^�VWU����>t��F;�r�.�.�����D�u��V�r�������u�
���F
;Dr����F
���D���F=	v�����.���"��60�B<�o��V���������t��~}�"�z�F��t�}t�E�	�}t
�EP�����+��T�E�N�E�H�E�B�D�F��|�N�|ۋ߃��7�F�FP�����>t��V���������u���D�F��|�N�|,�v�k����F��}�>u�"��F���F���π>u�f���P�vV�-����R��>t�;t���v������F@@P������D�FP�����%�
��D�	��>t�;u��D
�D���D������;Dr"�}t
�EP�����}t��EP�������t�����D��������]_^�VWU��P�F��>t����W�F;�r����.�.��������;�r|�D�u �~�t�^��G�W;T|�;DvӉv��΋FF
tƋF�V
;Tu�;Du��Ft�Ft��|��N����D#F;�t�
�c��D;Fr��d��Fu��F��~�u��8��v��F���P�6�����D�|tڋF�D�D�D���D�T�F���D������;Dr+��E�E�E�����D��D�D�F%�
��D�F�V
�D�T��+��.�>���]_^�VWU����>t���F;�r����F;�r���F.�.�����D�t�V���������u�
��F
�F��F�F��~�u��v������F��F�@@P�w����F��F�P�g����F��>u�F�;DrO�n��F�;F
r1P�B����F��F�@@P�3����F��F����D���v�W�o���À>t������F����D���v�W�����F��}\�n��F�;F
r-P������F�F�@@P������F�P�F���DP����ǀ>t��F�t��w�~�}_�E�]�F��N�����F
�F��F�F��~�t,�v��h����F����D�F��G�^�G�N��F����D�T�F���EPV����|�}������]_^�VWU��P�v�~
��F��}&���؋�;<wB)<�<u�|t
�DP������F��)�~��=�v�"�<�|tߍD�Ӄ<tո����]_^�VWU��v�~
)<t�|t�D�	�|t
�DP����]_^�VWU��P�v�~
�D
�F��+�PP�PW�]����D
;F�t
�!�����
��G$G&t�7��t���+���]_^�could not allocate %u semaphore ids
timer_free_putuwd_ipcaccess_nondsig_NSEM_�u_seminit_usemget_�usemctl_WNSEMID_�cprocp_alloc_wakeup_getuwd_printf_allkp_sleep_usemop_�kucopy_$ '7$$  %$)$4$A$D7H$O'a0g$n0s x$|0�7�'�0�'�0�0� � � � � � � � � � � �0�7�'07&
0.040:0@7`'g0m7q07�'�'�'�0�0�7�0�'�'�'�0�7�770 '$'*7T
7d
7o0z'~'�0�$�'�$� �$�$�'0'3070B0E'P0T'^0b'q7t'�'�'�'�$� �'	0$'0 $''-01 9$=7J'Y0]0r7x7�7�'�7�7�0�'�0�'�0�07(770L'U0['f0~7�'�'�'�0�0�7
'57z
7�'�'�7�'�ipc.o'M6��H(VWU��v�>u���/�;t;Du�D��;Dt;Du�D���D���%�]_^�ipcaccess_u_'
''&ipcas.o'M6�vPVWU���FHFr(;w"��ۋv�~
�N��������F]_^�+�]_^�VWU���FHFr�;w��~�v�N��������F]_^�udl_uds_fucopy_@ufcopy_'''R'X0707070064030114431006440000030000030000011777770507310754700004100000005772/newbits/kernel/USRSYS/lib/shm.a]�shmcon.o'P6�>|BTVWU��>�ta��.�&x��W�6�������u�6���P��������/��.�.z���.�.z����&��;r�D��+�]_^�VWU����v
�D�F��D�F�;�r������F�.�.z���E�u�!��W�E�������u�
�ȋE��F�V��F�+ҋ؋ʋD��;V�w�r;F�w��^�����G�F��F��F��t�t�v�P������u�o��D+���]_^�VWU����v
�D�F��D�F�;�r������F�.�.z���E�u�!��W���������tʋE��F�V��F�+ҋ؋ʋD��;V�w�r;F�w��^�����G�F��F��F��t�v�P�t�5����u�v��D+���]_^�VWU��F
=CHt=GHt8��x�FP�����P�FP�����P�F@@P�����P������=�FP�����P�FP����P�FP����P�F@@P����P����P�v����]_^�(&s.�couldn't kalloc %u shared memory ids
putuwd_ipcaccess_nonedev_u_shmsegs_nulldev_ushmget_ushmctl_NSHMID_�shmids_shmcon_|alloc_getuwd_printf_allkp_ufcopy_fucopy_'�'�'� � � �'�'� �'�$$
 '7'"	$*$-71
$8$? D'H	'K$N S'W	'b	$�'�0� �'�	'�7�'�'�70$G'M0T \'`	'm7t'�7�0�'�7777%747B7P7]7d7nshm.o'P6����VWU��P�F��>t������F;r���F.�.����D�t�F
=v�����.��Q��WV��������u�
른&P�vV�����F��|�>t�;t��b�v�c�����F@@P�U����D�d��FP�@���%�	D밃>t�;u��D
�~��>�5�����D���F����F���]_^�VWU��P�F��>t����Z�.�.�����&��;s��D�u �~�t�~��E"�U$;T$|�;D"vЉv��ˋFF
tËF�V
;Tu�;Du��Ft�Ft�늋~����D#F;�t�
�q��D;Fr���^��Fu��O��~�u��A��v���+�.�>�����>�@P�F+�RP������tʋF�D�D�D�D�D ���D"�T$�>�E�D���D��D�D�F%�
��D�F�V
�D�T�FF
u�L��+�.�>���]_^�&timer_ipcaccess_u_shmsegs_ushmget_salloc_ushmctl_NSHMID_cprocp_shmids_getuwd_sfree_kucopy_'
0''# .'2	0F O Q S U7Y'h7v'�'�'�7�
7�
7�
'�'�'�7�'�'0'  %')	'4	09'�'�0�0�'�0�'�0�'�0�'�	 �'�7�'!'%'/'8'@'q	 wipc.o'P6��H(VWU��v�>u���/�;t;Du�D��;Dt;Du�D���D���%�]_^�ipcaccess_u_'
''&ipcas.o'P6�vPVWU���FHFr(;w"��ۋv�~
�N��������F]_^�+�]_^�VWU���FHFr�;w��~�v�N��������F]_^�udl_uds_fucopy_@ufcopy_'''R'X0707070064030114421006440000000000000000011777770507310754700004300000000746/newbits/kernel/USRSYS/lib/stubs.a]�msgstub.o'\6��DxVWU�� ]_^�VWU���]_^�VWU���]_^�VWU���]_^�VWU���]_^�u_umsgget_msgpoll_umsgctl_6umsgsnd_(umsgrcv_''!'/'=semstub.o'\6�J
VWU��]_^�semexit_shmstub.o'\6�J
VWU��]_^�shmexit_0707070064030114411006440000000000000000011777770507310754700004700000000746/newbits/kernel/USRSYS/lib/stubs.a.310]�msgstub.o'\6��DxVWU�� ]_^�VWU���]_^�VWU���]_^�VWU���]_^�VWU���]_^�u_umsgget_msgpoll_umsgctl_6umsgsnd_(umsgrcv_''!'/'=semstub.o'\6�J
VWU��]_^�semexit_shmstub.o'\6�J
VWU��]_^�shmexit_0707070064030116141006440000000000000000011777770507310755000004100000013642/newbits/kernel/USRSYS/lib/gkb.a]�gkb.o�(>����:���VWU��>�u?jja������V)N}�h�ja�����+�Nu�j`�������h�ja�����jMja�����h�j����h������_^�VWU��j�����_^�VWU���F�t��N���t�h��u��8�vh��T����N�������u���h��2���V�+�����_^�VW�+���}
����LJ�F���F��+���}9����F�������㋿�
�F��F��F���G���^���=��t	�~��r��F���_^�VWU��������u����h�����V�����_^�VWU��j�v
h������>�t	h��u����_^�VWU��F
���CC.;��u.�gMN���
���@����v�v
h��2���V�+����V�v�v
�Q���H�8*��\����
|�
��k
�l
��#�8)�����\�
��
|�k
��l
�_^�VW��~�u�����sc��P�F
�F
P����F��+���}
����LJ�G���+���}1���㉷���F�F��F
�F
P�l����^���=��t���r��G���_^�VWU��f
���F
t"�>�u�~t	h
�+����>�u�f
���F
�_^�VW��F��>uh�h�������j`�����%��F�ja���������
�Pja�����Vja������>�t=���~��t�C���%���� t����t��Vj`������>�~����F����CC.;��u.�g�������>�t��������F�%H���F��u��Ru��%=u����B
*���ǀu��F��tK��5u	�&�����8�;�u	�&����t��u	�&����f��7t�^�>�t�������!��H�8�;�u	���7��5u	���)��u	�����7u�>�t���	����9u�6�������Dt���6� ���F��t���>�u����t��:�X��t,��u��
u��C�
�>��t��t����*�%�&#>�t��t��0u����
��0u􊄒*�����t[���t��t�΀V�U����v��>��F��~�t.���F�h�j`�������v��y����������_^�VW��F�+��F-=Dv�c����.���JPq���������������������������>�t�����t�������>�t������t�^��1�㋷���^��;����
@uo�F��� t�

������V�
������H�N�N+��� t���t����@t��>�t+�����N��Gk���ڋ��
�t�<t�<�t��F��%�P�s����F��_^�VWU��v�ƻ\�CC.;��uJ.�g
=>ctu���rz�� �'�&������@��&��������>����_^�VWU��v�2
*���ƈ�4
�2
�2
*�=r�2
�_^�VWU��v�!����X*�:�Yu���Y*�ȋ�ي�Z*����Y*�=�rƄY���Y�>t��.���;�t��/���;�u
WV������3��bu�>�u��6�V�����׃�cu�>�t�j�����>��f��_^�VW��t��F�h�j`�i������v��Z����_^�VWU��������_^�
zBk�i�)�������{[]}\���@����������~����������������������������������������������������������|��1234567890�'	qwertzuiop�+
�asdfghjkl��^�#yxcvbnm,.���� ����������������-���+�������<��!"$%&/()=?`�QWERTZUIOP�*
�ASDFGHJKL����'YXCVBNM;:���� ����������������-���+�������>��������cccccccccccc
"(.4:@FLRX^djpv|����������������������������������������������������7?w8?x9?y4?t75?u6?v1?q2?r3?s[@0?p.?n/_-*ismmfunc_Aclrivec_pollopen_super_initkeys_�updleds_�isuload_immwatch_isclose_Bsetivec_boot_sphi_u_putchar_isioctl_�drvl_isread_kinb_outb_nulldev_getubd_isload_isspecial_�ttsetgrp_agmaptab_:istty_�ttclose_kbunscroll_�ttin_isfunction_4ttioctl_ttread_islock_mmwrite_defer_mmstart_isturbo_�mmtime_mm_von_isopen_zspl_ispoll_�putubd_isrint_�ttopen_iscon_�isbusy_ � �'� �'�! �'�'� � � �'�#$77"7/7<7F'M R7W	$]7`#7q$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
'�$�7�'�$�7�7�$�$�0�$�$�7�,7�(0�%�%�%$%57H$N7S$X7[7b($v7y$�$�7�% � � � � �7�$�7�7�(0�$�$�$�$�$�$$$$$$$#$($-%B%F7V*%k%s%�7�%�$�$�7�$�'�.$� 7"'.77 7079%@%G0S%V%`%l7z0�%�%�0� � � � �%�%�%�%�%�7�
$�0�%0$%0"%+0008%<%K0N$Q%Z0_%h0m%v0{%�%�0�%�0�0�0�%�0�$�0�%�$�%�0$%%$%$1%E0Q0\7k7v%}7�(%�%�$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$�
$$0� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @ B D F H$K0N%R$X0[%_$f0i$l0o%s0y$|0%�%�0�%�$�$�$�%�%�$�%�%�%�%�%�%�$03 L h j l n p%t%|%�%�'� %�0�0�$�$�$�$�$�7�&'�.0�'  7>%L'S %Y7]%k7s
%z0}7�7�%�7�(%�0�0707070064030110651006440000000000000000011777770507310755100004000000013142/newbits/kernel/USRSYS/lib/kb.a]�kb.o�(���DF���lVWU��>`u?jja������V)N}�h�ja�����+�Nu�j`�������h�ja�����jMja�����h�j����hb�����_^�VWU��j�����_^�VWU���F�t��N���t�h��u��8�vhb�T����N���~�~�u���hb�2���V�+����0�_^�VW�+���}
����LJ�F���F�+���}9����F�������㋿��F��F��F���G���^���=��t	�~��r��F���_^�VWU�������~u����hb����V�����_^�VWU��j�v
hb�����>bt	hb�u����_^�VWU��F
���CC.;��u.�gMN���
���@����v�v
hb�2���V�+����V�v�v
�Q���H��*��\����?|�@�������#��)�����\�?��@|������_^�VW��~�u����sc��P�F
�F
P����F��+���}
����LJ�G��+���}1���㉷���F�F��F
�F
P�l����^���=��t���r��G���_^�VWU��f
���F
t"�>lu�~t	h�	�+����>lu�f
���F
�_^�VW��F��>uhbh\������j`�����%��F�ja���������
�Pja�����Vja������>tE��~��t����%������� t��������t��Vj`�|������>~���~��u	���~��u��F�%H���F��u��Ru��%=u�*���j*���ǀu��F��t:��5u�&��T���;�u�&��D��u�&��7��7t�/�&��'���;�u����5u��
��u�����7u�����9u�6�����Dt���6 ���F��t���>~u�������t,��u��
u��I�
�D��t��t���*�%�,��#�t������t��0u���
��0u��*�����tQ���t������t�΀V�����v��0��F��~�t ����F�h�j`�������v������_^�VW��F�+��F-=Dv�9����.��w��������������������������������������������*bbb�___�\\\\\��������t�^��1�㋷���^��;����	@ur�F��� t��	����Y��	����K�N�N+������� t�������t��������@t�����N��Gk���ڋ���t�<t�<�t��F��%�P�n����F��_^�VWU��v�ƻ��CC.;��uE.�g
=>ctu
�� �#�&���@��&���������_^�VWU��v��	*���ƈ��	��	��	*�=r��	�_^�VWU��v�����X*�:�Yu���Y*�ȋ�ي�Z*����Y*�=�rƄY���Y�>t��.���;�t��/���;�u
WV�8����3��bu�>u��6V�����׃�cu�>t�j�����>�f��_^�VW�����F�h�j`�������v�������_^�VWU�������_^�
zBk�i�)1234567890-=	qwertyuiop[]
�asdfghjkl;'`�\zxcvbnm,./�*� ����������������-���+�����!@#$%^&*()_+�QWERTYUIOP{}
�ASDFGHJKL:"~�|ZXCVBNM<>?�*� ����������������-���+�����������cccccccccccc(
.
4
:
@
F
L
R
X
^
d
j
p
v
|
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
	��������������������7?w8?x9?y4?t75?u6?v1?q2?r3?s[@0?p.?nismmfunc_�clrivec_pollopen_super_initkeys_�updleds_isuload_immwatch_isclose_Bsetivec_boot_sphi_u_putchar_isioctl_�drvl_isread_kinb_outb_nulldev_getubd_isload_isspecial_Sttsetgrp_istty_bttclose_kbunscroll_5ttin_isfunction_4ttioctl_ttread_islock_mmwrite_defer_mmstart_isturbo_`mmtime_mm_von_isopen_zspl_ispoll_�putubd_isrint_�ttopen_iscon_Fisbusy_ J L'N P'R  T'V'X Z \ ^'x"$77"7/7<7F'M R7W	$]7`"7q$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�'�$�7�'�$�7�7�$�$�0�$�$�7�+7�'0�%�%�%$%57H$N7S$X7[7b'$v7y$�$�7�$ � � � � �7�$�7�7�'0�$�$�$�$�$�$$$$$$$#$($-%B%F7V)%k%s%�7�%�$�$�7�$�'�-$� 7!'-77 7079%@%G0S%V%_%o7�0�%�%�0�%�0�0�%�7�
$�0�%�0�$�%0	%00%"0&$)%206%?0C%L0P%Y0]%f0j0m0u%y0�$�0�%�0�$�%�%�$�$�%00!707;%B7J'$�$�$�$�$�$�$�$�$�$�$�$�$�$
$
$
$
$
$

$
$
$
$
$
$
$
$
$
$
$ 
$"
$$
$&
0l u w y { }  � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �$0%%0 %+$/$:$A%E%I$O%S%W%e%t%�$�0� � � � � � �%%%%'%#0'0*$9$C$G$J$U7e%'i-0z'�7�%�'�%�7�%�7�
%077%$7,'%<0@0707070064030110641006440000000000000000011777770507310755300004100000014656/newbits/kernel/USRSYS/lib/nkb.a]�nkb.o�(*����
�,<�VWU����
�~���hj�����h�
�����h0@jh������t�>tu	hT�����v�_^�VWU��>�
t	h�����j�����>tt�~�6t�v����_^�VWU���F�t��H��t�Q��u��2�vh�
�=����7�����u�h�
����V�����_^�VWU�������u	h�
�����V������_^�VWU��j�v
h�
������>�
t	h�
������_^�VWU��F
-�=w/����.��T\\rj�v�v
�
���+�v�)� �v�������v�v
h�
�u���V�n����_^�VW�jh����h�����t�G�W�F��V�+���r�jh��v�'���j�v��v�h������F��V��F��*��;�t�>�tVh�������%����*��;�tF뚠�*�%��D�CC.;��u,.�g@��bVh(Vh�������Vh���Vh���h�������jh����h��&����
�F��g����6�
�^�������t�N��j`�6�
�E����F�2�N����
�F��6�
�+�������t�N���6�
�6�
������
�F��6�
��������t�N��W������~�_^�VW��>t�E�U�F��V�+���s.jh��v��v�����j�vh������F��V��FF���_^�VW��F��~�u#�>�u��4�6v�v
�6�
�c���� ���>�
t
�6�
�J����>�
t
�6�
�9���j�F�P�v
�*����v�F
@��+��F�*�;�v�v��FP����=�u�G���6v�6�������
�F�*���P�6�������
�>�
t�>�
u5�>�
t�6�
������
�>�
t�6�
������
��T��
@���F
@�F
+��F�*�;�v,�����
�7��F�F��F
�F
P�_����^��*�=�u�G�ˊF�*��
����_^�VWU��f
���F
t"�>u�~t	h.�����>u�f
���F
�_^�VWU��>uh�
h��������6�
�����%����6�
����������
P�6�
����V�6�
�����ǻl�CC.;��t�.�g��������������uh��i����j�6x�6�
�Y����Zh����
=w0����.�������h����
h�
�%����
�6z��6�
h3�
�베��PW������_^�VW��>~u��j�F�P�tkF����+�GWRP������F�*�;Ft��F�*�F��F�u���F�*�H=wl����.��n�tt�~
t��F�*�������1r��k�~
ue�F�*�������1r��"@uH� t
�&�P����3�'��~
t�F�*���������!r��F�*�������	r�|�rt	�|���r0t�|�rt�|�r�u���|���~
t��>u���>|�E�*�=�u��F�t�ru�F�t�rt�|��������>|�E�*�F��F�tT�~�u�~
u
�>�
t�@��>�t@�>�
�*�;F�v3�~���>�
����t"�*�=�t��F�*�P�`�����v��U���_^�VWU��v�ƻ&�CC.;��u1.�g
=>ctuUUO<G�r����&r������_^�VWU��v�N*���ƈ�P�N�N*�=r�N�_^�VWU��v�p����X*�:�Yu���Y*�ȋ�ي�Z*����Y*�=�rƄY���Y�>t��.���;�t��/���;�u
WV�����3��bu�>�u��6�V������׃�cu�>�t�j������>��f��_^�VWU��r��%Ph������_^�VWU��6�
����N~�6�
��������u���
�r��%�z�x�h��6�
�m���W�f����_^�VWU��&r�����_^�VWU���E����>�
th�jh�h�
�.�������
�6�
N~�6�
��������u��uhG�����'�v�6�
������>�
th�jh�h�
�������W������_^�VWU��������>�
th�jh�h�
��������
�F
�z�F�x�6�
N~�6�
��������u��uh\�p����'�v�6�
�a����>�
th�jh�h�
�I�����W�@����_^�`ad�'
��;Z�kb: unable to allocate keyboard table segment
kb: keyboard busy during unload
kb: incorrect or unsorted table entry %d
kb: bad key mode
kb: keyboard BAT failed
kb: keyboard buffer overrun
kb: ACK while keyboard idle
kb: bad kbstate %d
kb: command timeout
kb: command timeout
ismmfunc_free_updleds2_O	isgettable_process_key_
KBFLAG_�
KBDATA_�
clrivec_pollopen_super_issettable_�updleds_4	isuload_Zmmwatch_isclose_�setivec_boot_sphi_KBTIMEOUT_�
u_putchar_isioctl_;drvl_isread_inb_outb_nulldev_KBSTS_CMD_�
getubd_isload_ttsetgrp_istty_�
ttclose_salloc_kbunscroll_�	ttin_KBBOOT_�
isfunction_oKBCTRL_�
ttioctl_ttread_mmwrite_islock_defer_mmstart_mmtime_alloc_mm_von_fkcopy_kfcopy_wakeup_isopen_�spl_kb_cmd2_7
printf_ispoll_�allkp_sfree_KBCMDBYTE_�
sleep_isrint_ttopen_kucopy_ukcopy_iscon_�
isbusy_kb_cmd_�	 �
 �
'�
 �
'�
) �
'�
'�

 �
 �
 �
',$%
%' 7!$'7*,78!%>%B$H7K6%R$a$g7j67r%y%�%�7�9'�$�7�	'�$�7�7�$�$�$�$�7�=7�47�$�$7 74$7"($)$/72- R T V X Z0c0n0v7{$�7�'7�40�0�%�0�%�7�?%�7�1%�%$
76'0%%, 4 N P R T0[$o7r60z0�0�$�7�$�7�$�7�$�$�7�$�$�7�$�$�7�74%%'%@7I0%T7W>%�'�0�%�$�7�>0�%�$�$�7�$�$�7�7�?%�%�7�%'87.$'!87$.$*$.$5$<$C7F$M$S$Z7]$d'j$p$�7�$�%�$�$�7�$�'A$ 7+'A$!7$$073$>$C7F$N7Q Y0h | ~ � � � � �%�$�7�6%�$�7�$�$� � � � � �$�$�$�7�2$�%�$�$�7�6%�0�%%0%"7700G0X l n p r0{%�0�%�0�$�$�$�0�$�%�%�%%%0%% %&%.%40;%?0D0M$Q0W%]0j%t%�%�%�$�7�%�$�$�0�0  2 4 6 8 :%>0C%I'Q*$b$l$p$s$~7�/'�A0�'�*7�#%�'	*%
	7	#%	7$	%+	0.	%:	0F	$V	7Y	$b	7e	$t	%y	%�	%�	$�	7�	7�	4%�	0�	7�	$�	$�	7�	;$�	$�	$�	7�	$�	7�	6$

7
$
$"
7%
;7.
47=
$C
$Q
7T
;$]
%e
%k
$o
$v
7y
$�
7�
6$�
7�
$�
$�
7�
;7�
40707070064030127160407550000030000030000011777770507310755400003700000000000/newbits/kernel/USRSYS/confdrv0707070064030116111004440000030000030000011777770507310755400004300000001065/newbits/kernel/USRSYS/confdrv/al0:
: 'Serial Lines COM1 and COM3'
:
UNDEF="${UNDEF} -u a0con_ lib/al.a"
PATCH="${PATCH} drvl_+50=a0con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/com1l  c 5 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com1r  c 5 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com1pl c 5 192	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com1pr c 5 64		|| exit 1

	/etc/mknod -f ${DEV-/dev}/com3l  c 5 129	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com3r  c 5 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com3pl c 5 193	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com3pr c 5 65		|| exit 1
fi
0707070064030116101004440000030000030000011777770507310755500004300000001065/newbits/kernel/USRSYS/confdrv/al1:
: 'Serial Lines COM2 and COM4'
:
UNDEF="${UNDEF} -u a1con_ lib/al.a"
PATCH="${PATCH} drvl_+60=a1con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/com2l  c 6 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com2r  c 6 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com2pl c 6 192	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com2pr c 6 64		|| exit 1

	/etc/mknod -f ${DEV-/dev}/com4l  c 6 129	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com4r  c 6 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com4pl c 6 193	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com4pr c 6 65		|| exit 1
fi
0707070064030116071004440000030000030000011777770507310755500004200000003034/newbits/kernel/USRSYS/confdrv/at:
: AT Hard Disk
:
MAJOR=11

case "${ARG}" in
*1?)	HD_TYPE=at1 ;;
*)	HD_TYPE=at0 ;;
esac
:
:	needed by config
:
UNDEF="${UNDEF} -u atcon_ lib/at.a"
PATCH="${PATCH} drvl_+110=atcon_"

case ${ARG} in
at0a)	MAKEDEV="makedev(11,0)" ;;
at0b)	MAKEDEV="makedev(11,1)" ;;
at0c)	MAKEDEV="makedev(11,2)" ;;
at0d)	MAKEDEV="makedev(11,3)" ;;
at1a)	MAKEDEV="makedev(11,4)" ;;
at1b)	MAKEDEV="makedev(11,5)" ;;
at1c)	MAKEDEV="makedev(11,6)" ;;
at1d)	MAKEDEV="makedev(11,7)" ;;
at)
	;;
*)
	/bin/echo "invalid argument: ${ARG}"
	exit 1
	;;
esac

:
: needed for both build and config
:
DEV=${DEV-/dev}
if [ -d "$DEV" ]
then
	umask 077
	/etc/mknod -f $DEV/at0a  b 11 0		|| exit 1
	/etc/mknod -f $DEV/at0b  b 11 1		|| exit 1
	/etc/mknod -f $DEV/at0c  b 11 2		|| exit 1
	/etc/mknod -f $DEV/at0d  b 11 3		|| exit 1
	/etc/mknod -f $DEV/at0x  b 11 128	|| exit 1
	/etc/mknod -f $DEV/rat0a c 11 0		|| exit 1
	/etc/mknod -f $DEV/rat0b c 11 1		|| exit 1
	/etc/mknod -f $DEV/rat0c c 11 2		|| exit 1
	/etc/mknod -f $DEV/rat0d c 11 3		|| exit 1
	/etc/mknod -f $DEV/rat0x c 11 128	|| exit 1
	/etc/mknod -f $DEV/at1a  b 11 4		|| exit 1
	/etc/mknod -f $DEV/at1b  b 11 5		|| exit 1
	/etc/mknod -f $DEV/at1c  b 11 6		|| exit 1
	/etc/mknod -f $DEV/at1d  b 11 7		|| exit 1
	/etc/mknod -f $DEV/at1x  b 11 129	|| exit 1
	/etc/mknod -f $DEV/rat1a c 11 4		|| exit 1
	/etc/mknod -f $DEV/rat1b c 11 5		|| exit 1
	/etc/mknod -f $DEV/rat1c c 11 6		|| exit 1
	/etc/mknod -f $DEV/rat1d c 11 7		|| exit 1
	/etc/mknod -f $DEV/rat1x c 11 129	|| exit 1
	chown sys $DEV/at* $DEV/rat*
	chgrp sys $DEV/at* $DEV/rat*
fi
0707070064030115721004440000030000030000011777770507310755500004300000000140/newbits/kernel/USRSYS/confdrv/ati:
: 'Array Technologies Inc - Graphics Solution - excludes Keyboard'
UNDEF="${UNDEF} lib/ati.a"
0707070064030115151004440000030000030000011777770507310755500004200000001164/newbits/kernel/USRSYS/confdrv/fl:
: AT Floppy Driver
:
UNDEF="${UNDEF} -u flcon_ lib/fl.a"
PATCH="${PATCH} drvl_+40=flcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0133
	/etc/mknod -f ${DEV-/dev}/f9a0 b 4 12	|| exit 1
	/etc/mknod -f ${DEV-/dev}/f9a1 b 4 28	|| exit 1
	/etc/mknod -f ${DEV-/dev}/f9d0 b 4  4	|| exit 1
	/etc/mknod -f ${DEV-/dev}/f9d1 b 4 20	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fha0 b 4 14	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fha1 b 4 30	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fqa0 b 4 13	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fqa1 b 4 29	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fva0 b 4 15	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fva1 b 4 31	|| exit 1
fi
0707070064030115141004440000030000030000011777770507310755500004200000000423/newbits/kernel/USRSYS/confdrv/gm:
: Tecmar Graphics Master
:
UNDEF="${UNDEF} -u iscon_ -u grcon_ lib/gm.a"
PATCH="${PATCH} drvl_+20=iscon_ drvl_+300=grcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c  2 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/gr      c 30 0 || exit 1
fi
0707070064030115131004440000030000030000011777770507310755600004200000000344/newbits/kernel/USRSYS/confdrv/gr:
: Graphics Display on PC Color Card - excludes keyboard
:
UNDEF="${UNDEF} -u grcon_ lib/gr.a"
PATCH="${PATCH} drvl_+300=grcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/gr      c 30 0 || exit 1
fi
0707070064030115121004440000030000030000011777770507310755600004200000001744/newbits/kernel/USRSYS/confdrv/hs:
: 'Hostess/Arnet multi-port Serial Support (Version 7 Compatible)'
:
UNDEF="${UNDEF} -u hscon_ lib/hs.a"
PATCH="${PATCH} drvl_+70=hscon_"
:
: non modem control devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/hs00 c 7  0 || exit 1
/etc/mknod -f ${DEV-/dev}/hs01 c 7  1 || exit 1
/etc/mknod -f ${DEV-/dev}/hs02 c 7  2 || exit 1
/etc/mknod -f ${DEV-/dev}/hs03 c 7  3 || exit 1
/etc/mknod -f ${DEV-/dev}/hs04 c 7  4 || exit 1
/etc/mknod -f ${DEV-/dev}/hs05 c 7  5 || exit 1
/etc/mknod -f ${DEV-/dev}/hs06 c 7  6 || exit 1
/etc/mknod -f ${DEV-/dev}/hs07 c 7  7 || exit 1
:
: modem control versions
:
/etc/mknod -f ${DEV-/dev}/hs00r c 7 128 || exit 1
/etc/mknod -f ${DEV-/dev}/hs01r c 7 129 || exit 1
/etc/mknod -f ${DEV-/dev}/hs02r c 7 130 || exit 1
/etc/mknod -f ${DEV-/dev}/hs03r c 7 131 || exit 1
/etc/mknod -f ${DEV-/dev}/hs04r c 7 132 || exit 1
/etc/mknod -f ${DEV-/dev}/hs05r c 7 133 || exit 1
/etc/mknod -f ${DEV-/dev}/hs06r c 7 134 || exit 1
/etc/mknod -f ${DEV-/dev}/hs07r c 7 135 || exit 1
0707070064030115111004440000030000030000011777770507310755600004200000000560/newbits/kernel/USRSYS/confdrv/lp:
: Parallel Line Printers LPT1, LPT2 and LPT3
:
UNDEF="${UNDEF} -u lpcon_ lib/lp.a"
PATCH="${PATCH} drvl_+30=lpcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0555
	/etc/mknod -f ${DEV-/dev}/lpt1 c 3 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/lpt2 c 3 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/lpt3 c 3 2		|| exit 1
	: /bin/ln  -f ${DEV-/dev}/lpt1 ${DEV-/dev}/lp	|| exit 1
fi
0707070064030115101004440000030000030000011777770507310755600004200000000117/newbits/kernel/USRSYS/confdrv/mm:
: 'Memory Mapped (Text) Video - excludes Keyboard'
UNDEF="${UNDEF} lib/mm.a"
0707070064030115071004440000030000030000011777770507310755600004200000000302/newbits/kernel/USRSYS/confdrv/ms:
: 'Microsoft Bus Mouse'
:
UNDEF="${UNDEF} -u mscon_ lib/ms.a"
PATCH="${PATCH} drvl_+100=mscon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0333
	/etc/mknod -f ${DEV-/dev}/mouse c 10 0 || exit 1
fi
0707070064030115061004440000030000030000011777770507310755600004300000000313/newbits/kernel/USRSYS/confdrv/msg:
: System V Compatible Messaging
:
UNDEF="${UNDEF} -u msgcon_ lib/msg.a"
PATCH="${PATCH} drvl_+250=msgcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0333
	/etc/mknod -f ${DEV-/dev}/msg c 25 0 || exit 1
fi
0707070064030115041004440000030000030000011777770507310755600004200000001112/newbits/kernel/USRSYS/confdrv/rm:
: Dual RAM Disk
: Default each to 512K for now...
:
UNDEF="${UNDEF} -u rmcon_ lib/rm.a"
PATCH="${PATCH} drvl_+80=rmcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/ram0 b 8 8 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram0 c 8 8 || exit 1
	/etc/mknod -f ${DEV-/dev}/ram0close b 8 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram0close c 8 0 || exit 1

	/etc/mknod -f ${DEV-/dev}/ram1 b 8 136 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram1 c 8 136 || exit 1
	/etc/mknod -f ${DEV-/dev}/ram1close b 8 128 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram1close c 8 128 || exit 1
fi
0707070064030115031004440000030000030000011777770507310755700004200000000513/newbits/kernel/USRSYS/confdrv/rp:
: Ram Pipes
:
UNDEF="${UNDEF} -u rpcon_ lib/rp.a"
PATCH="${PATCH} NRP_=4 drvl_+220=rpcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/rp0 c 22 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/rp1 c 22 1 || exit 1
	/etc/mknod -f ${DEV-/dev}/rp2 c 22 2 || exit 1
	/etc/mknod -f ${DEV-/dev}/rp3 c 22 3 || exit 1
fi
0707070064030115021004440000030000030000011777770507310755700004300000000421/newbits/kernel/USRSYS/confdrv/rs0:
: 'Raw (fast) Serial Line COM1 (System V Compatible)'
:
UNDEF="${UNDEF} -u rs0con_ lib/rs.a"
PATCH="${PATCH} drvl_+50=rs0con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/rs0  c 5 0	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rs0r c 5 128	|| exit 1
fi
0707070064030115011004440000030000030000011777770507310755700004300000000421/newbits/kernel/USRSYS/confdrv/rs1:
: 'Raw (fast) Serial Line COM2 (System V Compatible)'
:
UNDEF="${UNDEF} -u rs1con_ lib/rs.a"
PATCH="${PATCH} drvl_+60=rs1con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/rs1  c 6 0	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rs1r c 6 128	|| exit 1
fi
0707070064030114771004440000030000030000011777770507310755700004300000000314/newbits/kernel/USRSYS/confdrv/sem:
: System V Compatible Semaphores
:
UNDEF="${UNDEF} -u semcon_ lib/sem.a"
PATCH="${PATCH} drvl_+230=semcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0333
	/etc/mknod -f ${DEV-/dev}/sem c 23 0 || exit 1
fi
0707070064030114761004440000030000030000011777770507310755700004300000000313/newbits/kernel/USRSYS/confdrv/shm:
: System V Subset Shared Memory
:
UNDEF="${UNDEF} -u shmcon_ lib/shm.a"
PATCH="${PATCH} drvl_+240=shmcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/shm c 24 0 || exit 1
fi
0707070064030114741004440000030000030000011777770507310755700004200000001114/newbits/kernel/USRSYS/confdrv/st:
: Archive SC-400 Streaming Tape Drive.
:
:	Minor device 0 allocates a maximum sized read/write cache [up to 256k].
:	Minor device n [1..127] allocates a n Kbyte sized read/write cache.
:	Adding 128 to one of the above minor devices inhibits rewind on close.
:
UNDEF="${UNDEF} -u stcon_ lib/st.a"
PATCH="${PATCH} drvl_+120=stcon_"

if [ -d "${DEV-/dev}" ]
then
	umask 077
	/etc/mknod -f ${DEV-/dev}/rst    c 12   0	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rst32  c 12  32	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rst64  c 12  64	|| exit 1
	/etc/mknod -f ${DEV-/dev}/nrst   c 12 128	|| exit 1
fi
0707070064030114731004440000030000030000011777770507310755700004200000000543/newbits/kernel/USRSYS/confdrv/tn:
: 'Tiac PC-234/6 ARCNET LAN boards [0..3]'
:
UNDEF="${UNDEF} -u tncon_ lib/tn.a"
PATCH="${PATCH} drvl_+200=tncon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/tn0 c 20 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/tn1 c 20 1 || exit 1
	/etc/mknod -f ${DEV-/dev}/tn2 c 20 2 || exit 1
	/etc/mknod -f ${DEV-/dev}/tn3 c 20 3 || exit 1
fi
0707070064030114751004440000030000030000011777770507310755700004200000003231/newbits/kernel/USRSYS/confdrv/ss:
: Hard Disk on Seagate ST01/ST02 series SCSI controller.
:
MAJOR=13

case "${ARG}" in
*1?)	HD_TYPE=ss1 ;;
*)	HD_TYPE=ss0 ;;
esac
:
:	needed by config
:
UNDEF="${UNDEF} -u sscon_ lib/ss.a"
PATCH="${PATCH} drvl_+130=sscon_"

case ${ARG} in
ss0a)	MAKEDEV="makedev(13,0)" ;;
ss0b)	MAKEDEV="makedev(13,1)" ;;
ss0c)	MAKEDEV="makedev(13,2)" ;;
ss0d)	MAKEDEV="makedev(13,3)" ;;
ss1a)	MAKEDEV="makedev(13,16)" ;;
ss1b)	MAKEDEV="makedev(13,17)" ;;
ss1c)	MAKEDEV="makedev(13,18)" ;;
ss1d)	MAKEDEV="makedev(13,19)" ;;
ss)
	;;
*)
	/bin/echo "invalid argument: ${ARG}"
	exit 1
	;;
esac

:
: needed for both build and config
:
if [ -d "${DEV-/dev}" ]
then
	umask 077
	/etc/mknod -f ${DEV-/dev}/ss0a  b 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0b  b 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0c  b 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0d  b 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0x  b 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0a c 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0b c 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0c c 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0d c 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0x c 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1a  b 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1b  b 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1c  b 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1d  b 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1x  b 13 144	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1a c 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1b c 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1c c 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1d c 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1x c 13 144	|| exit 1
fi
0707070064030035651004440000030000030000021777770507310756000004700000003126/newbits/kernel/USRSYS/confdrv/aha154x:
: Hard Disk on Adaptec AHA154x series host adaptor
:
MAJOR=13

case "${ARG}" in
*1?)	HD_TYPE=sd1 ;;
*)	HD_TYPE=sd0 ;;
esac
:
:	needed by config
:
UNDEF="${UNDEF} -u sdcon_ lib/aha154x.a"
PATCH="${PATCH} drvl_+130=sdcon_"

case ${ARG} in
sd0a)	MAKEDEV="makedev(13,0)" ;;
sd0b)	MAKEDEV="makedev(13,1)" ;;
sd0c)	MAKEDEV="makedev(13,2)" ;;
sd0d)	MAKEDEV="makedev(13,3)" ;;
sd1a)	MAKEDEV="makedev(13,16)" ;;
sd1b)	MAKEDEV="makedev(13,17)" ;;
sd1c)	MAKEDEV="makedev(13,18)" ;;
sd1d)	MAKEDEV="makedev(13,19)" ;;
sd)
	;;
aha154x)
	;;
*)
	/bin/echo "invalid argument: ${ARG}"
	exit 1
	;;
esac

:
: needed for both build and config
:
DEV=${DEV-/dev}
if [ -d "$DEV" ]
then
	umask 077
	/etc/mknod -f $DEV/sd0a  b 13 0		|| exit 1
	/etc/mknod -f $DEV/sd0b  b 13 1		|| exit 1
	/etc/mknod -f $DEV/sd0c  b 13 2		|| exit 1
	/etc/mknod -f $DEV/sd0d  b 13 3		|| exit 1
	/etc/mknod -f $DEV/sd0x  b 13 128	|| exit 1
	/etc/mknod -f $DEV/rsd0a c 13 0		|| exit 1
	/etc/mknod -f $DEV/rsd0b c 13 1		|| exit 1
	/etc/mknod -f $DEV/rsd0c c 13 2		|| exit 1
	/etc/mknod -f $DEV/rsd0d c 13 3		|| exit 1
	/etc/mknod -f $DEV/rsd0x c 13 128	|| exit 1
	/etc/mknod -f $DEV/sd1a  b 13 16	|| exit 1
	/etc/mknod -f $DEV/sd1b  b 13 17	|| exit 1
	/etc/mknod -f $DEV/sd1c  b 13 18	|| exit 1
	/etc/mknod -f $DEV/sd1d  b 13 19	|| exit 1
	/etc/mknod -f $DEV/sd1x  b 13 144	|| exit 1
	/etc/mknod -f $DEV/rsd1a c 13 16	|| exit 1
	/etc/mknod -f $DEV/rsd1b c 13 17	|| exit 1
	/etc/mknod -f $DEV/rsd1c c 13 18	|| exit 1
	/etc/mknod -f $DEV/rsd1d c 13 19	|| exit 1
	/etc/mknod -f $DEV/rsd1x c 13 144	|| exit 1
	chown sys $DEV/sd* $DEV/rsd*
	chgrp sys $DEV/sd* $DEV/rsd*
fi
0707070064030035651004440000030000030000021777770507310756000004200000000000/newbits/kernel/USRSYS/confdrv/sd0707070064030115051004440000030000030000011777770507310756000004200000000300/newbits/kernel/USRSYS/confdrv/qq:
: 'Dummy driver for write to absolute RAM area'
:
UNDEF="${UNDEF} -u qqcon_ lib/qq.a"
PATCH="${PATCH} drvl_+70=qqcon_"
:
: devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/qq c 7  0 || exit 1
0707070064030115161004440000030000030000011777770507310756100004200000000424/newbits/kernel/USRSYS/confdrv/dg:
: 'Driver for Digiboard PC/Xe'
:
UNDEF="${UNDEF} -u dgcon_ lib/dg.a"
PATCH="${PATCH} drvl_+210=dgcon_"
:
: devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/dg c 21  0 || exit 1
/etc/mknod -f ${DEV-/dev}/dgx c 21  128 || exit 1
/etc/mknod -f ${DEV-/dev}/dgy c 21  64 || exit 1
0707070064030066730407550000030000030000011777770507310756100004300000000000/newbits/kernel/USRSYS/confdrv/RCS0707070064030057011004440000030000030000011777770507310756100005500000003633/newbits/kernel/USRSYS/confdrv/RCS/aha154x,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.11;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Hard Disk on Adaptec AHA154x series host adaptor
:
MAJOR=13

case "${ARG}" in
*1?)	HD_TYPE=sd1 ;;
*)	HD_TYPE=sd0 ;;
esac
:
:	needed by config
:
UNDEF="${UNDEF} -u sdcon_ lib/aha154x.a"
PATCH="${PATCH} drvl_+130=sdcon_"

case ${ARG} in
sd0a)	MAKEDEV="makedev(13,0)" ;;
sd0b)	MAKEDEV="makedev(13,1)" ;;
sd0c)	MAKEDEV="makedev(13,2)" ;;
sd0d)	MAKEDEV="makedev(13,3)" ;;
sd1a)	MAKEDEV="makedev(13,16)" ;;
sd1b)	MAKEDEV="makedev(13,17)" ;;
sd1c)	MAKEDEV="makedev(13,18)" ;;
sd1d)	MAKEDEV="makedev(13,19)" ;;
sd)
	;;
aha154x)
	;;
*)
	/bin/echo "invalid argument: ${ARG}"
	exit 1
	;;
esac

:
: needed for both build and config
:
if [ -d "${DEV-/dev}" ]
then
	umask 077
	/etc/mknod -f ${DEV-/dev}/sd0a  b 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0b  b 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0c  b 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0d  b 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0x  b 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0a c 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0b c 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0c c 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0d c 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0x c 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1a  b 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1b  b 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1c  b 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1d  b 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1x  b 13 144	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1a c 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1b c 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1c c 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1d c 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1x c 13 144	|| exit 1
fi
@
0707070064030116131004440000030000030000011777770507310756100005100000001453/newbits/kernel/USRSYS/confdrv/RCS/al0,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.25;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Serial Lines COM1 and COM3'
:
UNDEF="${UNDEF} -u a0con_ lib/al.a"
PATCH="${PATCH} drvl_+50=a0con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/com1l  c 5 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com1r  c 5 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com1pl c 5 192	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com1pr c 5 64		|| exit 1

	/etc/mknod -f ${DEV-/dev}/com3l  c 5 129	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com3r  c 5 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com3pl c 5 193	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com3pr c 5 65		|| exit 1
fi
@
0707070064030076071004440000030000030000011777770507310756200005100000001453/newbits/kernel/USRSYS/confdrv/RCS/al1,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.27;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Serial Lines COM2 and COM4'
:
UNDEF="${UNDEF} -u a1con_ lib/al.a"
PATCH="${PATCH} drvl_+60=a1con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/com2l  c 6 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com2r  c 6 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com2pl c 6 192	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com2pr c 6 64		|| exit 1

	/etc/mknod -f ${DEV-/dev}/com4l  c 6 129	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com4r  c 6 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/com4pl c 6 193	|| exit 1
	/etc/mknod -f ${DEV-/dev}/com4pr c 6 65		|| exit 1
fi
@
0707070064030076121004440000030000030000011777770507310756200005000000003531/newbits/kernel/USRSYS/confdrv/RCS/at,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.28;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: AT Hard Disk
:
MAJOR=11

case "${ARG}" in
*1?)	HD_TYPE=at1 ;;
*)	HD_TYPE=at0 ;;
esac
:
:	needed by config
:
UNDEF="${UNDEF} -u atcon_ lib/at.a"
PATCH="${PATCH} drvl_+110=atcon_"

case ${ARG} in
at0a)	MAKEDEV="makedev(11,0)" ;;
at0b)	MAKEDEV="makedev(11,1)" ;;
at0c)	MAKEDEV="makedev(11,2)" ;;
at0d)	MAKEDEV="makedev(11,3)" ;;
at1a)	MAKEDEV="makedev(11,4)" ;;
at1b)	MAKEDEV="makedev(11,5)" ;;
at1c)	MAKEDEV="makedev(11,6)" ;;
at1d)	MAKEDEV="makedev(11,7)" ;;
at)
	;;
*)
	/bin/echo "invalid argument: ${ARG}"
	exit 1
	;;
esac

:
: needed for both build and config
:
if [ -d "${DEV-/dev}" ]
then
	umask 077
	/etc/mknod -f ${DEV-/dev}/at0a  b 11 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at0b  b 11 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at0c  b 11 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at0d  b 11 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at0x  b 11 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat0a c 11 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat0b c 11 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat0c c 11 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat0d c 11 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat0x c 11 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/at1a  b 11 4		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at1b  b 11 5		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at1c  b 11 6		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at1d  b 11 7		|| exit 1
	/etc/mknod -f ${DEV-/dev}/at1x  b 11 129	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat1a c 11 4		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat1b c 11 5		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat1c c 11 6		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat1d c 11 7		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rat1x c 11 129	|| exit 1
fi
@
0707070064030105601004440000030000030000011777770507310756200005100000000744/newbits/kernel/USRSYS/confdrv/RCS/ati,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.29;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Array Technologies Inc - Graphics Solution - includes Keyboard'
:
UNDEF="${UNDEF} -u iscon_ lib/ati.a"
PATCH="${PATCH} drvl_+20=iscon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c 2 0	|| exit 1
fi
@
0707070064030031671004440000030000030000011777770507310756300005000000001012/newbits/kernel/USRSYS/confdrv/RCS/dg,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.30;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Driver for Digiboard PC/Xe'
:
UNDEF="${UNDEF} -u dgcon_ lib/dg.a"
PATCH="${PATCH} drvl_+210=dgcon_"
:
: devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/dg c 21  0 || exit 1
/etc/mknod -f ${DEV-/dev}/dgx c 21  128 || exit 1
/etc/mknod -f ${DEV-/dev}/dgy c 21  64 || exit 1
@
0707070064030066701004440000030000030000011777770507310756300005000000001552/newbits/kernel/USRSYS/confdrv/RCS/fl,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.30;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: AT Floppy Driver
:
UNDEF="${UNDEF} -u flcon_ lib/fl.a"
PATCH="${PATCH} drvl_+40=flcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0133
	/etc/mknod -f ${DEV-/dev}/f9a0 b 4 12	|| exit 1
	/etc/mknod -f ${DEV-/dev}/f9a1 b 4 28	|| exit 1
	/etc/mknod -f ${DEV-/dev}/f9d0 b 4  4	|| exit 1
	/etc/mknod -f ${DEV-/dev}/f9d1 b 4 20	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fha0 b 4 14	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fha1 b 4 30	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fqa0 b 4 13	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fqa1 b 4 29	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fva0 b 4 15	|| exit 1
	/etc/mknod -f ${DEV-/dev}/fva1 b 4 31	|| exit 1
fi
@
0707070064030127101004440000030000030000011777770507310756300005000000001011/newbits/kernel/USRSYS/confdrv/RCS/gm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.31;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Tecmar Graphics Master
:
UNDEF="${UNDEF} -u iscon_ -u grcon_ lib/gm.a"
PATCH="${PATCH} drvl_+20=iscon_ drvl_+300=grcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c  2 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/gr      c 30 0 || exit 1
fi
@
0707070064030056311004440000030000030000011777770507310756300005000000001024/newbits/kernel/USRSYS/confdrv/RCS/gr,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.32;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Graphics Display on PC Color Card
:
UNDEF="${UNDEF} -u iscon_ -u grcon_ lib/gr.a"
PATCH="${PATCH} drvl_+20=iscon_ drvl_+300=grcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c  2 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/gr      c 30 0 || exit 1
fi
@
0707070064030055771004440000030000030000011777770507310756300005000000002332/newbits/kernel/USRSYS/confdrv/RCS/hs,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.33;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Hostess/Arnet multi-port Serial Support (Version 7 Compatible)'
:
UNDEF="${UNDEF} -u hscon_ lib/hs.a"
PATCH="${PATCH} drvl_+70=hscon_"
:
: non modem control devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/hs00 c 7  0 || exit 1
/etc/mknod -f ${DEV-/dev}/hs01 c 7  1 || exit 1
/etc/mknod -f ${DEV-/dev}/hs02 c 7  2 || exit 1
/etc/mknod -f ${DEV-/dev}/hs03 c 7  3 || exit 1
/etc/mknod -f ${DEV-/dev}/hs04 c 7  4 || exit 1
/etc/mknod -f ${DEV-/dev}/hs05 c 7  5 || exit 1
/etc/mknod -f ${DEV-/dev}/hs06 c 7  6 || exit 1
/etc/mknod -f ${DEV-/dev}/hs07 c 7  7 || exit 1
:
: modem control versions
:
/etc/mknod -f ${DEV-/dev}/hs00r c 7 128 || exit 1
/etc/mknod -f ${DEV-/dev}/hs01r c 7 129 || exit 1
/etc/mknod -f ${DEV-/dev}/hs02r c 7 130 || exit 1
/etc/mknod -f ${DEV-/dev}/hs03r c 7 131 || exit 1
/etc/mknod -f ${DEV-/dev}/hs04r c 7 132 || exit 1
/etc/mknod -f ${DEV-/dev}/hs05r c 7 133 || exit 1
/etc/mknod -f ${DEV-/dev}/hs06r c 7 134 || exit 1
/etc/mknod -f ${DEV-/dev}/hs07r c 7 135 || exit 1
@
0707070064030053341004440000030000030000011777770507310756400005000000001146/newbits/kernel/USRSYS/confdrv/RCS/lp,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.34;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Parallel Line Printers LPT1, LPT2 and LPT3
:
UNDEF="${UNDEF} -u lpcon_ lib/lp.a"
PATCH="${PATCH} drvl_+30=lpcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0555
	/etc/mknod -f ${DEV-/dev}/lpt1 c 3 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/lpt2 c 3 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/lpt3 c 3 2		|| exit 1
	: /bin/ln  -f ${DEV-/dev}/lpt1 ${DEV-/dev}/lp	|| exit 1
fi
@
0707070064030004051004440000030000030000011777770507310756400005000000000723/newbits/kernel/USRSYS/confdrv/RCS/mm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.34;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Memory Mapped (Text) Video - includes Keyboard'
:
UNDEF="${UNDEF} -u iscon_ lib/mm.a"
PATCH="${PATCH} drvl_+20=iscon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c 2 0	|| exit 1
fi
@
0707070064030003531004440000030000030000011777770507310756400005000000000670/newbits/kernel/USRSYS/confdrv/RCS/ms,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.35;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Microsoft Bus Mouse'
:
UNDEF="${UNDEF} -u mscon_ lib/ms.a"
PATCH="${PATCH} drvl_+100=mscon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0333
	/etc/mknod -f ${DEV-/dev}/mouse c 10 0 || exit 1
fi
@
0707070064030076151004440000030000030000011777770507310756400005100000000701/newbits/kernel/USRSYS/confdrv/RCS/msg,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.36;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: System V Compatible Messaging
:
UNDEF="${UNDEF} -u msgcon_ lib/msg.a"
PATCH="${PATCH} drvl_+250=msgcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0333
	/etc/mknod -f ${DEV-/dev}/msg c 25 0 || exit 1
fi
@
0707070064030105511004440000030000030000011777770507310756400005000000000666/newbits/kernel/USRSYS/confdrv/RCS/qq,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.37;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Dummy driver for write to absolute RAM area'
:
UNDEF="${UNDEF} -u qqcon_ lib/qq.a"
PATCH="${PATCH} drvl_+70=qqcon_"
:
: devices
:
umask 0111
/etc/mknod -f ${DEV-/dev}/qq c 7  0 || exit 1
@
0707070064030066711004440000030000030000011777770507310756500005000000001500/newbits/kernel/USRSYS/confdrv/RCS/rm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.37;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Dual RAM Disk
: Default each to 512K for now...
:
UNDEF="${UNDEF} -u rmcon_ lib/rm.a"
PATCH="${PATCH} drvl_+80=rmcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/ram0 b 8 8 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram0 c 8 8 || exit 1
	/etc/mknod -f ${DEV-/dev}/ram0close b 8 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram0close c 8 0 || exit 1

	/etc/mknod -f ${DEV-/dev}/ram1 b 8 136 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram1 c 8 136 || exit 1
	/etc/mknod -f ${DEV-/dev}/ram1close b 8 128 || exit 1
	/etc/mknod -f ${DEV-/dev}/rram1close c 8 128 || exit 1
fi
@
0707070064030056231004440000030000030000011777770507310756500005000000001101/newbits/kernel/USRSYS/confdrv/RCS/rp,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.38;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Ram Pipes
:
UNDEF="${UNDEF} -u rpcon_ lib/rp.a"
PATCH="${PATCH} NRP_=4 drvl_+220=rpcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/rp0 c 22 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/rp1 c 22 1 || exit 1
	/etc/mknod -f ${DEV-/dev}/rp2 c 22 2 || exit 1
	/etc/mknod -f ${DEV-/dev}/rp3 c 22 3 || exit 1
fi
@
0707070064030056131004440000030000030000011777770507310756500005100000001007/newbits/kernel/USRSYS/confdrv/RCS/rs0,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Raw (fast) Serial Line COM1 (System V Compatible)'
:
UNDEF="${UNDEF} -u rs0con_ lib/rs.a"
PATCH="${PATCH} drvl_+50=rs0con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/rs0  c 5 0	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rs0r c 5 128	|| exit 1
fi
@
0707070064030056051004440000030000030000011777770507310756500005100000001007/newbits/kernel/USRSYS/confdrv/RCS/rs1,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.40;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Raw (fast) Serial Line COM2 (System V Compatible)'
:
UNDEF="${UNDEF} -u rs1con_ lib/rs.a"
PATCH="${PATCH} drvl_+60=rs1con_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/rs1  c 6 0	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rs1r c 6 128	|| exit 1
fi
@
0707070064030074571004440000030000030000011777770507310756600005000000003633/newbits/kernel/USRSYS/confdrv/RCS/sd,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.41;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Hard Disk on Adaptec AHA154x series host adaptor
:
MAJOR=13

case "${ARG}" in
*1?)	HD_TYPE=sd1 ;;
*)	HD_TYPE=sd0 ;;
esac
:
:	needed by config
:
UNDEF="${UNDEF} -u sdcon_ lib/aha154x.a"
PATCH="${PATCH} drvl_+130=sdcon_"

case ${ARG} in
sd0a)	MAKEDEV="makedev(13,0)" ;;
sd0b)	MAKEDEV="makedev(13,1)" ;;
sd0c)	MAKEDEV="makedev(13,2)" ;;
sd0d)	MAKEDEV="makedev(13,3)" ;;
sd1a)	MAKEDEV="makedev(13,16)" ;;
sd1b)	MAKEDEV="makedev(13,17)" ;;
sd1c)	MAKEDEV="makedev(13,18)" ;;
sd1d)	MAKEDEV="makedev(13,19)" ;;
sd)
	;;
aha154x)
	;;
*)
	/bin/echo "invalid argument: ${ARG}"
	exit 1
	;;
esac

:
: needed for both build and config
:
if [ -d "${DEV-/dev}" ]
then
	umask 077
	/etc/mknod -f ${DEV-/dev}/sd0a  b 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0b  b 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0c  b 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0d  b 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd0x  b 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0a c 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0b c 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0c c 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0d c 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd0x c 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1a  b 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1b  b 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1c  b 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1d  b 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/sd1x  b 13 144	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1a c 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1b c 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1c c 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1d c 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rsd1x c 13 144	|| exit 1
fi
@
0707070064030111411004440000030000030000011777770507310756600005100000000702/newbits/kernel/USRSYS/confdrv/RCS/sem,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.42;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: System V Compatible Semaphores
:
UNDEF="${UNDEF} -u semcon_ lib/sem.a"
PATCH="${PATCH} drvl_+230=semcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0333
	/etc/mknod -f ${DEV-/dev}/sem c 23 0 || exit 1
fi
@
0707070064030074501004440000030000030000011777770507310756600005100000000701/newbits/kernel/USRSYS/confdrv/RCS/shm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.43;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: System V Subset Shared Memory
:
UNDEF="${UNDEF} -u shmcon_ lib/shm.a"
PATCH="${PATCH} drvl_+240=shmcon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/shm c 24 0 || exit 1
fi
@
0707070064030074461004440000030000030000011777770507310756600005000000003617/newbits/kernel/USRSYS/confdrv/RCS/ss,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.44;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Hard Disk on Seagate ST01/ST02 series SCSI controller.
:
MAJOR=13

case "${ARG}" in
*1?)	HD_TYPE=ss1 ;;
*)	HD_TYPE=ss0 ;;
esac
:
:	needed by config
:
UNDEF="${UNDEF} -u sscon_ lib/ss.a"
PATCH="${PATCH} drvl_+130=sscon_"

case ${ARG} in
ss0a)	MAKEDEV="makedev(13,0)" ;;
ss0b)	MAKEDEV="makedev(13,1)" ;;
ss0c)	MAKEDEV="makedev(13,2)" ;;
ss0d)	MAKEDEV="makedev(13,3)" ;;
ss1a)	MAKEDEV="makedev(13,16)" ;;
ss1b)	MAKEDEV="makedev(13,17)" ;;
ss1c)	MAKEDEV="makedev(13,18)" ;;
ss1d)	MAKEDEV="makedev(13,19)" ;;
ss)
	;;
*)
	/bin/echo "invalid argument: ${ARG}"
	exit 1
	;;
esac

:
: needed for both build and config
:
if [ -d "${DEV-/dev}" ]
then
	umask 077
	/etc/mknod -f ${DEV-/dev}/ss0a  b 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0b  b 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0c  b 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0d  b 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss0x  b 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0a c 13 0		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0b c 13 1		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0c c 13 2		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0d c 13 3		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss0x c 13 128	|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1a  b 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1b  b 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1c  b 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1d  b 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/ss1x  b 13 144	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1a c 13 16		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1b c 13 17		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1c c 13 18		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1d c 13 19		|| exit 1
	/etc/mknod -f ${DEV-/dev}/rss1x c 13 144	|| exit 1
fi
@
0707070064030073201004440000030000030000011777770507310756700005000000001502/newbits/kernel/USRSYS/confdrv/RCS/st,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.45;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: Archive SC-400 Streaming Tape Drive.
:
:	Minor device 0 allocates a maximum sized read/write cache [up to 256k].
:	Minor device n [1..127] allocates a n Kbyte sized read/write cache.
:	Adding 128 to one of the above minor devices inhibits rewind on close.
:
UNDEF="${UNDEF} -u stcon_ lib/st.a"
PATCH="${PATCH} drvl_+120=stcon_"

if [ -d "${DEV-/dev}" ]
then
	umask 077
	/etc/mknod -f ${DEV-/dev}/rst    c 12   0	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rst32  c 12  32	|| exit 1
	/etc/mknod -f ${DEV-/dev}/rst64  c 12  64	|| exit 1
	/etc/mknod -f ${DEV-/dev}/nrst   c 12 128	|| exit 1
fi
@
0707070064030073241004440000030000030000011777770507310756700005000000001131/newbits/kernel/USRSYS/confdrv/RCS/tn,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.11.45;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@:
: 'Tiac PC-234/6 ARCNET LAN boards [0..3]'
:
UNDEF="${UNDEF} -u tncon_ lib/tn.a"
PATCH="${PATCH} drvl_+200=tncon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/tn0 c 20 0 || exit 1
	/etc/mknod -f ${DEV-/dev}/tn1 c 20 1 || exit 1
	/etc/mknod -f ${DEV-/dev}/tn2 c 20 2 || exit 1
	/etc/mknod -f ${DEV-/dev}/tn3 c 20 3 || exit 1
fi
@
0707070064030112661004440000030000030000011777770507310757000004300000000353/newbits/kernel/USRSYS/confdrv/gkb:
: Keyboard part of console device
: Fixed, German keyboard table.
:
UNDEF="${UNDEF} -u iscon_ lib/gkb.a"
PATCH="${PATCH} drvl_+20=iscon_"
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c 2 0	|| exit 1
fi
0707070064030110701004440000030000030000011777770507310757000004200000000344/newbits/kernel/USRSYS/confdrv/kb:
: Keyboard part of console device
: Fixed keyboard table.
:
UNDEF="${UNDEF} -u iscon_ lib/kb.a"
PATCH="${PATCH} drvl_+20=iscon_"
:
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c 2 0	|| exit 1
fi
0707070064030110671004440000030000030000011777770507310757000004300000000346/newbits/kernel/USRSYS/confdrv/nkb:
: Keyboard part of console device
: Loadable keyboard table.
:
UNDEF="${UNDEF} -u iscon_ lib/nkb.a"
PATCH="${PATCH} drvl_+20=iscon_"
if [ -d "${DEV-/dev}" ]
then
	umask 0111
	/etc/mknod -f ${DEV-/dev}/console c 2 0	|| exit 1
fi
0707070064030064260407770000030000030000011777770507310757000003700000000000/newbits/kernel/USRSYS/objects0707070064030114400407550000030000030000011777770507310757000003300000000000/newbits/kernel/USRSYS/doc0707070064030114101004440000030000030000011777770507310757000004300000000110/newbits/kernel/USRSYS/doc/aha154xaha154x		- Adaptec AHA-154x SCSI H/A (specify: root=sd0a ... root=sd1d)
0707070064030114071004440000030000030000011777770507310757000003600000000055/newbits/kernel/USRSYS/doc/alal0, al1	- Serial lines COM1/COM3, COM2/COM4
0707070064030114061004440000030000030000011777770507310757000003600000000066/newbits/kernel/USRSYS/doc/atat		- AT hard disk (specify: root=at0a ... root=at1d)
0707070064030114051004440000030000030000011777770507310757000003700000000102/newbits/kernel/USRSYS/doc/atiati		- Array Technologies Inc 'Graphics Solution' Display Adapter
0707070064030114041004440000030000030000011777770507310757000003600000000043/newbits/kernel/USRSYS/doc/flfl		- AT floppy driver (root=fha0)
0707070064030114031004440000030000030000011777770507310757000003600000000070/newbits/kernel/USRSYS/doc/gmgm		- Tecmar Graphics Master (640x400) graphics display
0707070064030114021004440000030000030000011777770507310757100003600000000060/newbits/kernel/USRSYS/doc/grgr		- IBM Color card (640x200) graphics display
0707070064030114011004440000030000030000011777770507310757100003600000000054/newbits/kernel/USRSYS/doc/hshs		- Generic polled multi-line serial card
0707070064030114001004440000030000030000011777770507310757100003600000000057/newbits/kernel/USRSYS/doc/lplp		- Parallel line printer (LPT1, LPT2, LPT3)
0707070064030113771004440000030000030000011777770507310757100003600000000041/newbits/kernel/USRSYS/doc/mmmm		- Memory Mapped (Text) Video
0707070064030113761004440000030000030000011777770507310757100003600000000032/newbits/kernel/USRSYS/doc/msms		- Microsoft bus mouse
0707070064030113751004440000030000030000011777770507310757100003700000000045/newbits/kernel/USRSYS/doc/msgmsg		- System V compatible messaging
0707070064030113741004440000030000030000011777770507310757100003600000000024/newbits/kernel/USRSYS/doc/rmrm		- Dual RAM disk
0707070064030113731004440000030000030000011777770507310757100003600000000020/newbits/kernel/USRSYS/doc/rprp		- Ram pipes
0707070064030113721004440000030000030000011777770507310757100003600000000054/newbits/kernel/USRSYS/doc/rsrs0, rs1	- Fast raw serial lines COM1, COM2
0707070064030113711004440000030000030000011777770507310757100003700000000046/newbits/kernel/USRSYS/doc/semsem		- System V compatible semaphores
0707070064030113701004440000030000030000011777770507310757100003700000000045/newbits/kernel/USRSYS/doc/shmshm		- System V subset shared memory
0707070064030113671004440000030000030000011777770507310757200003600000000052/newbits/kernel/USRSYS/doc/stst		- Archive SC-400 streaming tape drive
0707070064030113661004440000030000030000011777770507310757200004000000000046/newbits/kernel/USRSYS/doc/swapswap		- Swap tasks in and out of core
0707070064030113651004440000030000030000011777770507310757200003600000000050/newbits/kernel/USRSYS/doc/tntn		- Tiac PC-234/6/8 ARCNET LAN Driver
0707070064030114130407550000030000030000011777770507310757200003700000000000/newbits/kernel/USRSYS/doc/RCS0707070064030114111004440000030000030000011777770507310757200005100000000476/newbits/kernel/USRSYS/doc/RCS/aha154x,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.35;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@aha154x		- Adaptec AHA-154x SCSI H/A (specify: root=sd0a ... root=sd1d)
@
0707070064030114371004440000030000030000011777770507310757200004400000000443/newbits/kernel/USRSYS/doc/RCS/al,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.36;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@al0, al1	- Serial lines COM1/COM3, COM2/COM4
@
0707070064030114361004440000030000030000011777770507310757200004400000000454/newbits/kernel/USRSYS/doc/RCS/at,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.37;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@at		- AT hard disk (specify: root=at0a ... root=at1d)
@
0707070064030114351004440000030000030000011777770507310757200004500000000470/newbits/kernel/USRSYS/doc/RCS/ati,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.37;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@ati		- Array Technologies Inc 'Graphics Solution' Display Adapter
@
0707070064030114341004440000030000030000011777770507310757200004400000000431/newbits/kernel/USRSYS/doc/RCS/fl,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.38;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@fl		- AT floppy driver (root=fha0)
@
0707070064030114331004440000030000030000011777770507310757200004400000000456/newbits/kernel/USRSYS/doc/RCS/gm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@gm		- Tecmar Graphics Master (640x400) graphics display
@
0707070064030114321004440000030000030000011777770507310757300004400000000446/newbits/kernel/USRSYS/doc/RCS/gr,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@gr		- IBM Color card (640x200) graphics display
@
0707070064030114311004440000030000030000011777770507310757300004400000000442/newbits/kernel/USRSYS/doc/RCS/hs,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.40;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@hs		- Generic polled multi-line serial card
@
0707070064030114301004440000030000030000011777770507310757300004400000000445/newbits/kernel/USRSYS/doc/RCS/lp,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.40;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@lp		- Parallel line printer (LPT1, LPT2, LPT3)
@
0707070064030114271004440000030000030000011777770507310757300004400000000427/newbits/kernel/USRSYS/doc/RCS/mm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.41;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@mm		- Memory Mapped (Text) Video
@
0707070064030114261004440000030000030000011777770507310757300004400000000420/newbits/kernel/USRSYS/doc/RCS/ms,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.42;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@ms		- Microsoft bus mouse
@
0707070064030114251004440000030000030000011777770507310757300004500000000433/newbits/kernel/USRSYS/doc/RCS/msg,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.42;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@msg		- System V compatible messaging
@
0707070064030114241004440000030000030000011777770507310757300004400000000412/newbits/kernel/USRSYS/doc/RCS/rm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.43;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@rm		- Dual RAM disk
@
0707070064030114231004440000030000030000011777770507310757300004400000000406/newbits/kernel/USRSYS/doc/RCS/rp,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.44;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@rp		- Ram pipes
@
0707070064030114221004440000030000030000011777770507310757300004400000000442/newbits/kernel/USRSYS/doc/RCS/rs,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.44;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@rs0, rs1	- Fast raw serial lines COM1, COM2
@
0707070064030114211004440000030000030000011777770507310757300004500000000434/newbits/kernel/USRSYS/doc/RCS/sem,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.45;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@sem		- System V compatible semaphores
@
0707070064030114201004440000030000030000011777770507310757400004500000000433/newbits/kernel/USRSYS/doc/RCS/shm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.45;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@shm		- System V subset shared memory
@
0707070064030114171004440000030000030000011777770507310757400004400000000440/newbits/kernel/USRSYS/doc/RCS/st,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.46;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@st		- Archive SC-400 streaming tape drive
@
0707070064030114161004440000030000030000011777770507310757400004600000000434/newbits/kernel/USRSYS/doc/RCS/swap,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.47;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@swap		- Swap tasks in and out of core
@
0707070064030114151004440000030000030000011777770507310757400004400000000436/newbits/kernel/USRSYS/doc/RCS/tn,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.18.47;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@tn		- Tiac PC-234/6/8 ARCNET LAN Driver
@
0707070064030110661004440000030000030000011777770507310757400003600000000103/newbits/kernel/USRSYS/doc/ssss		- Seagate/Future Domain SCSI (specfy: root=sd0a ... root=sd1d)
0707070064030111320407550000030000030000011777770507310757400003400000000000/newbits/kernel/USRSYS/ldrv0707070064030111311006000000030000030000011777770507310757400004400000023676/newbits/kernel/USRSYS/ldrv/aha154x�J��	.���v�v�v�Ѓ��VW��6�t;6|Vh����j���k�
��u���ヿtVh��h��j�������������k�
LJ����LJ�������>t
����P���jjhh�������G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�*������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v��.���͋^����G�j�p���_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h�����_^�VWU���Vh(�6��6�j�v	���}��_^�VWU��>V~
�6Vh�����6��	��+��� }���烽�t����������F���_^�VW��F%���%�F�~���jP�6��������~��狅��F�j%�6�����F��~�t�~��烽�uh����#+��jP�~�������O���F�F��F��F��F��6�v�����F��V����F�%�F�+�;v�}��~��F���F�P�t	���F�P�j	���^��G*�Ȋ*�������+҉F�V���������F�V�^��G*�ȊG*�������+�	F�	V�~��E*�ȊE*�����F�S�Z���F�V�~�EL�UN���~�������~����F��%����
�P�

���_^�VW��v�ƀt#��t�h0V��
������V���%���%�F���%���^��ヿ�uV�)����u��n�^��㋇��F��^��GL�WN�F�V�����^��G�W�F��V�����^��G�W
F�V�;V�wr;F�v�%�����^��GGt�Y���_^�VWU�����V�_^�VWU��h@�j�v�v
h6�3
��
�_^�VWU��h@�j�v�v
h6�
��
�_^�VW��v�F���%���%�F��F
�(�CC.;��t�.�gHH2���B��~��烽�u �F�V������~��烽�u����~��狅��F���.����ǙRP�~��uN�uL����F�F����F���F�j�v�F�P�o���~�t�~�������"���~���Dž�+��l�~��狅��F�j�F�P�v����F�*���F�*�����RP���RP���RP�F�RP�
���~�EL�UN��v�v
�
��������_^�VW��v�D%�F��D%���%�F��D�t�F��D�D�^��㋇��F��^��ヿ�t��~�t��D
Dt���|t��j
�6�
�����uhY������u�F��E
�E�~�t�^���^��D
�TGW
��D
�T�E�U�E�{�F��>(u�>(��*�?�>*�v��_�����>h<덋^���^��D��	�ȋ�+�D
T;Ww
s�O�;Gw�G��LV�
���_^�VWU�������o����_^�VWU�츓�_^�VWU��h�����_^�VWU��6\�F�\���_^�VWU��\�_^�VW��~�u;�^�;u
��v��o�|�^�u�tD�L�^�u/�u)�s�F��h�?t�_�7�h�w�v��Y�����#�M��EW�)	��V�	���v�	���_^�VWU���6\�	��%���t��u�\@@P�g	������tӸ����v�\@P�
��+��_^�VWU���6\�7	��%���u��u�\@@P�	������tӸ����\@P�	��%��_^�VW������F��V��n��^��F��V��x"u�t�6\����������t��v�'��h��q	���_^�VWU�졄��O~�\@@P����ȋ���t��u	h��=	���6\�o����j �6\�	�����_^�VWU���N
|
�~�F��������_^�VW��6\�-��=�u�����|�~�F��V��n��^��F��V��xu�t�6\�������ǀu֋F�F�u����G�6\��������@t����0�6\������� t���6\�������t+������_^�VWU��N|)��~�F�V
%�+҈��F�V
�������F�V
���_^�VW��~�*䙉F��V���������F��V��v�D*�ȊD*�������+�	F�	V��X�Z)F�V��F��_^�VWU��j
�����jhn����+���}��nt��n�PVh
���F��h����_^�VWU��>^t �>lt�6l����l�v�����_^�VW��v�;����>lu0�x����P�6�����l�u	��������x��l�j+�;6x}����l����>j+��*�F���6j�'���X�Z�F�P�6�6l���RP�f����x�F�hM�v
���h�h����jh����h��6\�z�����}h�t���6\hK�g���E�j����+���}����E�*�P�����F��F�h�^�x�_^�VW��v�D�F���T�F��V�j>�6�����F��~�u	�������v�^��G;��D�%���G�D�%G�D
��^��G*�=*u�O��^��O�^��G�F��G�V���������^��G�F��V���������^��G�F��G�G�F��.�>��G�F��G�G�G
�G�F�P�D
�RP������F�P�t�t������l@P�6�v��q��RP������l�j�����^��?ujh�h�S������^��uO�tI�D�%P�D���PhZ����+��^��G�;�~�߃�
^��G*�Ph���G��h�����^��G��ȊG����S������_^�VWU��vj>�6�!�����u;��D
�%���E�D
�%E�\�u
�M�E(��M�E*�E�D�T��������E�D�T��������E�D�E�E�\�G+ҹ�������E�\�G��	�E�E�E
�E�EP�G+�RP�n����EP�\�w�w����RP�S������_^�VW��F��d���>nt
W�[����nW�M���h��F��u��;6x|�����l�?uq�F��v�������F�����l@P�6�v��p��RP���������l�j�������F��^���h��F��~�u�G�v�����~�tF�t�;6xt�X��n�F��_^�VWU��+�+�;6x}9����j�?t(����j@P�x���Ph��������j�GF�����_^�VWU��\@@P��������ǀu
Vh��O����%H=w+����.�����������jh �$����Y��	h����j �6\�����_^�VWU��h������_^�VW��v
�F���F�jj�v�����>uejjj�v����F��tF�^�����U�u/�F��~�}j�F�����P�ƃ�P�D���F����F��v��W���v�X���v��-���F��_^���`���`�VWU��N�	�v
�~��F��]_^ø�`���`���`�U���v�v�P�;��]���`���`���`�����܋W+�����`�[XS�`[SSø�`���`��c��c���+�������VWU��S�؋�S+��y
�^�W���V�F�y���؃���rFRP�V
�F�y���؃�FRP�V���
��s���؃�[��]_^�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh������>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh�M���
�+������(��D�F�D�vh�v
Vh�'���
W�����_^���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@��[��]_^��Ë܋_��Ë܍_VWU��P�F�'����F�g��F
�'��֋�[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
@ 0
��L������	aha154x: sdunload() athough %d active
aha154x: out of kernel memory
No tape yetaha154x: no partition table
aha154x: out of kernel memory
�no messageerror messages not verboseaha154x: out of kernel memory
aha154x: timeout sending cmd byte
aha154x: aha_poll timed out
[%d] %x 
aha154x: initialization error or host adaptor not found at 0x%x
aha: SCSI ID %d LUN %d. SCSI sense = %x
aha: spurious interrupt %x
aha: multiple interrupts not yet handled
aha_ioctl: Not implemented
Kdopen_ahigh	
ahigh	
ahigh	
free_�bhigh	bhigh	bhigh	Ksleep_sdgetpartitions_Saha_ioctl_�drive_info_ main_Kukcopy_Kkucopy_aha_command_�clrivec_Daha_load_oKioreq_Kfree_SD_SPT_�sdclose_�sdwatch_�uexit_�Kdefend_SDBASE_�kclear_Kclrivec_setivec_�sphi_�ldrvipc_u_aha_start_ ldrvics_buildccb_Bdrvl_ldrvcon_llmodCinb_�Kuexit_dclose_�outb_�nulldev_�drvn_timq_ldrvsel_l0KKkclear_blkmv�Ksetivec_l1fxcalledbread_�lrmod:l2ll3|con_Kldtimcall_l4�llsgnHl5�ldrvint_brelease_�aha_get_base_�SDIRQ_�aha_device_info_�
Kdclose_vldivaha_intr_Mdefer_�devmsg_�aha_completed_�llmul4lrsgn?cprocp_kcall_timeout_�aha_process_�bdone_~Kbread_vtop_
sds_alloc_tucs_aha_unload_?vrdivlrmul.wakeup_�Kbrelease_aha_set_base_�spl_�vlmulZKdevmsg_MAX_MAILBOX_xfdisk_�Ktimeout_Kbdone_printf_�alow	alow	Kvtop_alow	allkp_ldrvpsy_blow	blow	blow	SD_HDS_�Kalloc_dopen_�getcs_�vrmulcsdcon_�Kwakeup_bptr	sleep_�kucopy_$ukcopy_fptr	��Kprintf_Kldeferioreq_0'8'$+$*0-05'?#'J$$Q0T0\'b8$e'h8$k'o8 q'u8 w'~#'�g'�$'�8'�S'�-'�8'�8$�0�'�J$�'�8'�8'�#'�$'�-'!'S0'#!'-'407'J,0_0p0�$�$�'�$�$�$�$�$�0� � � � � � � � � � �%�%�$�$�0�'%%$0$$0'%9%D0G'qf0t%{%�'�f0�%�$�0�'�0�%�0�'�Q0�'�#00$0�'�#%�0�'�$�0�0�'�#%0%!0('3%?'�0�'�'�#%�%�0�%�0� 0$ 6 8 : < > @%I0U%a'h0l%u${$0�$�$�0�%�0�%�%�0�$�$$$00"09'B%�%�0�0�0�0�'�f0�$�0�0�0%%#%)%/050;$@0g0o0x0�0�$z$�$�0�%�%�%�0�0%$%20;0A0S0Z0c%s0v%�0�%�0�%�0�%�0�%�0�$	$	%-	00	0C	$H	0K	$Z	%b	0h	$|	0	%�	0�	%�	0�	0�	0�	%�	0�	0�	$�	$�	%
0
%!
0$
%8
0;
%O
0R
%�
%�
0%	0%%!$'0*$306%F%M%T0W%^0f0y%�$�'�f0�%�0�0�$�%�%�$�%�%�'�Q0�%�%�'�Q%�0�0$ 00 0+%5080>$E0H%O$R0U0[0`0w%�%�$�'�f0�0�0� M
0r
0�
%�
'�
Q0�
0�
%�
0�
0�
$�
0�
$0$007'Nf0Q0�0
00,%2090?%C0G%N0Z$a0f%o0}%�'�Q0�0�%�0�0�%�0�0�$�0�%�$
%%#0( /02%>%S0Y$j0m � � � � � � � � � �0�0�$�0�%�0�$�0�0�0�'�00B0U0^0g'ul'x3'`'�3'�O'�3'�X'�3'�B'�3'�x0�'�\'�3'�'�3'�'�3''3'3'/'3'%'(3 /02 508'�w'�3'�'�!'�'�''S'!'='10'%'1'<!'V!'ZS'`'g0j'u'!'�'�3'�_0�0�0�'�9'�_0�0�'�''�3'
'3'd'3'�q'�30707070064030114641006660000030000030000011777770507310757700004000000022571/newbits/kernel/USRSYS/ldrv/al0���;���v�v�v�Ѓ��VW��6�t;6|Vh��=��j����k�
��u���ヿtVh����j��������������k�
LJ����LJ�������>t
����P���jjhh��~����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W��������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v������͋^����G�j����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h�����_^�VW��>$t�i�^P�6����� �u�k�P�6������u�xi�^P�6 �	��k�P�6���������$���> �E��E��E� ��>���E�>�~0���> ��y���x���r� ^��>�E��E�F��F�;�|��iF�^��> �E��F�iF�^��> �}��F�j@P�{���F�@P�(���uXj�F�P�]��h��F�P�M���~�������v��;���~��狅���P�F�@P�#��j�F�P���iF�^��> �E�
iF�^��> �EEiF�^��> �s��\�F��&�h�j����V����_^�VW��F��F�;�}[iF�^��> �}��F�j@P���j�F�P���jjj��jiF�^ HP��P�����R���F��j�����6 ��
���6��
���_^�VWU��F%?;�s:���~��?i�^ P����h"�~��?i�^ P�v
�v�~�����_^�VWU��N��?i�^��> �Mu(����~��?i�^ P�v
�v���V����_^�VWU���v
�~��?i�^ P����_^�VWU��v
�<tV�N��?i�^ P����|V�
�����|o�^��?i�^�� �_�P�������� t؋^��?i�^�� �_�P������� t�W�N��?i�^�� �_�7������_^�VWU��~��?i�^ P�v�v
�v�)���_^�VWU���v�v
�~��?i�^ P����_^�VWU���6"����_^�VW��v�~�F%��F��\��F�@P���������t��&�D�t
�
�u��F���ȁ��k�
��t�'���F@t���u��F@u��\�G����㋇=t˃|t��\�tjjh�DP�������F��F@tj��\�G����㋇�j�F�P���j�F�@P�|���F��t��L $�F�P����F��F�*�\G�F��u`jjh�DP�����G$G&t���t��F�P��
��%P�F�P�
��j�F�@P��
����v��������d���F�t�d����d���LV�=����	�,����!�,V����v�����D�vV�8���F@t�\�G�����LJ�_�g�\�G�����LJ�T�\�G����㋇=u�>��\�G��؁��㋇=t�X�� ��F��u	�Du��
�Du�t���_^�VW��^�w�_�G�v�D���^�G�F��^��?�F��~�tU�^�GPhvj
�GP�
��jjh�^�GP�
���^��[*�F���Z*�:F�u��~�t��N���� uj��@P�x	����^�G$��@tQ��P�	��%P��P�L	���F��%��F�k^�
LJjjhkF�
P��	��k^�
LJ��P����%��P��P�����^�_�G�����LJ���^�_�G�^�GP��
���_^�VWU��v�����k�
������=~�~�����k�
P�
���_^�VW��v�Y	���\��F�@P�$���F��F�P����F��F�P����F��F
�3
�	CC.;��t��.�g��������x
�
�
�
Y
p
�
�
�
�F�
@P�F�P������F�%����F�
P�F��ߋF�%����F�
��F�%���ߋF�
�P�F�P����v�v�����F��P�F�@P����v�늋N���F�%����w��F�P�(���F��F�*�\G�F�*����F�j�v�F�P�*�
�v�v
V����F�*�P�F�@P�+��W����_^�VW��^�G�F��^��7�^��)��F���(�:F�t����^��(����㋇����u+�^�Gt!�g����P�v��%P��P����t}��F���@P�R���F�h���P���WV�������P��@P�p���^��,%�=t	=tj�j�j
��P�F���F�*�P��@P�6���v������_^�VW��v�Du����F��\�P����F��F�*�\G�v������\�Gt>�g��|u	�DP���(�F��u%��F���X*䈄YƄY�v����V�����\�Gt�g��F�t�d����L ��Y*�=�w"�\�P���
P�\�P�T���Dt�Du=��Yt6��Y*�ȋ�ي�Z*�PV�����Y*�=�s��Y�ƄY��Y���F����Z*�Ȋ�[*�+�F��F��.�>��V��N�|7V�W�����|*��Z*�ȋ�ًLj�\��Z*�=�rƄZ����Z��V�R��Vh?j
��HP����_^�VW��v�\�F��\�P�'������t
VhY������ t>��Z*�:�[t2��[*�ȋ�ي�\*�P�\�7�-����[��[*�=rƄ[�v������_^�VWU��j�v����_^�VW��v�\��F��F�@@P���=v�`����.�����}�����F�P�g������t�VhY�1����v��J�����|t���,@u-�ρ���1�;�u�L 녋ρ���0�;�u�d���n���Y*�=�s,��X*�ȋ�ًLj�Z��X*�=�s��X�ƄX��Y�Du�-���Y*�=�w���F�P���%��P�F�P���H���Z*�:�[u����D t�����[*�ȋ�ي�\*�P�v������[��[*�=rƄ[��[*�:�Zt��Vh?����F�P�4���\G���_^�VW��F��~�}"�~��狅=u�~������L����F����(�(;&|�(�(�_^�VW����t��F��F��~�}:�~��狅=u'�~��狽��(����狅��F��F�;F�}�F��F��F����F�;t.��.�>��&���&���~�t�h��6����_^�d��`�VWU��N�	�v
�~��F��]_^�VW��~dra�F+�.�6��uS�F+�RPjh�4����F��
�F�j6jC�"���F�%�Pj@����F���Pj@����v������F���F����F��_^�VW��v�{����F��u��F��F
��P��v�����F��_^�VW���F��~�t!jd�8����n�F���P�_���F��_^�d���U���v�v�P�'��]���`�����܋W+�����`�[XS�`[SSø�`���`���`�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�`����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X���`�VWU��v�~t�~
jjjVh����
�+�������D�F�D�vh�v
Vh����
W�����_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy

.�X���X�	���	Y@��`@:0 dddddddd�,��X �@Kttstart_ahigh	
free_bhigh	Ksleep_Kttopen_main_Kkucopy_al_sg_clr_�ttsignal_alxtimer_�	clrivec_�albaud_�Kttpoll_Kfree_super_Nuexit_&Kttsignal_al_sg_set_�altclk_in_}Kdefend_nondsig_Naltclk_out_�kclear_:Kclrivec_com_usage_alxstart_�
setivec_vsphi_@ldrvipc_tthup_�u_alxopen_�ldrvics_drvl_ldrvcon_inb_cs_sel_�Kuexit_Ksuper_nulldev_Xoutb_bdrvn_altclk_iogetc_$timq_ldrvsel_Knondsig_Kkclear_ttsetgrp_�blkmv�Ksetivec_xcalledttclose_�ttin_�Ktthup_ttout_�con_Kldtimcall_poll_owner_poll_rate_alxintr_mldrvint_ttioctl_�ttread_�altsel_vldiv0Kiogetc_defer_�cprocp_kcall_.timeout_XKttsetgrp_alp_rate_�Kttclose_Kttin_alxbreak_YKttout_alloc_�tp_table_ucs_vrdiv9wakeup_vKttioctl_Kttread_spl_DC1BAUD_�a0con_�Ktimeout_C3BAUD_�ttwrite_printf_lalow	allkp_ldrvpsy_blow	alxcycle_?Kalloc_ttstart_A0CNT_�alxparam_Egetcs_Kwakeup_sleep_6ttopen_�kucopy_Dalxclose_QKttwrite_Kprintf_Kldeferttpoll_�alxioctl_�	0'9'$*$*0-05'?"'J#$Q0T0\'b9$e'h9$k'o9 q'u9 w'~"'�^'�#'�9'�P'�.'�9'�9$�0�'�E$�'�9'�9'�"'�#'�.'!'P0'#!'-'407'J-0_0p0�$�$�'�$�$�$�$�$�0� � � � � � � � � � � �%�0�$�'�]0�%0$']0%0!$%%,0/$6%<0?0E%K$N%R%\%b'eO%i$u${%%�%�'�O%�$�0�%�%�0�0�00$0%$10=0L%Z _%j o%z0}0� �0�0�$�%�0�0�%�0�00%0%"0%$;0@%O0S%Y%h0r'{%�0�%�0�0�%�0�%0
0%-09%U0a%~0�%�0�%�0�%�0�0'!0%0/06'I"'P0T'_;0m'|0�0�0�'�O0�0�0�00%',E070E0V0c'j0q0w0�$�$�0�0�0�'�0�'�'0'!0)0,0F'J0h �0�0�0�0	0	'+	"';	"0?	'J	"0U	0e	'z	0	0�	'�	"'�	"'�	"0�	0�	0�	0
0
  
0/
 G
 I
 K
 M
 O
 Q
 S
 U
 W
0h
0n
0�
0�
0�
0�
0�
00$050<'p0t$�0�0�0�0�0�0�0�00*03090P0S0b0y0�0�0�0�0�0
0;
 {
0�
0�
 �
0�
0�
0�
 0030P0d0�0� � � � � � � � �0� �0�0�00O0]0g0x0{0�0�0�0� �0�0�0�''O0%+%.%2%8%='K;0R'k'yO$�'�<'�< �%�0�'�;'�; �'�<0�'�a'�4 0+040>0M0\0e0�0�'�+0�'�A0�'�+0�0�'�+'�A0�'m0'
'4'%C'(4'24';0'>4'E'H4'O/'R4'ml'p4'}'�!'�'�'�'�P'�!'�>'�30�'�'�'�!'!'P''0'#'-!'7':4'O''R4'tX0w00�'�:'�X0�0�'�J'�4'�7'�4'�K'�4'�S'�4'�'�4'�M'�4'�
'�4'�T'�4'�H'4'	'4''4'k' 4''&'*4'wf'z40707070064030114631006660000030000030000011777770507310760100004000000022571/newbits/kernel/USRSYS/ldrv/al1���;���v�v�v�Ѓ��VW��6�t;6|Vh��=��j����k�
��u���ヿtVh����j��������������k�
LJ����LJ�������>t
����P���jjhh��~����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W��������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v������͋^����G�j����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h�����_^�VW��>$t�i�^P�6����� �u�k�P�6������u�xi�^P�6 �	��k�P�6���������$���> �E��E��E� ��>���E�>�~0���> ��y���x���r� ^��>�E��E�F��F�;�|��iF�^��> �E��F�iF�^��> �}��F�j@P�{���F�@P�(���uXj�F�P�]��h��F�P�M���~�������v��;���~��狅���P�F�@P�#��j�F�P���iF�^��> �E�
iF�^��> �EEiF�^��> �s��\�F��&�h�j����V����_^�VW��F��F�;�}[iF�^��> �}��F�j@P���j�F�P���jjj��jiF�^ HP��P�����R���F��j�����6 ��
���6��
���_^�VWU��F%?;�s:���~��?i�^ P����h"�~��?i�^ P�v
�v�~�����_^�VWU��N��?i�^��> �Mu(����~��?i�^ P�v
�v���V����_^�VWU���v
�~��?i�^ P����_^�VWU��v
�<tV�N��?i�^ P����|V�
�����|o�^��?i�^�� �_�P�������� t؋^��?i�^�� �_�P������� t�W�N��?i�^�� �_�7������_^�VWU��~��?i�^ P�v�v
�v�)���_^�VWU���v�v
�~��?i�^ P����_^�VWU���6"����_^�VW��v�~�F%��F��\��F�@P���������t��&�D�t
�
�u��F���ȁ��k�
��t�'���F@t���u��F@u��\�G����㋇=t˃|t��\�tjjh�DP�������F��F@tj��\�G����㋇�j�F�P���j�F�@P�|���F��t��L $�F�P����F��F�*�\G�F��u`jjh�DP�����G$G&t���t��F�P��
��%P�F�P�
��j�F�@P��
����v��������d���F�t�d����d���LV�=����	�,����!�,V����v�����D�vV�8���F@t�\�G�����LJ�_�g�\�G�����LJ�T�\�G����㋇=u�>��\�G��؁��㋇=t�X�� ��F��u	�Du��
�Du�t���_^�VW��^�w�_�G�v�D���^�G�F��^��?�F��~�tU�^�GPhvj
�GP�
��jjh�^�GP�
���^��[*�F���Z*�:F�u��~�t��N���� uj��@P�x	����^�G$��@tQ��P�	��%P��P�L	���F��%��F�k^�
LJjjhkF�
P��	��k^�
LJ��P����%��P��P�����^�_�G�����LJ���^�_�G�^�GP��
���_^�VWU��v�����k�
������=~�~�����k�
P�
���_^�VW��v�Y	���\��F�@P�$���F��F�P����F��F�P����F��F
�3
�	CC.;��t��.�g��������x
�
�
�
Y
p
�
�
�
�F�
@P�F�P������F�%����F�
P�F��ߋF�%����F�
��F�%���ߋF�
�P�F�P����v�v�����F��P�F�@P����v�늋N���F�%����w��F�P�(���F��F�*�\G�F�*����F�j�v�F�P�*�
�v�v
V����F�*�P�F�@P�+��W����_^�VW��^�G�F��^��7�^��)��F���(�:F�t����^��(����㋇����u+�^�Gt!�g����P�v��%P��P����t}��F���@P�R���F�h���P���WV�������P��@P�p���^��,%�=t	=tj�j�j
��P�F���F�*�P��@P�6���v������_^�VW��v�Du����F��\�P����F��F�*�\G�v������\�Gt>�g��|u	�DP���(�F��u%��F���X*䈄YƄY�v����V�����\�Gt�g��F�t�d����L ��Y*�=�w"�\�P���
P�\�P�T���Dt�Du=��Yt6��Y*�ȋ�ي�Z*�PV�����Y*�=�s��Y�ƄY��Y���F����Z*�Ȋ�[*�+�F��F��.�>��V��N�|7V�W�����|*��Z*�ȋ�ًLj�\��Z*�=�rƄZ����Z��V�R��Vh?j
��HP����_^�VW��v�\�F��\�P�'������t
VhY������ t>��Z*�:�[t2��[*�ȋ�ي�\*�P�\�7�-����[��[*�=rƄ[�v������_^�VWU��j�v����_^�VW��v�\��F��F�@@P���=v�`����.�����}�����F�P�g������t�VhY�1����v��J�����|t���,@u-�ρ���1�;�u�L 녋ρ���0�;�u�d���n���Y*�=�s,��X*�ȋ�ًLj�Z��X*�=�s��X�ƄX��Y�Du�-���Y*�=�w���F�P���%��P�F�P���H���Z*�:�[u����D t�����[*�ȋ�ي�\*�P�v������[��[*�=rƄ[��[*�:�Zt��Vh?����F�P�4���\G���_^�VW��F��~�}"�~��狅=u�~������L����F����(�(;&|�(�(�_^�VW����t��F��F��~�}:�~��狅=u'�~��狽��(����狅��F��F�;F�}�F��F��F����F�;t.��.�>��&���&���~�t�h��6����_^�d��`�VWU��N�	�v
�~��F��]_^�VW��~dra�F+�.�6��uS�F+�RPjh�4����F��
�F�j6jC�"���F�%�Pj@����F���Pj@����v������F���F����F��_^�VW��v�{����F��u��F��F
��P��v�����F��_^�VW���F��~�t!jd�8����n�F���P�_���F��_^�d���U���v�v�P�'��]���`�����܋W+�����`�[XS�`[SSø�`���`���`�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�`����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X���`�VWU��v�~t�~
jjjVh����
�+�������D�F�D�vh�v
Vh����
W�����_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy

.�X���X�	���	Y@��`@:0 dddddddd�,��X �@Kttstart_ahigh	
free_bhigh	Ksleep_Kttopen_main_Kkucopy_al_sg_clr_�ttsignal_alxtimer_�	clrivec_�albaud_�Kttpoll_Kfree_super_Nuexit_&Kttsignal_al_sg_set_�altclk_in_}Kdefend_nondsig_Naltclk_out_�kclear_:Kclrivec_com_usage_alxstart_�
setivec_vsphi_@ldrvipc_tthup_�u_alxopen_�ldrvics_drvl_ldrvcon_inb_cs_sel_�Kuexit_Ksuper_nulldev_Xoutb_bdrvn_altclk_iogetc_$timq_ldrvsel_Knondsig_Kkclear_ttsetgrp_�blkmv�Ksetivec_xcalledttclose_�ttin_�Ktthup_ttout_�con_Kldtimcall_poll_owner_poll_rate_alxintr_mldrvint_ttioctl_�ttread_�altsel_vldiv0Kiogetc_defer_�cprocp_kcall_.timeout_XKttsetgrp_alp_rate_�Kttclose_Kttin_alxbreak_YKttout_alloc_�tp_table_ucs_vrdiv9wakeup_vKttioctl_Kttread_spl_DC2BAUD_�Ktimeout_a1con_�C4BAUD_�ttwrite_printf_lalow	allkp_ldrvpsy_blow	alxcycle_?Kalloc_ttstart_alxparam_Egetcs_A1CNT_�Kwakeup_sleep_6ttopen_�kucopy_Dalxclose_QKttwrite_Kprintf_Kldeferttpoll_�alxioctl_�	0'9'$*$*0-05'?"'J#$Q0T0\'b9$e'h9$k'o9 q'u9 w'~"'�^'�#'�9'�P'�.'�9'�9$�0�'�E$�'�9'�9'�"'�#'�.'!'P0'#!'-'407'J-0_0p0�$�$�'�$�$�$�$�$�0� � � � � � � � � � � �%�0�$�'�]0�%0$']0%0!$%%,0/$6%<0?0E%K$N%R%\%b'eO%i$u${%%�%�'�O%�$�0�%�%�0�0�00$0%$10=0L%Z _%j o%z0}0� �0�0�$�%�0�0�%�0�00%0%"0%$;0@%O0S%Y%h0r'{%�0�%�0�0�%�0�%0
0%-09%U0a%~0�%�0�%�0�%�0�0'!0%0/06'I"'P0T'_;0m'|0�0�0�'�O0�0�0�00%',E070E0V0c'j0q0w0�$�$�0�0�0�'�0�'�'0'!0)0,0F'J0h �0�0�0�0	0	'+	"';	"0?	'J	"0U	0e	'z	0	0�	'�	"'�	"'�	"0�	0�	0�	0
0
  
0/
 G
 I
 K
 M
 O
 Q
 S
 U
 W
0h
0n
0�
0�
0�
0�
0�
00$050<'p0t$�0�0�0�0�0�0�0�00*03090P0S0b0y0�0�0�0�0�0
0;
 {
0�
0�
 �
0�
0�
0�
 0030P0d0�0� � � � � � � � �0� �0�0�00O0]0g0x0{0�0�0�0� �0�0�0�''O0%+%.%2%8%='K;0R'k'yO$�'�<'�< �%�0�'�;'�; �'�<0�'�a'�4 0+040>0M0\0e0�0�'�+0�'�A0�'�+0�0�'�+'�A0�'m0'
'4'%C'(4'24';0'>4'E'H4'O/'R4'ml'p4'}'�!'�'�'�'�P'�!'�>'�30�'�'�'�!'!'P''0'#'-!'7':4'O''R4'tW0w00�'�:'�W0�0�'�J'�4'�7'�4'�K'�4'�S'�4'�'�4'�M'�4'�
'�4'�T'�4'�H'4'	'4''4'k' 4''&'*4'wf'z40707070064030111261006000000030000030000011777770507310760300003700000021741/newbits/kernel/USRSYS/ldrv/at��l����v�v�v�Ѓ��VW��6�t;6|Vh��K��j�{��k�
��u���ヿtVh��$��j�T������������k�
LJ����LJ�������>t
����P���jjhh������G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W��������LJ����LJ��h���+���s=���㋇�F��~�t)�^��G�F���;F�ujjj�v������͋^����G�j�,���_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h�����_^�VW�jjp�{��jq�5���������T��%�Uj�F�Pjh�Z��+�����|��=u,jW�F�+҉F��V��F�+ҹ������F�V�RP����@��TuƄT�}u�E�E*�P�u�E*�P�E*�P�u�E*�P�5Vh��
��j�F�Pjh��
����F�o�+�����}I��Tu��F������F��E*�RP�E*�RP�1��RP�+�RP�#���^���������Ph�
j�w
���Y�h�6����c�Z�h�6����e�g���_^�VWU��j�
���_^�VWU��jh��
���dNu���*�%Ph�����j���h����=t	hE����+�����|���Tu��F��V��
���E*�Ph�����E��Ph�����E*�Ph��~��jh��s����Ph��f������Ph��V���E*�ȋ�����Ph��;��h�h��/��V�U
��jh����V�C
���Z��_^�VW�
�v��%�F��ƀt
��%���F��
��%�������}��Tu���ƀt��^��������u#�����P�ρ������%����P�C
���߃����������F��V��^����������F��V��^���������F�V�;V�wr;F�v�%��^��������u��_^�VWU��h@�j�v�v
hn��
��
�_^�VWU��h@�j�v�v
hn�
��
�_^�VW��v�ƀt��%���%����F��F
=Ht=Ht"�����j�v�F����P�
���nj�F����P�v�����~�ƅT�F����F������*�RP�~������*�RP���RP�~������+�RP�����~���������+��_^�VWU��6<����tH�6N�6L�t�t
�D�tjx�
�R%aP�6Jhq��	���J�g�L�i�N�k���oW�
���_^�VW��v�D%�F��D�D�D�t�F��F�������|u�D
�T;Uu;Eu	V�����^�D��	�ȋ�+�D
T;Urw;Ew
�D�u�|u�L����><u�6<��>�7�6>�>Wu
��t��_^�VW��X�V�<���u+���D%�R�D�t
�R�D%�	�D%����J�J�����*�F��R������D
�TEU
�D�F�D��	�H�D�T�@�B�|uE�>Hv
�Y��Z��	�D�F;]u	;[u���D�F;at��;_t���ǃ>Ht���Y*�;Ju:�D�F;]u-;[u'h�t�t�6c������<�DV�K������Z*�;Ju"�D�F;au;_uh�t�t�6e빃<uW�F�+�RP�6F�6D�	���F��V��N������+�+F�V��X�X*�=r
�X�Z��>Xt�X*�H�Y���_^�VW��J������D*�RP�D*�RP�6F�6D���RP����N�D*�RP�D*�RP�6F�6D�o��RP�����L�D*�RP�6F�6D�������P�J;gu]�N;kuT�L;iuK�<�F��6N�6L�~��u�u
�E�tjx�
�R%aP�6Jh�����~��MW�y�����6J����D*�Ph��]���D��Ph��M���6Hh��@���6Ph��3���6Nh��&���N��Ph�����J��L�Ph������><�}u3j0h�������u�6Jh������6B�6@�%���W�j h�����W�t�_^�VWU��jh�
�6���_^�VWU��6<�W*�H=v�����.���
�
��
����t�}�����u
�6Jh��[���X*�;Hu�6�>H�������c��6B�6@�����u��X*�;Hu*�>H������D�F��[��]�J�>H��X�X��@�l�V�D�F�HuWV����N�O�t�K��@�l�V�D�F�Ht��"�u�6Jh�������6B�6@�����_^�VW�
�6<h�����ȋ���!u�Gh������F��W*�=u�X*�;Hu�Vd�3�F��u��Vd�J�g�L�i�N�k�6N�6L�H+҉F��V��X*䙉F��V��D��	�ȋ�+�D
TF�V�+F�V�RP�D�tjx�
�R%aP�6Jh������@u	h������ t	h����F�t	h����F�t	h+�o���F�t	h@�_���F�@t	hP�O���F�t	he�?���F��t	hx�/���V*�=s	h����h�����+���V�V*�=r�����_^�VW��6<�p�N�F��V*�H=w9����.���
�
�
�
�
�
�
�N�}'�F��!�J���F��F�;��r�n����F��V*�=sP��u����t�v�h��\���F���Ph��L���J���Ph��9��Wh��/���W�!�W*�=u�X*�;Ht�LV����_^�VWU��v�t�W��<V�>������t�|��_^�VWU��6��~�I���t���N���vh�����+��_^�VU���v�����o]^�WU���~�����m]_ú�����쨀��tKu��ú��������uKu���VW��v
�F��%�F�jj�v�����>uejjj�v����F��tF�^�����U�u/�F��~�}j�F�����P�ƃ�P�D���F����F��v��W���v�X���v�����F��_^���`���`�VWU��N�	�v
�~��F��]_^ø�`���`���`�U���v�v�P�'��]���`�����܋W+�����`�[XS�`[SSø�`���`�VWU���_^��܋W�G�ø�`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�`����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@��[��]_^��Ë܋_��Ë܍_VWU��P�F�'����F�g��F
�'��֋�[��]_^��Ë܋_��Ë܍_VWU��P�v
�~+�+�� ��������;Wrw;r+W��[��]_^ø�`�ldrv:%d: bad dev
ldrv:%d: dev bsy
Z\�B_|\@�D2at%d: TO
at%d: ncyl=%d nhead=%d wpcc=%d eccl=%d ctrl=%d landc=%d nspt=%d
at: AT disk controller not present (reset)
at%d%c: bno=%U head=%u cyl=%u <Watchdog Timeout>
at%d%c: bno=%U head=%u cyl=%u <Track Flagged Bad>
at%d%c: bno=%U head=%u cyl=%u <Drive Not Ready> <Write Fault> <No Data Addr Mark> <Track 0 Not Found> <ID Not Found> <Bad Data Checksum> <Command Aborted> <Block Flagged Bad> retrying...
Kpkcopy_Kkpcopy_Kdopen_ahigh	
ahigh	
ahigh	
bhigh	bhigh	bhigh	Ksleep_main_Kukcopy_Kkucopy_clrivec_Kioreq_uexit_�Kdefend_Kclrivec_setivec_�sphi_Nldrvipc_u_ldrvics_drvl_ldrvcon_inb_(Kuexit_dclose_�nulldev_\outb_fdrvn_timq_ldrvsel_blkmv�Ksetivec_xcalledbread_�atsend_�myatbsyw_�con_Kldtimcall_ldrvint_brelease_�Kdclose_atparm_�atrecv_�vldiv�CSR_REG	�defer_vlremFcprocp_kcall_<timeout_\bdone_�Kbread_sds_alloc_�ucs_vrdiv�vrremOwakeup_�Kbrelease_DRQ_ST	spl_Rvlmulfdisk_Ktimeout_Kbdone_atdrqw_printf_zalow	alow	alow	allkp_ldrvpsy_blow	blow	blow	BSY_ST	�atcon_�Kalloc_dopen_pkcopy_pkpcopy_Hgetcs_$vrmulKwakeup_sleep_DATBSYW_�atbsyw_�kucopy_Rukcopy_�Kprintf_Kldeferioreq_20'''$$*0-05'?'J$Q0T0\'b'$e'h'$k'o' q'u' w'~'�J'�'�''�9'� '�''�'$�0�'�2$�'�''�''�'�'� ''90'#'-'407'J0_0p0�$�$�'�$�$�$�$�$�0� � � � � � � � � � �0�0�%�%0$0$0P%Y%`$�0�0�0�$�%�0�0�%�%�0 0%'I0%#%''/I02%8%<0L0`$l0x0�0�$�0�$�0�%�0�0�0�0�0�0�00)050<0G0N0T%�'�0�0�%�%�%�0�%�%�%�%�%
%'$%1%5';%S0V%p0s'�0�$�0�$�0�%�$�$	0$ 0'%1%508%G0J'P%V%Z%n%y$|0%�%�%�%�%�%�0�0�0�%�0�%,%3%9%?%C0I0P%^%c%g0r%{%�%�%�$�%�%�%�%�%�%�%�%�%�%�0�%�%%%
0%%%0%#0(%.04%7%=%B%F%J%P%_0b%j0s0y%|%�%�%�%�%�%�%�%�0�%�%�%�%�%�%�%�%	%	$	%.	%2	05	0=	%C	%W	%[	0^	0f	%l	%x	%|	0	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	%�	$�	0�	0�	0�	%�	0�	0
0
%
0$
%+
01
%8
0>
%D
0N
%T
%[
0e
%l
0z
0�
%�
$�
0�
%�
%�
0�
%�
0�
%�
'�
 �
0�
%�
%�
0�
 �
 �
 �
 �
0�
0�
00	00%$0%#%)'/7%3%<%B%F0I0O%V%\%b%k%o%s%w%z%~%�%�%�%�%�%�%�0�0�0�%�%�%�%�%�0�%�$�0�%�%�0�%
00#0)%2%<%B%H0L0V%Z%^%a%d%g%j%m%q%u%x%�%�%�$�0�$�0�$�0�$�0�$
0	
$
0
$&
0)
$6
09
$F
0I
%O
$Y
0\
$b
0e
%r
%u
0
%�
%�
%�
 �
 �
 �
 �
 �
 �
 �
%�
$�
%�
'�
00%0+05%<%B%L%R0]'p%v%|0�0�0�$�0�$�0�0'04';0J0�0�0�0�'�P'�#'�C'�#'�6'�#'�='�#'�+'�#']0''#'3'6#'@#'I'L#'S'V#'q't#'{\'~#'�'�'�'�'�'�9'�'�)'�"0�'�'�'�''9''#0&'1';'E	'H#'xB0{0�0�'�('�B0�0�'�'�#'�'�#'�V'�#0707070064030114611006440000030000030000011777770507310760500003700000017175/newbits/kernel/USRSYS/ldrv/fl�&�P����v�v�v�Ѓ��VW��6�t;6|Vh����j�7��k�
��u���ヿtVh���
��j�������������k�
LJ����LJ�������>t
����P���jjhh��H����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�
������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v��
���͋^����G�j��
���_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h��
���_^�VWU��j����jjp�0��jq�������ƈu7��
����������%�������t,����t"�����������t����%@���>�tt���jh����h�
j����jh����jh�������=t���Ph��~��j�!	�������P�	������P�	��W�>���_^�VWU��>�tj����jjjh�!���.jh�����_^�VWU�������F%���;�s�v�������~��������u��_^�VWU��j�v�v
h��
���_^�VWU��j�v�v
h��e
���_^�VW��~
@t���F%������v�D
���F��F@P�6
���F��~�wʋF�;Es��Ft�E�f�F��	�E�f�F������e����+ҹ	�����������F���E����j@�vh�h��	���_^�VW��v�D��	�ȋ�+�D
T-���F��\�����D
;��v�LV���c�|@t"�\�����F�;��r�D�D�D@t����D�t�|@u���d
���>�u�6�����7�6��>�u�W�A
���_^�VW��6����=v�����.����f�?�.�u��j�D%���Ph��;���D%������D%������ظ������D�T�����D
�������Ƈ��D��	���u��������F��t����F�;F�t���Ph��~������Ƞ��#�uG��������Ƞ���
Ph��O���;jh�jdh�2	�������Ƈ����������Ƈ�����Ƞ���
Ph����������؀��u%��������j������P����������>�B���>�t!����>�����>�������>��������>�����>�������>���j�������ȡ����P�
���>�Pt"����؀��u����P�����؀��t��6����������|tjh�jh�����������Ƈ����jh�h$�Y���t������Ƈ��f���|t�|uP���E�6�h�6��6�j�Z��
�u>�6��6�hL�t����h$����LV�N���+����M�6��t�j���W�������ȡ����P�����|@u%���P�����6��������P����h��H�6�����6�����6�������P����6��������؊���P�{��h��r����������Ƈ�j�V��h$�7����������t+�����=}
�����Ƈ��-�X�LV�C���!��u�D�����������>�u������Ph�j��hk�5���_^�VW���F����=u	�F�����v������_^�VWU��v���%����؀��uO�ށ������=u O���%����؀��u��%=u+����_^�VW���F�+����}H���#�uF����|��������=|���� ����;�uր>�t��?�>�u����������Ƞ���
Ph��0���>�u�.�v�����_^�VWU��j���h$���jh�����jh��������=t���Ph�����j�v�������P�e������P�Y��+�����������������t+���Pho����|�LV�L�������t;|t�jh�jh�O�����_^�VWU���-���2�>�t���V����_^�VWU��v�����V�G���_^�VW��F����F�+�h������ȋ����u�N�u�h�������@th��������sɋ�G�ƈ��뾉>�jh����+�h��x���ȋ����u�N�u�h������@th��Q������sɋ�G�ƈ��뾉>��v��H���_^�VWU��+�h����%�=�tNu�h��H����vh��&���_^�VWU���6��6����%Ph�����>�|*�������t	h������������t	h������>�|~�������t	h������������t	h����������t	h����������t	h ���������� t	h+�w��������ǀt	h9�b���>�|i�������t	hG�F���������t	hd�1���������t	ht���������� t	h�����������@t	h�����h������_^ø�`�VWU��N�	�v
�~��F��]_^ø�`���`�VWU��v�Q�D�F
�D�vhVh�]���_^�VWU��vVh�G���_^ø�`���`���`������`��܋W+�����`�[XS�`[SS�VWU���_^��܋W�G�ø�`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�t����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh�(�������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh�����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
(Nh�~	��@(#*P�(#*PP#*Ph(	#*P�(	#*P�P	#*P`	PT@PTfd: DMA page straddle at %x:%xfdsfd%d: <Door Open>
flintr: timeout
flsense: timeout
flput: timeout
fd%d: head=%u cyl=%u <Not Ready> <Equipment Check> <Missing Address Mark> <Write Protected> <No Data> <Overrun> <Data Error> <End of Cyl> <Missing Data Address Mark> <Bad Cylinder> <Wrong Cylinder> <Bad Data CRC> <Data Deleted>
Ksleep_main_Kdmalock_clrivec_�dmaoff_�
int11_uexit_nflrecov_
Kdefend_Kclrivec_setivec_@sphi_
ldrvipc_u_ldrvics_Kint11_Kdmaoff_fldone_�
drvl_ldrvcon_fl_hlt_�inb_�
Kuexit_nulldev_outb_"dmareq_�
drvn_getubd_�
timq_ldrvsel_blkmv^
Ksetivec_xcalleddmaunlock_�
con_Kldtimcall_fl_hut_�ldrvint_Kdmareq_Kgetubd_devmsg_z
cprocp_kcall_timeout_bdone_T
dmago_�
Kdmaunlock_fl_srt_�panic_,ucs_wakeup_xspl_dmaon_�
Kdevmsg_Ktimeout_flcon_�Kdmago_Kbdone_printf_6ldrvpsy_flunload_�Kpanic_getcs_�
Kwakeup_sleep_Kdmaon_dmalock_�
Kprintf_0'"'$$*0-05'?'J$Q0T0\'b"$e'h"$k'o" q'u" w'~'�;'�'�"'�1'�'�"'�"$�0�'�)$�'�"'�"'�'�'�''10'#'-'407'J0_0p0�$�$�'�
$�$�$�$�$�0� � � � � � � � � � �0�0�0�$$
%%%#%.%80=%C%V%Z0`0j p0u0�0�%�%�0�0�$�$�0�$�0�0�%�0�%�0�'�0%0+$@'G
%\0_%v0y'�
0�$�0�0�'�
'
'
'
'
%0$[0f$0�%�%�%�%�%�0�0�%�%�0� � � � � � � � �'0$%0!%0%9%<%I%R%V%\%_%f%p%x%~%�0�%�0�%�%�%�%�%�%�0�0� �%�0�%�%�%�0�%�%%%00!%$%+%1%80=%C0H%O0S%V%[%`%d%j%o%r%w%z%}%�%�%�%�%�%�%�%�%�%�0�%�%�0�%�%�%�%�%�%�%�0�%�0� 
%00%%"%' -%0030=%@%G%O%a%j%q%u0z%�%�$�0�%�0�0�0�%�%�0�0�%�%�0�%�0�%�0�%0%0%0%&0)%/04%;0>%D%K0P0Y%`0d%g%n0t%z0}%�%�%�%�%�0�0�%�%�%�%�%�%�0�%� �0�$�0�0	%	%	0	0 	%@	$Q	%g	0�	%�	%�	%�	%�	%�	%�	%�	0�	%�	0�	%�	%�	0�	%�	'�	0
0
%
0 
0+
06
%<
%E
0M
0U
$[
$b
0f
$l
0r
%z
%~
%�
%�
%�
%�
$�
0�
0�
%�
 �
%�
0�
%�
0�
0�
%�
0�
0�
%%00 0+$@0C0R%e%k0s0~$�0�0�%�%�0�0�$�0�0�%
%%$0%#%)$508%>$J0M%T%Z$f0i%o${0~%�$�0�%�$�0�%�$�0�%�$�0�%�%�$�0�%�$
0
%	
$
0
%
$*
0-
%3
$?
0B
$H
0K
'U
9'X
 '{
5'~
 '�
8'�
 0�
'�
#'�
0�
'�
.0�
'�
'�
 '�
A'�
 '�
&'�
 '�
''�
 '' ' '-='0 '7C': 'G
'V'b'i
'x'�1'�'�%'�0�'�
'�'�'�'�1'�
'�	0�'�'�'' '46070?0D'S#'Z60]0d'o'r 'y?'| 0707070064030114601006660000030000030000011777770507310760700003700000042766/newbits/kernel/USRSYS/ldrv/gr�h`"P���v�v�v�Ѓ��VW��6�t;6|Vh��#��j�g��k�
��u���ヿtVh�����j�@������������k�
LJ����LJ�������>t
����P���jjhh��d����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v������͋^����G�j����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h������_^�8(+dp VWU����^�w�O�?t��۽��v�V�F�~�F#F&1��&1�� +��f����.���
�ڀ~(u����F#F&1��&1�� [�^�v�V�~��������^���O+OO]_^�6�c����Q��V���B.����JK}�Y��������$t������F���F���F�F�F��F�FP*Ҋv�v
�^�^+��F�6���y6��s*���:v~U�vVQ�^�^
��.���
.���
����.���
Q+���VWQ�Y_^�� �� �F#F_W���_�� ���Y^�D����.���
�ڀ~(u����I�����.���
����I�����.���
�~(t�V*���������2���Ȏػ��3F#F�W�3F#F&���N�3F#F��3F#F&���N�3F#F��3F#F&���N�3F#F��F3F#F&�_^+���:V}
�I�����.���
*���:v�3��v����oV*�������n�����ػ��3F�W&�!��O�3F�&�!��O�3F�&�!��O�
f3F�&�!_^+���:V}
�I�����.���
*���:v����v�j�����I�����.���
*Ҋ���.���
��I�����.���
��}�V����:v
}*Ҋv
�|��H���I��~�~����.����2���I�<;t!�؀�0��	w9�f�F����FÈF���	���I��؀�0��	w�f�F����FÈF�ފ���.��������I��؀�0��	w�f�F����FÈF��<htL<ltX�������I��؀�0��	w�f�F����FÈF��<hu��<lu�������€�*����~
u6����~
u6����V��}*�:Vr�V���d�� QV+Ɋʀ���*�ыv�~Pu���A��F#ƫ&�A�&�EN&�AN&���&���&���F#�&�����+�^Y:V|*V��:v~�v�����*���:v
s�v
�����~u�F����~u�F�����:vv�v�����:Vr*V��:vv�v�V�����v��*�v
:vr�v�V��*�:Vr�V���{���:v
}�v
�n�VQ�^����.���
.���
�^��.���
+�~1��VWQ�Y_^�� �� �.���
W���F#F�_�� ���*�Y^��6�� ��F<u�^�<u�^
�r*Ҋv
����.���
�^*��<�F<u�^��<u*��H*Ҋv
+��^��F��<u�<t,��.���
*�*�Q�F#F��������� ��}�Y��RQW�F#F��.���
����.���
+�~��WQ�Y_�� �Y����.���
+�~x�׋���P������P������P������������P������P������P�����+�YZ���RQW�F#F��.���
����.���
+�~��WQ�Y_�� �_+ɊN*ʀ~(u��׋���P������P������P������������P������P������P�����+�YZ�t�6���VQ�^�^��.���
�΃�.���
������.+��
~3��VWQ��Y_^�� �� �.���
W���F#F��_�� ���*�Y^�	��V��*�:Vr�V������F
�u���:Vr�V������v��*�:vv�v�V��*�:Vr�V������:v���v�R��V�v���V�v����:v
}�v
�����Nt

�F�����F���F<u�F���F�F�!<u�F���<u�F���<u�F����D��~Pu�F(�����F�����~(u�FP���F����F��}*�:Fw�^��}*�:^w:�w
�F
�^��*�����v��*�:vv�v����F
�u���:vr�v��ttttttt����	t�0
F
ttttttttttt�tttt��������������������������������������������������������������������������������������������������������������������������������ttttttttttttttttttttttt�	�	tttt��ttttt�	ttttttt�	ttttttttttttt�ttttJt��tttttttttttttttt��ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttStt����e�������tTttt�	�	ttttt�tttttV	l	tt�
�
�	�ttttt�	ttttZ
ttt�	ttttttttt@��@��
@��
@��@��@��@� �!#@$�%�&(@)�*�+-@.�/�02@3�4�57@8�9�:<@=�>�?VWU��n
�~t����~���؋FF=@wW�F+ҹP������������u�P+�;N~�N�-)NNV�^�� �P+�;N~�N�)NN�� +���]_^�VWU��n
�~t��؋v�����FF=@wҋF+ҹP�������������u�P+�;N~�N�)NNW�_�� �P+�;N~�N�)NN�� +��ĺ���ú���6����0�3�����0��?�������??��00������?���?���?��������������?���?�������������������?�0000?����������������???�������?�?�������?�����?���<?�<<<?�<�������?�?���������������<������<?�����?�<�<�<�<�<�<�?�������?����<�<<<<�<���������?��?���?�?�����?�������<��<����00��00�?���������?��������������<<���<���<����?��?�<����<��<<�<�<��?����?<<���������<�����<���?�����?���<��<�?������<�<�<?�������?�?��<<�?�<��?��<<�<�<?���<������������<<�<?��<����<�<?����<��?��<�<?��<�<?�?��<�<?�<�?�����������<��?�?���<���<<<���?��<�������?��<��<�<���<�<��<�<<?�<<<����<���<���<�<<<<<<<�����<<?�<<����<<?�<<��<����<<��<�<�<���<�<�<��������������?��<<<<�?�?�<��<�<<<<<<���<�����<�<�<�<�<�<�<�������<?��<�<�<�<�<?���<<<<?�<<�?��<�<�<��?�<��<<<<?�?�<��<?��<����<?�?�3������<<<<<<<<<<<<�<<<<<<<<<<���<�<�<�<�����<�<<���<��<�<<<<<<<���������<�<������<��<���������<<�������?���?<<<<?�<<<<��?��0��0?����?�����?<?������?��<�<��<<�?<����?��?��<<?�<<<<<<?���������?��<<<<�?�<�<<?������<�<�<��<<<<<<<<�<<<<<<���<<<<?�<�?<����?�����?<<<<?��?��?�?�0����������<<<<<<<���<�<�<��<���?�?���������?��?����<�����?���?�����??<���<��<�<�<��VW��v�D u2V�D���F��|$�F��F��F��F��F��F�Ph�����ǃ>u�Vh�j
h����_^�VWU������>}2�h�jC���h�jB���j
jB���ja�C��
��>~�uja�)��%��Pja�U���>t��P�����V����v�z���vh�j
h�	���_^�VWU��>~�>~	�u����_^�VW��v
�D�F��<uV����u����Dup� t'��F��jjhh�~���v�����ы>�E$E&t&�k�t�>�F�;Du��6V����t+��V����|u��� t��V�����u��_^�����܋W+���[XS�`[SSø�`�VWU����_^�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�f����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh�����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
>>0�0>>>>������P�Kttstart_ZERO	mm_vpa�
ismmfunc_AZERO	0mm_cup�mm_scr�	BXXXXXXXX	��mm_ed�csivalGKsleep_mmtim_mm_hprl	mm_new�	MM_SROW	main_mmspec�mm_sgr�	mm_cuu�scrolldown�mm_hvp�	clrivec_�mmbeeps_B_XXXXXXX	?�BX_XXXXXX	��BXX_XXXXX	��BXXX_XXXX	��BXXXX_XXX	�?BXXXXX_XX	��BXXXXXX_X	��BXXXXXXX_	��BANKSZ	 mm_dl�mm_voff_XMSR	�ewait0�mm_el�ewait12CLOWER	cmmcrtsav_fontw_2read1\mminit�mm_cr�mm_e0cmm_il�read2upage1�nonedev_0uexit_�mmgo_�rowtab�
csi_q�mm_e1�page2�mmwatch_2B__XXXXXX	�B_X_XXXXX	3�B_XX_XXXX	<�B_XXX_XXX	??B_XXXX_XX	?�B_XXXXX_X	?�B_XXXXXX_	?�BX__XXXXX	��BX_X_XXXX	��BX_XX_XXX	�?BX_XXX_XX	��BX_XXXX_X	��BX_XXXXX_	��BXX__XXXX	��BXX_X_XXX	�?BXX_XX_XX	��BXX_XXX_X	��BXX_XXXX_	��BXXX__XXX	�?BXXX_X_XX	��BXXX_XX_X	��BXXX_XXX_	��BXXXX__XX	�BXXXX_X_X	�3BXXXX_XX_	�<BXXXXX__X	��BXXXXX_X_	��BXXXXXX__	��mm_e2�Kdefend_nondsig_&HLOWER	hmm_ssrZ
mm_vpr�
setivec_\Kclrivec_IO_IOC	IO_BASE	sphi_&ldrvipc_NRB2	@MM_BASE	mm_ri�	grread_u_NCR2	mm_siF
NRB4	�IO_SEG	mmputc�ldrvics_B___XXXXX	�B__X_XXXX	�B__XX_XXX	?B__XXX_XX	�B__XXXX_X	�B__XXXXX_	�B_X__XXXX	0�B_X_X_XXX	3?B_X_XX_XX	3�B_X_XXX_X	3�B_X_XXXX_	3�B_XX__XXX	<?B_XX_X_XX	<�B_XX_XX_X	<�B_XX_XXX_	<�B_XXX__XX	?B_XXX_X_X	?3B_XXX_XX_	?<B_XXXX__X	?�B_XXXX_X_	?�B_XXXXX__	?�BX___XXXX	��BX__X_XXX	�?BX__XX_XX	��BX__XXX_X	��BX__XXXX_	��BX_X__XXX	�?BX_X_X_XX	��BX_X_XX_X	��BX_X_XXX_	��BX_XX__XX	�BX_XX_X_X	�3BX_XX_XX_	�<BX_XXX__X	��BX_XXX_X_	��BX_XXXX__	��BXX___XXX	�?BXX__X_XX	��BXX__XX_X	��BXX__XXX_	��BXX_X__XX	�BXX_X_X_X	�3BXX_X_XX_	�<BXX_XX__X	��BXX_XX_X_	��BXX_XXX__	��BXXX___XX	�BXXX__X_X	�3BXXX__XX_	�<BXXX_X__X	��BXXX_X_X_	��BXXX_XX__	��BXXXX___X	�BXXXX__X_	�BXXXX_X__	�0BXXXXX___	��NCR4	IOSYS	MM_COL	drvl_ldrvcon_inb_NHB	PKuexit_outb_Hnulldev_>drvn_ewait�timq_mm_so0
ldrvsel_Knondsig_istty_Ksetivec_xcalledkbunscroll_B____XXXX	�B___X_XXX	?B___XX_XX	�B___XXX_X	�B___XXXX_	�B__X__XXX	?B__X_X_XX	�B__X_XX_X	�B__X_XXX_	�B__XX__XX	B__XX_X_X	3B__XX_XX_	<B__XXX__X	�B__XXX_X_	�B__XXXX__	�B_X___XXX	0?B_X__X_XX	0�B_X__XX_X	0�B_X__XXX_	0�B_X_X__XX	3B_X_X_X_X	33B_X_X_XX_	3<B_X_XX__X	3�B_X_XX_X_	3�B_X_XXX__	3�B_XX___XX	<B_XX__X_X	<3B_XX__XX_	<<B_XX_X__X	<�B_XX_X_X_	<�B_XX_XX__	<�B_XXX___X	?B_XXX__X_	?B_XXX_X__	?0B_XXXX___	?�BX____XXX	�?BX___X_XX	��BX___XX_X	��BX___XXX_	��BX__X__XX	�BX__X_X_X	�3BX__X_XX_	�<BX__XX__X	��BX__XX_X_	��BX__XXX__	��BX_X___XX	�BX_X__X_X	�3BX_X__XX_	�<BX_X_X__X	��BX_X_X_X_	��BX_X_XX__	��BX_XX___X	�BX_XX__X_	�BX_XX_X__	�0BX_XXX___	��BXX____XX	�BXX___X_X	�3BXX___XX_	�<BXX__X__X	��BXX__X_X_	��BXX__XX__	��BXX_X___X	�BXX_X__X_	�BXX_X_X__	�0BXX_XX___	��BXXX____X	�BXXX___X_	�BXXX__X__	�0BXXX_X___	��BXXXX____	�COL	
ttout_�IO_SEEK	con_Kldtimcall_ldrvint_NRB	�NCR	crtdata�putc16�grwrite_�mmwrite_RMM_FLIP	islock_B_____XXX	?B____X_XX	�B____XX_X	�B____XXX_	�B___X__XX	B___X_X_X	3B___X_XX_	<B___XX__X	�B___XX_X_	�B___XXX__	�B__X___XX	B__X__X_X	3B__X__XX_	<B__X_X__X	�B__X_X_X_	�B__X_XX__	�B__XX___X	B__XX__X_	B__XX_X__	0B__XXX___	�B_X____XX	0B_X___X_X	03B_X___XX_	0<B_X__X__X	0�B_X__X_X_	0�B_X__XX__	0�B_X_X___X	3B_X_X__X_	3B_X_X_X__	30B_X_XX___	3�B_XX____X	<B_XX___X_	<B_XX__X__	<0B_XX_X___	<�B_XXX____	?BX_____XX	�BX____X_X	�3BX____XX_	�<BX___X__X	��BX___X_X_	��BX___XX__	��BX__X___X	�BX__X__X_	�BX__X_X__	�0BX__XX___	��BX_X____X	�BX_X___X_	�BX_X__X__	�0BX_X_X___	��BX_XX____	�BXX_____X	�BXX____X_	�BXX___X__	�0BXX__X___	��BXX_X____	�BXXX_____	�MM_FUNC	MM_MASK	MM_NCOL	mm_cha�done�cprocp_kcall_timeout_4mmstart_2mmtime_�CSR	�evaltrepos_Kttout_MM_SCOL	ucs_MM_POS	MM_VIS	uds_mm_cgh�mm_von_$B______XX	B_____X_X	3B_____XX_	<B____X__X	�B____X_X_	�B____XX__	�B___X___X	B___X__X_	B___X_X__	0B___XX___	�B__X____X	B__X___X_	B__X__X__	0B__X_X___	�B__XX____	B_X_____X	0B_X____X_	0B_X___X__	00B_X__X___	0�B_X_X____	3B_XX_____	<BX______X	�BX_____X_	�BX____X__	�0BX___X___	��BX__X____	�BX_X_____	�BXX______	�wakeup_�spl_*asctab�
mm_cgl�Ktimeout_MM_ROW	SEMIC	;POS	MSR	�esctab�mm_cbt�mm_hpaV	printf_RB_______X	B______X_	B_____X__	0B____X___	�B___X____	B__X_____	B_X______	0BX_______	�MM_BROW	
MM_WRAP	mm_cub�mm_dmiJldrvpsy_MM_ATTR	
mmdata�mmvcnt_mmesc_scrollup
putc84mm_esc�mm_emi�mm_ind�	ttstart_�VSEG	�mm_cqhwmm_cud�getcs_MM_EROW	MM_ULINE	mm_cnlcsitab�Kwakeup_mm_cuf�ROW	MM_N1	mm_cht�mm_cplemm_old�	grcon_�sleep_MM_N2	mmbell�csi_gtSmm_cql�B________	exit.MM_CURSE	MM_IBROW	Kprintf_MM_LROW	csi_n1�MM_PORT	csi_n2%MM_IEROW	mm_eaT0''$�$*0-05'?�'J�$Q0T0\'b$e'h$k'o q'u w'~�'��'��'�'�R'��'�'�$�0�'�H$�'�'�'��'��'��'j'R0'#j'-_'4U07'J�0_0p0�$�$�'�d$�$�$�$�$�0� � � � � � � � � � � �'U$ 5$j'�� �0�'�'��    )0] f 0� �0� � 0*00 �0�0�0� � � �0�0� �0�0# N0Q0~0�0�0�0�0�$�0�$�0�0�0`0c0r0u0�0�0�0�0�0� �  
 *0H'M
0R0_0i w0�0� �0� � � 0a q z0�'�
0� 	 
	 	 5	0T	0j	0�	0�	0�	0�	0�	0�	0�	0�	0�	0�	0.
0D
0X
0�
0�
0�
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
     	  
          ! # % ' ) + - / 1 3 5 7 9 ; = ? A C E G I K M O Q S U W Y [ ] _ a c e g i k m o q s u w y { }  � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �     	  
          ! # % ' ) + - / 1 3 5 7 9 ; = ? A C E G I K M O Q S U W Y [ ] _ a c e g i k m o q s u w y { }  � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 
 
 
 
 	
 
 

 
 
 
 
 
 
 
 
 
 !
 #
 %
 '
 )
 +
 -
 /
 1
 3
 5
 7
 9
 ;
 =
 ?
 A
 C
 E
 G
 I
 K
 M
 O
 Q
 S
 U
 W
 Y
 [
 ]
 _
 a
 c
 e
 g
 i
 k
 m
 o
 q
 s
 u
 w
 y
 {
 }
 
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
'*U'�U$-0D0m%v%} �'�0�0�'�'�0�0�0�0�'�'�0�0�'��'��7'
�00 !'&0)$9$@$G0L0h0r'�0�'��'��0�0�'�H0�7��'�d0�0�'��'�d0�'�''�'*�'7d'S�'V�'cd'rj'~_'�d'�_'�R'�j'�'��0�'�d'�_'�j'�j'�R'�d'�[0�'	_'j'
' �'Px0S0[0`'o'vx0y0�'�P'��'�'��'��'��'��'��0707070064030114571006440000030000030000011777770507310761400003700000014365/newbits/kernel/USRSYS/ldrv/hs�������v�v�v�Ѓ��VW��6�t;6|Vh��	��j�M��k�
��u���ヿtVh��~	��j�&������������k�
LJ����LJ�������>t
����P���jjhh���	����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�@	������LJ����LJ��h�q��+���s=���㋇�F��~�t)�^��G�F��;;F�ujjj�v��D	���͋^����G�j��	���_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h���	���_^�VW�i^P�6������uh�������i^P�6�����F��F�;|���^�����
iF�^���j��P���j��@P�t����@P�@���t��!��\�Di�D��^������D��D���(���)�|��)����㋇D�F�h���P����v�W����F���P��@P����j��P�����6��F��3��_^�VWU��>�t
�6�����_^�VW��~��i�^����|t�D@P�r��������t�����t�'�r�D�D=uZV�����F�t;�<�F��DP�'�����L ��t�d���� t�L�v��
���
�d���LV����vV����2�_^�VW��~��i�^����|uJV�%���F��~�t8h�h�j
h����jjhh������Z*�:�[u̓~�t��N����L���_^�VWU��v
jV�~��i�^�P�����_^�VWU��v
jV�~��i�^�P����_^�VWU���v�v
�~��i�^�P����_^�VWU���v�v
�~��i�^�P����_^�VW��v��X*�:�Yt2��Y*�ȋ�ي�Z*�PV�)����Y*�=�rƄY����Y�¿���Z*�؊�[*��+���Ǚ.�>���O|9V����F��|+��Z*�ȋ�ًF���\��Z*�=�rƄZ����Z��V�����|tVh�j
��HP�,���_^�VW��6��|u��DtL�DP��������t7��t��t�d����L ��t�� t�L��d��V�"���DP�������t�Dt	jV�M����t:��X*�ȋ���F��t�i���^���Z�Dt��X��X*�=rƄX�� tC�D u<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�<����[��[*�=rƄ[��^��;�w����_^�VW��v���F�+���)t��W�DP������)����㋇D���t+h��DP����W�t�������P�D@P�����,%�=t=t���
��W�DP���j�D@P�t���v��M����_^�VWU��v�4���DP� ������ t<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�����[��[*�=rƄ[W�����_^�VWU��������;�|�����_^�VW����t��F��F��F�;}?iF�^��>��}t)iF�^��>���(����狅l�F��F�;F�}�F��F��F�븋F�;t.��.�>������&���~�th��6�����_^�d��`�VW��~dra�F+�.�6�	�uS�F+�RPjh�4�����F����F�j6jC�����F�%�Pj@�����F���Pj@�����v�����F���F����F��_^�VW��v�{����F��u�v�F��F
��P��v��e���F��_^�VW���F��~�t!jd�8����:�F���P�+���F��_^�d�����`�����܋W+���[XS�`[SSø�`�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�t����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh�(�������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh�����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
����
	��	7\��	�	���	Y@��`@:0 dddddddd�,��X �@hsload: can't allocate tty's
Kttstart_ahigh	
free_�	bhigh	Ksleep_Kttopen_main_ttsignal_fclrivec_Z
Kttpoll_hscycle_�hsparam_�Kfree_uexit_�Kttsignal_hsclose_�altclk_in_	Kdefend_kclear_�	altclk_out_Q	setivec_�	Kclrivec_sphi_�
ldrvipc_tthup_u_hsioctl_�hsread_7ldrvics_poll_hz_ldrvl_ldrvcon_inb_�	cs_sel_�	Kuexit_nulldev_�	outb_�	drvn_altclk_timq_ldrvsel_Kkclear_ttsetgrp_\Ksetivec_xcalledttclose_ttin_ Ktthup_ttout_>con_Kldtimcall_poll_owner_poll_rate_ldrvint_ttioctl_*ttread_Raltsel_vldiv�hswrite_\cprocp_kcall_�	timeout_�
Kttsetgrp_Kttclose_hsstart_iKttin_Kttout_HSNUM_alloc_�ucs_vrdiv�hsopen_	wakeup_�Kttioctl_Kttread_spl_�
Ktimeout_HS_PORTS_
hspoll_�ttwrite_zprintf_�	alow	allkp_ldrvpsy_blow	Kalloc_ttstart_pgetcs_�	Kwakeup_hsintr_�sleep_�
ttopen_4hscon_*Kttwrite_Kprintf_ttpoll_H0'1'$%$*0-05'?'J$Q0T0\'b1$e'h1$k'o1 q'u1 w'~'�S'�'�1'�E'�('�1'�1$�0�'�;$�'�1'�1'�'�'�(''E0'#'-'407'J'0_0p0�$�$�'�$�$�$�$�$�0� . 0 2 4 6 8 : < > @ B$�'�R0�%�$�00$
%0$#0($2%;0H0T0^0h0k t y$�$�0�0�0�0�%�0�%�%�0%0,';0?'C3'K0]0j0w0�0�0�0�%�0�%� �%�0%001%O0S%t0x%�0�%�0�0� /080q ~0�%�0�0�0�0�0050�%�0�0�0�$�00
00G0T0]0c0r0~0�0�0�%�%�%�%�%�'�30$%!%2$?'\4'a4 g%j0m'q3 |'�40�'�3'�U'�, �0�0�0�0�0�0	0#	00	'9	&0<	'?	80E	'X	&0f	0l	's	&'y	80	'�	'�	,'�	,'�	)'�	,'�	^'�	,'�	'�	'
'
'
'
E'"
'+
5'1
+04
';
'G
'R
'l
'p
E'v
'}
0�
'�
'�
'�
'�
,'�
L0�
0�
0�
'�
2'�
L0�
0'
?','/','!A'$,'+I'.,'5'8,'?B'B,'I	'L,'SJ'V,']>'`,'g'j,'q't,'{]'~,'�"'�,'�X'�,0707070064030114551006660000030000030000011777770507310761500003700000003777/newbits/kernel/USRSYS/ldrv/mm:*�����v�v�v�Ѓ��VW��6�t;6|Vh@���j����k�
��u���ヿtVhR���j�����<��>����k�
LJ����LJ�������>t
����P���jjhh:�����G$t�>:uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�Z������LJ����LJ��h���+���s=���㋇�F��~�t)�^��G�F��};F�ujjj�v��P���͋^����G�j����_^�VWU��><t
�v
�v�<���>u�:�_^�VWU��>>t
�v�>���:u	h:�K���_^Ì��[XS�`[SSø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh�F�������Dž����Dž�_^���`�VWU��v�~t�~
jjjVh�����
�+�A������D�F�D�vh�v
Vh�����
W� ���_^���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
Ksleep_main_clrivec_tuexit_Kdefend_setivec_�Kclrivec_sphi_,ldrvipc_u_ldrvics_drvl_ldrvcon_Kuexit_drvn_timq_ldrvsel_Ksetivec_xcalledcon_Kldtimcall_ldrvint_cprocp_kcall_�timeout_�ucs_wakeup_"spl_0Ktimeout_printf_�ldrvpsy_getcs_�Kwakeup_sleep_�Kprintf_0''$$*0-05'?'J$Q0T0\'b$e'h$k'o q'u w'~'�'�'�'�'�'�'�$�0�'�$�'�'�'�'�'�'
'0'#
'-'407'J0_0p0�$�$�'�	$�$�$�$�$�0�'�'�"'�'�	'
''!	'0'8'<
'E'K0N'U	'a'l
'�
'�'�	'�0�'�'�
'�'�'�0�0�0�'�'00'
''# '&0707070064030114541004440000030000030000011777770507310761500003700000012304/newbits/kernel/USRSYS/ldrv/ms�	�Dx8���v�v�v�Ѓ��VW��6�t;6|Vh�	�-��j�]	��k�
��u���ヿtVh�	���j�6	�����	���	����k�
LJ����LJ�������>t
����P���jjhh�	�n����G$t�>�	uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W��������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v������͋^����G�j����_^�VWU��>�	t
�v
�v��	���>u��	�_^�VWU��>�	t
�v��	����	u	h�	�����_^�VW���	�D
��	@�F
��	@@�H
��	�J
�+�F�h��6J
�,��j�6H
� ��hP�6�	�;���v����+��_^�VWU���6�	���h��6J
����j�6H
�����_^�VW��v�����F��>>
t�'P��������h��6J
���jZ�6F
����6F
�R��=Zt
��v���h��6H
�n���6D
�,��h��6H
�W���6D
���h��6H
�@���6D
����h��6H
�)���6D
����j�6H
���jh
hT
���jjh
hf
���Phb
���jh 
hj
���jh$
hn
�w��+����

�>
�v����+��_^�VW���F�j�6H
���+����>
�v��}��+��_^�VW��g�F��~
|�~
s�v�^
�����	������v��;���>t����+��_^�VWU��f
���f
���
#

u�~t	hL
����
#

u�f
���F
�_^�VWU��jhT
�v�D���>^
u�^
�>`
u�`
�_^�VWU��jhb
�v����&

���_^�VWU��j�vhb
�t���&

���_^�VWU��jhj
�v�����_^�VWU��j�vhj
�@���_^�VWU��j�vhn
�)���&

���_^�VWU��j�vh

����_^�VWU��jh
�v�w���

#
ujh�h�h

�������
�_^�VW��>>
u����F�h��6H
�����6D
����F�h��6H
����6D
�r���F��~����F�%ǘ�F�h��6H
����6D
�F���F�h��6H
�n���6D
�,���F��~����F�%ǘ�F�j�6H
�C��+��F��F��F��u�F��n
%3F�t�~�tjj�jj�I���F� u�F��n
%3F�t�~�tjj�jj����F�F�n
�~�u	�~�u���F�j
�F�l
�v��A��;T
�v��2��;T
~�f��f��~�t7�F���@
�F���>^
�@
�F���>^
b
�F��6X
�6V
P�����b
�~�t7�F���B
�F���>`
�B
�F���>`
d
�F��6\
�6Z
P����d
�b
;f
u	�d
;h
t�

jhb
hf
����

#
th

�O���>R
t	hL
�����v������_^�VWU��k^����p
jhb
kFr
P�N���F
	

�_^�VWU��F;F
}�F
��F;F~�F�F�F�_^�VWU��~}�F����F�_^�VWU��N�	�v
�~��F��]_^Ì���܋W+���[XS�`[SSø�`�VWU����_^�VWU���_^��܋W�G�ø�`���`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�R����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
<

i�&&&�44�=J{����������@d@d@d@d@dmsunload_=ms_readcrs_�Ksleep_MSPORT_�	main_Kukcopy_Kkucopy_clrivec_�pollopen_HKpollwake_nonedev_&ms_setmick_�uexit_�	ms_setup_JKdefend_Kclrivec_setivec_fKpollopen_ms_wait_sphi_0	ldrvipc_u_msclose_�abs_�ldrvics_drvl_ldrvcon_inb_Kuexit_nulldev_4outb_>drvn_msioctl_�timq_ldrvsel_blkmv�Ksetivec_xcalledms_readmick_�msload_�con_Kldtimcall_ldrvint_cprocp_kcall_timeout_>	ucs_MSIRQ_�	wakeup_�	ioctls_�	spl_4	c_range_�Ktimeout_msopen_ims_readbtns_�ms_setcrs_{printf_\ldrvpsy_getcs_mspoll_ms_readstat_Kwakeup_sleep_&	ukcopy_�	kucopy_button_ymsintr_PKprintf_pollwake_Rmscon_�	0'('$$*0-05'?'J$Q0T0\'b($e'h($k'o( q'u( w'~'�9'�'�('�.'�"'�('�($�0�'�+$�'�('�('�'�'�"''.0'#'-'407'J!0_0p0�$�$�'�$�$�$�$�$�0� �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 
 
 
 
 
$�%�$�%�$�%�$�%0%
0%0 "$&0)02$D0G%Q0T%]0`0s$}'�0�0�%�0�%�0�%�0�'�%�0�%�0�%�0�%�0�%�0�%0%0%0%&0)$1%407$A%D0G%N0Q$Y%\0_$g%j0m'u$y$}0�0�%�0�'�$�0�0�$�'�'�0�'�$$"%-00$6$:%R0X%_%f%l%s%�0�$�%�0�$�%�0�%�0�%�0�$�$0$0%$+$/$<0?$H$X0^0a%k0n%u0x%�0�%�0�%�0�%�0�%�0�%�0�%�0�%0.%@0[%g0v%}%�0�%�0�%�$�%�$�%�%�%�%�0�%�$�%�$%	%
%%0%"%%%)%.%2$8%?%B0E$K$O$T0W%^%d0g0p%�%�%�0�$�'%'' %'-'I'L%'S	'V%']C'`%'m'|'�'�'�'�.'�'�*'�$0�'�'�'�'�'�.'�'	0	'	'	''	'*	%'Z	40]	0e	0j	'y	)'�	40�	0�	'�	'�	%'�	'�	%'�	='�	%0707070064030114511006660000030000030000011777770507310761700003700000006523/newbits/kernel/USRSYS/ldrv/rm�DX�3���v�v�v�Ѓ��VW��6�t;6|Vh�����j�3��k�
��u���ヿtVh�����j�������������k�
LJ����LJ�������>t
����P���jjhh��R����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�������LJ����LJ��h���+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v�����͋^����G�j�����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h�����_^�VWU���_^�VW��F��~�}%k^�,�������tk^�,����������F����_^�VW��F%�����k�,����N����+҉F��V���T�F��V��~
u�t0�F�F�t�F�F�t�F��V�;V�u;F�u�F�F�u�F�F�u��o�F�F�td�F�F�u\h0��F��V��	�������������RP�o���D���u��,�F��V���T�E�U�D�T�D*jhRP����D*�_^�VW��~�����k�,����~����+҉F��V���T�F��V��t�F�F�t�F��V�;V�u;F�u�|*u��*�L*�F�F�u�|*t�'��t�{����D�_^�VW��v�D�F�%�����k�,����N�����+҉F��V���U�F�V��t�F��V�;V�u;F�t�L��F��V���������F�V��D��	�ȋ�+�D
T-��;V�w�r;F�s��D
�T�	������EU�F��V��|u�D+�RP�t�t�v��v���D+�RP�v��v��t�t���V�d���_^�VWU��v��%�����k�,���h@�jV�v
W�D��
�_^�VWU��v��%�����k�,���h@�jV�v
W���
�_^���`������`�[XS�`[SS�VWU����_^�VWU���_^���`���`���`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�\����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`���`�VWU��v�~t�~
jjjVh����
�+�A�����D�F�D�vh�v
Vh����
W� ���_^���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
!
����Ksleep_main_clrivec_�Kioreq_nonedev_uexit_jKdefend_setivec_@Kclrivec_sphi_~ldrvipc_u_pclear_ldrvics_drvl_ldrvcon_Kuexit_nulldev_drvn_timq_ldrvsel_Ksetivec_xcalledsalloc_6con_Kldtimcall_Kpclear_ldrvint_cprocp_kcall_�timeout_bdone_�Ksalloc_plrcopy_"ucs_wakeup_tspl_�Ktimeout_Kbdone_printf_,Kplrcopy_ldrvpsy_sfree_getcs_�Kwakeup_sleep_
Kprintf_rmcon_�Ksfree_ioreq_�0''$$*0-05'?'J$Q0T0\'b$e'h$k'o q'u w'~'�)'�'�'�"'�'�'�$�0�'�$�'�'�'�'�'�'
'"0'#
'-
'407'J0_0p0�$�$�'�$�$�$�$�$�0� � � � � � � � � � �%%%0%6'�0�'�0�%'b'z0�%�0�0o0v%�0�%�0�'�&'�'�'�'�''''#('&'-.'0'7 ':'G'V
'b
'i'x
'�"'�
'�'�0�'�'�
'�
'�
'�"'�'�0�'�
'�
'0''''0%030;0@'O'V%0Y0`'k'n'u,'x0707070064030111121006000000030000030000011777770507310761700003700000034774/newbits/kernel/USRSYS/ldrv/ss>$�f��	���v�v�v�Ѓ��VW��6�t;6|VhD$�}"��j��#��k�
��u���ヿtVhV$�V"��j�#����@$��B$����k�
LJ����LJ�������>t
����P���jjhh>$��"����G$t�>>$uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�""������LJ����LJ��h�I!��+���s=���㋇�F��~�t)�^��G�F��!;F�ujjj�v��N"���͋^����G�j�"���_^�VWU��>@$t
�v
�v�@$���>u�>$�_^�VWU��>B$t
�v�B$���>$u	h>$�]"���_^�VW�
�F��F����F���$+ҹ��������&��&jh RP� ����&��&����&��&hZ�RP�a!��h�<��&��&��RP�I!��hZ���&��&���-��RP�+!��h�<��&��&���-��RP�
!���6�&�6�&����=Z�uZ��&��&��RP���=�<u@��&��&���-��RP���=Z�u ��&��&���-��RP�m��=�<th�$����F���$����CC.;��t�.�g@�+�Z��&��&����&�'��&��&���'�'�'��a��&��&����&�'��&��&���'�'�'@�2��&��&����&�'��&��&���'�'�'@�'�'*���!�$�~�uj�F��~�}�>�$�N�����t	�F��F��F��F��݃~�uh�$����F��,iF��P�6���� '�uh�$��iF��P�6 '�[���~�u6� '�F��F��~�}%�>�$�N�����t�~���F��F����"'�F���h��6�$�D���2'���F�@P�'���'5�~�u&�F��~�}�>�$�N�����tQ�����F����' N�_^�VWU��> 't
�6 '�����6�&�6�&�:���6�$�B���_^�VW��v����%�F���%�F�����%�F��~��狅"'�F�"�F�������u��N���#�$u�F�%��v�V�������ƀt
�~�t�F�$%���ƀt�F��~�tX�~����uM��
�%���F��v�P����t,�~���U�~��EL�UN�EH�EJ�~�����������F�:%�r��~�tE�~��EL�UN�F��V�^���ߋ~���~��E�U
GW;V�wr;F�v
�F�N%�%�,��~�t�~���~��EEu
�F�o%������~��E�_^�VW��F��%�F��~��狅"'�F����~��M�_^�VWU��h@�j�v�v
h�&����
�_^�VWU��h@�j�v�v
h�&���
�_^�VW��v�F�����%�F�~��狅"'�F�"�F�F
=Ht=HtU��F�����F�"�F�~������$�F�F��~������$*�F��~������$*�F�j�v�F�P�G���C�F�"�F�j�F�P�v����~����F�$�~����F�*䈅�$�~����F�*䈅�$�F��F��_^�VW��v�F��D�F�%�F��F���%�F��F���%�F��~��狅"'�F��F��t�F��F�"�F��D�D�~����u>�~�u1�D
Du�|tt�F�%�L�~�t�v��v�����V��w�F�%�܀|u�~���~��D
�T;Uu;Et‹^���^��|��	��+�D
T;Wwr;Gv�F�%��D�u�|u�F�%�|�V�v��p���v��Q
���_^�VW���	�F��~��t!�v��拼"'�}ruPh��v�h��0���_^�VW��F��v�拼"'�}ru�vh������@�u����F��F�P�%���u���~�u��6'�6�&����%�F��F�*�P���=w�����.��v	�	.	.	.	�	.	.	.	�	.	�	.	�	.	�	�6'�6'����F��t=u�j`�6'�6�&�����m�j�6'�6'���h����6'�6'�g���F��D��F��<��6'�6'�K���+��v�����_^�VW��F��~�},�~��狅"'�F��~�t�~��}t�v�h�����F����_^�VW��F��F��~��}7�6'�6�&�����F��v����F�*���F��#�;�u�F���F��‹F��_^�VW�j�F��~�狅"'�F��~���j$���
��F��vh�%�����~�t6�F�P�vhU�R���t�F��~�u�F��h�%�h�%�v�����~�u���F�P�vh����u���F��F�*䙹�������F��V��F�*䙹�������F��V��F�*����ȊF�*����+�F�V�F�V��~���U�F�*䙹�������F��V��F�*䙹�������F��V��F�*����ȊF�*����+�F�V�F�V��~��E�URP�u�5h&���
�h-&�v��0���~�u��F�P�vh��%���u���F�*���F�*���ljF��F�*�ȊF�*�����F�*�������Ǚ�F��V��F�*�F�R�v�hB&�7���F�*�Ph\&�(���v�hf&����~�����$u+�~���F����$�~���F�*䈅�$�~���F����$�J�~�����$hn&�����~�����$*�Ph�&����~�����$*�Ph�&��	h�&�v��"���F��_^�VW��~�狅"'�F��~��E �F��F��v�~�E+D�F��F��~��E�E���F��F�P�����u���~�u��6'�6�&����%�F��~�u��F��F��F�*�P�Z��=w�����.���
b
b
b
�b
b
b
ob
Cb
Xb
�
�6'�6'�d���F��F�*��CC.;��t�a�.�g��%b
b
%b
b
b
b
�F�*�~��Ej`�6'�6�&�C����j�6'�6'�0��h����6'�6'�����~��E����v��~��E+D�F��~�~F�|�D��E*�P�6'�6'�����~�t���~�}t���~�u���v��������F����~�u�~�}u��F�h�F�EURP�6'�6'���
�\��~�u��~�}u��F�h�6'�6'�F�EURP�g��
�{��~�t	�v��l���~�t+����_^�VW�	�Y�F��~��F��F��F��'+�;V�wr:;F�v5�6'�6�&����F��F�t�F���F��V����F�u��~��v������F��_^�VW��F��F��F��F��F��F��F��?�tRj�v����tCjjj�F�Pj�F�P����t)�F�*�;�CC.;��u.�gIII�F��F��_^�VW��F��F��F��F��F��F�6�F���t-j�v�<���tjjj6�v
j�F�P����t�F��F��_^�VW��F��F��F��F�?�F��F�\�F��^�t-j�v�����tjjj\�v
j�F�P�3���t�F��F��_^�VW��F��F�%�F��F��F��F��F��F��F��F��F����t-j�v�p���tjjj�v
j
�F�P��
���t�F��F��_^�VW��F��~���j$���
��F��~�tFj �6'�6�&�����'*�P�6'�6'���j0�6'�6�&���h���s����u�F��~�tA��N��'*��P�6'�6'�u��h��6'�6�&�d��h�,����u�F��~�t#h��6'�6�&�;��h�����u�F��~�t3h��6'�6�&���j�6'�6'���h�������u�F��F��_^�VW��F����6'�6�&����F��F�$tE�6'�6'����F��'*���F�*�#�t$�F�*�#�$t�'*��� F��F��n�t�F����F��_^�VW��~�狅"'�F��'�>'u���~��E �F��Er*�-=v�����.��LRH��6'�6�&�������ǀt6�~���������j�v�D���t�v�!���j�v����낋~����t��������j���'�^��6'�6�&�{������$tT��N��'*����6'�6'�T��#�t1�~����������>2'�u�F�2'��2';F�?�t�]��e��~����t���������j�K��~�u
�~��Er����>2'�uj�6'�6�&��
������!uT�6'�6�&��
������!u>�~����������v�����t�F�2'j�v����d�j
�v���������F�=��t�vh��A
���~�����~����drj��j�Ƌ~����t���v��{��_^�VW�
�~�狅"'�F��~��E �F��Er*�=v������.��F�X��333��v�!����t�'j�v�4���~��Er�j�v����v����u��~����t����������v����F��~��E �~��E�F�%�F��F��t�F��F�"�F��~�t�v�����~��E
�UDT
�	�~��E
�U�~��E�U
�~��}u	�~��E(��~��E*�~��E�E�U
��������~��E�E�U
��������~��E�E�U
��������~��E�E�E�E�E�E�E�E
�v����~�ƅ�ƅ�ƅ��Er�|�'�t�2';Ft�>2'�uZ�F�2'h��6'�6�&����~��Er�:�2';Fu�2'���v������u�t��~��j �6'�6�&�b���~��Erj(�v�w���_^�VW��F�j �6'�6�&�1���'*�P�6'�6'���j0�6'�6�&�
���F��~��}:�6'�6�&�
�����ǀt�F���F������=��t�j �6'�6�&�����F��_^�VW��F���N��'*��P�6'�6'���h��6'�6�&���h�N���tPh��6'�6�&�h��h�0���t2�~
th��h��6'�6'�?��h��6'�6�&�.���F��F��_^�VW��F�h��6'�6�&���h �����th��6'�6�&��
���F��F��_^�VW��~�狅"'�F��~������������������'�vh��v
sP��
���_^�VW��~�狅"'�F��~����t�����������������v������_^�VW��~�狅"'�F��~��E �F��E���Eƅ��_^�VW��~�狅"'�F��~��E �F�����~����
su�F
=v�����.����������~�����~����s�Erj�v�������~��Er�z�~��Er�q�~�����~����r��Er�Z�~��Er�Q�~�tB�~��M�E%�P�E��%�Ph�&����~��u�u
�}uh�&�h�&h�&�h���v����_^�VW��~�狅"'�F��~��E �F��F��2';Fu�2'���~����������~�t5�~��Eu�m�~��Eu�}u�~��E �v�����F��~�te�~��Erƅ�ƅ�ƅ��E�U
�E�U
��������~��E�E�U
��������~��E�E�U
��������~��E�E�E��'�~��Er�v����_^�VW��F�F��F��~�|�F��~��烽"'t*�~��狽"'�}ru
�v��	���t�v�h�����F�;Fu��_^�VW��~�狅"'�F��v�W���F��~�tQ�~��E=u�Erj2�v���@�~��}u�}u�v�U����)�~��E=uj��~��E=uj�j�v�7����_^�VW��F��F��F��F��F��F����F����Q�F��F�P�����u�3�~�u�*�6'�6�&����%�F��F�*�P�m��=w�����.����```_````�``��6'�6'�w���F��t=u�j`�6'�6�&����m�j�6'�6'���h����6'�6'�5���F��D��F�;F
s3�~��F�~�*�P�6'�6'�C���F�;F
t���v��a�����F����F�;Fs��~��F�~�6'�6'���������F�;Fs��6'�6'�~��F�~�*�P�F��v�����~�u�~�t�~�u�F��F��_^�VW����F�h��6'�6�&���j2�(��j �6'�6�&���j2����v�����_^�VW��F��F�;F}�F��~�0u}�F����F����_^�VW��F��^�F��F��~�|��6�F��~��t	�v
����v�v
�V���un�v
�F���v�v
�V���uU�v
�����t!j2�d����v
����v�v
�V���u'����v
������v�v
�V���u�F��i��F��v�����F��_^�VW��F�F��>'t�f���Ft�N��Ft�N��F�*��_^�U��WV�v�ށ��~������uHu������^_]�U��WV�v�~�߁����&���uHu������^_]�U��WV�v�~�N�^_]�VW��~~2kFP�6����6'�t�F�kFP�66'����F�4'��F��F��_^�VWU���4'�>6't
�66'�S���_^�VW��F;4'}dkF6'�F��s�F��~��}u�F
�E�+��~
�E��'�~��}�F
��~
��~��E�~
�E�F
�~��E�~��E�v��$���_^�VW��F;4'}kF6'�F��~���+��_^�VW��F;4'}[kF6'�F����F��~��}~1��F��E=u	+��E���~��=��~���=�E�~��M��F��v������F��F��_^�VW��v
�F��k�F�jj�v�����>uejjj�v����F��tF�^�����U�u/�F��~�}j�F�����P�ƃ�P�D���F����F��v��W���v�X���v������F��_^���`���`�VWU��N�	�v
�~��F��]_^ø�`���`���`�U���v�v�P�S��]���`���`�WU���~+�&�]_�WU���~&�]_���`������`�[XS�`[SSø�`���`�VWU���_^���`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�j����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^�WU���~�F&�]_�WU���~�F&�]_ø�`��X��X[SSP�X��X��VWU��v�~t�~
jjjVh����
�+��������D�F�D�vh�v
Vh�{���
W�����_^���`���`���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy

c�����"
���"�Error - host failed memory test
Error - ss has no valid target id's
Error - ss can't allocate structs
bad LUN or SCSI idbad special partitionbad partition tablepartition exceeds drive capacitypartition not foundinvalid requestno partition tablepartition overruninvalid byte countSCSI ID %d  LUN 0
Not Direct Access DeviceInquiry FailedCapacity=%ld blocks  Block length=%ld
Read Capacity FailedPhysical:  cylinders=%ld heads=%d spt=%d
Logical:  cylinders=%d heads=%d spt=%d
Mode Sense Failed(%d,%d): %s error bno=%ld
readwriteKdopen_free_j"Ksleep_main_Kukcopy_Kkucopy_sscon_h$ss_getb_:clrivec_<#Kioreq_Kfree_uexit_$SS_INT_�$Kdefend_kclear_�"Kclrivec_setivec_�"sphi_�#ldrvipc_u_ldrvics_drvl_ldrvcon_Kuexit_dclose_"nulldev_�"drvn_timq_ldrvsel_Kkclear_blkmv�!Ksetivec_xcalledbread_"splo_�#bufq_wr_tail_ ss_putb_jffbyte_H"con_Kldtimcall_bufq_init_�ldrvint_brelease_
"CSR_OFF	bufq_rlse_�Kdclose_devmsg_4"defer_"ffcopy_�cprocp_kcall_�"timeout_�#ffword_Z"bdone_�!Kbread_G01Pptov_�"REQ_LIM	�G02SG03_alloc_�!ucs_G04bsfbyte_�#wakeup_4$Kbrelease_RS_REQUEST	spl_�#Kdevmsg_vrelse_*$fdisk_2!Ktimeout_P01�Kbdone_P02�printf_�"Kptov_P03�allkp_bufq_rd_head_� ldrvpsy_P04�sfword_�#Kalloc_dopen_>"getcs_t"Kwakeup_sleep_�#NSDRIVE_�$drv_parm_�$kucopy_�"ukcopy_ $Kvrelse_bufq_rm_head_� Kprintf_KldeferBSIZE	ss_mach_SS_BASE_�$ioreq_x"0'&'$$*0-05'?'J$Q0T0\'b&$e'h&$k'o& q'u& w'~'�P'�'�&'�='�'�&'�&$�0�'�1$�'�&'�&'�'�'�''=0'#'-'4
07'J0_0p0�$�$�'�$�$�$�$�$�0� l$ n$ p$ r$ t$ v$ x$ z$ |$ ~$ �$$�%%0%%%#%'0/%8%<0G%P%T0e%n%r0�%�%�0�%�%�0�%�%�0�%�%�0�$�0�$ 
0 % ' )%,%0%9%=%@%D%M%Q%U%[%_%h%l%o%s%|%�%�%�%�%�%�%�%�%�%�%�%�%�$�$�$�0�'N0%$"%.01%=$O%k s$w0z%�0�%�$�0�%�%�%�0�0�%�%�0�$�0�%/$O$V'Z0b0h$y0�$�0�$''+0/$K'O0S'W%|'�%�0�%�0�%�'0$$/$>0O0i$y$�$�%�$!050<$C$�$�0�0�0�0�%� � �0�%	 	0	0	0	0&	0)	03	0=	0F	%J	%N	0Q	0c	 t	 v	 x	 z	 |	 ~	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	%�	%�	0�	%�	%�	0�	0�	%�	%�	0�	%�	%�	0�	0�	0�	%�	%�	0�	0
0
%(
 @
0C
%j
%n
0q
%�
$�
$�
0�
 �
0�
$	$00  *0-07$�0�$�00 00%$p0s$0�$�0�$�$�$�$�$�$�0�$�$�0�$�$
0
$

0
%)
0g
0q
0z
%~
%�
0�
0�
0�
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
%�
%�
0�
 �
0�
       ! #%4%80;0A%G%K0N%Z%^0a0m%�%�0�0�0�0�0�0�0�%�%�0�0%%#02080D0a%}%�%�0�0�0�00 + C E G0y0�0�0�0�0�0E0Q0j$�%�%�0�%�%�%�0�%�%�0�0�%�%%0	%%00#%<%@0C0L%e%i0l%u%y0|0�%�%�0�%�%�0�%�$�%�%%%"0(0A J L N P%T%X0[0}0�0�%�0�%�%�0�%�%�%�0�%%%0 0'0*0F0V%Z%a%e0h%w%{0~0�0�%�0�0�0�0�0� �0�0�000%"0; D F H J L N P R T V0\%g0q0~0�0�0�0�0�0�0�%�%�%�%�%�%�0�%�%�00
%%00.%F%J0M%S%Z%^0a%j%n0q%�%�0�0�%�%�0�%�%�%�0�%�%�0�0%%00%8%<0?%I%M0P%q%u0x0�%�%�0�%�%� �0�%�0*%@%n0� � � � � � � �0�0�$0"$7$<$?0B0K%a%u%~0�%90H%r%~0� �0�%�0�0�0�0(0[0e0o0x%|%�0�0� � � � � � � � � � � � � � � � �%�%�0�%�%�0�0�%�%�0�%
%00%4%80;0I0O0U0]%r%v0y0�%�%�0�0�0�%�%�0�0�%�%�0�000N0_0b0q0�0�0�0�0�0�0�0�%'�N0�%�%�0�%�% % % 0 %) %3 09 0� %� %� %� %� 0� 0!0A!0N!'U!0d!0�!0�!0�!0�!'�!S'�! '�!I'�! '"6'" '"A'" '"-'" ')"_0-"'5"D'8" '?"'B" 'k"
'n" 'y"	'|" '�" '�"'�" '�"'�" '�"^'�" '�"L'�" '�"'�"'�"'�"'�"'#='#'
#)'#0#'#')#'4#'N#'R#='X#'_#0b#'m#'w#'�#'�# '�#G0�#0�#0�#'�#''$G0$0$'$'$ '!$'$$ '+$\'.$ '5$V'8$ 0707070064030114621006660000030000030000011777770507310762300003700000014471/newbits/kernel/USRSYS/ldrv/dg�`:���v�v�v�Ѓ��VWU����6�t�;�V��P��
���P�E����.�.��؃�u���ヿtV��P��
��+�P���������������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P��P�Q����G$t�>�u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�
������LJ����LJ�ϸP�	��+��G��}5���㋇�F��~�t��t	�ȋ^��G;�u+�PPPS�
���ҋ^����+�P��
����]_^�VWU��>�t
�v
�v�����>u��]_^�VWU��>�t
�v������u
��P�
��]_^�
VWU��P�O	P�6��+	����������������P�PR�6�������P�6������P�:���6�����F��F��%=u���s�P�6�����6��c���F��F��%=u�
�F�4
P�x���P�6��`���dP�����6��"��%=t�>6t�D
��
P��ոP�6�� ���c
P� ���Z�P�6�6������<P����RP�����Z�P������RP������<P������RP����6�6�m��=Z�uN����RP�S��=�<u4������RP�9��=Z�u������RP���=�<t�w
�!��
P�S���P�6��;���@��
P�5����]_^�VWU��>>t�>+�P����RP�����P�6������6��~���6�6�E��]_^�VWU���F�t#�>8t�'�7�>@t+�8�<�"�F@t�>:uփ>Bt�:���]_^�VWU���F�t&�8�><uB�7�t;�@�B��
�#�F@t#�:��t�B�>��
P�*��]_^�VWU��v
]_^�VWU��P�v
�F�t7V�����F��|_�><}WP�<����RP����<���F@t/V����F��|!P�<� ��RP�y���<�ы�]_^�VWU��P��P�v�P���+�P���P+�P�P�c��]_^�VWU���6�P��P�v�&P�I��]_^�VWU��F�6]_^�VWU��+�P����RP�����P�6�������P��������RP���=GDt�>6t�P����+���
P�0��Ÿ#P����]_^�VWU��P�P��@��RP�}����P��B��RP�d��+�P��D��RP�L���P��F��RP�3��+�P��H��RP���� P��J��RP����
P�6�����P�6������dP������@��RP����t�>6t
�7P�������
P�)��ǸXP����P��@��RP����P��B��RP�j���P��D��RP�Q��+�P�� 
��RP�9���
P�6��9���P�6��+����P������� 
��RP����=OSt?�>6t/�{P�����@��RP���P��P����+����
P�=�뤸�P������"��RP�Y���D�P����RP�����
��RP�:���F����P�F����RP�I�����P�F����RP�+���F�%�P��
��RP����dP�����F�>Ft �>6t
��P�������
P�[����ٸ�P�������]_^�VWU�����
��RP�u���F���
��RP�]���F���
��RP�E���F���
��RP�-���F��>>u����
��RP�������
��RP����;�u����
��RP�����F��F��~�}3��~�F�؋ʋF������RP����E��F��NJF�*�P�F�*�P�F�*�P�F�*�P�P���
�F�%�P��
��RP����3��>Ft1�F��
��RP�1��P��
��RP�K����]_^�WU���~+�&�]_�WU���~&�]_�����܋W+�����`�[XS�`[SS�VWU��]_^��܋W�G�ø�`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�s����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P�&�������Dž����Dž]_^�WU���~�F&�]_�WU���~�F&�]_ø�`�VWU��v�~t�~
+�PPPV�P����
�-�M�����D�F�D�v�P�v
V�P����
W�*��]_^���`���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
N���Error - board type is PC/Xi
Error - board type is PC/Xm
PC/Xe ID found
Error - PC/Xe failed to reset
PC/Xe passed reset
Error - PC/Xe failed memory test
PC/Xe passed memory test
PC/Xe waiting for BIOS load
PC/Xe waiting for FEPOS load
PC/Xe ready for use
Error - PC/Xe BIOS won't start
PC/Xe BIOS started
Error - PC/Xe FEPOS move failed
PC/Xe FEPOS relocated to host RAM
Error - PC/Xe FEPOS won't start
Failure code (%x)
PC/Xe FEPOS started
Error - PC/Xe no FEPOS interrupts
PC/Xe interrupts working
%x %x %x %x
Ksleep_main_clrivec_�uexit_�Kdefend_Kclrivec_setivec_:sphi_�ldrvipc_u_ldrvics_drvl_ldrvcon_inb_�
Kuexit_nulldev_outb_drvn_iogetc_�
timq_ldrvsel_Ksetivec_xcalledffbyte_�
con_Kldtimcall_ldrvint_DG_IOB_�Kiogetc_cprocp_kcall_timeout_*ffword_�
ptov_0DG_RAM_�dgcon_�ucs_sfbyte_�wakeup_�spl_�vrelse_�Ktimeout_printf_&Kptov_ldrvpsy_DG_INT_�sfword_getcs_�
Kwakeup_sleep_ Kvrelse_Kprintf_0''%$-010; E'K'V$]0a0j'p$s'v$y'} '� � �'�'�,'�'�'�$'�'�'�$�0�'�$�'�'� �'''',
'0$06'A
'K'R0V'l0x0�0�$�$�'�	$�$�$�$�$�0� � � � � � � � � � � � $
0
$$%#%'%407%=%A$I0L0V$]0`$u0x$�0�$�0�$�0�$�0�$�0�0�$�0�%�$�0�0�$�0�$0%%0% %$0/%9%=0H%R%V0a%h%l0o%z%~0�%�%�0�%�%�0�$�$�0�$�0�%�$�0�%%%%0$*0-$407%>%B0E%\'c	%j%q%w%�%�%�'�	%�%�0�%�%�$�%�0�%�%�$�0�0!%/%7%<%@0K%R0_%m%r%v0�%�%� �%�0�%�0�%� �%�0�%�%%0$00'%-%10<%H$N0R0`$e0i%�%�0�%�%�0�%�%�0�%�%�0�%�%�0�%�%�0
$0$#0&00%6%:0E%P$V0Z0`0g$l0p%z%~0�%�%�0�%�%�0�%�%�0�$�0�$�0�0�%�%0%$ 0$%*%.09$@0D0L0S$X0\%b%f0q%w%~%�0�%�%�0�%�%�0�%�%�0�%�%�0	0
	%	%	%	$$	0(	0.	05	$=	0A	%X	%\	0g	%p	%t	0	%�	%�	0�	%�	%�	0�	%�	0�	%�	%�	0�	%�	%�	0�	0�	%�	%�	0
%*
%.
0=
$c
0g
%w
%{
0�
0�
%�
%�
%�
%�
0�
%�
%�
0�
'�
''
''3'*'1+'4'A	'P
'\'c	'r'z$'~
'�'�0�'�	'�'�
'�
'�$'�	'�0�'�'�
'!'$'E)0I0Q0V'e'm)0q0x'�'�'�2'�'�0'�0707070064030114561006440000030000030000011777770507310762400004300000014732/newbits/kernel/USRSYS/ldrv/hs.310L�����v�v�v�Ѓ��VWU����6�t�;�V�RP�
���P�����.�.��؃�u���ヿtV�dP��	��+�P�����N��P������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P�LP�;
����G$t�>Lu܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�	������LJ����LJ�ϸP���+��G��}5���㋇�F��~�t���ȋ^��G;�u+�PPPS�	���ҋ^����+�P�Q
����]_^�VWU��>Nt
�v
�v�N���>u�L]_^�VWU��>Pt
�v�P���Lu
�LP�M
��]_^�
VWU����v.�&�P�6����� 
�u
�
P������v.�&�P�6 
�����F��F�;v|���^����㋿x.�.� 
��+�P��P����+�P��@P�����@P����t��a��\�D��D��^����㋇z�D��D���(���)�|��)����㋇��F���P��P�S���v�W�I���F����P��@P�7���P��P�'���6"
�F��+���]_^�VWU���6 
����]_^�VWU��P�F%.�.� 
���|t�D@P���������t�����t�'�r�D�D=uZV����F�t;�~�F��DP�g�����L ��t�d���� t�L�v��O���
�d���LV�&���vV�����N��]_^�VWU��P�F%.�.� 
���|uQV�g���F��~�t?�$
P�BP�
P�$
P����+�PP�P�$
P������Z*�:�[uƃ~�t��N���L����]_^�VWU��v
+�PV�F%.�.� 
P�5��]_^�VWU��v
+�PV�F%.�.� 
P�7��]_^�VWU���v�v
�F%.�.� 
P����]_^�VWU���v�v
�F%.�.� 
P���]_^�VWU��P�v��X*�:�Yt2��Y*�ȋ�ي�Z*�PV�`����Y*�=�rƄY����Y�¿���Z*�؊�[*��+���Ǚ.�>���O|9V�;���F��|+��Z*�ȋ�ًF���\��Z*�=�rƄZ����Z��V�4���|tV�P�
P��HP�^����]_^�VWU��P�6 
�|u��DtL�DP�������t7��t��t�d����L ��t�� t�L��d��V�T���DP��������t�Dt�PV�}����t:��X*�ȋ���F��t����^���Z�Dt��X��X*�=rƄX�� tC�D u<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�h����[��[*�=rƄ[��^��;"
w�����]_^�VWU��P�v��F�+���)t��W�DP�����)����㋇����t-��P�DP����W�t�����DZ��P�D@P������,%�=t=t���
��W�DP����P�D@P����v��u�����]_^�VWU��v�Z���DP�D������ t<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�>����[��[*�=rƄ[W���]_^�VWU�����6
�6
;4
|�6
�6
]_^�VWU������t��F��F��F�;v}B.�.���> 
�}t,�F�.�.���> 
��(����狅��F��F�;F�}�F��F��F�뵋F�;t/��.�>��4
���&���~�t�P�6������]_^�^d��`�VWU����~drm�F+�.�6�	�u_�F+�RP�P��4P�����F����F��6P�CP�����F�%�P�@P�����F����P�@P�����v�����F���F����F���]_^�VWU����v�i����F��u��F��F
��X��v��o���F���]_^�VWU�����F��~�t#�dP� ����>�F���P�/���F���]_^�d�����`�����܋W+���[XS�`[SSø�`�VWU��]_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�s����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P�&�������Dž����Dž]_^���`��X��X[SSP�X�VWU��v�~t�~
+�PPPV�P�����
�-��������D�F�D�v�P�v
V�P����
W����]_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
����
3�*
l��*
*
� �	Y@��`@:0 dddddddd�,��X �@hsload: can't allocate tty's
Kttstart_ahigh	
free_�	bhigh	Ksleep_Kttopen_main_ttsignal_�clrivec_�
Kttpoll_hscycle_hsparam_�Kfree_uexit_�Kttsignal_hsclose_�altclk_in_y	Kdefend_kclear_ 
altclk_out_�	setivec_H
Kclrivec_sphi_ldrvipc_tthup_�u_hsioctl_�hsread_lldrvics_poll_hz_�drvl_ldrvcon_inb_

cs_sel_�	Kuexit_nulldev_*
outb_4
drvn_altclk_timq_ldrvsel_Kkclear_ttsetgrp_�Ksetivec_xcalledttclose_zttin_�Ktthup_ttout_�con_Kldtimcall_poll_owner_poll_rate_ldrvint_ttioctl_�ttread_�altsel_vldiv�hswrite_�cprocp_kcall_
timeout_"Kttsetgrp_Kttclose_hsstart_�Kttin_Kttout_HSNUM_valloc_�ucs_vrdivhsopen_3wakeup_BKttioctl_Kttread_spl_Ktimeout_HS_PORTS_xhspoll_�ttwrite_�printf_>
alow	allkp_ldrvpsy_blow	Kalloc_ttstart_�getcs_
Kwakeup_hsintr_�sleep_
ttopen_�hscon_�L0L1Kttwrite_Kprintf_L22ttpoll_�L380'1'%%$-010; E'K'V$]0a0j'p1$s'v1$y'}1 '�1 � �'�'�S'�'�1'�E'�('�1'�1$�0�'�;$�'�1'�1 �'''(','0E06'A'K'R0V'l'0x0�0�$�$�'�$�$�$�$�$�0� � � � � � � � � � � �$ 'R0%$!0%0+$. 3%80;$J0O$Z _%c0q0~0�0�0� � �$�$�0�0�0�0%0%'0* B%F0V'e0i'm3'u0�0�0�0�0�0�0� %0%" &%.02%@0D0d �%�0� �%�0� �%�0� �%�0�0, f0o0� �0�%�0�0�0.0;0U0s0�%�0�00$-0A0K0]0�0�0�0�0�0�0�00%"%%%)%/%4'D30K$\ c%i w%}$�'�4'�4 �%�0�'�3 �'�40�'�3'�U'�, 	0	0%	03	0D	0V	0_	0�	0�	'�	&0�	'�	80�	'�	&0�	0�	'�	&'�	80�	'�	'
,'
,'!
)'$
,'?
`'B
,'O
'^
'j
'q
'�
'�
E'�
'�
5'�
+0�
'�
'�
'�
'�
'�
E'�
'�
0�
'�
''','=L0A0I0N']2'eL0i0p'{?'~,'�/'�,'�A'�,'�I'�,'�'�,'�B'�,'�	'�,'�J'�,'�>'�,'�'�,'�'�,'�_'�,'�"'�,'CX'F,0707070064030114531004440000030000030000011777770507310762600004000000017075/newbits/kernel/USRSYS/ldrv/msg,��i���v�v�v�Ѓ��VWU����6�t�;�V�2P�Q���P�����.�.��؃�u���ヿtV�DP�!��+�P�Z����.��0������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P�,P�����G$t�>,u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W��
������LJ����LJ�ϸP����+��G��}5���㋇�F��~�t���ȋ^��G;�u+�PPPS��
���ҋ^����+�P�%����]_^�VWU��>.t
�v
�v�.���>u�,]_^�VWU��>0t
�v�0���,u
�,P���]_^�
VWU��>pu��>pu�]_^�VWU��v�F
-M=v������.��<Dv���DP����P�DP����P�DP���P���PV�����DP���P�DP���P�DP���P��̍DP�s��P�DP�h��P�DP�]��P�DP�R��P���뛍DP�?��P�D
P�4��P�DP�)��P�DP���P�DP���P�DP���P�����P��]_^�VWU���
�>xu�t�>zu�t�>tu+���>t�v�t��P�
P�x+�RP�q���F��V��P�:P�t+�RP�V��F�V��F��V��~�	|�~�@v
�|P��
���$�F�P�6�;
���p�u���F�P+�P�6p�X
���t.�.:
p�r�z+�RP�xRP�����F��V��~�|)�~��v#��P�g
���6p��	���t�p���P�v��v��R
���
�>
u�6x��P�&
��뽋6p�F��F�;ts!����D
�D*�D.�D,�D2�D6�D4�F���:�֋6p�x.�.<
r����
��;rr/�z+�)F�V��F��E�D��|���6t��P�	���t��]_^�VWU��P�~~�F�.�>>
;ts�>pu������F�.�>>
.�.:
p���t��D�tփ~
t�D
;FuȋF
=v�����.��Vk�\V��������u�
��*P�vV����|,t*�΃�*�D,;�t�FP�y��
P�FP�����|4t*�΃�2�D4;�t�FP�I��
P�FP����D
;Fu�,��$�>t�;t���FP����F��>t���>t;Dw��v������F@@P�����D�d��FP���%�	D�F��D��>t�;u��D���t��D�p�G����p�Gt�g��S�k	���p�0t
�p*P����D�D�D�D
%�=�u�d
�D
�DtV�$	���|0t
�D*P�z���|8t
�D2P�j���D�>t���+���]_^�VWU��P+��>pu����>pu���F%��F��t.�.:
p����:��;pvg�D�u�t�E&�U(;T(|�;D&v؋��ԋFF
t̋F�V
;Tu�;Du��Ft�Ft������D#F�;F�u��
���Fu��׋Nj��u����D�D�D�D�v�D�D�D�D�D �D"�D$���D&�T(���D��D�D�F�
��D�F�V
�D�T�D
��]_^�VWU��~~�F�.�>>
;ts�F;zw�>pu�����e�F�.�>>
.�.:
p���D
;Fu��D�t�V��������u�
���p�t�D;Dwi�Ft�롋D;Dw�L+�PP�PV��p�O+�PP�PS�D����G$G&t��t��V��F;D
t��!�F��p��F�E�P�EP�v
�g���v�
�w�u�F
P���;Ft��>t�����p�G��|t�\�?��|�|�FD�D��G�D���D�T �Dt�d��V�*���|0t
�D*P���+�]_^�VWU����~~�F�.�>>
;ts�>pu�����B�F�.�>>
.�.:
p���D
;Fu��D�t�V��������u�
���|�F��~y~�F��F��F�V���؃��F�V�t?�E�U;V|;Fv�~��=��~�t�^��E�U;W|�;Gsމ~��F��F��Ӌ~��F��F��F�V���؃��F�V�)�~x#u�~t�t�E�U;Vu;Ft�~��=���uQ�Ft�����L+�PP�PV� ����G$G&t���t�����F;D
u����!���F;Es�Fu����F;Ev�E�F�P�v
�EP����v�F
P�
�w�u���;Ft��>t�S��~�t	��^�����D;|u�F��D�E)D�L��G�D���D"�T$�Dt�d��V�����|8t
�D2P�B���6p�D��|�Dt�d��V����p�0t
�p*P����F��]_^�VWU��~~�F�.�>>
;ts�>pu� ��F�.�>>
.�.:
p���D�t�D
;Ft��m�f
���F
t"�|u�~t
�D*P����f
����F�F
t5�D;Dr�~t"�D2��>p�}u�~t
�p*P�E���f
���F
]_^�:
VWU��v�>u���/�;t;Du�D��;Dt;Du�D���D���%�]_^�VWU���FHFr(;w"��ۋv�~
�N��������F]_^�+�]_^�VWU���FHFr�;w��~�v�N��������F]_^ø�`���`������`�[XS�`[SSø�`�VWU��N�F
�~��F]_^ø�`�VWU���]_^�VWU��]_^���`���`���`���`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�%����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P���������Dž����Dž]_^���`�VWU��v�~t�~
+�PPPV�P����
�-����v��D�F�D�v�P�v
V�P�i���
W�d��]_^���`���`��Ë܋_��Ë܍_VWU��P�F�'����F�g��F
�'��֋�[��]_^���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
�fXXXffff	
�invalid NMSQID or NMSG kernel variable
invalid NMSG or NMSC kernel variable
could not salloc %u messages
could not kalloc %u message ids
timer_ahigh	
free_bhigh	Ksleep_main_Kukcopy_Kkucopy_clrivec_pollopen_pputuwd_�Kpollwake_Count	Kfree_ipcaccess_@
nonedev_Xuexit_�NMSC_zKdefend_nondsig_Nsetivec_�Kclrivec_sphi_Kputuwd_Kpollopen_ldrvipc_NMSG_xu_ldrvics_drvl_ldrvcon_Kuexit_msgs_rnulldev_fdrvn_msginit_$timq_umsgget_*ldrvsel_Knondsig_Ksetivec_xcalledsalloc_�msgpoll_zumsgctl_�con_Kldtimcall_NMSQB_vumsgsnd_eldrvint_msqs_pudl_umsgrcv_
msgcon_Vcprocp_kcall_ timeout_nKsalloc_alloc_�
memset_6ucs_uds_NMSQID_twakeup_spl_"getuwd_vlmul�Ktimeout_printf_�alow	allkp_ldrvpsy_blow	Kalloc_ufcopy_�
fucopy_�
getcs_vrmul�Kwakeup_String	sleep_dKgetuwd_kucopy_,ukcopy_�L0�Kprintf_Char	
pollwake_z0'-'%"$-010; E'K'V$]0a0j'p-$s'v-$y'}- '�- � �'�'�G'�'�-'�<'�&'�-'�-$�0�'�6$�'�-'�- �'''&','0<06'A'K'R0V'l$0x0�0�$�$�'�$�$�$�$�$�0� Z \ ^ ` b d f h j l$0$'01 : < > @ B0I0T0_0f0n0t0{0�0�0�0�0�0�0�0�0�0�0�0�0000'$.$5$;$B$H0P$T$\$i0p$�0�$�0�0�'�F0�$�0�$�0�$� �$�$�$�$�0�$0$"0%$,$2070D%J%N$U$X0\$e$q$�$� �$�$�$�$�$�0�$� �$�$'0  !$%0K T V X Z0^'m0q0|0�0�0�0�0�'�0�'�'�'00'0"'&040B0W0i'm's$�$�0�$�$�0�0�0�0'0 $40:$>'E0I$U Z$^$i'�0�0�'�'�'�$'*'.'7'? w${$�$�'�0� � �$�0�'�$�'�$
	0	'%	600	'8	0<	'H	0L	$P	0g	%q	0�	'�	'�	0�	$�	'�	6'�	'�	0�	0�	 
$
$"
')
00
 9
 >
$B
0W
'f
'-010B'I60T'\0`0k'o0s'�0�0�%�0�'�'�0�'6''0&06$=0U$\$e0l �$�$�0� � �$�0�$
$"
0)
'J
'U
'f
'�
3'�
='�
3'�
='�
I')'	
')'Q')'$)'-'0)'O''R)'_'q't)'{'~)'�U'�)'�'�)'�9'�)'�'�'�'�'�'�<'�'�1'�(0�''''1'5<';'B0F'Q'['e'h)'�C0�0�0�'�.'�C0�0�'�'�)'�'�)'N')0707070064030114521006660000030000030000011777770507310763000003700000005560/newbits/kernel/USRSYS/ldrv/qq�D
�$���v�v�v�Ѓ��VWU����6�t�;�V��P�����P�;����.�.��؃�u���ヿtV��P����+�P���������������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P��P�G����G$t�>�u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�������LJ����LJ�ϸP����+��G��}5���㋇�F��~�t���ȋ^��G;�u+�PPPS����ҋ^����+�P������]_^�VWU��>�t
�v
�v�����>u��]_^�VWU��>�t
�v������u
��P���]_^�
VWU�������P�P�6��6��������]_^�VWU���6��6��B��]_^�VWU��]_^�VWU��]_^�VWU��P�v
�|t8�����RP�u���F�VP���=��t�����.�>����‹�]_^�VWU����v
�F�V�J���F��|"�~�}P�F����RP�'���F��Ћ�]_^�WU���~+�&�]_������`���`�[XS�`[SS�VWU��]_^���`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�}����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P�0�������Dž����Dž]_^�WU���~�F&�]_ø�`�VWU��v�~t�~
+�PPPV�P�����
�-�M�����D�F�D�v�P�v
V�P����
W�*��]_^���`���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
GP$Y�$$$�0$qqcon_�Ksleep_main_clrivec_�uexit_xKdefend_setivec_BKclrivec_sphi_�ldrvipc_u_ldrvics_qqclose_Pdrvl_ldrvcon_Kuexit_nulldev_$drvn_iogetc_timq_ldrvsel_Ksetivec_xcalledqqread_Yffbyte_�con_Kldtimcall_ldrvint_Kiogetc_cprocp_kcall_timeout_ ptov_8ucs_qqwrite_�sfbyte_wakeup_�spl_�vrelse_�Ktimeout_printf_.Kptov_qqopen_Gioputc_ldrvpsy_getcs_Kwakeup_sleep_Kvrelse_Kprintf_Kioputc_0''%$-010; E'K
'V$]0a0j'p$s'v$y'} '� � �'�
'�,'�'�'�!'�'�'�$�0�'�$�'�'� �'
''','0!06'A'K	'R0V'l0x0�0�$�$�'�
$�$�$�$�$�0� � � � � � � � � � � �%%%%0 %&%*%7%;0>%i%n%r0w0�%�%� �%�0�%�%�0�'''2'''/1'2'9)'<'I
'X'd	'k
'z	'�!'�'�'�0�'�
'�	'�'�'�!'�
'�0�'�	'�''';'0?0G0L'['c'0g0n'y'|'�0'�'�.'�0707070064030114501006660000030000030000011777770507310763100004000000011345/newbits/kernel/USRSYS/ldrv/shmn	l�����v�v�v�Ѓ��VWU����6�t�;�V�t	P�����P�	����.�.��؃�u���ヿtV��	P���+�P������p	��r	������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P�n	P�����G$t�>n	u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�c������LJ����LJ�ϸP�z��+��G��}5���㋇�F��~�t��J�ȋ^��G;�u+�PPPS�e���ҋ^����+�P�����]_^�VWU��>p	t
�v
�v�p	���>u�n	]_^�VWU��>r	t
�v�r	���n	u
�n	P�a��]_^�
VWU��>�	ta��	.�&v��W�6�����u�6�	��	P������	�/��	.�.x���	.�.x����&��;r�D��+�]_^�VWU����v
�D�F��D�F�;�	r������F�.�.x���E�u�!��W�C������u�
�ȋE��F�V��F�+ҋ؋ʋD��;V�w�r;F�w��^�����G�F��F��F��t�t�v�P�o���u�o��D+���]_^�VWU����v
�D�F��D�F�;�	r������F�.�.x���E�u�!��W��������tʋE��F�V��F�+ҋ؋ʋD��;V�w�r;F�w��^�����G�F��F��F��t�v�P�t�{���u�v��D+���]_^�VWU��F
=CHt=GHt8��x�FP����P�FP���P�F@@P���P�U���=�FP���P�FP���P�FP�x��P�F@@P�k��P���P�v���]_^�(&VWU��P�F��>t������F;�	r���F.�.����D�t�F
=v�����.���E��V�'������u�
른&P�vV�����F��|�>t�;t��b�v�����F@@P����D�d��FP���%�	D밃>t�;u��D
�~��>�5�|���D���F����F���]_^�VWU��P�F��>t����Z��	.�.�����&��;s��D�u �~�t�~��E"�U$;T$|�;D"vЉv��ˋFF
tËF�V
;Tu�;Du��Ft�Ft�늋~����D#F;�t�
�q��D;Fr���^��Fu��O��~�u��A��v���+�.�>�����>�@P�F+�RP�����tʋF�D�D�D�D�D ���D"�T$�>�E�D���D��D�D�F%�
��D�F�V
�D�T�FF
u�L��+�.�>���]_^�&VWU��v�>u���/�;t;Du�D��;Dt;Du�D���D���%�]_^�VWU���FHFr(;w"��ۋv�~
�N��������F]_^�+�]_^�VWU���FHFr�;w��~�v�N��������F]_^ø�`������`�[XS�`[SSø�`�VWU���]_^�VWU��]_^���`���`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�[����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P��������Dž����Dž]_^���`���`�VWU��v�~t�~
+�PPPV�P����
�-�C�����D�F�D�v�P�v
V�P����
W� ��]_^���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
���q,�����couldn't kalloc %u shared memory ids
timer_Ksleep_main_Kkucopy_clrivec_�putuwd_
ipcaccess_�nonedev_�uexit_L	Kdefend_setivec_Kclrivec_sphi_`	Kputuwd_ldrvipc_u_ldrvics_drvl_ldrvcon_Kuexit_nulldev_�shmsegs_drvn_timq_ldrvsel_ushmget_�Ksetivec_xcalledsalloc_ushmctl_zcon_Kldtimcall_ldrvint_NSHMID_�	udl_cprocp_kcall_�timeout_�shmids_shmcon_�	Ksalloc_alloc_�ucs_uds_wakeup_V	spl_d	getuwd_�Ktimeout_printf_allkp_ldrvpsy_sfree_�Kalloc_fucopy_�ufcopy_Dgetcs_�Kwakeup_sleep_�Kgetuwd_kucopy_�Kprintf_Ksfree_0''%$-010; E'K'V$]0a0j'p$s'v$y'} '� � �'�'�2'�'�'�*'�'�'�$�0�'�#$�'�'� �'''','0*06'A'K'R	0V'l0x0�0�$�$�'�$�$�$�$�$�0� �	 �	 �	 �	 �	 �	 �	 �	 �	 �	$$ '10' &$($+0/$6$= B'F&'I$L Q'U&'`&$�'�0� �'�&'�0�'�'�00$E'K0R Z'^&'k0r'�0�0�'�0000#020@0N0[0b0l'�0�$�'� �'�&0� � � � �0�'�0�'�''00#08'G'M']0b'p'�0�$� �'�&'�&0�''0 0+'/03'>0B'L0P'Y& _'g0u'�'�'�#'�'�'�& �'''"'V"'\+'�"'�+'�4'�'�:'�'�'�'�'�'<''
''(''%'4'@'G'V'^*'b'k 'q0u'|'�'�'�'�*'�'�0�'�'�'�='�'�'�'	/0	0	0 	'/	'7	/0;	0B	'M	'P	'W	8'Z	0707070064030114670407550000030000030000011777770507310763200004000000000000/newbits/kernel/USRSYS/ldrv/RCS0707070064030114651004440000030000030000011777770507310763200004600000022547/newbits/kernel/USRSYS/ldrv/RCS/al0,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.17;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@��p#���v�v�v�Ѓ��VW��6�t;6|Vh����j�;��k�
��u���ヿtVh��b��j�������������k�
LJ����LJ�������>t
����P���jjhh�������G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�$������LJ����LJ��h�A��+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v��2���͋^����G�j�����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h������_^�VW��>pt�i^P�6�.���l�u�kP�6����j�u�xi^P�6l�U��kP�6j�E���E���p��>l�E��E�j�E�l��>j���E�>~0��>l��y���x�j��r�l^��>j�E��E�F��F�;|��iF�^��>l�E��F�iF�^��>l�}��F�j@@P�����F�@@P�t���uXj�F�P���h��F�P����~������v�����~��狅��P�F�@@P�o��j�F�P�`��iF�^��>l�Ed
iF�^��>l�E>iF�^��>l�
��\�F��&�h�j�1��V�����_^�VW��F��F�;}[iF�^��>l�}��F�j@@P��
��j�F�P��
��jjj��jiF�^lHP��P�4������F��j�+���6l�;
���6j�1
���_^�VWU��F%?;s:���~��?i�^lP����hn�~��?i�^lP�v
�v������_^�VWU��N��?i�^��>l�Mu(��
���~��?i�^lP�v
�v���V��
���_^�VWU��j�v
�~��?i�^lP�Z���_^�VWU��v
�<tjV�N��?i�^lP�X���|V�W�����|o�^��?i�^��l�_�P�'������ t؋^��?i�^��l�_�P�������� t�W�N��?i�^��l�_�7�"����_^�VWU��~��?i�^lP�v�v
�v����_^�VWU���v�v
�~��?i�^lP�[
���_^�VWU���6n����_^�VW��v�~�F%��F��\��F�@@P�N��������t���D�t
�e�u��F���ȁ��k�
��t�'���F@@t���u��F@@u��\�G����㋇=t˃|t��\�tjjh�DP���������F��F@@tj��\�G����㋇�j�F�P��
��j�F�@@P��
���F��t��L$�F�P�`
���F��F�*�\G�F��u`jjh�DP�W����G$G&t��]
�t��F�P�
��%P�F�P�R
��j�F�@@P�E
����v�������d����d���LV����	�,���!�,V����v���
���D�vV����F@@t�\�G�����LJ��g�\�G�����LJ�T�\�G����㋇=u�I��\�G��؁��㋇=t�c��+��F��u	�Du��
�Du�t���_^�VW��^�w�_�G�v�
���^�G�F��^��?�F��~�tU�^�GPh�j
�GP�
��jjh�^�GP��	���^��[*�F���Z*�:F�u��~�t��N���� uj��@@P������^�G$��@@tQ��P�g��%P��P����F��%��F�k^�
LJjjhkF�
P�H	��k^�
LJ��P���%��P��P�N���^�_�G�����LJ��^�_�G�^�GP�1
���_^�VWU��v�����k�
������=~�~�����k�
P��	���_^�VW��v����\��F�@@P�w���F��F�P�g���F��F�P�W���F��F
�,
�	CC.;��t��.�g��������q
�
�
�
R
i
�
�
�
�F�
@@P�F�P�K����F�%����F�
P�F��ߋF�%����F�
��F�%���ߋF�
�P�F�P����v�v������F��P�F�@@P�����v�늋N���F�%����w��F�P�{���F��F�*�\G�F�*����F�j�v�F�P�}�
�v�v
V�����F�*�P�F�@@P�~��W�Y���_^�VW��^�G�F��^��7�^��)��F���(�:F�t����^��(����㋇���u+�^�Gt!�g����P����%P��P����t}���F���@@P����F�h���P����WV��������P��@@P�����^��,%�=t	=tj�j�j
��P����F�*�P��@@P����v��b���[�_^�VW��v�Dtb�A�F��\�P����F��F�*�\G�v�����\�Gt-�G�%���|u	�DP�1��F��u��X*䈄YV�]����X*�:�Yt2��Y*�ȋ�ي�Z*�PV�A����Y*�=�rƄY����Y���F����Z*�Ȋ�[*�+�F��F��.�>&�V��N�|7V������|*��Z*�ȋ�ًLj�\��Z*�=�rƄZ����Z��V���Vh8j
��HP�G���_^�VW��v��F��\�P��������t
Vh�
����� t>��Z*�:�[t2��[*�ȋ�ي�\*�P�\�7������[��[*�=rƄ[�v�����_^�VWU��vjV�a���_^�VW��v�\��F��F�@@@@P�R��=v�����.��((>�>W>6�F�P�&������t�Vh�
������v��	�����|t���,@@u-�ρ���1�;�u�L 녋ρ���0�;�u�d���n���X*�ȋ�ًLj�Z��X��X*�=s�J�ƄX�B���Z*�:�[u�3��D t�)���[*�ȋ�ي�\*�P�v������[��[*�=rƄ[��[*�:�Zt���Vh8�'��F�P�4���\G����_^�VW��F��~�}"�~��狅=u�~����������F����t�t;r|�t�t�_^�VW����t��F��F��~�}:�~��狅=u'�~��狽��(����狅B�F��F�;F�}�F��F��F����F�;t.��.�>(�r���&���~�t�hB�6����_^�d��`�VWU��N�	�v
�~��F��]_^�VW��~dra�F+�.�6<�uS�F+�RPjh�4����F��
�F�j6jC�"���F�%�Pj@@����F���Pj@@����v������F���F����F��_^�VW��v�{����F��u��F��F
��P��v�����F��_^�VW���F��~�t!jd�8����n�F���P�_���F��_^�d���U���v�v�P�'��]���`�����܋W+�����`�[XS�`[SSø�`���`���`�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�`����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X���`�VWU��v�~t�~
jjjVh����
�+�������D�F�D�vh�v
Vh����
W�����_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy

.�������	���	Y@@��`@@:0 dddddddd�,��X �@@Kttstart_free_XKsleep_Kttopen_main_Kkucopy_al_sg_clr_ttsignal_Talxtimer_�	clrivec_>albaud_Kttpoll_Kfree_super_�uexit_rKttsignal_al_sg_set_altclk_in_�Kdefend_nondsig_�altclk_out_kclear_�Kclrivec_com_usage_alxstart_d
setivec_�sphi_�ldrvipc_tthup_u_alxopen_�ldrvics_drvl_ldrvcon_inb_fcs_sel_>Kuexit_Ksuper_nulldev_�outb_�drvn_altclk_iogetc_ptimq_ldrvsel_Knondsig_Kkclear_ttsetgrp_Jblkmv4Ksetivec_xcalledttclose_�ttin_Ktthup_ttout_,con_Kldtimcall_poll_owner_poll_rate_alxintr_�
ldrvint_ttioctl_ttread_@@altsel_vldiv|Kiogetc_defer_Bcprocp_kcall_ztimeout_�Kttsetgrp_alp_rate_BKttclose_Kttin_alxbreak_�
Kttout_alloc_*tp_table_ucs_vrdiv�wakeup_�Kttioctl_Kttread_spl_�C1BAUD_a0con_�Ktimeout_C3BAUD_ttwrite_hprintf_�allkp_ldrvpsy_alxcycle_8Kalloc_ttstart_^A0CNT_alxparam_>getcs_bKwakeup_sleep_�ttopen_"kucopy_�alxclose_JKttwrite_Kprintf_Kldeferttpoll_6alxioctl_�	0'7'$($*0-05'? 'J!$Q0T0\'b7$e'h7$k'o7 q'u7 w'~ '�['�!'�7'�N'�,'�7'�7$�0�'�C$�'�7'�7'� '�!'�,''N0'#'-'407'J+0_0p0�$�$�'�$�$�$�$�$�0� � � �      
  %�0�$�'�Z0�%0$'Z0%0!$%%,0/$6%<0?0E%K$N%R%\%b'eM%i$u${%%�%�'�M%�$�0�%�%�0�0�00$0%$10=0L%Z _%j o%z0}0� �0�0�$�%�0�0�%�0�00%0%"0%$;0@@%O0S%Y%h0r'{%�0�%�0�0�%�0�%
00%10=%Y0e%�0�%�0�%�0�%�0�0'%0)030:'M 'T0X'c90q'�0�0�0�'�M0�0�0�00)'0C0;0I0Z0g'n0u0{0�$�$�0�0�0�'�0�'�'�0'0"0%0?'C0a �0�0�0�0�0
	'$	 '4	 08	'C	 0N	0^	's	0x	0�	'�	 '�	 '�	 0�	0�	0�	0�	0
 
0(
 @@
 B
 D
 F
 H
 J
 L
 N
 P
0a
0g
0�
0�
0�
0�
0�
000.05'i0m$}0�0�0�0�0�0�0�00#0,020I0X0o0�0�0� 
0
0J
 Q
0[
0n
0}
 �
0�
0�
0�
0�
00 & ( * , . 0 2 40> M0P0[0�0�0�0�0�0�0 #0&000<'Z'hM0k%w%z%~%�%�'�90�'�'�M$�'�:'�: �%�0'9'9 ':0'+]'.2 d0w0�0�0�0�0�0�0�'�)0�'�?0�')00'#)')?0/'Mi0Q'Y'\2'qA't2'~2'�.'�2'�'�2'�-'�2'�h'�2'�'�'�'�'�'N''<'10''+'6'P'TN'Z'a0d'o'y'�'�2'�%'�2'�V0�0�0�'�8'�V0�0�'�H'�2'5'2'I'2'Q'2'#'&2'-K'02'7':2'AR'D2'KF'N2'U'X2'_'b2'ig'l2's$'v2'�b'�2@
0707070064030111301004440000030000030000011777770507310763400004600000022547/newbits/kernel/USRSYS/ldrv/RCS/al1,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.20;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@��p#���v�v�v�Ѓ��VW��6�t;6|Vh����j�;��k�
��u���ヿtVh��b��j�������������k�
LJ����LJ�������>t
����P���jjhh�������G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�$������LJ����LJ��h�A��+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v��2���͋^����G�j�����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h������_^�VW��>pt�i^P�6�.���l�u�kP�6����j�u�xi^P�6l�U��kP�6j�E���E���p��>l�E��E�j�E�l��>j���E�>~0��>l��y���x�j��r�l^��>j�E��E�F��F�;|��iF�^��>l�E��F�iF�^��>l�}��F�j@@P�����F�@@P�t���uXj�F�P���h��F�P����~������v�����~��狅��P�F�@@P�o��j�F�P�`��iF�^��>l�Ed
iF�^��>l�E>iF�^��>l�
��\�F��&�h�j�1��V�����_^�VW��F��F�;}[iF�^��>l�}��F�j@@P��
��j�F�P��
��jjj��jiF�^lHP��P�4������F��j�+���6l�;
���6j�1
���_^�VWU��F%?;s:���~��?i�^lP����hn�~��?i�^lP�v
�v������_^�VWU��N��?i�^��>l�Mu(��
���~��?i�^lP�v
�v���V��
���_^�VWU��j�v
�~��?i�^lP�Z���_^�VWU��v
�<tjV�N��?i�^lP�X���|V�W�����|o�^��?i�^��l�_�P�'������ t؋^��?i�^��l�_�P�������� t�W�N��?i�^��l�_�7�"����_^�VWU��~��?i�^lP�v�v
�v����_^�VWU���v�v
�~��?i�^lP�[
���_^�VWU���6n����_^�VW��v�~�F%��F��\��F�@@P�N��������t���D�t
�e�u��F���ȁ��k�
��t�'���F@@t���u��F@@u��\�G����㋇=t˃|t��\�tjjh�DP���������F��F@@tj��\�G����㋇�j�F�P��
��j�F�@@P��
���F��t��L$�F�P�`
���F��F�*�\G�F��u`jjh�DP�W����G$G&t��]
�t��F�P�
��%P�F�P�R
��j�F�@@P�E
����v�������d����d���LV����	�,���!�,V����v���
���D�vV����F@@t�\�G�����LJ��g�\�G�����LJ�T�\�G����㋇=u�I��\�G��؁��㋇=t�c��+��F��u	�Du��
�Du�t���_^�VW��^�w�_�G�v�
���^�G�F��^��?�F��~�tU�^�GPh�j
�GP�
��jjh�^�GP��	���^��[*�F���Z*�:F�u��~�t��N���� uj��@@P������^�G$��@@tQ��P�g��%P��P����F��%��F�k^�
LJjjhkF�
P�H	��k^�
LJ��P���%��P��P�N���^�_�G�����LJ��^�_�G�^�GP�1
���_^�VWU��v�����k�
������=~�~�����k�
P��	���_^�VW��v����\��F�@@P�w���F��F�P�g���F��F�P�W���F��F
�,
�	CC.;��t��.�g��������q
�
�
�
R
i
�
�
�
�F�
@@P�F�P�K����F�%����F�
P�F��ߋF�%����F�
��F�%���ߋF�
�P�F�P����v�v������F��P�F�@@P�����v�늋N���F�%����w��F�P�{���F��F�*�\G�F�*����F�j�v�F�P�}�
�v�v
V�����F�*�P�F�@@P�~��W�Y���_^�VW��^�G�F��^��7�^��)��F���(�:F�t����^��(����㋇���u+�^�Gt!�g����P����%P��P����t}���F���@@P����F�h���P����WV��������P��@@P�����^��,%�=t	=tj�j�j
��P����F�*�P��@@P����v��b���[�_^�VW��v�Dtb�A�F��\�P����F��F�*�\G�v�����\�Gt-�G�%���|u	�DP�1��F��u��X*䈄YV�]����X*�:�Yt2��Y*�ȋ�ي�Z*�PV�A����Y*�=�rƄY����Y���F����Z*�Ȋ�[*�+�F��F��.�>&�V��N�|7V������|*��Z*�ȋ�ًLj�\��Z*�=�rƄZ����Z��V���Vh8j
��HP�G���_^�VW��v��F��\�P��������t
Vh�
����� t>��Z*�:�[t2��[*�ȋ�ي�\*�P�\�7������[��[*�=rƄ[�v�����_^�VWU��vjV�a���_^�VW��v�\��F��F�@@@@P�R��=v�����.��((>�>W>6�F�P�&������t�Vh�
������v��	�����|t���,@@u-�ρ���1�;�u�L 녋ρ���0�;�u�d���n���X*�ȋ�ًLj�Z��X��X*�=s�J�ƄX�B���Z*�:�[u�3��D t�)���[*�ȋ�ي�\*�P�v������[��[*�=rƄ[��[*�:�Zt���Vh8�'��F�P�4���\G����_^�VW��F��~�}"�~��狅=u�~����������F����t�t;r|�t�t�_^�VW����t��F��F��~�}:�~��狅=u'�~��狽��(����狅B�F��F�;F�}�F��F��F����F�;t.��.�>(�r���&���~�t�hB�6����_^�d��`�VWU��N�	�v
�~��F��]_^�VW��~dra�F+�.�6<�uS�F+�RPjh�4����F��
�F�j6jC�"���F�%�Pj@@����F���Pj@@����v������F���F����F��_^�VW��v�{����F��u��F��F
��P��v�����F��_^�VW���F��~�t!jd�8����n�F���P�_���F��_^�d���U���v�v�P�'��]���`�����܋W+�����`�[XS�`[SSø�`���`���`�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�`����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X���`�VWU��v�~t�~
jjjVh����
�+�������D�F�D�vh�v
Vh����
W�����_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy

.�������	���	Y@@��`@@:0 dddddddd�,��X �@@Kttstart_free_XKsleep_Kttopen_main_Kkucopy_al_sg_clr_ttsignal_Talxtimer_�	clrivec_>albaud_Kttpoll_Kfree_super_�uexit_rKttsignal_al_sg_set_altclk_in_�Kdefend_nondsig_�altclk_out_kclear_�Kclrivec_com_usage_alxstart_d
setivec_�sphi_�ldrvipc_tthup_u_alxopen_�ldrvics_drvl_ldrvcon_inb_fcs_sel_>Kuexit_Ksuper_nulldev_�outb_�drvn_altclk_iogetc_ptimq_ldrvsel_Knondsig_Kkclear_ttsetgrp_Jblkmv4Ksetivec_xcalledttclose_�ttin_Ktthup_ttout_,con_Kldtimcall_poll_owner_poll_rate_alxintr_�
ldrvint_ttioctl_ttread_@@altsel_vldiv|Kiogetc_defer_Bcprocp_kcall_ztimeout_�Kttsetgrp_alp_rate_BKttclose_Kttin_alxbreak_�
Kttout_alloc_*tp_table_ucs_vrdiv�wakeup_�Kttioctl_Kttread_spl_�C2BAUD_Ktimeout_a1con_�C4BAUD_ttwrite_hprintf_�allkp_ldrvpsy_alxcycle_8Kalloc_ttstart_^alxparam_>getcs_bA1CNT_Kwakeup_sleep_�ttopen_"kucopy_�alxclose_JKttwrite_Kprintf_Kldeferttpoll_6alxioctl_�	0'7'$($*0-05'? 'J!$Q0T0\'b7$e'h7$k'o7 q'u7 w'~ '�['�!'�7'�N'�,'�7'�7$�0�'�C$�'�7'�7'� '�!'�,''N0'#'-'407'J+0_0p0�$�$�'�$�$�$�$�$�0� � � �      
  %�0�$�'�Z0�%0$'Z0%0!$%%,0/$6%<0?0E%K$N%R%\%b'eM%i$u${%%�%�'�M%�$�0�%�%�0�0�00$0%$10=0L%Z _%j o%z0}0� �0�0�$�%�0�0�%�0�00%0%"0%$;0@@%O0S%Y%h0r'{%�0�%�0�0�%�0�%
00%10=%Y0e%�0�%�0�%�0�%�0�0'%0)030:'M 'T0X'c90q'�0�0�0�'�M0�0�0�00)'0C0;0I0Z0g'n0u0{0�$�$�0�0�0�'�0�'�'�0'0"0%0?'C0a �0�0�0�0�0
	'$	 '4	 08	'C	 0N	0^	's	0x	0�	'�	 '�	 '�	 0�	0�	0�	0�	0
 
0(
 @@
 B
 D
 F
 H
 J
 L
 N
 P
0a
0g
0�
0�
0�
0�
0�
000.05'i0m$}0�0�0�0�0�0�0�00#0,020I0X0o0�0�0� 
0
0J
 Q
0[
0n
0}
 �
0�
0�
0�
0�
00 & ( * , . 0 2 40> M0P0[0�0�0�0�0�0�0 #0&000<'Z'hM0k%w%z%~%�%�'�90�'�'�M$�'�:'�: �%�0'9'9 ':0'+]'.2 d0w0�0�0�0�0�0�0�'�)0�'�?0�')00'#)')?0/'Mi0Q'Y'\2'qA't2'~2'�.'�2'�'�2'�-'�2'�h'�2'�'�'�'�'�'N''<'10''+'6'P'TN'Z'a0d'o'y'�'�2'�%'�2'�U0�0�0�'�8'�U0�0�'�H'�2'5'2'I'2'Q'2'#'&2'-K'02'7':2'AR'D2'KF'N2'U'X2'_'b2'ig'l2's$'v2'�b'�2@
0707070064030111271004440000030000030000011777770507310763600004500000015073/newbits/kernel/USRSYS/ldrv/RCS/dg,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.23;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�`:���v�v�v�Ѓ��VWU����6�t�;�V��P��
���P�E����.�.��؃�u���ヿtV��P��
��+�P���������������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P��P�Q����G$t�>�u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�
������LJ����LJ�ϸP�	��+��G��}5���㋇�F��~�t��t	�ȋ^��G;�u+�PPPS�
���ҋ^����+�P��
����]_^�VWU��>�t
�v
�v�����>u��]_^�VWU��>�t
�v������u
��P�
��]_^�
VWU��P�O	P�6��+	����������������P�PR�6�������P�6������P�:���6�����F��F��%=u���s�P�6�����6��c���F��F��%=u�
�F�4
P�x���P�6��`���dP�����6��"��%=t�>6t�D
��
P��ոP�6�� ���c
P� ���Z�P�6�6������<P����RP�����Z�P������RP������<P������RP����6�6�m��=Z�uN����RP�S��=�<u4������RP�9��=Z�u������RP���=�<t�w
�!��
P�S���P�6��;���@@��
P�5����]_^�VWU��>>t�>+�P����RP�����P�6������6��~���6�6�E��]_^�VWU���F�t#�>8t�'�7�>@@t+�8�<�"�F@@t�>:uփ>Bt�:���]_^�VWU���F�t&�8�><uB�7�t;�@@�B��
�#�F@@t#�:��t�B�>��
P�*��]_^�VWU��v
]_^�VWU��P�v
�F�t7V�����F��|_�><}WP�<����RP����<���F@@t/V����F��|!P�<� ��RP�y���<�ы�]_^�VWU��P��P�v�P���+�P���P+�P�P�c��]_^�VWU���6�P��P�v�&P�I��]_^�VWU��F�6]_^�VWU��+�P����RP�����P�6�������P��������RP���=GDt�>6t�P����+���
P�0��Ÿ#P����]_^�VWU��P�P��@@��RP�}����P��B��RP�d��+�P��D��RP�L���P��F��RP�3��+�P��H��RP���� P��J��RP����
P�6�����P�6������dP������@@��RP����t�>6t
�7P�������
P�)��ǸXP����P��@@��RP����P��B��RP�j���P��D��RP�Q��+�P�� 
��RP�9���
P�6��9���P�6��+����P������� 
��RP����=OSt?�>6t/�{P�����@@��RP���P��P����+����
P�=�뤸�P������"��RP�Y���D�P����RP�����
��RP�:���F����P�F����RP�I�����P�F����RP�+���F�%�P��
��RP����dP�����F�>Ft �>6t
��P�������
P�[����ٸ�P�������]_^�VWU�����
��RP�u���F���
��RP�]���F���
��RP�E���F���
��RP�-���F��>>u����
��RP�������
��RP����;�u����
��RP�����F��F��~�}3��~�F�؋ʋF������RP����E��F��NJF�*�P�F�*�P�F�*�P�F�*�P�P���
�F�%�P��
��RP����3��>Ft1�F��
��RP�1��P��
��RP�K����]_^�WU���~+�&�]_�WU���~&�]_�����܋W+�����`�[XS�`[SS�VWU��]_^��܋W�G�ø�`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�s����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P�&�������Dž����Dž]_^�WU���~�F&�]_�WU���~�F&�]_ø�`�VWU��v�~t�~
+�PPPV�P����
�-�M�����D�F�D�v�P�v
V�P����
W�*��]_^���`���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
N���Error - board type is PC/Xi
Error - board type is PC/Xm
PC/Xe ID found
Error - PC/Xe failed to reset
PC/Xe passed reset
Error - PC/Xe failed memory test
PC/Xe passed memory test
PC/Xe waiting for BIOS load
PC/Xe waiting for FEPOS load
PC/Xe ready for use
Error - PC/Xe BIOS won't start
PC/Xe BIOS started
Error - PC/Xe FEPOS move failed
PC/Xe FEPOS relocated to host RAM
Error - PC/Xe FEPOS won't start
Failure code (%x)
PC/Xe FEPOS started
Error - PC/Xe no FEPOS interrupts
PC/Xe interrupts working
%x %x %x %x
Ksleep_main_clrivec_�uexit_�Kdefend_Kclrivec_setivec_:sphi_�ldrvipc_u_ldrvics_drvl_ldrvcon_inb_�
Kuexit_nulldev_outb_drvn_iogetc_�
timq_ldrvsel_Ksetivec_xcalledffbyte_�
con_Kldtimcall_ldrvint_DG_IOB_�Kiogetc_cprocp_kcall_timeout_*ffword_�
ptov_0DG_RAM_�dgcon_�ucs_sfbyte_�wakeup_�spl_�vrelse_�Ktimeout_printf_&Kptov_ldrvpsy_DG_INT_�sfword_getcs_�
Kwakeup_sleep_ Kvrelse_Kprintf_0''%$-010; E'K'V$]0a0j'p$s'v$y'} '� � �'�'�,'�'�'�$'�'�'�$�0�'�$�'�'� �'''',
'0$06'A
'K'R0V'l0x0�0�$�$�'�	$�$�$�$�$�0� � � � � � � � � � � � $
0
$$%#%'%407%=%A$I0L0V$]0`$u0x$�0�$�0�$�0�$�0�$�0�0�$�0�%�$�0�0�$�0�$0%%0% %$0/%9%=0H%R%V0a%h%l0o%z%~0�%�%�0�%�%�0�$�$�0�$�0�%�$�0�%%%%0$*0-$407%>%B0E%\'c	%j%q%w%�%�%�'�	%�%�0�%�%�$�%�0�%�%�$�0�0!%/%7%<%@@0K%R0_%m%r%v0�%�%� �%�0�%�0�%� �%�0�%�%%0$00'%-%10<%H$N0R0`$e0i%�%�0�%�%�0�%�%�0�%�%�0�%�%�0�%�%�0
$0$#0&00%6%:0E%P$V0Z0`0g$l0p%z%~0�%�%�0�%�%�0�%�%�0�$�0�$�0�0�%�%0%$ 0$%*%.09$@@0D0L0S$X0\%b%f0q%w%~%�0�%�%�0�%�%�0�%�%�0�%�%�0	0
	%	%	%	$$	0(	0.	05	$=	0A	%X	%\	0g	%p	%t	0	%�	%�	0�	%�	%�	0�	%�	0�	%�	%�	0�	%�	%�	0�	0�	%�	%�	0
%*
%.
0=
$c
0g
%w
%{
0�
0�
%�
%�
%�
%�
0�
%�
%�
0�
'�
''
''3'*'1+'4'A	'P
'\'c	'r'z$'~
'�'�0�'�	'�'�
'�
'�$'�	'�0�'�'�
'!'$'E)0I0Q0V'e'm)0q0x'�'�'�2'�'�0'�@
0707070064030055021004440000030000030000011777770507310764000004500000017605/newbits/kernel/USRSYS/ldrv/RCS/fl,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.26;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�&�P����v�v�v�Ѓ��VW��6�t;6|Vh����j�7��k�
��u���ヿtVh���
��j�������������k�
LJ����LJ�������>t
����P���jjhh��H����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�
������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v��
���͋^����G�j��
���_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h��
���_^�VWU��j����jjp�0��jq�������ƈu7��
����������%�������t,����t"�����������t����%@@���>�tt���jh����h�
j����jh����jh�������=t���Ph��~��j�!	�������P�	������P�	��W�>���_^�VWU��>�tj����jjjh�!���.jh�����_^�VWU�������F%���;�s�v�������~��������u��_^�VWU��j�v�v
h��
���_^�VWU��j�v�v
h��e
���_^�VW��~
@@t���F%������v�D
���F��F@@P�6
���F��~�wʋF�;Es��Ft�E�f�F��	�E�f�F������e����+ҹ	�����������F���E����j@@�vh�h��	���_^�VW��v�D��	�ȋ�+�D
T-���F��\�����D
;��v�LV���c�|@@t"�\�����F�;��r�D�D�D@@t����D�t�|@@u���d
���>�u�6�����7�6��>�u�W�A
���_^�VW��6����=v�����.����f�?�.�u��j�D%���Ph��;���D%������D%������ظ������D�T�����D
�������Ƈ��D��	���u��������F��t����F�;F�t���Ph��~������Ƞ��#�uG��������Ƞ���
Ph��O���;jh�jdh�2	�������Ƈ����������Ƈ�����Ƞ���
Ph����������؀��u%��������j������P����������>�B���>�t!����>�����>�������>��������>�����>�������>���j�������ȡ����P�
���>�Pt"����؀��u����P�����؀��t��6����������|tjh�jh�����������Ƈ����jh�h$�Y���t������Ƈ��f���|t�|uP���E�6�h�6��6�j�Z��
�u>�6��6�hL�t����h$����LV�N���+����M�6��t�j���W�������ȡ����P�����|@@u%���P�����6��������P����h��H�6�����6�����6�������P����6��������؊���P�{��h��r����������Ƈ�j�V��h$�7����������t+�����=}
�����Ƈ��-�X�LV�C���!��u�D�����������>�u������Ph�j��hk�5���_^�VW���F����=u	�F�����v������_^�VWU��v���%����؀��uO�ށ������=u O���%����؀��u��%=u+����_^�VW���F�+����}H���#�uF����|��������=|���� ����;�uր>�t��?�>�u����������Ƞ���
Ph��0���>�u�.�v�����_^�VWU��j���h$���jh�����jh��������=t���Ph�����j�v�������P�e������P�Y��+�����������������t+���Pho����|�LV�L�������t;|t�jh�jh�O�����_^�VWU���-���2�>�t���V����_^�VWU��v�����V�G���_^�VW��F����F�+�h������ȋ����u�N�u�h�������@@th��������sɋ�G�ƈ��뾉>�jh����+�h��x���ȋ����u�N�u�h������@@th��Q������sɋ�G�ƈ��뾉>��v��H���_^�VWU��+�h����%�=�tNu�h��H����vh��&���_^�VWU���6��6����%Ph�����>�|*�������t	h������������t	h������>�|~�������t	h������������t	h����������t	h����������t	h ���������� t	h+�w��������ǀt	h9�b���>�|i�������t	hG�F���������t	hd�1���������t	ht���������� t	h�����������@@t	h�����h������_^ø�`�VWU��N�	�v
�~��F��]_^ø�`���`�VWU��v�Q�D�F
�D�vhVh�]���_^�VWU��vVh�G���_^ø�`���`���`������`��܋W+�����`�[XS�`[SS�VWU���_^��܋W�G�ø�`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�t����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh�(�������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh�����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
(Nh�~	��@@(#*P�(#*PP#*Ph(	#*P�(	#*P�P	#*P`	PT@@PTfd: DMA page straddle at %x:%xfdsfd%d: <Door Open>
flintr: timeout
flsense: timeout
flput: timeout
fd%d: head=%u cyl=%u <Not Ready> <Equipment Check> <Missing Address Mark> <Write Protected> <No Data> <Overrun> <Data Error> <End of Cyl> <Missing Data Address Mark> <Bad Cylinder> <Wrong Cylinder> <Bad Data CRC> <Data Deleted>
Ksleep_main_Kdmalock_clrivec_�dmaoff_�
int11_uexit_nflrecov_
Kdefend_Kclrivec_setivec_@@sphi_
ldrvipc_u_ldrvics_Kint11_Kdmaoff_fldone_�
drvl_ldrvcon_fl_hlt_�inb_�
Kuexit_nulldev_outb_"dmareq_�
drvn_getubd_�
timq_ldrvsel_blkmv^
Ksetivec_xcalleddmaunlock_�
con_Kldtimcall_fl_hut_�ldrvint_Kdmareq_Kgetubd_devmsg_z
cprocp_kcall_timeout_bdone_T
dmago_�
Kdmaunlock_fl_srt_�panic_,ucs_wakeup_xspl_dmaon_�
Kdevmsg_Ktimeout_flcon_�Kdmago_Kbdone_printf_6ldrvpsy_flunload_�Kpanic_getcs_�
Kwakeup_sleep_Kdmaon_dmalock_�
Kprintf_0'"'$$*0-05'?'J$Q0T0\'b"$e'h"$k'o" q'u" w'~'�;'�'�"'�1'�'�"'�"$�0�'�)$�'�"'�"'�'�'�''10'#'-'407'J0_0p0�$�$�'�
$�$�$�$�$�0� � � � � � � � � � �0�0�0�$$
%%%#%.%80=%C%V%Z0`0j p0u0�0�%�%�0�0�$�$�0�$�0�0�%�0�%�0�'�0%0+$@@'G
%\0_%v0y'�
0�$�0�0�'�
'
'
'
'
%0$[0f$0�%�%�%�%�%�0�0�%�%�0� � � � � � � � �'0$%0!%0%9%<%I%R%V%\%_%f%p%x%~%�0�%�0�%�%�%�%�%�%�0�0� �%�0�%�%�%�0�%�%%%00!%$%+%1%80=%C0H%O0S%V%[%`%d%j%o%r%w%z%}%�%�%�%�%�%�%�%�%�%�0�%�%�0�%�%�%�%�%�%�%�0�%�0� 
%00%%"%' -%0030=%@@%G%O%a%j%q%u0z%�%�$�0�%�0�0�0�%�%�0�0�%�%�0�%�0�%�0�%0%0%0%&0)%/04%;0>%D%K0P0Y%`0d%g%n0t%z0}%�%�%�%�%�0�0�%�%�%�%�%�%�0�%� �0�$�0�0	%	%	0	0 	%@@	$Q	%g	0�	%�	%�	%�	%�	%�	%�	%�	0�	%�	0�	%�	%�	0�	%�	'�	0
0
%
0 
0+
06
%<
%E
0M
0U
$[
$b
0f
$l
0r
%z
%~
%�
%�
%�
%�
$�
0�
0�
%�
 �
%�
0�
%�
0�
0�
%�
0�
0�
%%00 0+$@@0C0R%e%k0s0~$�0�0�%�%�0�0�$�0�0�%
%%$0%#%)$508%>$J0M%T%Z$f0i%o${0~%�$�0�%�$�0�%�$�0�%�$�0�%�%�$�0�%�$
0
%	
$
0
%
$*
0-
%3
$?
0B
$H
0K
'U
9'X
 '{
5'~
 '�
8'�
 0�
'�
#'�
0�
'�
.0�
'�
'�
 '�
A'�
 '�
&'�
 '�
''�
 '' ' '-='0 '7C': 'G
'V'b'i
'x'�1'�'�%'�0�'�
'�'�'�'�1'�
'�	0�'�'�'' '46070?0D'S#'Z60]0d'o'r 'y?'| @
0707070064030111251004440000030000030000011777770507310764200004500000040543/newbits/kernel/USRSYS/ldrv/RCS/gr,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.29;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�#��p
���v�v�v�Ѓ��VW��6�t;6|Vh$�"��j�#��k�
��u���ヿtVh$��!��j�#����$��$����k�
LJ����LJ�������>t
����P���jjhh�#�j"����G$t�>�#uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W��!������LJ����LJ��h�� ��+���s=���㋇�F��~�t)�^��G�F�� ;F�ujjj�v���!���͋^����G�j�d"���_^�VWU��>$t
�v
�v�$���>u��#�_^�VWU��>$t
�v�$����#u	h�#�"���_^�8(+dp VWU����^�w�O�?t��۽B$�v�V�F�~�F#F&1��&1�� +��f����.���
�ڀ~(u����F#F&1��&1�� [�^�v�V�~������*���^���O+OO]_^�6�c����Q��V���B.����JK}�Y��������$t������F���F���F�F�F��F�FP*Ҋv�v
�^�^+��F�6���y6��s*���:v~U�vVQ�^�^
��.���
.���
����.���
Q+���VWQ�Y_^�� �� �F#F_W���_�� ���Y^�D����.���
�ڀ~(u����I�����.���
����I�����.���
�~(t�V*���������2���Ȏػ��3F#F�W�3F#F&���N�3F#F��3F#F&���N�3F#F��3F#F&���N�3F#F��F3F#F&�_^+���:V}
�I�����.���
*���:v�3��v����oV*�������n�����ػ��3F�W&�!��O�3F�&�!��O�3F�&�!��O�
f3F�&�!_^+���:V}
�I�����.���
*���:v����v�j�����I�����.���
*Ҋ���.���
��I�����.���
��}�V����:v
}*Ҋv
�|��H���I��~�~����.����2���I�<;t!�؀�0��	w9�f�F����FÈF���	���I��؀�0��	w�f�F����FÈF�ފ���.��������I��؀�0��	w�f�F����FÈF��<htL<ltX�������I��؀�0��	w�f�F����FÈF��<hu��<lu�������€�*����~
u6��*���~
u6��*���V��}*�:Vr�V���d�� QV+Ɋʀ���*�ыv�~Pu���A��F#ƫ&�A�&�EN&�AN&���&���&���F#�&�����+�^Y:V|*V��:v~�v�����*���:v
s�v
�����~u�F����~u�F�����:vv�v�����:Vr*V��:vv�v�V�����v��*�v
:vr�v�V��*�:Vr�V���{���:v
}�v
�n�VQ�^����.���
.���
�^��.���
+�~1��VWQ�Y_^�� �� �.���
W���F#F�_�� ���*�Y^��6�� ��F<u�^�<u�^
�r*Ҋv
����.���
�^*��<�F<u�^��<u*��H*Ҋv
+��^��F��<u�<t,��.���
*�*�Q�F#F��������� ��}�Y��RQW�F#F��.���
����.���
+�~��WQ�Y_�� �Y����.���
+�~x�׋���P������P������P������������P������P������P�����+�YZ���RQW�F#F��.���
����.���
+�~��WQ�Y_�� �_+ɊN*ʀ~(u��׋���P������P������P������������P������P������P�����+�YZ�t�6���VQ�^�^��.���
�΃�.���
������.+��
~3��VWQ��Y_^�� �� �.���
W���F#F��_�� ���*�Y^�	��V��*�:Vr�V������F
�u���:Vr�V������v��*�:vv�v�V��*�:Vr�V������:v���v�R��V�v���V�v����:v
}�v
�����Nt

�F�����F���F<u�F���F�F�!<u�F���<u�F���<u�F����D��~Pu�F(�����F�����~(u�FP���F����F��}*�:Fw�^��}*�:^w:�w
�F
�^��*�����v��*�:vv�v����F
�u���:vr�v��ttttttt����	t�0
F
ttttttttttt�tttt��������������������������������������������������������������������������������������������������������������������������������ttttttttttttttttttttttt�	�	tttt��ttttt�	ttttttt�	ttttttttttttt�ttttJt��tttttttttttttttt��ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttStt����e�������tTttt�	�	ttttt�tttttV	l	tt�
�
�	�ttttt�	ttttZ
ttt�	ttttttttt@@��@@��
@@��
@@��@@��@@��@@� �!#@@$�%�&(@@)�*�+-@@.�/�02@@3�4�57@@8�9�:<@@=�>�?VWU��n
�~t����~���؋FF=@@wW�F+ҹP������������u�P+�;N~�N�-)NNV�^�� �P+�;N~�N�)NN�� +���]_^�VWU��n
�~t��؋v�����FF=@@wҋF+ҹP�������������u�P+�;N~�N�)NNW�_�� �P+�;N~�N�)NN�� +��ĺ���ú���6��*���0�3���0��?������?��������?���?���?�����������?��������������?��?�������0��0������?�?�������?�?��<�<?�?���?��?��0<?00���������������?�00�<?��<?�?�?�<<�?��<�?�����?��<<<<<<<<<<<<���<?<<<<<?������?�?�?��?���?�����?�����������?��0<��<0<��<�����0<<��<<0�?�����?��<<<<<�<���<���<�<�?��?��<?���<����?��0�?�����?����<���<�<<<�30����30��?����??��<��<�?������<�<�<?���?�����?��<<�<��?��<<�<�<?���<<<��<<������<<��?��<����<�<?���<��<<?��<�<?��<�<?�?��<�<?�<�<?��<�?�?�?���??��<��?����������?�?��<�<���<�<�<��<<<<?�<<<<��?��<����<?���<<<<<<<<<<����<<�?�<�<����<<�?�<�<�?��<�<����<?��<�<�<���<�<�<��������������?��<����������<�<<<<<���<�����<�<�<�<�<�<�<�����<�<?��<�<�<�<�<?���<<<<?�<<�?��<�<�<�<�<?����<<<<?�<<<<�<?��<�?�<�<?�?�3�������<�<�<�<�<�<?��<�<�<�<�<<���<�<�<�<�<���<�<<����<��<<<<<<<�������<��<<����������<��<??�<��<���?�<?��<?������<�<�<��?��<��<?�<<?��<�<�<?�?��<���?��<<<�<<<?��<�<?�<?������<�<�<�<������������?����<������<������������<�<�<���<�<�<�<?��<�<�<?����<�<����?��<�<?�<<��?<<<<?��?�<?���?������<�<�<�<?��<�<�<<���<�<�<���<�<<��<��<�<�<�<?�<?�����<�����?������������?�����<<��VWU��>|$u?jja��
���V)N}�h�ja��
��+�Nu�j`�
����h�ja��
��jMja�
���hj��
��h~$�\���_^�VWU��j�9���_^�VWU���F�t��N��$�t�p�u��8�vh~$�����H��$��$�u���$h~$���V�)����_^�VW�+���}
����LJd+F���F��*+���}9����F���d+���㋿>)�F��F��F���G���^���=��t	�~�`+r��F���_^�VWU���
����$u�
��h~$���V�
���_^�VWU��j�v
h~$����>~$t	h~$����_^�VWU��F
���CC.;��u.�gMN��?�:
���v�v
h~$�
��V�)
���V�v�v
�Q���H��'*�_(\�`(���(|��(��)�)��#��')�_(��`(\��(���(|�)��)�_^�VW��~�u��*��c+sc��P�F
�F
P����F��+���}
����LJd+G�*+���}1���㉷d+��F�F��F
�F
P�(���^���=��t��`+r��G���_^�VWU��f
���F
t"�>�$u�~t	h�%�3���>�$u�f
���F
�_^�VW��F��>uh~$h����j`���%��F�ja�������
�Pja����Vja�����>�+t=��+�~��t�C��*�%����* t����*t��Vj`�����>�+~��+��F����CC.;��u.�g�������>�+t��+��+���+�F�%H���F��u��Ru��*%=u����(*���ǀu��F��tK��5u	�&�*�����'�;�u	�&�*���t��u	�&�*���f��7t�^�>�+t�������!�*�H��'�;�u	��*�7��5u	��*�)��u	��*���7u�>�+t���	�*���9u�6�*������Dt���6�* ���F��t���>�$u����*t���'�X��*t,��u��
u��C�
�>��t��t����(*�%�&#>�*t��*t��0u���(�
��0u�6(*�����t[���t��*t�΀V�U����v��>��F��~�t.��F�h�j`�����+�v��w�����+���+�_^�VW��F�+��F-=Dv�c����.���|LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL�L�LLL����������L�


LL��*���>�+t��*���*t��*���*��>�+t���*���*t�^��1�㋷d+��^��;�ヤ+��%@@uo�F���$ t��%���+��*�V��%���+��*�H�N�N+���* t���*t����*@@t��>�+t+�����N��Gk���ڋ�f)�t�<t�<�t��F��%�P�s����F��_^�VWU��v�ƻ��CC.;��uJ.�g
=>ctu�������* �'�&�*�����*@@��&�*������*�>����_^�VWU��v��%*���ƈ��%��%��%*�=r��%�_^�VWU��v�����X*�:�Yu���Y*�ȋ�ي�Z*����Y*�=�rƄY���Y�>t��.���;�t��/���;�u
WV�2���3��bu�>�+u��6�+V����׃�cu�>�+t�j����>�+�f��_^�VW��n�F�h�j`�g����+�v��X���_^�VWU����*����_^�VW��v�D u2V����F��|$�F��F��F��F��F��F�Ph�����ǃ>�+u��+VhP j
h�����_^�VWU�������>}2�h�jC����h�jB���j
jB���ja�m��
��>~�uja�S��%��Pja����>t��P�����V�a���v����vhP j
h�[���_^�VWU��>�*~�>�*~	��*u���_^�VW��v
�D�F��<uV������u����Dup��$ t'���F���$jjhh~$�����v������ы>�E$E&t&��t�_��F�;Du��6V�[����t+��V�N����|u����$ t��V�0����u��_^���`�U���v�v�P���]������`��܋W+���[XS�`[SSø�`�VWU����_^�VWU���_^��܋W�G�ø�`���`���`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�H����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh���������Dž����Dž�_^���`��X��X[SSP�X���`�VWU��v�~t�~
jjjVh����
�+�����x��D�F�D�vh�v
Vh�w���
W�����_^���`���`���`���`���`���`���`���`���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
&"&""�"&"&"&"&"������P
�t&"�!�&"� 2���)�������{[]}\���@@����������~����������������������������������������������������������|��1234567890�'	qwertzuiop�+
�asdfghjkl��^�#yxcvbnm,.���� ����������������-���+�������<��!"$%&/()=?`�QWERTZUIOP�*
�ASDFGHJKL����'YXCVBNM;:���� ����������������-���+�������>��������cccccccccccc�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)***** *$*&***.*0*4*8*:*>*B*D*H*K*M*Q*U*W*[*a*c*g*k*m*q*u*w*{**�*�*�*�*��������������������7?w8?x9?y4?t75?u6?v1?q2?r3?s[@@0?p.?n/_-*�Kttstart_ismmfunc_sKsleep_mmtim_Kttopen_main_clrivec_�"pollopen_:"mmbeeps_mm_voff_mmcrtsav_�*fontw_2super_:#nonedev_"uexit_�#initkeys_mmgo_�mmwatch_� isuload_�updleds_�Kdefend_nondsig_"isclose_tKclrivec_setivec_b"Kpollopen_sphi_,#boot_�!ldrvipc_grread_u_isioctl_�putchar_N"ldrvics_isread_�drvl_ldrvcon_inb_�!Kuexit_Ksuper_outb_0"nulldev_&"drvn_getubd_�!timq_isload_2ldrvsel_Knondsig_istty_~$agmaptab_�'ttsetgrp_�#isspecial_�Ksetivec_xcalledttclose_�#Kboot_ttin_�#kbunscroll_�ttout_�#con_Kldtimcall_Kputchar_isfunction_fldrvint_ttioctl_�#ttread_�#grwrite_�mmwrite_!islock_Kgetubd_defer_�!cprocp_kcall_"timeout_D#Kttsetgrp_isturbo_|$mmstart_�Kttclose_mmtime_P Kttin_Kttout_ucs_uds_mm_von_$wakeup_�#Kttioctl_isopen_�Kttread_spl_0#Ktimeout_ispoll_�printf_D"putubd_X"ldrvpsy_mmvcnt_�*mmesc_ttstart_�#getcs_�!Kwakeup_isrint_grcon_($sleep_"#ttopen_�#iscon_b$Kprintf_KldeferKputubd_isbusy_0';'$*$*0-05'?#'J$$Q0T0\'b;$e'h;$k'o; q'u; w'~#'�]'�$'�;'�Q'�.'�;'�;$�0�'�G$�'�;'�;'�#'�$'�.'!'Q0'#!'-'407'J,0_0p0�$�$�'�$�$�$�$�$�0� ,$ .$ 0$ 2$ 4$ 6$ 8$ :$ <$ >$ B$'R$ 5$j'�_ �0�'�'�_    )0] f 0� �0� � 0*00 �0�0�0� � � �0�0� �0�0# N0Q0~0�0�0�0�0�$�0�$�0�0�0`0c0r0u0�0�0�0�0�0� �  
 *0H'MD0R0_0i w0�0� �0� � � 0a q z0�'�D0� 	 
	 	 5	0T	0j	0�	0�	0�	0�	0�	0�	0�	0�	0�	0�	0.
0D
0X
0�
0�
0�
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
     	  
          ! # % ' ) + - / 1 3 5 7 9 ; = ? A C E G I K M O Q S U W Y [ ] _ a c e g i k m o q s u w y { }  � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �     	  
          ! # % ' ) + - / 1 3 5 7 9 ; = ? A C E G I K M O Q S U W Y [ ] _ a c e g i k m o q s u w y { }  � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 
 
 
 
 	
 
 

 
 
 
 
 
 
 
 
 
 !
 #
 %
 '
 )
 +
 -
 /
 1
 3
 5
 7
 9
 ;
 =
 ?
 A
 C
 E
 G
 I
 K
 M
 O
 Q
 S
 U
 W
 Y
 [
 ]
 _
 a
 c
 e
 g
 i
 k
 m
 o
 q
 s
 u
 w
 y
 {
 }
 
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
 �
'*R'�R$- f$ h$ j$ l$ n$ p$ r$ t$ v$ x$ z$ �$$90C0T0a0n0x'# �0�$�0�0�$>)$@@)$B)$D)$F)$H)$J)$L)$N)$P)$R)$T)$V)$X)$Z)$\)$^)$`)$b)$d)'�$�0�'�$�0�0�$�$�0�$�$�0�00%$%.%@@$H%g0z$�0�$�0�0�$�0�$�$�0� � � � � �0�$�0�00$$!$&$+$0$5$:$A$F$K$P$U$Z$_%t%x0�%�%�%�0�%�$�$0$'*k$0 306'=k0D0R0b0k%r%y0�%�%�%�0�0�%�%�0� � � � �%�%�%�%�%0$!0.%>0C$F%O0T%]0b0j%n%}0�$�%�0�%�0�%�0�%�%�0�%�0�0�0�%�0�$�0�%$	%04$8%C%I$W$c%w0�0�0�0�%�0�%�%�$f)$h)$j)$l)$n)$p)$r)$t)$v)$x)$z)$|)$~)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)$�)0� � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @@ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z$}0�%�$�0�%�$�0�$�0�%�0�$�0�%�%�0�%�$�$�$�%�%�$�%�%�%%%%%0$J0e ~ � � � � �%�%�%�%�'�D%�0�0�$�$�$�$�$�0'k0$'RD0p%~'�D%�0�%�0�%�0�0�0�%�0�%�0�0 0+ %4 %;  ? 'D 0G 0V '\ 'c 0l 0w 0� 0� '� '� 0� 0� '� _'� _0� '� _0� 0�  � '� 0� $� $� $!0
!0&!00!$=!0D!$K!$W!0Z!0c!'l!G0w!0~!'�!0�!0�!$�!'�!0�!'�!7'�!5'�!i0�!'�!E'�!5'"5'"/'"5'"';"'>"5'E"h'H"5'O"='R"5'Y"j'\"5'i"'x"!'�"'�"'�"'�"Q'�"!'�"?'�"40�"'�"'�"'�"!'�"!'�"Q'�"'#0#'#'#!'##'&#5';#''>#5'`#Y0c#0k#0p#'#<'�#Y0�#0�#'�#M'�#5'�#O'�#5'�#U'�#5'�#'�#5'�#P'�#5'�#W'�#5'�#J'�#5'�#'�#5'�#&'�#5'�#b'�#5@
0707070064030111241004440000030000030000011777770507310764600004500000014653/newbits/kernel/USRSYS/ldrv/RCS/hs,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.33;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@��0����v�v�v�Ѓ��VW��6�t;6|Vh��	��j�M��k�
��u���ヿtVh��~	��j�&������������k�
LJ����LJ�������>t
����P���jjhh���	����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�@@	������LJ����LJ��h�q��+���s=���㋇�F��~�t)�^��G�F��;;F�ujjj�v��D	���͋^����G�j��	���_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h���	���_^�VW�i^P�6������uh�������i^P�6�����F��F�;|���^�����
iF�^���j��P���j��@@P�t����@@P�@@���t��!��\�Di�D��^������D��D���(���)�|��)����㋇D�F�h���P����v�W����F���P��@@P����j��P�����6��F��3��_^�VWU��>�t
�6�����_^�VW��~��i�^����|t�D@@P�r��������t�����t�'�r�D�D=uZV�����F�t;�<�F��DP�'�����L ��t�d���� t�L�v��
���
�d���LV����vV����2�_^�VW��~��i�^����|uJV�%���F��~�t8h�h�j
h����jjhh������Z*�:�[u̓~�t��N����L���_^�VWU��v
jV�~��i�^�P�����_^�VWU��v
jV�~��i�^�P����_^�VWU���v�v
�~��i�^�P����_^�VWU���v�v
�~��i�^�P����_^�VW��v��X*�:�Yt2��Y*�ȋ�ي�Z*�PV�)����Y*�=�rƄY����Y�¿���Z*�؊�[*��+���Ǚ.�>���O|9V����F��|+��Z*�ȋ�ًF���\��Z*�=�rƄZ����Z��V�����|tVh�j
��HP�,���_^�VW��6��|u��DtL�DP��������t7��t��t�d����L ��t�� t�L��d��V�"���DP�������t�Dt	jV�M����t:��X*�ȋ���F��t�i���^���Z�Dt��X��X*�=rƄX�� tC�D u<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�<����[��[*�=rƄ[��^��;�w����_^�VW��v���F�+���)t��W�DP������)����㋇D���t+h��DP����W�t�������P�D@@P�����,%�=t=t���
��W�DP���j�D@@P�t���v��M����_^�VWU��v�4���DP� ������ t<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�����[��[*�=rƄ[W�����_^�VWU��������;�|�����_^�VW����t��F��F��F�;}?iF�^��>��}t)iF�^��>���(����狅l�F��F�;F�}�F��F��F�븋F�;t.��.�>������&���~�th��6�����_^�d��`�VW��~dra�F+�.�6�	�uS�F+�RPjh�4�����F����F�j6jC�����F�%�Pj@@�����F���Pj@@�����v�����F���F����F��_^�VW��v�{����F��u�v�F��F
��P��v��e���F��_^�VW���F��~�t!jd�8����:�F���P�+���F��_^�d�����`�����܋W+���[XS�`[SSø�`�VWU���_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�t����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh�(�������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh�����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
����
	��	7\��	�	���	Y@@��`@@:0 dddddddd�,��X �@@hsload: can't allocate tty's
Kttstart_free_�	Ksleep_Kttopen_main_ttsignal_fclrivec_Z
Kttpoll_hscycle_�hsparam_�Kfree_uexit_�Kttsignal_hsclose_�altclk_in_	Kdefend_kclear_�	altclk_out_Q	setivec_�	Kclrivec_sphi_�
ldrvipc_tthup_u_hsioctl_�hsread_7ldrvics_poll_hz_ldrvl_ldrvcon_inb_�	cs_sel_�	Kuexit_nulldev_�	outb_�	drvn_altclk_timq_ldrvsel_Kkclear_ttsetgrp_\Ksetivec_xcalledttclose_ttin_ Ktthup_ttout_>con_Kldtimcall_poll_owner_poll_rate_ldrvint_ttioctl_*ttread_Raltsel_vldiv�hswrite_\cprocp_kcall_�	timeout_�
Kttsetgrp_Kttclose_hsstart_iKttin_Kttout_HSNUM_alloc_�ucs_vrdiv�hsopen_	wakeup_�Kttioctl_Kttread_spl_�
Ktimeout_HS_PORTS_
hspoll_�ttwrite_zprintf_�	allkp_ldrvpsy_Kalloc_ttstart_pgetcs_�	Kwakeup_hsintr_�sleep_�
ttopen_4hscon_*Kttwrite_Kprintf_ttpoll_H0'/'$#$*0-05'?'J$Q0T0\'b/$e'h/$k'o/ q'u/ w'~'�P'�'�/'�C'�&'�/'�/$�0�'�9$�'�/'�/'�'�'�&''C0'#'-'407'J%0_0p0�$�$�'�$�$�$�$�$�0� . 0 2 4 6 8 : < > @@ B$�'�O0�%�$�00$
%0$#0($2%;0H0T0^0h0k t y$�$�0�0�0�0�%�0�%�%�0%0,';0?'C1'K0]0j0w0�0�0�0�%�0�%� �%�0%001%O0S%t0x%�0�%�0�0� /080q ~0�%�0�0�0�0�0050�%�0�0�0�$�00
00G0T0]0c0r0~0�0�0�%�%�%�%�%�'�10$%!%2$?'\2'a2 g%j0m'q1 |'�20�'�1'�Q'�* �0�0�0�0�0�0	0#	00	'9	$0<	'?	60E	'X	$0f	0l	's	$'y	60	'�	
'�	*'�	*'�	''�	*'�	Z'�	*'�	'�	'
'
'
'
C'"
'+
3'1
)04
';
'G
'R
'l
'p
C'v
'}
0�
'�
'�
'�
'�
*'�
J0�
0�
0�
'�
0'�
J0�
0'
='*'-'*'!?'$*'+G'.*'5'8*'?@@'B*'I'L*'SH'V*']<'`*'g'j*'q't*'{Y'~*'� '�*'�T'�*@
0707070064030111231004440000030000030000011777770507310765000005100000015333/newbits/kernel/USRSYS/ldrv/RCS/hs.310,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @@;


1.1
date     91.07.15.14.14.36;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@L�����v�v�v�Ѓ��VWU����6�t�;�V�RP�
���P�����.�.��؃�u���ヿtV�dP��	��+�P�����N��P������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P�LP�;
����G$t�>Lu܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�	������LJ����LJ�ϸP���+��G��}5���㋇�F��~�t���ȋ^��G;�u+�PPPS�	���ҋ^����+�P�Q
����]_^�VWU��>Nt
�v
�v�N���>u�L]_^�VWU��>Pt
�v�P���Lu
�LP�M
��]_^�
VWU����v.�&�P�6����� 
�u
�
P������v.�&�P�6 
�����F��F�;v|���^����㋿x.�.� 
��+�P��P����+�P��@@P�����@@P����t��a��\�D��D��^����㋇z�D��D���(���)�|��)����㋇��F���P��P�S���v�W�I���F����P��@@P�7���P��P�'���6"
�F��+���]_^�VWU���6 
����]_^�VWU��P�F%.�.� 
���|t�D@@P���������t�����t�'�r�D�D=uZV����F�t;�~�F��DP�g�����L ��t�d���� t�L�v��O���
�d���LV�&���vV�����N��]_^�VWU��P�F%.�.� 
���|uQV�g���F��~�t?�$
P�BP�
P�$
P����+�PP�P�$
P������Z*�:�[uƃ~�t��N���L����]_^�VWU��v
+�PV�F%.�.� 
P�5��]_^�VWU��v
+�PV�F%.�.� 
P�7��]_^�VWU���v�v
�F%.�.� 
P����]_^�VWU���v�v
�F%.�.� 
P���]_^�VWU��P�v��X*�:�Yt2��Y*�ȋ�ي�Z*�PV�`����Y*�=�rƄY����Y�¿���Z*�؊�[*��+���Ǚ.�>���O|9V�;���F��|+��Z*�ȋ�ًF���\��Z*�=�rƄZ����Z��V�4���|tV�P�
P��HP�^����]_^�VWU��P�6 
�|u��DtL�DP�������t7��t��t�d����L ��t�� t�L��d��V�T���DP��������t�Dt�PV�}����t:��X*�ȋ���F��t����^���Z�Dt��X��X*�=rƄX�� tC�D u<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�h����[��[*�=rƄ[��^��;"
w�����]_^�VWU��P�v��F�+���)t��W�DP�����)����㋇����t-��P�DP����W�t�����DZ��P�D@@P������,%�=t=t���
��W�DP����P�D@@P����v��u�����]_^�VWU��v�Z���DP�D������ t<��Z*�:�[t0��[*�ȋ�ي�\*�P�t�>����[��[*�=rƄ[W���]_^�VWU�����6
�6
;4
|�6
�6
]_^�VWU������t��F��F��F�;v}B.�.���> 
�}t,�F�.�.���> 
��(����狅��F��F�;F�}�F��F��F�뵋F�;t/��.�>��4
���&���~�t�P�6������]_^�^d��`�VWU����~drm�F+�.�6�	�u_�F+�RP�P��4P�����F����F��6P�CP�����F�%�P�@@P�����F����P�@@P�����v�����F���F����F���]_^�VWU����v�i����F��u��F��F
��X��v��o���F���]_^�VWU�����F��~�t#�dP� ����>�F���P�/���F���]_^�d�����`�����܋W+���[XS�`[SSø�`�VWU��]_^��܋W�G�ø�`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�s����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P�&�������Dž����Dž]_^���`��X��X[SSP�X�VWU��v�~t�~
+�PPPV�P�����
�-��������D�F�D�v�P�v
V�P����
W����]_^���`���`���`���`���`���`���`���`���`���`���`���`���`��Ë܋_��Ë܍_VWU��P�V
�F+�+�� ��������;wrw;?r+?w@@��[��]_^���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
����
3�*
l��*
*
� �	Y@@��`@@:0 dddddddd�,��X �@@hsload: can't allocate tty's
Kttstart_ahigh	
free_�	bhigh	Ksleep_Kttopen_main_ttsignal_�clrivec_�
Kttpoll_hscycle_hsparam_�Kfree_uexit_�Kttsignal_hsclose_�altclk_in_y	Kdefend_kclear_ 
altclk_out_�	setivec_H
Kclrivec_sphi_ldrvipc_tthup_�u_hsioctl_�hsread_lldrvics_poll_hz_�drvl_ldrvcon_inb_

cs_sel_�	Kuexit_nulldev_*
outb_4
drvn_altclk_timq_ldrvsel_Kkclear_ttsetgrp_�Ksetivec_xcalledttclose_zttin_�Ktthup_ttout_�con_Kldtimcall_poll_owner_poll_rate_ldrvint_ttioctl_�ttread_�altsel_vldiv�hswrite_�cprocp_kcall_
timeout_"Kttsetgrp_Kttclose_hsstart_�Kttin_Kttout_HSNUM_valloc_�ucs_vrdivhsopen_3wakeup_BKttioctl_Kttread_spl_Ktimeout_HS_PORTS_xhspoll_�ttwrite_�printf_>
alow	allkp_ldrvpsy_blow	Kalloc_ttstart_�getcs_
Kwakeup_hsintr_�sleep_
ttopen_�hscon_�L0L1Kttwrite_Kprintf_L22ttpoll_�L380'1'%%$-010; E'K'V$]0a0j'p1$s'v1$y'}1 '�1 � �'�'�S'�'�1'�E'�('�1'�1$�0�'�;$�'�1'�1 �'''(','0E06'A'K'R0V'l'0x0�0�$�$�'�$�$�$�$�$�0� � � � � � � � � � � �$ 'R0%$!0%0+$. 3%80;$J0O$Z _%c0q0~0�0�0� � �$�$�0�0�0�0%0%'0* B%F0V'e0i'm3'u0�0�0�0�0�0�0� %0%" &%.02%@@0D0d �%�0� �%�0� �%�0� �%�0�0, f0o0� �0�%�0�0�0.0;0U0s0�%�0�00$-0A0K0]0�0�0�0�0�0�0�00%"%%%)%/%4'D30K$\ c%i w%}$�'�4'�4 �%�0�'�3 �'�40�'�3'�U'�, 	0	0%	03	0D	0V	0_	0�	0�	'�	&0�	'�	80�	'�	&0�	0�	'�	&'�	80�	'�	'
,'
,'!
)'$
,'?
`'B
,'O
'^
'j
'q
'�
'�
E'�
'�
5'�
+0�
'�
'�
'�
'�
'�
E'�
'�
0�
'�
''','=L0A0I0N']2'eL0i0p'{?'~,'�/'�,'�A'�,'�I'�,'�'�,'�B'�,'�	'�,'�J'�,'�>'�,'�'�,'�'�,'�_'�,'�"'�,'CX'F,@
0707070064030073231004440000030000030000011777770507310765100004500000033570/newbits/kernel/USRSYS/ldrv/RCS/mm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.39;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@���H����v�v�v�Ѓ��VW��6�t;6|Vh�����j�o��k�
��u���ヿtVh����j�H������������k�
LJ����LJ�������>t
����P���jjhh��&����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�������LJ����LJ��h���+���s=���㋇�F��~�t)�^��G�F��I;F�ujjj�v�����͋^����G�j� ���_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h������_^�VWU��>�u?jja�����V)N}�h�ja����+�Nu�j`�����h�ja����jMja�����h�j����h�\���_^�VWU��j�I���_^�VWU���F�t��N��t��u��8�vh����X����u��h����V�9����_^�VW�+���}
����LJ� F���F�> +���}9����F���� ���㋿��F��F��F���G���^���=��t	�~�� r��F���_^�VWU�������u���h���V����_^�VWU��j�v
h�/���>t	h����_^�VWU��F
���CC.;��u.�gMN�������J���v�v
h���V�9���V�v�v
�Q���H�^*��\����9|�:�������#�^)�����\�9��:|������_^�VW��~�u�> ��� sc��P�F
�F
P����F��+���}
����LJ� G��> +���}1���㉷� ��F�F��F
�F
P�<���^���=��t��� r��G���_^�VWU��f
���F
t"�>
u�~t	h8�C���>
u�f
���F
�_^�VW��F��>uhh�	����j`����%��F�ja�������
�Pja����Vja�����>&!t=�&!�~��t�C�< �%���:  t���: t��Vj`�����>(!~�(!��F����CC.;��u.�g���jqv�>,!t�,!�*!��*!�F�%H���F��u��Ru�: %=u���h*���ǀu��F��tK��5u	�&: ����^�;�u	�&: ���t��u	�&: ���f��7t�^�>*!t�������!: �H�^�;�u	�: �7��5u	�: �)��u	�: ���7u�>*!t���	: ���9u�6: ������Dt���6:  ���F��t���>u���: t��`�X�: t,��u��
u��C�
�>��t��t���*�%�&#>: t�: t��0u���
��0u􊄸*�����t[���t�: t�΀V�U����v��>��F��~�t.��F�h�j`����&!�v������,!��(!�_^�VW��F�+��F-=Dv�c����.���(�������������������������������������.�O���__________�~�������������� ���>*!t� ��: t� �� ��>*!t�� ��: t�^��1�㋷� ��^��;��.!�,@@uo�F�� t�0��.!�< �V�1��.!�< �H�N�N+��:  t��: t���: @@t��>*!t+�����N��Gk���ڋ���t�<t�<�t��F��%�P�s����F��_^�VWU��v�ƻ:	�CC.;��uJ.�g
=>ctu`	h	p	P	X	�:  �'�&: ����: @@��&: �����: �>����_^�VWU��v�X*���ƈ�Z�X�X*�=r�X�_^�VWU��v�
���X*�:�Yu���Y*�ȋ�ي�Z*����Y*�=�rƄY���Y�>t��.���;�t��/���;�u
WV�B���3��bu�>0!u��60!V�#���׃�cu�>0!t�j�
���>0!�f��_^�VW��~�F�h�j`�w
���&!�v��h���_^�VWU���< ����_^�VW��v�D u2V�����F��|$�F��F��F��F��F��F�Ph�����ǃ>2!u�2!Vh�
j
h����_^�VWU����
���>}2�h�jC����h�jB����j
jB���ja���
��>~�uja�g��%��Pja����>t��P�����V�q
���v����vh�
j
h�k
���_^�VWU��> ~�>  ~	�  u��_^�VW��v
�D�F��<uV����u����Dup� t'���F��jjhh�����v������ы>�E$E&t&��t�_��F�;Du��6V�7���t+��V�*���|u��� t��V����u��_^�VWU����^�w�O�?t��۽" �V���t�~t���t����%�v�V�F�~+ۊf
�f[�f
�^�v�V�~�V��^���B���J��B���V���)��  X��^���O+OO]_^�6�c�
%0=0t
�F��F��F�V���!�V��B*��J�
�B*��V��*��B��F��f
�F�v�v
�^�^+��F�6��n6���f*���:vvK�vVQ�^�^
��.��.�� ����.��Q+����� _�P�Y^����.��~����.���������.��~����.��\I�����r.��~��€�P}�EI�����r�.��~�~u�����+I�����r�.��~*���:v�I�����r�.��~�v�H��v���I�����r�.��~*Ҋ���.����I�����r�.��~����}�O��:v
}*Ҋv
����.���I�����s�Z�.��~����I��~�~����s�?�.��~�����I�<;t!�؀�0��	w9�f�F����FÈF�������I��؀�0��	w�f�F����FÈF�ފ���s���.��~����I��؀�0��	w�f�F����FÈF��<htL<ltX���s���I��؀�0��	w�f�F����FÈF��<hu�<lu��i����€�*��H��~
u6� �J��~
u6� �:��V��}*Ҁ�Pr�O��Q+Ɋʀ���*�Ѱ �Y��Pr��P��:vv�v�����*���:v
s�v
�����~u�F�~u�F����~u�F�~u�F����:vv�v���€�Pr��P��:vv�v�O���v��*�v
:vr�v�V��*Ҁ�Pr�O�]���:v
}�v
�P�VQ�^����.��.�� �^��.��+�~���.���P� �*Ҋ���.��Y^�����6����F<u�^�~<u�^
�]*Ҋv
����.���^*��8�F<u�^�T<u*��4*Ҋv
+��^��F��<t7<t��.��*�*�Q� �P���}�Y��Q����.��+�|� ���Y�u�Q��.�� +�|� ���Y�_�6��g�VQ�^�^��.���΃�.�� ������.+�~����.���P� ��*Ҋ���.��Y^������V��*Ҁ�Pr�O����F
�u��Ѐ�Pr�O����v��*�:vv�v�V��*Ҁ�Pr�O����:v���v�c��V�v���V�v����:v
}�v
�7����Nt

�F���F�����F<u��x�<u����<u�~�t�䈀���<u�̀��<u�p�~�u��$w����������
��<u�~�u��p����������
�뜀�뗁~�u�,|<<�؀��.
�^�,,
|(<�؀�.
�f�,
|<��.��^R�V���Z����F��}*�:Fw�^��}*�:^w:�w
�F
�^��*����v��*�:vv�v�u��F
�u���:vr�v�_��
�
�
�
�
�
�
�
y��
"�
_�
�
�
�
�
�
�
�
�
�
�
�
�
��
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
2;�
�
�
�
{
{
�
�
�
�
�
"�
�
�
�
�
�
�
�
D�
�
�
�
�
�
�
�
�
�
�
�
�
��
�
�
�
��
~
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
{
{
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
#S�
�3@@y�
��Y�(���
��
�
�
"D�
�
�
�
�
��
�
�
�
�
���
�
Th�Y�
�
�
�
�
k�
�
�
�
'�
�
�
T�
�
�
�
�
�
�
�
�

 "$&(*,.02468:<>@@BDFHJLNPRTVXZ\^`bdfhjlnprtvxz|~�����������������@@�� �`�@@�� �`	
�
@@�� 
�
`�@@�� �`@@ `P0p�$ ���!�Ë$ ���)��  �ø�`�U���v�v�P�'��]������`��܋W+�����`�[XS�`[SSø�`�VWU���_^��܋W�G�ø�`���`���`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�V����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh�
�������Dž����Dž�_^���`��X��X[SSP�X���`�VWU��v�~t�~
jjjVh����
�+�����|��D�F�D�vh�v
Vh����
W�����_^���`���`���`���`���`���`���`���`���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy

X �I�p���G��
)�������{[]}\���@@����������~����������������������������������������������������������|��1234567890�'	qwertzuiop�+
�asdfghjkl��^�#yxcvbnm,.���� ����������������-���+�������<��!"$%&/()=?`�QWERTZUIOP�*
�ASDFGHJKL����'YXCVBNM;:���� ����������������-���+�������>��������cccccccccccc*06<BHNTZ`flrx~���������������������������������    
 ��������������������7?w8?x9?y4?t75?u6?v1?q2?r3?s[@@0?p.?n/_-*�
��Kttstart_ismmfunc_	Ksleep_mmtim_Kttopen_main_VIDSLOW_8 clrivec_�mmbeeps_pollopen_�mm_voff_nint11_�mmcrtsav_ super_�uexit_�mmgo_vinitkeys_�mmwatch_�isuload_Gupdleds_a
Kdefend_nondsig_�isclose_ Kclrivec_setivec_Kpollopen_sphi_�boot_�ldrvipc_u_isioctl_pputchar_
ldrvics_Kint11_isread_Idrvl_ldrvcon_inb_�Kuexit_Ksuper_nulldev_�outb_�drvn_getubd_�timq_isload_�ldrvsel_Knondsig_istty_agmaptab_`ttsetgrp_�isspecial_zKsetivec_xcalledttclose_VKboot_ttin_`kbunscroll_�
ttout_~con_Kldtimcall_Kputchar_isfunction_ldrvint_ttioctl_jttread_�mmwrite_�islock_Kgetubd_defer_�cprocp_kcall_�timeout_Kttsetgrp_isturbo_�mmstart_�
Kttclose_mmtime_�
Kttin_Kttout_ucs_uds_mm_von_ywakeup_�Kttioctl_isopen_XKttread_spl_�Ktimeout_ispoll_�printf_putubd_ldrvpsy_mmesc_mmvcnt_  ttstart_�getcs_�Kwakeup_isrint_�sleep_�ttopen_tiscon_�Kprintf_KldeferKputubd_isbusy_0';'$*$*0-05'?#'J$$Q0T0\'b;$e'h;$k'o; q'u; w'~#'�\'�$'�;'�P'�.'�;'�;$�0�'�F$�'�;'�;'�#'�$'�.' 'P0'# '-'407'J,0_0p0�$�$�'�$�$�$�$�$�0� � � � � � � � � � � � $�0�00
00$'+# 005$;0>0O$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�$�'f$m0t'|$�0�0�$�$�0�$�$�0�0�0�%�%�%�$�%0&$,01$6090@@$T0W$^$d0g y � � � �0�$�0�0�0�$�$�$�$�$�$�$�$�$�$�$�$$$% %$04%I%Q%`0p%�$�$�0�$�'�i$� �0�'�i0�0�00%%%01%4%>%J0X0^%b%i0l r � � �%�%�%�%�%�0�$�0�%�0�$�%�0%	00%%)0,$/%80=%F0K%T0Y%b%q0t%}0�0�0�%�0�$�0�%�$�%�0�$�%�%�$$%#0/0:0I0T%[0c%l%s$�$�$�$�$�$�$�$�$�$�$�$�$$$$$$
$$$$$$$$$$$ $"$$$&$(0� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ &$)0,%0$609%=$D0G$J0M%Q0W$Z0]%a%q0t%$�$�$�%�%�$�%�%�%�%�%�%�$�0	 *	 F	 H	 J	 L	 N	%R	%Z	%b	%j	'r	C%x	0}	0�	$�	$�	$�	$�	$�	0�	'�	i0�	'�	C0
%*
'1
C%7
0;
%I
0Q
%X
0[
0h
0s
%z
0�
%�
0�
0�
0�
%�
%�
 �
'�
0�
0''00#0-05'A'H0O0['b]'h]0m't]0y0� �'�0�$�$�$�0�0�0�$�0�$�$00'F0#0*'60=0J$Y'a0h " '�Q$�$�'
]0
0y
'}
]'�
 �
 �
 �
 �
 �
0�
 �
 �
 �
  - E0K0N ] h w �0� �0�0� �0�0�0 0!0N0Q0z0�0�0�$�0�$�0�0�0�0�000010>0W0~0� � � � � �0�0�'�C0�0� � :0N X0f n0|'�C0� � � � � �0�0�0�0�0 0*00090B0O0R0a0i0u �  0%0R0f0| ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @@ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @@ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z | ~ � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �      
             " $ & ( * , . 0 2 4 6 8 : < > @@ B D F H J L N P R T V X Z \ ^ ` b d f h j l n p r t v x z |$p${$�'�7'�5'�g0�'�D'�5'�!'�5'�5'�/'�5'�'�5'f'5'='5'h'5'%'4 '@@'G'V'^P'b 'k?'q40t'{'�'� '� '�P'�'�0�'�'� '�'�5'�''�5'X00'0,';<'BX0E0L'WL'Z5'aN'd5'kT'n5'u'x5'O'�5'�V'�5'�I'�5'�'�5'�&'�5'�a'�5@
0707070064030111211004440000030000030000011777770507310765500004500000012707/newbits/kernel/USRSYS/ldrv/RCS/ms,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.43;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�	�Dx8���v�v�v�Ѓ��VW��6�t;6|Vh�	�-��j�]	��k�
��u���ヿtVh�	���j�6	�����	���	����k�
LJ����LJ�������>t
����P���jjhh�	�n����G$t�>�	uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W��������LJ����LJ��h����+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v������͋^����G�j����_^�VWU��>�	t
�v
�v��	���>u��	�_^�VWU��>�	t
�v��	����	u	h�	�����_^�VW���	�D
��	@@�F
��	@@@@�H
��	�J
�+�F�h��6J
�,��j�6H
� ��hP�6�	�;���v����+��_^�VWU���6�	���h��6J
����j�6H
�����_^�VW��v�����F��>>
t�'P��������h��6J
���jZ�6F
����6F
�R��=Zt
��v���h��6H
�n���6D
�,��h��6H
�W���6D
���h��6H
�@@���6D
����h��6H
�)���6D
����j�6H
���jh
hT
���jjh
hf
���Phb
���jh 
hj
���jh$
hn
�w��+����

�>
�v����+��_^�VW���F�j�6H
���+����>
�v��}��+��_^�VW��g�F��~
|�~
s�v�^
�����	������v��;���>t����+��_^�VWU��f
���f
���
#

u�~t	hL
����
#

u�f
���F
�_^�VWU��jhT
�v�D���>^
u�^
�>`
u�`
�_^�VWU��jhb
�v����&

���_^�VWU��j�vhb
�t���&

���_^�VWU��jhj
�v�����_^�VWU��j�vhj
�@@���_^�VWU��j�vhn
�)���&

���_^�VWU��j�vh

����_^�VWU��jh
�v�w���

#
ujh�h�h

�������
�_^�VW��>>
u����F�h��6H
�����6D
����F�h��6H
����6D
�r���F��~����F�%ǘ�F�h��6H
����6D
�F���F�h��6H
�n���6D
�,���F��~����F�%ǘ�F�j�6H
�C��+��F��F��F��u�F��n
%3F�t�~�tjj�jj�I���F� u�F��n
%3F�t�~�tjj�jj����F�F�n
�~�u	�~�u���F�j
�F�l
�v��A��;T
�v��2��;T
~�f��f��~�t7�F���@@
�F���>^
�@@
�F���>^
b
�F��6X
�6V
P�����b
�~�t7�F���B
�F���>`
�B
�F���>`
d
�F��6\
�6Z
P����d
�b
;f
u	�d
;h
t�

jhb
hf
����

#
th

�O���>R
t	hL
�����v������_^�VWU��k^����p
jhb
kFr
P�N���F
	

�_^�VWU��F;F
}�F
��F;F~�F�F�F�_^�VWU��~}�F����F�_^�VWU��N�	�v
�~��F��]_^Ì���܋W+���[XS�`[SSø�`�VWU����_^�VWU���_^��܋W�G�ø�`���`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�R����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`��X��X[SSP�X�VWU��v�~t�~
jjjVh����
�+��������D�F�D�vh�v
Vh����
W�����_^���`���`���`�ldrv:%d: bad dev
ldrv:%d: dev bsy
<

i�&&&�44�=J{����������@@d@@d@@d@@d@@dmsunload_=ms_readcrs_�Ksleep_MSPORT_�	main_Kukcopy_Kkucopy_clrivec_�pollopen_HKpollwake_nonedev_&ms_setmick_�uexit_�	ms_setup_JKdefend_Kclrivec_setivec_fKpollopen_ms_wait_sphi_0	ldrvipc_u_msclose_�abs_�ldrvics_drvl_ldrvcon_inb_Kuexit_nulldev_4outb_>drvn_msioctl_�timq_ldrvsel_blkmv�Ksetivec_xcalledms_readmick_�msload_�con_Kldtimcall_ldrvint_cprocp_kcall_timeout_>	ucs_MSIRQ_�	wakeup_�	ioctls_�	spl_4	c_range_�Ktimeout_msopen_ims_readbtns_�ms_setcrs_{printf_\ldrvpsy_getcs_mspoll_ms_readstat_Kwakeup_sleep_&	ukcopy_�	kucopy_button_ymsintr_PKprintf_pollwake_Rmscon_�	0'('$$*0-05'?'J$Q0T0\'b($e'h($k'o( q'u( w'~'�9'�'�('�.'�"'�('�($�0�'�+$�'�('�('�'�'�"''.0'#'-'407'J!0_0p0�$�$�'�$�$�$�$�$�0� �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 �	 
 
 
 
 
$�%�$�%�$�%�$�%0%
0%0 "$&0)02$D0G%Q0T%]0`0s$}'�0�0�%�0�%�0�%�0�'�%�0�%�0�%�0�%�0�%�0�%0%0%0%&0)$1%407$A%D0G%N0Q$Y%\0_$g%j0m'u$y$}0�0�%�0�'�$�0�0�$�'�'�0�'�$$"%-00$6$:%R0X%_%f%l%s%�0�$�%�0�$�%�0�%�0�%�0�$�$0$0%$+$/$<0?$H$X0^0a%k0n%u0x%�0�%�0�%�0�%�0�%�0�%�0�%�0�%0.%@@0[%g0v%}%�0�%�0�%�$�%�$�%�%�%�%�0�%�$�%�$%	%
%%0%"%%%)%.%2$8%?%B0E$K$O$T0W%^%d0g0p%�%�%�0�$�'%'' %'-'I'L%'S	'V%']C'`%'m'|'�'�'�'�.'�'�*'�$0�'�'�'�'�'�.'�'	0	'	'	''	'*	%'Z	40]	0e	0j	'y	)'�	40�	0�	'�	'�	%'�	'�	%'�	='�	%@
0707070064030111201004440000030000030000011777770507310765600004600000017470/newbits/kernel/USRSYS/ldrv/RCS/msg,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.44;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@,��i���v�v�v�Ѓ��VWU����6�t�;�V�2P�Q���P�����.�.��؃�u���ヿtV�DP�!��+�P�Z����.��0������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P�,P�����G$t�>,u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W��
������LJ����LJ�ϸP����+��G��}5���㋇�F��~�t���ȋ^��G;�u+�PPPS��
���ҋ^����+�P�%����]_^�VWU��>.t
�v
�v�.���>u�,]_^�VWU��>0t
�v�0���,u
�,P���]_^�
VWU��>pu��>pu�]_^�VWU��v�F
-M=v������.��<Dv���DP����P�DP����P�DP���P���PV�����DP���P�DP���P�DP���P��̍DP�s��P�DP�h��P�DP�]��P�DP�R��P���뛍DP�?��P�D
P�4��P�DP�)��P�DP���P�DP���P�DP���P�����P��]_^�VWU���
�>xu�t�>zu�t�>tu+���>t�v�t��P�
P�x+�RP�q���F��V��P�:P�t+�RP�V��F�V��F��V��~�	|�~�@@v
�|P��
���$�F�P�6�;
���p�u���F�P+�P�6p�X
���t.�.:
p�r�z+�RP�xRP�����F��V��~�|)�~��v#��P�g
���6p��	���t�p���P�v��v��R
���
�>
u�6x��P�&
��뽋6p�F��F�;ts!����D
�D*�D.�D,�D2�D6�D4�F���:�֋6p�x.�.<
r����
��;rr/�z+�)F�V��F��E�D��|���6t��P�	���t��]_^�VWU��P�~~�F�.�>>
;ts�>pu������F�.�>>
.�.:
p���t��D�tփ~
t�D
;FuȋF
=v�����.��Vk�\V��������u�
��*P�vV����|,t*�΃�*�D,;�t�FP�y��
P�FP�����|4t*�΃�2�D4;�t�FP�I��
P�FP����D
;Fu�,��$�>t�;t���FP����F��>t���>t;Dw��v������F@@@@P�����D�d��FP���%�	D�F��D��>t�;u��D���t��D�p�G����p�Gt�g��S�k	���p�0t
�p*P����D�D�D�D
%�=�u�d
�D
�DtV�$	���|0t
�D*P�z���|8t
�D2P�j���D�>t���+���]_^�VWU��P+��>pu����>pu���F%��F��t.�.:
p����:��;pvg�D�u�t�E&�U(;T(|�;D&v؋��ԋFF
t̋F�V
;Tu�;Du��Ft�Ft������D#F�;F�u��
���Fu��׋Nj��u����D�D�D�D�v�D�D�D�D�D �D"�D$���D&�T(���D��D�D�F�
��D�F�V
�D�T�D
��]_^�VWU��~~�F�.�>>
;ts�F;zw�>pu�����e�F�.�>>
.�.:
p���D
;Fu��D�t�V��������u�
���p�t�D;Dwi�Ft�롋D;Dw�L+�PP�PV��p�O+�PP�PS�D����G$G&t��t��V��F;D
t��!�F��p��F�E�P�EP�v
�g���v�
�w�u�F
P���;Ft��>t�����p�G��|t�\�?��|�|�FD�D��G�D���D�T �Dt�d��V�*���|0t
�D*P���+�]_^�VWU����~~�F�.�>>
;ts�>pu�����B�F�.�>>
.�.:
p���D
;Fu��D�t�V��������u�
���|�F��~y~�F��F��F�V���؃��F�V�t?�E�U;V|;Fv�~��=��~�t�^��E�U;W|�;Gsމ~��F��F��Ӌ~��F��F��F�V���؃��F�V�)�~x#u�~t�t�E�U;Vu;Ft�~��=���uQ�Ft�����L+�PP�PV� ����G$G&t���t�����F;D
u����!���F;Es�Fu����F;Ev�E�F�P�v
�EP����v�F
P�
�w�u���;Ft��>t�S��~�t	��^�����D;|u�F��D�E)D�L��G�D���D"�T$�Dt�d��V�����|8t
�D2P�B���6p�D��|�Dt�d��V����p�0t
�p*P����F��]_^�VWU��~~�F�.�>>
;ts�>pu� ��F�.�>>
.�.:
p���D�t�D
;Ft��m�f
���F
t"�|u�~t
�D*P����f
����F�F
t5�D;Dr�~t"�D2��>p�}u�~t
�p*P�E���f
���F
]_^�:
VWU��v�>u���/�;t;Du�D��;Dt;Du�D���D���%�]_^�VWU���FHFr(;w"��ۋv�~
�N��������F]_^�+�]_^�VWU���FHFr�;w��~�v�N��������F]_^ø�`���`������`�[XS�`[SSø�`�VWU��N�F
�~��F]_^ø�`�VWU���]_^�VWU��]_^���`���`���`���`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�%����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P���������Dž����Dž]_^���`�VWU��v�~t�~
+�PPPV�P����
�-����v��D�F�D�v�P�v
V�P�i���
W�d��]_^���`���`��Ë܋_��Ë܍_VWU��P�F�'����F�g��F
�'��֋�[��]_^���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
�fXXXffff	
�invalid NMSQID or NMSG kernel variable
invalid NMSG or NMSC kernel variable
could not salloc %u messages
could not kalloc %u message ids
timer_ahigh	
free_bhigh	Ksleep_main_Kukcopy_Kkucopy_clrivec_pollopen_pputuwd_�Kpollwake_Count	Kfree_ipcaccess_@@
nonedev_Xuexit_�NMSC_zKdefend_nondsig_Nsetivec_�Kclrivec_sphi_Kputuwd_Kpollopen_ldrvipc_NMSG_xu_ldrvics_drvl_ldrvcon_Kuexit_msgs_rnulldev_fdrvn_msginit_$timq_umsgget_*ldrvsel_Knondsig_Ksetivec_xcalledsalloc_�msgpoll_zumsgctl_�con_Kldtimcall_NMSQB_vumsgsnd_eldrvint_msqs_pudl_umsgrcv_
msgcon_Vcprocp_kcall_ timeout_nKsalloc_alloc_�
memset_6ucs_uds_NMSQID_twakeup_spl_"getuwd_vlmul�Ktimeout_printf_�alow	allkp_ldrvpsy_blow	Kalloc_ufcopy_�
fucopy_�
getcs_vrmul�Kwakeup_String	sleep_dKgetuwd_kucopy_,ukcopy_�L0�Kprintf_Char	
pollwake_z0'-'%"$-010; E'K'V$]0a0j'p-$s'v-$y'}- '�- � �'�'�G'�'�-'�<'�&'�-'�-$�0�'�6$�'�-'�- �'''&','0<06'A'K'R0V'l$0x0�0�$�$�'�$�$�$�$�$�0� Z \ ^ ` b d f h j l$0$'01 : < > @@ B0I0T0_0f0n0t0{0�0�0�0�0�0�0�0�0�0�0�0�0000'$.$5$;$B$H0P$T$\$i0p$�0�$�0�0�'�F0�$�0�$�0�$� �$�$�$�$�0�$0$"0%$,$2070D%J%N$U$X0\$e$q$�$� �$�$�$�$�$�0�$� �$�$'0  !$%0K T V X Z0^'m0q0|0�0�0�0�0�'�0�'�'�'00'0"'&040B0W0i'm's$�$�0�$�$�0�0�0�0'0 $40:$>'E0I$U Z$^$i'�0�0�'�'�'�$'*'.'7'? w${$�$�'�0� � �$�0�'�$�'�$
	0	'%	600	'8	0<	'H	0L	$P	0g	%q	0�	'�	'�	0�	$�	'�	6'�	'�	0�	0�	 
$
$"
')
00
 9
 >
$B
0W
'f
'-010B'I60T'\0`0k'o0s'�0�0�%�0�'�'�0�'6''0&06$=0U$\$e0l �$�$�0� � �$�0�$
$"
0)
'J
'U
'f
'�
3'�
='�
3'�
='�
I')'	
')'Q')'$)'-'0)'O''R)'_'q't)'{'~)'�U'�)'�'�)'�9'�)'�'�'�'�'�'�<'�'�1'�(0�''''1'5<';'B0F'Q'['e'h)'�C0�0�0�'�.'�C0�0�'�'�)'�'�)'N')@
0707070064030114721004440000030000030000011777770507310766000004500000006146/newbits/kernel/USRSYS/ldrv/RCS/qq,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.47;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�D
�$���v�v�v�Ѓ��VWU����6�t�;�V��P�����P�;����.�.��؃�u���ヿtV��P����+�P���������������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P��P�G����G$t�>�u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�������LJ����LJ�ϸP����+��G��}5���㋇�F��~�t���ȋ^��G;�u+�PPPS����ҋ^����+�P������]_^�VWU��>�t
�v
�v�����>u��]_^�VWU��>�t
�v������u
��P���]_^�
VWU�������P�P�6��6��������]_^�VWU���6��6��B��]_^�VWU��]_^�VWU��]_^�VWU��P�v
�|t8�����RP�u���F�VP���=��t�����.�>����‹�]_^�VWU����v
�F�V�J���F��|"�~�}P�F����RP�'���F��Ћ�]_^�WU���~+�&�]_������`���`�[XS�`[SS�VWU��]_^���`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�}����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P�0�������Dž����Dž]_^�WU���~�F&�]_ø�`�VWU��v�~t�~
+�PPPV�P�����
�-�M�����D�F�D�v�P�v
V�P����
W�*��]_^���`���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
GP$Y�$$$�0$qqcon_�Ksleep_main_clrivec_�uexit_xKdefend_setivec_BKclrivec_sphi_�ldrvipc_u_ldrvics_qqclose_Pdrvl_ldrvcon_Kuexit_nulldev_$drvn_iogetc_timq_ldrvsel_Ksetivec_xcalledqqread_Yffbyte_�con_Kldtimcall_ldrvint_Kiogetc_cprocp_kcall_timeout_ ptov_8ucs_qqwrite_�sfbyte_wakeup_�spl_�vrelse_�Ktimeout_printf_.Kptov_qqopen_Gioputc_ldrvpsy_getcs_Kwakeup_sleep_Kvrelse_Kprintf_Kioputc_0''%$-010; E'K
'V$]0a0j'p$s'v$y'} '� � �'�
'�,'�'�'�!'�'�'�$�0�'�$�'�'� �'
''','0!06'A'K	'R0V'l0x0�0�$�$�'�
$�$�$�$�$�0� � � � � � � � � � � �%%%%0 %&%*%7%;0>%i%n%r0w0�%�%� �%�0�%�%�0�'''2'''/1'2'9)'<'I
'X'd	'k
'z	'�!'�'�'�0�'�
'�	'�'�'�!'�
'�0�'�	'�''';'0?0G0L'['c'0g0n'y'|'�0'�'�.'�@
0707070064030114711004440000030000030000011777770507310766100004500000007115/newbits/kernel/USRSYS/ldrv/RCS/rm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.48;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@�DX�3���v�v�v�Ѓ��VW��6�t;6|Vh�����j�3��k�
��u���ヿtVh�����j�������������k�
LJ����LJ�������>t
����P���jjhh��R����G$t�>�uރ>t
����P���k�
LJ����LJ����LJ+���}.���㋇;tG��W�������LJ����LJ��h���+���s=���㋇�F��~�t)�^��G�F��;F�ujjj�v�����͋^����G�j�����_^�VWU��>�t
�v
�v�����>u���_^�VWU��>�t
�v������u	h�����_^�VWU���_^�VW��F��~�}%k^�,�������tk^�,����������F����_^�VW��F%�����k�,����N����+҉F��V���T�F��V��~
u�t0�F�F�t�F�F�t�F��V�;V�u;F�u�F�F�u�F�F�u��o�F�F�td�F�F�u\h0��F��V��	�������������RP�o���D���u��,�F��V���T�E�U�D�T�D*jhRP����D*�_^�VW��~�����k�,����~����+҉F��V���T�F��V��t�F�F�t�F��V�;V�u;F�u�|*u��*�L*�F�F�u�|*t�'��t�{����D�_^�VW��v�D�F�%�����k�,����N�����+҉F��V���U�F�V��t�F��V�;V�u;F�t�L��F��V���������F�V��D��	�ȋ�+�D
T-��;V�w�r;F�s��D
�T�	������EU�F��V��|u�D+�RP�t�t�v��v���D+�RP�v��v��t�t���V�d���_^�VWU��v��%�����k�,���h@@�jV�v
W�D��
�_^�VWU��v��%�����k�,���h@@�jV�v
W���
�_^���`������`�[XS�`[SS�VWU����_^�VWU���_^���`���`���`���`�VWU����f�~�烽u�~�烽t�'�J�~��F
���~�����~�����vh�\����>t�~��Dž�~��Dž�_^�VWU��v�����狅;t��Vh��������Dž����Dž�_^���`���`�VWU��v�~t�~
jjjVh����
�+�A�����D�F�D�vh�v
Vh����
W� ���_^���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
!
����Ksleep_main_clrivec_�Kioreq_nonedev_uexit_jKdefend_setivec_@@Kclrivec_sphi_~ldrvipc_u_pclear_ldrvics_drvl_ldrvcon_Kuexit_nulldev_drvn_timq_ldrvsel_Ksetivec_xcalledsalloc_6con_Kldtimcall_Kpclear_ldrvint_cprocp_kcall_�timeout_bdone_�Ksalloc_plrcopy_"ucs_wakeup_tspl_�Ktimeout_Kbdone_printf_,Kplrcopy_ldrvpsy_sfree_getcs_�Kwakeup_sleep_
Kprintf_rmcon_�Ksfree_ioreq_�0''$$*0-05'?'J$Q0T0\'b$e'h$k'o q'u w'~'�)'�'�'�"'�'�'�$�0�'�$�'�'�'�'�'�'
'"0'#
'-
'407'J0_0p0�$�$�'�$�$�$�$�$�0� � � � � � � � � � �%%%0%6'�0�'�0�%'b'z0�%�0�0o0v%�0�%�0�'�&'�'�'�'�''''#('&'-.'0'7 ':'G'V
'b
'i'x
'�"'�
'�'�0�'�'�
'�
'�
'�"'�'�0�'�
'�
'0''''0%030;0@@'O'V%0Y0`'k'n'u,'x@
0707070064030111171004440000030000030000011777770507310766200004600000011744/newbits/kernel/USRSYS/ldrv/RCS/shm,vhead     1.1;
branch   ;
access   ;
symbols  ;
locks    bin:1.1; strict;
comment  @# @;


1.1
date     91.07.15.14.14.50;  author bin;  state Exp;
branches ;
next     ;


desc
@initial version prov by hal
@



1.1
log
@Initial revision
@
text
@n	l�����v�v�v�Ѓ��VWU����6�t�;�V�t	P�����P�	����.�.��؃�u���ヿtV��	P���+�P������p	��r	������.�.���LJ����LJ�������>t�Ʊ��P���+�PP�P�n	P�����G$t�>n	u܃>t�Ʊ��P�����.�.���LJ����LJ����LJ+��G��}+���㋇;u�W�c������LJ����LJ�ϸP�z��+��G��}5���㋇�F��~�t��J�ȋ^��G;�u+�PPPS�e���ҋ^����+�P�����]_^�VWU��>p	t
�v
�v�p	���>u�n	]_^�VWU��>r	t
�v�r	���n	u
�n	P�a��]_^�
VWU��>�	ta��	.�&v��W�6�����u�6�	��	P������	�/��	.�.x���	.�.x����&��;r�D��+�]_^�VWU����v
�D�F��D�F�;�	r������F�.�.x���E�u�!��W�C������u�
�ȋE��F�V��F�+ҋ؋ʋD��;V�w�r;F�w��^�����G�F��F��F��t�t�v�P�o���u�o��D+���]_^�VWU����v
�D�F��D�F�;�	r������F�.�.x���E�u�!��W��������tʋE��F�V��F�+ҋ؋ʋD��;V�w�r;F�w��^�����G�F��F��F��t�v�P�t�{���u�v��D+���]_^�VWU��F
=CHt=GHt8��x�FP����P�FP���P�F@@@@P���P�U���=�FP���P�FP���P�FP�x��P�F@@@@P�k��P���P�v���]_^�(&VWU��P�F��>t������F;�	r���F.�.����D�t�F
=v�����.���E��V�'������u�
른&P�vV�����F��|�>t�;t��b�v�����F@@@@P����D�d��FP���%�	D밃>t�;u��D
�~��>�5�|���D���F����F���]_^�VWU��P�F��>t����Z��	.�.�����&��;s��D�u �~�t�~��E"�U$;T$|�;D"vЉv��ˋFF
tËF�V
;Tu�;Du��Ft�Ft�늋~����D#F;�t�
�q��D;Fr���^��Fu��O��~�u��A��v���+�.�>�����>�@@P�F+�RP�����tʋF�D�D�D�D�D ���D"�T$�>�E�D���D��D�D�F%�
��D�F�V
�D�T�FF
u�L��+�.�>���]_^�&VWU��v�>u���/�;t;Du�D��;Dt;Du�D���D���%�]_^�VWU���FHFr(;w"��ۋv�~
�N��������F]_^�+�]_^�VWU���FHFr�;w��~�v�N��������F]_^ø�`������`�[XS�`[SSø�`�VWU���]_^�VWU��]_^���`���`���`�VWU����f�~�烽u�~�烽t�'�K�~��F
���~�����~�����v�P�[����>t�~��Dž�~��Dž]_^�VWU��v�����狅;t��V�P��������Dž����Dž]_^���`���`�VWU��v�~t�~
+�PPPV�P����
�-�C�����D�F�D�v�P�v
V�P����
W� ��]_^���`���`��X��X[SSP�X�ldrv:%d: bad dev
ldrv:%d: dev bsy
���q,�����couldn't kalloc %u shared memory ids
timer_Ksleep_main_Kkucopy_clrivec_�putuwd_
ipcaccess_�nonedev_�uexit_L	Kdefend_setivec_Kclrivec_sphi_`	Kputuwd_ldrvipc_u_ldrvics_drvl_ldrvcon_Kuexit_nulldev_�shmsegs_drvn_timq_ldrvsel_ushmget_�Ksetivec_xcalledsalloc_ushmctl_zcon_Kldtimcall_ldrvint_NSHMID_�	udl_cprocp_kcall_�timeout_�shmids_shmcon_�	Ksalloc_alloc_�ucs_uds_wakeup_V	spl_d	getuwd_�Ktimeout_printf_allkp_ldrvpsy_sfree_�Kalloc_fucopy_�ufcopy_Dgetcs_�Kwakeup_sleep_�Kgetuwd_kucopy_�Kprintf_Ksfree_0''%$-010; E'K'V$]0a0j'p$s'v$y'} '� � �'�'�2'�'�'�*'�'�'�$�0�'�#$�'�'� �'''','0*06'A'K'R	0V'l0x0�0�$�$�'�$�$�$�$�$�0� �	 �	 �	 �	 �	 �	 �	 �	 �	 �	$$ '10' &$($+0/$6$= B'F&'I$L Q'U&'`&$�'�0� �'�&'�0�'�'�00$E'K0R Z'^&'k0r'�0�0�'�0000#020@@0N0[0b0l'�0�$�'� �'�&0� � � � �0�'�0�'�''00#08'G'M']0b'p'�0�$� �'�&'�&0�''0 0+'/03'>0B'L0P'Y& _'g0u'�'�'�#'�'�'�& �'''"'V"'\+'�"'�+'�4'�'�:'�'�'�'�'�'<''
''(''%'4'@@'G'V'^*'b'k 'q0u'|'�'�'�'�*'�'�0�'�'�'�='�'�'�'	/0	0	0 	'/	'7	/0;	0B	'M	'P	'W	8'Z	@
0707070064030112201007550000030000030000011777770507310766300003600000000574/newbits/kernel/USRSYS/usrsrc# back up USRSRC directories
TMPFILE=/tmp/usrsrc.$$
rm -f $TMPFILE
cd $USRSRC
for DIR in i8086/drv i8086/drv/tools i8086/ibm_at i8086/src coh ttydrv ker ldrv
do
	for FILE in `ls $USRSRC/$DIR`
	do
		echo $DIR/$FILE >> $TMPFILE
	done
done
echo "$TMPFILE created"
echo -n "Insert 3-1/2\" formatted diskette and press <Enter> "
read JUNK
cpio -ocv < $TMPFILE > /dev/rfva1
rm $TMPFILE
0707070064030112161007550000030000030000011777770507310766300003600000000516/newbits/kernel/USRSYS/usrsys# back up USRSYS directories
TMPFILE=/tmp/usrsys.$$
rm -f $TMPFILE
cd $USRSYS
for DIR in . ldrv doc confdrv lib
do
	for FILE in `ls $USRSYS/$DIR`
	do
		echo $DIR/$FILE >> $TMPFILE
	done
done
echo "$TMPFILE created"
echo -n "Insert 3-1/2\" formatted diskette and press <Enter> "
read JUNK
cpio -ocv < $TMPFILE > /dev/rfva1
rm $TMPFILE
0707070064030110611007550000030000030000011777770507310766300003500000002614/newbits/kernel/USRSYS/Build:
:  Build a Coherent executable with a host adapter driver linked in.
:
DRIVERS="rm fl lp mm"
COH_TYPE=fl
HD=""
KB=nkb
for ARG
do
	case $ARG in
	at|aha|ss)
		HD=$ARG
		COH_TYPE=$ARG
		;;
	kb|nkb)
		KB=$ARG
		;;
	*)		echo "Usage: $0 { at | ss | aha } { kb | nkb }"
			exit 0
			;;
	esac
done
DRIVERS="$KB $HD $DRIVERS"
echo "Kernel:    /coh.$COH_TYPE"
echo "Devices:   $DRIVERS"

: default root/pipe device
BOOTDEV="fva0"
echo "Default root/pipe device is $BOOTDEV."

( cd /usr/src/sys/i8086/drv; make -f Makefile install )	|| exit 1
./config ibm-at $DRIVERS root=$BOOTDEV			|| exit 1
cp coherent /tmp/coh					|| exit 1
strip /tmp/coh						|| exit 1
set `ls -s /tmp/coh`
SIZE=$1
rm /tmp/coh						|| exit 1
echo "Coherent bootable limit is 138 blocks.  This kernel is $SIZE"
if [ $SIZE -gt 138 ] ;then
	echo 
	echo Your Coherent image exceeds the bootable limit of 138 blocks
	echo by `expr $SIZE - 138` 'block(s).'  You will need to decrease the
	echo size of your kernel in order to make it bootable.
	echo
	echo We suggest removing some of the non critical drivers from the
	echo default list of drivers linked into Coherent.  These additional
	echo drivers may then be linked as loadable drivers using the
	echo ldconfig script located in this directory.
fi
mv coherent /coh.$COH_TYPE
chown sys /coh.$COH_TYPE
chgrp sys /coh.$COH_TYPE
chmod 400 /coh.$COH_TYPE
echo "New kernel in /coh.$COH_TYPE"
ls -l /coh.$COH_TYPE
0707070064030050621006440000000000000000011777770507310766400004200000173363/newbits/kernel/USRSYS/atkernel.o����	<x-9&��.�	+��d�������d+��d�������`+��d����6�C�����@���.�@���� ��� �!����!����!�����!���+����[��f��q�
�|�������������� ��"�$��&�(��*�,��.�0��2�4��6�����������d��������(����4����@����L����X����d����p����|��������������������������O����r��������%���>��u������������������؎м���œ�Ĝ.����+������.Ĝ����+���&��&9u����@;.��r�Ĝ������%��3Ѓ>��t
�������������%��3������������+������+��󫡠�����%��3�����������+�����+������ϸ���������3�%���3«+���׸���������3�%���3«+����+�������3�%��3�™����«+���>�������������3�%���3«+���>������������3�%���3«+��������������3�%���3«+�������������3�%���3«+�������������3�%���3«+�����+���+�+��˹����;ø�t+��+����Ў؎������
����+�а�p��q�����p��q�����+��������������D�D��D+�+����D�T��&��&9u��B6;��}���|��D�ӎێã������G�ʏ���G鿏���G鴏���G驏���G鞏���G铏��G鈏��G�}�X��G�q���G	�f�X��G
�Z�X��G�N�X�u�G�B�X�i�G
�6��^�G �+��S�G!� ��H�G@�&���<�G@�&���0�G@�&���$�G@�&����G@�&����G@�&����G@�&����
�G	@�&����
�G
@�&����
�G@�&����
�G@�&����
�G
@�&���
�G@�&���
�G@�&���
�G@+�P�w�>��u��G"�u���G�h���<r� 栰 � �WU��V�~
�N�����]_�VU��V�v
�N������]^�VWU���v�v�v�v�	������v�v�v
�v�	���Ǝڋ��N��������ƌ�VP���WP���]_^�VWU���v�v�v�v�M	������v�v�v
�v�7	���Ǝڋ��N�N�O����������ƌ�VP�
��WP�
���F]_^�VWU���v�v�v
�v�����‹��n�^�N+����PP�h
��]_^Ë܋GHGs�;̜v��6ʜ�VWU��+�P�v�v�v����‹��^�v
�N���������PP�

���F]_^��Ë܋GHGrS;̜wM�6ʜ�VWU��+�P�v�v�v
�2���ڋ��F�~�N���������PP�	���F]_^��û��+��.�	��+��d�������d���VWU��v����=u�	�t
���㋇��=�t��'�Z����F
������|,�h��&�����ރ��������#�Wh�����j!�������������#�Wj!�����_^�VWU��v����=u�	�u
Vh��TR������LJ�����|*�h�������ރ�������Wh�������u�>uj!�t����������Wj!�j���_^�VW��v�N��|�n�~�^
�F
�V+����F
V�F+�F
V+����F��V��F
�V+���;V�u;F�t+�����
�F���}1+��~t
��%
H���%
DP��P��
��j��P�*���~t
��%
H���%
DPh��
��jh��
���F
�V�������P��������}
����}	��%�����%������F
PW�X
���F
��PW�J
��G��|G�vW�9
���F��PW�+
���v��
����_^�VWU��v��}
��%Pj
�	��%Ph������_^�VW��v���F���}��%
Pj
������%��@���%
Ph������%�����W����F�W�����F��v��i���F���|�f��F��_^�VW��>�u��jj�6v�����~
uj
������F��F��F�F��F��F�P�6v��,���_^�VW��v�~
�F�P�v����F��u���DP�^���^���F��E�t��VW�G���F��u��F�D�D�^��G
�D+�RP�t�t����D�T�}u�J�Dt�@�E+�DT-��+���+DT�F�V��~�y�E�	�F�V�%��F��E�U�	�������F�V��~�t��v��F��F�;Ev�E�F��v��v��v�b
�����F��D�F�D�~t
�v��tW����vV�����Du�~u+�v��tW������D�^�G�D��G�~t�DE�LV�����v��8�F��D�F�D�F�V��D
�T�vV�w���Dt�D)F��F�)EE�F�D�DT�EU���t�t�H���^��O
�>t	h�V[���Dt�D���
�u���DP��\���_^�VWU��v�DA���	��V�v
����Dtjh�h�V�Z����W�	���_^�VW��	�F��F��F�����;6�t6�u�����6����P����u�j�6����P�����6��v��v��L	���F��V��_^�VW��>��tn����F��F
%���F��V���RP����F��F��V���RP����F��F��V���RP�|��P�v��v����P�v��v��v�hx��S���_^�VW��v�>��u#�D�T��������D�D�T%+҉D�����F��D�F��|u����D�T�u	h���L���D�F��Dt�v�t�th����K���F��V���RP�����u�v�t�thߛ��K����F��D�T-��P�v��v�����t�F��V���RP�l���t�F��V���RP�C����Dt�π�Dt��W�F��V���RP���j�F��V���RP����v�����_^�VW��>��u7jj�v
�v����F�V�F�V
��������������F�V�����F��V��u�F�Ph
���J������F��F��F���F��F�V-��P�v��v��z���v�F��V���RP�c���v
�F��V���RP�:��h��F��V���RP�#��j�F��V���RP����v�����F��V��_^�VW��>��u!�F+҉F�V��F
+ҹ������F�V��s����F��F
�F��V���RP����%�=�t�v
�vh'���I���F��V���RP����F��F��V���RP����F��F+�F�V��F��V��_^�VW��>��tc�~
t�F
t�v
hC��aI������F��F
�F��V���RP�6��%=t�v
�vh[��-I��j�F��V���RP�����_^�VW��v�΁�����;�v����N
����II�N�;�v
Vh����H���F���^��?�
����_^�VW��F
@��@�F��F��~�r��~�%��;Fu��u	h���H���u=�%���F��^��u	;Ft���F���F�+Ǚ.�>0�F�;F�r;F�v�~�u	�%����뚋F���Nj��F���5�
��v
�EP�G���E�
�F��_���#+��_^�VWU��FHH����r�u�vh����G���%����_^�����.H��lC����+��ʜ�Ɯ��ێÎӼtRQP�.���Μ���tC��`�v2T�6ΜS�PRQ�؎����W�܋G��@u��P�YZX����[��ρ�,���P�UG�М��G"�tNT�6Μ�6М�;tPRQ�؎����W�܋G��@u����몃����W�܋G��@u�����������ϻ��G��G��G��G��Ҝ�&Ԝ�Ĝ�g��6Ҝ�6Ԝ�6Μ�6М�PRQ�؎����W�܋G��@u���G"�t�2��eYZX�����М�Μ[���G��G��G��g��ێ�.���М�Μ�Ë܋_;̜v� �ʜ&�Ë܋_;Ȝv��Ɯ&�Ë܋_;̜v���ʜ&�*�Ë܋G�_;̜v���ʜ&�+�Ë܋G�_;Ȝv��6Ɯ+�P����+�S�6ȜRP�����܋G�_��&�R+�P�;���+�Ë܋G�_;̜wp�ʜ&�+�Ë܋GHGrY;̜wSVW�w��O���ʜ��������_^Ë܋GHGr(;̜w"VW�w��O���ʜ����������_^û��+��WU���~�F&�]_�WU���~�F&�]_�WU���~+�&�]_�WU���~&�]_�VWU���v�~
�N����������]_^�VWU���v�~�N����������]_^�WU���~�N+���������]_Ë܋G�g��Ëϋ܋�����ƫ�ū�ī���X��������+�����܋w�����ȭ�譋����P���������������Y�܋G�_�������+��g���������+Ͼ+������؁�������ȭ�譋����P����������Ã>t�VW��+������������+ο+����_^�ÜX�ÜX��X[SSP�X����������6�W+��Ë�6�W6�G�Ë܋_���&�Ë܋G�_���&�Ë܋G�_���&��VW��Ĝ�F��F����F��V��v��v�������؋ʡ�+�щF��t���P�6�9�����>u	h֜��B���t�H����;6r0�D���F��V��D�T�F��V��D�T�F��F��V��� ���_^�VWU��t�H����;6r2�Du�� ��DP�Q���Dt	jV�s���DP�Q�����_^�VWU��v�t�H����;>r:;ut�� ���EP�DQ��;uu�Et	jW����E���EP�TQ�����_^�VW��v�v�v
�v������Eu��t�e����MW�����E�E���F�W�v�����u
�v������+��W�Etjh�h�W�)N�����v�������Et�}t�E�����W�빁}t��t�������_^�VW�+��F��t�H����;6ry�D
�T;VuM;F
uH�D;Fu@�DP�P���D
�T;Vu
;F
u�D;Ft�DP�*P����Du���L���|u�+D;F�r���+D�F��� ��ug����F��t�H����;6r!�|u�+D;F�r���+D�F��� ���u �jh�h�h��L���v����f��v��������DP�JO���DtjV�*������D�F�D�F
�V�D
�TV�
�����_^�VWU��v�~
t�d����LV�����L�D�D����V�t�����~
t�Dtjh�h�V�CL����W������_^�VWU��v�|u�d���|u�Dt�D���Dt�d��V����d��V��L���_^�VWU��v�Du���D�
�d���D���d��V�8���DP�]N���>t�h�L���_^�VWU��v�L �_^�VWU��v�D t�d���_^�VWU��v�~
�=wH����.��Y_q}�vW�t��=��D�'�vW�t�����vW�t�t
����ȋ��D
T�F)D�_^�VWU��v�~
�=wH����.�������v�tW�=��D�'�v�tW�����v�t�t
W�M���ȋ��D
T�F)D�_^�VWU��v�|t0�L�<u�\�D��%�������D�DP�������>�t����_^�VWU��v
�|t/�L�<u�|�D�F��F��v�D�DP������>�t����_^�VW�
�v�~
�F�P�v�����F��u�5�DP�hL���^���F��F��t,�F@t�E�t�����F�tVW�����F��t�F
�D�F�D�F�D�t�E�U�	�������D
�T�E�D�~�t�D+�RP�t�t����D�T�^��G
���F�V�v�����Dtjh�h�V�6I�����v�������~�t�t�t�����^��O
�>t	h��I���Dt�|t�D�������t�E+D�F��EU)E�DP�qK���_^�VW��v�~
�<t	h��<���F�R��~���r��^��G�F��u�F���^��t�D�F�;Gr�^��G�W�F�V�^��G+�F�V�F��V��F�+ҋ؋ʋD��;V�w�r;F�w��^��G�W�F��V��^��N�+O��+�F�V��E�U�F��+��_^�VWU���+�;>j�}�<t��t�WG��
���_^�VW��v�F�PV������t�#Fu���
�v
V�U���_^�VW��v�F�PV�r�����tV�U���_^�VW��F�P�v�N�����t	�v
�T���_^�VW��v�~
�F�PV�$���F��tWV�^��W
���_^�VW��v�~
�F�PV�����F��tWV�^��W���_^�VW��v�F�PV�������t
�v�v
V�U���_^�VW��v�F�PV������tV�U���_^�VW��v�F�PV�}�����tV�U���_^�VW��v�F�PV�X�����u� � �t�v�v
V�U���F
��F
 �F
�_^�VW��F�P�v������u����<���_^�VWU��F��%���;j�r	��+��k�
����|u�<t�|��_^�VWU�����_^�VWU���_^��VWU�����+��n�.�.�"�F��F��n���F�;r	�v��<����>�>�����]_^Ë�U��n+�9FuH�V���v�^�@�NtC��~u3+ۋ�N;�u�^�^���69t��SRPQ�!FYXZ[�^��������]��Ë�U��N�n+����v�^;�u.�6;�u�������4����^;�u�v��7�v�؈HC��~u�؉^�F�n����]���VWU��v�R��V�����}�W�I��]_^�VWU��>u�+�PP�P�P�lD����]_^�VWU��>tr�>t�>t\�6�6��0���uR����T���>�E6=v�M6�6�6�l6�~
u
�DD�TF��D@�TB�F�����t��_^�VW����>T�d|�P��R��.T�d���>���>������%�+������(�F��5�Ƌ��tD�5�E�U;u�;u��]��t�E��G�E�v�����W�u
�U�������v���������>t:�+�;6j�},k�
�����uF����F�����P�?����v�������>&�t5�6&�����P��+$�P����� ���;>"�sW���@PW�����>�E$E&t��T��>�E"t�e"����>t	h�aC���>t$�	�F����;tV�kD����C�v������_^�VWU��>�E2��=��u���j�v
V�@����_^�VWU��>�u2�`����_^�VWU���v
�>�u2�����_^�VWU���v
�>�u2�����_^�VWU���v�v
�>�u2�����_^�VWU���v
�>�u2�����_^�X�P��6�G6�W�����������ϋ�;�t������������;�u��X�P��6�G6�O6�W
����� ��� �LJ��'������U�싇 ��� ��6"��^���]�VWU��v�>$�u+��V�F
�D�F�D
������>(�u�6(��6&�W�}�����;6(�uW�n���h*��';��&��7�6&�W�U�������_^�VW��v�7��F��>(�u	P�1����a;6(�t'�>(�;>&�t;5u��;6&�u
�>&���=���v��ˡ(�;&�u�(���(���(��v������6(��(��w
�W���_^�VWU�젿��=u����P��R������_P�Z1�d��G���u	�G���t�t�t�V,����W�+W���_^�VWU�����F�Dj��RP��D���F�u	hf���2���F�D�6�~�u�u�6�����~�MW�T��j��RP�D���F�u	ht��2���F�D�6�~�u�u�6���jjh�nD���F�u	h���_2���F�D
�*��fO�u	h���C2���T0�_^�VW�"��1�u����h'��)���F�P�F�P�F�P�v�?�����t֋F�%=
u&�F�F�t�F�F�u�F�F�u��;V�u;F�t��%V����뗋F�V�F�V�RPjj,�F�V�F�V�F�V�RPh8@V�F�P�A���F�V����~�}���K�h�(�:�����u
���v��_D�j
�]�G�W���RPh���z݃��F��E�E6��E8�E<�E�w�F�W��?���v��o���E�_^�VWU��kF
����EP�@���F;j�}����u����T�>�u��EP�@��+��_^�VW�6�>�F�P�F�P�F�P�v�������u���F�u��%V�����F�u�f��~�u�F�F�u׋F�F�u��v�v
�F�P�A���F��t��F�=t=t7�t�F֋V�F�V�F�V��F҉Vԋ^��G�WF�V�F�V�F�V��9�F֋V؉F҉V��v��v��6���FʉV̋^��G�WF�V�F�V�F�V̉FΉVЋFҋV����%��F҉VԋF΋V����%��FΉVЃ~�rw�~��s�~�wr�~��r������F��~�})�^���ߋG�F��t�^�����GP�HB���F��ыF��E
�F�=v�����.���,�,Z-R.�.�F֋V�F�V�F�V�F�V�F��V�RPjj,�FދV�F�V�F�V�RPjV�F�P��>���E�~�|�=V�������=u
�YMP�\:��j�T:�'��F֋V�F�V�RP�����F��V��v��v�jj,�FڋV�F�V�F�V�F�V�F�V�RPjV�F�P�V>���E�~�|��v��v֋F֋V�F�V�,��RP�v��v�V�u�^���u�S��v��v��F֋V�,��RP�v��v�V�u�3���u�(��FڋV�F�V�RP�F֋V�F�V�F�V�,��RP�v��v�V�u�����t�&����F֋V�F�V�RPjj,�F֋V�F�V�F�V�RPjV�F�P�|=���E�~�}���F�V�F�V�RP�F֋V�F�V�,��RP�F�V�F�V�F�V��U��v��v�jj,�v��v�jV�F�P�=���E�~�}�G��v��v��U���F��V��v��v�F֋V�,��RP�F�V�F�V�F�V�RPjV�F�P��<���E�~�}����v��v��F֋V�F�V�,��RP�v��v�V�u�����u����I�u���&��j
h
�h����+��jV�I���u
�M"�e"��jV�2���u�e"���Dt�D���E�e"���Dt�D���e"���F��~�}�^��㋇��=t�^���LJ���F����E"@t	Wj
�J��V�����v��v��-*����)+��_^�VW�jr�v����t+����6��jV����u	V������DIt�D%�=�t��
��jjV� ���F��u��%�ŋ^����F��~�t��S���륋E�F�;l�t
��%�v���j�v
�EP�*���F��~�}-�F���F
�F��^���^
�w�7��΃��^���W�F��͋E�^��E�^��v�������_^�VWU��v�~y�u	�~u����F�V�裉꣋F�VDT�����~	|�~r���n�^��F���F�F�D
h��v
�W���L
��H�t����F�V�F�V�[��>�u���+��_^�VW�*�F
�F��F�F��F��F��F��Fڋ^��G�GP�F�@@P�7����u+���^ڋGF܋G��F؋̓��F�;�t�F�볋F�@�����F܋F�F��F֡�Fց~��~���j�F֙RP�i;���F��t���)F֋^��G���+��G�F�+F։F��F�F�F�F��F��F�+F։F��F�F�F�F�F�HP�v�����F��F��F��v��v�����F��^ڋ���tK�ƃ�P�r�����t9�v��v��[���F��F���GP�~���F�P�v��N���F��F�~�u��j�v��#���F��F��̓��F�;�t�F��r��n�j�v������n��^��O�F�+�P�v������n�j�v������F�^��F�H�(��F�*��F��_^�VW��v�F��F��t?�ƃ�P������>�t+��9�t"�F���GP����F��>�u��F��~�u����F��^
�F��^��_^�VWU��F�V
��%���_^�VWU��v��s���㋇*����u	��	+�����_^�VW��v�~
��%��P������F��ti��@tD��r��	�W���;�u���N���ヿ*�tW�����>�u2����F���*��^��G��+���s���ヿ*�tG���u�������_^�VW��v�*���R�se�=t����j	�6��݃��F��tM�v
V�����>�t�v��ރ��1�F
�^���G�G�G�w�F����-*��.�>D6�������_^�VWU��v��s���㋇*����u��	�.����LJ*��}u	h���'&���Mu�u���W�ރ��_^�VWU��*���R�s����u�����E���_^�VWU��+���}���烽*�uF��V�j������_^�VW�����������>�u�^�F���
�F�FP�P߃��F�=/t�6&��&�>�u�^�F���
�F�FP�#߃��F��6(��~�/u$�>�u�^�F���
�F�FP��ރ��F��֍DP�?4���D�~�u�~
ru�6������N��V�
�������~�/t8�~�t2��
�s��G�F���>�u�^�F���
�F�FP�ރ��F��ƒ~�/u$�>�u�^�F���
�F�FP�Zރ��F��ց�
�s��G���D%�=@t���	jV�C
���>�t�Y�����|u)�;Z�t!��G�?.u��G�?.u��G�?u	V�y�����F��F��F��F��F��F��D�T�F�V��~�y�u	�~�u��F�V�F��V�RPV�_���F��u����^��G�F��^��G;F�vU�n��^�xK�^���F��u#�~�u�F�F��V��F�V�F��V��F���v������t��F��F��F��v�����S���F�~�u�F��V��F�V�~�u&�~�t�%��~
ct���6���F�V��裉����~�u1�~
uu�F����6���F��V���V�����v��v��m��������V�����v��v��T�����t������_^�VWU��v�>�t$�E;uV����u�DP�1���D��=�؋��_^�VW��^�?u+��+�F@@�����F���G���F���F��:F�u��N�u��_^�VWU��+��$���!F�Ft��!�tej�6�������tU�v�>���5��
�����t@�D�F
�D�t�?���L
�P��R��DL�TN�P��R��DP�TR�P��R��DT�TV�6���������_^�VWU��F�������������h��6�������_^�VW�+��r�Ik�X��;6r.�D;F
u�;Ft�|u�t�D;F�s���D�F���X��;6r���Nj��u`h���v�@!���F��~�
}!�^
�t��ÉF튇
���^�G��F��ً�^��G��6��6��F�Ph����'����+����DP��/���|t
�DP��/���.��F��F
�D�D�P��DV�k���u�D�D�DP�/��맋��l�D
t,��F��~�u����^�;wu�F
�G�F����^���׍DP�B/���D;F
t�p��;Ft�f��|}	hƝ� ���D�P��D��_^�VWU��v�|t�|
Vh՝�����Lu�D
u�|uV����DP�/���_^�VWU��v�DP�.��V�����_^�VW�Z�v�~
�r�Ik�X�F��F�;r�^�;u;7t�n�X��F�;s�F��F��^��7�P�'���u+���^��G%�=@u���t��_^�VW�F�v�D
�D�F�j������AA��+�RP�4��܃��F��u+��(�~��F���%���ȋ^��G��F�j@WP����v��k߃���D�E�D�E�D�E�D�E�U
�D�TRP�ƒ��D�T�D%�=�CC.;��uV.�g
 @`��=�=�=�=�=�E�D�Bj
�EP�DP�5ƒ��0j
�EP�DP�#ƒ��E*�D@�E,�DB�E.�DD�j4�DP����E4�U6�DL�TNRP������DL�TN�E8�U:�DP�TRRP������DP�TR�E<�U>�DT�TVRP�����DT�TV��_^�VW�F�vj�4�W���u��D�F��|u.�|u(�~�t"�~�tV����D�D�v��4����~��D��D�E�D�E�D�E�D�T�E�U
RP�,����E�U
�D%��>�CC.;��uV.�g
 @`�$?
??
??�D�E�Bj
�DP�EP������0j
�DP�EP������D@�E*�DB�E,�DD�E.�j(�EP�J���DL�TN�E4�U6RP�����E4�U6�DP�TR�E8�U:RP�����E8�U:�DT�TV�E<�U>RP�g����E<�U>j�F�������AA��+�RP�4�Nڃ��F��t7�F���%���ȋ^��G��F�j@PW����^��OS��܃��d
���_^�VWU��v�r�Ik�X��;>r*�}u��X��;5u��E%�= t��E
t�W�������_^�VW��v�D%�n@�CC.;��t��.�g@�A0A0A��
~,O����ދG�W�F��V��t��-	PR�v��4�]�����~&O����ދG�W�F��V��t�R�v��4�"�����D�Dj4�DP����L
�P��R��DL�TN�P��R��DP�TR�P��R��DT�TV��D@�DB�DD�
�L��
�F��_^�VWU��v�~
���D�E�D�E�D�E�D�E�D�E
�E���D�T�E�U�DL�TN�E�U�DP�TR�E�U�DT�TV�E�U�D%�A�CC.;��u,.�g `�A�A�A�D�E�E�E�
�D@��E�U�_^�VWU��v�~
�6��6�V�9����#�;�t	��
+��!��t�|~V�7���t���޸�_^�VWU��v�~
u��&�F
;Du�D����F;Du�D����D%�_^�VWU���6h��6Z��}�����u�Z�%�P�Z���%�Ph��e���������P��R�j�6Z�������(��u�Z�%�P�Z���%�Ph���)���(��&��>&��E�(�P�a(���_^�VW��vh�6�1Ѓ����u+��j�~
tj�jV�݃��>�t	W��Ѓ���jjjV�փ��F��u	V�݃���h��EP�^��w�����v��Iك��EP�%���E�u�F
�Eƅ����>���_^�VW��v�t�t�H����D�T+���@})����ƉF�������w
�w�����^��G�W
G��+���d}G��������������������������仃��������������λ���������_^�VW��v�Dug�t�����|���tTjj�t�\փ��F��P��R�������ƅ�h��^��wW�����^��w����j�v��e׃��v��؃��_^�VWU��v�>�t#;ut�=���Et�~
t��+�����
Vh��
���_^�VW�j�v�����F��u+���F����F�P��%����t���F���
�F�����F��F��F��+�;V�w
s�;F�v�v��v��v�}���t�F��F��V���j�v��v��v�rԃ��F��tڋ^��w���F�;v�s#�<t��@�F���F�;F�s�^��F��F�����v���փ��F�;F�r��ρ�
�F�+��.�>L����u'Dž��F�P�A%��h/��v��������������ߋ�
�F����ƅ��F�P�%���v��v�5���F��tC�^�t�v�h=��v����v��������^��G
�F
�G�G���G���G�F��_^�VWU��j�v��������t:�EP�S$���uƄ���d}������ދF
��
����EP�W$���_^�VW��v�F
Fu���N�t}j�v�v
�v��҃��F��te����O�~R�^��G�F�����؋�W�F��V��t�R�v�蘸���F��V��u
RP�v�w���V�v��v��v�v�����v��&Ճ��v�v
�v�K���_^�VW�j�v������F��u+����!�F�
P�H#���F����|u#�DhK��v�>�����F��F���Ƅ��L�\��ދG�W
�F��V��t��|u~�F�;T|-;Ds(�+�;V�rw;F�wj�v��v��v�у��F��uhX��v�����q��^����D�|@w�h�DP�EP�����t�DP�]���v��ԃ��������F��V�;T|�;Ds��+�;V�w�r;F�w��F�
P�n"���F��V��_^�VW�j�v�����F��u�����F
�V;T|;Ds�+�;Vwr;F
v�F
Phf��v������F�
P��!���|t�|@uY�v�v
�v�\у��F��^��hW����D�h�EP�DP�����t�EP�^���^��OS�
Ӄ��D�\�D��ދF
�V�G�W
������Ƅ��F�
P�j!���_^�VW�
j�v�������u	hz������D�T�	�������F��F�=
~�F�
�F��F�;F�}-�N��^���ދF
�V;Wu;Gu
V������F��ˋD@�TB�F��V�V����~�txj�v��v��v�xσ����ta�F��F�=�~�F���F��F�;F�}=�^���ߋ�W�F��V�RP�0����F��V��F
�V;V�u;F�uW����m��F��W��у�+��_^�VWU��v�~
��O�t�t�4�䴃���T�����_^�VW�/�>u���6j
�F�Ph
�����tB�t@觴���F��tF�tD蘴���F��P��R�+��RP�~����F�����F�V���F����F��F��6��6��O����F��D2�F�����F��P�S���>�E�U�FՉV��F��F�F��F��F��F�PW�w���P�J�����_^�VWU��v�D%����ǻ=L�CC.;��ug.�g @`�LOL}LOL�DP������ uj�j�v
�t�iԃ��DP����%�F
t�0�t�~
u���
�v
V����_^�VWU��v�DP�l���D%��L�CC.;��u<.�g `M�L�L�t��̃��DP�h���t�ԃ��DP�!�V�=��V����_^�VWU��v�~
�}tL�D%�<M�CC.;��u2.�g
 @`�eMRM^M^M^MW�t��Ӄ��WV���WV�/�����_^�VWU��v�~
�L
�P��R��DP�TR�L
�P��R��DT�TV�}t\�D%��M�CC.;��uB.�g
 @`��M�M�M�M�MW�t�Ӄ��#WV�B��j�4������t��WV������_^�VW��v
�D�T�	�������F��V��D�T%�+҉F��^�G%�=`u��+��F�^�G�W+DT�F��V��~�u�D+�;V�rw;F�s�D+҉F��V��~�y�u	�~�u��~�tj�v��v��^�w�Z˃���v��v��v�����F�~�tY�+F�����+�;V�wr
;F�v�F���W�^�F�GPV�΃��v��̓��>�u�F��V��F���+�)F�V��_��_^�VW��v
�D�T�	�������F��V��D�T%�+҉F��^�G%�=`u��+��F��|u��+F���;|s����D���~�u��u��+��F�~�uP�v��v��v���+�~�t�v��v��^�w��ʃ��j�v��v��^�w�'ʃ��F��~�u�W�^��F�GPV�=̓��^��O�~�t�^�G%�=t
j�v���˃��	�v��̃��>�uM�F��V��F��^��+�DT�D�T;W
}��;Gw����~�t����D�T�^�G�W����_^�VW��v�v�v
V�K���F��V��y+��6�F�F�tj�v��v��4�CɃ��jjj���Ƀ���h�u�
�����_^�VW��v�F�P�v�v
�+���F��u	��������n��^����ދG�W�F��V��t�̓��F�;�u�F��V��Pj�v��v��4�ȃ����u+����4�E�F��n��^����؋�W�F��V�W�:˃��v��v��n�����_^�VW��v�F�P�v�v
�|���F��u+��i�F���F��n��^���^���ދG�W�F��V��u)�F��v������F��V��t��^���ދF��G�W�̓��F�;�u��+��F��~�u&�~t�~�uj�v��v��v���ǃ����u%�e��v��v��v��hȃ���h�u�+	���M�~�t����F��E�F�n��^���^���؋�W�F��V�RP�Q����F��V��uc�F��v������F��V��u
W��Ƀ�����^���^�F��V��W�F���F�F�^���^��w�7����^��W�MW�Ƀ�����_^�VWU��v�~
|�~
s
�ރ��F�Q�n
�^
���O�u	��+��:�F%����F�V
��������F�V
�n�^
�uċރ��+lj���_^�VW��>��t����P�vh���a���l�>��u�b�>t�X�~�>"�u�Hjh�S�6��h ��@���3�UĉF��>t�vh�S�6��h ���?���v��:��h�����v��(ă����F��V�����=u��F��V�;Tu;Du�D�TDT�F��V����Duz�D u��Dt׋D
;DuϋD�F��t�t�v��v��t�t�p����F��V��D�TV�ں���>�}t�Ɯ;F�t�ʜ;F�u�4�;F�u�D��N~�k��>��t
��t�Dtjjj�	jh�S�6��h ���>��h�%���_^��U���^]�U����vj�F�^��f�]�U��^�GPj�G�^���]�U���v�v�v�v�v�v
�v�Ћ�]�U��+ۊ^�㋏�Qj���t�G�t�^���]Ë�]��U��+ۊ^�㋏�Qj���t�G�t�^���]Ë�]���U��+ۊ^�㋏�Qj���t�G
�t�^���]Ë�]��U��+ۊ^�㋏�Qj���t�G�t�^���]Ë�]��U��^�_	*��㋏�Qj���t�G�t�^���]Ë^�O��]���U��+ۊ^�㋏�Qj���t�G�t�^���]Ë�]��U��+ۊ^�㋏�Qj���t�G�t�^���]Ë�]���U��+ۊ^�㋏�Qj���t�G�t�^���]Ë�]��U��+ۊ^�㋏�Qj���t�G�t�^���]Ë�]�˻�K��F��A��<��7�
�2��-��(��#����������
����U�싏�Qj���t�^���]�VWU�������.��7
�����6�>��th5��h:�h��h���E��hĞ�<�������thD��*���6���6��hS����������;��u;��t	hW������h�jh�������u	h�����hR[������tj������u	h�����V�{Ѓ�����_^�VW��6�|�D"�t��D
�F��u��E�U�F��V��^��G�W�F�V�F�V��F�+�RPW����u+��8�v��v�F��V�EURP�^��w�w�%����D
�v������F�����F򣸣�>*�u��E���+��F�*��*��F��n��n��F�P�=����u�(�@@��)F��v��&����F��t�F�F�P�F��F�P�����كF��F�P������F��t�F�F�P�v�������q�i�D�F��u�D�F��~�t�F���œ����t�E��Ĝ����~�t�^��G�W-���+�����t�E�U-���+������_^�VWU������Ɯ�����ʜ����Ȝ����̜���Ɯ�D��ʜ���D�|�|��_^�VWU��F���F
�����_^�VWU��v�D���F
�D�D
�D�_^�VWU��v���|���~+��.���t����t����t���t���tށ��t؋F
�����_^�VWU��6��6�����P����6�����P�⺃��v����P�Ӻ���&����F
���6��~
t�~O��Dž���_^�VWU����_^�VWU���_^�VWU����	����_^�VW��v�~
�F�F��~�t��G�F���F���^���N�u�F�_^�VWU��v�~
�t	��F�Ou��_^�VWU��>�t	��+������_^�VWU���;Fu���>�u������+��_^�VWU��0��0��u�FPhʟ���j
�篃���4�>��0��_^�VWU��F
P�F%�P�F��%�Phԟ����h�������_^�VW��+҉F��V��p��F�V��>t�����+�F�V���@@�&����~���+�F�V�kr�X���~��F�V��>n����~��F�V��>t���	�~���F�V��F��V����%��F��V��~�|�~�r	h�������>Ĝ������+҉F�V�F�+ҋ؋ʋF��V�+��+F�V���>+~��+ң�+F�+F���Ĝ+ҹ������;6v	h������Ĝ+ҹ������F�V����%����+ƣjh��++RP�$�����6V�
���������
��bjh�6�6�ʲ���F��V��F���_^�VWU��v
�F%�=wN����.��H^a^e^{^)|���=u8���1+����t�t�t�t���������t�t�DP�ܷ�������_^�VWU��v
�F%�=wO����.���^�^�^�^)|���=u9���2�|���t�t�t�t�?��������t�DP�t袷�������_^�VWU��F
P�6\��������tV�)���D@�DB�DD���_^�VWU���_^�VWU��v�|uV����L
@�_^�VWU��v�D
t�d
���DDP�'
���D
 t�d
���DBP�
���_^�VW��v�~
�|@uT�D
@t�d
���F�|u�||:�Et�����L
 �DP�u��jjj�DBP����DP�'����D
@t�|@u�d
���E�F��>�uj�~�td�|@~^�+DB�F�;F�v�F��F��F�;D@v�D@�F��F��E�DB��E�UWV����E)F��F�DB�DB=u�DB�F�)D@)F�돋F��E�D
t�|@}�d
���DDP�����_^�VW��v�~
�E�F��>�t��~�u���|}�|u�� �6j�.�����+DD�F�;F�v�F��F��+D@;F�s	�+D@�F��Et�F�;F�u�D
@t����~�t�D
@t,�L
�DP�
��jjj�DDP�H���DP�	���N��F��E�DD��E�UWV����E)F��F�DD�DD=u�DD�F�D@)F��D
 u�
��|@���d
���DBP��럋F��E�_^�VWU��>*�uh�6�Q������t4���.�>,�t'�,��*���P�6�'������t
�*���Ƌ��t�2���62�����;�w�2��_^�VWU��v�|u�ƉD�D�2����u�n����uh.�����,��2���E��GR��R�u�\�]��|��D�_^�VWU��v�^�G�G���t#;vt�D���t�} u
�ERP�����t���_^�VWU��6�DR���t!�E�]�G�؋E�G��DR�2���>2����_^�VW��v�F
�F���F����=%t�u�VW�è�����F��<lu�F�F��F�����wc�CC.;��u�.�gDOUXcdoprsux�c)d�dxd�c�cdtd8dGd|dnd�^��F��7뒃~�u1�^��?|�j-�B���j
�^������؃�RP����F��F��^��x�j-����j
�^���W���؃�RP����F����~�uj�[j�^��w�7����݋^���F��^��7띋^���F��F��^��F������u���W裧����~�uj�j��~�uj
�^��+��N�j
�^��w�7�w��_^�VW��F�RP�v
�v�L����F��V��t
�vR�v�������F�RP�v
�v�#�������D��P�!����_^�VWU���6�6�6�6�6����s
�=�}�����_^�VW�jt�6�������u+����E"�E �E2���~t[�M"�h0@jh����F��~�u	W艮�����F��E�^��w�v�F�P����j�^��G�W���RP�F�P�f���h�i�����E�>0u|���D��=t�D;Er;Eu��̋D�E�\��u�|h�N�����_^�VWU��v�D���t�D�D"t�E
W����h�����D�\�G�D�\�Gh����V衭���_^�VW�j�������u���%�ӱ�F�蛱�v��ϱ��V�_���u��V�h������>(�t�(��G�>&�t�&��G�+ϋ>�E�D�E�D�E�D�E�D�E2�D2�E0�D0�E$�U&�D$�T&�E(�U*�D(�T*�D6��D:�D8�D<�4��F��F�P�M����v��)������;�tH�t�B��j�\�G�W���RP�F�P讯��V�����䰉F�V�Q���v��ܰ���D��P��R��������z�u�+��_^�VW��>jjj�EdP�N,��jjj�ETP�>,���U�>(�t
�6(��tԃ��>&�t
�6&��cԃ����F��N�~&�^���ߋG�F��t�^�����GP�����վ�D��=tI�D;Eu�| u;t,uV�R���D;Eu��D�| u
�6�5���D"@t�h�%��뭃>t	h����F�EP�E ���_^�VW���F��~
}�^��G$G&t���t腯hȣ�Ʈ���y��F��^��G �F�G,��G>�F
G6�F��G6�F��F�;F�s����^��G6�F�G:�F�G<�F��%�����u�?�F��E�w�F���v��������^��G6+F
�F��G6�F��F�;F�v+��^��G6�G:�G<�~
}�G$G&t��t�®hȣ�����_^�VWU���vh�i�k����_^�VW��F��%������腮�F����;�t@�D,;Fu���\��D��G�+D>D6�F�;D6s����D6V����v��G�����v��<����_^�VW��$��F��6��F����=t%�E6)F��E"t�5D6�F��E6�E�D�\�7���v��魃��
�;6t<�ɭ�F��6h���߬���uh��\�w������t�[��v�蛭���_^�VW��v�F���}��G6F��F�;D6s��u��w���5�|�D6)F��F��D6�F��)G6�D �_^�VWU��v�,����<t�Djjh@V�i������W�����_^�VWU��v��|t�D�V�/����_^�VWU��������;u;tN������+���!��
�����_^�VW��v
�^����FFu	�+���h������F%�F��>��t=;uu4�E%;F�u)h����W�9�����u�W�$���^��}�=뽋>��t;uu�E%;F�t��=��h�����v�v�v�W�����u�c�jj�v�v�v�vVW�mă��u
W�.���=��Ft�u�D�^����_^�VW��v��F��L"�F��~�};�^���^��G���u�F���W�a�����t�^���މ�Eu݁d"���փ~�}.�~�~(�N��^���ދG���t�^�����GW����ҁd"���F��_^�VWU��v�Dt
�D�D
���T�Du	hT��L���D
�P�t�t�8�����uV�������D�E�t�t�u�u�t�t�*������_^�VWU��F%>
���F��V
�f�h������Ft�v
�v�"
�	�v
�v�a	����h�����u;h��J��h�����Ft�v
�v��	�	�v
�v�"	����h������t'�|V�����F�u�v
�v�t�t�0������E�F@u<j�6�s������t*�4�t�|�D�D
�v
�vV�����u�V����+��_^�VWU��v�|t�L�L
�kh�����L
�Lth�#��O��\��D��Gh�����|
t	h������D���tW��̃��t�t����V腤��j�#���_^�VW��v�D%�F�h�����F
�V+DT�F��V��F
�V;T|9;Dw4�F
�V�D�T�~�t�F��V�)DTV赟��h�a������D��=u	����E�UEU�F��V����=u	����E�U�F�V��~�u;+DT;V|.;F
r)�v��v��D�TDTRP�v����F
�V�D�T�f��~�tK�D�TDT+F�V�;V|2;F
r-�F��V�)DT�F
�V�D�T�v��v��t�t�������F�V�+F�V�;V
}�;F
s��~�u:�t�t�v��v��t�t�����v��v��D�TF�V�RP������F��V��F�t�t�F�V�+DTRP�t�t�2����v��v��F�V�+F
VRP�~����F�V�+F
V�D�T���h������D
�P�v�v
�j������tz�~�u.�t�t�u�u�t�t�g����v��v��E�UDTRP�,�t�t�F��V�EURP�t�t�1����v��v��u�u�ᕃ�h����WV�/������v�v
V�����t_�~�u�v��v��F
�VDT+F�V�RP�4�F
�V+F�V�RP�F��V�DTRP�t�t�����v��v��t�t�`����l�+��_^�VWU��v�D���F
+�RPV������u���.�b�u$��+�RPV������t�J�u�6j�=���5��_^�VWU��v�>u
��+��h�����v�v
������uh�2�����h�'����D
�DDt�t�t�u�u�t�tj���h�����WV����h������d���L
V�$���V�	�����_^�VW��v�Du7�>�D�D
�u�e"��觤�F�W�����m��v�蜤���EV�5����_^�VWU��v�>u+��mh�1����t�t������uh�J������D
h�<����t�t�u�u�t�tj�(���L
�D%���E�D�T�E�UW�N������_^�VW��F�V;b�|Y;`�rSjh�v�v�}���FV;f�|4;d�w.�F
�V;| ;r�F
�VFV;|;v	h���5����4��DP�C�����O"�E�F
�V�E�U�F�V�E�UW蕚���E�U�D�T�FFu���~	|�~@v�@��F�F��F
V%�F��V��F
�V%;V�u;F�t�^
�N����+�+��+�щF��D�~t����D�^��D�F�V�D
�T�F
�V�D�T�F��D衢�F�V�6^��p����Dtjh�h�V�������v��}����Dt	h������F�D�F
V�.�>z�ȋ��FV�F��)FV����EW�v����DP�!�����g"���_^�VWU��v�~
�}t�u�u�!�����\��D��G�]�7�E�D��w���E�U�D�T�E�U�D�T�E�U�D�TV�����W�M����_^�VW�jh�v
�v�2����F��V��`��b��F��V���F��V�;f�~�|	;d�r����=t�D�T��d��f��F�V�+F�V�;V�|M;F�rHj�6�������t\�\�?�D�E�|�5�E�E
�F�V
�E�U�F��V��E�U���(jh�t�t�y���DT�F��V���t�H�+��_^�VW����F��V�����=t�D�T����F��V�+F�V�;V
|T;FrOj�6�K������tX�\�?�D�E�|�5�E�E
�F�V
�E�U�F��V��E�UW�m�������D�TDT�F��V���t�f�+��_^�VW�����F��V��D��=t�D�TDT����F��V��F��V�+F�V�;V
|X;FrSj�6舚�����tV�����<�u�E�E
�F�V
�E�U�F��V�+FV
�E�UW視������D�T�F��V���t�[�+��_^�VWU��j0hR��r��+���}u�����G���uF���u
����LJT���������R���t��t������R��t��t��t������R������E��V�������X������_^�VWU��vh�d���>��t";uu�E%=uh�u����-�=�؋>��t;uu�E%=tԋ=��h�E��+��_^�VW��v�~
�ރ���+ҋ���������F��V��E(�U*�F�uS�V�uN�F��V�	E$	U&�} u<��F���]��E��G�+E>E6�F�;E6s����E6W�8����v��Ý���_^�VW��6+��D(�T*����!D$!T&�D$D&t2�F��F�G�D$�T&�F�u�V�u��F��V��������F��V��؋��_^�VW������u��>N�+ҋ������������!E$!U&���㋇���F�F�ƣ,��~�t�v�V�߃��Dh֣������E"@t�M"�H���e"���t!��	
��t��u��t�΀V����_^�VW���G"u!�����
jch��胺���t�
+��$������ujh���齃����u8�܋D%�=�ujV��Ń��tj�4�ȃ��u	V������V�*ă��I
�������R��>�t�����r��E�F��t�u�������^��G�W�����G�W�F��V��G
�>�uD�F�F�t<�~�	|�~�@v�@��F��F���h�V�Ѓ��F����)F�V�뵋^��O
�|�V�/����>�t�����_^�VWU��h����6��t
�D;F
t�t��h�0����t�D" t�>�D;Et���gh�����F��F
��F��F���
�h�"���>tjjhh�������h����
�_^�VW��6���|u�	�@�F���h�H����E��=u�F�	��E;Du�} uW���h�J���~�|���>t	�D;tjjhh�w��넡H=wE����.��K~]~l~u~�~�~�~�~�~�~�6�N����
�~�6�'���>s
���������\�6�6�h����L�6�6�;����6�6��ۃ��u-���F�	�$�q܃>|��>���F��>t�������=u��h�����F��_^�VWU��vVj������_^�VWU��6+��|ft%Wjd�Dh�Tj+d�-�RP言����Vhjjd�F+�RP葀��RP�DdP�!��
���_^�VW��6�F��F��|ft�Dh�Tj+�F��V�Vh�v
�v�DdP����
�F��V��_^�VWU���w�>|��~t
�F+�PV����L����_^�VWU���v�v
�v�:����_^�VWU��F��P����_^�VWU���2��_^�VW�
�P��R��F��V�kT�
�F��V��F��X��F������j
�v�F�P�����V�闃��_^�VWU����_^�VWU����_^�VWU��"��_^�VWU��>�E�_^�VWU�� ��_^�VWU��>�E0�_^�VWU��6�D�D0�_^�VW��v
��v���W�F�h����~~K�>��u� �} u�}��E;Fu��F��u�WV����tWV������������~�}N�F�؉F�>��u���} u�}��E0;Fu��F��t�WV�����t
WV�~��������̓~u@�>��t~�} u�}���E0;G0u��F��t�WV�s���t�WV�1����Ѓ~�uB�>��t8�} u�}��}t��}t��E"�u��F��t����t�WV�������h����~�u��+��_^�VWU��v
��;Du��0� �;Du�~t�~t�~t�~tۃ>�u����+��_^�VWU�����t�~t�>�M"�	�>�e"��+��_^�VWU��v�>u4�}+���(~�(�>;u4s����t	�>�u4+��_^�VWU�����_^�VWU���_^�VWU��jj�jh�������_^�VWU��v�6 ���F
�"��F�$��F�&��_^�VWU��~u
�>�M"@+���v�v�v
�v�}����_^�VWU��v;6�t�"��t�6��6"��>�u+��_^�VWU��v;6 �t����t�6��6 ��>�u�u+��_^�VW��v�>�~
����	u���mN�޸+ҋ���������F��V����㋇���F��~
u�F�	E(	U*����F
���������F
�����F��V�����!E(!U*�F��V�����!E$!U&�F��_^�VWU���v�Q����_^�VWU��v�,��t�Ɠ��jhP�V�����W輓��+��_^�VWU����_^�VW��6�D@�TB�F��V�DD�TF�F�V��DH�TJ�F��V��DL�TN�F��V�j�v�F�P�a���+��_^�VWU��v���t	V�ܥ��+��_^�VW��>h�����F���D��=u�;�t�D;Eu��D" u��D"t*�d"���L" h�����~tj�v�Y����D��| uQ�D@�TBDHTJEHUJ�DD�TFDLTNELUN�~t�tP�v�����D�F�h�y��V�-����F��.�v��R�h�^���~�u��
�hj�h�W������_^�VW��v
�Fjr�v�����F��5�~�u+�>���6"��6 �W�ໃ��؋�#�;�t��
W讵��+��_^�VWU��6�� ����6 ��6��"����6"��_^�VWU��v���te�u �>u���S�6蝵����?�>u�jrV�q����u-�>���E%�=�t��W�!�����EP�U���>+��_^�VWU��h&��v�	��+��_^�VWU��v
jr�v�����uE�>���E%�=@t��W�´���(jW胺���u��
��EP�����4�ߴ���<�_^�VWU��jr�v赮���uF�6���t�6ԃ��t,�>�t�f
���d��F
%�	D�L
�P��R��DT�TVV�<���+��_^�VWU��jr�v�W����u7�6�����t#�d��F
�D�F�D�L
�P��R��DT�TVV�����+��_^�VWU��v�{��t
h(�V�����+��_^�VWU���v�I���+��_^�VW��v
�F�jc�v�̭���t�������uj��%�
�P�1������u9�jW�5����tk�E%�ʈ�CC.;��uH.�g @`؈	�؈�F�jW�>����F��|1�~�tW�T����EP�T���F�����j�5襻���u�W����_^�VWU���v
�v�[����_^�VW��v�������t�u�F�PV�ܷ��j�v
�F�P�����+��_^�VWU��~|�~}�~�狅*����u��	��F
=v�����.������J�J�����~}��~}�~�烽*�u�~�牵*��D�F�g�F�F=|����U�$��Ft��Ft���%=t=t�F��F��F�t�N�t��N����_^�VW��v�	������t2�|�E%��F��~� t�~�`t����v�v
�u����+��_^�VWU��jr�v蛫���t��6���D%�=@u����u
V�F�����DP�y���jc�v
�_����tV�h��ۃ>��t���6��������>���;t��W��j�6��躶���u�6�����t�$����6���Ѱ���DP��߃��D�L
�P��R��DT�TVV諰��+��_^�VWU���v�ꨃ����ta�|�E%�=u���L�F=w?����.������͋ۋ�~x*�F
�V�D�T�F
�V��D�TF
V�؋E�U�����_^�VWU��F
%�����t���tR��`t�� t�Fjc�v�'����u2������t��V�ݯ����v�v
膭�����tV�¯��+��_^�VW�jr�v�ܩ���t��6��jV�c����u��D�F��D�F��F�%�=`t���}V�k���jr�v
葩���up�6��jV�����tV�D%�=@t���D�|�|u���1�>�t�E;F�t�=���v�v��쵃����t�u�L
�DV��+��_^�VW��~wr�~
v���M�N
k�F���~t;vr;6̜v���)�F��F
�F��v�~��V�����F��~�}�F��G�~�|�F� �:�^��㋇*����t�]�G%�= u��v�DP�ȇ��P�]�w�H����F��v��DP������~�t�F�F��N����u��~u	��ԋF���~~*�F	�F�.�>���F�RPh�i�v�TP����jjh�RP�Rڃ��ԃ~~jjj�TP����F�$��t
�������~t���+��_^�
VW��F
%=wz����.�����!�&�jr�v�~����ua�>��VW�	����u	W�2����H�F
t���F
t��VW�����F��|ҍEP�A܃��F���럾뚾����_^�VW�j��σ����t`jV�ӥ�����|H�DjV������F��|"W�v�s����v��F@@P�d����DP�����L�DP�ۃ�W���V�r���+��_^�VWU��j�v�v
�v����_^�VW��v薤�����u+������ȃ~t���#�u��	���v�v
�����u���Ƌ|�E%��F��~� t
�EP��ڃ��t�E�U�D�T�D�T�裉꣋F
�죋F���t��+���~uh�W蜼���M
�P��R��EL�UN�
h�W�߼����)F�F+�DT�~� t
�EP�ڃ��F�_^�VW�jr�v�v����u'�6���F�PV�W���V�+���j�v
�F�P�k���+��_^�VWU��hP��ڃ��6�tV�%����4���=�hP��)ڃ�+��_^�VWU��6$��F%��$����_^�VW�jr�v�뤃��t���6��jV�r����u
V蛪�����D�F��D�F�V腪���F�%�=`t����F��^�����t
�E;F�t�~����u���W�n����r�Ik�X��;6r�|~�;F�u���[��X��r�Ik�X��;6r�;F�u�D��X���v�胇���v��֎����^���]�g
��S�
���W謁��+��_^�VWU��j�6Z��Q������t�|ƅ��������������_^�VWU��ju�v解���t��6��jV�.����u��
�j�<�6��W謩���tYj臧��V�7����6��W詧�����tB�|~�L�L
�P��R��DT�TV�D%�=u�|u
�|uV�9̃�V�樃�+��_^�VW�jr�v�����us�6���t�ȃ��tY�L
�P��R��DL�TN�P��R��DP�TR�P��R��DT�TV�~
t'j�F�P�v
������F��V��DL�TN�F��V��DP�TRV�Z���+��_^�VWU��j�v�v
�v������_^�VWU��v�~
u;6̜v��F
H��;�w;>̜v+����_^�VW��v�<��F��D���t�D���t���v�� ����~tO�F
+��D�T�F�D�F�D
�D%�+������ރ�F����t��w�|�5�v��˃���_^�VW��v调�F��D���t�D���t���v�蔃���~tW�F
FtO��F
V�D�T�F�D�F�D
�D%�+������J��F����t��w�|�5�v��7����_^�VW��F��=u�v�vh��ƃ��>��u��F�F�h���̓��v��v��y���F�F�h��̓��v��v��y���F�F�h��̓��v��v��yy���F�F�h	��k̓��v��v��^y���F�F�h
��P̓��v��v��Cy���v�v�vh��ƃ���G"�u��F�F�h0��̓��v��v��y���F�F�h4���̃��v��v���x���F�F�h8���̃��v��v���x���F�F�h<���̃��v��v��x���F�F�h@��̃��v��v��x���v�v�v��whD��eŃ�
�F��= t�����F��F��P��~�����>�u
��%�=�t�F��A����%�F��~�J}���������Ph֣�F@@P����>�u���hȣ�[����t���F�<w�6ڣ�6أ�6֣�T����6��6ޣ�6ܣ�6ڣ�6أ�6֣�T���F��V��F�F��F�>�u��F���F�����Pj�R~�����=t��5��F��=
wd����.����ԗۗ�ۗ�����������F��G�F�
�@�F�
�9�F��2�v�vhs��ă����v�vh�����F�	��v�vh����Ã��~�u���~�t��F�F�h¢��ʃ��v��v���v���F�F�hǢ��ʃ��v��v��v���F�F�h̢�ʃ��v��v��v���F�F�hѢ�ʃ��v��v��v���F�F�h֢�vʃ��v��v��iv����w�v�vhۢ�Tʃ��v�vh���Eʃ�����6�v��,���_^�+�P�P�P��͋�� /etc/init=WBWGWLWQWVW[W`WeWjWoWtWyW~W�W�W�����������������clrivec: level=%d����������� @sel=%x paddr=%X lim=%x flags=%x
vremap: out of gdt's
vremap( faddr=%X, ip=%x ) - not gdt at level 0
vremap( faddr=%X, ip=%x ) - selector is free
ptov:ip=%x: out of gdt's
vtop:ip=%x: sel %x invalid
vrelse: sel %x invalid
vrelse:ip=%x: sel %x already released
Arena %o too smallCorrupt arenaBad free %o
stack overflowbufinit: no space for BUF'sRaw I/O from non user
t&�&�"�&�&�&�"�"�"�"'dmalock: driver attempting to doubly lock DMA controller.
eveinit(code)eveinit(data)eveinit()eveinit()fdclose()Inode table overflowcmd=%s time=%lu
ialloc(%p), ipidetach(%p)fsminit: no rootdev(%d,%d)fsminit: no / on rootdev(%d,%d)getment: dev=0x%xOut of inodesInode %u busyOut of spaceBad free listBad block %u (free)bad()�krunch(%d,depth=%d) �U�UGV�UV�V�V�V�"�"W1.2.0.DKCopyright (c) 1982, 1991 by Mark Williams Company
Mark Williams COHERENT Version %s - %s Mode (mem=%u Kbytes)
RealProtectedSerial Number %U
Verification error - call Mark Williams Company at 1-800-MARK-WMS
Cannot allocate user areaCannot create processPanic: %r(%d,%d): %r
Kernel data exceeds 64 KbytesNo alloc space�"�"�",^�^�"�"�"�"�"out of poll buffers
0123456789ABCDEFCannot duplicate non shared swapped segmentBad segment countSwapio bad parameterSwapio errorcore��,����P�(�d������
�������s���\�M�������V�'>��8����ǂ8������)�4���2�]�����ۃ�������S��~�����5�1�΀��n��v�0��������Parity error: cs=%x ip=%x
ax cs ds es ss system trap: id=%x ip=%x ax=%xax cs ds es ss pid%d: kernel process trap: id=%x, ip=%x ax=%ddouble exception: cs=%x ip=%xinvalid tss: cs=%x ip=%xuser trap: id=%x ip=%x
	ax 	cs 	ds 	es 	ss user trap: SEGV id=%x ax=%x pid=%d
	ip=%x sp=%x
@@ukill_�mproto_�XB_DEV	ld_open_�Ucansuper_�Csetrun_�jsav_dsΜtimer_P�sdalloc_�vpfork_ffpopen_:_defqix�EFAULT	oops��free_EFAULT	ranupipe_4�ulink_��C_LOAD	mountp_aputi_�vprint_!KBCTRL	dtkusave�sav_bxМusave_&intflag_unone_�istat_:Aprocq_tcltfree_main_�Wuseracc_ޓshalloc_[xld_poll_Wisync_@defend_='waitq_$MAXMEM��uopen_��uaccess_�ufork_,�bad_�Isetacct_-Ksproto_yPFKERN	�PFKERN	�tss_di�umount_\�msize_defqox�bclaim_�clrivec_�	ugetgid_��segadup_�lsegfinm_�spollopen_Hbbufl_UMCSP	putuwd_�halt_llock_!kronflag_h�uwait_(�sexflag_lmap_-Smsync_ADpexit_�guasa_aputp_�etext_smalloc_�wdigtab_D�pollinit_�aowner_�[ISTSIZE_�NBUF_t�upoll_0�segdupd_�sexsread_91DMALCK_$�tss_bpܙseglink_balloc_�Gsendsig_zctclose_�&tabort�tisave�sav_spԜfclear_Upipedev_\�dmaoff_�holebot_int11_�tss_sp0ęsetcdir_$�ugetpgrp_��ld_intr10oWC_BLOCK	corebot_l3tol_ltol3_putuwi_tss_sp1șptret_�}slotsz_�ld_intr11tWidirent_^:uexit_�super_�[nonedev_�"tksave�consave_{dblock_2!tss_sp2̙unull_�ptset_�|ld_intr12yWiclear_K@sav_ssҜsyc�tss_ss0ƙtss_cs�ustat_pollexit_�bld_intr13~Wssalloc_�kactvsig_{getq_+#bufinit_�USIZE	vecs_��tss_ss1ʙtss_ds�ugetpid_��slotp_usync_�ld_intr14�Wltoc_nondsig_�zftoi_F6ctioctl_�&outflag_clrq_�#kclear_�[tss_ss2Ιtss_es�usignal_ۃseginit_|kld_intr15�Widatap_exstack_�1ldefend�'ctread_�&devinit_� a1*�com_usage_mactype_l�setivec_	tss_ipЙtss_axԙualarm2_�ubrk_�uptrace_V�segdupl_�mmfixcon_I[ldrvipc_ vmap_�Pacctip_ialloc_�Dgetment_�Deveinit_�(icodep_bufseqn_ioread_>sphi_Xboot_�tss_pswҙtss_bxڙusetgid_��C_OPEN	icopydm_�<icopymd_U>fn �u_�tss_cx֙nlread_,^ldtimcall_WUDRV_J	sbusy_�yidatas_sbl�tss_dxؙtss_si��sysio_Əugetuid_��sigperm_R�pnxgate_relproc_fldrvics_ icodes_cltinit_�"end_putchar_trap_0�pclear_�swapbuf_ C_ULOAD	ldrvcon_@ttsavekpscale_penvsave_{drvl_�CMOSmax_��timeout2_��sigdump_�{C_CLOSE	tusaveinb_pEXTMEMH	trap10�segswap_usetpgrp_΀segsize_�rmsigsin_:[pcsinit_�dC_POLL	ld_block_GVfsminit_nBpexece_I+dclose_
!nulldev_�"dmareq_`swapdev_^�drvn_j�outb_ztrap11�ttyflag_msigint_�Zexlopen_70altclk_timq_blockp_iogetc_getubd_�trap12�holetop_ldrvsel_@fdopen_!5iomapvp_�trap13�coretop_usuload_�ld_intr0=Waread_�Q_canl_cltwant__idle_iNINODE_r�EXTMEML	PIC	 gdtmap_��tss_spޙudup_)�seggrow_�o___��xcalledmUld_intr1BWC_IOCTL	salloc_ndmaunlock_(bread_
dflag_j"conrest_�splo_\sysitab_��uchdir_
�uexece_�ld_intr2GWinodep_iclose_�Lprocess_%edioctl_�!i8086_f\condev_v�edata_idtmap_��uchmod_��ld_intr3LWdread_X!ffbyte_�swapbot_`�tss_ss�uprofil_2�ld_intr4QWfdaclose_6poll_owner_dev10pvret_�ualarm_'lrdivld_intr5VWfread_
Nctwrite_�&UPASIZE	poll_rate_UPASIZE	dev11|usetuid_��segsext_�rsatcopy_Dvmsetuof_�Zldrvint_l�ld_intr6[Wld_xcall_8Ulrremiowrite_�brelease_�rootdev_Z�dev12�gdtsel_��uchroot_1�ucreat_d�segiom_ld_intr7`WC_TIMER	bfree_�Hbflush_�ucl_Ȝdev13�tsave[debflag_�NPOLL_*�nlwrite_�^ld_intr8eWld_close_�Upuload_�*exround_O4iread_Maltsel_dev14�idtsel_��udl_̜uunlink_��version_��ld_intr9jWpclose_C_devmsg_6\excount_�3defer_'msysgen_Wval11	dev15�timeout_�imake_�9envrest_�sas_��argl�cprocp_usload_n�bdone_xffword_dmago_bKBDATA	`trap0[ulseek_s�eprocp_ctopen_t&getupd_�vtop_�trap1frealmode_��scs_œplrcopy_#ptov_�prlcopy_uftime_8�ld_ioctl_�Vfdget_h4defarg�putq_�#kuerr�ageti_�drvmap_�"PICM	!trap2qsds_Ĝkuerr�uclose_P�ld_read_�UKRUNCH_��ifree_�Fkrunch_�Sld_call_AUquantum_ucs_Ɯalloc_?tp_table_vremap_�panic_\trap3|uunique_]�ufcntl_v�vrdivT_LDRV	pread_�_fsmount_�Bkfcopy_fkcopy_5unlock_Uktrap4�clock_H$uds_ʜlrmulvrremld_intr�Wbwrite_iprocp_sfbyte_�wakeup_�iNCLIST_n�trap5�umknod_�ugetegid_~�pmake__C_WRITE	imode_1Bctpoll_'swaptop_d�PIT	@trap6�clistp_dwrite_�!dmaon_
spl_`trap7�start2uacct_��uioctl_S�schizo_p�NSLOT_�C_POWER	pload_�)dispatch_+jL21#$getuwd_�SPIC	�trap8�uread_��_entry_��fwrite_*Obatflag_kkcopy_f[dpower_�!trap9�dev1vrelse_pevent_a_BFERR	idetach_<vread_�Pincopy_�upause_�swapio_[tfddup_�4msetusr_XZldeferb'ldcseg �bsmap_dtime_"setarena_�printf_"cdev3outcopy_
uchown_�unice_ǂsegdq_ldrvpsy_��iwrite_uMallkp_ioputc_KUSZ1	�putubd_Jaidatap_
�stimer_ALLSIZE_p�CMOSA	pdev4(direq_�9ldetach_Z<sfree_obumap_&aicodep_��getuwi_�sfword_�nirqslave_dev54depth_��uumask_5�defunc�utimer_L18$dopen_� dev6@kpcopy_;pkcopy_�ufstat_>�ustime_��utimes_��pts_L19D$aidatas_bctcon_�CMOSD	qdev7Lmsetsys_qZaicodes_dev8Xuutime_8�copyright_Ğbufneed_sleep_�hdev9dld_write_Vdisflag_ttkdone�stand_�$nlcon_�tss_™printn_�dpwrite_�`iopen_Liaccess_�Admalock_�'dpoll_'"kucopy_dukcopy_�clk�cds�ugeteuid_��asize_B_FLAG	ld_power_�Viucheck_w<SIDEV	@uumount_M�segmq_indfree_Gldfunc �four"�lbolt_aputc_�SPICM	�ulock_��idle_R[ld_time_�Viattach_�:PFLAGS	"PFLAGS	"eoi�tss_ldt�linkq_�pollwake_�bC_READ	
canndaddr_Kftoim_Q9segload_ZL10001�"L2#bsync_ctss_lnk™uwrite_ēutick_��cpid_fdclose_�5fdadupl_�5L3#L10002#ioreq_�upcopy_pucopy_�  s } � � � � � � � � � � � � � 	   ' 1 ; E O Y c m w � � � �'�G$�$�$�'�'�'�%�$�$� �'�'$$)$/$?'E�'I�0L'O]'S]$V$d$i$m$v$~$�$�$�$�$�'�G$�$$$$)$�$�$�$�'��'�$$='R�'V�0Y0\0d0g0o0r0z0}0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0000$0$&0)$205$>0A$J0M$V0Y$b0e$n0q$z0}$�0�$�0�$�0�$�0�$�0�$�'�g0�070M0n0v0�0�0�0�0�00*$.03$70P0s$�$�0�0�%� � �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� ��$"	 %	%+	$9	'B	�0H	0d	0o	0�	$�	0�	$�	 �	'�	�0�	0�	'�	�0�	0
0t
0w
0�
0�
0�
$�
0�
0 0.0?0M0V0�0�0�0�0�0�0�$�$�%%$#0&04$T0W0t0�0�0�0�0�0�0�0�0D
0f
0�
0�
0�
0�
0�
0,05'B�'H�0K%\%d0l0�0�0�0�0�%�%�$�0�$�0%	0$)$/0I0`0w0�$�0�$�0�$�0�$�0�$00)$<0?0E0^0u0�0�0�0�$�7�<0$0'$90<$B0N0g0~0�0�0�0�$�$	0 $4070K0b$�$�0�$�0�$�0�0�$ 0#0[0k$r0u �0�0�%�'�$0%3060:$?$E$I _$c$g%m$u0�$�$�0�$�'�g$�$�'��0�0�0$%$$ $$$+$/$3$70R'Vg0`0c$l$p$t �$�$�$�0�$�$�0�$�$�0�$�$�0�$�$0$0$$0)0B$T$[$q$�$�$�%�$�$�$�0�'�E%�%�%$'(E'7E%:%F$�$�$�$�'��'��0�'��'��$�'�0'
:':$0$'%:'+:$i'q:'w:0�0�0�$�'�:'�:0�0�0�00,0@0O0Y0f0�0�%�0�%�%�$�'�:'�:00)080@'I�'V�0h$n'v:'|:'��'��'�	'�	0�0�0�0�0�0�0�00-0A0J0f0o0�0�'��'��0�0�'�	'	'		0 W Y [ ]0g0y0� � � � �0�0�0�06%?0|%�0�0�0�%�0�0�0A0S0]0s0~0�'��'��0�%�0�$�0 % %
 0 $� $� 0� %� 0!0@!0j!0�!0�!0�!0"06"0x"$�"%�"$�"%�"$�" �"'�"�'#�'#0 #'f#'l#'p#'v#'y#0�#0�#'�#0�#'�#0�#0$0
$0$'%$',$'9$0=$'O$�'V$�']$T'd$�'h$T0k$'v$�%z$$~$'�$�'�$'�$'�$g%�$'�$�%�$$�$$�$$�$$�$'�$�'�$�'�$�'%
%%0%'%''%''%''%'')%�0.%'G%''M%'0m%0}%0�%%�%'�%�'�%�$�%$�%0�%0�%0�%%�%%�%%�%%�%0�%%�%%�%0�%0&'&g0&0&'!&g'1&
'7&�'=&�0@&'G&
0M&'S&g'Y&�0_&0e&0k& � � � � � � � � � �  �'{&g%�&0�&'�&g0�&'�&g0�&'�&g0�&'�&g0�&''g0'%-'%1'%5'%9'%?'%C'%I'%N'%R'%Y'%]'%w'%{'%'%�' �'%�'%�'%�'%�'$�'$�'0�'$�'$�'$�'0�'$�'0�'$�'0�'$�'$(0	(0($&(0-($6($<($@($N($T($b($f($l($t($y(0($�($�($�($�($�($�(%�(%�(0�(0�('�(g0�(0�('�(o'�(g')�0)$)0)'+)�'8)�0;)0J)'R)�0X)$e)0h)'u)�'�)�0�)0�)$�)0�)%�)0�)$�)0�)0�)0�)0�)0�)0�)'%*�%4*09*0o*0y*%�*0�* �*0�*%�*0�*%�*0�*0�*0�*0�*$+0+$+%&+%0+0>+'Q+g0c+0o+%z+0+0�+0�+0,%�,0�,0�,0�, �, �, �, �, �,0'-06-0:-%@-0I-0M-0U-0X-0i-0�-0�-0�-0.0.0C.0M.0P.0�.0�.0�.0�.0�.0�.03/0B/0i/0s/0v/0}/%�/%�/%�/0�/0�/0�/%�/%�/%�/%000000)00/00C00O0%S00Y00d0%00�0%�0%�00�0$�0%�00�0710.10H10S1%W1%b1%f1%u1%y1%}1%�1%�1%�10�10�1%�10�1%�10320?2${2%�20�2$�2$�20�2030&30830J30W30p30�30�30�30�3%�3%�304%	404%(4%{4%�40�4%�4%�40�4%�4%�4%5%5%+5%/5'A5�0D50U5%\50e5%�5 �5%�5%�5%�5%�5$�50�50�50�5%�5%6%.6086%N6%T6%Z6%`60x6%�6%�60�6%�6%�60�60�6%�6%�60�6%707%7%7%,70D7%V70n7%z7%�70�7%�70�7%�7$�70�708080-80:80�80�80�80�80�8%�8%�8%�80�8%9%9090#9%)90,90090<90H90K9'[90j90w9%�9%�90�9%�90�9%�90:0:$(:$,:$5:$9:$B:$F:%P:0S:%g:%k:%q:%s:%w:%}:%�:%�:0�:$�:'�:'�:'�:0�:$�:0�:%	;%;%0;%4;$;;0>;%E;0K;0R;0b;0h;${;0�;0�;'�;0�;0�;0�;0�;0�;$�;0<$
<$+<0.<0G<0Q<0g<0n<$�<'�<'�<'�<0�<0�<0=0'=0J=0S=7~= �= �= �= �= �= �=7�=e7�=e0�=7>7)>7C>0c>0m>0�>0�>7�> �> ? ? ? ? ?7?f7/?f0O?7c?7}?7�?0�?0�?0�?$@'@'@0@@ [@0j@ v@ x@ z@0�@0�@0�@$�@$�@$A$A$
A$A0.A04A �A �A �A �A%�A%�A0�A%B0B%%B$uB$yB0|B$�B$�B$�B0�B$�B$�B$�B0�B%�B$�B$�B$�B0�B%�B%�B%�B%�B0�B'	C�0C0C0,C%3C0:C0IC0WC0lC0uC0C'�C'�C7�C7�C7D7D70D0UD0lD$uD$yD0�D0�D0�D0�D'�D%�D$�D0�D0	E0E0*E07E0bE0sE0�E0�E �E0F$F0F%%F0)F0OF0[F$tF0zF0�F0�F%�F%�F0�F0�F0�F0G0,G7fG0{G0�G0�G0�G0�G0�G0�G$�G0�G%�G0H0^H$kH0qH0wH0�H0�H0�H0�H0I0
I$;I0AI0GI0QI0lI0I0�I0�I0�I0�I0�I$
J0
J0[J0dJ0yJ0�J7�J0�J0�J0�J7K'5K�0;K'?Kg%HK0KK7WK�7fK�$oK$sK%wK%{K7�K�%�K%�K%�K%�K%�K%�K7�K�%�K'�K�0�K'�K�0�K'L�0	L%L -L GL IL KL ML0TL0lL0vL0�L%�L0�L0�L �L �L �L �L0�L0�L0�L0�L0M0M ,M HM JM LM NM PM0WM0aM0hM%nM$�M$�M$�M$�M �M �M �M �M �M �M0�M0�M0�M0�M%N0�N0�N0�N0�N0�N0O%O0$O0uO0�O0�O0�O0�O0�O0&P01P%8P0eP0mP0vP0�P0�P0�P0�P0�P0Q0Q0RQ0�Q7�Q0�Q0�Q0�Q0HR0TR0`R0nR0�R7�R0�R0�R0�R7
S0!S0'S%aS$�S$�S$�S0�S0�S$�S0�S'�SA0�S%�S0�S �S$�S%�S0�S0�S0T'TS T$T%T0T0$T0'T'*TS0-T06T'<Td'@Td'IT#'PT#0UT0�T0�T'�Tg$�T$�T0�T'�TE'�TE0�T$�T'U# U$U%"U0%U'+US0.U �� �� �� �� �� �� �� �� �� �� �� l� n� p� r� t� v� x� z� |� ~� �� �� �� �� �� ��'�U�'�U�0�U'�U�'�U�0�U'�U�'�U�0V'$V�'-V�0EV'VV�'_V�0V'�V�'�V�0�V'�V�'�V�0�V'�V�'�V�0W'W�'#W�0;W'�W�'�W�%�W0�W0�W0�W0�W0�W'�W2$�W$�W$�W$�W$�W0�W$�W0�W$�W$�W$�W0�W$�W$X$X0X$
X$X$X$X$ X0#X'*X�07X$CX0FX LX0OX'UX�0^X'dXo$kX0nX0uX0{X'�Xg0�X0�X0�X0�X0�X0
Y%Y%Y%Y0#Y$)Y%2Y%5Y0GY%QY0^Y0zY0�Y0�Y0�Y$�Y%�Y$�Y%�Y%�Y%Z%!Z$&Z%*Z$/Z%2Z$5Z%8Z$;Z%>Z$AZ$GZ%aZ%hZ%kZ%|Z%�Z%�Z%�Z0�Z%�Z0[0[%[%[%"[%2[%A['Y[
0^[%�[%�[%�[%�[%�[%�[%�[%	\%
\$\0\0#\0)\0,\%0\$Q\0T\$Z\0]\'m\�$x\$�\$�\$�\$�\$�\$�\$]0]$]';]�'?]�'C]�'M]�'Q]�'W]']]�'`]�$c]'r]�'v]�'z]�$]0�]$�]'�]d'�]d'�]�'�]'�]�'�]�'�]�'�]�'�]]'�]]'�]d'�]d7�]-'�]2'�]0�]'�]�'�]�#�]'�]�)�]'�]�#^'^�)^'^d'^d0^'%^E � � � � � �  � "� $� &� F^ H^ J^ L^%R^%\^0r^0�^%�^ �^ �^ �^ �^%�^%�^0�^0�^%�^$_0_0 _0S_0z_0�_%�_0�_0�_0�_0�_%`0_`0�`%�`0�`0�`%�`'�`g0�`0�`%4a08a0Qa0aa0ka0qa0�a0�a0�a0�a$�a'�a�0�a$�a$b$b'b�0b$"b%0b%6b%Bb%_b0hb$qb0tb%~b'�bg'�bg'�bg0�b'�bg%c%c0Cc0Gc gc �c �c �c �c �c �c �c �c �c �c �c �c0�c0�c0�c0�c0�c0�c0d0d04d0cd0gd0�d0�d7�d�0�d7�d�$�d0�d'�d'�dg'e'e'e'e'e2'e2'/e�02e0@e0ee0ue0�e0�e'�e�0�e'�e>'�e>'�e>'�e>'�e'�e'f�0f02f'8f�0;f'Sf�0Vf0]f0of%|f0�f0�f0�f0�f0�f%�f0�f0�f%�f%�f%�f%�f0�f'�fg0"g0,g05g'<gg0Hg0eg0lg0rg0yg0�g$�g$�g%�g%�g%�g0�g0�g'�gg0�g0�g0�g%�g%�g0�g%�g%�g0�g0�g0&h'.h'6h0Oh'iho0lh'yh�0|h'�h�'�h�0�h'�hE0�h'�hg0�h0�h%�h0�h0�h'�h�'.i20Ii0Oi0�i0�i%�i0�i �i0�i'�i20�i'�i�0j0j0"j02j'9j�'<j'Hj0uj'|j�'�j
'�jg0�j'�jg%�j0�j0�j'�jg0�j0�j'�j'�j0*k0@k0Lk'lk
0rk'�k#'�k#'�k#'�k#'�k�'�k�'�k�'�k�'�k]'�k]'�k�'�k�'�k]'�k]'�kD'�kD'�k�'�k�'�k]'�k]'�kD'�kD'�kD'�kD'�kD'�kD'�k#'�kD'�k#'�k#'�kD'�k#'�kD0l' lS0#l'3l#'7l#'LlS0Ol0Vl0bl0fl'zl�'~l�'�lS0�l0�l0�l0�l0�l0�l'mg0.m0~m$�m0�m0�m0�m0�m'!nS0$n07n0Bn'JnS0Mn0Zn'`nS0cn0vn0�n'�nS0�n0�n0�n'�n�0�n0�n0�n'oS0o'-oS00o'DoS0Go$So0Vo0fo0ro0yo0�o'�oS0�o0�o'�oS0�o0�o'p#'pd'pd''p#',p�'0p�0mp0p0�p0�p0�p0�p0	q0#q0Kq0eq0}q'�qS0�q0�q0�q0�q0r'rS0r0r0r0#r0qr0�r0�r0�r%�r0�r0�r0�r'�rg0�r0�r'�rA%�r0s'sS0s0s'sS0!s')sS0,s0Qs'WsS0Zs0bs'hsS0ks0zs0�s'�sg0�s0�s0�s0�s0�s'�sA'�sS0�s0�s'tS0	t'tS0t01t0Pt$it$qt7�t-$�t$�t'�td'�td'�t�'�t�$�t0�t'�t�%�t0�t'�tg0	u0#u$�u0�u$�u0�u0�u0�u$�u0�u v0v0(v02v'9vg0\v0�v0�v7�v-$�v$�v'�v�$�v0�v$�v0�v'w�$w$w'5w�08w7�w-'�w�0�w'�wd'�wd'�w#'�w#'�w�'�w�'�w�0�w01x'Nx#0Sx'bx#'ex�'ix�'wx#'�xd'�xd'�x�0�x0�x'y#0y%$y0'y'9yg%Ry%Ty%_y%ty%�y%�y%�y0�y'�yS0�y'�y#'�y#'�yS0�y'�y�'�y�'zS0z0ez'zz�0�z0�z'�zg0{0{'{g%6{%?{0L{%T{0W{0i{0�{0�{'�{g%�{%�{0�{$�{0�{0�{0�{%�{0�{0�{0|0|0|0%|%)|%.|%4|%9|%=|0C|%G|0L|%e|%s|%w|%{|%�|%�|%�|0�|%�|%�|0�|0�|%�|0�|'}�0}'
}'}' }�0#}'*}'7}g%C}'I}�0L}'U}�'[}�'a}�'g}�'k}�'q}�'w}�'|}�0}'�}�'�}�0�}'�}�%�}'�}�0�}'�}�'�}g%�}0�}'�}�0�}'�}'�}0~'~�0	~0~'~�'#~�'/~�02~':~� I~ K~ M~ O~ Q~ S~ U~ W~ Y~ [~'_~�0b~'h~�'n~�0q~'w~�'~�%�~%�~'�~�'�~�0�~'�~�'�~�0�~'�~�'�~�0�~0�~'�~�'�~�'�~�'�~�'�~�%�~%�~'�~�'�~�'�~�'�00	0'.g'C''G'7V- _7m�0y'�g'�''�' �0�'�g%�0�0
�0#�02�$?�$C�$M�$T�$Z�0`�0n�0u�%��%��%��'��g%��'ŀg'Հg%�0��'���0�'
�'�0�05�0:�0F�0L�%P�0T�'f�'j�0o�0��0��%��'��'��'ǁg0݁0�'��'��0(�01�'9��0<�%I�%[�%h�%��%��0��'��g'��g'тg'�g0�'��g%�%$�0'�%<�%D�%J�%P�'c�g0{�%��0��%��%��'��g%��0��%Ń%Ƀ'̓g'�g%��%�%8�%E�0w�0��0��$��0��0��'��''��''ńg0�0�0�'0�g'3��06�'A�'I�0N�'u��0x�0��0��0˅'ׅ�0څ0�0�'��0��%�0�0�0(�00�09�%C�%G�%K�0O�%`�0e�%w�%z�%}�%��%��%��%��%��0��'���%��'���0��'†�'ʆ�0ӆ%ކ%�0�0��'��%�0�02�%=�%L�0Q�0\�%g�0q�0y�0��%��0��%��$ɇ$͇0ׇ0�%��0��$�$�0&�0:�%A�0E�0Y�0x�0��%��0��0�� �� ҈ Ԉ ֈ0�0��0��%�0�0 �05�0H�0\�0k�%��%��0��0�� �� �� �� �� �� ��0É%҉%މ%��%L�0]�%��0��0��0��%��0Ŋ0͊0ӊ0ڊ0�0��%��%��%�0�%�%�%"�0%�%0�08�%?�0B�0L�$Z�$^�0h�0|�%�� �� �� �� ��%�0�0�%'�%1�06�0D�0Q�0h�0r�%v�0|�0��%��0��0��%��0Č%ڌ%�'�0
�0%�%F�0J�$d�%j�0n�0��0��%��0Ѝ0ݍ0�0�0�0� )�'/�g 6�'<�g0C�'P�g0W�0]�'l�g0s�0~�%��0�� �� �� �� ��0Ǝ%ю0֎0�0�0�%-�0=�0L�0^�0o�0~�0��0��0��0��0��0Џ0ޏ%��0�%�0-�%J�%N�%T�%Z�%i�%r�0v�$��$��%��0��%��0��0ΐ%ِ0�0�0��%�0�'�0�0$�%'�0*�%<�%E�0Y�0c�%g�0m�0x�0~�0��%��0��'��%ɑ0͑0ё$ؑ'��'�%��$�'
�'�0,�05�0K�0R�$f�0i�0��0��%��0��%��%Œ0ɒ0Ւ0ܒ%�0�$�$�0&�0-�0D�%O�0U�$d�$h�$q�$u�$~�$��0��0��0Փ$�$� �� �� Ġ Ƞ ̠ Р Ԡ ؠ ܠ � � � � � �� �� �� � � � � � � � �  � $� (� ,� 0� 4� 8� <� @� D� H� L� P� T� X� \� `� d� h� l� p� t� x� |� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� ġ ȡ ̡ С ԡ ء ܡ �0�0>�'P�''T�''s��0x�0��0��0ʔ'ޔ''�''��0�0'�$H�0K�$R�0X�$a�0d�0p�$|�0�0��$��0��0��$��0��0��$͕0Е0ܕ$�0�'��g0��$�0�0�$#�0&�02�$>�0A�0M�$Y�0\�0h�$t�0w�0��'��g$��0��0��%��0��%ʖ0ߖ$��%��0�%�%�%�0�%)�%5�%9�%=�%I�%M�%Q�%U�%Y�%]�%v�0|�%��0��%��0��0�� �� �� �� �� �� �� — ė Ɨ ȗ ʗ ̗ Η З җ$��0��$�$�0�0)�02�$;�0>�0J�$V�0Y�0e�$q�0t�0��$��0��0��$��0��0��'��g$ɘ0̘$ؘ0ۘ%�'�g0�0707070064030053121007440000030000030000011777770507310770100004200000013733/newbits/kernel/USRSYS/config.mwc:
:	configure a Coherent kernel for the AT
:
: usage: config [help]
:	 config [stand=fha0]
:	 config [stand=fva0]
:	 config [stand=fha0] [standard] [root=DRV] [DRV ...]
:	 config [stand=fva0] [standard] [root=DRV] [DRV ...]

:	initialize variables
:
ATSTANDARD=" fl lp mm "
ATKERNEL=atkernel.o

STANDARD="${ATSTANDARD}"
KERNEL="${ATKERNEL}"
LIBS="lib/tty.a lib/support.a"
BUILD=0
DEV=/tmp/dev
PASS1=""
PASS2=""
UNDEF=""
PATCH=""
ROOTDEV=""
INSTALL=""

case "$#" in
0)	/bin/echo
	/bin/echo	"The following can be used as arguments to config:"
	/bin/echo
	/bin/cat doc/*
	exit 0
	;;
esac

for ARG in $*
do
	case "${ARG}" in
	help)
		/bin/echo
		/bin/echo "The following can be used as arguments to config:"
		/bin/echo
		/bin/cat doc/*
		exit 0
		;;
	ibm-at)
		STANDARD="${ATSTANDARD}"
		KERNEL="${ATKERNEL}"
		;;
	*)
		PASS1="${PASS1} ${ARG}"
		;;
	esac
done

for ARG in ${PASS1}
do
	case "${ARG}" in
	standard)
		PASS2="${STANDARD} ${PASS2}"
		;;
	stand\=fha0)
		/etc/umount /dev/fha0 2> /dev/null
		echo -n "Insert 5.25 high capacity floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fha0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fha0 2400		|| exit 1
		/bin/cp /conf/boot.fha /dev/fha0	|| exit 1
		/etc/mount /dev/fha0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,14)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,14)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fha0 ; /bin/df /dev/fha0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	stand\=fva0)
		/etc/umount /dev/fva0 2> /dev/null
		echo -n "Insert high density 3.5 floppy into drive 0, press return [y to format]: "
		read x
		case "x$x" in
		xy)	/etc/fdformat -i 6 /dev/fva0 || exit 1 ;;
		esac
		/etc/mkfs  /dev/fva0 2880		|| exit 1
		/bin/cp /conf/boot.fva /dev/fva0	|| exit 1
		/etc/mount /dev/fva0 /f0		|| exit 1
		/bin/mkdir /f0/bin /f0/dev /f0/etc /f0/mnt /f0/tmp || exit 1
		umask 011
		/etc/mknod /f0/dev/null c 0 0		|| exit 1
		/bin/ln -f /f0/dev/null /f0/dev/swap	|| exit 1
		umask 077
		/etc/mknod /f0/dev/mem  c 0 1		|| exit 1
		/etc/mknod /f0/dev/kmem c 0 2		|| exit 1
		/bin/chmod 777 /f0/tmp			|| exit 1
		umask 022

		/bin/cp /bin/bad /bin/cat /bin/cp /bin/cpdir \
			/bin/db /bin/dd /bin/df /bin/du \
			/bin/echo /bin/kill \
			/bin/ls /bin/mkdir /bin/mv /bin/ncheck \
			/bin/rm /bin/sh /bin/stty /bin/sync \
			/bin/time /bin/true /f0/bin || exit 1
		/bin/cp /etc/fsck /etc/init /etc/badscan /etc/clri \
			/etc/fdisk /etc/mkfs \
			/etc/mknod /etc/mount /etc/umount /f0/etc || exit 1

		DEV=/f0/dev
		:
		: Place a Coherent image out on drive 0.
		: Add a floppy root patched version as a file called 'stand'.
		:
		INSTALL="umask 022; set -e ; /bin/cp coherent /f0 ; \
			/conf/patch coherent 'rootdev_=makedev(4,15)' ; \
			/conf/patch coherent 'pipedev_=makedev(4,15)' ; \
			/bin/cp coherent /f0/stand ; /bin/strip /f0/stand ; \
			/etc/umount /dev/fva0 ; /bin/df /dev/fva0"

		case "$#" in
		1) eval ${INSTALL} ; exit 0 ;;
		esac
		;;

	DEV\=*)
		DEV=`/bin/echo "${ARG}" | /bin/sed -e 's/^....//'`
		;;
	*)
		PASS2="${PASS2} ${ARG}"
		;;
	esac
done

:	get the proper driver information
:

for ARG in ${PASS2}
do
	case "$ARG" in

	root\=fva0)
		ROOTDEV="makedev(4,15)"
		. confdrv/fl
		;;
	root\=fha0)
		ROOTDEV="makedev(4,14)"
		. confdrv/fl
		;;
	root\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			ROOTDEV="${MAKEDEV}"
/bin/echo "'confdrv/${FILE}' executing"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	swap)
		;;

	swap\=*)
		ARG=`/bin/echo "${ARG}" | /bin/sed -e 's/^.....//'`

		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			if [ -d "${DEV-/dev}" ]
			then
				/bin/ln -f ${DEV-/dev}/${ARG} ${DEV-/dev}/swap
			fi
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			PATCH="${PATCH} swapdev_=${MAKEDEV}"
			/bin/echo "Swap device will be ${DEV-/dev}/${ARG}"
			/bin/echo "See documentation before enabling"
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;

	*\=*)
		PATCH="${PATCH} ${ARG}"
		;;

	*)
		case "${ARG}" in
		*[0123][abcdx])
			FILE=`/bin/echo "${ARG}" | /bin/sed -e 's/..$//'`
			;;
		*)
			FILE="${ARG}"
			;;
		esac

		if /bin/test -r confdrv/${FILE}
		then
			. confdrv/${FILE}
			case "${ROOTDEV}" in
			?*)	;;
			*)	ROOTDEV="${MAKEDEV}" ;;
			esac
		else
			/bin/echo "'confdrv/${FILE}' does not exist"
			exit 1
		fi
		;;
	esac
done
ROOTDEV="${ROOTDEV-makedev(4,14)}"

:	include stub drivers
:
UNDEF="${UNDEF} ${LIBS}"

:	make the proper root and pipe devices
:
PATCH="${PATCH} rootdev_=${ROOTDEV} pipedev_=${ROOTDEV}"

set -ex
:
:	create a kernel with the desired device drivers
:
/bin/ld -i -x -o coherent ${KERNEL} ${UNDEF} -lc
:
:	enable the desired device drivers
:
/conf/patch coherent ALLSIZE_=16384 NBUF_=32 NCLIST_=24 ${PATCH}
/bin/chmod 644 coherent
/bin/chown sys coherent
/bin/chgrp sys coherent
/bin/sync
:
eval ${INSTALL}
0707070064030110571007550000030000030000011777770507310770200003700000001165/newbits/kernel/USRSYS/newkers# newkers - copy kernels to floppy
VOL=${1-foo}
case $VOL in
f0 | 5)
	VOL=f0
	PATCH="rootdev_=0x40E"
	;;
f1 | 3)
	PATCH="rootdev_=0x40F"
	VOL=f1
	;;
*)
	echo "Usage: $0 { f0 | 5 | f1 | 3 }"
	exit 0
esac
echo -n "Place boot diskette in $1 drive and press <Enter> "
read JUNK
mount $VOL || exit 1
cp /coh.at /$VOL/begin
ln -f /$VOL/begin /$VOL/coherent
chmog 400 sys sys /$VOL/coherent	
/conf/patch /$VOL/coherent $PATCH pipedev_=0x883 ronflag_=1 || exit 1
cp /coh.ss /$VOL/coherent.ss
chmog 400 sys sys /$VOL/coherent.ss
cp /coh.aha /$VOL/coherent.aha
chmog 400 sys sys /$VOL/coherent.aha
ls -l /$VOL/begin /$VOL/coh*
umount $VOL
0707070064030027041004440000030000030000011777770507310770300002400000015076/newbits/Makefile,vhead     1.1;
access   ;
symbols  ;
locks    ;
comment  @@;


1.1
date     91.03.12.21.05.34;  author bin;  state Exp;
branches ;
next	;


desc
@provided by stevesf. uses SRCPATH. designed to make all
executables. I haven't had time to look at it so It's here until
I do...
@



1.1
log
@Initial revision
@
text
@# /usr/src/cmd/Makefile 2/20/91
# Makefile for COHERENT commands.
# Preliminary, does not yet make most subdirectories.

# Commands in /bin compiled from single sources.
BIN=\
	ac\
	ar\
	at\
	bad\
	banner\
	basename\
	c\
	cal\
	calendar\
	cat\
	chgrp\
	chmod\
	chown\
	cmp\
	col\
	comm\
	conv\
	cp\
	cpdir\
	crypt\
	date\
	dd\
	deroff\
	df\
	du\
	echo\
	egrep\
	epson\
	expr\
	factor\
	file\
	fixstack\
	fnkey\
	from\
	grep\
	help\
	join\
	kill\
	lc\
	ln\
	look\
	ls\
	m4\
	man\
	mesg\
	mkdir\
	msg\
	mv\
	newgrp\
	nm\
	od\
	pr\
	prep\
	prof\
	pwd\
	quot\
	ranlib\
	rev\
	rm\
	rmdir\
	sa\
	scat\
	size\
	sleep\
	sort\
	split\
	strings\
	strip\
	stty\
	sum\
	sync\
	tail\
	tar\
	tee\
	time\
	touch\
	tr\
	tty\
	typo\
	uniq\
	wc\
	who\
	write\
	yes

# Commands in /bin built by making subdirectories.
BIN2=\
	awk\
	check\
	dcheck\
	diff\
	dos\
	dump\
	dumpdate\
	dumpdir\
	ed\
	hp\
	hpr\
	hpskip\
	icheck\
	lex\
	lpr\
	lpskip\
	ncheck\
	restor\
	sed\
	tsort\
	yacc

# Shell scripts in /bin, the source is the executable.
BINSH=\
	diff3\
	false\
	mount\
	phone\
	shutdown\
	spell\
	true\
	umount

# Commands in /bin not yet included.
BINMISSING=\
	as\
	bc\
	cc\
	compress\
	db\
	dc\
	find\
	head\
	ld\
	login\
	mail\
	make\
	msgs\
	nroff\
	passwd\
	ps\
	rmail\
	sh\
	su\
	test\
	troff\
	uncompress\
	units\
	zcat

# Commands in /etc compiled from single sources.
ETC=\
	accton\
	cron\
	mkfs\
	mknod\
	mount\
	umount\
	update\
	wall

# Commands in /etc built from subdirectories.
ETC2=\
	clri

# Commands in /usr/lib compiled from single sources.
USRLIB=\
	atrun

# Commands in /usr/lib built from subdirectories.
USRLIB2=\
	diff3\
	diffh\
	hpd\
	lpd

# Objects built from subdirectories but not currently distributed.
EXTRA=\
	prps

# Sources in /usr/src/cmd but executables not currently distributed.
UNUSED=\
	connect.c\
	detab.c\
	learn.c\
	load.c\
	mf.c\
	mkproto.c\
	more.c\
	uload.c

# Primary target.
all:	$(BIN) $(ETC) $(USRLIB)
	make SRCPATH=$(SRCPATH)/awk
	make SRCPATH=$(SRCPATH)/check
	make SRCPATH=$(SRCPATH)/diff
	make SRCPATH=$(SRCPATH)/dos
	make SRCPATH=$(SRCPATH)/dump
	make SRCPATH=$(SRCPATH)/ed
	make SRCPATH=$(SRCPATH)/grep
	make SRCPATH=$(SRCPATH)/lex
	make SRCPATH=$(SRCPATH)/lpr
	make SRCPATH=$(SRCPATH)/sed
	make SRCPATH=$(SRCPATH)/tsort
	make SRCPATH=$(SRCPATH)/yacc
	: /usr/src/cmd done.

# Secondary targets.
# The actions would not be necessary if make could deal with null extensions.
ac:	ac.c
	$(CC) $(LDFLAGS) -o $@@ $?
accton:	accton.c
	$(CC) $(LDFLAGS) -o $@@ $?
ar:	ar.c
	$(CC) $(LDFLAGS) -o $@@ $?
at:	at.c
	$(CC) $(LDFLAGS) -o $@@ $?
atrun:	atrun.c
	$(CC) $(LDFLAGS) -o $@@ $?
bad:	bad.c
	$(CC) $(LDFLAGS) -o $@@ $?
banner:	banner.c
	$(CC) $(LDFLAGS) -o $@@ $?
basename:	basename.c
	$(CC) $(LDFLAGS) -o $@@ $?
c:	c.c
	$(CC) $(LDFLAGS) -o $@@ $?
cal:	cal.c
	$(CC) $(LDFLAGS) -o $@@ $?
calendar:	calendar.c
	$(CC) $(LDFLAGS) -o $@@ $?
cat:	cat.c
	$(CC) $(LDFLAGS) -o $@@ $?
chgrp:	chgrp.c
	$(CC) $(LDFLAGS) -o $@@ $?
chmod:	chmod.c
	$(CC) $(LDFLAGS) -o $@@ $?
chown:	chown.c
	$(CC) $(LDFLAGS) -o $@@ $?
cmp:	cmp.c
	$(CC) $(LDFLAGS) -o $@@ $?
col:	col.c
	$(CC) $(LDFLAGS) -o $@@ $?
comm:	comm.c
	$(CC) $(LDFLAGS) -o $@@ $?
conv:	conv.o
	$(CC) $(LDFLAGS) -o $@@ $?
conv.o:	conv.y
cp:	cp.c
	$(CC) $(LDFLAGS) -o $@@ $?
cpdir:	cpdir.c
	$(CC) $(LDFLAGS) -o $@@ $?
cron:	cron.c
	$(CC) $(LDFLAGS) -o $@@ $?
crypt:	crypt.c
	$(CC) $(LDFLAGS) -o $@@ $?
date:	date.c
	$(CC) $(LDFLAGS) -o $@@ $?
dd:	dd.c
	$(CC) $(LDFLAGS) -o $@@ $?
deroff:	deroff.c
	$(CC) $(LDFLAGS) -o $@@ $?
df:	df.c
	$(CC) $(LDFLAGS) -o $@@ $?
du:	du.c
	$(CC) $(LDFLAGS) -o $@@ $?
echo:	echo.c
	$(CC) $(LDFLAGS) -o $@@ $?
egrep:	egrep.c
	$(CC) $(LDFLAGS) -o $@@ $?
epson:	i8086/epson.c
	$(CC) $(LDFLAGS) -o $@@ $?
expr:	expr.o
	$(CC) $(LDFLAGS) -o $@@ $?
expr.o:	expr.y
factor:	factor.c
	$(CC) $(LDFLAGS) -o $@@ $? -lm
file:	file.c
	$(CC) $(LDFLAGS) -o $@@ $?
fixstack:	fixstack.c
	$(CC) $(LDFLAGS) -o $@@ $?
fnkey:	i8086/fnkey.c
	$(CC) $(LDFLAGS) -o $@@ $?
from:	from.c
	$(CC) $(LDFLAGS) -o $@@ $?
help:	help.c
	$(CC) $(LDFLAGS) -o $@@ $?
join:	join.c
	$(CC) $(LDFLAGS) -o $@@ $?
kill:	kill.c
	$(CC) $(LDFLAGS) -o $@@ $?
lc:	lc.c
	$(CC) $(LDFLAGS) -o $@@ $?
ln:	ln.c
	$(CC) $(LDFLAGS) -o $@@ $?
look:	look.c
	$(CC) $(LDFLAGS) -o $@@ $?
# N.B. cmd/ls.c is old source, current is in cmd/skut/ls.c.
ls:	skut/ls.c
	$(CC) $(LDFLAGS) -o $@@ $?
m4:	m4.c
	$(CC) $(LDFLAGS) -o $@@ $?
man:	man.c
	$(CC) $(LDFLAGS) -o $@@ $?
mesg:	mesg.c
	$(CC) $(LDFLAGS) -o $@@ $?
mkdir:	mkdir.c
	$(CC) $(LDFLAGS) -o $@@ $?
mkfs:	mkfs.c
	$(CC) $(LDFLAGS) -o $@@ $?
mknod:	mknod.c
	$(CC) $(LDFLAGS) -o $@@ $?
mount:	mount.c
	$(CC) $(LDFLAGS) -o $@@ $?
msg:	msg.c
	$(CC) $(LDFLAGS) -o $@@ $?
mv:	mv.c
	$(CC) $(LDFLAGS) -o $@@ $?
newgrp:	newgrp.c
	$(CC) $(LDFLAGS) -o $@@ $?
nm:	nm.c
	$(CC) $(LDFLAGS) -o $@@ $?
od:	od.c
	$(CC) $(LDFLAGS) -o $@@ $?
pr:	pr.c
	$(CC) $(LDFLAGS) -o $@@ $?
prep:	prep.c
	$(CC) $(LDFLAGS) -o $@@ $?
prof:	prof.c
	$(CC) $(LDFLAGS) -o $@@ $?
pwd:	pwd.c
	$(CC) $(LDFLAGS) -o $@@ $?
quot:	quot.c
	$(CC) $(LDFLAGS) -o $@@ $?
ranlib:	ranlib.c
	$(CC) $(LDFLAGS) -o $@@ $?
rev:	rev.c
	$(CC) $(LDFLAGS) -o $@@ $?
rm:	rm.c
	$(CC) $(LDFLAGS) -o $@@ $?
rmdir:	rmdir.c
	$(CC) $(LDFLAGS) -o $@@ $?
sa:	sa.c
	$(CC) $(LDFLAGS) -o $@@ $?
scat:	scat.c
	$(CC) $(LDFLAGS) -o $@@ $?
size:	size.c
	$(CC) $(LDFLAGS) -o $@@ $?
sleep:	sleep.c
	$(CC) $(LDFLAGS) -o $@@ $?
sort:	sort.c
	$(CC) $(LDFLAGS) -o $@@ $?
split:	split.c
	$(CC) $(LDFLAGS) -o $@@ $?
strings:	strings.c
	$(CC) $(LDFLAGS) -o $@@ $?
strip:	strip.c
	$(CC) $(LDFLAGS) -o $@@ $?
stty:	stty.c
	$(CC) $(LDFLAGS) -o $@@ $?
sum:	sum.c
	$(CC) $(LDFLAGS) -o $@@ $?
sync:	sync.c
	$(CC) $(LDFLAGS) -o $@@ $?
tail:	tail.c
	$(CC) $(LDFLAGS) -o $@@ $?
tar:	tar.c
	$(CC) $(LDFLAGS) -o $@@ $?
tee:	tee.c
	$(CC) $(LDFLAGS) -o $@@ $?
time:	time.c
	$(CC) $(LDFLAGS) -o $@@ $?
touch:	touch.c
	$(CC) $(LDFLAGS) -o $@@ $?
tr:	tr.c
	$(CC) $(LDFLAGS) -o $@@ $?
tty:	tty.c
	$(CC) $(LDFLAGS) -o $@@ $?
typo:	typo.c
	$(CC) $(LDFLAGS) -o $@@ $?
umount:	umount.c
	$(CC) $(LDFLAGS) -o $@@ $?
uniq:	uniq.c
	$(CC) $(LDFLAGS) -o $@@ $?
update:	update.c
	$(CC) $(LDFLAGS) -o $@@ $?
wall:	wall.c
	$(CC) $(LDFLAGS) -o $@@ $?
wc:	wc.c
	$(CC) $(LDFLAGS) -o $@@ $?
who:	who.c
	$(CC) $(LDFLAGS) -o $@@ $?
write:	write.c
	$(CC) $(LDFLAGS) -o $@@ $?
yes:	yes.c
	$(CC) $(LDFLAGS) -o $@@ $?

# Etc.
clean:
	rm *.o
stripall:
	strip $(BIN) $(BIN2) $(ETC) $(ETC2) $(USRLIB) $(USRLIB2)

# end of /usr/src/cmd/Makefile
@
0707070000000000000000000000000000000000010000000000000000000001300000000527TRAILER!!!

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.