Category : Files from Magazines
Archive   : DDJ9403A.ZIP
Filename : ASPI.ASC

 
Output of file : ASPI.ASC contained in archive : DDJ9403A.ZIP
_THE ADVANCED SCSI PROGRAMMING INTERFACE_
by Brian Sawert


Listing One

// ------ Initializing the ASPI driver. -------
#include "aspi.h" // ASPI definitions and constants
#include "scsi.h" // SCSI definitions and constants
// -------------------- defines and macros --------------------
#define IOCTL_READ 2 // IOCTL read function
#define ASPI_NAME "SCSIMGR$" // SCSI manager driver name
// -------------------- global variables --------------------
void (far *ASPIRoutine) (aspi_req_t far *); // far address of ASPI routine
BYTE f_installed; // flag for ASPI existence

aspi_req_t *srb; // SCSI Request Block pointers
// ----------------------------------------------------------------------
// Routine to check for and initialize ASPI driver.
// Usage: int aspi_open(void);
// Returns nonzero on success, 0 if ASPI driver not found or init failed.
int aspi_open(void)
{
int dh; // ASPI driver handle
if (!f_installed)
{ // not initialized
if ((dh = open(ASPI_NAME, O_RDONLY | O_BINARY)) != -1)
{ // open device driver
if (ioctl(dh, IOCTL_READ, (void *) &ASPIRoutine,
sizeof(ASPIRoutine)) == sizeof(ASPIRoutine))
{ // got ASPI entry point
srb = (aspi_req_t *) malloc(sizeof(aspi_req_t));
if (srb != NULL)
{ // allocated SRB buffers
f_installed++; // set installed flag
}
}
close(dh); // close device driver
}
}
return(f_installed);
}
// ----------------------------------------------------------------------
// Routine to close and clean up.
// Usage: void aspi_close(void);
// Called with nothing. Returns nothing.
void aspi_close(void)
{
if (f_installed)
{ // already initialized
free(srb); // deallocate buffers
f_installed = 0; // clear installed flag
}
return;
}


Listing Two

// ------ Calling the ASPI entry point and ASPI I/O. -------
#include "aspi.h" // ASPI definitions and constants
#include "scsi.h" // SCSI definitions and constants

// -------------------- defines and macros --------------------
#define BUSY_WAIT 0x1000 // repeat count for busy check
#define MIN_GRP_1 0x20 // minimum SCSI group 1 command
// -------------------- global variables --------------------
void (far *ASPIRoutine) (aspi_req_t far *); // far address of ASPI routine
BYTE f_installed; // flag for ASPI existence
BYTE aspi_stat; // ASPI status byte
BYTE host_stat; // host status byte
BYTE targ_stat; // target status byte
BYTE host_num; // host adapter number (0 default)

aspi_req_t *srb; // SCSI Request Block pointers
sense_block_t *srb_sense; // pointer to SRB sense data
// ----------------------------------------------------------------------
// Routine to call ASPI driver.
// Usage: int aspi_func(aspi_req_t *ar);
// Called with pointer to SCSI Request Block (SRB).
// Returns nonzero on success, 0 on error.
int aspi_func(aspi_req_t *ar)
{
int retval = 0;

if (f_installed)
{ // ASPI manager initialized
ASPIRoutine((aspi_req_t far *) ar); // call ASPI manager
retval++;
}
return(retval);
}
// ----------------------------------------------------------------------
// Execute SCSI I/O through ASPI interface.
// Usage: int aspi_io(BYTE *cdb, BYTE far *dbuff, WORD dbytes,
// BYTE flags, BYTE id, WORD *stat);
// Called with pointer to data buffer, data buffer size, pointer to CDB,
// request flags, and target ID. Returns ASPI status on success, -1 on error.
// Fills stat variable with host status in high byte, target in low byte.
int aspi_io(BYTE *cdb, BYTE far *dbuff, WORD dbytes, BYTE flags,
BYTE id, WORD *stat)
{
int cdbsize;
int timeout; // timeout counter for polling
int retval = -1;

memset(srb, 0, sizeof(aspi_req_t)); // clear SRB
srb->command = SCSI_IO; // set command byte
srb->hostnum = host_num; // set host adapter number
srb->su.s2.targid = id; // set target SCSI ID
srb->reqflags = flags; // set request flags
srb->su.s2.databufptr = dbuff; // set pointer to data buffer
srb->su.s2.datalength = dbytes; // set data buffer length
srb->su.s2.senselength = sizeof(sense_block_t);
// set sense data buffer length
cdbsize = sizeof(group_0_t); // assume 6 byte CDB
if (*((BYTE *) cdb) >= MIN_GRP_1 && *((BYTE *) cdb) < MIN_GRP_6)
{ // CDB size is 10 bytes
cdbsize = sizeof(group_1_t);
}
srb->su.s2.cdblength = cdbsize; // set CDB length
srb->su.s2.senselength = MAX_SENSE; // sense sense data length
memcpy(srb->su.s2.scsicdb, cdb, cdbsize); // copy CDB to SRB
srb_sense = srb->su.s2.scsicdb + cdbsize; // point to sense data buffer
if (aspi_func(srb))
{ // ASPI call succeeded
timeout = BUSY_WAIT; // set timeout counter

while (srb->status == REQ_INPROG && timeout > 0)
{ // request in progress - keep polling
timeout--; // decrement timeout counter
}
retval = aspi_stat = srb->status; // save ASPI status
if (aspi_stat != REQ_INPROG)
{ // request completed
host_stat = srb->su.s2.hoststat; // save host status
targ_stat = srb->su.s2.targstat; // save target status
*stat = ((WORD) host_stat << 8) | targ_stat;
// return combined SCSI status
}
}
return(retval);
}


