home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 13
/
mediashare_13.zip
/
mediashare_13
/
ZIPPED
/
PROGRAM
/
DDJ9403A.ZIP
/
ASPI.ASC
next >
Wrap
Text File
|
1994-01-30
|
13KB
|
290 lines
_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);
}