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