program CAMTest;

{ This program performs a simple test to see what SCSI devices are
  attached to an MS-DOS machine with a CAM driver. The CAM unit tests
  for the presence of CAM automatically. This program then performs
  a Path Inquiry command -- which verifies that a SCSI bus exists and
  that the program has allocated sufficient buffer space. It then
  sends a series of Device Inquiry commands to each of the 8 possible
  SCSI device addresses and reports what it finds. The CAM unit provides
  an object-oriented framework for this process and hides most of its
  complexity. }

{ Copyright (C) 1991 by Brett Glass, All Rights Reserved.
  Original program concept from BallardSynergy CAM Developer's
   Toolkit, Copyright (C) 1990 by BallardSynergy, All Rights Reserved.
   Used with permission. }

uses CAM;

var
  pathInq : PathInquiryCCB; {CCB for path inquiry request}
  scsiReq : SCSIRequestCCB; {CCB for SCSI I/O requests}
  inqBuf  : array [0..31] of Byte; {Buffer for data returned by inquiry}
  id : Byte; {SCSI ID loop counter}
  i : Integer; {Temporary character counter}

procedure WriteDevType(d : Byte);
{ Write the type of device that's associated with a number, according
  to the SCSI spec }
begin
case d of
  0 : Write('Disk');
  1 : Write('Tape');
  2 : Write('Printer');
  4 : Write('WORM')
else
  Write('Unknown')
  end;
end;


begin {Main Program}
{Doing a Path Inquiry is as simple as invoking two methods.}
with pathInq do
  begin
  Init; {Set all fields to their default values}
  Submit; {Submit the CCB for processing}
  {Wait for completion; pro forma on single-tasking systems like MS-DOS}
  while camStatus = STAT_REQUEST_IN_PROGRESS do;
  if camStatus <> STAT_REQUEST_DONE_NO_ERROR then
    begin
    Writeln('Path Inquiry returned error ', pathInq.camStatus);
    Halt;
    end;
  if privateDataSize > SCSI_REQUEST_FILL_SIZE then
    begin
    Writeln('Error: CCB not big enough to allow SCSI requests');
    Halt;
    end;
  end;
Writeln;
Writeln('SCSI Device Report');
Writeln('------------------');
for id := 0 to 7 do {Loop over all 8 SCSI ids}
  begin
  with scsiReq do
    begin
    Init;
    camFlags := CAM_DIR_DATA_IN; {We're receiving data}
    targetID := id; {From this device}
    cdbLength := 6; {We're sending 6 bytes of command}
    dataLength := 32; {And receiving 32}
    dataPtr := @inqBuf; {In this buffer}
    cdb[0] := $12; {Inquiry command}
    cdb[4] := 32; {Maximum size of buffer}

    Submit; {Submit the request}

    while camStatus = STAT_REQUEST_IN_PROGRESS do; {Wait for completion}
    {Report the results}
    Write(id, ': ');
    case camStatus of
      STAT_REQUEST_DONE_NO_ERROR:
        begin
        {There's a device there; say what kind it is and show its ID string}
        WriteDevType(inqBuf[0]);
        Write(' -- ');
        {Write string returned by inquiry}
        for i := 8 to 32 do
          Write(Char(inqBuf[i]));
        Writeln;
        end;
      STAT_SELECTION_TIMEOUT:
        Writeln('No device present');
      STAT_SCSI_BUS_BUSY:
        Writeln('Device busy');
      STAT_INVALID_TARGET_ID:
        Writeln('Host')
    else
      Writeln('** ERROR **')
      end;
    end;
  end;
end.
