[comp.realtime] pSOS SCSI driver

unhd (Roger Gonzalez ) (06/04/90)

Here's the SCSI driver that was requested.  I'm not sure if
the interest of only 6 people warrants a post instead of mail,
but I don't have much choice, since mail to all but one bounced.

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by root on Mon Jun  4 1990 12:04:00
# Contents:  LICENSE.MSEL SCSI.DOC iv3273.h parse_args.c scsi.c scsi.h
#	scsi_aux.c scsi_bus.c scsi_cmds.c scsi_defs.h scsi_psos.c scsi_types.h
#	scsi_vars.h scsimon.c
 
echo x - LICENSE.MSEL
sed 's/^@//' > "LICENSE.MSEL" <<'@//E*O*F LICENSE.MSEL//'
--------------------------------------------------------------------------------
MSEL Software General Public License

Because the software produced at the Marine Systems Engineering
Laboratory (MSEL) is entirely in the public domain, the purpose of this
license is to ensure that prospective users of this software may only
use, modify, or redistribute it for non-profit applications in the
public domain. 

MSEL software is available at distribution cost.

Comments, suggestions, and criticisms about our software and licensing
policies are welcome and encouraged.

	Marine Systems Engineering Laboratory
	UNH Marine Programs Building
	Durham, N.H.  03824
	(603) 862-4600

--------------------------------------------------------------------------------
1) Use, modification, or distribution of MSEL software implies agreement
   with this license.

2) Every distribution of MSEL software must be accompanied by this licensing
   agreement, which is Copyright (c) 1990, Marine Systems Engineering 
   Laboratory, and may not be altered.

3) MSEL software, and any software that uses or includes MSEL code,
   must be distributed at no cost, and entirely in the public domain.

4) MSEL software may be freely modified, as long as valid MSEL copyright
   notice appears prominently in every file containing MSEL code, and 
   in any documentation that pertains to software containing MSEL code.

5) No warranties are provided to users of MSEL software, to the extent
   permitted by applicable state laws.  Except when otherwise stated in
   writing by MSEL, the software is provided "as is", without warranty
   of any kind, expressed or implied.
--------------------------------------------------------------------------------


@//E*O*F LICENSE.MSEL//
chmod u=rw,g=rw,o=rw LICENSE.MSEL
 
echo x - SCSI.DOC
sed 's/^@//' > "SCSI.DOC" <<'@//E*O*F SCSI.DOC//'
First of all, if you are expecting a nice tight package ready to run, 
this isn't it.  You will need lots of pizza and coke before even looking
through this stuff.

This SCSI driver software was designed to be used with a WORM optical
drive, controlled by an Ironics iv3273 VME system controller board, and
thus there are many reflections of this in the code:

- The code is not particularly optimized, because WORM devices are slow.

- The command set implemented contains some WORM specific commands.

- Although most ANSI-1 WORM commands are in the code, many are untested.

- Since our application requires only one device, arbitration is not
  implemented.

- The code controls a NCR5380, a buggy SCSI controller chip.

- This code will be a big chore to alter if the NCR5380 registers are not
  mapped into system memory.

- The code is sparsely commented, but was written to be readable to C
  programmers.

- This code is written to run on Unix, or on pSOS with Unix C libraries
  mapped to pSOS equivilents (I trust most people have done this..!)
  Fortunately, at the driver level, the C routines called are minimal.

- Not all necessary include files are bundled with the package, but the
  required typedefs or #defines should be obvious (i.e. U_int is unsigned
  int)

So.  You aren't discouraged so far, because you have a VME machine, with
a SCSI controller board with a NCR5380 mapped into VME memory.  How do you
get this to run.  Here's the recipe:

1) Change all occurences of IV3273 to some variable that you have #defined
   to be the base address of your NCR5380 chip.  If you are running from
   a Unix development environment, this should be a virtual address as
   reflected by a phys() in your application code.  If a pSOS target, then
   use the physical address.

2) Change the structure definitions of the '5380 registers (if necessary)
   to reflect whatever E.E. weenie scheme they implemented on your board.
   If you're lucky, you can take out all the dummy byte references.

3) Compile, and fix all the little things that you (or I) forgot.  With
   luck, they should be self-documenting.  I suggest building a library
   with the .o files; I use 3 libraries: a pSOS version, a Unix version,
   and a version for PROMming.

4) Write a quick and dirty routine to call scsi_reset().  Build the "scsimon"
   program to watch the scsi bus.  Leave it running whild you run your reset
   program.  You should see the "R" bit highlight, and then go dim.

5) Buy a new real-time OS that gives you a commercial SCSI driver so that
   you don't have to do work like this and reinvent the wheel.


Well, thats that.  Feel free to call me, but don't expect much.  I prefer
email so that I can just file it make bugfixes at my leisure.  If you are
having problems not directly related to my code, don't ask me.  If you
find the SCSI code difficult to understand, well, it *is*.  Buy the SCSI
spec from
Global Engineering Documents
2805 McGraw Drive, Irvine CA 92714
(800) 854-7179.

I'm willing to help you *only* if you are running a fairly similar system
to mine, and understand C, SCSI, the NCR5380, VME addressing, pSOS/Unix,
and are running my code with little modification.  Driver code is very
subtle stuff, and can be affected by little things.  I don't have the time
to track down little buggies in your system; it was bad enough doing it
on mine.  My suggestion is to use this code as a *reference*, and not to
try to use it until you completely understand it.  If you run this on
a Unix development system as root, and screw up, you're probably going to
take the system down, cause data loss, and generally make lots of sparks.
Be careful, and have fun.  The SCSI driver animal is a very satisfying
beast to grind beneath your heel!  :-)

-Roger


@//E*O*F SCSI.DOC//
chmod u=rw,g=rw,o=rw SCSI.DOC
 
echo x - iv3273.h
sed 's/^@//' > "iv3273.h" <<'@//E*O*F iv3273.h//'
/*	@(#)iv3273.h	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    10/89
  Modification History:
******************************************************************/

/* Board description of Ironics IV3273 System Controller board              */
/* References: IV3273 Manual (pp6.1-6.54), NCR5380 Manual (pp10-17).        */

/* This section defines the templates for the NCR5380 SCSI interface chip   */

typedef struct {                    /* READ mode (IOR pulse)                */
    byte    curr_data;              /* Read active SCSI data bus            */
    byte        dummy1;             /* The iv3273 puts "empty" spots in     */
    byte    init_cmd;               /* Assert SCSI bus signals (see below)  */
    byte        dummy2;
    byte    mode;                   /* Controls chip operation (see below)  */
    byte        dummy3;
    byte    target_cmd;             /* Target command register              */
    byte        dummy4;
    byte    status_1;               /* 7 bus sigs + parity bit              */
    byte        dummy5;
    byte    status_2;               /* 2 bus sigs + 6 status bits           */
    byte        dummy6;
    byte    input_data;             /* used to read latched data from bus   */
    byte        dummy7;
    byte    reset_status;           /* a read resets ParErr/IntReq/BusyErr  */
} ncr5380_rd;

