Via: uk.ac.ulcc.vmsfe; Thu, 2 Feb 1995 11:18:32 +0000 Date: Thu, 2 Feb 95 11:18 GMT From: "Kevin Ashley, Systems Development, ULCC" To: DJGPP Subject: Request for advice with djgpp, ASPI manager and them _go32_dpmi* functions Greetings, djgpp-ers. I'm try to port a program written in Microsoft C which communicates with the Adaptec SCSI Aspi Manager driver. (Well, it's more complex than that ; it was actually a Unix program ported to Microsoft C, but that's not relevant right now...) I'm basically a Unix/VMS systems hacker and am not at all familiar with using traditional DOS system calls via compilers such as Microsoft C, which I don't have access to, and I haven't yet found a good reference to explain it all. I've found the docs on using the intxxx and _go32_dpmi_* functions difficult to grapple with, since they reasonable assume that one already knows how to program in the traditional DOS fashion and mainly just explain the differences introduced by the djgpp 32-bit environment. I've been happily using djgpp for 18 months for other programs which don't need to interact so closely with DOS. I'm hoping someone can shed some advice which might get me started and then hopefully I can make more progress on my own. I have a code fragment from the original program like this: ******************* /* * This will be the function for all aspi requests, it gets * initialized at aspiinit() and called from aspirequest() */ void (far *aspi)(void far *) = (void far *) 0; void aspiinit() { int h,i; long l; union REGS inregs; union REGS outregs; char *getenv(), *tapeid; if ( (h=open("SCSIMGR$",0)) == -1 ) { perror("Opening ASPI Manager"); exit(1); } /* * This is an ioctl(READ) to the "SCSIMGR$". * It returns the entrypoint of the aspi-module (far pointer) * in the 4 bytes, pointed to by the dx register. */ inregs.x.ax = 0x4402; inregs.x.dx = ( int ) &aspi; inregs.x.cx = 4; inregs.x.bx = h; intdos(&inregs, &outregs); ************ The intent of this as far as I can see is to get an address, which I guess is real-mode, and which is later used to despatch all requests to the manager. I tried simply using the djgpp intdos(), which I didn't expect to work as I realise it only does for interrupts which go32 knows about. I then tried the following: ************* void ( *aspi)(void *) = (void *) 0; void aspiinit() { int h,i; long l; #ifdef __GO32__ #include _go32_dpmi_registers inregs; _go32_dpmi_seginfo dosmem1,dosmem2; #else union REGS inregs; union REGS outregs; #endif char *getenv(), *tapeid; if ( (h=open("SCSIMGR$",0)) == -1 ) { perror("Opening ASPI Manager"); exit(1); } /* * This is an ioctl(READ) to the "SCSIMGR$". * It returns the entrypoint of the aspi-module (far pointer) * in the 4 bytes, pointed to by the dx register. */ inregs.x.ax = 0x4402; inregs.x.cx = 4; inregs.x.bx = h; #ifdef __GO32__ dosmem1.size = 1; inregs.x.ss = inregs.x.sp = inregs.x.flags = 0; if(_go32_dpmi_allocate_dos_memory(&dosmem1)) { printf("Unable to allocate DOS memory\n"); exit(1); } printf("Alloc DOS mem returns RS: %x RO: %x size: %d\n", dosmem1.rm_segment,dosmem1.rm_offset,dosmem1.size); inregs.x.dx = dosmem1.rm_segment*16; i = dosmem1.rm_segment*16; dosmemget(dosmem1.rm_segment*16,sizeof(int),&aspi); printf("Aspi entry before int is %x\n",(int) aspi); i = _go32_dpmi_simulate_int(0x21,&inregs); printf("File was %d, int returns %d\n",h,i); dosmemget(dosmem1.rm_segment*16,sizeof(int),&aspi); _go32_dpmi_free_dos_memory(&dosmem1); printf("Aspi entry is %x\n",(int) aspi); exit(1); ********** I'm unsure in this case what I should be putting in inregs.x.dx. It should be the address of a location in which to place the ASPI entry point. As you can see, I have allocated one 16-byte block with dosmemget to receive this, but I can't understand from the docs what the real-mode address of this is. Is it dosmem.rm_segment or dosmem.rm_segment*16+dosmem.rm_offset or what ? In any event, the code above doesn't return an error, but the dosmemget shows that the address I've pointed to doesn't change after the call. I simply don't know enough about 80x86 real-mode addressing to fathom how an address is constructed from segment/offset pairs. I presume the segment is the number of a 64 Kbyte block, and the offset a 16-bit address within that block, since the real-mode addressing seems to be all done with 16-bit values. Assuming someone can get me past this, I then need to work out how to dispatch things via the pointer returned. I presume that _go32_dpmi_simulate_fcall is what I want. The rest of the program builds up command request blocks using code similar to that below: ***************** /* * GetDeviceTyp: The returned typ corresponds to the typ of an * SCSI-Inquiry command. */ int GetDeviceTyp(adapter, target_id, lun) int adapter; int target_id; int lun; { struct _srbgettyp *srb; int i; /* allocate a SCSI Request Block (SRB) */ if ( (srb=calloc(sizeof( struct _srbgettyp), 1)) == 0 ) return(E$NoMem); srb->h.cmd = 1; srb->h.adapter = adapter; srb->target_id = target_id; srb->lun = lun; /* Issue the request */ if ( (i=aspireq(srb)) ) { ************* *********** and the function aspireq() does the following: int aspireq(srb) void *srb; { int cnt; struct _srbinquiry *s; s = ( struct _srbinquiry *) srb; aspi(s); cnt = 10; while ( cnt-- ) while ( ! s->h.status ) ; /* POLL ! */ if ( s->h.status == 1 ) return E$NoErr; return E$AspiErr; } ********** I presume that I need to allocate these structures in low memory with dosmemget, fill them in with copies of the structures I have, and use _go32_dpmi_simulate_fcall to dispatch the aspi() function. Am I right ? And, when these structures themselves contain the addresses of buffers to read and/or write from, what sort of address do I put there? Thanks to anyone who has taken the time to read through this and can offer any advice. Kevin Ashley ------------------------------------------------------------------------------ Kevin Ashley K DOT Ashley AT Ulcc DOT ac DOT uk Systems Development Group Manager http://www.ulcc.ac.uk/staff/Kevin+Ashley University of London Computer Centre. ...ukc!ncdlab!K.Ashley This is not a signature