/***************************************************************************** softset IRQ and DMA of original Windows Sound System board Chris Giese http://www.execpc.com/~geezer *****************************************************************************/ #include <stdlib.h> /* atoi() */ #include <stdio.h> /* printf() */ #include <dos.h> /* union REGS, int86(), inportb(), outportb() */ #if 0 #define DEBUG(X) X #else #define DEBUG(X) #endif #define POWER_UP_DLY 100000L /***************************************************************************** *****************************************************************************/ static int ad1848_detect(unsigned short ioadr) { unsigned char temp, reg_val; unsigned long timeout; /* poll index register of AD1848 until it returns something other than 0x80 */ for(timeout = POWER_UP_DLY; timeout != 0; timeout--) { if(inportb(ioadr) != 0x80) break; } if(timeout == 0) return -1; DEBUG( timeout = POWER_UP_DLY - timeout; if(timeout != 0) printf("<waited %lu clocks>\n", timeout); ) /* try writing various AD1848 registers (left and right input gain and control regs) to see if chip is there */ for(temp = 0; temp < 2; temp++) { outportb(ioadr + 0, temp); outportb(ioadr + 1, 0xAA); reg_val = inportb(ioadr + 1); outportb(ioadr + 1, 0x45);/* b4 is reserved; always write 0 */ if(reg_val != 0xAA || inportb(ioadr + 1) != 0x45) return -1; } /* try changing the chip revision ID bits (they are read-only) */ outportb(ioadr + 0, 0x0C); reg_val = inportb(ioadr + 1); outportb(ioadr + 1, reg_val ^ 0x0F); if(((inportb(ioadr + 1) ^ reg_val) & 0x0F) != 0) return -1; /* found it! */ return 0; } /***************************************************************************** from PORTS.B of Ralf Brown's Interrupt List (this is for WSS emulation by OPTi "Vendetta" chipset, but it seems to work my original WSS board) Bit(s) Description (Table P0898) 7 reserved 6 IRQ sense source 0 = normal 1 = interrupt auto-selection 5-3 WSS IRQ 000 = disable 001 = IRQ7 010-100 = IRQ9-IRQ11 101 = IRQ5 110-111 = reserved 2-0 WSS DRQ playback capture 000 = disable disable 001 = DRQ0 disable 010 = DRQ1 disable 011 = DRQ3 disable 100 = disable DRQ1 101 = DRQ0 DRQ1 110 = DRQ1 DRQ0 111 = DRQ3 DRQ0 *****************************************************************************/ int main(int arg_c, char *arg_v[]) { static const unsigned short base_io_adr[] = { 0x530, 0x604, 0xE80, 0xF40 }; unsigned char irq, dma, irq_bits, dma_bits, temp; unsigned short ioadr = 0x530; union REGS regs; int err; if(arg_c < 3) { printf("Softsets Windows Sound System IRQ and DMA. Usage:\n" "\t""softset irq dma\nirq=7,9,10,11; dma=0,1,3\n"); return 1; } /* get IRQ num from command line and validate it */ irq = atoi(arg_v[1]); irq_bits = 0; if(irq == 7) irq_bits |= 0x08; else if(irq == 9) irq_bits |= 0x10; else if(irq == 10) irq_bits |= 0x18; else if(irq == 11) irq_bits |= 0x20; /* maybe IRQ 5 for OPTi Vendetta chip, but not for original WSS... else if(irq == 5) irq_bits |= 0x28; */ else { printf("Illegal IRQ number %u\n", irq); return 2; } /* get DMA num from command line and validate it */ dma = atoi(arg_v[2]); /* NOTE: capture (record) DMA is always disabled here, either change this or use single-mode DMA (set SDC bit in reg 9 of AD1848) */ dma_bits = 0; if(dma == 0) dma_bits |= 0x01; else if(dma == 1) dma_bits |= 0x02; else if(dma == 3) dma_bits |= 0x03; else { printf("Illegal DMA number %u\n", dma); return 3; } /* make sure it's really DOS */ regs.x.ax=0x1600; int86(0x2F, ®s, ®s); if(regs.h.al != 0 && regs.h.al != 0x80) { printf("Detected Windows version "); if(regs.h.al == 0x01 || regs.h.al == 0xFF) printf("2.x"); else printf("%u.%u", regs.h.al, regs.h.ah); printf(", aborting\n"); return 4; } /* probe for board xxx - doesn't work! */ #if 1 ioadr = 0x530; #else temp = 0; for(; temp < sizeof(base_io_adr) / sizeof(base_io_adr[0]); temp++) { ioadr = base_io_adr[temp] + 4; DEBUG(printf("\t""probing at I/O=0x%03X...\n", ioadr);) err = ad1848_detect(ioadr); if(err == 0) break; } if(err != 0) { printf("\t""error: chip not found\n"); return 5; } #endif /* do it */ outportb(ioadr + 0, irq_bits | 0x40); if((inportb(ioadr + 3) & 0x40) == 0) printf("IRQ conflict?\n"); outportb(ioadr, irq_bits | dma_bits); return 0; }