program i1284_info;
{The following code is based on the IEEE-1284 probe code from Linux, which was
written by Phil Blundell, Carsten Gross and Jose Renau.

The Turbo Pascal *implementation* is entirely my own creation.

version 1.1 : bugfix. Timing of signals in 'second check' found to work OK
for HP Laserjet 5L, but not for Canon BJ-210. Re-worked code to be compatable
with both types of printers. I assume this is an anomalie with the Linux
code, since the order of operations was copied from there.}

var q,y,z:byte;
    r:array[0..1023] of char;
    f,quit:boolean;
    baseport:word;

const
    numbers:array[0..15] of char = '0123456789ABCDEF';


function read_nibble : byte;assembler;			{ read 4 bits of info }
asm
push dx
   mov dx,baseport
   inc dx       {DX=379h}
   in al,dx
   shr al,3
   and al,0f7h
   test al,10h
  jnz @not_zero
   or al,8
@not_zero:
   and al,0fh
pop dx
end;

Procedure read_baseport;assembler;
asm
xor di,di
mov es,di
mov di,408h
mov ax,es:[di]
mov baseport,ax
end;

procedure print;assembler;
{retezec musi byt na DS:SI a ukonceny 0}
asm
push dx
@cycle:
   mov dl,ds:[si];inc si
   cmp dl,0
  jz @finished
   mov ah,2
   int 21h
  jmp @cycle
@finished:
pop dx
end;

procedure int2str;assembler; {BX = value; DS:SI = ASCIIZ value}
asm                          {AX = numeral base}
push dx
push cx
push bx
push ax
push es
push di
xchg ax,bx
xor cx,cx
seges lea di,numbers
@smycka1:
   cmp ax,0
 jng @konec
 {------------------------}

 xor dx,dx
 div bx     {AX:=AX div 10; zbytek je v DX, PODIL v AX}

 push bx
 {add dx,48}  {48=ord('0')}
 mov bx,dx
 mov dl,es:[di+bx]

 pop bx

 inc cx
 push dx
 jmp @smycka1
 {------------------------}
@konec:

xor bx,bx
cmp cx,0
jnz @smycka2
mov ax,3000h
mov ds:[si+0],ah
mov ds:[si+1],al
jmp @int_2_str_join
@smycka2:
pop ax
mov ds:[si+bx],al
inc bx
loop @smycka2
@zero_value:
mov al,0
mov ds:[si+bx],al
@int_2_str_join:
pop di
pop es
pop ax
pop bx
pop cx
pop dx
end;

const  ieee:pchar = 'IEEE-1284 Parallel port device scan.'#13#10#13#10;
       present:pchar = 'Passed initial check. An IEEE-1284 device is present.'#13#10;
       second:pchar = 'Passed second check. Device ID is readable.'#13#10;
       read_1_timeout:pchar = 'Read1 timeout!'#13#10;
       read_2_timeout:pchar = 'Read2 timeout!'#13#10;
       ok_id:pchar = 'ID Read terminated OK'#13#10#13#10;
       err_id:pchar = 'ID Read terminated with error!'#13#10#13#10;
       our_size:pchar = 'Size our count : ';
       ret_size:pchar = 'Size returned  : ';
       inf_ret:pchar = 'Info returned  : ';
       formatter:pchar = #13#10'                 ';
       failed_1:pchar = 'Failed initial check. No IEEE-1284 device detected.'#13#10;
       failed_2:pchar = 'Failed second check. No device ID Readable.'#13#10;
       crlf:pchar = #13#10;
       calib:pchar = #0#0#0#0#0#0#0;
       timer:pchar = #0#0#0#0#0#0#0;
       timsize:byte = 4;



Procedure Delay;assembler;      {AH=number of loops}
asm
push es
push di
push ax
push bx

@de0:
push ax
push ds

les di,timer
lds si,calib

   xor bx,bx
   mov bl,timsize
@copycounter:
   mov al,ds:[si+bx]
   mov es:[di+bx],al
   sub bl,1
    jnc @copycounter
pop ds

mov ah,1
@de1:
   mov bx,0
@de11:
   sub es:[di+bx],ah
    jnc @de1           {if was 0-1=>255}
   inc bl
   cmp bl,timsize
    jz @de2
    jmp @de11

@de2:
pop ax
dec ah
jnz @de0

pop bx
pop ax
pop di
pop es
end;

function wait : byte;assembler;	{ wait 35ms for response }
{CH=mask, CL=RES}
asm
push dx
push bx
   mov bl,1
   {mov dx,379h}
   mov dx,baseport
   inc dx
@cycle:

   in al,dx
   inc bl
   mov ah,1
   call delay
   cmp bl,40
  jz @quit_cycle
   and al,ch
   cmp al,cl
  jnz @cycle
@quit_cycle:
   mov al,1
   cmp bl,40
  jl @is_true
   xor al,al
@is_true:
pop bx
pop dx
end;

procedure set_delay;assembler;
asm
push ds
push si
xor di,di
mov es,di
mov di,46ch
xor ch,ch
lds si,calib
mov ah,1
mov al,es:[di]
@st1:
cmp al,es:[di]
jz @st1
mov al,es:[di]

@st2:
   mov bx,0
   cmp al,es:[di]
   jnz @st3
@st22:
   add ds:[si+bx],ah
    jnc @st2
   inc bl
   cmp bl,ch
    jng @st23
   inc ch