Listing Three

// ------ Initializing and using ASPI in a DLL. ------
#include "aspi.h" // ASPI definitions and constants
#include "scsi.h" // SCSI definitions and constants
// -------------------- defines and macros -------------------
#define IOCTL_READ 2 // IOCTL read function
#define ASPI_NAME "SCSIMGR$" // SCSI manager driver name
#define DPMI_INT 0x31 // DPMI interrupt number
#define REAL_CALL 0x301 // real mode call function

typedef struct RealCall
{ // struct for real mode call
DWORD edi, esi, ebp, reserved, ebx, edx, ecx, eax;
WORD flags, es, ds, fs, gs, ip, cs, sp, ss;
} RealCall_t ;
// -------------------- global variables -------------------
void (far *ASPIRoutine) (aspi_req_t far *); // far address of ASPI routine
BYTE f_installed; // flag for ASPI existence
aspi_req_t _FAR *srb; // SCSI Request Block pointers
DWORD dwPtr; // return from GlobalDOSAlloc
// -------------------- local functions -------------------
void far *MaptoReal(void far *pptr); // map to real mode address
int AspiCall(void far *aspiproc, aspi_req_t far *ar); // DPMI function
// ----------------------------------------------------------------------
// Routine to check for and initialize ASPI driver.
// Usage: int FUNC aspi_open(void);
// Returns nonzero on success, 0 if ASPI driver not found or init failed.
int FUNC aspi_open(void)
{
int dh; // ASPI driver handle
UINT wSRB; // selector for buffer memory
if (!f_installed)
{ // not initialized
if ((dh = open(ASPI_NAME, O_RDONLY | O_BINARY)) != -1)
{ // open device driver
if (ioctl(dh, IOCTL_READ, (void far *) &ASPIRoutine,
sizeof(ASPIRoutine)) == sizeof(ASPIRoutine))
{ // got ASPI entry point
dwPtr = GlobalDosAlloc(sizeof(aspi_req_t));

if (dwPtr[0] != NULL)
{ // allocated SRB buffer
wSRB = LOWORD(dwPtr[0]); // extract selector
GlobalPageLock(wSRB); // lock memory
srb = (aspi_req_t _FAR *) MAKELP(wSRB, 0);
f_installed++; // set installed flag
}
}
close(dh); // close device driver
}
}
return(f_installed);
}
// ----------------------------------------------------------------------
// Routine to close and clean up.
// Usage: void FUNC aspi_close(void);
// Called with nothing. Returns nothing.
void FUNC aspi_close(void)
{
UINT wSRB; // selector for buffer memory
if (f_installed)
{ // already initialized
wSRB = FP_SEG(srb); // extract selector from pointer
GlobalPageUnlock(wSRB); // unlock buffer
GlobalDosFree(wSRB); // deallocate buffer
dwPtr = NULL;
srb = NULL;
f_installed = 0; // clear installed flag
}
return;
}
// ----------------------------------------------------------------------
// Routine to call ASPI driver.
// Usage: int aspi_func(aspi_req_t _FAR *ar);
// Called with pointer to SCSI Request Block (SRB).
// Returns nonzero on success, 0 on error.
int aspi_func(aspi_req_t _FAR *ar)
{
aspi_req_t far *arptr; // real mode pointer
int retval = 0;
if (f_installed)
{ // ASPI manager initialized
if ((arptr = (aspi_req_t far *) MaptoReal(ar)) != NULL)
{ // got a valid real mode pointer
retval = AspiCall(ASPIRoutine, arptr); // call ASPI through DPMI
}
}
return(retval);
}
// ----------------------------------------------------------------------
// Routine to map protected mode pointer to real mode.
// Usage: void far *MaptoReal(void far *pptr);
// Returns real mode pointer on success, NULL on error.
void far *MaptoReal(void far *pptr)
{
WORD sel; // protected mode selector
void far *ptr = NULL; // real mode pointer
sel = FP_SEG(pptr); // get selector value
if (sel == LOWORD(dwPtr))
{ // found matching selector
ptr = MAKELP(HIWORD(dwPtr), FP_OFF(pptr));
// build real mode pointer
}
return(ptr);
}
// ----------------------------------------------------------------------
// Call ASPI manager through DPMI server.
// Usage: int AspiCall(void far *aspiproc, aspi_req_t far *ar);
// Returns 1 on success, 0 otherwise.
int AspiCall(void far *aspiproc, aspi_req_t far *ar)
{
RealCall_t rcs; // real mode call struct
int retval = 0;
int npush;
void far *sptr;
memset(&rcs, 0, sizeof(RealCall_t)); // clear call structure
rcs.cs = HIWORD(aspiproc); // point to real mode proc
rcs.ip = LOWORD(aspiproc);
npush = sizeof(aspi_req_t far *) / sizeof(WORD); // words to pass on stack
sptr = (void far *) &rcs; // far pointer to call structure
asm {
push di // save registers
push es
sub bx, bx // don't reset A20 line
mov cx, npush; // number of words to copy to stack
les di, sptr // point ES:DI to call structure
mov ax, REAL_CALL // load function number
push WORD PTR [ar + 2] // push SRB address
push WORD PTR [ar]
int DPMI_INT // call DPMI server
pop ax // restore stack count
pop ax
pop es // restore registers
pop di
jc asm_exit // DPMI error
mov retval, 1 // return 1 for success
}
asm_exit:
return(retval);
}





  3 Responses to “Category : Files from Magazines
Archive   : DDJ9403A.ZIP
Filename : ASPI.ASC

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/