typedef struct {                    /* WRITE mode (IOW pulse)               */
    byte    output_data;            /* sends data to scsi bus               */
    byte        dummy1;
    byte    init_cmd;               /* ditto as read                        */
    byte        dummy2;
    byte    mode;                   /* ditto as read                        */
    byte        dummy3;
    byte    target_cmd;             /* ditto as read                        */
    byte        dummy4;
    byte    select_enable;          /* see manual - mondo strange           */
    byte        dummy5;
    byte    dma_send;               /* initiate dma send (set dma mode 1st) */
    byte        dummy6;
    byte    dma_target_rec;         /* start dma receive in target mode     */
    byte        dummy7;
    byte    dma_init_rec;           /* start dma receive in initiator mode  */
} ncr5380_wr;
@//E*O*F iv3273.h//
chmod u=rw,g=rw,o=rw iv3273.h
 
echo x - parse_args.c
sed 's/^@//' > "parse_args.c" <<'@//E*O*F parse_args.c//'
#include <stdio.h>
#include <string.h>

char active_flags[10];

int parse_args(legal_flags, p_argc, p_argv, inputfile, outputfile)
    char *legal_flags;
    int p_argc;
    char *p_argv[];
    char *inputfile;
    char *outputfile;
{
    int c, flag, argnum;
    char f;
    
    *inputfile = NULL;
    *outputfile = NULL;
    *active_flags = NULL;
    c = 0;
    for (argnum = 1; argnum < p_argc; argnum++) {
        if (p_argv[argnum][0] == '-') {
            for (flag = 1; flag <= strlen(p_argv[argnum]) - 1; flag++) {
                f = p_argv[argnum][flag];
                if (strchr(legal_flags, f) == NULL) {
                    fprintf(stderr, "%s: bad flag -%c.\n",p_argv[0], f);
                    return -1;
                }
                active_flags[c] = f;
                c++;
            }
        }
        else {
            if (*inputfile == NULL)
                strncpy(inputfile, p_argv[argnum], 80);
            else if (*outputfile == NULL)
                strncpy(outputfile, p_argv[argnum], 80);
            else
                fprintf(stderr, "%s: extra argument ignored: %s\n", p_argv[0], p_argv[argnum]);
        }
    }
    active_flags[c] = NULL;
    return 0;
}

int on(flag)
    char flag;
{
    if (strchr(active_flags, flag) == NULL) {
        return 0;
    }
    else {
        return 1;
    }
}

int turn_on(flags)
    char *flags;
{
    strcat(active_flags, flags);
}    
@//E*O*F parse_args.c//
chmod u=rw,g=rw,o=rw parse_args.c
 
echo x - scsi.c
sed 's/^@//' > "scsi.c" <<'@//E*O*F scsi.c//'
/*	@(#)scsi.c	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/
#include "../include/scsi.h"
#include "../include/scsi_vars.h"
    
/*----------------------------------------------------------------------------*/
/* traverse - given a scsi command, traverses a state table of bus states     */
/*----------------------------------------------------------------------------*/
Exit_packet traverse(cmd, cmdlen, data, datalen, rs, dt)
    Byte        *cmd;           /* SCSI command packet      */
    short       cmdlen;         /* length of packet         */
    Byte        *data;          /* data packet              */
    short       datalen;        /* length of packet         */
    Byte        rs;             /* true if req sen on error */
    Byte        dt;             /* flag for data transfer   */
{
    Byte        status;         /* status byte returned from scsi transfer  */
    Byte        message;        /* message byte returned from scsi          */
    Byte        exit_val;       /* exit value from scsi transfer            */
    Byte        sense[16];      /* 16 byte request sense storage space      */
    Byte        retries;        /* # of retries counter                     */
    Byte        state, newstate;/* state table variables                    */
    Byte        rsflag;         /* true if a request sense will be used     */
    Byte        resets;         /* # of bus resets counter                  */
    Exit_packet ep, rep;        /* exit packet variables                    */

    rsflag = FALSE;
    newstate = START;
    state = START;
    retries = 0;
    resets = 0;

    ep.type = SUCCESS;
    ep.scsi = SUCCESS;
    ep.status = SUCCESS;
    ep.message = 0;
    ep.sense = NO_SENSE;
    ep.xsense = NO_SENSE;
    
    rep.type = SUCCESS;
    
    exit_val = 0;
#ifdef DEBUG    
    printf("States: ");
#endif
    while ((state & EXIT) != EXIT) {
        newstate = find_next_state(state, exit_val, dt, retries);
#ifdef DEBUG
        printf("%d-", newstate);
#endif
        switch(newstate) {
            case BUSFREE:
                exit_val = scsi_bus_free();
                if (exit_val)
                    ep.scsi = BUS_FREE_FAILURE;
                break;
            case SELECT:
                exit_val = scsi_select();
                if (exit_val)
                    ep.scsi = SELECT_FAILURE;
                break;
            case COMMAND:
                exit_val = scsi_put(COMMAND_PHASE, cmd, cmdlen);
                if (exit_val)
                    ep.scsi = COMMAND_FAILURE;
                while (scsi_phase() == COMMAND_PHASE)
                    ;
                break;
            case DATAIN:
                if (scsi_phase() == STATUS_PHASE) {
                    rsflag = TRUE;      /* uh oh, we'd better reqsen    */
                    exit_val = 0;
                }
                else {
                    exit_val = scsi_get(DATA_IN_PHASE, data, datalen);
                    if (exit_val)
                        ep.scsi = DATA_FAILURE;
                }
                break;
            case DATAOUT:
                if (scsi_phase() == STATUS_PHASE) {
                    rsflag = TRUE;      /* uh oh, we'd better reqsen    */
                    exit_val = 0;
                }
                else {
                    exit_val = scsi_put(DATA_OUT_PHASE, data, datalen);
                    if (exit_val)
                        ep.scsi = DATA_FAILURE;
                }
                break;
            case STATUS:
                exit_val = scsi_get(STATUS_PHASE, &status, 1);
                if (exit_val)
                    ep.scsi = STATUS_FAILURE;
                if (!exit_val && status)
                    rsflag = TRUE;
                ep.status = status;
                while (scsi_phase() == STATUS_PHASE)
                    ;
                break;
            case MESSAGE:
                ep.sense = NO_SENSE;
                ep.xsense = NO_SENSE;
                exit_val = scsi_get(MSG_IN_PHASE, &message, 1);
                if (exit_val)
                    ep.scsi = MESSAGE_FAILURE;
                else {
                    ep.scsi = SUCCESS;
                    retries = 0;
                }
                ep.message = message;
                if (rs && rsflag && !exit_val) {
#ifdef DEBUG
                    printf("\nRequesting sense data... ");
#endif                                        
                    rep = request_sense(0, sense, 16);  /* note: this is    */
                    if (rep.type == SUCCESS) {          /* recursing here   */
                        ep.sense = sense[2];
                        ep.xsense = sense[12];
                        rsflag = FALSE;
                    }
                    else {
                        printf("\nrequest sense did not work.\n");
                        newstate = DEATH;
                    }
                }
                switch(ep.sense) {
                    case NO_SENSE:
                        newstate = COMPLETED;
                        break;
                    case RECOVERED_ERROR:
                        newstate = COMPLETED;
                        ep.type = CORRECTED;
                        break;
                    case NOT_READY:
                        newstate = operator(ep);
                        ep.type = OPERATOR;
                        break;
                    case MEDIUM_ERROR:
                        newstate = operator(ep);
                        ep.type = OPERATOR;
                        break;
                    case HARDWARE_ERROR:
                        newstate = operator(ep);
                        ep.type = OPERATOR;
                        break;
                    case ILLEGAL_REQUEST:
                        newstate = operator(ep);
                        ep.type = OPERATOR;
                        break;
                    case UNIT_ATTENTION:
                        if (ep.xsense == 28) {
                            ep.type = NEWMEDIA;
                            newstate = DEATH;
                        }
                        else {
                            newstate = START;
                            ep.type = SUCCESS;
                        }
                        break;
                    case DATA_PROTECT:
                        ep.type = OPERATOR;                        
                        newstate = operator(ep);
                        break;
                    case BLANK_CHECK:
                        newstate = DEATH;
                        ep.type = FAIL;
                        break;
                    case ABORTED_COMMAND:
                        newstate = START;
                        ep.type = RETRY;
                        break;
                }
#ifdef DEBUG                
                printf("\n");
#endif                
                break;
            case ERROR:
                printf("Too many SCSI errors.. wait for soft reset.\n");
                exit_val = scsi_reset();
                if (resets++ > 2) {         /* this isn't working right.    */
                    newstate = DEATH;       /* the intention is to quit     */
                    ep.type = FATAL;        /* after 3, but it doesn't.     */
                }                           /* but then, if you have to     */
                else                        /* reset more than twice, there */
                    newstate = START;       /* are *big* problems!          */
                break;
                
        }
        if (state == newstate) {
             retries++;
        }
        state = newstate;
    }
    
    if (ep.scsi != SUCCESS)
        ep.type = SCSIFAIL;
        
    return(ep);
}
/*----------------------------------------------------------------------------*/
@//E*O*F scsi.c//
chmod u=rw,g=rw,o=rw scsi.c
 
