xf86pciBus.c revision 4642e01f
1/*
2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * This file contains the interfaces to the bus-specific code
30 */
31#ifdef HAVE_XORG_CONFIG_H
32#include <xorg-config.h>
33#endif
34
35#include <ctype.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include <X11/X.h>
39#include <pciaccess.h>
40#include "os.h"
41#include "Pci.h"
42#include "xf86.h"
43#include "xf86Priv.h"
44#include "xf86Resources.h"
45
46/* Bus-specific headers */
47#include "xf86Bus.h"
48
49#define XF86_OS_PRIVS
50#define NEED_OS_RAC_PROTOS
51#include "xf86_OSproc.h"
52
53#include "xf86RAC.h"
54
55/* Bus-specific globals */
56Bool pciSlotClaimed = FALSE;
57static struct pci_device ** xf86PciVideoInfo = NULL;	/* PCI probe for video hw */
58
59
60/* PCI classes that get included in xf86PciVideoInfo */
61#define PCIINFOCLASSES(c) \
62    ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \
63      || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
64      || ((((c) & 0x00ffff00) \
65	   == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \
66      || ((((c) & 0x00ffff00) \
67	   == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) )
68
69/*
70 * PCI classes that have messages printed always.  The others are only
71 * have a message printed when the vendor/dev IDs are recognised.
72 */
73#define PCIALWAYSPRINTCLASSES(c) \
74    ( (((c) & 0x00ffff00) \
75       == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \
76      || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \
77      || ((((c) & 0x00ffff00) \
78	   == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) )
79
80#define IS_VGA(c) \
81    (((c) & 0x00ffff00) \
82	 == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8)))
83
84/*
85 * PCI classes for which potentially destructive checking of the map sizes
86 * may be done.  Any classes where this may be unsafe should be omitted
87 * from this list.
88 */
89#define PCINONSYSTEMCLASSES(c) PCIALWAYSPRINTCLASSES(c)
90
91/*
92 * PCI classes that use RAC
93 */
94#define PCISHAREDIOCLASSES(c) \
95    ( (((c) & 0x00ffff00) \
96       == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \
97      || IS_VGA(c) )
98
99
100_X_EXPORT void
101xf86FormatPciBusNumber(int busnum, char *buffer)
102{
103    /* 'buffer' should be at least 8 characters long */
104    if (busnum < 256)
105	sprintf(buffer, "%d", busnum);
106    else
107	sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8);
108}
109
110/*
111 * IO enable/disable related routines for PCI
112 */
113#define pArg ((pciArg*)arg)
114#define SETBITS PCI_CMD_IO_ENABLE
115static void
116pciIoAccessEnable(void* arg)
117{
118#if 0
119#ifdef DEBUG
120    ErrorF("pciIoAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
121#endif
122    pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
123    pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG);
124#endif
125}
126
127static void
128pciIoAccessDisable(void* arg)
129{
130#if 0
131#ifdef DEBUG
132    ErrorF("pciIoAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
133#endif
134    pArg->ctrl &= ~SETBITS;
135    pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG);
136#endif
137}
138
139#undef SETBITS
140#define SETBITS (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE)
141static void
142pciIo_MemAccessEnable(void* arg)
143{
144#if 0
145#ifdef DEBUG
146    ErrorF("pciIo_MemAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
147#endif
148    pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
149    pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG);
150#endif
151}
152
153static void
154pciIo_MemAccessDisable(void* arg)
155{
156#if 0
157#ifdef DEBUG
158    ErrorF("pciIo_MemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
159#endif
160    pArg->ctrl &= ~SETBITS;
161    pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG);
162#endif
163}
164
165#undef SETBITS
166#define SETBITS (PCI_CMD_MEM_ENABLE)
167static void
168pciMemAccessEnable(void* arg)
169{
170#if 0
171#ifdef DEBUG
172    ErrorF("pciMemAccessEnable: 0x%05lx\n", *(PCITAG *)arg);
173#endif
174    pArg->ctrl |= SETBITS | PCI_CMD_MASTER_ENABLE;
175    pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG);
176#endif
177}
178
179static void
180pciMemAccessDisable(void* arg)
181{
182#if 0
183#ifdef DEBUG
184    ErrorF("pciMemAccessDisable: 0x%05lx\n", *(PCITAG *)arg);
185#endif
186    pArg->ctrl &= ~SETBITS;
187    pci_device_cfg_write_u32(pArg->dev, pArg->ctrl, PCI_CMD_STAT_REG);
188#endif
189}
190#undef SETBITS
191#undef pArg
192
193
194/* move to OS layer */
195#define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN)
196static void
197pciBusAccessEnable(BusAccPtr ptr)
198{
199#if 0
200    struct pci_device * const dev = ptr->busdep.pci.dev;
201    uint16_t ctrl;
202
203#ifdef DEBUG
204    ErrorF("pciBusAccessEnable: bus=%d\n", ptr->busdep.pci.bus);
205#endif
206    pci_device_cfg_read_u16( dev, & ctrl, PCI_PCI_BRIDGE_CONTROL_REG );
207    if ((ctrl & MASKBITS) != PCI_PCI_BRIDGE_VGA_EN) {
208	ctrl = (ctrl | PCI_PCI_BRIDGE_VGA_EN) &
209	    ~(PCI_PCI_BRIDGE_MASTER_ABORT_EN | PCI_PCI_BRIDGE_SECONDARY_RESET);
210	pci_device_cfg_write_u16(dev, ctrl, PCI_PCI_BRIDGE_CONTROL_REG);
211    }
212#endif
213}
214
215/* move to OS layer */
216static void
217pciBusAccessDisable(BusAccPtr ptr)
218{
219#if 0
220    struct pci_device * const dev = ptr->busdep.pci.dev;
221    uint16_t ctrl;
222
223#ifdef DEBUG
224    ErrorF("pciBusAccessDisable: bus=%d\n", ptr->busdep.pci.bus);
225#endif
226    pci_device_cfg_read_u16( dev, & ctrl, PCI_PCI_BRIDGE_CONTROL_REG );
227    if (ctrl & MASKBITS) {
228	ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET);
229	pci_device_cfg_write_u16(dev, ctrl, PCI_PCI_BRIDGE_CONTROL_REG);
230    }
231#endif
232}
233#undef MASKBITS
234
235static void
236pciSetBusAccess(BusAccPtr ptr)
237{
238#if 0
239#ifdef DEBUG
240    ErrorF("pciSetBusAccess: route VGA to bus %d\n", ptr->busdep.pci.bus);
241#endif
242
243    if (!ptr->primary && !ptr->current)
244	return;
245
246    if (ptr->current && ptr->current->disable_f)
247	(*ptr->current->disable_f)(ptr->current);
248    ptr->current = NULL;
249
250    /* walk down */
251    while (ptr->primary) {	/* No enable for root bus */
252	if (ptr != ptr->primary->current) {
253	    if (ptr->primary->current && ptr->primary->current->disable_f)
254		(*ptr->primary->current->disable_f)(ptr->primary->current);
255	    if (ptr->enable_f)
256		(*ptr->enable_f)(ptr);
257	    ptr->primary->current = ptr;
258	}
259	ptr = ptr->primary;
260    }
261#endif
262}
263
264/* move to OS layer */
265static void
266savePciState( struct pci_device * dev, pciSavePtr ptr )
267{
268#if 0
269    int i;
270
271    pci_device_cfg_read_u32( dev, & ptr->command, PCI_CMD_STAT_REG );
272
273    for ( i = 0; i < 6; i++ ) {
274	pci_device_cfg_read_u32( dev, & ptr->base[i],
275				 PCI_CMD_BASE_REG + (i * 4) );
276    }
277
278    pci_device_cfg_read_u32( dev, & ptr->biosBase, PCI_CMD_BIOS_REG );
279#endif
280}
281
282/* move to OS layer */
283#if 0
284static void
285restorePciState( struct pci_device * dev, pciSavePtr ptr)
286{
287    int i;
288
289    /* disable card before setting anything */
290    pci_device_cfg_write_bits(dev, PCI_CMD_MEM_ENABLE | PCI_CMD_IO_ENABLE, 0,
291			      PCI_CMD_STAT_REG);
292
293    pci_device_cfg_write_u32(dev, ptr->biosBase, PCI_CMD_BIOS_REG);
294
295    for ( i = 0; i < 6; i++ ) {
296	pci_device_cfg_write_u32(dev, ptr->base[i],
297				 PCI_CMD_BASE_REG + (i * 4));
298    }
299
300    pci_device_cfg_write_u32(dev, ptr->command, PCI_CMD_STAT_REG);
301}
302#endif
303
304/* move to OS layer */
305static void
306savePciBusState(BusAccPtr ptr)
307{
308#if 0
309    struct pci_device * const dev = ptr->busdep.pci.dev;
310    uint16_t temp;
311
312    pci_device_cfg_read_u16( dev, & temp, PCI_PCI_BRIDGE_CONTROL_REG );
313    ptr->busdep.pci.save.control = temp & ~PCI_PCI_BRIDGE_SECONDARY_RESET;
314
315    /* Allow master aborts to complete normally on non-root buses */
316    if ( ptr->busdep.pci.save.control & PCI_PCI_BRIDGE_MASTER_ABORT_EN ) {
317	temp = ptr->busdep.pci.save.control & ~PCI_PCI_BRIDGE_MASTER_ABORT_EN;
318	pci_device_cfg_read_u16( dev, & temp, PCI_PCI_BRIDGE_CONTROL_REG );
319    }
320#endif
321}
322
323/* move to OS layer */
324#define MASKBITS (PCI_PCI_BRIDGE_VGA_EN | PCI_PCI_BRIDGE_MASTER_ABORT_EN)
325static void
326restorePciBusState(BusAccPtr ptr)
327{
328#if 0
329    struct pci_device * const dev = ptr->busdep.pci.dev;
330    uint16_t ctrl;
331
332    /* Only restore the bits we've changed (and don't cause resets) */
333    pci_device_cfg_read_u16( dev, & ctrl, PCI_PCI_BRIDGE_CONTROL_REG );
334
335    if ((ctrl ^ ptr->busdep.pci.save.control) & MASKBITS) {
336	ctrl &= ~(MASKBITS | PCI_PCI_BRIDGE_SECONDARY_RESET);
337	ctrl |= ptr->busdep.pci.save.control & MASKBITS;
338	pci_device_cfg_write_u16(dev, ctrl, PCI_PCI_BRIDGE_CONTROL_REG);
339    }
340#endif
341}
342#undef MASKBITS
343
344
345/*
346 * xf86Bus.c interface
347 */
348
349void
350xf86PciProbe(void)
351{
352    int i = 0, k;
353    int num = 0;
354    struct pci_device *info;
355    struct pci_device_iterator *iter;
356
357
358    if (!xf86scanpci()) {
359	xf86PciVideoInfo = NULL;
360	return;
361    }
362
363    iter = pci_slot_match_iterator_create(& xf86IsolateDevice);
364    while ((info = pci_device_next(iter)) != NULL) {
365	if (PCIINFOCLASSES(info->device_class)) {
366	    num++;
367	    xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo,
368					  (sizeof(struct pci_device *)
369					   * (num + 1)));
370	    xf86PciVideoInfo[num] = NULL;
371	    xf86PciVideoInfo[num - 1] = info;
372
373	    pci_device_probe(info);
374	    info->user_data = 0;
375	}
376    }
377
378
379    /* If we haven't found a primary device try a different heuristic */
380    if (primaryBus.type == BUS_NONE && num) {
381	for (i = 0; i < num; i++) {
382	    uint16_t  command;
383
384	    info = xf86PciVideoInfo[i];
385	    pci_device_cfg_read_u16(info, & command, 4);
386
387	    if ((command & PCI_CMD_MEM_ENABLE)
388		&& ((num == 1) || IS_VGA(info->device_class))) {
389		if (primaryBus.type == BUS_NONE) {
390		    primaryBus.type = BUS_PCI;
391		    primaryBus.id.pci = info;
392		} else {
393		    xf86Msg(X_NOTICE,
394			    "More than one possible primary device found\n");
395		    primaryBus.type ^= (BusType)(-1);
396		}
397	    }
398	}
399    }
400
401    /* Print a summary of the video devices found */
402    for (k = 0; k < num; k++) {
403	const char *vendorname = NULL, *chipname = NULL;
404	const char *prim = " ";
405	Bool memdone = FALSE, iodone = FALSE;
406
407
408	info = xf86PciVideoInfo[k];
409
410	vendorname = pci_device_get_vendor_name( info );
411	chipname = pci_device_get_device_name( info );
412
413	if ((!vendorname || !chipname) &&
414	    !PCIALWAYSPRINTCLASSES(info->device_class))
415	    continue;
416
417	if (xf86IsPrimaryPci(info))
418	    prim = "*";
419
420	xf86Msg( X_PROBED, "PCI:%s(%u@%u:%u:%u) ", prim, info->domain,
421		 info->bus, info->dev, info->func );
422
423	if (vendorname)
424	    xf86ErrorF("%s ", vendorname);
425	else
426	    xf86ErrorF("unknown vendor (0x%04x) ", info->vendor_id);
427
428	if (chipname)
429	    xf86ErrorF("%s ", chipname);
430	else
431	    xf86ErrorF("unknown chipset (0x%04x) ", info->device_id);
432
433	xf86ErrorF("rev %d", info->revision);
434
435	for (i = 0; i < 6; i++) {
436	    struct pci_mem_region * r = & info->regions[i];
437
438	    if ( r->size && ! r->is_IO ) {
439		if (!memdone) {
440		    xf86ErrorF(", Mem @ ");
441		    memdone = TRUE;
442		} else
443		    xf86ErrorF(", ");
444		xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size);
445	    }
446	}
447
448	for (i = 0; i < 6; i++) {
449	    struct pci_mem_region * r = & info->regions[i];
450
451	    if ( r->size && r->is_IO ) {
452		if (!iodone) {
453		    xf86ErrorF(", I/O @ ");
454		    iodone = TRUE;
455		} else
456		    xf86ErrorF(", ");
457		xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size);
458	    }
459	}
460
461	if ( info->rom_size ) {
462	    xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", (long)info->rom_size);
463	}
464
465	xf86ErrorF("\n");
466    }
467}
468
469void
470initPciState(void)
471{
472    unsigned i;
473    pciAccPtr pcaccp;
474
475    if (xf86PciVideoInfo == NULL) {
476	return;
477    }
478
479    for (i = 0 ; xf86PciVideoInfo[i] != NULL ; i++) {
480	struct pci_device * const pvp = xf86PciVideoInfo[i];
481
482	if (pvp->user_data == 0) {
483	    pcaccp = xnfalloc( sizeof( pciAccRec ) );
484	    pvp->user_data = (intptr_t) pcaccp;
485
486	    pcaccp->arg.dev = pvp;
487	    pcaccp->ioAccess.AccessDisable = pciIoAccessDisable;
488	    pcaccp->ioAccess.AccessEnable = pciIoAccessEnable;
489	    pcaccp->ioAccess.arg = &pcaccp->arg;
490	    pcaccp->io_memAccess.AccessDisable = pciIo_MemAccessDisable;
491	    pcaccp->io_memAccess.AccessEnable = pciIo_MemAccessEnable;
492	    pcaccp->io_memAccess.arg = &pcaccp->arg;
493	    pcaccp->memAccess.AccessDisable = pciMemAccessDisable;
494	    pcaccp->memAccess.AccessEnable = pciMemAccessEnable;
495	    pcaccp->memAccess.arg = &pcaccp->arg;
496
497	    pcaccp->ctrl = PCISHAREDIOCLASSES(pvp->device_class);
498
499	    savePciState(pvp, &pcaccp->save);
500	    pcaccp->arg.ctrl = pcaccp->save.command;
501	}
502    }
503}
504
505/*
506 * initPciBusState() - fill out the BusAccRec for a PCI bus.
507 * Theory: each bus is associated with one bridge connecting it
508 * to its parent bus. The address of a bridge is therefore stored
509 * in the BusAccRec of the bus it connects to. Each bus can
510 * have several bridges connecting secondary buses to it. Only one
511 * of these bridges can be open. Therefore the status of a bridge
512 * associated with a bus is stored in the BusAccRec of the parent
513 * the bridge connects to. The first member of the structure is
514 * a pointer to a function that open access to this bus. This function
515 * receives a pointer to the structure itself as argument. This
516 * design should be common to BusAccRecs of any type of buses we
517 * support. The remeinder of the structure is bus type specific.
518 * In this case it contains a pointer to the structure of the
519 * parent bus. Thus enabling access to a specific bus is simple:
520 * 1. Close any bridge going to secondary buses.
521 * 2. Climb down the ladder and enable any bridge on buses
522 *    on the path from the CPU to this bus.
523 */
524
525void
526initPciBusState(void)
527{
528    static const struct pci_id_match bridge_match = {
529	PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
530	(PCI_CLASS_BRIDGE << 16), 0x0000ff0000, 0
531    };
532    struct pci_device *dev;
533    struct pci_device_iterator *iter;
534    BusAccPtr pbap, pbap_tmp;
535
536    iter = pci_id_match_iterator_create(& bridge_match);
537    while((dev = pci_device_next(iter)) != NULL) {
538	const uint8_t subclass = (dev->device_class >> 8) & 0x0ff;
539	int primary;
540	int secondary;
541	int subordinate;
542
543
544	pci_device_get_bridge_buses(dev, &primary, &secondary, &subordinate);
545
546	pbap = xnfcalloc(1,sizeof(BusAccRec));
547	pbap->busdep.pci.bus = secondary;
548	pbap->busdep.pci.primary_bus = primary;
549	pbap->busdep_type = BUS_PCI;
550	pbap->busdep.pci.dev = dev;
551
552	pbap->set_f = pciSetBusAccess;
553
554	switch (subclass) {
555	case PCI_SUBCLASS_BRIDGE_HOST:
556	    pbap->type = BUS_PCI;
557	    break;
558	case PCI_SUBCLASS_BRIDGE_PCI:
559	case PCI_SUBCLASS_BRIDGE_CARDBUS:
560	    pbap->type = BUS_PCI;
561	    pbap->save_f = savePciBusState;
562	    pbap->restore_f = restorePciBusState;
563	    pbap->enable_f = pciBusAccessEnable;
564	    pbap->disable_f = pciBusAccessDisable;
565	    savePciBusState(pbap);
566	    break;
567	}
568	pbap->next = xf86BusAccInfo;
569	xf86BusAccInfo = pbap;
570    }
571
572    pci_iterator_destroy(iter);
573
574    for (pbap = xf86BusAccInfo; pbap; pbap = pbap->next) {
575	pbap->primary = NULL;
576
577	if (pbap->busdep_type == BUS_PCI
578	    && pbap->busdep.pci.primary_bus > -1) {
579	    pbap_tmp = xf86BusAccInfo;
580	    while (pbap_tmp) {
581		if (pbap_tmp->busdep_type == BUS_PCI &&
582		    pbap_tmp->busdep.pci.bus == pbap->busdep.pci.primary_bus) {
583		    /* Don't create loops */
584		    if (pbap == pbap_tmp)
585			break;
586		    pbap->primary = pbap_tmp;
587		    break;
588		}
589		pbap_tmp = pbap_tmp->next;
590	    }
591	}
592    }
593}
594
595void
596PciStateEnter(void)
597{
598#if 0
599    unsigned i;
600
601    if (xf86PciVideoInfo == NULL)
602	return;
603
604    for ( i = 0 ; xf86PciVideoInfo[i] != NULL ; i++ ) {
605	pciAccPtr paccp = (pciAccPtr) xf86PciVideoInfo[i]->user_data;
606
607 	if ( (paccp != NULL) && paccp->ctrl ) {
608	    savePciState(paccp->arg.dev, &paccp->save);
609	    restorePciState(paccp->arg.dev, &paccp->restore);
610	    paccp->arg.ctrl = paccp->restore.command;
611	}
612    }
613#endif
614}
615
616void
617PciBusStateEnter(void)
618{
619#if 0
620    BusAccPtr pbap = xf86BusAccInfo;
621
622    while (pbap) {
623	if (pbap->save_f)
624	    pbap->save_f(pbap);
625	pbap = pbap->next;
626    }
627#endif
628}
629
630void
631PciStateLeave(void)
632{
633#if 0
634    unsigned i;
635
636    if (xf86PciVideoInfo == NULL)
637	return;
638
639    for ( i = 0 ; xf86PciVideoInfo[i] != NULL ; i++ ) {
640	pciAccPtr paccp = (pciAccPtr) xf86PciVideoInfo[i]->user_data;
641
642 	if ( (paccp != NULL) && paccp->ctrl ) {
643	    savePciState(paccp->arg.dev, &paccp->restore);
644	    restorePciState(paccp->arg.dev, &paccp->save);
645	}
646    }
647#endif
648}
649
650void
651PciBusStateLeave(void)
652{
653#if 0
654    BusAccPtr pbap = xf86BusAccInfo;
655
656    while (pbap) {
657	if (pbap->restore_f)
658	    pbap->restore_f(pbap);
659	pbap = pbap->next;
660    }
661#endif
662}
663
664void
665DisablePciAccess(void)
666{
667#if 0
668    unsigned i;
669
670    if (xf86PciVideoInfo == NULL)
671	return;
672
673    for ( i = 0 ; xf86PciVideoInfo[i] != NULL ; i++ ) {
674	pciAccPtr paccp = (pciAccPtr) xf86PciVideoInfo[i]->user_data;
675
676 	if ( (paccp != NULL) && paccp->ctrl ) {
677	    pciIo_MemAccessDisable(paccp->io_memAccess.arg);
678	}
679    }
680#endif
681}
682
683void
684DisablePciBusAccess(void)
685{
686#if 0
687    BusAccPtr pbap = xf86BusAccInfo;
688
689    while (pbap) {
690	if (pbap->disable_f)
691	    pbap->disable_f(pbap);
692	if (pbap->primary)
693	    pbap->primary->current = NULL;
694	pbap = pbap->next;
695    }
696#endif
697}
698
699/*
700 * If the slot requested is already in use, return -1.
701 * Otherwise, claim the slot for the screen requesting it.
702 */
703
704_X_EXPORT int
705xf86ClaimPciSlot(struct pci_device * d, DriverPtr drvp,
706		 int chipset, GDevPtr dev, Bool active)
707{
708    EntityPtr p = NULL;
709    pciAccPtr paccp = (pciAccPtr) d->user_data;
710    BusAccPtr pbap = xf86BusAccInfo;
711    const unsigned bus = PCI_MAKE_BUS(d->domain, d->bus);
712
713    int num;
714
715    if (xf86CheckPciSlot(d)) {
716	num = xf86AllocateEntity();
717	p = xf86Entities[num];
718	p->driver = drvp;
719	p->chipset = chipset;
720	p->bus.type = BUS_PCI;
721	p->bus.id.pci = d;
722	p->active = active;
723	p->inUse = FALSE;
724	if (dev)
725            xf86AddDevToEntity(num, dev);
726	/* Here we initialize the access structure */
727	p->access = xnfcalloc(1,sizeof(EntityAccessRec));
728	if (paccp != NULL) {
729	    p->access->fallback = & paccp->io_memAccess;
730	    p->access->pAccess = & paccp->io_memAccess;
731	    paccp->ctrl = TRUE; /* mark control if not already */
732	}
733	else {
734	    p->access->fallback = &AccessNULL;
735	    p->access->pAccess = &AccessNULL;
736	}
737
738	p->busAcc = NULL;
739	while (pbap) {
740	    if (pbap->type == BUS_PCI && pbap->busdep.pci.bus == bus)
741		p->busAcc = pbap;
742	    pbap = pbap->next;
743	}
744
745	pciSlotClaimed = TRUE;
746
747	if (active) {
748	    /* Map in this domain's I/O space */
749	   p->domainIO = xf86MapLegacyIO(d);
750	}
751
752 	return num;
753    } else
754 	return -1;
755}
756
757/*
758 * Parse a BUS ID string, and return the PCI bus parameters if it was
759 * in the correct format for a PCI bus id.
760 */
761
762_X_EXPORT Bool
763xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func)
764{
765    /*
766     * The format is assumed to be "bus[@domain]:device[:func]", where domain,
767     * bus, device and func are decimal integers.  domain and func may be
768     * omitted and assumed to be zero, although doing this isn't encouraged.
769     */
770
771    char *p, *s, *d;
772    const char *id;
773    int i;
774
775    if (StringToBusType(busID, &id) != BUS_PCI)
776	return FALSE;
777
778    s = xstrdup(id);
779    p = strtok(s, ":");
780    if (p == NULL || *p == 0) {
781	xfree(s);
782	return FALSE;
783    }
784    d = strpbrk(p, "@");
785    if (d != NULL) {
786	*(d++) = 0;
787	for (i = 0; d[i] != 0; i++) {
788	    if (!isdigit(d[i])) {
789		xfree(s);
790		return FALSE;
791	    }
792	}
793    }
794    for (i = 0; p[i] != 0; i++) {
795	if (!isdigit(p[i])) {
796	    xfree(s);
797	    return FALSE;
798	}
799    }
800    *bus = atoi(p);
801    if (d != NULL && *d != 0)
802	*bus += atoi(d) << 8;
803    p = strtok(NULL, ":");
804    if (p == NULL || *p == 0) {
805	xfree(s);
806	return FALSE;
807    }
808    for (i = 0; p[i] != 0; i++) {
809	if (!isdigit(p[i])) {
810	    xfree(s);
811	    return FALSE;
812	}
813    }
814    *device = atoi(p);
815    *func = 0;
816    p = strtok(NULL, ":");
817    if (p == NULL || *p == 0) {
818	xfree(s);
819	return TRUE;
820    }
821    for (i = 0; p[i] != 0; i++) {
822	if (!isdigit(p[i])) {
823	    xfree(s);
824	    return FALSE;
825	}
826    }
827    *func = atoi(p);
828    xfree(s);
829    return TRUE;
830}
831
832/*
833 * Compare a BUS ID string with a PCI bus id.  Return TRUE if they match.
834 */
835
836_X_EXPORT Bool
837xf86ComparePciBusString(const char *busID, int bus, int device, int func)
838{
839    int ibus, idevice, ifunc;
840
841    if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) {
842	return bus == ibus && device == idevice && func == ifunc;
843    } else {
844	return FALSE;
845    }
846}
847
848/*
849 * xf86IsPrimaryPci() -- return TRUE if primary device
850 * is PCI and bus, dev and func numbers match.
851 */
852
853_X_EXPORT Bool
854xf86IsPrimaryPci(struct pci_device *pPci)
855{
856    return ((primaryBus.type == BUS_PCI) && (pPci == primaryBus.id.pci));
857}
858
859/*
860 * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity.
861 */
862_X_EXPORT struct pci_device *
863xf86GetPciInfoForEntity(int entityIndex)
864{
865    EntityPtr p;
866
867    if (entityIndex >= xf86NumEntities)
868	return NULL;
869
870    p = xf86Entities[entityIndex];
871    return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL;
872}
873
874/*
875 * xf86CheckPciMemBase() checks that the memory base value matches one of the
876 * PCI base address register values for the given PCI device.
877 */
878_X_EXPORT Bool
879xf86CheckPciMemBase( struct pci_device * pPci, memType base )
880{
881    int i;
882
883    for (i = 0; i < 6; i++)
884	if (base == pPci->regions[i].base_addr)
885	    return TRUE;
886    return FALSE;
887}
888
889/*
890 * Check if the slot requested is free.  If it is already in use, return FALSE.
891 */
892
893_X_EXPORT Bool
894xf86CheckPciSlot(const struct pci_device *d)
895{
896    int i;
897
898    for (i = 0; i < xf86NumEntities; i++) {
899	const EntityPtr p = xf86Entities[i];
900
901	if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) {
902	    return FALSE;
903	}
904    }
905    return TRUE;
906}
907
908
909void
910pciConvertRange2Host(int entityIndex, resRange *pRange)
911{
912    struct pci_device *const pvp = xf86GetPciInfoForEntity(entityIndex);
913    const PCITAG tag = PCI_MAKE_TAG(PCI_MAKE_BUS(pvp->domain, pvp->bus),
914				    pvp->dev, pvp->func);
915
916    if (pvp == NULL) {
917	return;
918    }
919
920    if (!(pRange->type & ResBus))
921	return;
922
923    switch(pRange->type & ResPhysMask) {
924    case ResMem:
925	switch(pRange->type & ResExtMask) {
926	case ResBlock:
927	    pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rBegin);
928	    pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_MEM, pRange->rEnd);
929	    break;
930	case ResSparse:
931	    pRange->rBase = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_BASE,
932						  pRange->rBegin);
933	    pRange->rMask = pciBusAddrToHostAddr(tag,PCI_MEM_SPARSE_MASK,
934						pRange->rEnd);
935	    break;
936	}
937	break;
938    case ResIo:
939	switch(pRange->type & ResExtMask) {
940	case ResBlock:
941	    pRange->rBegin = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rBegin);
942	    pRange->rEnd = pciBusAddrToHostAddr(tag,PCI_IO, pRange->rEnd);
943	    break;
944	case ResSparse:
945	    pRange->rBase = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_BASE
946						  , pRange->rBegin);
947	    pRange->rMask = pciBusAddrToHostAddr(tag,PCI_IO_SPARSE_MASK
948						, pRange->rEnd);
949	    break;
950	}
951	break;
952    }
953
954    /* Set domain number */
955    pRange->type &= ~(ResDomain | ResBus);
956    pRange->type |= pvp->domain << 24;
957}
958