2 The contents of this file are subject to the AROS Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
3 http://www.aros.org/license.html
5 Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
6 ANY KIND, either express or implied. See the License for the specific language governing rights and
7 limitations under the License.
9 (C) Copyright xxxx-2009 Davy Wentzler.
10 (C) Copyright 2009-2010 Stephen Jones.
12 The Initial Developer of the Original Code is Davy Wentzler.
17 #include <exec/memory.h>
19 #include <proto/expansion.h>
20 #include <proto/dos.h>
21 #include <proto/exec.h>
22 #include <clib/alib_protos.h>
24 #include <aros/debug.h>
25 struct DosLibrary
* DOSBase
;
26 struct Library
*StdCBase
= NULL
;
32 #include "pci_wrapper.h"
37 struct DriverBase
* AHIsubBase
;
47 struct VendorDevice
*vendor_device_list
= NULL
;
48 static int vendor_device_list_size
= 0;
50 static void parse_config_file(void);
51 static int hex_char_to_int(char c
);
52 #define MAX_DEVICE_VENDORS 512
55 /******************************************************************************
56 ** Custom driver init *********************************************************
57 ******************************************************************************/
59 BOOL
DriverInit(struct DriverBase
* ahisubbase
)
61 struct HDAudioBase
* card_base
= (struct HDAudioBase
*) ahisubbase
;
62 struct PCIDevice
*dev
;
66 D(bug("[HDAudio] %s()\n", __PRETTY_FUNCTION__
));
67 AHIsubBase
= ahisubbase
;
69 DOSBase
= (struct DosLibrary
*) OpenLibrary(DOSNAME
, 37);
73 Req("Unable to open 'dos.library' version 37.\n");
78 StdCBase
= OpenLibrary("stdc.library", 0);
81 Req("Unable to open 'stdc.library'.\n");
86 if (!ahi_pci_init(ahisubbase
))
91 InitSemaphore(&card_base
->semaphore
);
93 /*** Count cards ***********************************************************/
95 vendor_device_list
= (struct VendorDevice
*) AllocVec(sizeof(struct VendorDevice
) * MAX_DEVICE_VENDORS
, MEMF_PUBLIC
| MEMF_CLEAR
);
97 // Add Intel ICH7 (used in iMica)
98 vendor_device_list
[0].vendor
= 0x8086;
99 vendor_device_list
[0].device
= 0x27D8;
100 vendor_device_list_size
++;
102 // Then parse the hdaudio.config file, if available in ENV:
105 D(bug("[HDAudio] vendor_device_list_size = %ld\n", vendor_device_list_size
));
107 card_base
->cards_found
= 0;
110 for (i
= 0; i
< vendor_device_list_size
; i
++)
112 dev
= ahi_pci_find_device(vendor_device_list
[i
].vendor
, vendor_device_list
[i
].device
, dev
);
116 D(bug("[HDAudio] Found device with vendor ID = %x, device ID = %x!(i = %d)\n", vendor_device_list
[i
].vendor
, vendor_device_list
[i
].device
, i
));
117 ++card_base
->cards_found
;
118 break; // stop at first found controller
123 FreeVec(vendor_device_list
);
125 // Fail if no hardware (prevents the audio modes from being added to
126 // the database if the driver cannot be used).
128 if (card_base
->cards_found
== 0)
130 D(bug("[HDAudio] No HDaudio controller found! :-(\n"));
135 /*** Allocate and init all cards *******************************************/
137 card_base
->driverdatas
= (struct HDAudioChip
**) AllocVec(
138 sizeof(*card_base
->driverdatas
) * card_base
->cards_found
,
139 MEMF_PUBLIC
| MEMF_CLEAR
);
141 if (card_base
->driverdatas
== NULL
)
143 D(bug("[HDAudio] Out of memory.\n"));
151 card_base
->driverdatas
[card_no
] = AllocDriverData(dev
, AHIsubBase
);
152 if (card_base
->driverdatas
[card_no
] == NULL
)
154 FreeVec(card_base
->driverdatas
);
161 D(bug("[HDAudio] exit init\n"));
166 /******************************************************************************
167 ** Custom driver clean-up *****************************************************
168 ******************************************************************************/
170 VOID
DriverCleanup(struct DriverBase
* AHIsubBase
)
172 struct HDAudioBase
* card_base
= (struct HDAudioBase
*) AHIsubBase
;
175 for(i
= 0; i
< card_base
->cards_found
; ++i
)
177 FreeDriverData(card_base
->driverdatas
[i
], AHIsubBase
);
180 FreeVec(card_base
->driverdatas
);
187 CloseLibrary(StdCBase
);
193 CloseLibrary((struct Library
*) DOSBase
);
198 static void parse_config_file(void)
203 handle
= Lock("ENV:hdaudio.config", SHARED_LOCK
);
207 bug("No handle found\n");
213 config_file
= Open("ENV:hdaudio.config", MODE_OLDFILE
);
217 BOOL Continue
= TRUE
;
218 bug("Opened config file\n");
222 char *line
= (char *) AllocVec(512, MEMF_CLEAR
);
225 ret
= FGets(config_file
, line
, 512);
242 UWORD vendor
, device
;
243 char *tmp
= (char *) AllocVec(16, MEMF_CLEAR
);
244 char *tmp2
= (char *) AllocVec(4, MEMF_CLEAR
);
246 CopyMem(line
+ 2, tmp
, 4);
249 // convert hex to decimal
250 value
= hex_char_to_int(tmp
[0]) * 16 * 16 * 16 + hex_char_to_int(tmp
[1]) * 16 * 16 + hex_char_to_int(tmp
[2]) * 16 + hex_char_to_int(tmp
[3]);
251 vendor
= (UWORD
) value
;
253 CopyMem(line
+ 10, tmp
, 4);
254 value
= hex_char_to_int(tmp
[0]) * 16 * 16 * 16 + hex_char_to_int(tmp
[1]) * 16 * 16 + hex_char_to_int(tmp
[2]) * 16 + hex_char_to_int(tmp
[3]);
255 device
= (UWORD
) value
;
256 //bug("Adding vendor = %x, device = %x to list, size = %ld\n", vendor, device, vendor_device_list_size);
258 vendor_device_list
[vendor_device_list_size
].vendor
= vendor
;
259 vendor_device_list
[vendor_device_list_size
].device
= device
;
260 vendor_device_list_size
++;
262 if (vendor_device_list_size
>= MAX_DEVICE_VENDORS
)
264 bug("Exceeded MAX_DEVICE_VENDORS\n");
271 else if (ret
[0] == 'Q' && ret
[1] == 'U' && ret
[2] == 'E' && ret
[3] == 'R' && ret
[4] == 'Y')
273 bug("QUERY found!\n");
276 if (ret
[5] == 'D') // debug
281 else if (Strnicmp(ret
, "speaker=0x", 10) == 0)
284 char *tmp
= (char *) AllocVec(16, MEMF_CLEAR
);
286 CopyMem(line
+ 10, tmp
, 2);
289 // convert hex to decimal
290 speaker
= hex_char_to_int(tmp
[0]) * 16 + hex_char_to_int(tmp
[1]);
292 bug("Speaker in config = %x!\n", speaker
);
294 setForceSpeaker(speaker
);
304 bug("Couldn't open config file!\n");
309 static int hex_char_to_int(char c
)
311 if (c
>= '0' && c
<= '9')
315 else if (c
>= 'A' && c
<= 'F')
317 return 10 + (c
- 'A');
319 else if (c
>= 'a' && c
<= 'f')
321 return 10 + (c
- 'a');
325 bug("Error in hex_char_to_int: char was %c\n", c
);