echo x - scsi.h
sed 's/^@//' > "scsi.h" <<'@//E*O*F scsi.h//'
/*	@(#)scsi.h	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/
#include "/usr/usr1/include/types.h"
#include "/usr/usr1/include/defs.h"
#include "/usr/usr1/maxtor/src/rg/include/scsi_types.h"
#include "/usr/usr1/maxtor/src/rg/include/scsi_defs.h"

extern Byte         it_went_high();
extern Byte         it_went_low();

extern U_int        scsi_reset();
extern U_int        scsi_select();
extern U_int        scsi_get();
extern U_int        scsi_put();

extern Exit_packet  traverse();
extern Exit_packet  read_blocks();
extern Exit_packet  write_blocks();
extern Exit_packet  request_sense();
extern Exit_packet  inquiry();
extern Exit_packet  mode_sense();
extern Exit_packet  medium_removal();

extern char         states[9][16];
@//E*O*F scsi.h//
chmod u=rw,g=rw,o=rw scsi.h
 
echo x - scsi_aux.c
sed 's/^@//' > "scsi_aux.c" <<'@//E*O*F scsi_aux.c//'
/*	@(#)scsi_aux.c	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/

#include "../include/scsi.h"

/*--------------------------------------------------------------------------*/
/* find_next_state - auxillary routine for "traverse".                      */
/*--------------------------------------------------------------------------*/

Byte find_next_state(state, exit_val, data, retries)
    Byte state, exit_val, data, retries;
{
    short       x;
    
    x = ((exit_val == SUCCESS)? (data) :( ((retries + 1) << 2) | data));

    return(states[state][x]);
}

/*--------------------------------------------------------------------------*/
/* it_went_high - return true if the register bits go high before timeout   */
/*--------------------------------------------------------------------------*/

Byte it_went_high(regaddr, bitmap)
    Byte    *regaddr;
    Byte    bitmap;
{
    U_int   counter = 0;

    while ((++counter < LIMIT) && ((*regaddr & bitmap) != bitmap))
        ;
    return ((counter < LIMIT)? TRUE : FALSE);
}

/*--------------------------------------------------------------------------*/
/* it_went_low - return true if the register bits go low before timeout     */
/*--------------------------------------------------------------------------*/

Byte it_went_low(regaddr, bitmap)
    Byte    *regaddr;
    Byte    bitmap;
{
    U_int   counter = 0;
    while ((++counter < LIMIT) && ((~(*regaddr) & bitmap) != bitmap))
        ;
    return((counter < LIMIT)? TRUE : FALSE);
}

/*--------------------------------------------------------------------------*/
@//E*O*F scsi_aux.c//
chmod u=rw,g=rw,o=rw scsi_aux.c
 
echo x - scsi_bus.c
sed 's/^@//' > "scsi_bus.c" <<'@//E*O*F scsi_bus.c//'
/*	@(#)scsi_bus.c	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/

#include "../include/scsi.h"
#include "/usr/usr1/include/iv3273.h"

/*--------------------------------------------------------------------------*/
/* scsi_bus_free - return true if the bus becomes free before timeout       */
/*--------------------------------------------------------------------------*/

U_int scsi_bus_free()
{
    Ncr5380_rd  *sread = (Ncr5380_rd *) IV3273;

    if (!it_went_low(&sread->status_1, SEL | BSY)) {
#ifdef DEBUG        
        printf("scsi_bus_free: bus is selected or busy\n");
#endif        
        return(TIMEOUT);
    }
    else
        return(SUCCESS);
}

/*--------------------------------------------------------------------------*/
/* scsi_reset - toggle the reset control bit of the scsi bus                */
/*--------------------------------------------------------------------------*/

U_int scsi_reset()
{
    Ncr5380_rd  *sread = (Ncr5380_rd *) IV3273;
    Ncr5380_wr  *swrite = (Ncr5380_wr *) IV3273;
    Byte        dummy;

    swrite->init_cmd = ASSERT_RST;
    sleep(1);
    swrite->init_cmd = 0x00;
    dummy = sread->reset_status;    
    sleep(10);
    return(SUCCESS);
}

