home *** CD-ROM | disk | FTP | other *** search
- ;*DDK*************************************************************************/
- ;
- ; COPYRIGHT Copyright (C) 1995 IBM Corporation
- ;
- ; The following IBM OS/2 WARP source code is provided to you solely for
- ; the purpose of assisting you in your development of OS/2 WARP device
- ; drivers. You may use this code in accordance with the IBM License
- ; Agreement provided in the IBM Device Driver Source Kit for OS/2. This
- ; Copyright statement may not be removed.;
- ;*****************************************************************************/
-
- ;/************************************************************************/
- ;/* */
- ;/* Driver Name: IBM2SCSI.ADD - Adapter Driver for ABIOS SCB Devices */
- ;/* --------------------------------------------------- */
- ;/* */
- ;/* Source File Name: IO.ASM */
- ;/* */
- ;/* Descriptive Name: I/O routines for accessing the adpaters. */
- ;/* */
- ;/* Function: */
- ;/* */
- ;/* */
- ;/*----------------------------------------------------------------------*/
- ;/* */
- ;/* */
- ;/* DISCLAIMER OF WARRANTIES. The following [enclosed] code is */
- ;/* provided to you solely for the purpose of assisting you in */
- ;/* the development of your applications. The code is provided */
- ;/* "AS IS", without warranty of any kind. IBM shall not be liable */
- ;/* for any damages arising out of your use of this code, even if */
- ;/* they have been advised of the possibility of such damages. */
- ;/* */
- ;/*----------------------------------------------------------------------*/
- ;/* */
- ;/* Change Log */
- ;/* */
- ;/* Mark Date Programmer Comment */
- ;/* ---- ---- ---------- ------- */
- ;/* @nnnn mm/dd/yy NNN */
- ;/* */
- ;/* */
- ;/************************************************************************/
-
- ;
- ; Some local equates
-
- BPTR EQU <byte ptr>
- WPTR EQU <word ptr>
- DPTR EQU <dword ptr>
-
- CIR0 EQU 0 ; command interface register 0
- CIR1 EQU 1 ; command interface register 1
- CIR2 EQU 2 ; command interface register 2
- CIR3 EQU 3 ; command interface register 3
- AR EQU 4 ; attention register
- BCR EQU 5 ; basic control reg
- ISR EQU 6 ; interrupt status register
- BSR EQU 7 ; basic status register
-
- LONGSCB EQU 40h ; long SCB attention request code
- NORMSCB EQU 30h ; normal SCB attention request code
- IMMDCMD EQU 10h ; immediate command
-
-
-
- WAIT400 EQU 27 ; 27 15.625 intervals for 400 us wait (a little longer)
- WAIT50 EQU 4 ; 4 intervals for 50 us wait
-
-
-
- BUSY EQU 01h ; busy bit
-
-
-
-
- public __StartIO
- public _ReadReg
- public _WriteReg
- public _WriteAttn
- public _ResetToggle
-
-
- _TEXT segment word public 'code'
- assume cs:_TEXT
-
- .286p
-
-
- ;/*************************************************************************/
- ;/* */
- ;/* StartIO - Start an SCB to the specified device. */
- ;/* */
- ;/* This routine will start the SCB on the device passed. */
- ;/* */
- ;/* Entry: StartSCB(USHORT IOAddr,ULONG ppSCB, USHORT cmd); */
- ;/* */
- ;/* IOAddr - I/O base address of the card */
- ;/* ppSCB - phys ptr to SCB or the immediate command */
- ;/* cmd - command to write to the attention register. */
- ;/* It includes the logical device number and */
- ;/* the request code. Only the low byte is used */
- ;/* */
- ;/* Exit: AX = 0 if no error, <> 0 if busy never cleared. */
- ;/* ints disabled if started (AX = 0) */
- ;/* */
- ;/*************************************************************************/
-
- ;
- ; Stack frame, accounts for bp pushed on stack by enter instruction
-
-
- IOAddr EQU <(WPTR [bp+4])> ; IO base address
- ppSCB EQU <(DPTR [bp+6])> ; physical ptr to the SCB
- cmd EQU <(WPTR [bp+10])> ; command to the adapter.
-
-
- __StartIO proc near
-
- enter 0,0
-
- ;
- ; First wait for busy to be cleared
-
- push dx
- push cx
-
- mov cx, WAIT400 ; 400 us wait
- mov dx, IOAddr ; card IO address
- call wbsy ; go wait
-
- jc bsy ; card is busy, something wrong
-
- ;
- ; Card is not busy and ints are off now. Program the Command interface
- ; registers with the SCB address.
-
- .386p
- mov eax, ppSCB ; get the physical address
- mov cx, 4 ; loop 4 times
- outl: out dx, al ; out the low byte
- inc dx ; next CIR
- shr eax, 8 ; shift next byte into al
- loop outl ; go loop
-
- .286p
-
- ;
- ; Now get the command code from the stack and write the low byte to
- ; the attention register.
-
- mov ax, cmd ; get logical device number from stack
- mov dx, IOAddr ; get base I/O address
- add dx, AR ; attention register offset
- out dx, al ; start the I/0
- mov ax, 0 ; no error
- jmp exit ; leave
-
- bsy: mov ax, 1 ; signal some error
-
- exit: pop cx ; restore stack
- pop dx
-
- leave
- ret
-
- __StartIO endp
-
-
- ;/*************************************************************************/
- ;/* */
- ;/* ReadReg - read the specified adapter register. */
- ;/* */
- ;/* This routine reads the register pointed to by IOAddr and returns */
- ;/* the value in AX. */
- ;/* */
- ;/* Entry: ReadReg(USHORT IOAddr); */
- ;/* */
- ;/* Exit: AL = register value */
- ;/* */
- ;/*************************************************************************/
-
- ;
- ; Stack frame, accounts for bp pushed on stack by enter instruction
-
-
- IOAddr EQU <(WPTR [bp+4])> ; IO reg address
-
- _ReadReg proc near
-
- enter 0,0
-
- push dx ; save DX
- mov dx, IOAddr ; get register address
- in al, dx ; read it
- pop dx ; restore dx
- leave ; clear stack frame
- ret ; return to caller
-
- _ReadReg endp
-
-
- ;/*************************************************************************/
- ;/* */
- ;/* WriteReg - write adapter register. */
- ;/* */
- ;/* This routine writes the low byte of the value on the stack to the */
- ;/* specified register. This should not be used for writing to the */
- ;/* attention register. */
- ;/* */
- ;/* Entry: WriteReg(USHORT IOAddr, USHORT val); */
- ;/* */
- ;/* Exit: None. */
- ;/* */
- ;/*************************************************************************/
-
- ;
- ; Stack frame, accounts for bp pushed on stack by enter instruction
-
-
- IOAddr EQU <(WPTR [bp+4])> ; IO reg address
- val EQU <(WPTR [bp+6])> ; value
-
- _WriteReg proc near
-
- enter 0,0
-
- push dx ; save DX
- push ax ; save AX
- mov ax, val ; get value to write out (low byte only)
- mov dx, IOAddr ; get register address
- out dx, al ; write the low byte out
- pop ax ; restore ax
- pop dx ; restore dx
- leave ; clear stack frame
- ret ; return to caller
-
- _WriteReg endp
-
-
- ;/*************************************************************************/
- ;/* */
- ;/* WriteAttn - write the attention register. */
- ;/* */
- ;/* This routine writes the low byte of the value on the stack to the */
- ;/* attention register of the specified adapter. It checks to make */
- ;/* sure that busy is clear before doing the write. */
- ;/* */
- ;/* Entry: WriteReg(USHORT IOAddr, USHORT val); */
- ;/* */
- ;/* Exit: 0 = no error, <>0 = error */
- ;/* */
- ;/*************************************************************************/
-
- ;
- ; Stack frame, accounts for bp pushed on stack by enter instruction
-
-
- IOAddr EQU <(WPTR [bp+4])> ; base IO address
- val EQU <(WPTR [bp+6])> ; value
-
- _WriteAttn proc near
-
- enter 0,0
-
- ;
- ; First wait for busy to be cleared
-
- push dx
- push cx
-
- mov cx, WAIT400 ; 400 us wait
- mov dx, IOAddr ; card IO address
- call wbsy ; go wait
-
- jc hosed ; card is busy, something wrong
-
- mov ax, val ; get value to write out (low byte only)
- mov dx, IOAddr ; get the base IO address
- add dx, AR ; get to the attention register
- out dx, al ; write the low byte out
- mov ax, 0 ; no error
- jmp allok
-
- hosed: mov ax, 1 ; error
-
- allok: pop cx ; restore ax
- pop dx ; restore dx
- sti
- leave ; clear stack frame
- ret ; return to caller
-
- _WriteAttn endp
-
- ;------ wbsy ---------------------------------------------------------------
- ; fixed time wait routine (memory refresh output used as reference)
- ; as well as the busy indicator in the BSR
- ;
- ; entry:
- ; cx - count of 15.625 microsecond intervals to wait
- ; dx - base port value
- ;
- ; exit:
- ; CFL - 1, card busy, IFL unchanged
- ; 0, card is idle and IFL disabled
- ; cx - undefined
- ;---------------------------------------------------------------------------
- wbsy proc near ;
- push ax ; save reg
- push dx ; save port base
- add dx,BSR
- wbsy1: ;
- pushf ; save current IFL
- cli ; disable ints
- in al,dx ; eyeball BSR for not busy condition
- test al,BUSY ; is card still busy?
- jz not_bsy ; nope - exit loop w/ IFL=0, CFL=0
- popf ; restore IFL
- in al,61h ; read current refresh request output
- and al,10h ; mask for refresh request bit
- cmp al,ah ; did it just change
- je wbsy1 ; wait for a change
- mov ah,al ; save new state
- loop wbsy1 ; decrement half cycles till count end
- stc ; time expired - CFL set means error
- jmp short wb1 ; exit
-
- not_bsy: ; (CFL=0)
- pop ax ; balance stack (throw away flags)
- wb1:
- pop dx ; restore base port
- pop ax ; restore ax
- ret ; exit - CFL is clear
-
- wbsy endp
-
-
- ;/*************************************************************************/
- ;/* */
- ;/* _ResetToggle */
- ;/* */
- ;/* This routine will reset the specified adapter by toggling the */
- ;/* sub-system reset bit in the basic control register. */
- ;/* */
- ;/* Entry: _ResetToggle (USHORT baseIO) */
- ;/* */
- ;/* Exit: 0 always */
- ;/* */
- ;/*************************************************************************/
-
- ;
- ; Stack frame, accounts for bp pushed on stack by enter instruction
-
-
- baseIO EQU <(WPTR [bp+4])> ; base IO address
-
- _ResetToggle proc near
-
- enter 0,0
-
- ;
- ; Get current BCR value, mask some bits off and save it
-
- mov dx, baseIO ; base IO
- add dx, BCR ; pt to basic control reg
- in al, dx ; get current value
- and al, 0fh ; mask off high nibble
- push ax ; save value
-
- ;
- ; Now write the reset bit on, wait 50 us and then turn it off.
- ; Use memory refresh as a counter.
-
- mov al, 80h
- out dx, al ; reset bit on
- mov cx, 4 ; wait at least 50 us
-
- @@: ;
- in al,61h ; read current refresh request output
- and al,10h ; mask for refresh request bit
- cmp al,ah ; did it just change
- je @b ; wait for a change
- mov ah,al ; save new state
- loop @b ; decrement half cycles till count end
-
- mov al, 00h
- out dx, al ; now turn it off
-
- ;
- ; Now program it back to the original value, minus a few bits.
-
- pop ax ; original value
- out dx, al ; write it back
-
- leave
- ret
-
- _ResetToggle endp
-
-
- _TEXT ends
- end
-