@st23:
   jmp @st22

jmp @st2
@st3:


mov bl,0
mov cl,6
@tim4:
mov al,ds:[si+bx]   {all bytes of calibrator}
mov ah,ds:[si+bx+1]
shr al,cl        {divides by 64. Better would be div 55, but this is easier}
shl ah,1
shl ah,1
or al,ah
mov ds:[si+bx],al
inc bl
cmp bl,ch
jng @tim4
pop si
pop ds
mov timsize,ch
end;


var ff:text;
     {b:boolean;}
    buffer:array[0..255] of char;
begin
{Set_delay;
write(byte(calib[0]),' ');
write(byte(calib[1]),' ');
write(byte(calib[2]),' ');
write(byte(calib[3]),' ');
write(byte(calib[4]),' ');
write(byte(calib[5]),' ');
write(byte(calib[6]),' ');
writeln;
writeln(timsize);
}


  asm
  lds si,ieee;call print;
  call read_baseport
  call set_delay
  seges lea di,r
  {mov dx,378h}
  mov dx,baseport
  mov al,4;out dx,al
      mov ah,5;call delay
  {mov dx,37ah}
  mov dx,baseport
  add dx,2
  in al,dx;and al,0f7h;out dx,al
  in al,dx;or al,2;out dx,al

  mov cx,7838h;call wait;
  cmp al,0
  jz @no_first
{------------------------------------------------------------------------}
    lds si,present;call print;
    {mov dx,37ah}
    mov dx,baseport
    add dx,2
    in al,dx;or al,1;out dx,al                  { strobe high }
    in al,dx;and al,0fdh;out dx,al              { autofeed low }
       mov ah,1;call delay
    in al,dx;and al,0feh;out dx,al              { stobe low }
       mov ah,1;call delay

    mov cx,2000h;call wait;
    cmp al,0
    jz @no_second

{------------------------------------------------------------------------}

      lds si,second;call print;

      mov f,0
      mov quit,0
      mov bx,0                                   { BX=index into array r() }
      mov ah,1;call delay

{}@repeat_cycle:
        {mov dx,37ah}                             { autofeed high }
        mov dx,baseport
        add dx,2
        in al,dx;or al,2;out dx,al

        mov cx,4000h;call wait

        cmp al,0;jnz @no_timeout1

   {---------------------------------------------------------------------}
          lds si,read_1_timeout;call print;
          {mov dx,37ah}                           { autofeed low }
          mov dx,baseport
          add dx,2
          in al,dx;and al,0fdh;out dx,al
          mov quit,1
   {---------------------------------------------------------------------}
     @no_timeout1:

        call read_nibble                        { get 4 bits }
        mov y,al
        {mov dx,37ah}
        mov dx,baseport
        add dx,2
        in al,dx;and al,0fdh;out dx,al          { autofeed low }
        mov cx,4040h;call wait;
        cmp al,0;jnz @no_timeout2
   {---------------------------------------------------------------------}
          lds si,read_2_timeout;call print;
          mov quit,1
   {---------------------------------------------------------------------}
     @no_timeout2:
          cmp f,0                               { f signals when a byte is }
            jz @f_not_set                       { ready - each 2 passes }
          xor f,1

          mov al,y
          shl al,4
          add al,q
          mov q,al

          mov al,q
          mov es:[di+bx],al
          inc bx

          {mov dx,379h}
          mov dx,baseport
          add dx,1
          in al,dx;and al,8                      { eof? }
          cmp al,8
            jnz @no_eof
          mov quit,1
       @no_eof:
            jmp @f_join

     @f_not_set:

          xor f,1
          mov al,y
          mov q,al
     @f_join:

          cmp bx,1023
            jng @s_no_greater                   { out of table space ? }
          mov quit,1
       @s_no_greater:


      cmp quit,0
        jz @repeat_cycle
{-----------------------------------------------------------------------}

      {mov dx,37ah}
      mov dx,baseport
      add dx,2
      in al,dx;and al,0fdh;or al,8;out dx,al    { terminate read }

      push 80h;push 00h;call wait;

      cmp al,0
        jz @id_error
      lds si,ok_id;call print;
        jmp @id_join
   @id_error:
      lds si,err_id;call print;
   @id_join:


{ Display Result, nicely formatted }

      { Display Result, nicely formatted }

    lds si,our_size;call print;
    mov ax,10
    lea si,buffer;call int2str;call print;
    lds si,crlf;call print;

    lds si,ret_size;call print;
    mov ah,es:[di]
    mov al,es:[di+1]
    mov cx,bx
    mov bx,ax
    mov ax,10
    lea si,buffer;call int2str;call print;
    lds si,crlf;call print;
    lds si,inf_ret;call print;




    mov bx,2
@write_cycle:
    mov al,es:[di+bx]
    cmp al,59 {;}
   jnz @normal_char
    lds si,formatter;call print;
   jmp @write_join
@normal_char:
    mov dl,al
    mov ah,2
    int 21h
@write_join:
    inc bx
    cmp bx,cx
    jng @write_cycle
    lds si,crlf;call print;
    lds si,crlf;call print;
      jmp @go_exit

@no_second:
    lds si,failed_2;call print;
      jmp @Go_Exit

@no_first:
    lds si,failed_1;call print;
    mov dx,37ah;in al,dx;and al,0fdh;or al,8;out dx,al

@go_exit:
mov ax,4c00h
int 21h
end;

end.
