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;
    i,s:integer;
    f,quit:boolean;

Procedure Delay(m:byte);assembler;
asm
@smycka2:
mov cx,-1;@smycka: nop;nop;nop;loop @smycka
dec m
jnz @smycka2
end;

function wait : boolean;assembler;	{ wait 35ms for response }
{CH=mask, CL=RES}
asm
push dx
push bx
   mov bl,1
@cycle:
   mov dx,379h
   in al,dx
   inc bl
   push 5
   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;


(*function wait(mask,result:byte) : boolean;	{ wait 35ms for response }
var x,i:byte;
begin
  i:=1;
  repeat
    x:=port[$379];
    inc(i);
    delay(1);
  until ((x and mask)=result) or (i=40);	{ 40 = small error margin }
  if i<40 then wait:=true else wait:=false;
end;*)

function read_nibble : byte;assembler;			{ read 4 bits of info }
asm
push dx
   mov 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;

(*function read_nibble : byte;			{ read 4 bits of info }
var z:byte;
begin
  z:=(port[$379] shr 3) and $f7;
  if z and $10=0 then z:=z or 8;
  read_nibble:=z and $f;
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
push dx
push cx
push bx
push ax
mov ax,bx
mov bx,10
xor cx,cx
@smycka1:
   cmp ax,0
 jng @konec
 {------------------------}

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

 add dx,48  {48=ord('0')}
 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 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;

var ff:text;
     b:boolean;
    buffer:array[0..255] of char;
begin
  Assign(ff,'');
  Rewrite(ff);

  asm
  lds si,ieee;call print;
  seges lea di,r

  mov dx,378h
  mov al,4;out dx,al
      push 5;call delay
  mov dx,37ah
  in al,dx;and al,0f7h;out dx,al
  in al,dx;or al,2;out dx,al

  push 78h;push 38h;call wait;mov b,al
  cmp al,0
  jz @no_first
{------------------------------------------------------------------------}
    lds si,present;call print;
    mov dx,37ah
    in al,dx;or al,1;out dx,al                  { strobe high }
    in al,dx;and al,0fdh;out dx,al              { autofeed low }
       push 5;call delay
    in al,dx;and al,0feh;out dx,al              { stobe low }
       push 5;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 s,0                                   { s=index into array r() }
      push 5
      call delay

{}@repeat_cycle:
        mov dx,37ah                             { autofeed high }
        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 }
          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
        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 bx,s
          mov al,q
          mov es:[di+bx],al
          inc s

          mov dx,379h
          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 s,1023
            jng @s_no_greater                   { out of table space ? }
          mov quit,1
       @s_no_greater:


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

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

      push 80h;push 00h;call wait;mov b,al

      cmp B,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 bx,s
    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]
    {xchg ax,bx
    mov cx,ax}
    mov bx,ax
    lea si,buffer;call int2str;call print;
    lds si,crlf;call print;
    lds si,inf_ret;call print;
    mov cx,bx



    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:
end;

Close(ff);
end.
