source: GPL/drv32/rm.cpp@ 18

Last change on this file since 18 was 18, checked in by vladest, 20 years ago

initial import

File size: 36.5 KB
Line 
1/* $Id: rm.cpp,v 1.1.1.1 2003/07/02 13:56:56 eleph Exp $ */
2/*
3 * OS/2 Resource Manager C++ interface
4 *
5 * (C) 2000-2002 InnoTek Systemberatung GmbH
6 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
21 * USA.
22 *
23 */
24
25extern "C" int cdecl printk(const char * fmt, ...);
26
27#include "rm.hpp" // Will include os2.h, etc.
28#include <devhelp.h>
29#include <devinfo.h>
30#include <malloc.h>
31#include <string.h>
32#include <dbgos2.h>
33#include <version.h>
34#include <osspci.h>
35#include <linux\pci.h>
36#include "pciids.h"
37#include <unicard.h>
38#include <ossidc32.h>
39
40/**@external LDev_Resources::isEmpty
41 * Returns TRUE iff the LDev_Resources structure has no information.
42 * @param None.
43 * @return BOOL
44 */
45BOOL LDev_Resources::isEmpty()
46{
47 BOOL bIsEmpty = TRUE;
48
49 for ( int i=0; i<MAX_ISA_Dev_IO; ++i) {
50 if (uIOBase[i] != NoIOValue)
51 bIsEmpty = FALSE;
52 if ((i < MAX_ISA_Dev_IRQ) && (uIRQLevel[i] != NoIOValue))
53 bIsEmpty = FALSE;
54 if ((i < MAX_ISA_Dev_DMA) && (uDMAChannel[i] != NoIOValue))
55 bIsEmpty = FALSE;
56 if ((i < MAX_ISA_Dev_MEM) && (uMemBase[i] != 0xffffffff))
57 bIsEmpty = FALSE;
58 }
59 return bIsEmpty;
60}
61
62
63/**@external LDev_Resources::vClear
64 * Set an LDev_Resources structure to Empty.
65 * @param None.
66 * @return VOID
67 */
68void LDev_Resources::vClear()
69{
70 memset( (PVOID) this, NoIOValue, sizeof(LDev_Resources) );
71}
72
73
74/*
75 * --- Linkages required by system Resource Manager (rm.lib).
76 */
77
78extern "C" PFN RM_Help;
79extern "C" PFN RM_Help0;
80extern "C" PFN RM_Help3;
81extern "C" ULONG RMFlags;
82
83/*
84 * --- Public member functions.
85 */
86
87/**@external ResourceManager
88 * Constructor for RM object.
89 * @notes Creates a "driver" node for this device driver, but does not
90 * allocate resources.
91 */
92ResourceManager::ResourceManager() :
93 busnr(0), devnr(0), funcnr(0), devfn(0), DevID(0), idxRes(0)
94{
95 APIRET rc;
96 DRIVERSTRUCT DriverStruct;
97 char DriverName[sizeof(RM_DRIVER_NAME)];
98 char VendorName[sizeof(RM_DRIVER_VENDORNAME)];
99 char DriverDesc[sizeof(RM_DRIVER_DESCRIPTION)];
100 FARPTR16 p;
101 GINFO FAR *pGIS = 0;
102 HDRIVER hDriver;
103
104 /* Warp version level, bus type, machine ID, and much other information is
105 * readily available. Reference the RM ADD sample in the DDK for code.
106 *
107 * Create a "driver" struct for this driver. This must ALWAYS be the
108 * first true RM call executed, as it attaches the Resource Manager
109 * library and performs setup for the other RM calls.
110 */
111 memset( (PVOID) &DriverStruct, 0, sizeof(DriverStruct) );
112
113 //copy strings to stack, because we need to give RM 16:16 pointers
114 //(which can only be (easily) generated from 32 bits stack addresses)
115 strcpy(DriverName, RM_DRIVER_NAME);
116 strcpy(VendorName, RM_DRIVER_VENDORNAME);
117 strcpy(DriverDesc, RM_DRIVER_DESCRIPTION);
118
119 DriverStruct.DrvrName = FlatToSel((ULONG)DriverName); /* ### IHV */
120 DriverStruct.DrvrDescript = FlatToSel((ULONG)DriverDesc); /* ### IHV */
121 DriverStruct.VendorName = FlatToSel((ULONG)VendorName); /* ### IHV */
122 DriverStruct.MajorVer = CMVERSION_MAJOR; //rmbase.h /* ### IHV */
123 DriverStruct.MinorVer = CMVERSION_MINOR; //rmbase.h /* ### IHV */
124 DriverStruct.Date.Year = RM_DRIVER_BUILDYEAR; /* ### IHV */
125 DriverStruct.Date.Month = RM_DRIVER_BUILDMONTH; /* ### IHV */
126 DriverStruct.Date.Day = RM_DRIVER_BUILDDAY; /* ### IHV */
127 DriverStruct.DrvrType = DRT_AUDIO;
128 DriverStruct.DrvrSubType = 0;
129 DriverStruct.DrvrCallback = NULL;
130
131 if(_hDriver == 0) {
132 //hDriver must be used as FlatToSel only works for stack variables
133 rc = RMCreateDriver( FlatToSel((ULONG)&DriverStruct), FlatToSel((ULONG)&hDriver) );
134 if( rc == RMRC_SUCCESS ) {
135 _state = rmDriverCreated;
136 _hDriver = hDriver;
137 }
138 else {
139 _state = rmDriverFailed;
140 _hDriver = 0;
141 }
142 }
143 else {
144 //Only create one driver object
145 _state = rmDriverCreated;
146 }
147 // Build a pointer to the Global Information Segment.
148 rc = DevGetDOSVar( DHGETDOSV_SYSINFOSEG, 0, (VOID NEAR *)&p );
149 if (rc) {
150 _rmDetection = FALSE;
151 }
152 else {
153 SEL FAR48 *pSel = (SEL FAR48 *)MAKE_FARPTR32(p);
154 pGIS = (GINFO FAR *)MAKE_FARPTR32((ULONG)(*pSel << 16));
155 _rmDetection =
156 ( (pGIS->MajorVersion > 20) ||
157 ((pGIS->MajorVersion == 20) && (pGIS->MinorVersion > 30)) );
158 }
159 detectedResources.vClear();
160 resources.vClear();
161}
162
163#pragma off (unreferenced)
164int ResourceManager::bIsDevDetected( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice, int idx)
165#pragma on (unreferenced)
166/*
167; PURPOSE: Search the Resource Manager's "current detected" tree for
168; the matching PnP ID.
169;
170; IN: - DevID - PnP Device ID being sought (Compressed Ascii).
171; - ulSearchFlags - Search flags, ref rmbase.h SEARCH_ID_*; also
172; documented as SearchFlags parm in PDD RM API RMDevIDToHandleList().
173; Defines whether DevID is a Device ID, Logical device ID, Compatible
174; ID, or Vendor ID.
175;
176; OUT: Boolean indicator, TRUE when number of matching detected devices > 0.
177;
178*/
179{
180 int detected = 0;
181
182 detected = getPCIConfiguration(DevID, idx);
183 if(!detected) {
184 return 0;
185 }
186
187 this->DevID = DevID;
188
189 //Manual detection in ResourceManager class constructor;
190 return (_state == rmDriverCreated || _state == rmAdapterCreated);
191}
192
193
194
195/**@internal GetRMDetectedResources
196 * Return the set of IO ports, IRQ levels, DMA channels, & memory ranges
197 * required by the specified device, as detected by the OS/2 resource
198 * manager.
199 * @param Refer to _bIsDevDetected() for parameters.
200 * @notes It's expectded that the spec'd DevID & flags will select a single
201 * device in the system. If multiples are found, the first matching device
202 * is referenced.
203 * @return LDev_Resources* object, filled in with required resources. Object
204 * is allocated from heap, is responsibility of caller to free object.
205 * Ordering on the resources is preserved. Unused fields are set to NoIOValue.
206 * @return NULL on error situations.
207 */
208#pragma off (unreferenced)
209BOOL ResourceManager::GetRMDetectedResources ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice)
210#pragma on (unreferenced)
211{
212 //Fill in resources read from PCI Configuration space
213 detectedResources.uIRQLevel[0] = pciConfigData->InterruptLine;
214 if(detectedResources.uIRQLevel[0] == 0 || detectedResources.uIRQLevel[0] > 15) {
215 //Does not matter if device doesn't have any resources (like a PCI bus controller)
216 dprintf(("Invalid PCI irq %x", (int)detectedResources.uIRQLevel[0]));
217 detectedResources.uIRQLevel[0] = NoIOValue;
218 }
219
220 int idxmem = 0, idxio = 0;
221 for(int i=0;i<MAX_PCI_BASE_ADDRESS;i++)
222 {
223 if(pciConfigData->Bar[i] != -1)
224 {
225 ULONG l, barsize;
226 int reg = PCI_BASE_ADDRESS_0 + (i << 2);
227
228 pci_read_config_dword(reg, &l);
229 if (l == 0xffffffff)
230 {
231 dprintf(("l == 0xffffffff\n"));
232 return 0;
233 }
234
235 pci_write_config_dword(reg, ~0);
236 pci_read_config_dword(reg, &barsize);
237 pci_write_config_dword(reg, l);
238
239 if (!barsize || barsize == 0xffffffff)
240 continue;
241
242 if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
243 barsize = ~(barsize & PCI_BASE_ADDRESS_MEM_MASK);
244 detectedResources.uMemBase[idxmem] = (pciConfigData->Bar[i] & 0xFFFFFFF0);
245 detectedResources.uMemLength[idxmem++] = barsize + 1;
246 }
247 else {
248 barsize = ~(barsize & PCI_BASE_ADDRESS_IO_MASK) & 0xffff;
249 detectedResources.uIOBase[idxio] = (USHORT)(pciConfigData->Bar[i] & 0xFFFFFFF0);
250 detectedResources.uIOLength[idxio++] = (USHORT)barsize + 1;
251 }
252 }
253 }
254 return TRUE;
255}
256
257
258/**@external pGetDevResources
259 *
260 * Allocate set of IO ports, IRQ levels, DMA channels requested by the
261 * specified device.
262 *
263 * @param Refer to bIsDevDetected()
264 *
265 * @return LDev_Resources object, filled in with required resources. Object
266 * is returned on stack. Ordering on the resources is preserved. Unused
267 * fields are set to 0xFF.
268 *
269 * @notes The allocation from OS/2's RM is required; if not performed, the
270 * resources could be allocated by a driver which loads after this one.
271 * Also perform other bookeepping by registering driver, adapter, and
272 * device with the system RM.
273 *
274 * @notes Additional comments from DevCon 'ADD' sample for RM: "Create all
275 * Resource Manager nodes required by this driver. The Resource Manager
276 * structures created in this module may be thought of as being allocated
277 * in a seperate tree called the 'driver' tree. The snooper resource nodes
278 * were created in the 'current detected' tree. Therefore, these
279 * allocations will not compete with previous snooper resource allocations.
280 *
281 * @notes
282 *
283 * - Fetch defaults for named device
284 * - Warp3: GetSpecDefaults( pnpID )
285 * - (not implemented:) snoop on Warp3 -> GetSnoopedResources()
286 * - Warp4: GetLDev_Resources( pnpID ) (rename to GetRMDetectedResources())
287 * - @return LDev_Resources structure
288 * - Fill in any user overrides
289 * - object Override( pnpID ) subclasses an LDev_Resources
290 * - has an added "exists" flag, set true if any overrides exist
291 * - on creation, interacts with parsed information for overrides
292 * - bool Override.exist( pnpID )
293 * - LDev_Resources Override.apply( pnpID, LDev_Resources )
294 * - Format LDev_Resources into RESOURCELIST
295 * - pResourceList = MakeResourceList( LDev_Resources )
296 * - Allocate adapter if this is the 1st time through
297 * - RMCreateAdapter()
298 * - Allocate resources to device
299 * - Call GetDescriptiveName( pnpID ) if Warp3
300 * - Call RMCreateDevice() to allocate the resources
301 * - Add as last step:
302 * - if (Warp3 or any command line overrides) and
303 * - if resources are successfully allocated
304 * - then SLAM the chip with the allocated resources
305 */
306
307LDev_Resources* ResourceManager::pGetDevResources ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice)
308{
309 // Initialize resource object. Use detected information if available,
310 // otherwise use hardcoded defaults.
311 if(GetRMDetectedResources( DevID, ulSearchFlags, fPciDevice) == FALSE) {
312// dprintf(("error in GetRMDetectedResources1\n"));
313 return NULL;
314 }
315
316 if(_pahRMAllocDetectedResources() == FALSE) {
317// dprintf(("error in _pahRMAllocDetectedResources2\n"));
318 _state = rmAllocFailed;
319 return NULL;
320 }
321 return &detectedResources;
322}
323//*****************************************************************************
324//*****************************************************************************
325BOOL ResourceManager::registerResources()
326{
327 APIRET rc;
328
329 char szDeviceName[128];
330 char szMixerName[64];
331
332 if(OSS32_QueryNames(OSS32_DEFAULT_DEVICE, szDeviceName, sizeof(szDeviceName),
333 szMixerName, sizeof(szMixerName), FALSE) != OSSERR_SUCCESS)
334 {
335 DebugInt3();
336 return FALSE;
337 }
338
339 switch(DevID) {
340 case PCIID_VIA_686A:
341 case PCIID_VIA_8233:
342 case PCIID_SI_7012:
343 case PCIID_INTEL_82801:
344 case PCIID_INTEL_82901:
345 case PCIID_INTEL_92801BA:
346 case PCIID_INTEL_440MX:
347 case PCIID_INTEL_ICH3:
348 case PCIID_INTEL_ICH4:
349 case PCIID_INTEL_ICH5:
350 case PCIID_INTEL_ICH6:
351 case PCIID_INTEL_ICH7:
352 case PCIID_NVIDIA_MCP_AUDIO:
353 case PCIID_NVIDIA_MCP2_AUDIO:
354 case PCIID_NVIDIA_MCP3_AUDIO:
355 case PCIID_NVIDIA_CK8S_AUDIO:
356 case PCIID_NVIDIA_CK8_AUDIO:
357 strcat(szDeviceName, " with ");
358 strcat(szDeviceName, szMixerName);
359 break;
360 case PCIID_CREATIVELABS_SBLIVE:
361 case PCIID_ALS4000:
362 case PCIID_CMEDIA_CM8338A:
363 case PCIID_CMEDIA_CM8338B:
364 case PCIID_CMEDIA_CM8738:
365 case PCIID_CMEDIA_CM8738B:
366 case PCIID_CIRRUS_4281:
367 case PCIID_CIRRUS_4280:
368 case PCIID_CIRRUS_4612:
369 case PCIID_CIRRUS_4615:
370 case PCIID_ESS_ALLEGRO_1:
371 case PCIID_ESS_ALLEGRO:
372 case PCIID_ESS_MAESTRO3:
373 case PCIID_ESS_MAESTRO3_1:
374 case PCIID_ESS_MAESTRO3_HW:
375 case PCIID_ESS_MAESTRO3_2:
376 case PCIID_ESS_CANYON3D_2LE:
377 case PCIID_ESS_CANYON3D_2:
378 case PCIID_ESS_ES1938:
379 case PCIID_AUREAL_VORTEX:
380 case PCIID_AUREAL_VORTEX2:
381 case PCIID_AUREAL_ADVANTAGE:
382 case PCIID_ENSONIQ_CT5880:
383 case PCIID_ENSONIQ_ES1371:
384 case PCIID_YAMAHA_YMF724:
385 case PCIID_YAMAHA_YMF724F:
386 case PCIID_YAMAHA_YMF740:
387 case PCIID_YAMAHA_YMF740C:
388 case PCIID_YAMAHA_YMF744:
389 case PCIID_YAMAHA_YMF754:
390 case PCIID_ESS_M2E:
391 case PCIID_ESS_M2:
392 case PCIID_ESS_M1:
393 case PCIID_ALI_5451:
394 case PCIID_TRIDENT_4DWAVE_DX:
395 case PCIID_TRIDENT_4DWAVE_NX:
396 case PCIID_SI_7018:
397 case PCIID_FM801:
398 case PCIID_ATIIXP_SB200:
399 case PCIID_ATIIXP_SB300:
400 case PCIID_ATIIXP_SB400:
401 case PCIID_AUDIGYLS:
402 case PCIID_AUDIGYLS1:
403 case PCIID_AUDIGYLS2:
404 break;
405
406 default:
407 DebugInt3();
408 return FALSE;
409 }
410
411 //--- Here, we got all the resources we wanted. Register adapter if not yet done.
412 //### Problem here with mult adpaters, would need to cross ref PnP ID's to adapters created.
413 if (_state != rmAdapterCreated) {
414 rc = _rmCreateAdapter();
415 }
416 _rmCreateDevice(szDeviceName);
417 return TRUE;
418}
419//*****************************************************************************
420//*****************************************************************************
421
422
423/*
424 * --- Private member functions.
425 */
426
427
428/**@internal _pahRMAllocDetectedResources
429 * Allocate a set of resources from OS/2 by interfacing with the
430 * OS/2 resource manager.
431 * @param PRESOURCELIST pResourceList - list of resources to allocate.
432 * @return TRUE - on success
433 * @return FALSE - on failure
434 * @notes Logs appropriate errors in global error log if any allocation
435 * problem.
436 * @notes Either all resources are allocated, or none. If there is a
437 * failure within this function when some (but not all) resources are
438 * allocated, then any allocated resources are freed.
439 */
440BOOL ResourceManager::_pahRMAllocDetectedResources( )
441{
442 int j;
443
444 for ( j=0; j<MAX_ISA_Dev_IO; ++j) {
445 if (detectedResources.uIOBase[j] != NoIOValue) {
446 if(requestIORange(detectedResources.uIOBase[j], detectedResources.uIOLength[j]) == FALSE) {
447 dprintf(("error in IO range\n"));
448 return FALSE;
449 }
450 }
451 }
452 for ( j=0; j<MAX_ISA_Dev_IRQ; ++j) {
453 if (detectedResources.uIRQLevel[j] != NoIOValue) {
454 //shared irq is not necessarily true, but let's assume that for now
455 if(requestIRQ(detectedResources.uIRQLevel[j], TRUE) == FALSE) {
456 dprintf(("error in IRQ\n"));
457 return FALSE;
458 }
459 }
460 }
461 for ( j=0; j<MAX_ISA_Dev_DMA; ++j) {
462 if (detectedResources.uDMAChannel[j] != NoIOValue) {
463 if(requestDMA(detectedResources.uDMAChannel[j]) == FALSE) {
464 dprintf(("error in DMA\n"));
465 return FALSE;
466 }
467 }
468 }
469
470 for ( j=0; j<MAX_ISA_Dev_MEM; ++j) {
471 if (detectedResources.uMemBase[j] != 0xffffffff) {
472 if(requestMemRange(detectedResources.uMemBase[j], detectedResources.uMemLength[j]) == FALSE) {
473 dprintf(("error in mem range\n"));
474 return FALSE;
475 }
476 }
477 }
478 return TRUE;
479}
480//*****************************************************************************
481//*****************************************************************************
482BOOL ResourceManager::isPartOfAllocatedResources(int type, ULONG ulBase, ULONG ulLength)
483{
484 int j;
485
486 switch(type) {
487 case RS_TYPE_IO:
488 for ( j=0; j<MAX_ISA_Dev_IO; ++j) {
489 if (resources.uIOBase[j] == ulBase && ulLength == resources.uIOLength[j]) {
490 return TRUE;
491 }
492 }
493 break;
494 case RS_TYPE_DMA:
495 for ( j=0; j<MAX_ISA_Dev_DMA; ++j) {
496 if (resources.uDMAChannel[j] == ulBase) {
497 return TRUE;
498 }
499 }
500 break;
501 case RS_TYPE_MEM:
502 for ( j=0; j<MAX_ISA_Dev_MEM; ++j) {
503 if (ulBase >= resources.uMemBase[j] && ulBase+ulLength <= resources.uMemBase[j] + resources.uMemLength[j]) {
504 return TRUE;
505 }
506 }
507 break;
508 case RS_TYPE_IRQ:
509 for ( j=0; j<MAX_ISA_Dev_IRQ; ++j) {
510 if (resources.uIRQLevel[j] == ulBase) {
511 return TRUE;
512 }
513 }
514 break;
515 }
516 return FALSE;
517}
518//*****************************************************************************
519//*****************************************************************************
520BOOL ResourceManager::requestIORange(ULONG ulBase, ULONG ulLength)
521{
522 RESOURCESTRUCT Resource;
523 HRESOURCE hres = 0;
524 APIRET rc;
525 int j;
526
527 if(isPartOfAllocatedResources(RS_TYPE_IO, ulBase, ulLength)) {
528 return TRUE;
529 }
530
531 memset(__Stack32ToFlat(&Resource), 0, sizeof(Resource));
532 Resource.ResourceType = RS_TYPE_IO;
533 Resource.IOResource.BaseIOPort = (USHORT)ulBase;
534 Resource.IOResource.NumIOPorts = (USHORT)ulLength;
535 Resource.IOResource.IOFlags = RS_IO_EXCLUSIVE;
536 if (ulBase > 0x3ff)
537 Resource.IOResource.IOAddressLines = 16;
538 else
539 Resource.IOResource.IOAddressLines = 10;
540
541 rc = RMAllocResource( _hDriver, // Handle to driver.
542 FlatToSel((ULONG)&hres), // OUT: "allocated" resource node handle
543 FlatToSel((ULONG)&Resource) ); // Resource to allocate.
544
545 dprintf(("RMAllocResource IO rc = %d\n", rc));
546 if (rc == RMRC_SUCCESS || rc == RMRC_RES_ALREADY_CLAIMED || rc == 14) {
547 //insert into allocated resources array
548 for ( j=0; j<MAX_ISA_Dev_IO; ++j) {
549 if (resources.uIOBase[j] == NoIOValue) {
550 resources.uIOBase[j] = (USHORT)ulBase;
551 resources.uIOLength[j] = (USHORT)ulLength;
552 break;
553 }
554 }
555 if(j != MAX_ISA_Dev_IO) {
556 hResource[idxRes] = hres;
557 idxRes++;
558 return TRUE;
559 }
560 DebugInt3();
561 }
562 releaseAllResources();
563 return FALSE;
564}
565//*****************************************************************************
566//*****************************************************************************
567BOOL ResourceManager::requestMemRange(ULONG ulBase, ULONG ulLength)
568{
569 RESOURCESTRUCT Resource;
570 HRESOURCE hres = 0;
571 APIRET rc;
572 int j;
573
574 if(isPartOfAllocatedResources(RS_TYPE_MEM, ulBase, ulLength)) {
575 return TRUE;
576 }
577 memset(__Stack32ToFlat(&Resource), 0, sizeof(Resource));
578 Resource.ResourceType = RS_TYPE_MEM;
579 Resource.MEMResource.MemBase = ulBase;
580 Resource.MEMResource.MemSize = ulLength;
581 Resource.MEMResource.MemFlags= RS_MEM_EXCLUSIVE;
582
583 rc = RMAllocResource( _hDriver, // Handle to driver.
584 FlatToSel((ULONG)&hres), // OUT: "allocated" resource node handle
585 FlatToSel((ULONG)&Resource) ); // Resource to allocate.
586
587 dprintf(("RMAllocResource MEM rc = %d\n", rc));
588 if (rc == RMRC_SUCCESS || rc == RMRC_RES_ALREADY_CLAIMED) {
589 //insert into allocated resources array
590 for ( j=0; j<MAX_ISA_Dev_MEM; ++j) {
591 if (resources.uMemBase[j] == 0xffffffff) {
592 resources.uMemBase[j] = ulBase;
593 resources.uMemLength[j] = ulLength;
594 break;
595 }
596 }
597 if(j != MAX_ISA_Dev_MEM) {
598 hResource[idxRes] = hres;
599 idxRes++;
600 return TRUE;
601 }
602 DebugInt3();
603 }
604 releaseAllResources();
605 return FALSE;
606}
607//*****************************************************************************
608//*****************************************************************************
609BOOL ResourceManager::requestIRQ(USHORT usIRQ, BOOL fShared)
610{
611 RESOURCESTRUCT Resource;
612 HRESOURCE hres = 0;
613 APIRET rc;
614 int j;
615
616 if(isPartOfAllocatedResources(RS_TYPE_IRQ, usIRQ, 0)) {
617 return TRUE;
618 }
619 memset(__Stack32ToFlat(&Resource), 0, sizeof(Resource));
620 Resource.ResourceType = RS_TYPE_IRQ;
621 Resource.IRQResource.IRQLevel = usIRQ;
622 Resource.IRQResource.IRQFlags = (fShared) ? RS_IRQ_SHARED : RS_IRQ_EXCLUSIVE;
623 Resource.IRQResource.PCIIrqPin = RS_PCI_INT_NONE;
624
625 rc = RMAllocResource( _hDriver, // Handle to driver.
626 FlatToSel((ULONG)&hres), // OUT: "allocated" resource node handle
627 FlatToSel((ULONG)&Resource) ); // Resource to allocate.
628
629 dprintf(("RMAllocResource IRQ rc = %d\n", rc));
630 if (rc == RMRC_SUCCESS || rc == RMRC_RES_ALREADY_CLAIMED) {
631 //insert into allocated resources array
632 for ( j=0; j<MAX_ISA_Dev_IRQ; ++j) {
633 if (resources.uIRQLevel[j] == NoIOValue) {
634 resources.uIRQLevel[j] = usIRQ;
635 break;
636 }
637 }
638 if(j != MAX_ISA_Dev_IRQ) {
639 hResource[idxRes] = hres;
640 idxRes++;
641 return TRUE;
642 }
643 DebugInt3();
644 }
645 releaseAllResources();
646 return FALSE;
647}
648//*****************************************************************************
649//*****************************************************************************
650BOOL ResourceManager::requestDMA(USHORT usDMA)
651{
652 RESOURCESTRUCT Resource;
653 HRESOURCE hres = 0;
654 APIRET rc;
655 int j;
656
657 if(isPartOfAllocatedResources(RS_TYPE_DMA, usDMA, 0)) {
658 return TRUE;
659 }
660 memset(__Stack32ToFlat(&Resource), 0, sizeof(Resource));
661 Resource.ResourceType = RS_TYPE_DMA;
662 Resource.DMAResource.DMAChannel = usDMA;
663 Resource.DMAResource.DMAFlags = RS_DMA_EXCLUSIVE;
664
665 rc = RMAllocResource( _hDriver, // Handle to driver.
666 FlatToSel((ULONG)&hres), // OUT: "allocated" resource node handle
667 FlatToSel((ULONG)&Resource) ); // Resource to allocate.
668
669 if (rc == RMRC_SUCCESS) {
670 //insert into allocated resources array
671 for ( j=0; j<MAX_ISA_Dev_DMA; ++j) {
672 if (resources.uDMAChannel[j] == NoIOValue) {
673 resources.uDMAChannel[j] = usDMA;
674 break;
675 }
676 }
677 if(j != MAX_ISA_Dev_DMA) {
678 hResource[idxRes] = hres;
679 idxRes++;
680 return TRUE;
681 }
682 DebugInt3();
683 }
684 releaseAllResources();
685 return FALSE;
686}
687//*****************************************************************************
688//*****************************************************************************
689void ResourceManager::releaseAllResources()
690{
691 int i;
692
693 for(i=0;i<idxRes;i++) {
694 RMDeallocResource(_hDriver, hResource[i]);
695 }
696 idxRes = 0;
697}
698//*****************************************************************************
699//*****************************************************************************
700/**@internal _rmCreateAdapter
701 * Create the "adapter" node. The "adapter" node belongs to this driver's
702 * "driver" node. Also as part of this operation, the "resource" nodes
703 * associated with this driver will be moved to the "adapter" node.
704 * @param None.
705 * @notes Changes state of the RM object to 'rmAdapterCreated'.
706 * @return APIRET rc - 0 iff good creation. Returns non-zero and logs a soft
707 * error on failure.
708 */
709APIRET ResourceManager::_rmCreateAdapter()
710{
711 APIRET rc = 0;
712 ADAPTERSTRUCT AdapterStruct;
713 char AdapterName[sizeof(RM_ADAPTER_NAME)];
714 HADAPTER hAdapter;
715
716 if (!_hAdapter && _state != rmAdapterCreated)
717 {
718 //copy string to stack, because we need to give RM 16:16 pointers
719 //(which can only be (easily) generated from 32 bits stack addresses)
720 strcpy(AdapterName, RM_ADAPTER_NAME);
721
722 memset( (PVOID) &AdapterStruct, 0, sizeof(AdapterStruct) );
723 AdapterStruct.AdaptDescriptName = FlatToSel((ULONG)AdapterName); /* ### IHV */
724 AdapterStruct.AdaptFlags = AS_16MB_ADDRESS_LIMIT; // AdaptFlags /* ### IHV */
725 AdapterStruct.BaseType = AS_BASE_MMEDIA; // BaseType
726 AdapterStruct.SubType = AS_SUB_MM_AUDIO; // SubType
727 AdapterStruct.InterfaceType = AS_INTF_GENERIC; // InterfaceType
728 AdapterStruct.HostBusType = AS_HOSTBUS_PCI; // HostBusType /* ### IHV */
729 AdapterStruct.HostBusWidth = AS_BUSWIDTH_32BIT; // HostBusWidth /* ### IHV */
730 AdapterStruct.pAdjunctList = NULL; // pAdjunctList /* ### IHV */
731
732 //--- Register adapter. We'll record any error code, but won't fail
733 // the driver initialization and won't return resources.
734 //NOTE: hAdapter must be used as FlatToSel only works for stack variables
735 rc = RMCreateAdapter( _hDriver, // Handle to driver
736 FlatToSel((ULONG)&hAdapter), // (OUT) Handle to adapter
737 FlatToSel((ULONG)&AdapterStruct), // Adapter structure
738 NULL, // Parent device (defaults OK)
739 NULL ); // Allocated resources. We assign ownership
740 // of the IO, IRQ, etc. resources to the
741 // device (via RMCreateDevice()), not to the
742 // adapter (as done in disk DD sample).
743 if (rc == RMRC_SUCCESS) {
744 _state = rmAdapterCreated;
745 _hAdapter = hAdapter;
746 }
747 }
748 else {
749 //Only create one RM Adapter object
750 _state = rmAdapterCreated;
751 }
752 return rc;
753}
754
755/**@internal _rmCreateDevice
756 * Create Device node in the OS/2 RM allocation tree. Device nodes belong
757 * to the Adapter node, just like the Resource nodes.
758 * @param PSZ pszName - Descriptive name of device.
759 * @param LPAHRESOURCE pahResource - Handles of allocated resources that are
760 * owned by this device.
761 * @return APIRET rc - Value returned by RMCreateDevice() call.
762 * @notes Same "soft" error strategy as adapter registration: we'll record
763 * any errors but hold onto the resources and continue to operate the
764 * driver.
765 * @notes
766 */
767APIRET ResourceManager::_rmCreateDevice( char *lpszDeviceName)
768{
769 DEVICESTRUCT DeviceStruct;
770 HDEVICE hDevice;
771 APIRET rc;
772 typedef struct _myhresource {
773 ULONG NumResource;
774 HRESOURCE hResource[MAX_ResourceCount]; /*First Entry in Array of HRESOURCE */
775 } MYAHRESOURCE;
776
777 MYAHRESOURCE hres;
778
779 hres.NumResource = idxRes;
780 for(int i=0;i<idxRes;i++) {
781 hres.hResource[i] = hResource[i];
782 }
783
784 memset( (PVOID) &DeviceStruct, 0, sizeof(DeviceStruct));
785
786 //NOTE: Assumes szDeviceName is a stack pointer!!
787 DeviceStruct.DevDescriptName = FlatToSel((ULONG)lpszDeviceName);
788 DeviceStruct.DevFlags = DS_FIXED_LOGICALNAME;
789 DeviceStruct.DevType = DS_TYPE_AUDIO;
790 DeviceStruct.pAdjunctList = NULL;
791
792 rc = RMCreateDevice(_hDriver, // Handle to driver
793 FlatToSel((ULONG)&hDevice), // (OUT) Handle to device, unused.
794 FlatToSel((ULONG)&DeviceStruct), // Device structure
795 _hAdapter, // Parent adapter
796 FlatToSel((ULONG)&hres)); // Allocated resources
797 return rc;
798}
799//******************************************************************************
800//******************************************************************************
801int ResourceManager::getPCIConfiguration(ULONG pciId, int idx)
802{
803 ULONG devNr, busNr, funcNr, temp, cfgaddrreg, detectedId;
804 int found = 0;
805
806 cfgaddrreg = _inpd(PCI_CONFIG_ADDRESS);
807 for(busNr=0;busNr<MAX_PCI_BUSSES;busNr++) //BusNumber<255
808 {
809 for(devNr=0;devNr<32;devNr++)
810 {
811 for(funcNr=0;funcNr<8;funcNr++)
812 {
813 temp = ((ULONG)((ULONG)devNr<<11UL) + ((ULONG)busNr<<16UL) + ((ULONG)funcNr << 8UL));
814
815 _outpd(PCI_CONFIG_ADDRESS, PCI_CONFIG_ENABLE|temp);
816 detectedId = _inpd(PCI_CONFIG_DATA);
817 if(detectedId == pciId)
818 {
819 found++;
820 if (found == (idx+1))
821 break;
822 }
823 }
824 if (found == (idx+1)) break;
825// if(found) break;
826 }
827 if (found == (idx+1)) break;
828// if(found) break;
829 }
830
831 if(!found) {
832 _outpd(PCI_CONFIG_ADDRESS, cfgaddrreg);
833 return 0;
834 }
835
836 for(int i=0;i<64;i++)
837 {
838 temp = ((ULONG)((ULONG)devNr<<11UL) + ((ULONG)busNr<<16UL) + ((ULONG)funcNr << 8UL) + (i << 2));
839 _outpd(PCI_CONFIG_ADDRESS, PCI_CONFIG_ENABLE|temp);
840
841 PCIConfig[i] = _inpd(PCI_CONFIG_DATA);
842 }
843 _outpd(PCI_CONFIG_ADDRESS, cfgaddrreg);
844
845 pciConfigData = (PCIConfigData *)&PCIConfig[0];
846
847 if(pciConfigData->Bar[0] == 0 || pciConfigData->Bar[0] == 0xFFFFFFFF)
848 {
849 dprintf(("WARNING: No BAR address for PCI device!!"));
850 }
851 busnr = busNr & 0xFF;
852 devnr = devNr & 0x1F;
853 funcnr = funcNr & 0x7;
854 devfn = (devnr << 3) | funcnr;
855 printk("found %i devices for %X PCI ID\n", found, pciId);
856 return found;
857}
858//******************************************************************************
859//******************************************************************************
860void ResourceManager::pci_write_config_dword(ULONG where, ULONG value)
861{
862 _outpd(PCI_CONFIG_ADDRESS, CONFIG_CMD(busnr,devfn, where));
863 _outpd(PCI_CONFIG_DATA, value);
864}
865//******************************************************************************
866//******************************************************************************
867void ResourceManager::pci_read_config_dword(ULONG where, ULONG *pValue)
868{
869 _outpd(PCI_CONFIG_ADDRESS, CONFIG_CMD(busnr,devfn, where));
870 *pValue = _inpd(PCI_CONFIG_DATA);
871}
872//******************************************************************************
873//******************************************************************************
874HDRIVER ResourceManager::_hDriver = 0;
875HADAPTER ResourceManager::_hAdapter= 0;
876//******************************************************************************
877//******************************************************************************
878HRESMGR RMFindPCIDevice(ULONG vendorid, ULONG deviceid, IDC_RESOURCE *lpResource, int idx)
879{
880 LDev_Resources* pRMResources;
881 ResourceManager* pRM = NULL; // Resource manager object.
882 int i;
883 ULONG pcidevid;
884
885 pcidevid = (deviceid << 16) | vendorid;
886
887 pRM = new ResourceManager(); // Create the RM object.
888 if (!pRM) {
889 goto fail;
890 }
891 if(pRM->getState() != rmDriverCreated) {
892 goto fail;
893 }
894
895 if(!pRM->bIsDevDetected(pcidevid, SEARCH_ID_DEVICEID, TRUE, idx)) {
896 dprintf(("Error in bIsDevDetected"));
897 goto fail;
898 }
899
900 pRMResources = pRM->pGetDevResources(pcidevid, SEARCH_ID_DEVICEID, TRUE);
901 if (!pRMResources) {
902 dprintf(("Error in pGetDevResources"));
903 goto fail;
904 }
905 lpResource->busnr = pRM->getBusNr();
906 lpResource->devnr = pRM->getDeviceNr();
907 lpResource->funcnr = pRM->getFunctionNr();
908 lpResource->devfn = pRM->getDevFuncNr();
909 dprintf(("Detected device %x%x bus %d dev %d func %d", vendorid, deviceid, lpResource->busnr, lpResource->devnr, lpResource->funcnr));
910
911 // Available device resources identified
912 for(i=0;i<MAX_ISA_Dev_IO;i++) {
913 lpResource->io[i] = pRMResources->uIOBase[i];
914 lpResource->iolength[i] = pRMResources->uIOLength[i];
915 if(lpResource->io[i] != 0xffff)
916 dprintf(("IO resource %x length %d", (ULONG)lpResource->io[i], (ULONG)lpResource->iolength[i]));
917 }
918 for(i=0;i<MAX_ISA_Dev_IRQ;i++) {
919 lpResource->irq[i] = pRMResources->uIRQLevel[i];
920 if(lpResource->irq[i] != 0xffff)
921 dprintf(("IRQ resource %d ", (ULONG)lpResource->irq[i]));
922 }
923 for(i=0;i<MAX_ISA_Dev_DMA;i++) {
924 lpResource->dma[i] = pRMResources->uDMAChannel[i];
925 }
926 for(i=0;i<MAX_ISA_Dev_MEM;i++) {
927 lpResource->mem[i] = pRMResources->uMemBase[i];
928 lpResource->memlength[i] = pRMResources->uMemLength[i];
929 if(lpResource->mem[i] != 0xffffffff)
930 dprintf(("Memory resource %x length %d", (ULONG)lpResource->mem[i], (ULONG)lpResource->memlength[i]));
931 }
932
933 return (HRESMGR)pRM;
934
935fail:
936 if(pRM) delete pRM;
937 return 0;
938}
939//******************************************************************************
940//register resources & destroy resource manager object
941//******************************************************************************
942void RMFinialize(HRESMGR hResMgr)
943{
944 if(hResMgr) {
945 ResourceManager* pRM = (ResourceManager*)hResMgr;
946 pRM->registerResources();
947 delete pRM;
948 }
949}
950//******************************************************************************
951//destroy resource manager object
952//******************************************************************************
953void RMDestroy(HRESMGR hResMgr)
954{
955 if(hResMgr) {
956 ResourceManager* pRM = (ResourceManager*)hResMgr;
957 delete pRM;
958 }
959}
960//******************************************************************************
961//******************************************************************************
962BOOL RMRequestIO(HRESMGR hResMgr, ULONG ulIOBase, ULONG ulIOLength)
963{
964 ResourceManager* pRM = (ResourceManager*)hResMgr;
965
966 if(!pRM) {
967 DebugInt3();
968 return FALSE;
969 }
970 return pRM->requestIORange(ulIOBase, ulIOLength);
971}
972//******************************************************************************
973//******************************************************************************
974BOOL RMRequestMem(HRESMGR hResMgr, ULONG ulMemBase, ULONG ulMemLength)
975{
976 ResourceManager* pRM = (ResourceManager*)hResMgr;
977
978 if(!pRM) {
979 DebugInt3();
980 return FALSE;
981 }
982 return pRM->requestMemRange(ulMemBase, ulMemLength);
983}
984//******************************************************************************
985//******************************************************************************
986BOOL RMRequestIRQ(HRESMGR hResMgr, ULONG ulIrq, BOOL fShared)
987{
988 ResourceManager* pRM = (ResourceManager*)hResMgr;
989
990 if(!pRM) {
991 DebugInt3();
992 return FALSE;
993 }
994 return pRM->requestIRQ((USHORT)ulIrq, fShared);
995}
996//******************************************************************************
997//******************************************************************************
998BOOL RMRequestDMA(HRESMGR hResMgr, ULONG ulDMA)
999{
1000 ResourceManager* pRM = (ResourceManager*)hResMgr;
1001
1002 if(!pRM) {
1003 DebugInt3();
1004 return FALSE;
1005 }
1006 return pRM->requestDMA((USHORT)ulDMA);
1007}
1008//******************************************************************************
1009//******************************************************************************
1010
Note: See TracBrowser for help on using the repository browser.