2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: mkernel/modules/sound/sound.c
5 * PURPOSE: SoundBlaster 16 Driver
6 * PROGRAMMER: Snatched from David Welch (welch@mcmail.com)
7 * Modified for Soundblaster by Robert Bergkvist (fragdance@hotmail.com)
13 /* FUNCTIONS **************************************************************/
15 #include <ddk/ntddk.h>
31 PKINTERRUPT IrqObject
;
32 BOOLEAN
DMAOutputISR(PKINTERRUPT Interrupt
, PVOID ServiceContext
)
34 DPRINT1("interrupt\n");
38 void sb16_play(WAVE_HDR
* wave
)
44 PKINTERRUPT IrqObject
;
45 unsigned int mask
,newmask
;
48 unsigned int tmp
[255];
53 // tmp[i++]=get_dma_page(0x0fffff);
54 // DPRINT1("0x%x ",tmp[i-1]);
56 while((tmp
[i
-1]&0xffff)!=0);
57 // free_page((tmp[0]),i-1);
58 sb16
.buffer
=((unsigned char*)tmp
[i
-1]);
61 * Because this is used by alomost every subsystem including irqs it
62 * must be atomic. The following code sequence disables interrupts after
63 * saving the previous state of the interrupt flag
66 __asm__("pushf\n\tpop %0\n\tcli\n\t"
70 memcpy(sb16
.buffer
,(&wave
->data
),wave
->dLen
);
73 MappedIrq
= HalGetInterruptVector(Internal
,0,0,8+sb16
.irq
,&Dirql
,&Affinity
);
77 IoConnectInterrupt(&IrqObject
,DMAOutputISR
,0,NULL
,MappedIrq
,Dirql
,Dirql
,0,FALSE
,Affinity
,FALSE
);
80 newmask
=((int)1<<sb16
.irq
);
81 // outb(0x21,(mask&~newmask));
83 // Restore the interrupt flag
84 __asm__("push %0\n\tpopf\n\t"
90 // disable_dma(sb16.dma8);
94 // set_dma_count(1,wave->dLen);
95 //set_dma_mode(1,DMA_MODE_WRITE);
97 //outb(0x3,(wave->dLen)&0xff);
98 //outb(0x3,((unsigned int)(wave->dLen)>>8)&0xff);
99 //set_dma_addr(sb16.dma8,(unsigned int)sb16.buffer);
100 //outb(0x83,(((unsigned int)(sb16.buffer-IDMAP_BASE)>>16))&0xf);
101 //outb(0x2,((unsigned int)sb16.buffer&0xff));
102 //outb(0x2,(((unsigned int)(sb16.buffer-IDMAP_BASE)>>8))&0xff);
103 //enable_dma(sb16.dma8);
106 write_dsp(sb16
.base
,0x00D1);
108 write_dsp(sb16
.base
,0x40);
109 write_dsp(sb16
.base
,((unsigned char)256-(1000000/wave
->nSamplesPerSec
)));
111 // outb(sb16.base + 4, (int) 0xa);
112 // outb(sb16.base + 5, (int) 0x00);
114 // outb(sb16.base + 4, (int) 4);
115 // outb(sb16.base + 5, (int) 0xFF);
117 // outb(sb16.base + 4, (int) 0x22);
118 // outb(sb16.base + 5, (int) 0xFF);
120 write_dsp(sb16
.base
,0x14);
121 write_dsp(sb16
.base
,(wave
->dLen
&0x00ff));
122 write_dsp(sb16
.base
,((wave
->dLen
)&0xff00)>>8);
124 // write_dsp(sb16.base,0xc0);
125 // write_dsp(sb16.base,0x0);
126 // OldIRQ=HalGetInterruptVector(Internal,0,0,irq+8,&irql,&affinity);
127 // DPRINT1("OldIRQ: 0x%x\n",OldIRQ);
129 // status=IoConnectInterrupt(&IrqObject,playRoutine,0,NULL,OldIRQ,irql,irql,0,FALSE,affinity,FALSE);
130 // if(status!=STATUS_SUCCESS) DPRINT1("Couldn't set irq\n");
131 // else DPRINT1("IRQ set\n");
135 void dump_wav(WAVE_HDR
* wave
)
137 DPRINT1("wave.rID: %c%c%c%c\n",wave
->rID
[0],wave
->rID
[1],wave
->rID
[2],wave
->rID
[3]);
138 DPRINT1("wave.rLen: 0x%x\n",wave
->rLen
);
139 DPRINT1("wave.wID: %c%c%c%c\n",wave
->wID
[0],wave
->wID
[1],wave
->wID
[2],wave
->wID
[3]);
140 DPRINT1("wave.fID: %c%c%c%c\n",wave
->fID
[0],wave
->fID
[1],wave
->fID
[2],wave
->fID
[3]);
141 DPRINT1("wave.fLen: 0x%x\n",wave
->fLen
);
142 DPRINT1("wave.wFormatTag: 0x%x\n",wave
->wFormatTag
);
143 DPRINT1("wave.nChannels: 0x%x\n",wave
->nChannels
);
144 DPRINT1("wave.nSamplesPerSec: 0x%x\n",wave
->nSamplesPerSec
);
145 DPRINT1("wave.nAvgBytesPerSec: 0x%x\n",wave
->nAvgBytesPerSec
);
146 DPRINT1("wave.nBlockAlign: 0x%x\n",wave
->nBlockAlign
);
147 DPRINT1("wave.FormatSpecific: 0x%x\n",wave
->FormatSpecific
);
148 DPRINT1("wave.dID: %c%c%c%c\n",wave
->dID
[0],wave
->dID
[1],wave
->dID
[2],wave
->dID
[3]);
149 DPRINT1("wave.dLen: 0x%x\n",wave
->dLen
);
152 BOOLEAN
playRoutine(PKINTERRUPT Interrupt
,PVOID ServiceContext
)