summaryrefslogtreecommitdiffstats
path: root/include/asm-sparc64/pbm.h
blob: 0c09bd338688d901d4c6dae75cc4c5fedcb1cfdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* $Id: pbm.h,v 1.8 1998/01/10 18:26:10 ecd Exp $
 * pbm.h: U2P PCI bus module pseudo driver software state.
 *
 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
 */

#ifndef __SPARC64_PBM_H
#define __SPARC64_PBM_H

#include <linux/bios32.h>
#include <linux/pci.h>

#include <asm/psycho.h>
#include <asm/oplib.h>

struct linux_pbm_info;

/* This is what we use to determine what the PROM has assigned so
 * far, so that we can perform assignments for addresses which
 * were not taken care of by OBP.  See psycho.c for details.
 * Per-PBM these are ordered by start address.
 */
struct pci_vma {
	struct pci_vma			*next;
	struct linux_pbm_info		*pbm;
	unsigned int			start;
	unsigned int			end;
	unsigned int			base_reg;
	unsigned int			_pad;
};

struct linux_psycho;

struct linux_pbm_info {
	struct linux_psycho		*parent;
	struct pci_vma			*IO_assignments;
	struct pci_vma			*MEM_assignments;
	int				prom_node;
	char				prom_name[64];
	struct linux_prom_pci_ranges	pbm_ranges[PROMREG_MAX];
	int				num_pbm_ranges;

	/* Now things for the actual PCI bus probes. */
	unsigned int			pci_first_busno;
	unsigned int			pci_last_busno;
	struct pci_bus			pci_bus;
};

struct linux_psycho {
	struct linux_psycho		*next;
	struct psycho_regs		*psycho_regs;
	unsigned long			*pci_config_space;
	unsigned long			*pci_IO_space;
	unsigned long			*pci_mem_space;
	u32				upa_portid;
	int				index;
	struct linux_pbm_info		pbm_A;
	struct linux_pbm_info		pbm_B;
};

/* PCI devices which are not bridges have this placed in their pci_dev
 * sysdata member.  This makes OBP aware PCI device drivers easier to
 * code.
 */
struct pcidev_cookie {
	struct linux_pbm_info		*pbm;
	int				prom_node;
};

extern struct linux_psycho *psycho_root;
extern struct linux_psycho **psycho_index_map;
extern int linux_num_psycho;

static __inline__ struct linux_psycho *
psycho_by_index(int index)
{
	if (index >= linux_num_psycho)
		return NULL;
	return psycho_index_map[index];
}

/* Special PCI IRQ encoding, this just makes life easier for the generic
 * irq registry layer, there is already enough crap in there due to sbus,
 * fhc, and dcookies.
 */
#define PCI_IRQ_IDENT		0x80000000	/* This tells irq.c what we are        */
#define PCI_IRQ_IMAP_OFF	0x7ff00000	/* Offset from first PSYCHO imap       */
#define PCI_IRQ_IMAP_OFF_SHFT	20
#define PCI_IRQ_BUSNO		0x000fc000	/* PSYCHO instance, currently unused   */
#define PCI_IRQ_BUSNO_SHFT	14
#define PCI_IRQ_IGN		0x000007c0	/* PSYCHO "Int Group Number"           */
#define PCI_IRQ_INO		0x0000003f	/* PSYCHO INO                          */

#define PCI_IRQ_P(__irq)	(((__irq) & PCI_IRQ_IDENT) != 0)

extern __inline__ unsigned int pci_irq_encode(unsigned long imap_off,
					      unsigned long psycho_instance,
					      unsigned long ign,
					      unsigned long ino)
{
	unsigned int irq;

	irq  = PCI_IRQ_IDENT;
	irq |= ((imap_off << PCI_IRQ_IMAP_OFF_SHFT) & PCI_IRQ_IMAP_OFF);
	irq |= ((psycho_instance << PCI_IRQ_BUSNO_SHFT) & PCI_IRQ_BUSNO);
	irq |= ((ign << 6) & PCI_IRQ_IGN);
	irq |= (ino & PCI_IRQ_INO);

	return irq;
}

#endif /* !(__SPARC64_PBM_H) */