/* This program is public domain. Note that VIA has a nice VIAAUDIO.COM */ /* which does the un-mute AND the Windows support but is < 600 bytes :-) */ /* Note: VIAFMTSR.COM is only needed if you want Adlib/OPL3 simulation. */ /* It's a software synthesizer. The SB16 DSP is done by hardware / BIOS. */ #define VERIFYENABLE 1 /* only needed if you tend to misconfig your CMOS */ #define SCANFORDEVICE 1 /* only needed if you do not know pcisel already */ #define VERBOSE 1 /* only needed if you want to see some messages */ /* Summary: Minimal "un-mute sound" code in Assembly language is... mov al,0x39 ; for "enter Win" 0x19, for "leave Win" 0x29 out 0x80,al mov eax,0x80003d48 ; <--- adjust to YOUR pcisel here! mov dx,0xcf8 out dx,eax mov dx,0xcfc in eax,dx ; in al,dx would be enough and al,0xfe ; same for "leave Win", for "enter Win" or al,1 out dx,eax ; out dx,al would be enough int 0x20 ; exit to DOS (optional ;-)) Quite short, huh? Less than 32 bytes. */ /* The PCI bus location of the AC97 function of the VT82C686: */ unsigned int pcisel = 0x80003d00U; /* <--- bus 0 slot 7 function 5 */ void mute (int muted) { outl(0xcf8, pcisel | 0x48); /* registers 0x40 ... are vendor specific */ outb(0xcfc, (inb(0xcfc) & ~1) | (muted ? 1 : 0)); return; } /* mute */ /* Scan the system for the VIA (0x1106) VT82C686 AC97 controller (0x3058) */ /* and disable the muting (enable the sound) of the SB16 mode then... */ int main (void) { unsigned int slot; outb(0x80, 0x39); /* "state 3" (initial access) */ /* (VIA abuses "DMA extra page register, temporary storage" here...) */ #if SCANFORDEVICE /* Search is simple: sub-function is always 5, bus is always 0 */ for (slot = 0; slot < 32; slot++) { outl(0xcf8, (0x80000500U | (slot << 11))); /* read device ID register */ if (inl(0xcfc) != 0x30581106) continue; /* no VIA VT82C686, search on */ pcisel = (pcisel & 0xffff07ff) | (slot << 11); break; /* we found it :-) */ }; if (slot == 0x1f) { /* bad luck for people with 32 PCI slots */ #if VERBOSE printf ("No VIA VT82c686a/b (VT8231) AC97 southbridge function found!\n"); #endif return 1; } #endif #if VERIFYENABLE outl(0xcf8, pcisel | 0x40); /* registers 0x40 ... are vendor specific */ if (!(inb(0xcfe) & 1)) { /* ... more elegant: inl(0xcfc) & 0x10000 ... */ #if VERBOSE printf ("VIA VT82c686a/b (VT8231) 'SoundBlaster' not enabled in BIOS\n"); #endif return 2; } #endif mute (0); /* unmute the device. *** rest is done by BIOS already! *** */ #if VERBOSE printf ("VIA VT82c686a/b (VT8231) 'SoundBlaster' at 'slot' %x un-muted.\n", (pcisel >> 11) & 0x1f); #endif return 0; } /* main */ /* if you have Wind*ws: call mute(1) for int 2f.1605, init broadcast */ /* (win /s AND /3) and call mute(0) for int 2f.1606, exit broadcast. */ /* DOSX/Win386 exit broadcast means: system is now back in real mode */ /* Do outb(0x80, 0x19) before mute(1) at Wind*ws start */ /* Do outb(0x80, 0x29) before mute(0) at return to DOS */ /* Volume control 00..63 -> set 32bit register to 0 - (volume << 14) */ /* See: http://mobokive.dyndns.org/Archive/Clayton/drivers/Intel#20Chipset/ */ /* Ac97sound/cs4299/Win98SE/cwawdm.inf ... and probably more useful: */ /* "PCI Configuration Data", table 00878, in Ralf Brown's Interrupt List 61 */ /* You can also check register 0x08: bytes are class:sub:interface:revision */ /* RBIL 61 table F0085 Plug-and-Play device type: class 4, sub 1 --> audio */ /* (EISA-PnP: device id "PNPB002" would mean SBPro. Same class, sub as PCI) */