initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / ia64 / sn / io / sn2 / pcibr / pcibr_ate.c
blobbb35b4424ea6aaa3e90b19a7abdab43cb0b02499
1 /*
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
4 * for more details.
6 * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
7 */
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>
17 * functions
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.
35 int
36 pcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count, struct resource *res)
38 int status = 0;
39 unsigned long flag;
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,
46 NULL, NULL);
47 if (status) {
48 /* Failed to allocate */
49 pcibr_unlock(pcibr_soft, flag);
50 return -1;
53 /* Save the resource for freeing */
54 pcibr_unlock(pcibr_soft, flag);
56 return res->start;
59 void
60 pcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count, struct resource *res)
63 bridge_ate_t ate;
64 int status = 0;
65 unsigned long flags;
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);
76 if (status)
77 BUG(); /* Ouch .. */
82 * Convert PCI-generic software flags and Bridge-specific software flags
83 * into Bridge-specific Address Translation Entry attribute bits.
85 bridge_ate_t
86 pcibr_flags_to_ate(pcibr_soft_t pcibr_soft, unsigned flags)
88 bridge_ate_t attributes;
90 /* default if nothing specified:
91 * NOBARRIER
92 * NOPREFETCH
93 * NOPRECISE
94 * COHERENT
95 * Plus the valid bit
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);
138 return (attributes);
142 * Setup an Address Translation Entry as specified. Use either the Bridge
143 * internal maps or the external map RAM, as appropriate.
145 bridge_ate_p
146 pcibr_ate_addr(pcibr_soft_t pcibr_soft,
147 int ate_index)
149 if (ate_index < pcibr_soft->bs_int_ate_size) {
150 return (pcireg_int_ate_addr(pcibr_soft, ate_index));
151 } else {
152 printk("pcibr_ate_addr(): INVALID ate_index 0x%x", ate_index);
153 return (bridge_ate_p)0;
158 * Write the ATE.
160 void
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));
169 } else {
170 printk("ate_write(): INVALID ate_index 0x%x", ate_index);
171 return;
173 ate_index++;
174 ate += IOPGSIZE;
177 pcireg_tflush_get(pcibr_soft); /* wait until Bridge PIO complete */