2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
9 #include <linux/types.h>
10 #include <asm/sn/sgi.h>
11 #include <asm/sn/pci/pciio.h>
12 #include <asm/sn/pci/pcibr.h>
13 #include <asm/sn/pci/pcibr_private.h>
14 #include <asm/sn/pci/pci_defs.h>
19 int pcibr_ate_alloc(pcibr_soft_t
, int, struct resource
*);
20 void pcibr_ate_free(pcibr_soft_t
, int, int, struct resource
*);
21 bridge_ate_t
pcibr_flags_to_ate(pcibr_soft_t
, unsigned);
22 bridge_ate_p
pcibr_ate_addr(pcibr_soft_t
, int);
23 void ate_write(pcibr_soft_t
, int, int, bridge_ate_t
);
25 int pcibr_invalidate_ate
; /* by default don't invalidate ATE on free */
28 * Allocate "count" contiguous Bridge Address Translation Entries
29 * on the specified bridge to be used for PCI to XTALK mappings.
30 * Indices in rm map range from 1..num_entries. Indicies returned
31 * to caller range from 0..num_entries-1.
33 * Return the start index on success, -1 on failure.
36 pcibr_ate_alloc(pcibr_soft_t pcibr_soft
, int count
, struct resource
*res
)
41 memset(res
, 0, sizeof(struct resource
));
42 flag
= pcibr_lock(pcibr_soft
);
43 status
= allocate_resource( &pcibr_soft
->bs_int_ate_resource
, res
,
44 count
, pcibr_soft
->bs_int_ate_resource
.start
,
45 pcibr_soft
->bs_int_ate_resource
.end
, 1,
48 /* Failed to allocate */
49 pcibr_unlock(pcibr_soft
, flag
);
53 /* Save the resource for freeing */
54 pcibr_unlock(pcibr_soft
, flag
);
60 pcibr_ate_free(pcibr_soft_t pcibr_soft
, int index
, int count
, struct resource
*res
)
67 if (pcibr_invalidate_ate
) {
68 /* For debugging purposes, clear the valid bit in the ATE */
69 ate
= *pcibr_ate_addr(pcibr_soft
, index
);
70 ate_write(pcibr_soft
, index
, count
, (ate
& ~ATE_V
));
73 flags
= pcibr_lock(pcibr_soft
);
74 status
= release_resource(res
);
75 pcibr_unlock(pcibr_soft
, flags
);
82 * Convert PCI-generic software flags and Bridge-specific software flags
83 * into Bridge-specific Address Translation Entry attribute bits.
86 pcibr_flags_to_ate(pcibr_soft_t pcibr_soft
, unsigned flags
)
88 bridge_ate_t attributes
;
90 /* default if nothing specified:
97 attributes
= ATE_CO
| ATE_V
;
99 /* Generic macro flags
101 if (flags
& PCIIO_DMA_DATA
) { /* standard data channel */
102 attributes
&= ~ATE_BAR
; /* no barrier */
103 attributes
|= ATE_PREF
; /* prefetch on */
105 if (flags
& PCIIO_DMA_CMD
) { /* standard command channel */
106 attributes
|= ATE_BAR
; /* barrier bit on */
107 attributes
&= ~ATE_PREF
; /* disable prefetch */
109 /* Generic detail flags
111 if (flags
& PCIIO_PREFETCH
)
112 attributes
|= ATE_PREF
;
113 if (flags
& PCIIO_NOPREFETCH
)
114 attributes
&= ~ATE_PREF
;
116 /* Provider-specific flags
118 if (flags
& PCIBR_BARRIER
)
119 attributes
|= ATE_BAR
;
120 if (flags
& PCIBR_NOBARRIER
)
121 attributes
&= ~ATE_BAR
;
123 if (flags
& PCIBR_PREFETCH
)
124 attributes
|= ATE_PREF
;
125 if (flags
& PCIBR_NOPREFETCH
)
126 attributes
&= ~ATE_PREF
;
128 if (flags
& PCIBR_PRECISE
)
129 attributes
|= ATE_PREC
;
130 if (flags
& PCIBR_NOPRECISE
)
131 attributes
&= ~ATE_PREC
;
133 /* In PCI-X mode, Prefetch & Precise not supported */
134 if (IS_PCIX(pcibr_soft
)) {
135 attributes
&= ~(ATE_PREC
| ATE_PREF
);
142 * Setup an Address Translation Entry as specified. Use either the Bridge
143 * internal maps or the external map RAM, as appropriate.
146 pcibr_ate_addr(pcibr_soft_t pcibr_soft
,
149 if (ate_index
< pcibr_soft
->bs_int_ate_size
) {
150 return (pcireg_int_ate_addr(pcibr_soft
, ate_index
));
152 printk("pcibr_ate_addr(): INVALID ate_index 0x%x", ate_index
);
153 return (bridge_ate_p
)0;
161 ate_write(pcibr_soft_t pcibr_soft
, int ate_index
, int count
, bridge_ate_t ate
)
163 while (count
-- > 0) {
164 if (ate_index
< pcibr_soft
->bs_int_ate_size
) {
165 pcireg_int_ate_set(pcibr_soft
, ate_index
, ate
);
166 PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP
, pcibr_soft
->bs_vhdl
,
167 "ate_write(): ate_index=0x%x, ate=0x%lx\n",
168 ate_index
, (uint64_t)ate
));
170 printk("ate_write(): INVALID ate_index 0x%x", ate_index
);
177 pcireg_tflush_get(pcibr_soft
); /* wait until Bridge PIO complete */