/*--------------------------------------------------------------------------*/
/* scsi_phase - returns the current phase of the scsi bus                   */
/*--------------------------------------------------------------------------*/

U_int scsi_phase()
{
    Ncr5380_rd  *sread = (Ncr5380_rd *) IV3273;

    return((sread->status_1 & 0x1c) >> 2);
}

/*--------------------------------------------------------------------------*/
/* scsi_select - select a target (NO ARBITRATION SUPPORTED!)                */
/*--------------------------------------------------------------------------*/

U_int scsi_select()
{
    Ncr5380_rd  *sread = (Ncr5380_rd *) IV3273;
    Ncr5380_wr  *swrite = (Ncr5380_wr *) IV3273;
    
    swrite->output_data = 0x01;	                    /* Put target ID on bus */
    swrite->init_cmd = ASSERT_DB;
    swrite->init_cmd = ASSERT_SEL | ASSERT_DB;
    swrite->target_cmd = 0x00;
    if (!it_went_high(&sread->status_1, BSY)) {     /* Did target respond?  */
#ifdef DEBUG    
        printf("scsi_select timeout: no response from target\n");
#endif        
        return(TIMEOUT);                            /* No.                  */
    }
    swrite->init_cmd = 0x00;          
    return(SUCCESS);                                /*  go home.            */
}

/*--------------------------------------------------------------------------*/
/* scsi_put - transfer bytes to the scsi bus.  the target must be ready to  */
/*            receive the bytes, or an error will be returned.              */
/*--------------------------------------------------------------------------*/

U_int scsi_put(phase_cmd, buffer, count)
    Byte    phase_cmd;
    Byte    *buffer;
    U_int   count;
{
    Ncr5380_rd  *sread = (Ncr5380_rd *) IV3273;
    Ncr5380_wr  *swrite = (Ncr5380_wr *) IV3273;
    U_int       c;
    Byte        r;

    swrite->target_cmd = phase_cmd;
    if (!it_went_high(&sread->status_2, PHASE_MATCH)) {
#ifdef DEBUG        
        printf("phase %d scsi_put timeout: mismatch with target phase %d.\n",phase_cmd, (sread->status_1 & 0x1c) >> 2);
#endif        
        return(TIMEOUT);
    }
    for (c = 0; c < count; c++) {
        if (!it_went_high(&sread->status_1, REQ)) {
#ifdef DEBUG            
            printf("phase %d scsi_put timeout: no request on Byte %d.\n", phase_cmd, c);
#endif
            return(TIMEOUT);
        }
        if (sread->status_2 == IRQ_ACTIVE) {
            r = sread->reset_status;
        }
        swrite->output_data = buffer[c];
        swrite->init_cmd = ASSERT_DB;
        swrite->init_cmd = ASSERT_DB | ASSERT_ACK;
        if (!it_went_low(&sread->status_1, REQ)) {
#ifdef DEBUG            
            printf("phase %d scsi_put timeout: no acknowledge on Byte %d.\n", phase_cmd, c);
#endif            
            return(TIMEOUT);
        }
        swrite->init_cmd = 0x00;
    }
    return(SUCCESS);
}
/*--------------------------------------------------------------------------*/
/* scsi_get - read bytes from the scsi bus                                  */
/*--------------------------------------------------------------------------*/

U_int scsi_get(phase_cmd, buffer, count)
    Byte    phase_cmd;
    Byte    *buffer;
    U_int   count;
{
    Ncr5380_rd  *sread = (Ncr5380_rd *) IV3273;
    Ncr5380_wr  *swrite = (Ncr5380_wr *) IV3273;
    Byte        r;
    U_int       c = 0;
    
    swrite->target_cmd = phase_cmd;
    if (!it_went_high(&sread->status_2, PHASE_MATCH)) {
#ifdef DEBUG        
        printf("phase %d scsi_get timeout: mismatch with target phase %d.\n", phase_cmd, (sread->status_1 & 0x1c) >> 2);
#endif        
        return(TIMEOUT);
    }
    while ((c < count) && ((sread->status_2 & PHASE_MATCH) == PHASE_MATCH)) {
        if (!it_went_high(&sread->status_1, REQ)) {
#ifdef DEBUG            
            printf("phase %d scsi_get timeout: no request on Byte %d.\n", phase_cmd, c);
#endif            
            return(TIMEOUT);
        }
        if (sread->status_2 == IRQ_ACTIVE)
            r = sread->reset_status;
        buffer[c++] = sread->curr_data;
        swrite->init_cmd = ASSERT_ACK;
        if (!it_went_low(&sread->status_1, REQ)) {
#ifdef DEBUG            
            printf("phase %d scsi_get timeout: no acknowledge on Byte %d.\n", phase_cmd, c);
#endif            
            return(TIMEOUT);
        }
        swrite->init_cmd = 0x00;
    }
    if (c != count) {
#ifdef DEBUG        
        printf("phase %d scsi_get failure: only read %d Bytes, expected %d.\n", phase_cmd, c, count);
#endif        
        return(FAILURE);
    }
    return(SUCCESS);
}

/*--------------------------------------------------------------------------*/
@//E*O*F scsi_bus.c//
chmod u=rw,g=rw,o=rw scsi_bus.c
 
echo x - scsi_cmds.c
sed 's/^@//' > "scsi_cmds.c" <<'@//E*O*F scsi_cmds.c//'
/*	@(#)scsi_cmds.c	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/

#include "../include/scsi.h"

/*--------------------------------------------------------------------------*/
/* These routines exercise the SCSI transactions supported by the Maxtor    */
/*      RXT-800s worm optical drive, an ANSI SCSI-I device                  */
/*--------------------------------------------------------------------------*/

