[comp.sys.nsc.32k] Locating SCSI devices

news@daver.bungi.com (10/12/90)

I would like some feedback regarding how to best locate and identify SCSI
units attached to the bus.  To this end I have attached a code fragment
which seems to work with the SCSI devices that I have available.

I am exercising the code under DOS and am talking directly to the SCSI
host adapter.  And the attached code produces the following output with my
devices attached:

        device    type              vendor   product
        --------- ----------------- -------- ----------------
        32  0:4:0 sequential access ADAPTEC
        48  0:6:0 direct access     MAXTOR   XT-4380S

        Total number of units found   : 2
        Total number of devices found : 2

In addition to comments on the logic of flushing out SCSI devices, I
would really appreciate receiving / seeing the response to the
INQUIRY command from other devices (eg. OMTI floppy controller, etc).

best regards,
johnc


/*===================================================================
    scan.c          Scan for all SCSI devices.

    The INQUIRY command is used to identify SCSI devices.

    The data format of the INQUIRY command has been expanded in SCSI-2
    to include additional information.  Unfornately the SCSI-1 data format
    beyound byte 5 is generally vendor unique, however, in general the 
    vendor name seems to be located at or beyound data byte 0x08.

    SCSI-1 data format:

 0   |                        Peripheral Device Type                         |
-----|-----------------------------------------------------------------------|
 1   |  RMB   |                  Device-Type Qualifier                       |
-----|-----------------------------------------------------------------------|
 2   |   ISO Version   |       ECMA Version       |  ANSI-Approved Version   |
-----|-----------------------------------------------------------------------|
 3   |                       Reserved                                        |
-----|-----------------------------------------------------------------------|
[ stuff deleted ]


    SCSI-2 data format:

 0   | Peripheral Qualifier     |           Peripheral Device Type           |
-----|-----------------------------------------------------------------------|
 1   |  RMB   |                  Device-Type Modifier                        |
-----|-----------------------------------------------------------------------|
 2   |   ISO Version   |       ECMA Version       |  ANSI-Approved Version   |
-----|-----------------------------------------------------------------------|
 3   |  AENC  | TrmIOP |     Reserved    |         Response Data Format      |
-----|-----------------------------------------------------------------------|
[ stuff deleted ]


    Beginning with SCSI-2, a response data format value of zero indicates
    the INQUIRY data format is as specified in SCSI-1.  A response data
    format value of one indicates compatibility with some products that
    were designed prior to the development of SCSI-2 (i.e., CCS).
    A response data format value of two indicates that the data shall be
    in the format specified in SCSI-2.  Response data format values greater
    than two are reserved.

    According to SCSI-2, if the target is not capable of supporting a
    device on a logical unit, data byte 0 should be set to 7Fh
    (peripheral qualifier set to 011b and peripheral device type set to 1Fh).
    However, on all SCSI-1 direct access devices that I have tested
    return 00h for all LUNs.  Therefore, we will make the assumption that
    unless response data format is 2, direct access devices only support
    LUN 0.

===================================================================*/

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <dos.h>
#include "scsi.h"

struct sccb  ccb;

char  buffer[ 512];

struct unit
{
    int     adapter_no;             /* which host adapter   */
    int     device_no;              /* scsi_addr << 3 | lun */
    int     type;                   /* direct, seq, etc     */
    char   *vendor_nm;
    char   *product_nm;
};

int  nodevices;
int  devices[ 8];

int  nounits;
struct unit  units[ 16];


main()
{
    int i, j, ierr;

    install_timer();
    install_scsi_isr();

    scsi_resetbus();

    /* intialize the device array */
    for (i = 0; i < 8; i++)
        devices[ i] = -1;

    /* initialize the unit array */
    for (i = 0; i < 16; i++)
        units[ i].device_no = -1;

    /* locate the devices */
    for (i = 0; i < 7; i++)
    {
        ierr = inquiry( i, 0, buffer, 36 );

        if (ierr == CNOCONNECT)
            continue;

        devices[ nodevices++] = i;

    }

    /* for each located device, locate its logical units */
    for (i = 0; i < nodevices; i++)
    {
        for (j = 0; j < 8; j++)
        {
            ierr = inquiry( devices[i], j, buffer, 36 );

            if (ierr == COK)
            {
                record_unit( 0, devices[i], j, buffer, ccb.actuallen );
            }
        }
    }

    printf("\n");
    show_scan();
    printf("\n");
    printf("Total number of units found   : %d\n", nounits);
    printf("Total number of devices found : %d\n", nodevices);

    remove_timer();
    remove_scsi_isr();
}


