home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; MIDIINT.ASM -- Assembler subroutines for MIDIEX patch exchange utility
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- ; COPYRIGHT (C) 1986 John Bailin, Cantus Corporation
- ;
- ; Date: 01/02/86
- ;
- ; Changed 08/24/86 Jim Bergsten to function using the Microsoft "C"
- ; compiler. Summary of changes:
- ; 1. PAGE statement added for better output listing.
- ; 2. Entry point names prefixed with "_".
- ; 3. GROUP, PROG, SEGMENT statements changed to match Microsoft
- ; small model standards.
- ; 4. Unnecessary stack subtracts and adds removed.
- ; 5. Other corrections, simplifications...
- ;
- ; Changed 11/14/86 by Michael Geary - fixed several bugs
- ;
- ;
- ; Note: Linkage conventions assume the Microsoft C compiler small model.
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; equates
-
- mpudata equ 330h ; mpu data port address.
- mpustat equ 331h ; mpu status port address.
- mpucmd equ 331h ; mpu command port address.
- mpudsr equ 80h ; mpu data set ready, active low.
- mpudrr equ 40h ; mpu data read ready, active low.
-
- loop_delay equ 0ffffh ; delay for timeouts.
-
- BUFMAX equ 8192 ; **MUST MATCH C CODE**
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
- _TEXT ENDS
- CONST SEGMENT PARA PUBLIC 'CONST'
- CONST ENDS
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
- _DATA SEGMENT WORD PUBLIC 'DATA'
- _DATA ENDS
- DGROUP GROUP CONST, _BSS, _DATA
-
- ASSUME cs:_TEXT, ds:DGROUP, es:nothing, ss:nothing
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; data segment
-
- _DATA segment word public 'DATA'
-
- public _recv_data_count,_recv_buf,_recv_buf_ptr
- public _fetch_buf_ptr
- public _wait_char
-
- oldInt2 label dword
- int_2_save dw ?,?
-
- _recv_buf db BUFMAX dup (0)
- _recv_buf_end label byte
- _recv_data_count dw 0
- _recv_buf_ptr dw 0
- _fetch_buf_ptr dw 0
-
- _wait_char db 0
-
- _DATA ends
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; code segment
-
- _TEXT segment byte public 'CODE'
-
- public _set_mpu_vector,_reset_mpu_vector,mpu_int,_int10
- public _write_mpu_command,_write_mpu_data,_get_char
- public _queue_mpu_data
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Set the interrupt vector for the MPU/401
-
- _set_mpu_vector proc near
-
- mov ax,350ah ; get current int 2
- int 21h ; dos does it.
- mov int_2_save,bx ; save the vector offset.
- mov int_2_save+2,es ; save the vector segment.
- push ds ; save data segment.
- mov dx,offset mpu_int ; offset for dos call.
- mov ax,seg mpu_int ; segment for dos call
- mov ds,ax ;
- mov ax,250ah ; set vector call, int 2.
- int 21h ; dos installs vector.
- pop ds
- cli ; interrupts off.
- in al,21h ; read 8259 address.
- jmp short $+2
- and al,0fbh ; enable irq2.
- out 21h,al ;
- call _mpu_reset ; reset the mpu, return code in AX
- sti ; interrupts back on.
- ret ; return to caller.
-
- _set_mpu_vector endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Reset the interrupt vector for the MPU/401
-
- _reset_mpu_vector proc near
-
- push ds ; save registers.
- cli ; interrupts off.
- in al,21h ; read 8259.
- jmp short $+2
- or al,4 ; disable irq2.
- out 21h,al ; done.
- sti ; interrupts back on.
- mov ax,250ah ; restore old int 2 vector.
- mov dx,int_2_save ; get old offset into dx.
- mov ds,int_2_save+2 ; get old segment into ds.
- int 21h ; dos sets the vector.
- pop ds ; restore registers.
- ret ; return to caller.
-
- _reset_mpu_vector endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Reset the MPU/401
-
- _mpu_reset proc near
- cli ; disable interrupts.
-
- mov dx,mpustat ; mpu status port.
- mov cx,loop_delay ; delay counter.
- mr10: in al,dx ; get the status.
- and al,mpudrr ; test for data receive ready.
- jz mr15 ; ready.
- loop mr10 ; not ready.
- xor ax,ax ; timed out.
- jmp short mr40 ; leave.
- mr15: mov ax,0ffh ; get the command.
- out dx,al ; send to mpu.
- mov cx,loop_delay ; delay counter.
- mr20: in al,dx ; get the status.
- and al,mpudsr ; test for data set ready.
- jz mr30 ; ready.
- loop mr20 ; not ready.
- xor ax,ax ; timed out.
- jmp short mr40 ; leave.
- mr30: mov dx,mpudata ; mpu data port.
- in al,dx ; read data.
- mov ax, 1
- mr40:
- sti ; interrupts back on.
- ret ; return to caller.
-
- _mpu_reset endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Write a command to the MPU
- ; BOOL write_mpu_command( command-byte );
-
- _write_mpu_command proc near
-
- push bp ; save caller's base pointer
- mov bp,sp ; establish new base pointer.
- mov dx,mpustat ; mpu status port.
- mov cx,loop_delay ; loop counter for no response.
- wmc10: in al,dx ; get the status.
- and al,mpudrr ; test for data receive ready.
- jz wmc15 ; ready.
- loop wmc10 ; not ready.
- xor ax,ax ; timed out.
- jmp short wmc30 ; leave.
- wmc15: cli ; interrupts off.
- mov ax,[bp+4] ; get the command.
- out dx,al ; send to mpu.
- mov cx,loop_delay ; loop counter for no response.
- wmc20: in al,dx ; get the status.
- and al,mpudsr ; test for data set ready.
- jz wmc25 ; ready.
- loop wmc20 ; not ready.
- xor ax,ax ; timed out.
- jmp short wmc30 ; leave.
- wmc25: mov dx,mpudata ; mpu data port.
- in al,dx ; read data.
- cmp al,0FEh ; acknowledge?
- je wmc29 ; yes.
- call _queue_mpu_data ; no. queue the data.
- wmc29: mov ax,1 ; normal return
- wmc30: sti ; interrupts back on.
- pop bp ; get base pointer back.
- ret ; return to caller.
-
- _write_mpu_command endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Write data to the MPU
- ; BOOL write_mpu_data( data-byte );
-
- _write_mpu_data proc near
-
- push bp ; save caller's base pointer
- mov bp,sp ; establish new base pointer.
- mov dx,mpustat ; mpu status port.
- mov cx,loop_delay ; loop counter for no response.
- wmd10: in al,dx ; get the status.
- and al,mpudrr ; test for data receive ready.
- jz wmd20 ; ready.
- loop wmd10 ; not ready.
- xor ax,ax ; timed out.
- jmp short wmd30 ; leave.
- wmd20: mov dx,mpudata ; mpu data port.
- mov ax,[bp+4] ; get the byte to send.
- out dx,al ; send to mpu.
- mov ax,1 ; normal return
- wmd30: pop bp ; get base pointer back.
- ret ; return to caller.
-
- _write_mpu_data endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; MPU interrupt handler (IRQ2, INT 0Ah)
-
- mpu_int proc far
-
- push ax ; save regs.
- push dx
- pushf
- mov dx,mpustat ; mpu status port
- in al,dx ; read status
- rol al,1 ; bit 7 into cy.
- jb mi90 ; not generated by mpu.
- popf
- sti ; allow other interrupts
- push ds
- mov ax,DGROUP
- mov ds,ax
- mov dx,mpudata ; ready. now get data port.
- in al,dx ; get data.
- cmp al,0FEh ; acknowledge?
- je mi30 ; yes. don't queue data.
- cmp _wait_char,0 ; waiting for a particular char?
- je mi20 ; no.
- cmp al,_wait_char ; the char we're waiting for?
- jne mi20 ; no.
- mov _wait_char,0 ; yes. reset flag.
- mi20: call _queue_mpu_data ; queue it up.
- mi30: mov al,20h ; eoi to send to 8259.
- out 20h,al ; send it.
- pop ds ; restore regs.
- pop dx
- pop ax
- iret ; return to caller.
-
- mi90: popf
- pop dx
- pop ax
- jmp oldInt2
-
- mpu_int endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; queue received mpu data
- ; input -- al = received data
-
- _queue_mpu_data proc near
-
- push bx ; save regs
- cli ; interrupts off.
- mov bx,_recv_buf_ptr ; buffer ptr.
- mov _recv_buf[bx],al ; store data.
- inc _recv_buf_ptr ; increment the buffer pointer.
- inc _recv_data_count ; increment the data count.
- cmp _recv_buf_ptr,BUFMAX ; incremented past the end?
- jb qmd10 ; not yet.
- mov _recv_buf_ptr,0 ; yes. wrap around to zero.
- qmd10: sti ; interrupts back on.
- pop bx
- ret ; return to caller.
-
- _queue_mpu_data endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; fetch received mpu data (*not used*)
- ;
- ; input -- none
- ; output -- ah = 1 if data received, 0 if not. al = data.
-
- IF 0
-
- _fetch_mpu_data proc near
-
- xor ax, ax
- cli ; interrupts off.
- mov bx,_fetch_buf_ptr ; buffer ptr.
- cmp bx,_recv_buf_ptr ; any data?
- je fmd10 ; no, return
- mov al,_recv_buf[bx] ; fetch data.
- mov ah, 1
- inc _fetch_buf_ptr ; increment the buffer pointer.
- cmp _fetch_buf_ptr,_recv_buf_end ; incremented past the end?
- jb fmd10 ; not yet.
- mov _fetch_buf_ptr,0 ; yes. wrap around to zero.
- fmd10: sti ; interrupts back on.
- ret ; return to caller.
-
- _fetch_mpu_data endp
-
- ENDIF
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; bios int 16h call.
- ;
- ; calling convention get_char( mode ) ;
- ;
- ; input -- mode = 0 -- read next char, return result in al, scan code in ah.
-
- ; -- mode = 1 -- returns 1 if a char is available, 0 if not.
- ; -- mode = 2 -- returns shift flags in al.
-
- _get_char proc near
-
- push bp ; save caller's base pointer
- mov bp,sp ; establish new base pointer.
- mov ax,[bp+4] ; get mode.
- xchg ah,al ; turn it around for bios call.
- int 16h ; do the bios call.
- pushf ; save flags.
- cmp word ptr [bp+4],1 ; check for char available?
- jne gc10 ; no. just return what bios returns.
-
- xor ax,ax ; assume no char.
- popf ; get flags back.
- jz gc20 ; no char available.
- mov ax,1 ; signal char available.
- jmp short gc20 ; continue.
- gc10: popf ; sync.
- gc20: pop bp ; get base pointer back.
- ret ; return to caller.
-
- _get_char endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; bios int 10h c level call.
- ;
- ; calling convention int10( ax, bx, cx, dx )
- ;
-
- _int10 proc near
-
- push bp ; save caller's base pointer
- mov bp,sp ; establish new base pointer.
- mov ax,[bp+4] ; get register calling value.
- mov bx,[bp+6] ; get register calling value.
- mov cx,[bp+8] ; get register calling value.
- mov dx,[bp+10] ; get register calling value.
- int 10h ; do the bios call.
- pop bp ; get base pointer back.
- ret ; return to caller.
-
- _int10 endp
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- _TEXT ends
-
- end