Exit_packet test_unit_ready(lun)
    Byte    lun;
{
    Byte    command[6], data;
    
    command[0] = TEST_UNIT_READY;
    command[1] = lun << 5;
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = RESERVED;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet rezero_unit(lun)
    Byte    lun;
{
    Byte    command[6], data;
    
    command[0] = REZERO_UNIT;
    command[1] = lun << 0x05;
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = RESERVED;
    command[5] = 0x00;
    
    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet request_sense(lun, data, length)
    Byte    lun;
    Byte    *data;
    Byte    length;
{
    Byte    command[6];
    
    command[0] = REQUEST_SENSE;
    command[1] = lun << 5;
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = length;
    command[5] = 0x00;

    return(traverse(command, 6, data, length, NS, DI));
}
/*--------------------------------------------------------------------------*/
Exit_packet format_unit(lun, fmt, cmp, dlf, interleave)
    Byte    lun;
    Byte    fmt;
    Byte    cmp;
    Byte    dlf;
    long    interleave;
{
    Byte    command[6], data;
    
    command[0] = FORMAT_UNIT;
    command[1] = (lun << 5) + (fmt << 4) + (cmp << 3) + dlf;
    command[2] = RESERVED;
    command[3] = (interleave & 0xff00) >> 4;
    command[4] = interleave & 0xff;
    command[5] = 0x00;
                     
    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet reassign_blocks(lun)
    Byte    lun;
{
    Byte    command[6], data;
    
    command[0] = REASSIGN_BLOCKS;
    command[1] = lun << 5;
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = RESERVED;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet read_blocks(lun, start, blocks, data, length)
    Byte    lun;
    long    start;
    Byte    blocks;
    Byte    *data;    
    short    length;
{
    Byte    command[6];
    
    command[0] = READ;
    command[1] = (lun << 5) + ((start & 0x1f0000) >> 16);
    command[2] = (start & 0xff00) >> 0x08;
    command[3] = (start & 0xff);
    command[4] = blocks;
    command[5] = 0x00;
                     
    return(traverse(command, 6, data, length, RS, DI));
}

/*--------------------------------------------------------------------------*/
Exit_packet write_blocks(lun, start, blocks, data, length)
    Byte    lun;
    long    start;
    Byte    blocks;
    Byte    *data;
    short   length;
{
    Byte    command[6];
    
    command[0] = WRITE;
    command[1] = (lun << 5) + ((start & 0x1f0000) >> 16);
    command[2] = (start & 0xff00) >> 0x08;
    command[3] = (start & 0xff);
    command[4] = blocks;
    command[5] = 0x00;
                     
    return(traverse(command, 6, data, length, RS, DO));
}
/*--------------------------------------------------------------------------*/
Exit_packet seek(lun, lbn)
    Byte    lun;
    long    lbn;
{
    Byte    command[6], data;
    
    command[0] = SEEK;
    command[1] = (lun << 5) + ((lbn & 0xff0000) >> 16);
    command[2] = (lbn & 0xff00) >> 8;
    command[3] = lbn & 0xff;
    command[4] = RESERVED;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet inquiry(lun, data, length)
    Byte    lun;
    Byte    *data;
    Byte    length;
{
    Byte    command[6];
    	    
    command[0] = INQUIRY;
    command[1] = lun << 5;
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = length;
    command[5] = 0x00;
                     
    return(traverse(command, 6, data, length, RS, DI));
}
/*--------------------------------------------------------------------------*/
Exit_packet mode_select(lun, pf, data, length)
    Byte    lun;
    Byte    pf;
    Byte    length;
{
    Byte    command[6];
    
    command[0] = MODE_SELECT;
    command[1] = (lun << 5) + ((pf & 0x01) << 4);
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = length;
    command[5] = 0x00;
                     
    return(traverse(command, 6, data, length, RS, DO));
}
/*--------------------------------------------------------------------------*/
Exit_packet reserve(lun, tp, tpid)
    Byte    lun;
    Byte    tp;
    Byte    tpid;
{
    Byte    command[6], data;
    
    command[0] = RESERVE;
    command[1] = (lun << 5) + ((tp & 0x01) << 0x04) + (tpid << 0x01);
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = RESERVED;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
/* I'm commented out because of name conflicts with mascon. Fix me someday.
Exit_packet release(lun, tp, tpid)
    Byte    lun, tp, tpid;
{
    Byte    command[6], data;
    
    command[0] = RELEASE;
    command[1] = (lun << 5) + ((tp & 0x01) << 0x04) + (tpid << 0x01);
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = RESERVED;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}     
*/
/*--------------------------------------------------------------------------*/
Exit_packet copy(lun, length)
    Byte    lun;
    long    length;
{
    Byte    command[6], data;
    
    command[0] = COPY;
    command[1] = lun << 5;
    command[2] = (length & 0xff0000) >> 16;
    command[3] = (length & 0xff00) >> 8;
    command[4] = length & 0xff;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet mode_sense(lun, pcf, pc, data, length)
    Byte    lun;
    Byte    pcf;
    Byte    pc;
    Byte    *data;
    Byte    length;
{
    Byte    command[6];
    
    command[0] = MODE_SENSE;
    command[1] = lun << 5;
    command[2] = ((pcf & 0x03) << 6) + pc;
    command[3] = RESERVED;
    command[4] = length;
    command[5] = 0x00;

    return(traverse(command, 6, data, length, RS, DI));
}
/*--------------------------------------------------------------------------*/
Exit_packet unit_motor(lun, staddr, imm)
    Byte    lun;
    Byte    staddr;
    Byte    imm;
{
    Byte    command[6], data;
    
    command[0] = UNIT_MOTOR;
    command[1] = (lun << 5) + (imm & 0x01);
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = staddr & 0x01;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet send_diagnostic(lun, st)
    Byte    lun;
    Byte    st;
{
    Byte    command[6], data;
    
    command[0] = SEND_DIAGNOSTICS;
    command[1] = (lun << 5) + ((st & 0x01) << 0x02);
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = RESERVED;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet medium_removal(lun, prevent)
    Byte    lun;
    Byte    prevent;
{
    Byte    command[6], data;
    
    command[0] = MEDIUM_REMOVAL;
    command[1] = (lun << 5);
    command[2] = RESERVED;
    command[3] = RESERVED;
    command[4] = prevent & 0x01;
    command[5] = 0x00;

    return(traverse(command, 6, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
Exit_packet read_capacity(lun, addr, pmi, data)
    Byte    lun;
    long    addr;
    Byte    pmi;
    Byte    *data;
{
    Byte    command[10];
    
    command[0] = READ_CAPACITY;
    command[1] = lun << 5;
    command[2] = ((addr & 0xff000000) >> 32);
    command[3] = ((addr & 0xff0000) >> 16);
    command[4] = ((addr & 0xff00) >> 8);
    command[5] = addr & 0xff;
    command[6] = RESERVED;
    command[7] = RESERVED;
    command[8] = pmi & 0x01;
    command[9] = 0x00;
                     
    return(traverse(command, 10, data, 8, RS, DI));
}
/*--------------------------------------------------------------------------*/
Exit_packet extended_read(lun, staddr, data, length)
    Byte    lun;
    long    staddr;
    Byte    *data;
    long    length;
    
{
    Byte    command[10];
    
    command[0] = EXTENDED_READ,
    command[1] = (lun << 5);
    command[2] = ((staddr & 0xff000000) >> 32);
    command[3] = ((staddr & 0xff0000) >> 16);
    command[4] = ((staddr & 0xff00) >> 8);
    command[5] = staddr & 0xff;
    command[6] = RESERVED;
    command[7] = ((length & 0xff00) >> 8);
    command[8] = length & 0xff;
    command[9] = 0x00;
                     
    return(traverse(command, 10, data, length, RS, DI));
}
/*--------------------------------------------------------------------------*/
Exit_packet extended_write(lun, staddr, data, length)
    Byte    lun;
    long    staddr;
    Byte    *data;
    long    length;
    
{
    Byte    command[10];
    
    command[0] = EXTENDED_WRITE;
    command[1] = lun << 5;
    command[2] = ((staddr & 0xff000000) >> 32);
    command[3] = ((staddr & 0xff0000) >> 16);
    command[4] = ((staddr & 0xff00) >> 8);
    command[5] = (staddr & 0xff);
    command[6] = RESERVED;
    command[7] = ((length & 0xff00) >> 0x08);
    command[8] = (length & 0xff);
    command[9] = 0x00;
                     
    return(traverse(command, 10, data, length, RS, DO));
}
/*--------------------------------------------------------------------------*/
Exit_packet extended_seek(lun, addr)
    Byte    lun;
    long    addr;
{
    Byte    command[10], data;
    
    command[0] = EXTENDED_SEEK;
    command[1] = (lun << 5);
    command[2] = ((addr & 0xff000000) >> 32);
    command[3] = ((addr & 0xff0000) >> 16);
    command[4] = ((addr & 0xff00) >> 8);
    command[5] = (addr & 0xff);
    command[6] = RESERVED;
    command[7] = RESERVED;
    command[8] = RESERVED;
    command[9] = 0x00;
                     
    return(traverse(command, 10, &data, 0, RS, ND));
}
/*--------------------------------------------------------------------------*/
@//E*O*F scsi_cmds.c//
chmod u=rw,g=rw,o=rw scsi_cmds.c
 
echo x - scsi_defs.h
sed 's/^@//' > "scsi_defs.h" <<'@//E*O*F scsi_defs.h//'
/*	@(#)scsi_defs.h	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/

/*----------------------------------------------------------------------------*/
/* IRONICS IV3273 - REGISTER BITMASK DEFINITIONS                              */
/*----------------------------------------------------------------------------*/
#define DATA_OUT_PHASE  0x00    /* Target Command register                    */
#define DATA_IN_PHASE   0x01
#define COMMAND_PHASE   0x02
#define STATUS_PHASE    0x03
#define MSG_OUT_PHASE   0x06
#define MSG_IN_PHASE    0x07
#define REQ             0x20    /* Current SCSI Bus Status register           */
#define BSY             0x40
#define SEL             0x02
#define PHASE_MATCH     0x08    /* Bus and Status register                    */
#define ACK             0x01
#define IRQ_ACTIVE      0x10
#define ASSERT_DB       0x01    /* Initiator Command register                 */
#define ASSERT_SEL      0x04
#define ASSERT_BSY      0x08
#define ASSERT_ACK      0x10
#define ASSERT_RST      0x80
#define TARGET_MODE     0x40    /* Mode register                              */

/*----------------------------------------------------------------------------*/
/* SYSTEM CONTROLLER BOARD ADDRESSES (AFTER PHYS)                             */
/*----------------------------------------------------------------------------*/
#ifdef UNIX
#define IV3273      0xfffa01        /* Slave 3273  (Unix, virtual address)    */
#define IV3273_U    0xfffc01        /* Master 3273 (Unix, virtual address)    */
#endif
#ifdef PSOS
#define IV3273      0xfffffa01      /* Master 3273 (pSOS, physical address)   */
#endif

/*----------------------------------------------------------------------------*/
/* EXIT PACKET SCSI REPORT                                                    */
/*----------------------------------------------------------------------------*/
#define COMMAND_COMPLETE    0   /* Operation succeeded                        */
#define BUS_FREE_FAILURE    1   /* Timeout on SEL or BSY                      */
#define SELECT_FAILURE      2   /* Couldn't SEL                               */
#define COMMAND_FAILURE     3   /* Command phase failed                       */
#define DATA_FAILURE        4   /* REQ/ACK timeout or data count wrong        */
#define STATUS_FAILURE      5   /* Couldn't get status                        */
#define MESSAGE_FAILURE     6   /* Couldn't get message                       */
/*----------------------------------------------------------------------------*/
/* LEGAL STATES                                                               */
/*----------------------------------------------------------------------------*/
#define START       0   /* States that are traversed in scsi_aux.c.  These    */
#define BUSFREE     1   /* states dictate which SCSI phase to enter, as well  */
#define SELECT      2   /* as error handling ability.                         */
#define COMMAND     3
#define DATAIN      4
#define DATAOUT     5
#define STATUS      6
#define MESSAGE     7
#define ERROR       8
#define COMPLETED   16
#define EXIT        16
#define DEATH       17

/*----------------------------------------------------------------------------*/
/* STATE TABLE DEFINITIONS                                                    */
/*----------------------------------------------------------------------------*/
#define RS      1   /* Request sense true                                     */
#define NS      0   /* Request sense false                                    */
#define ND      0   /* No data                                                */
#define DI      1   /* Data in                                                */
#define DO      2   /* Data out                                               */

/*----------------------------------------------------------------------------*/
/* EXIT PACKET TYPE                                                           */
/*----------------------------------------------------------------------------*/
#define CORRECTED   1       /* There was an error that was corrected          */
#define OPERATOR    2       /* An error was passed to the operator            */
#define NEWMEDIA    3       /* Optical disk in drive has changed              */
#define RETRY       4       /* Operation may succeed if retried               */
#define SCSIFAIL    5       /* Something was wrong with the SCSI protocol     */
#define FAIL        6       /* Current operation did not succeed              */
#define FATAL       7       /* Major failure; all worm/scsi code affected     */

/*----------------------------------------------------------------------------*/
/* EXIT PACKET STATUS                                                         */
/*----------------------------------------------------------------------------*/
#define GOOD                0x00    /* Operation succeeded                    */
#define CHECK_CONDITION     0x02    /* Operation ignored; do reqsen and retry */
#define BUSY                0x08    /* Drive is busy.. retry later            */
#define INTERMEDIATE_GOOD   0x10    /* Success in one part of multipart op    */
#define RESERVE_CONFLICT    0x18    /* Shouldn't happen (no arbitration)      */

/*----------------------------------------------------------------------------*/
/* EXIT PACKET SENSE                                                          */
/*----------------------------------------------------------------------------*/
#define NO_SENSE        0x0     /* No sense information                       */
#define RECOVERED_ERROR 0x1     /* Internal correction of error               */
#define NOT_READY       0x2     /* No disk in drive, or drive not connected   */
#define MEDIUM_ERROR    0x3     /* Physical problem with disk                 */
#define HARDWARE_ERROR  0x4     /* See extended sense bytes for more info     */
#define ILLEGAL_REQUEST 0x5     /* Command packet contained illegal info      */
#define UNIT_ATTENTION  0x6     /* Power on, reset, or drive info changed     */
#define DATA_PROTECT    0x7     /* Tried to write to protected block          */
#define BLANK_CHECK     0x8     /* Read an empty block, or wrote a written    */
#define ABORTED_COMMAND 0xB     /* Drive aborted. Retry operation             */

/*----------------------------------------------------------------------------*/
/* SCSI TYPES                                                                 */
/*----------------------------------------------------------------------------*/
#define TEST_UNIT_READY     0x00    /* Group 0 SCSI commands                  */
#define REZERO_UNIT         0x01
#define REQUEST_SENSE       0x03
#define FORMAT_UNIT         0x04
#define REASSIGN_BLOCKS     0x07
#define READ                0x08
#define WRITE               0x0A
#define SEEK                0x0B
#define INQUIRY             0x12
#define MODE_SELECT         0x15
#define RESERVE             0x16
#define RELEASE             0x17
#define COPY                0x18
#define MODE_SENSE          0x1A
#define UNIT_MOTOR          0x1B
#define SEND_DIAGNOSTICS    0x1D
#define MEDIUM_REMOVAL      0x1E
#define READ_CAPACITY       0x25    /* Group 1 SCSI Commands                  */
#define EXTENDED_READ       READ + 0x20
#define EXTENDED_WRITE      WRITE + 0x20
#define EXTENDED_SEEK       SEEK + 0x20
#define VERIFY              0x2F
#define READ_DEFECT_DATA    0x37
#define COMPARE             0x39
#define COPY_AND_VERIFY     0x3A
#define WRITE_DATA_BUFFER   0x3B
#define READ_DATA_BUFFER    0x3C

/*----------------------------------------------------------------------------*/
/* MISC                                                                       */
/*----------------------------------------------------------------------------*/
#define TIMEOUT         2           /* Error number for timeout               */
#define LIMIT           100000      /* Timeout maximum count                  */
#define RESERVED        0           /* Used to fill SCSI commands             */
#define LUN 0
#define LOCK 1
#define UNLOCK 0
@//E*O*F scsi_defs.h//
chmod u=rw,g=rw,o=rw scsi_defs.h
 
echo x - scsi_psos.c
sed 's/^@//' > "scsi_psos.c" <<'@//E*O*F scsi_psos.c//'
/*	@(#)scsi_psos.c	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/
#include "../include/scsi.h"

/*--------------------------------------------------------------------------*/
/* operator - prompt the operator for error correction procedure            */
/*--------------------------------------------------------------------------*/

Byte operator(ep)           /* I should be replaced with something more     */
    Exit_packet ep;         /* apropos to an autonomous vehicle with only   */
{                           /* occasional operator interaction. Oh well.    */
    char c;
    if (ep.sense == NOT_READY)
        printf("Optical drive not ready.  (R)etry or (F)ail? ");
    else if (ep.sense == DATA_PROTECT)
        printf("Protected data.  (R)etry or (F)ail? ");
    else  {
        printf("Optical drive error:\n");           /* note that %02X is    */
        printf("  Status:   %02X\n", ep.status);    /* different here       */
        printf("  Message:  %02X\n", ep.message);   /* than unix            */
        printf("  Sense:    %02X\n", ep.sense);
        printf("  XSense:   %02X\n", ep.xsense);
        printf("\n(R)etry or (F)ail? ");
    }
    c = getchar();
    
    if ((c == 'f') || (c == 'F'))
        return DEATH;
    else
        return START;
}        
/*--------------------------------------------------------------------------*/
@//E*O*F scsi_psos.c//
chmod u=rw,g=rw,o=rw scsi_psos.c
 
echo x - scsi_types.h
sed 's/^@//' > "scsi_types.h" <<'@//E*O*F scsi_types.h//'
/*	@(#)scsi_types.h	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/
typedef struct  {
    Byte    type;
    Byte    scsi;
    Byte    status;
    Byte    message;
    Byte    sense;
    Byte    xsense;
} Exit_packet;
@//E*O*F scsi_types.h//
chmod u=rw,g=rw,o=rw scsi_types.h
 
echo x - scsi_vars.h
sed 's/^@//' > "scsi_vars.h" <<'@//E*O*F scsi_vars.h//'
/*	@(#)scsi_vars.h	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    1/90
  Modification History:
******************************************************************/
/* s=success, f=failure w/0 retries, F=failure w/1, Q=failure w/2   */
/* n=no data, i=data in, o=data out, e=bad error state              */

char states[9][16] = {
/*              sn  si  so  se  fn  fi  fo  fe  Fn  Fi  Fo  Fe  Qn  Qi  Qo  Qe*/
/* 0start   */ { 1,  1,  1, 17,  1,  1,  1, 17,  1,  1,  1, 17,  1,  1,  1, 17},
/* 1busfree */ { 2,  2,  2, 17,  1,  1,  1, 17,  1,  1,  1, 17,  8,  8,  8, 17},
/* 2select  */ { 3,  3,  3, 17,  2,  2,  2, 17,  2,  2,  2, 17,  8,  8,  8, 17},
/* 3command */ { 6,  4,  5, 17,  3,  3,  3, 17,  3,  3,  3, 17,  8,  8,  8, 17},
/* 4datain  */ {17,  6, 17, 17, 17,  4, 17, 17, 17,  4, 17, 17,  8,  8,  8, 17},
/* 5dataout */ {17, 17,  6, 17, 17, 17,  5, 17, 17, 17,  5, 17,  8,  8,  8, 17},
/* 6status  */ { 7,  7,  7, 17,  6,  6,  6, 17,  6,  6,  6, 17,  8,  8,  8, 17},
/* 7message */ {16, 16, 16, 17,  7,  7,  7, 17,  7,  7,  7, 17,  8,  8,  8, 17},
/* 8error   */ { 0,  0,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}
};
@//E*O*F scsi_vars.h//
chmod u=rw,g=rw,o=rw scsi_vars.h
 
echo x - scsimon.c
sed 's/^@//' > "scsimon.c" <<'@//E*O*F scsimon.c//'
/*	@(#)scsimon.c	1.0	
****************************************************************** 
*   Copyright (c) 1990, Marine Systems Engineering Laboratory    * 
*     Use, modification, or distribution of this software is     * 
*         permitted only with express permission of MSEL.        * 
****************************************************************** 
  Author(s): Roger Gonzalez    
  Modification History:
******************************************************************/

/* This program monitors the SCSI bus, and displays interesting information */
/* by highlighting bits that are turned on.  The NCR5380 documentation is a */
/* must-read.  Note that a great deal of space is taken up doing termcap    */
/* and argument decoding stuff.  The code is ugly, but it runs purty :-)    */
/* The command line termcap options were sucked in from a different program */
/* and are thus bordering on overkill.  Believe me, if your terminal can    */
/* highlight, this program can do it.                                       */

#include <stdio.h>
#include <string.h>
#include <termcap.h>

#include "../include/scsi.h"
#include "/usr/usr1/include/iv3273.h"

#define NORMAL  0
#define HILITE 1

char    termtype[10];
char    *temp;
char    *hilite[2];
char    bp[1024];
char    capbuf[512];
char    *area;
byte    drawstate;


setdrawmode(state)
    byte    state;
{
    if (state == drawstate)
        return;
    else {
        printf("%s", hilite[state]);
        drawstate = state;
    }
}

prstr(string, chkbyte, bit)
    char    *string;
    byte    chkbyte;
    byte    bit;
{
    byte c, res;
    for (c = 0; c <= 7; c++) {
        res = 1 << (7 - c);
        if ((chkbyte & res) == res) {
            setdrawmode(HILITE);
            putchar(string[c]);
        }
        else {
            setdrawmode(NORMAL);
            putchar(string[c]);
        }
    }
}


main(argc, argv)
    int argc;
    char *argv[];
{
    char inputfile[80];
    char outputfile[80];
    ncr5380_rd *sread;
    byte init, targ, s1, s2, mode, indata, outdata;
    byte oldinit, oldtarg, olds1, olds2, oldmode, oldindata, oldoutdata;
    oldinit = oldtarg = olds1 = olds2 = oldmode = oldindata = oldoutdata = 0x00;

    if (parse_args("bdfhrsuvx", argc, argv, inputfile, outputfile) != 0) {
        fprintf(stderr, "usage: scsimon [-bdfhrsuv]\n");
        exit(1);
    }
    if (!on('s') && !on('b') && !on('d') && !on('f') && !on('u'))
        turn_on("s");
    if (on('x')) 
        sread = (ncr5380_rd *) IV3273_U;
    else
        sread = (ncr5380_rd *) IV3273;

    area = capbuf;
    if (*strcpy(termtype, getenv("TERM")) == NULL) {
        fprintf(stderr, "%s: TERM not set.\n", argv[0]);
        exit(1);
    }
    else {
        if (tgetent(bp, termtype) != 1) {
            fprintf(stderr, "%s: terminal '%s' not found.\n", argv[0], termtype);
            exit(1);
        }
        if (on('f')) {

            if (((hilite[HILITE] = tgetstr("mb", &area)) == NULL) ||
                ((hilite[NORMAL] = tgetstr("me", &area)) == NULL)) {
                fprintf(stderr, "%s: your terminal can't flash.\n", argv[0]);
                exit(1);
            }
        }        
        if (on('b')) {
            if (((hilite[HILITE] = tgetstr("md", &area)) == NULL) ||
                ((hilite[NORMAL] = tgetstr("me", &area)) == NULL)) {
                fprintf(stderr, "%s: your terminal can't display bold.\n", argv[0]);
                exit(1);
            }
        }
        if (on('d')) {
            if (((hilite[HILITE] = tgetstr("mh", &area)) == NULL) ||
                ((hilite[NORMAL] = tgetstr("me", &area)) == NULL)) {
                fprintf(stderr, "%s: your terminal can't display dim.\n", argv[0]);
                exit(1);
            }
        }
        if (on('u')) {
            if (((hilite[HILITE] = tgetstr("us", &area)) == NULL) ||
                ((hilite[NORMAL] = tgetstr("ue", &area)) == NULL)) {
                fprintf(stderr, "%s: your terminal can't underline.\n", argv[0]);
                exit(1);
            }
            if (tgetnum("ug") != -1) {
                fprintf(stderr, "%s: your terminal leaves magic underline cookies!\n", argv[0]);
                exit(1);
            }
        }
        if (on('s')) {
            if (((hilite[HILITE] = tgetstr("so", &area)) == NULL) ||
                ((hilite[NORMAL] = tgetstr("se", &area)) == NULL)) {
                fprintf(stderr, "%s: your terminal can't standout.\n", argv[0]);
                exit(1);
            }
            if (tgetnum("sg") != -1) {
                fprintf(stderr, "%s: your terminal leaves magic standout cookies!\n", argv[0]);
                exit(1);
            }
        }
        if (on('r')) {
            hilite[2] = hilite[HILITE];
            hilite[HILITE] = hilite[NORMAL];
            hilite[NORMAL] = hilite[2];
        }

    }
    if (on('v')) {
       printf("scsimon v1.0 - R. Gonzalez 10/89\n");
    }
    
    drawstate = HILITE;
    setdrawmode(NORMAL);
    
    if (phys(0, 0xfc0000, 0x40000, 0xfffc0000) != 0) {
        fprintf(stderr, "%s: must be root to access physical memory.\n", argv[0]);
        exit(1);
    }
    while(1) {
        oldinit = init;
        oldtarg = targ;
        olds1 = s1;
        olds2 = s2;
        oldmode = mode;
        oldindata = indata;
        oldoutdata = outdata;

        init = sread->init_cmd;
        targ = sread->target_cmd;
        s1 = sread->status_1;
        s2 = sread->status_2;
        mode = sread->mode;
        if (((oldinit^init)|(oldtarg^targ)|(olds1^s1)|(olds2^s2)|
            (oldmode^mode)) != 0x00) {
        if ((mode & 0x40) == 0x00) {
            setdrawmode(NORMAL);
            printf("M(I) IC(");
        }
         else {
            printf("M(");
            setdrawmode(HILITE);
            printf("T");
            setdrawmode(NORMAL);
            printf(") IC(");
        }
        prstr("RxxABSxD", init);
        setdrawmode(NORMAL);
        printf(") TC(");
        prstr("xxxxRMCI", targ);
        setdrawmode(NORMAL);
        printf(") S1(");
        prstr("RBRMCISD", s1);
        setdrawmode(NORMAL);
        printf(") S2(");
        prstr("xxPIMBxA", s2);
        setdrawmode(NORMAL);
/*        printf(") ID(%02X) OD(%02X) ", indata, outdata);*/
          printf(") ");
        switch((s1 >> 2) & 0x07) {
            case 0: {printf("dataout\n"); break;}
            case 1: {printf("datain \n"); break;}
            case 2: {printf("command\n"); break;}
            case 3: {printf("status \n"); break;}
            case 6: {printf("messout\n"); break;}
            case 7: {printf("messin \n"); break;}
            default:{printf(".......\n"); break;}
        }
        }
    }

}            
@//E*O*F scsimon.c//
chmod u=rw,g=rw,o=rw scsimon.c
 
exit 0
-- 
UUCP:   ..!uunet!unhd!rg      | USPS: Marine Systems Engineering Laboratory
BITNET: r_gonzalez at unhh    |       University of New Hampshire
PHONE:  (603) 862-4600        |       Marine Programs Building
FAX:    (603) 862-4399        |       Durham, NH  03824-3525