BIOS.i810Sound.Mod 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622
  1. (* AUTHOR: Kristofer Jonsson, kjonsson@student.ethz.ch, krijo210@student.liu.se *)
  2. (* Written Sommer Semester 2003 *)
  3. MODULE i810Sound; (** AUTHOR "krijo210@student.liu.se"; PURPOSE "Intel 810 Sound driver for SoundDevices"; *)
  4. IMPORT SYSTEM, PCI, Machine, Kernel, Objects, Modules, Plugins,
  5. SoundDevices, KernelLog;
  6. CONST
  7. (* PCI Audio Control register offsets *)
  8. PACRegAC97CmdData = 0060H;
  9. PACRegAC97CmdAddress = 0062H;
  10. PACRegAC97StatusData = 0064H;
  11. PACRegAC97StatusAddress = 0066H;
  12. (* Sound Preferences *)
  13. MasterVolume = 225; (* 0 silent, 255 full volume *)
  14. InitVolume = 128; (* 0 silent, 255 full volume *)
  15. (* Could be any value MOD 4 = 0. Small buffer size means much work for
  16. the driver but fast respons times. Big buffers vice versa. *)
  17. BufferSize = 08FF0H;
  18. NofMixerChannels = 6;
  19. Boost = TRUE;
  20. InsecureMode = TRUE; (* also search for untested but probably compatible devices *)
  21. (* States for channel *)
  22. StatePlaying = 1;
  23. StateRecording = 2;
  24. StatePaused = 3;
  25. StateStoped = 4;
  26. StateClosed = 5;
  27. (* Bus Master Registers *)
  28. BMRInBase = 00H;
  29. BMROutBase = 10H;
  30. BMRBufferDescriptorBaseAddress = 00H;
  31. BMRCurrentIndexReg = 04H;
  32. BMRLastValidIndexReg = 05H;
  33. BMRStatusReg = 06H;
  34. BMRCtrlReg = 0BH;
  35. BMRGlobalStatusReg = 30H;
  36. (* AC97 Registers *)
  37. AC97MasterVolReg = 02H;
  38. AC97AuxVolReg = 04H;
  39. AC97MonoVolReg = 06H;
  40. AC97MicVolReg = 0EH;
  41. AC97LineInVolReg = 10H;
  42. AC97CDVolReg = 12H;
  43. AC97PCMOutVolReg = 18H;
  44. AC97RecordGainReg = 1CH;
  45. AC97ResetReg = 0;
  46. AC97RecordSelectReg = 1AH;
  47. AC97DacRateReg = 2CH;
  48. AC97AdcRateReg = 32H;
  49. AC97StatCtrlReg = 2AH;
  50. DebugBaseAddress = 0;
  51. DebugDMAAddess = 1;
  52. TraceOpenChannel = 2;
  53. DebugTraceListeners = 3;
  54. DebugInit = 4;
  55. Debug = {DebugBaseAddress, DebugDMAAddess, TraceOpenChannel, DebugTraceListeners, DebugInit };
  56. TYPE
  57. PlayChannelList = POINTER TO RECORD
  58. channel : PlayChannel;
  59. next : PlayChannelList;
  60. END;
  61. RecChannelList = POINTER TO RECORD
  62. channel : RecChannel;
  63. next : RecChannelList;
  64. END;
  65. MixerChangedProcList = POINTER TO RECORD
  66. mixerChangedProc : SoundDevices.MixerChangedProc;
  67. next : MixerChangedProcList;
  68. END;
  69. BufferList = POINTER TO RECORD
  70. buffer : SoundDevices.Buffer;
  71. next : BufferList;
  72. END;
  73. Sample = ARRAY 4 OF CHAR; (* 16 bit stereo sample *)
  74. DriverList = POINTER TO RECORD
  75. driver : Driver;
  76. next : DriverList;
  77. END;
  78. (**
  79. PCM data is transmitted through a DMA channel. Pointers to buffers are held in the
  80. memory in form of a structure named Buffer Drescriptor List.
  81. See Intel 82801xx Programmers manual for further details.
  82. *)
  83. DMABufferDescriptorList = POINTER TO ARRAY 32 OF RECORD
  84. addr : LONGINT;
  85. CmdAndLength : LONGINT;
  86. END;
  87. (**
  88. PCIAudioControl read/write from the PCI I/O space.
  89. I/O space is not memory mapped so we have to use PORTIN/PORTOUT.
  90. *)
  91. PCIAudioControl = OBJECT
  92. VAR
  93. base: LONGINT;
  94. PROCEDURE &Constr*(base : LONGINT);
  95. BEGIN
  96. SELF.base := base
  97. END Constr;
  98. (* Read from I/O register *)
  99. PROCEDURE RegRead8(offset : LONGINT) : SHORTINT;
  100. VAR
  101. res : CHAR;
  102. BEGIN
  103. Machine.Portin8(base + offset, res);
  104. RETURN SYSTEM.VAL(SHORTINT, res)
  105. END RegRead8;
  106. PROCEDURE RegRead16(offset : LONGINT) : INTEGER;
  107. VAR
  108. res : INTEGER;
  109. BEGIN
  110. Machine.Portin16(base + offset, res);
  111. RETURN SYSTEM.VAL(INTEGER, res)
  112. END RegRead16;
  113. PROCEDURE RegRead32(offset : LONGINT) : LONGINT;
  114. VAR
  115. res : WORD;
  116. BEGIN
  117. Machine.Portin32(base + offset, res);
  118. RETURN res
  119. END RegRead32;
  120. (* Write to I/O register *)
  121. PROCEDURE RegWrite8(offset : LONGINT; val : LONGINT);
  122. BEGIN
  123. Machine.Portout8(base + offset, SYSTEM.VAL(CHAR, val))
  124. END RegWrite8;
  125. PROCEDURE RegWrite16(offset : LONGINT; val : LONGINT);
  126. BEGIN
  127. Machine.Portout16(base + offset, SYSTEM.VAL(INTEGER, val))
  128. END RegWrite16;
  129. PROCEDURE RegWrite32(offset : LONGINT; val : LONGINT);
  130. BEGIN
  131. Machine.Portout32(base + offset, val)
  132. END RegWrite32;
  133. END PCIAudioControl;
  134. (**
  135. The AC97 Codec is a serial chip and we have to respect this fact. We may not flood it
  136. with data, but have to first check the semaphore register at NABMBAR + 34H if the
  137. chip is read to receive/transmit data. Else we get/put data to/from the I/O space
  138. as usual.
  139. All registers are 16 bit.
  140. *)
  141. AC97Control = OBJECT
  142. VAR
  143. NAMBAR, NABMBAR: PCIAudioControl;
  144. PROCEDURE &Constr*(NAMBAR, NABMBAR : PCIAudioControl);
  145. BEGIN
  146. SELF.NAMBAR := NAMBAR;
  147. SELF.NABMBAR := NABMBAR
  148. END Constr;
  149. PROCEDURE RegRead16(offset : LONGINT): LONGINT;
  150. BEGIN{EXCLUSIVE}
  151. ASSERT(BusyWait());
  152. RETURN NAMBAR.RegRead16(offset)
  153. END RegRead16;
  154. PROCEDURE RegWrite16(offset, value : LONGINT);
  155. BEGIN{EXCLUSIVE}
  156. ASSERT(BusyWait());
  157. NAMBAR.RegWrite16(offset, value)
  158. END RegWrite16;
  159. (* Read semaphore register. If 0 is returned access to the AC97 I/O space
  160. is granted. If 1 is returned AC97 Codec is blocked. Then retry until timer
  161. of 2 ms times out. *)
  162. PROCEDURE BusyWait() : BOOLEAN;
  163. VAR t: Kernel.MilliTimer;
  164. BEGIN
  165. Kernel.SetTimer(t, 2);
  166. WHILE ~Kernel.Expired(t) DO
  167. IF ~(0 IN SYSTEM.VAL(SET, NABMBAR.RegRead8(34H))) THEN
  168. RETURN TRUE
  169. END
  170. END;
  171. RETURN FALSE
  172. END BusyWait;
  173. (* Writing any value to this register restes the AC97 Codec *)
  174. PROCEDURE Reset*;
  175. BEGIN
  176. RegWrite16(AC97ResetReg, 1);
  177. END Reset;
  178. PROCEDURE WriteCodec*;
  179. BEGIN
  180. (* Set volumes *)
  181. RegWrite16(AC97ResetReg, 0001H); (* Reset *)
  182. RegWrite16(AC97MasterVolReg, MasterVolume); (* Master volume *)
  183. RegWrite16(AC97AuxVolReg, 8000H); (* AUX volume *)
  184. RegWrite16(AC97MonoVolReg, 8000H); (* Mono volume *)
  185. RegWrite16(AC97PCMOutVolReg, 1818H); (* PCM Out Volume *)
  186. (* Enable variable DAC rate *)
  187. RegWrite16(AC97StatCtrlReg, 0001H)
  188. END WriteCodec;
  189. PROCEDURE SetDacRate*(rate : LONGINT);
  190. BEGIN
  191. RegWrite16(AC97DacRateReg, rate)
  192. END SetDacRate;
  193. PROCEDURE SetAdcRate*(rate : LONGINT);
  194. BEGIN
  195. RegWrite16(AC97AdcRateReg, rate)
  196. END SetAdcRate;
  197. END AC97Control;
  198. TYPE
  199. (**
  200. Driver object is the core of the driver. It is responsible for creating
  201. new objects, setting registers, returning channels, handling interrupts.
  202. *)
  203. Driver = OBJECT(SoundDevices.Driver)
  204. VAR
  205. base : LONGINT;
  206. irq : LONGINT;
  207. AC97 : AC97Control;
  208. NAMBAR, NABMBAR : PCIAudioControl;
  209. DMAIn, DMAOut : DMABufferDescriptorList;
  210. firstPlayChannel : PlayChannelList;
  211. firstRecChannel : RecChannelList;
  212. mixerChannelList : ARRAY NofMixerChannels OF MixerChannel;
  213. firstMixerChangedProc : MixerChangedProcList;
  214. playCurrentBufferIndex, recCurrentBufferIndex : LONGINT;
  215. playLastValidIndex, recLastValidIndex : LONGINT;
  216. playBuffer, recBuffer, silentBuffer : SoundDevices.Buffer;
  217. playSamplingRate : ARRAY 32 OF LONGINT;
  218. recSamplingRate : LONGINT;
  219. playCurrentSamplingRate : LONGINT;
  220. playBufferList, recBufferList : ARRAY 32 OF SoundDevices.Buffer;
  221. playInterrupt, recInterrupt : BOOLEAN;
  222. PROCEDURE &Constr*(nambar, nabmbar, irq : LONGINT);
  223. VAR
  224. res : WORD;
  225. DMAInPhysAdr, DMAOutPhysAdr: LONGINT;
  226. i : LONGINT;
  227. BEGIN
  228. SELF.base := base;
  229. SELF.irq := irq;
  230. (* Create PCI Audio Control Object *)
  231. NEW(NAMBAR, nambar);
  232. (* Create PCI Audio Control Object *)
  233. NEW(NABMBAR, nabmbar);
  234. (* Create AC97 Control Object *)
  235. NEW(AC97, NAMBAR, NABMBAR);
  236. (* Reset registers *)
  237. NABMBAR.RegWrite8(BMRInBase + BMRCtrlReg, 02H);
  238. NABMBAR.RegWrite8(BMROutBase + BMRCtrlReg, 02H);
  239. (* Write AC97 Codec *)
  240. AC97.Reset;
  241. AC97.WriteCodec;
  242. NEW(DMAIn);
  243. NEW(DMAOut);
  244. (* Size is 32 entries * 2 fields * 8 byte = 256 byte *)
  245. DMAInPhysAdr := GetPhysicalAdr(ADDRESSOF(DMAIn[0]), 256);
  246. DMAOutPhysAdr := GetPhysicalAdr(ADDRESSOF(DMAOut[0]), 256);
  247. (* Read Buffer Descriptor List Base Addresses *)
  248. NABMBAR.RegWrite32(BMRInBase + BMRBufferDescriptorBaseAddress, DMAInPhysAdr);
  249. NABMBAR.RegWrite32(BMROutBase + BMRBufferDescriptorBaseAddress, DMAOutPhysAdr);
  250. IF DebugDMAAddess IN Debug THEN
  251. KernelLog.String("DMA In Physical Address: "); KernelLog.Int(DMAInPhysAdr, 5); KernelLog.Ln;
  252. KernelLog.String("DMA Out Physical Address: "); KernelLog.Int(DMAOutPhysAdr, 5); KernelLog.Ln
  253. END;
  254. (* Create buffers for playing and recording *)
  255. FOR i := 0 TO 31 DO
  256. NEW(playBufferList[i]); NEW(recBufferList[i]);
  257. NEW(playBufferList[i].data, BufferSize); NEW(recBufferList[i].data, BufferSize);
  258. playBufferList[i].len := BufferSize; recBufferList[i].len := BufferSize;
  259. DMAOut[i].addr := GetPhysicalAdr(
  260. ADDRESSOF(playBufferList[i].data[0]), BufferSize);
  261. DMAIn[i].addr := GetPhysicalAdr(
  262. ADDRESSOF(recBufferList[i].data[0]), BufferSize);
  263. DMAOut[i].CmdAndLength := LSH(BufferSize, -1);
  264. SetBit(DMAOut[i].CmdAndLength, 31);
  265. DMAIn[i].CmdAndLength := LSH(BufferSize, -1);
  266. SetBit(DMAIn[i].CmdAndLength, 31)
  267. END;
  268. (* Create silent buffer *)
  269. NEW(silentBuffer);
  270. NEW(silentBuffer.data, BufferSize);
  271. FOR i := 0 TO BufferSize - 1 DO silentBuffer.data[i] := silentData END;
  272. silentBuffer.len := BufferSize;
  273. (* Set initial samplings rate *)
  274. FOR i := 0 TO 31 DO playSamplingRate[i] := 48000 END;
  275. playCurrentSamplingRate := 48000;
  276. (* Choose mic as record channel *)
  277. AC97.RegWrite16(AC97RecordSelectReg, 0000H);
  278. (* Create mixer channels *)
  279. NEW(mixerChannelList[0], SELF, AC97MasterVolReg, FALSE, "MasterOut", "Master output mixer channel");
  280. NEW(mixerChannelList[1], SELF, AC97RecordGainReg, FALSE, "MasterIn", "Master input mixer channel");
  281. NEW(mixerChannelList[2], SELF, AC97LineInVolReg, TRUE, "LineIn", "LineIn mixer channel");
  282. NEW(mixerChannelList[3], SELF, AC97PCMOutVolReg, FALSE, "PCMOut", "PCM out mixer channel");
  283. NEW(mixerChannelList[4], SELF, AC97CDVolReg, TRUE, "CD", "CD input mixer channel");
  284. NEW(mixerChannelList[5], SELF, AC97MicVolReg, FALSE, "Mic", "Microphone mixer channel");
  285. mixerChannelList[5].SetVolume(0); (* cancel noise that might come from the mic *)
  286. (* Give master volume some more gas *)
  287. mixerChannelList[0].SetVolume(MasterVolume);
  288. (* Install Objects interrupt handler *)
  289. Objects.InstallHandler(HandleInterrupt, Machine.IRQ0+irq);
  290. (* Register Driver in SoundDevices *)
  291. SoundDevices.devices.Add(SELF, res);
  292. ASSERT(res = Plugins.Ok);
  293. (* Update driver table *)
  294. SoundDevices.devices.GetAll(DriverTab);
  295. (* Enable DMA
  296. Set the PCM Control Register
  297. Read more about it in the Intel documentation
  298. 0001 1101 = 1Dh
  299. 0000 0001 = 01h
  300. The Current Buffer Position seems to turn around when it reaches zero. This will result in a
  301. negative number counting backwards. It is not that interesting hearing the kernel code played
  302. at your loudspeakers, but who knows, maybe you hear satanic words if you play it backwards
  303. through the soundcard. I have to try it with the Windows...
  304. It is said that if you play the Windows install CD backwards you hear satanic words. What is
  305. that to care about. I mean, if you play it forwards it installs Windows!
  306. 11H will enable DMA and raise an interrupt when a buffer is completed.
  307. *)
  308. Enable
  309. END Constr;
  310. PROCEDURE Finalize;
  311. BEGIN
  312. Disable;
  313. (* Reset AC97 Codec *)
  314. AC97.Reset;
  315. (* Remove interrupt handler *)
  316. Objects.RemoveHandler(HandleInterrupt, Machine.IRQ0+irq);
  317. (* Remove registered driver *)
  318. SoundDevices.devices.Remove(SELF);
  319. (* Update driver table *)
  320. SoundDevices.devices.GetAll(DriverTab)
  321. END Finalize;
  322. PROCEDURE HandleInterrupt;
  323. VAR
  324. status : LONGINT;
  325. interrupt : LONGINT;
  326. BEGIN
  327. interrupt := NABMBAR.RegRead32(BMRGlobalStatusReg);
  328. (* Did a PCM Out interrupt occur? *)
  329. IF (6 IN SYSTEM.VAL(SET, interrupt)) THEN
  330. (*
  331. Do a 32 bit read over Current Index, Last Valid Index and Status Register
  332. starting at Current Buffer Index.
  333. *)
  334. status := NABMBAR.RegRead32(BMROutBase + BMRCurrentIndexReg);
  335. (* Did a Buffer completion interrupt occur? *)
  336. IF (19 IN SYSTEM.VAL(SET, status)) THEN
  337. BEGIN {EXCLUSIVE}
  338. playLastValidIndex := (SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, status)*{0..7}) + 2) MOD 32;
  339. playInterrupt := TRUE;
  340. END;
  341. END;
  342. (* Clear the interrupt *)
  343. NABMBAR.RegWrite16(BMROutBase + BMRStatusReg, 0FFH);
  344. END;
  345. (* Did a PCM In interrupt occur? *)
  346. IF (5 IN SYSTEM.VAL(SET, interrupt)) THEN
  347. (*
  348. Do a 32 bit read over Current Index, Last Valid Index and Status Register
  349. starting at Current Buffer Index.
  350. *)
  351. status := NABMBAR.RegRead32(BMRInBase + BMRCurrentIndexReg);
  352. (* Did a Buffer completion interrupt occur? *)
  353. IF (19 IN SYSTEM.VAL(SET, status)) THEN
  354. BEGIN {EXCLUSIVE}
  355. recLastValidIndex := (SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, status)*{0..7}) + 2) MOD 32;
  356. recInterrupt := TRUE;
  357. END;
  358. END;
  359. (* Clear the interrupt *)
  360. NABMBAR.RegWrite16(BMRInBase + BMRStatusReg, 0FFH)
  361. END;
  362. END HandleInterrupt;
  363. (* Enqueues a new buffer for DMA to fetch, and updates last valid buffer index. *)
  364. PROCEDURE QueueBuffer*;
  365. VAR
  366. noOfSamples : LONGINT;
  367. BEGIN
  368. MixBuffers;
  369. DMAOut[playLastValidIndex].addr := GetPhysicalAdr(
  370. ADDRESSOF(playBufferList[playCurrentBufferIndex].data[0]), BufferSize);
  371. noOfSamples := LSH(playBufferList[playCurrentBufferIndex].len, -1);
  372. DMAOut[playLastValidIndex].CmdAndLength := noOfSamples;
  373. SetBit(DMAOut[playLastValidIndex].CmdAndLength, 31);
  374. NABMBAR.RegWrite8(BMROutBase + BMRLastValidIndexReg, playLastValidIndex)
  375. END QueueBuffer;
  376. (* Mix all active channels into one single buffer. *)
  377. PROCEDURE MixBuffers;
  378. VAR
  379. item : PlayChannelList;
  380. buffer : SoundDevices.Buffer;
  381. silent : BOOLEAN;
  382. BEGIN
  383. playCurrentBufferIndex := playLastValidIndex;
  384. playBuffer := NIL;
  385. playSamplingRate[playCurrentBufferIndex] := 1;
  386. silent := TRUE;
  387. (* Set max sampling rate *)
  388. item := firstPlayChannel;
  389. WHILE item # NIL DO
  390. IF item.channel.state = StatePlaying THEN
  391. playSamplingRate[playCurrentBufferIndex] :=
  392. Max(playSamplingRate[playCurrentBufferIndex], item.channel.samplingRate);
  393. silent := FALSE
  394. END;
  395. item := item.next
  396. END;
  397. (* Mix buffers *)
  398. item := firstPlayChannel;
  399. WHILE item # NIL DO
  400. IF item.channel.state = StatePlaying THEN
  401. item.channel.PrepareData(playSamplingRate[playCurrentBufferIndex]);
  402. buffer := item.channel.ReturnBuffer();
  403. MixTwo(playBuffer, buffer);
  404. END;
  405. item := item.next
  406. END;
  407. (* If no active channel is found then outpus silent data *)
  408. IF silent THEN
  409. playSamplingRate[playCurrentBufferIndex] := 48000;
  410. playBuffer := silentBuffer
  411. END;
  412. (* We are always two steps ahead of DMA *)
  413. IF playSamplingRate[(playCurrentBufferIndex-2) MOD 32] # playCurrentSamplingRate THEN
  414. playCurrentSamplingRate := playSamplingRate[(playCurrentBufferIndex-2) MOD 32];
  415. AC97.SetDacRate(playCurrentSamplingRate)
  416. END;
  417. SYSTEM.MOVE(
  418. ADDRESSOF(playBuffer.data[0]),
  419. ADDRESSOF(playBufferList[playCurrentBufferIndex].data[0]),
  420. BufferSize);
  421. playBufferList[playCurrentBufferIndex].len := playBuffer.len;
  422. END MixBuffers;
  423. (* Mix two buffers of the same sampling rate *)
  424. PROCEDURE MixTwo(VAR buffer : SoundDevices.Buffer; buffer2 : SoundDevices.Buffer);
  425. VAR
  426. mix, sample1, sample2 : LONGINT;
  427. i : LONGINT;
  428. BEGIN
  429. (* First buffer don't have to be mixed *)
  430. IF buffer = NIL THEN
  431. buffer := buffer2;
  432. RETURN;
  433. END;
  434. ASSERT(buffer.len = buffer2.len);
  435. FOR i := 0 TO buffer.len-1 DO
  436. (* Lineary interpolate two samples *)
  437. sample1 := SYSTEM.VAL(INTEGER, buffer.data[i]);
  438. sample2 := SYSTEM.VAL(INTEGER, buffer2.data[i]);
  439. (* Lower volume to try to avoid clipping *)
  440. mix := sample1+sample2;
  441. (* Clip *)
  442. IF mix > MAX(INTEGER) THEN
  443. mix := MAX(INTEGER);
  444. END;
  445. IF mix < MIN(INTEGER) THEN
  446. mix := MIN(INTEGER);
  447. END;
  448. buffer.data[i] := CHR(mix);
  449. buffer.data[i+1] := CHR(LSH(mix, -8));
  450. INC(i)
  451. END
  452. END MixTwo;
  453. (* Procedure to return recorded data *)
  454. PROCEDURE ReturnBuffers*;
  455. VAR
  456. item : RecChannelList;
  457. BEGIN
  458. (* Last valid index is always 3 steps ahead of current buffer index *)
  459. recCurrentBufferIndex := (recLastValidIndex - 3) MOD 32;
  460. item := firstRecChannel;
  461. WHILE item # NIL DO
  462. IF item.channel.state = StateRecording THEN
  463. item.channel.PrepareData(recBufferList[recCurrentBufferIndex], recSamplingRate)
  464. END;
  465. item := item.next
  466. END;
  467. NABMBAR.RegWrite8(BMRInBase + BMRLastValidIndexReg, recLastValidIndex)
  468. END ReturnBuffers;
  469. PROCEDURE Init*;
  470. BEGIN
  471. SetName("i810 Sound driver");
  472. desc := "Sound driver for the Intel 810 chips"
  473. END Init;
  474. PROCEDURE Enable*;
  475. BEGIN
  476. (* PCM Out *)
  477. IF TestBit(NABMBAR.RegRead16(BMROutBase + BMRStatusReg), 0) THEN
  478. NABMBAR.RegWrite8(BMROutBase + BMRCtrlReg, 11H)
  479. END;
  480. (* PCM In *)
  481. IF TestBit(NABMBAR.RegRead16(BMRInBase + BMRStatusReg), 0) THEN
  482. NABMBAR.RegWrite8(BMRInBase + BMRCtrlReg, 11H)
  483. END
  484. END Enable;
  485. PROCEDURE Disable*;
  486. BEGIN
  487. (* PCM Out *)
  488. NABMBAR.RegWrite16(BMROutBase + BMRStatusReg, 0002H);
  489. NABMBAR.RegWrite8(BMROutBase + BMRCtrlReg, 00H);
  490. (* PCM In *)
  491. NABMBAR.RegWrite16(BMRInBase + BMRStatusReg, 0002H);
  492. NABMBAR.RegWrite8(BMRInBase + BMRCtrlReg, 00H)
  493. END Disable;
  494. PROCEDURE NofNativeFrequences() : LONGINT;
  495. BEGIN
  496. RETURN 0;
  497. END NofNativeFrequences;
  498. PROCEDURE GetNativeFrequency*(nr : LONGINT) : LONGINT;
  499. BEGIN
  500. RETURN 48000;
  501. END GetNativeFrequency;
  502. PROCEDURE NofSamplingResolutions*() : LONGINT;
  503. BEGIN
  504. RETURN 2 (* 16 Bit and 8 Bit *)
  505. END NofSamplingResolutions;
  506. PROCEDURE GetSamplingResolution(nr : LONGINT) : LONGINT;
  507. BEGIN
  508. ASSERT((nr >= 0) & (nr <2));
  509. IF nr = 0 THEN
  510. RETURN 16
  511. ELSE
  512. RETURN 8
  513. END;
  514. END GetSamplingResolution;
  515. PROCEDURE NofSubChannelSettings*() : LONGINT;
  516. BEGIN
  517. RETURN 2 (* Mono and stereo *)
  518. END NofSubChannelSettings;
  519. PROCEDURE GetSubChannelSetting*(nr : LONGINT) : LONGINT;
  520. BEGIN
  521. ASSERT((nr >= 0) & (nr <= 2));
  522. IF nr = 0 THEN
  523. RETURN 1 (* Mono *)
  524. ELSE
  525. RETURN 2 (* Stereo *)
  526. END
  527. END GetSubChannelSetting;
  528. PROCEDURE NofWaveFormats*() : LONGINT;
  529. BEGIN
  530. RETURN 1 (* Only PCM *)
  531. END NofWaveFormats;
  532. PROCEDURE OpenPlayChannel*(VAR channel : SoundDevices.Channel; samplingRate, samplingResolution,
  533. nofSubChannels, format : LONGINT; VAR res : WORD);
  534. VAR
  535. playChannel : PlayChannel;
  536. sResolution : LONGINT;
  537. BEGIN {EXCLUSIVE}
  538. channel := NIL;
  539. (* Check for valid sample rate.
  540. All values < 7040 will be set to 7040. *)
  541. IF ~((samplingRate > 0) & (samplingRate <= 48000)) THEN
  542. res := SoundDevices.ResUnsupportedFrequency;
  543. RETURN
  544. END;
  545. (* Check for supported samplingResolution *)
  546. IF samplingResolution = 16 THEN
  547. sResolution := 0
  548. ELSIF samplingResolution = 8 THEN
  549. sResolution := 1
  550. ELSE
  551. res := SoundDevices.ResUnsupportedSamplingRes;
  552. RETURN
  553. END;
  554. (* Check for supported subchannel *)
  555. IF (nofSubChannels # 1) & (nofSubChannels # 2) THEN
  556. res := SoundDevices.ResUnsupportedSubChannels;
  557. RETURN
  558. END;
  559. (* Check for supported format *)
  560. IF format # SoundDevices.FormatPCM THEN
  561. res := SoundDevices.ResUnsupportedFormat;
  562. RETURN
  563. END;
  564. (* Fine, we passed all tests. Let's create a channel. *)
  565. NEW(playChannel, SELF, samplingRate, sResolution, nofSubChannels);
  566. channel := playChannel;
  567. AddPlayChannel(playChannel);
  568. IF TraceOpenChannel IN Debug THEN
  569. KernelLog.String("Open PlayChannel: "); KernelLog.Int(samplingRate, 1); KernelLog.String("Hz, ");
  570. KernelLog.Int(samplingResolution, 1); KernelLog.String("bit, ");
  571. KernelLog.Int(nofSubChannels, 1); KernelLog.String(" channel(s)"); KernelLog.Ln
  572. END;
  573. res := SoundDevices.ResOK
  574. END OpenPlayChannel;
  575. PROCEDURE RemovePlayChannel(channel : PlayChannel);
  576. VAR
  577. item : PlayChannelList;
  578. BEGIN
  579. item := firstPlayChannel;
  580. IF item # NIL THEN
  581. IF item.channel = channel THEN
  582. firstPlayChannel := item.next;
  583. RETURN
  584. END
  585. END;
  586. WHILE item.next # NIL DO
  587. IF item.next.channel = channel THEN
  588. item.next := item.next.next;
  589. RETURN
  590. END;
  591. item := item.next
  592. END
  593. END RemovePlayChannel;
  594. PROCEDURE AddPlayChannel(channel : PlayChannel);
  595. VAR
  596. item : PlayChannelList;
  597. BEGIN
  598. NEW(item);
  599. item.channel := channel;
  600. item.next := firstPlayChannel;
  601. firstPlayChannel := item
  602. END AddPlayChannel;
  603. PROCEDURE OpenRecordChannel*(VAR channel : SoundDevices.Channel; samplingRate, samplingResolution,
  604. nofSubChannels, format : LONGINT; VAR res : WORD);
  605. VAR
  606. recChannel : RecChannel;
  607. item : RecChannelList;
  608. sResolution : LONGINT;
  609. BEGIN {EXCLUSIVE}
  610. channel := NIL;
  611. (* Check for valid sample rate.
  612. All values < 7040 will be set to 7040. *)
  613. IF ~((samplingRate > 0) & (samplingRate <= 48000)) THEN
  614. res := SoundDevices.ResUnsupportedFrequency;
  615. RETURN
  616. END;
  617. (* Check for supported samplingResolution *)
  618. IF samplingResolution = 16 THEN
  619. sResolution := 0
  620. ELSIF samplingResolution = 8 THEN
  621. sResolution := 1
  622. ELSE
  623. res := SoundDevices.ResUnsupportedSamplingRes;
  624. RETURN
  625. END;
  626. (* Check for supported subchannel *)
  627. IF (nofSubChannels # 1) & (nofSubChannels # 2) THEN
  628. res := SoundDevices.ResUnsupportedSubChannels;
  629. RETURN
  630. END;
  631. (* Check for supported format *)
  632. IF format # SoundDevices.FormatPCM THEN
  633. res := SoundDevices.ResUnsupportedFormat;
  634. RETURN;
  635. END;
  636. (* Fine, we passed all tests. Let's create a channel. *)
  637. NEW(recChannel, SELF, samplingRate, sResolution, nofSubChannels);
  638. channel := recChannel;
  639. AddRecChannel(recChannel);
  640. IF TraceOpenChannel IN Debug THEN
  641. KernelLog.String("Open RecChannel: "); KernelLog.Int(samplingRate, 1); KernelLog.String("Hz, ");
  642. KernelLog.Int(samplingResolution, 1); KernelLog.String("bit, ");
  643. KernelLog.Int(nofSubChannels, 1); KernelLog.String(" channel(s)"); KernelLog.Ln
  644. END;
  645. (* Set max sampling rate *)
  646. recSamplingRate := 1;
  647. item := firstRecChannel;
  648. WHILE item # NIL DO
  649. recSamplingRate := Max(recSamplingRate, item.channel.samplingRate);
  650. item := item.next;
  651. END;
  652. recSamplingRate := samplingRate;
  653. AC97.SetAdcRate(recSamplingRate);
  654. res := SoundDevices.ResOK
  655. END OpenRecordChannel;
  656. PROCEDURE RemoveRecChannel(channel : RecChannel);
  657. VAR
  658. item : RecChannelList;
  659. BEGIN
  660. item := firstRecChannel;
  661. IF item # NIL THEN
  662. IF item.channel = channel THEN
  663. firstRecChannel := item.next;
  664. RETURN
  665. END
  666. END;
  667. WHILE item.next # NIL DO
  668. IF item.next.channel = channel THEN
  669. item.next := item.next.next;
  670. RETURN
  671. END;
  672. item := item.next
  673. END;
  674. END RemoveRecChannel;
  675. PROCEDURE AddRecChannel(channel : RecChannel);
  676. VAR
  677. item : RecChannelList;
  678. BEGIN
  679. NEW(item);
  680. item.channel := channel;
  681. item.next := firstRecChannel;
  682. firstRecChannel := item
  683. END AddRecChannel;
  684. PROCEDURE RegisterMixerChangeListener*(mixChangedProc : SoundDevices.MixerChangedProc);
  685. VAR
  686. item : MixerChangedProcList;
  687. BEGIN {EXCLUSIVE}
  688. ASSERT(mixChangedProc # NIL);
  689. NEW(item);
  690. item.mixerChangedProc := mixChangedProc;
  691. item.next := firstMixerChangedProc;
  692. firstMixerChangedProc := item
  693. END RegisterMixerChangeListener;
  694. PROCEDURE UnregisterMixerChangeListener*(mixChangeProc : SoundDevices.MixerChangedProc);
  695. VAR
  696. item : MixerChangedProcList;
  697. BEGIN {EXCLUSIVE}
  698. item := firstMixerChangedProc;
  699. (* No registered listeners *)
  700. IF item = NIL THEN
  701. RETURN;
  702. END;
  703. (* Check first entry *)
  704. IF item.mixerChangedProc = mixChangeProc THEN
  705. firstMixerChangedProc := item.next;
  706. IF DebugTraceListeners IN Debug THEN KernelLog.String("Removed mixerChangedProc"); KernelLog.Ln END;
  707. RETURN;
  708. END;
  709. WHILE (item.next # NIL) & (item.next.mixerChangedProc # mixChangeProc) DO
  710. item := item.next
  711. END;
  712. IF item.next # NIL THEN
  713. item.next := item.next.next;
  714. IF DebugTraceListeners IN Debug THEN KernelLog.String("Removed mixerChangedProc"); KernelLog.Ln END
  715. ELSE
  716. IF DebugTraceListeners IN Debug THEN KernelLog.String("Could not remove mixerChangeProc"); KernelLog.Ln END
  717. END;
  718. END UnregisterMixerChangeListener;
  719. PROCEDURE GetMixerChannel*(channelNr : LONGINT; VAR channel : SoundDevices.MixerChannel);
  720. BEGIN
  721. IF (channelNr >= 0) & (channelNr < NofMixerChannels) THEN
  722. channel := mixerChannelList[channelNr]
  723. ELSE
  724. channel := NIL
  725. END
  726. END GetMixerChannel;
  727. PROCEDURE GetNofMixerChannels*() : LONGINT;
  728. BEGIN
  729. RETURN NofMixerChannels
  730. END GetNofMixerChannels;
  731. BEGIN {ACTIVE}
  732. playInterrupt := FALSE;
  733. recInterrupt := FALSE;
  734. WHILE (TRUE) DO
  735. BEGIN {EXCLUSIVE}
  736. AWAIT(playInterrupt OR recInterrupt);
  737. END;
  738. IF playInterrupt THEN
  739. QueueBuffer;
  740. playInterrupt := FALSE;
  741. ELSIF recInterrupt THEN
  742. ReturnBuffers;
  743. recInterrupt := FALSE;
  744. END;
  745. END;
  746. END Driver;
  747. (**
  748. MixerChannel is a hardware mixer channel that control the
  749. AC97 chip. It can set volume for each channel.
  750. *)
  751. MixerChannel = OBJECT(SoundDevices.MixerChannel)
  752. VAR
  753. driver : Driver;
  754. name, desc : POINTER TO ARRAY OF CHAR;
  755. volumeReg : LONGINT;
  756. volume, muteVol : LONGINT;
  757. volBits : LONGINT;
  758. mute : BOOLEAN;
  759. PROCEDURE &Constr*(driver : Driver; volumeReg : LONGINT; mute : BOOLEAN; name, desc : ARRAY OF CHAR);
  760. VAR
  761. i : LONGINT;
  762. BEGIN
  763. SELF.driver := driver;
  764. SELF.volumeReg := volumeReg;
  765. SELF.mute := mute;
  766. NEW(SELF.name, LEN(name));
  767. FOR i := 0 TO LEN(name) - 1 DO
  768. SELF.name^[i] := name[i];
  769. END;
  770. NEW(SELF.desc, LEN(desc));
  771. FOR i := 0 TO LEN(desc) - 1 DO
  772. SELF.desc^[i] := desc[i]
  773. END;
  774. (* Get number of volume bits *)
  775. (* Set first 6 bits and shift until a '0' appears *)
  776. driver.AC97.RegWrite16(volumeReg, 803FH);
  777. volume := driver.AC97.RegRead16(volumeReg);
  778. volBits := 0;
  779. WHILE ODD(volume) DO
  780. volume := LSH(volume, -1);
  781. INC(volBits)
  782. END;
  783. (* 64 seems to be a reasonable init volume *)
  784. SetVolume(InitVolume)
  785. END Constr;
  786. PROCEDURE GetName*(VAR name : ARRAY OF CHAR);
  787. BEGIN
  788. COPY(SELF.name^, name)
  789. END GetName;
  790. PROCEDURE GetDesc*(VAR desc : ARRAY OF CHAR);
  791. BEGIN
  792. COPY(SELF.desc^, desc)
  793. END GetDesc;
  794. PROCEDURE SetVolume*(volume : LONGINT);
  795. BEGIN {EXCLUSIVE}
  796. ASSERT((volume >= 0) & (volume <= 255));
  797. SELF.volume := volume;
  798. (* Shift away "overflow" bits *)
  799. volume := 255 - volume;
  800. volume := LSH(volume, volBits - 8);
  801. volume := volume + LSH(volume, 8);
  802. IF SELF.mute THEN SetBit(volume, 15) END;
  803. IF Boost THEN SetBit(volume, 6) END;
  804. driver.AC97.RegWrite16(volumeReg, volume);
  805. CallMixerListeners
  806. END SetVolume;
  807. PROCEDURE GetVolume*() : LONGINT;
  808. BEGIN
  809. RETURN SELF.volume
  810. END GetVolume;
  811. (* Volume has to be 0 <= volume < 256 *)
  812. PROCEDURE SetMute*(mute : BOOLEAN);
  813. VAR
  814. volume : LONGINT;
  815. BEGIN {EXCLUSIVE}
  816. SELF.mute := mute;
  817. IF mute THEN muteVol := volume; volume := 0
  818. ELSE volume := muteVol END;
  819. (* volume := driver.AC97.RegRead16(volumeReg);
  820. SetBit(volume, 15);
  821. driver.AC97.RegWrite16(volume, volumeReg);
  822. *) CallMixerListeners
  823. END SetMute;
  824. PROCEDURE GetIsMute*() : BOOLEAN;
  825. BEGIN
  826. RETURN SELF.mute;
  827. END GetIsMute;
  828. PROCEDURE CallMixerListeners;
  829. VAR
  830. item : MixerChangedProcList;
  831. BEGIN
  832. item := driver.firstMixerChangedProc;
  833. WHILE item # NIL DO
  834. item.mixerChangedProc(SELF);
  835. item := item.next
  836. END
  837. END CallMixerListeners;
  838. END MixerChannel;
  839. (**
  840. Audio player/recorder asks driver for a channel. Through the channel are data
  841. enqueued for playing or recording. Software mixing of volume i possible.
  842. *)
  843. Channel = OBJECT(SoundDevices.Channel)
  844. VAR
  845. driver : Driver;
  846. samplingRate, samplingResolution, nofSubChannels : LONGINT;
  847. bufferListener : SoundDevices.BufferListener;
  848. firstBuffer, lastBuffer : BufferList;
  849. playRecBuffer : SoundDevices.Buffer;
  850. firstBufferPos : LONGINT;
  851. volume : LONGINT;
  852. state : LONGINT;
  853. PROCEDURE &Constr*(driver : Driver; samplingRate, samplingResolution, nofSubChannels : LONGINT);
  854. BEGIN
  855. SELF.driver := driver;
  856. SELF.samplingRate := samplingRate;
  857. SELF.samplingResolution := samplingResolution;
  858. SELF.nofSubChannels := nofSubChannels;
  859. NEW(playRecBuffer);
  860. NEW(playRecBuffer.data, BufferSize);
  861. playRecBuffer.len := BufferSize;
  862. (* Set volume to max. Software software mixing only wastes data. *)
  863. SetVolume(255)
  864. END Constr;
  865. PROCEDURE GetChannelKind*() : LONGINT;
  866. BEGIN
  867. HALT(99) (* ABSTRACT *)
  868. END GetChannelKind;
  869. PROCEDURE SetVolume*(volume : LONGINT);
  870. BEGIN
  871. SELF.volume := volume
  872. END SetVolume;
  873. (* Linear volume *)
  874. PROCEDURE SampleSetVolume(VAR sample : Sample);
  875. VAR
  876. left, right : LONGINT;
  877. volume : LONGINT;
  878. BEGIN
  879. volume := SELF.volume;
  880. IF (volume < 0) THEN volume := 0 END;
  881. IF (volume > 255) THEN volume := 255 END;
  882. left := SYSTEM.VAL(INTEGER, sample);
  883. right := SYSTEM.VAL(INTEGER, sample[2]);
  884. (* Multiply volume with a number between 0 and 1. *)
  885. left := left * volume DIV 256;
  886. right := right * volume DIV 256;
  887. sample[0] := CHR(left);
  888. sample[1] := CHR(LSH(left, -8));
  889. sample[2] := CHR(right);
  890. sample[3] := CHR(LSH(right, -8))
  891. END SampleSetVolume;
  892. PROCEDURE GetVolume*() : LONGINT;
  893. BEGIN
  894. RETURN SELF.volume
  895. END GetVolume;
  896. PROCEDURE GetPosition*() : LONGINT;
  897. BEGIN
  898. RETURN firstBufferPos
  899. END GetPosition;
  900. PROCEDURE RegisterBufferListener*(bufferListener : SoundDevices.BufferListener);
  901. BEGIN {EXCLUSIVE}
  902. SELF.bufferListener := bufferListener
  903. END RegisterBufferListener;
  904. PROCEDURE QueueBuffer*(x : SoundDevices.Buffer);
  905. VAR
  906. bufferListItem : BufferList;
  907. BEGIN
  908. NEW(bufferListItem);
  909. bufferListItem.buffer := x;
  910. IF firstBuffer = NIL THEN
  911. firstBuffer := bufferListItem
  912. ELSE
  913. lastBuffer.next := bufferListItem
  914. END;
  915. lastBuffer := bufferListItem
  916. END QueueBuffer;
  917. PROCEDURE ReturnBuffer*() : SoundDevices.Buffer;
  918. BEGIN
  919. RETURN playRecBuffer
  920. END ReturnBuffer;
  921. PROCEDURE Start*;
  922. BEGIN
  923. HALT(99) (* ABSTRACT *)
  924. END Start;
  925. PROCEDURE Pause*;
  926. BEGIN
  927. state := StatePaused
  928. END Pause;
  929. PROCEDURE Stop*;
  930. BEGIN
  931. state := StateStoped;
  932. ReturnAllBuffers;
  933. END Stop;
  934. PROCEDURE Close*;
  935. BEGIN
  936. HALT(99) (* ABSTRACT *)
  937. END Close;
  938. PROCEDURE CallBufferListener() : BOOLEAN;
  939. BEGIN
  940. IF bufferListener = NIL THEN
  941. IF firstBuffer # NIL THEN
  942. firstBuffer := firstBuffer.next
  943. END;
  944. firstBufferPos := 0;
  945. RETURN FALSE
  946. END;
  947. bufferListener(firstBuffer.buffer);
  948. firstBuffer := firstBuffer.next;
  949. firstBufferPos := 0;
  950. RETURN TRUE
  951. END CallBufferListener;
  952. PROCEDURE ReturnAllBuffers;
  953. VAR
  954. item : BufferList;
  955. BEGIN {EXCLUSIVE}
  956. IF bufferListener = NIL THEN RETURN END;
  957. item := firstBuffer;
  958. WHILE item # NIL DO
  959. bufferListener(item.buffer);
  960. item := item.next
  961. END;
  962. firstBuffer := NIL
  963. END ReturnAllBuffers;
  964. END Channel;
  965. PlayChannel = OBJECT(Channel);
  966. PROCEDURE &ConstrPlay*(driver : Driver; samplingRate, samplingResolution, nofSubChannels : LONGINT);
  967. BEGIN
  968. Constr(driver, samplingRate, samplingResolution, nofSubChannels);
  969. END ConstrPlay;
  970. PROCEDURE Start*;
  971. BEGIN
  972. ASSERT(state # StateClosed);
  973. state := StatePlaying;
  974. driver.Enable;
  975. END Start;
  976. PROCEDURE Close*;
  977. BEGIN
  978. Stop;
  979. state := StateClosed;
  980. driver.RemovePlayChannel(SELF)
  981. END Close;
  982. (*
  983. 1) PCM Out Interrupt -> Driver::QueueBuffer -> Driver::MixBuffers -> PlayChannel::PrepareData
  984. 2) Driver::MixBuffer -> PlayChannel::ReturnBuffer
  985. Prepare data into playRecBuffer. That buffer is then read by Driver::MixBuffers which mixes
  986. several channels into one channel, which will be enqueued for DMA to read and play.
  987. WavePlayer enqueues a buffer the the channel. When this channel has emptied the buffer
  988. it calls the registered buffer listener and asks the player to enqueue another buffer.
  989. *)
  990. PROCEDURE PrepareData*(toRate : LONGINT);
  991. VAR
  992. playRecBufferPos : LONGINT;
  993. sample : Sample;
  994. srate : LONGINT;
  995. BEGIN {EXCLUSIVE}
  996. srate := 0;
  997. WHILE (firstBuffer # NIL) & (playRecBufferPos < BufferSize) DO
  998. (* Upsampling. If srate > torate then we insert the sample,
  999. else we strech buffer by inserting silent data. *)
  1000. srate := srate + samplingRate;
  1001. IF (srate >= toRate) THEN
  1002. srate := srate MOD toRate;
  1003. (* 16 bit stereo *)
  1004. IF (samplingResolution = 0) & (nofSubChannels = 2) THEN
  1005. sample[0] := firstBuffer.buffer.data[firstBufferPos];
  1006. sample[1] := firstBuffer.buffer.data[firstBufferPos+1];
  1007. sample[2] := firstBuffer.buffer.data[firstBufferPos+2];
  1008. sample[3] := firstBuffer.buffer.data[firstBufferPos+3];
  1009. INC(firstBufferPos, 4);
  1010. (* 16 bit mono *)
  1011. ELSIF (samplingResolution = 0) & (nofSubChannels = 1) THEN
  1012. sample[0] := firstBuffer.buffer.data[firstBufferPos];
  1013. sample[1] := firstBuffer.buffer.data[firstBufferPos+1];
  1014. MonoToStereo(sample);
  1015. INC(firstBufferPos, 2);
  1016. (* 8 bit stereo *)
  1017. ELSIF (samplingResolution = 1) & (nofSubChannels = 2) THEN
  1018. sample[0] := firstBuffer.buffer.data[firstBufferPos];
  1019. sample[1] := firstBuffer.buffer.data[firstBufferPos+1];
  1020. EightToSixten(sample);
  1021. INC(firstBufferPos, 2);
  1022. (* 8 bit stereo *)
  1023. ELSIF (samplingResolution = 1) & (nofSubChannels = 1) THEN
  1024. sample[0] := firstBuffer.buffer.data[firstBufferPos];
  1025. EightToSixten(sample);
  1026. MonoToStereo(sample);
  1027. INC(firstBufferPos);
  1028. (* Unsupported bitrate and no of channels *)
  1029. ELSE
  1030. KernelLog.Int(samplingResolution, 1); KernelLog.String(" bit, ");
  1031. KernelLog.Int(nofSubChannels, 1); KernelLog.String(" channels are not supported");
  1032. HALT(99)
  1033. END;
  1034. SampleSetVolume(sample);
  1035. playRecBuffer.data[playRecBufferPos] := sample[0];
  1036. playRecBuffer.data[playRecBufferPos+1] := sample[1];
  1037. playRecBuffer.data[playRecBufferPos+2] := sample[2];
  1038. playRecBuffer.data[playRecBufferPos+3] := sample[3];
  1039. INC(playRecBufferPos, 4);
  1040. (* End of queue buffer *)
  1041. IF firstBufferPos >= firstBuffer.buffer.len THEN
  1042. IF ~CallBufferListener() THEN
  1043. OutputSilentData(playRecBufferPos);
  1044. RETURN
  1045. END;
  1046. END;
  1047. (* Insert silent sample *)
  1048. ELSE
  1049. (*KernelLog.String("Upsample"); KernelLog.Ln;*)
  1050. playRecBuffer.data[playRecBufferPos] := CHR(0);
  1051. playRecBuffer.data[playRecBufferPos+1] := CHR(0);
  1052. playRecBuffer.data[playRecBufferPos+2] := CHR(0);
  1053. playRecBuffer.data[playRecBufferPos+3] := CHR(0);
  1054. INC(playRecBufferPos, 4);
  1055. END;
  1056. END;
  1057. (* If buffer is not filled up then output silent data *)
  1058. OutputSilentData(playRecBufferPos)
  1059. END PrepareData;
  1060. (* 8 bit => 16 bit conversion *)
  1061. PROCEDURE EightToSixten(VAR sample : Sample);
  1062. BEGIN
  1063. sample[3] := CHR(ORD(sample[1])-128);
  1064. sample[2] := CHR(0);
  1065. sample[1] := CHR(ORD(sample[0])-128);
  1066. sample[0] := CHR(0)
  1067. END EightToSixten;
  1068. (* mono => stereo conversion *)
  1069. PROCEDURE MonoToStereo(VAR sample : Sample);
  1070. BEGIN
  1071. sample[2] := sample[0];
  1072. sample[3] := sample[1]
  1073. END MonoToStereo;
  1074. (* If there is no more data to fill up playRecBuffer with we output silent data. *)
  1075. PROCEDURE OutputSilentData(playRecBufferPos : LONGINT);
  1076. BEGIN
  1077. WHILE (playRecBufferPos < BufferSize) DO
  1078. playRecBuffer.data[playRecBufferPos] := silentData;
  1079. INC(playRecBufferPos, 1)
  1080. END
  1081. END OutputSilentData;
  1082. END PlayChannel;
  1083. RecChannel = OBJECT(Channel)
  1084. PROCEDURE Start*;
  1085. BEGIN
  1086. ASSERT(state # StateClosed);
  1087. state := StateRecording;
  1088. driver.Enable
  1089. END Start;
  1090. PROCEDURE Close*;
  1091. BEGIN
  1092. Stop;
  1093. state := StateClosed;
  1094. driver.RemoveRecChannel(SELF);
  1095. END Close;
  1096. (*
  1097. PCM In Interrupt -> Driver::ReturnBuffers -> RecChannel::PrepareData
  1098. Prepares data and return it to RecPlayer
  1099. *)
  1100. PROCEDURE PrepareData(buffer : SoundDevices.Buffer; toRate : LONGINT);
  1101. VAR
  1102. bufferPos : LONGINT;
  1103. sample : Sample;
  1104. sampleSize : SHORTINT;
  1105. srate : LONGINT;
  1106. BEGIN
  1107. srate := 0;
  1108. bufferPos := 0;
  1109. WHILE (firstBuffer # NIL) & (bufferPos < buffer.len) DO
  1110. srate := srate + toRate;
  1111. IF (srate >= samplingRate) THEN
  1112. srate := srate MOD samplingRate;
  1113. sample[0] := buffer.data[bufferPos];
  1114. sample[1] := buffer.data[bufferPos+1];
  1115. sample[2] := buffer.data[bufferPos+2];
  1116. sample[3] := buffer.data[bufferPos+3];
  1117. (*SampleSetVolume(sample);*)
  1118. INC(bufferPos, 4);
  1119. (* 16 bit stereo *)
  1120. IF (samplingResolution = 0) & (nofSubChannels = 2) THEN
  1121. sampleSize := 4
  1122. (* 16 bit mono *)
  1123. ELSIF (samplingResolution = 0) & (nofSubChannels = 1) THEN
  1124. StereoToMono(sample);
  1125. sampleSize := 2
  1126. (* 8 bit stereo *)
  1127. ELSIF (samplingResolution = 1) & (nofSubChannels = 2) THEN
  1128. SixtenToEight(sample);
  1129. sampleSize := 2
  1130. (* 8 bit stereo *)
  1131. ELSIF (samplingResolution = 1) & (nofSubChannels = 1) THEN
  1132. StereoToMono(sample);
  1133. SixtenToEight(sample);
  1134. sampleSize := 1
  1135. (* Unsupported bitrate and no of channels *)
  1136. ELSE
  1137. KernelLog.Int(samplingResolution, 1); KernelLog.String(" bit, ");
  1138. KernelLog.Int(nofSubChannels, 1); KernelLog.String(" channels are not supported");
  1139. HALT(99)
  1140. END;
  1141. SYSTEM.MOVE(
  1142. ADDRESSOF(sample[0]),
  1143. ADDRESSOF(firstBuffer.buffer.data[0]) + firstBufferPos,
  1144. sampleSize);
  1145. INC(firstBufferPos, sampleSize);
  1146. (* If buffer is filled, then return buffer *)
  1147. IF firstBufferPos >= firstBuffer.buffer.len THEN
  1148. IF ~CallBufferListener() THEN
  1149. RETURN
  1150. END;
  1151. END;
  1152. (* Drop sample *)
  1153. ELSE
  1154. INC(bufferPos, 4);
  1155. END;
  1156. END;
  1157. END PrepareData;
  1158. (* stereo => mono conversion *)
  1159. PROCEDURE StereoToMono(VAR sample : Sample);
  1160. VAR
  1161. mix, left, right : LONGINT;
  1162. BEGIN
  1163. (* Take average of left and right channel *)
  1164. left := SYSTEM.VAL(INTEGER, sample);
  1165. right := SYSTEM.VAL(INTEGER, sample[2]);
  1166. mix := LSH(left + right, -1);
  1167. sample[0] := CHR(mix);
  1168. sample[1] := CHR(LSH(mix, -8))
  1169. END StereoToMono;
  1170. (* 16 bit => 8 bit conversion *)
  1171. PROCEDURE SixtenToEight(VAR sample : Sample);
  1172. BEGIN
  1173. sample[0] := CHR(ORD(sample[1]) - 128);
  1174. sample[1] := CHR(ORD(sample[3]) - 128)
  1175. END SixtenToEight;
  1176. END RecChannel;
  1177. VAR
  1178. silentData : CHAR;
  1179. firstDriver : DriverList;
  1180. DriverTab : Plugins.Table;
  1181. installedDriver : BOOLEAN;
  1182. PROCEDURE SetBit(VAR a : LONGINT; n : LONGINT);
  1183. BEGIN
  1184. ASSERT((n >= 0) & (n < 32));
  1185. INCL(SYSTEM.VAL(SET, a), n)
  1186. END SetBit;
  1187. (*
  1188. PROCEDURE ClearBit(VAR a : LONGINT; n : LONGINT);
  1189. VAR t : SET;
  1190. BEGIN
  1191. ASSERT((n >= 0) & (n < 32));
  1192. t := SYSTEM.VAL(SET, a);
  1193. EXCL(t, n);
  1194. a := SYSTEM.VAL(LONGINT, t)
  1195. END ClearBit;
  1196. *)
  1197. PROCEDURE TestBit(a, n : LONGINT) : BOOLEAN;
  1198. BEGIN
  1199. RETURN n IN SYSTEM.VAL(SET, a);
  1200. END TestBit;
  1201. (* Return maximum value *)
  1202. PROCEDURE Max(i, j : LONGINT) : LONGINT;
  1203. BEGIN
  1204. IF i > j THEN RETURN i ELSE RETURN j END
  1205. END Max;
  1206. (* Get physical address for DMA transfers *)
  1207. PROCEDURE GetPhysicalAdr(adr: ADDRESS; size : SIZE) : Machine.Address32;
  1208. VAR
  1209. physadr : Machine.Address32;
  1210. BEGIN
  1211. (* All data has to be continous in memory since DMA does not understand pages *)
  1212. physadr := Machine.Ensure32BitAddress (Machine.PhysicalAdr(adr, size));
  1213. ASSERT(physadr # Machine.NilAdr);
  1214. (* Address must be 8 byte align. See Intel programmes manual
  1215. for close details of the Buffer Description List *)
  1216. ASSERT(physadr MOD 4 = 0);
  1217. RETURN physadr
  1218. END GetPhysicalAdr;
  1219. (* Scan after PCI card and install it if found *)
  1220. PROCEDURE ScanPCI(vendid, devid : LONGINT);
  1221. VAR
  1222. index, res, i : LONGINT;
  1223. CmdReg : LONGINT;
  1224. bus, dev, fkt : LONGINT;
  1225. nambar, nabmbar, irq : LONGINT;
  1226. driver : Driver;
  1227. driverList : DriverList;
  1228. BEGIN
  1229. IF DebugInit IN Debug THEN KernelLog.String("Search for PCI card"); KernelLog.Ln END;
  1230. index := 0;
  1231. WHILE (index < 10) &
  1232. (PCI.FindPCIDevice(devid, vendid, index, bus, dev, fkt) = PCI.Done) DO
  1233. res := PCI.ReadConfigWord(bus, dev, fkt, PCI.CmdReg, i);
  1234. IF DebugInit IN Debug THEN
  1235. KernelLog.String("Vendor ID: "); KernelLog.Hex(vendid, 4); KernelLog.String("h"); KernelLog.Ln;
  1236. KernelLog.String("Device ID: "); KernelLog.Hex(devid, 4); KernelLog.String("h"); KernelLog.Ln;
  1237. KernelLog.String("Bus: "); KernelLog.Int(bus, 1); KernelLog.Ln;
  1238. KernelLog.String("Device: "); KernelLog.Int(dev, 1); KernelLog.Ln;
  1239. KernelLog.String("Function: "); KernelLog.Int(fkt, 1); KernelLog.Ln;
  1240. KernelLog.String("Command: "); KernelLog.Hex(i, 4); KernelLog.String("h"); KernelLog.Ln
  1241. END;
  1242. (* Get NAMBAR, Native Audio Mixer Base Address Register *)
  1243. res := PCI.ReadConfigDword(bus, dev, fkt, PCI.Adr0Reg, nambar);
  1244. ASSERT(res = PCI.Done);
  1245. ASSERT(ODD(nambar));
  1246. DEC(nambar, nambar MOD 16);
  1247. IF DebugInit IN Debug THEN
  1248. KernelLog.String("Native Audio Mastering Base Address (NAMABR): "); KernelLog.Int(nambar, 5); KernelLog.Ln
  1249. END;
  1250. (* Get NAMBMBAR, Native Audio Bus Mastering Base Address Register *)
  1251. res := PCI.ReadConfigDword(bus, dev, fkt, PCI.Adr1Reg, nabmbar);
  1252. ASSERT(res = PCI.Done);
  1253. ASSERT(ODD(nabmbar));
  1254. DEC(nabmbar, nabmbar MOD 16);
  1255. IF DebugInit IN Debug THEN
  1256. KernelLog.String("Native Audio Bus Mastering Base Address (NABMABR): "); KernelLog.Int(nabmbar, 5); KernelLog.Ln
  1257. END;
  1258. (* Get IRQ number *)
  1259. res := PCI.ReadConfigByte(bus, dev, fkt, PCI.IntlReg, irq);
  1260. ASSERT(res = PCI.Done);
  1261. IF DebugInit IN Debug THEN
  1262. KernelLog.String("IRQ: "); KernelLog.Int(irq, 2); KernelLog.Ln
  1263. END;
  1264. (* AC97 registers have to be enabled in the PCI Command Register *)
  1265. res := PCI.ReadConfigWord(bus, dev, fkt, PCI.CmdReg, CmdReg);
  1266. ASSERT(res = PCI.Done);
  1267. SetBit(CmdReg, 0);
  1268. res := PCI.WriteConfigWord(bus, dev, fkt, PCI.CmdReg, CmdReg);
  1269. ASSERT(res = PCI.Done);
  1270. (* Create Driver Object *)
  1271. NEW(driver, nambar, nabmbar, irq);
  1272. KernelLog.String("Intel 810 sound driver installed."); KernelLog.Ln;
  1273. NEW(driverList);
  1274. driverList.driver := driver;
  1275. driverList.next := firstDriver;
  1276. firstDriver := driverList;
  1277. INC(index)
  1278. END
  1279. END ScanPCI;
  1280. (* Install the driver *)
  1281. PROCEDURE Install*;
  1282. BEGIN {EXCLUSIVE}
  1283. (* Avoid multiple installation *)
  1284. IF ~installedDriver THEN
  1285. (* Scan for hardware *)
  1286. (* TODO - extend this list *)
  1287. ScanPCI(8086H,2485H);
  1288. ScanPCI(8086H, 24C5H);
  1289. ScanPCI(8086H, 266EH); (* Intel 915 chipset *)
  1290. (* These chips should work, but it hasn't been tested! *)
  1291. (* This list could probaly be further extended *)
  1292. IF (InsecureMode = TRUE) THEN
  1293. ScanPCI(8086H, 2415H);
  1294. ScanPCI(8086H, 2425H);
  1295. ScanPCI(8086H, 2445H);
  1296. ScanPCI(8086H, 24D5H);
  1297. ScanPCI(8086H, 7195H);
  1298. (*ScanPCI(8086H, 7012H);*)
  1299. END;
  1300. installedDriver := TRUE
  1301. END;
  1302. END Install;
  1303. (** Enable is a hardware enable. *)
  1304. PROCEDURE Enable*;
  1305. VAR
  1306. item : DriverList;
  1307. BEGIN
  1308. item := firstDriver;
  1309. WHILE item # NIL DO
  1310. item.driver.Enable;
  1311. item := item.next
  1312. END;
  1313. END Enable;
  1314. (** Enable is a hardware pause. *)
  1315. PROCEDURE Disable*;
  1316. VAR
  1317. item : DriverList;
  1318. BEGIN
  1319. item := firstDriver;
  1320. WHILE item # NIL DO
  1321. item.driver.Disable;
  1322. item := item.next
  1323. END;
  1324. END Disable;
  1325. (** Cleanup function called when the module is unloaded *)
  1326. PROCEDURE Cleanup;
  1327. VAR
  1328. item : DriverList;
  1329. BEGIN
  1330. item := firstDriver;
  1331. WHILE item # NIL DO
  1332. item.driver.Finalize;
  1333. item := item.next
  1334. END
  1335. END Cleanup;
  1336. BEGIN
  1337. Modules.InstallTermHandler(Cleanup)
  1338. END i810Sound.
  1339. PC.Compile * \s ~
  1340. System.Free i810Sound ~ (* Make sure module is unloaded *)
  1341. Aos.Call i810Sound.Install ~
  1342. Aos.Call i810Sound.Disable ~ (* pause all *)
  1343. Aos.Call i810Sound.Enable ~
  1344. Aos.Call PlayRecWave.Play x.wav ~
  1345. Aos.Call MP3Player.Play DATA:/SomeMp3File.Mp3 ~
  1346. System.Free i810Sound ~
  1347. SystemTools.Free i810Sound~