char *nm_devtypes[ ] =
{
    "direct access",
    "sequential access",
    "printer",
    "processor",
    "WORM",
    "CDROM",
    "scanner",
    "optical",
    "media changer",
    "communications"
};


show_scan()
{
    int  i;
    struct unit *dv;

    printf("device    type              vendor   product\n");
    printf("--------- ----------------- -------- ----------------\n");

    for (i = 0; i < nounits; i++)
    {
        dv = &units[i];

        printf("%02d  %d:%d:%d ", dv->device_no, dv->adapter_no,
                dv->device_no >> 3, dv->device_no & 7);

        printf("%-17s ",  nm_devtypes[ dv->type]);

        if (dv->vendor_nm)
            printf("%-8s ", dv->vendor_nm);

        if (dv->product_nm)
            printf("%-16s", dv->product_nm);

        printf("\n");
    }
}


char *get_vendor_nm( fmt, data, len )
int  fmt;              /* SCSI-1 = 0, CCS = 1, SCSI-2 = 2 */
char *data;
int   len;
{
    char  ch;
    char *s;

    if (fmt > 2 || len < 8) return( NULL );       /* reserved value */

    if (fmt == 0)                      /* SCSI-1, format vendor unique */
    {
        s = &data[ len];

        while( !isalpha( *data) )
            data++;

        while( !isalpha( *s ))
            s--;
        *(++s) = 0;

        return( strdup( data ) );
    }
                                        /* format standarized */

    ch = data[ 8];
    data[ 8] = 0;

    for (s = &data[7]; *s == ' '; s--)
        *s = 0;

    data[ 8] = ch;
    return( strdup( data ) );
}


char *get_product_nm( fmt, data, len )
int  fmt;
char *data;
int  len;
{
    char  *s, ch;

    if (fmt == 0 || fmt > 2)   return( NULL );

    ch = data[ 16];
    data[ 16] = 0;

    for (s = &data[15]; *s == ' '; s--)
        *s = 0;

    data[ 16] = ch;
    return( strdup( data ) );
}


record_unit( adapter, addr, lun, data, len )
int  adapter;               /* which host adapter    */
int  addr;                  /* SCSI address          */
int  lun;                   /* logical unit number   */
char *data;                 /* inquiry response data */
int  len;                   /* response length       */
{
    struct unit  *dv;
    int  format;

    /* A sufficient but not necessary test for non-existent LUN */
    if (data[0] == 0x7F)    return;

    /* To stop certain direct access devices from reporting multiple
     * LUNs. Such devices include Maxtor XT-4380S, CRC 94161-9 and
     *  Miniscribe  9380S.
     */

    if (data[0] == 0 && data[3] = 0x01 && lun > 0) return;

    dv     = &units[ nounits++];
    format = data[3] & 0x0F;

    dv->adapter_no = adapter;
    dv->device_no  = addr << 3 | (lun & 0xFF);
    dv->type       = data[ 0] & 0x1F;
    dv->vendor_nm  = get_vendor_nm( format, &data[ 0x08], len - 0x08 );
    dv->product_nm = get_product_nm(format, &data[ 0x10], len - 0x10 );
}

-- 

culberts@hplb.hpl.hp.com (Bruce Culbertson) (10/12/90)

Hi John,

I appreciate your efforts to try to improve our SCSI driver.  You
may want to ignore the OMTI controller I am using, though.  Guess
what -- it does not do INQUIRY!  Kind of defeats the whole scheme,
doesn't it?  The sooner I buy a new disk, the better.  I am thinking
of switching from being a home renter to being a home owner, so all
things financial are on hold at the moment.

Regards,
Bruce