Diff markup
1 /* 1 /*
2 * Device driver for the SYMBIOS/LSILOGIC 53C8 2 * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
3 * of PCI-SCSI IO processors. 3 * of PCI-SCSI IO processors.
4 * 4 *
5 * Copyright (C) 1999-2001 Gerard Roudier <gr 5 * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
6 * 6 *
7 * This driver is derived from the Linux sym53 7 * This driver is derived from the Linux sym53c8xx driver.
8 * Copyright (C) 1998-2000 Gerard Roudier 8 * Copyright (C) 1998-2000 Gerard Roudier
9 * 9 *
10 * The sym53c8xx driver is derived from the nc 10 * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
11 * a port of the FreeBSD ncr driver to Linux-1 11 * a port of the FreeBSD ncr driver to Linux-1.2.13.
12 * 12 *
13 * The original ncr driver has been written fo 13 * The original ncr driver has been written for 386bsd and FreeBSD by
14 * Wolfgang Stanglmeier <wolf@c 14 * Wolfgang Stanglmeier <wolf@cologne.de>
15 * Stefan Esser <se@mi. 15 * Stefan Esser <se@mi.Uni-Koeln.de>
16 * Copyright (C) 1994 Wolfgang Stanglmeier 16 * Copyright (C) 1994 Wolfgang Stanglmeier
17 * 17 *
18 * Other major contributions: 18 * Other major contributions:
19 * 19 *
20 * NVRAM detection and reading. 20 * NVRAM detection and reading.
21 * Copyright (C) 1997 Richard Waltham <dormous 21 * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
22 * 22 *
23 *-------------------------------------------- 23 *-----------------------------------------------------------------------------
24 * 24 *
25 * This program is free software; you can redi 25 * This program is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Publi 26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either versio 27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version. 28 * (at your option) any later version.
29 * 29 *
30 * This program is distributed in the hope tha 30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the 31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR 32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details 33 * GNU General Public License for more details.
34 * 34 *
35 * You should have received a copy of the GNU 35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to t 36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 59 Temple Place, Suite 33 37 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 */ 38 */
39 39
>> 40 #ifdef __FreeBSD__
>> 41 #include <dev/sym/sym_glue.h>
>> 42 #else
40 #include "sym_glue.h" 43 #include "sym_glue.h"
>> 44 #endif
41 45
42 /* 46 /*
43 * Simple power of two buddy-like generic all 47 * Simple power of two buddy-like generic allocator.
44 * Provides naturally aligned memory chunks. 48 * Provides naturally aligned memory chunks.
45 * 49 *
46 * This simple code is not intended to be fas 50 * This simple code is not intended to be fast, but to
47 * provide power of 2 aligned memory allocati 51 * provide power of 2 aligned memory allocations.
48 * Since the SCRIPTS processor only supplies 52 * Since the SCRIPTS processor only supplies 8 bit arithmetic,
49 * this allocator allows simple and fast addr 53 * this allocator allows simple and fast address calculations
50 * from the SCRIPTS code. In addition, cache 54 * from the SCRIPTS code. In addition, cache line alignment
51 * is guaranteed for power of 2 cache line si 55 * is guaranteed for power of 2 cache line size.
52 * 56 *
53 * This allocator has been developped for the 57 * This allocator has been developped for the Linux sym53c8xx
54 * driver, since this O/S does not provide na 58 * driver, since this O/S does not provide naturally aligned
55 * allocations. 59 * allocations.
56 * It has the advantage of allowing the drive 60 * It has the advantage of allowing the driver to use private
57 * pages of memory that will be useful if we 61 * pages of memory that will be useful if we ever need to deal
58 * with IO MMUs for PCI. 62 * with IO MMUs for PCI.
59 */ 63 */
60 static void *___sym_malloc(m_pool_p mp, int si 64 static void *___sym_malloc(m_pool_p mp, int size)
61 { 65 {
62 int i = 0; 66 int i = 0;
63 int s = (1 << SYM_MEM_SHIFT); 67 int s = (1 << SYM_MEM_SHIFT);
64 int j; 68 int j;
65 void *a; !! 69 m_addr_t a;
66 m_link_p h = mp->h; 70 m_link_p h = mp->h;
67 71
68 if (size > SYM_MEM_CLUSTER_SIZE) 72 if (size > SYM_MEM_CLUSTER_SIZE)
69 return NULL; 73 return NULL;
70 74
71 while (size > s) { 75 while (size > s) {
72 s <<= 1; 76 s <<= 1;
73 ++i; 77 ++i;
74 } 78 }
75 79
76 j = i; 80 j = i;
77 while (!h[j].next) { 81 while (!h[j].next) {
78 if (s == SYM_MEM_CLUSTER_SIZE) 82 if (s == SYM_MEM_CLUSTER_SIZE) {
79 h[j].next = (m_link_p) 83 h[j].next = (m_link_p) M_GET_MEM_CLUSTER();
80 if (h[j].next) 84 if (h[j].next)
81 h[j].next->nex 85 h[j].next->next = NULL;
82 break; 86 break;
83 } 87 }
84 ++j; 88 ++j;
85 s <<= 1; 89 s <<= 1;
86 } 90 }
87 a = h[j].next; !! 91 a = (m_addr_t) h[j].next;
88 if (a) { 92 if (a) {
89 h[j].next = h[j].next->next; 93 h[j].next = h[j].next->next;
90 while (j > i) { 94 while (j > i) {
91 j -= 1; 95 j -= 1;
92 s >>= 1; 96 s >>= 1;
93 h[j].next = (m_link_p) 97 h[j].next = (m_link_p) (a+s);
94 h[j].next->next = NULL 98 h[j].next->next = NULL;
95 } 99 }
96 } 100 }
97 #ifdef DEBUG 101 #ifdef DEBUG
98 printf("___sym_malloc(%d) = %p\n", siz 102 printf("___sym_malloc(%d) = %p\n", size, (void *) a);
99 #endif 103 #endif
100 return a; !! 104 return (void *) a;
101 } 105 }
102 106
103 /* 107 /*
104 * Counter-part of the generic allocator. 108 * Counter-part of the generic allocator.
105 */ 109 */
106 static void ___sym_mfree(m_pool_p mp, void *pt 110 static void ___sym_mfree(m_pool_p mp, void *ptr, int size)
107 { 111 {
108 int i = 0; 112 int i = 0;
109 int s = (1 << SYM_MEM_SHIFT); 113 int s = (1 << SYM_MEM_SHIFT);
110 m_link_p q; 114 m_link_p q;
111 unsigned long a, b; !! 115 m_addr_t a, b;
112 m_link_p h = mp->h; 116 m_link_p h = mp->h;
113 117
114 #ifdef DEBUG 118 #ifdef DEBUG
115 printf("___sym_mfree(%p, %d)\n", ptr, 119 printf("___sym_mfree(%p, %d)\n", ptr, size);
116 #endif 120 #endif
117 121
118 if (size > SYM_MEM_CLUSTER_SIZE) 122 if (size > SYM_MEM_CLUSTER_SIZE)
119 return; 123 return;
120 124
121 while (size > s) { 125 while (size > s) {
122 s <<= 1; 126 s <<= 1;
123 ++i; 127 ++i;
124 } 128 }
125 129
126 a = (unsigned long)ptr; !! 130 a = (m_addr_t) ptr;
127 131
128 while (1) { 132 while (1) {
129 if (s == SYM_MEM_CLUSTER_SIZE) 133 if (s == SYM_MEM_CLUSTER_SIZE) {
130 #ifdef SYM_MEM_FREE_UNUSED 134 #ifdef SYM_MEM_FREE_UNUSED
131 M_FREE_MEM_CLUSTER((vo !! 135 M_FREE_MEM_CLUSTER(a);
132 #else 136 #else
133 ((m_link_p) a)->next = 137 ((m_link_p) a)->next = h[i].next;
134 h[i].next = (m_link_p) 138 h[i].next = (m_link_p) a;
135 #endif 139 #endif
136 break; 140 break;
137 } 141 }
138 b = a ^ s; 142 b = a ^ s;
139 q = &h[i]; 143 q = &h[i];
140 while (q->next && q->next != ( 144 while (q->next && q->next != (m_link_p) b) {
141 q = q->next; 145 q = q->next;
142 } 146 }
143 if (!q->next) { 147 if (!q->next) {
144 ((m_link_p) a)->next = 148 ((m_link_p) a)->next = h[i].next;
145 h[i].next = (m_link_p) 149 h[i].next = (m_link_p) a;
146 break; 150 break;
147 } 151 }
148 q->next = q->next->next; 152 q->next = q->next->next;
149 a = a & b; 153 a = a & b;
150 s <<= 1; 154 s <<= 1;
151 ++i; 155 ++i;
152 } 156 }
153 } 157 }
154 158
155 /* 159 /*
156 * Verbose and zeroing allocator that wrapps 160 * Verbose and zeroing allocator that wrapps to the generic allocator.
157 */ 161 */
158 static void *__sym_calloc2(m_pool_p mp, int si 162 static void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
159 { 163 {
160 void *p; 164 void *p;
161 165
162 p = ___sym_malloc(mp, size); 166 p = ___sym_malloc(mp, size);
163 167
164 if (DEBUG_FLAGS & DEBUG_ALLOC) { 168 if (DEBUG_FLAGS & DEBUG_ALLOC) {
165 printf ("new %-10s[%4d] @%p.\n 169 printf ("new %-10s[%4d] @%p.\n", name, size, p);
166 } 170 }
167 171
168 if (p) 172 if (p)
169 memset(p, 0, size); 173 memset(p, 0, size);
170 else if (uflags & SYM_MEM_WARN) 174 else if (uflags & SYM_MEM_WARN)
171 printf ("__sym_calloc2: failed 175 printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
172 return p; 176 return p;
173 } 177 }
174 #define __sym_calloc(mp, s, n) __sym_calloc2( 178 #define __sym_calloc(mp, s, n) __sym_calloc2(mp, s, n, SYM_MEM_WARN)
175 179
176 /* 180 /*
177 * Its counter-part. 181 * Its counter-part.
178 */ 182 */
179 static void __sym_mfree(m_pool_p mp, void *ptr 183 static void __sym_mfree(m_pool_p mp, void *ptr, int size, char *name)
180 { 184 {
181 if (DEBUG_FLAGS & DEBUG_ALLOC) 185 if (DEBUG_FLAGS & DEBUG_ALLOC)
182 printf ("freeing %-10s[%4d] @% 186 printf ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
183 187
184 ___sym_mfree(mp, ptr, size); 188 ___sym_mfree(mp, ptr, size);
185 } 189 }
186 190
187 /* 191 /*
188 * Default memory pool we donnot need to invo 192 * Default memory pool we donnot need to involve in DMA.
189 * 193 *
190 * With DMA abstraction, we use functions (me 194 * With DMA abstraction, we use functions (methods), to
191 * distinguish between non DMAable memory and 195 * distinguish between non DMAable memory and DMAable memory.
192 */ 196 */
193 static void *___mp0_get_mem_cluster(m_pool_p m !! 197 static m_addr_t ___mp0_get_mem_cluster(m_pool_p mp)
194 { 198 {
195 void *m = sym_get_mem_cluster(); !! 199 m_addr_t m = (m_addr_t) sym_get_mem_cluster();
196 if (m) 200 if (m)
197 ++mp->nump; 201 ++mp->nump;
198 return m; 202 return m;
199 } 203 }
200 204
201 #ifdef SYM_MEM_FREE_UNUSED 205 #ifdef SYM_MEM_FREE_UNUSED
202 static void ___mp0_free_mem_cluster(m_pool_p m !! 206 static void ___mp0_free_mem_cluster(m_pool_p mp, m_addr_t m)
203 { 207 {
204 sym_free_mem_cluster(m); 208 sym_free_mem_cluster(m);
205 --mp->nump; 209 --mp->nump;
206 } 210 }
>> 211 #endif
>> 212
>> 213 #ifdef SYM_MEM_FREE_UNUSED
>> 214 static struct sym_m_pool mp0 =
>> 215 {NULL, ___mp0_get_mem_cluster, ___mp0_free_mem_cluster};
207 #else 216 #else
208 #define ___mp0_free_mem_cluster NULL !! 217 static struct sym_m_pool mp0 =
>> 218 {NULL, ___mp0_get_mem_cluster};
209 #endif 219 #endif
210 220
211 static struct sym_m_pool mp0 = { !! 221 /*
212 NULL, !! 222 * Actual memory allocation routine for non-DMAed memory.
213 ___mp0_get_mem_cluster, !! 223 */
214 ___mp0_free_mem_cluster !! 224 void *sym_calloc_unlocked(int size, char *name)
215 }; !! 225 {
>> 226 void *m;
>> 227 m = __sym_calloc(&mp0, size, name);
>> 228 return m;
>> 229 }
>> 230
>> 231 /*
>> 232 * Its counter-part.
>> 233 */
>> 234 void sym_mfree_unlocked(void *ptr, int size, char *name)
>> 235 {
>> 236 __sym_mfree(&mp0, ptr, size, name);
>> 237 }
216 238
217 /* 239 /*
218 * Methods that maintains DMAable pools accor 240 * Methods that maintains DMAable pools according to user allocations.
219 * New pools are created on the fly when a ne 241 * New pools are created on the fly when a new pool id is provided.
220 * They are deleted on the fly when they get 242 * They are deleted on the fly when they get emptied.
221 */ 243 */
222 /* Get a memory cluster that matches the DMA c !! 244 /* Get a memory cluster that matches the DMA contraints of a given pool */
223 static void * ___get_dma_mem_cluster(m_pool_p !! 245 static m_addr_t ___get_dma_mem_cluster(m_pool_p mp)
224 { 246 {
225 m_vtob_p vbp; 247 m_vtob_p vbp;
226 void *vaddr; !! 248 m_addr_t vaddr;
227 249
228 vbp = __sym_calloc(&mp0, sizeof(*vbp), 250 vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB");
229 if (!vbp) 251 if (!vbp)
230 goto out_err; 252 goto out_err;
231 253
232 vaddr = sym_m_get_dma_mem_cluster(mp, 254 vaddr = sym_m_get_dma_mem_cluster(mp, vbp);
233 if (vaddr) { 255 if (vaddr) {
234 int hc = VTOB_HASH_CODE(vaddr) 256 int hc = VTOB_HASH_CODE(vaddr);
235 vbp->next = mp->vtob[hc]; 257 vbp->next = mp->vtob[hc];
236 mp->vtob[hc] = vbp; 258 mp->vtob[hc] = vbp;
237 ++mp->nump; 259 ++mp->nump;
>> 260 return (m_addr_t) vaddr;
238 } 261 }
239 return vaddr; 262 return vaddr;
240 out_err: 263 out_err:
241 return NULL; !! 264 return 0;
242 } 265 }
243 266
244 #ifdef SYM_MEM_FREE_UNUSED 267 #ifdef SYM_MEM_FREE_UNUSED
245 /* Free a memory cluster and associated resour 268 /* Free a memory cluster and associated resources for DMA */
246 static void ___free_dma_mem_cluster(m_pool_p m !! 269 static void ___free_dma_mem_cluster(m_pool_p mp, m_addr_t m)
247 { 270 {
248 m_vtob_p *vbpp, vbp; 271 m_vtob_p *vbpp, vbp;
249 int hc = VTOB_HASH_CODE(m); 272 int hc = VTOB_HASH_CODE(m);
250 273
251 vbpp = &mp->vtob[hc]; 274 vbpp = &mp->vtob[hc];
252 while (*vbpp && (*vbpp)->vaddr != m) 275 while (*vbpp && (*vbpp)->vaddr != m)
253 vbpp = &(*vbpp)->next; 276 vbpp = &(*vbpp)->next;
254 if (*vbpp) { 277 if (*vbpp) {
255 vbp = *vbpp; 278 vbp = *vbpp;
256 *vbpp = (*vbpp)->next; 279 *vbpp = (*vbpp)->next;
257 sym_m_free_dma_mem_cluster(mp, 280 sym_m_free_dma_mem_cluster(mp, vbp);
258 __sym_mfree(&mp0, vbp, sizeof( 281 __sym_mfree(&mp0, vbp, sizeof(*vbp), "VTOB");
259 --mp->nump; 282 --mp->nump;
260 } 283 }
261 } 284 }
262 #endif 285 #endif
263 286
264 /* Fetch the memory pool for a given pool id ( 287 /* Fetch the memory pool for a given pool id (i.e. DMA constraints) */
265 static inline m_pool_p ___get_dma_pool(m_pool_ !! 288 static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
266 { 289 {
267 m_pool_p mp; 290 m_pool_p mp;
268 for (mp = mp0.next; 291 for (mp = mp0.next;
269 mp && !sym_m_pool_match(mp->de 292 mp && !sym_m_pool_match(mp->dev_dmat, dev_dmat);
270 mp = mp->next); 293 mp = mp->next);
271 return mp; 294 return mp;
272 } 295 }
273 296
274 /* Create a new memory DMAable pool (when fetc 297 /* Create a new memory DMAable pool (when fetch failed) */
275 static m_pool_p ___cre_dma_pool(m_pool_ident_t 298 static m_pool_p ___cre_dma_pool(m_pool_ident_t dev_dmat)
276 { 299 {
277 m_pool_p mp = __sym_calloc(&mp0, sizeo !! 300 m_pool_p mp = NULL;
>> 301
>> 302 mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
278 if (mp) { 303 if (mp) {
279 mp->dev_dmat = dev_dmat; 304 mp->dev_dmat = dev_dmat;
280 mp->get_mem_cluster = ___get_d !! 305 if (!sym_m_create_dma_mem_tag(mp)) {
>> 306 mp->get_mem_cluster = ___get_dma_mem_cluster;
281 #ifdef SYM_MEM_FREE_UNUSED 307 #ifdef SYM_MEM_FREE_UNUSED
282 mp->free_mem_cluster = ___free !! 308 mp->free_mem_cluster = ___free_dma_mem_cluster;
283 #endif 309 #endif
284 mp->next = mp0.next; !! 310 mp->next = mp0.next;
285 mp0.next = mp; !! 311 mp0.next = mp;
286 return mp; !! 312 return mp;
>> 313 }
287 } 314 }
>> 315 if (mp)
>> 316 __sym_mfree(&mp0, mp, sizeof(*mp), "MPOOL");
288 return NULL; 317 return NULL;
289 } 318 }
290 319
291 #ifdef SYM_MEM_FREE_UNUSED 320 #ifdef SYM_MEM_FREE_UNUSED
292 /* Destroy a DMAable memory pool (when got emp 321 /* Destroy a DMAable memory pool (when got emptied) */
293 static void ___del_dma_pool(m_pool_p p) 322 static void ___del_dma_pool(m_pool_p p)
294 { 323 {
295 m_pool_p *pp = &mp0.next; 324 m_pool_p *pp = &mp0.next;
296 325
297 while (*pp && *pp != p) 326 while (*pp && *pp != p)
298 pp = &(*pp)->next; 327 pp = &(*pp)->next;
299 if (*pp) { 328 if (*pp) {
300 *pp = (*pp)->next; 329 *pp = (*pp)->next;
>> 330 sym_m_delete_dma_mem_tag(p);
301 __sym_mfree(&mp0, p, sizeof(*p 331 __sym_mfree(&mp0, p, sizeof(*p), "MPOOL");
302 } 332 }
303 } 333 }
304 #endif 334 #endif
305 335
306 /* This lock protects only the memory allocati <<
307 static DEFINE_SPINLOCK(sym53c8xx_lock); <<
308 <<
309 /* 336 /*
310 * Actual allocator for DMAable memory. 337 * Actual allocator for DMAable memory.
311 */ 338 */
312 void *__sym_calloc_dma(m_pool_ident_t dev_dmat !! 339 void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name)
313 { 340 {
314 unsigned long flags; <<
315 m_pool_p mp; 341 m_pool_p mp;
316 void *m = NULL; 342 void *m = NULL;
317 343
318 spin_lock_irqsave(&sym53c8xx_lock, fla <<
319 mp = ___get_dma_pool(dev_dmat); 344 mp = ___get_dma_pool(dev_dmat);
320 if (!mp) 345 if (!mp)
321 mp = ___cre_dma_pool(dev_dmat) 346 mp = ___cre_dma_pool(dev_dmat);
322 if (!mp) !! 347 if (mp)
323 goto out; !! 348 m = __sym_calloc(mp, size, name);
324 m = __sym_calloc(mp, size, name); <<
325 #ifdef SYM_MEM_FREE_UNUSED 349 #ifdef SYM_MEM_FREE_UNUSED
326 if (!mp->nump) !! 350 if (mp && !mp->nump)
327 ___del_dma_pool(mp); 351 ___del_dma_pool(mp);
328 #endif 352 #endif
329 353
330 out: <<
331 spin_unlock_irqrestore(&sym53c8xx_lock <<
332 return m; 354 return m;
333 } 355 }
334 356
335 void __sym_mfree_dma(m_pool_ident_t dev_dmat, !! 357 /*
>> 358 * Its counter-part.
>> 359 */
>> 360 void
>> 361 __sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m, int size, char *name)
336 { 362 {
337 unsigned long flags; <<
338 m_pool_p mp; 363 m_pool_p mp;
339 364
340 spin_lock_irqsave(&sym53c8xx_lock, fla <<
341 mp = ___get_dma_pool(dev_dmat); 365 mp = ___get_dma_pool(dev_dmat);
342 if (!mp) !! 366 if (mp)
343 goto out; !! 367 __sym_mfree(mp, m, size, name);
344 __sym_mfree(mp, m, size, name); <<
345 #ifdef SYM_MEM_FREE_UNUSED 368 #ifdef SYM_MEM_FREE_UNUSED
346 if (!mp->nump) !! 369 if (mp && !mp->nump)
347 ___del_dma_pool(mp); 370 ___del_dma_pool(mp);
348 #endif 371 #endif
349 out: <<
350 spin_unlock_irqrestore(&sym53c8xx_lock <<
351 } 372 }
352 373
353 /* 374 /*
354 * Actual virtual to bus physical address tra 375 * Actual virtual to bus physical address translator
355 * for 32 bit addressable DMAable memory. 376 * for 32 bit addressable DMAable memory.
356 */ 377 */
357 dma_addr_t __vtobus(m_pool_ident_t dev_dmat, v !! 378 u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m)
358 { 379 {
359 unsigned long flags; <<
360 m_pool_p mp; 380 m_pool_p mp;
361 int hc = VTOB_HASH_CODE(m); 381 int hc = VTOB_HASH_CODE(m);
362 m_vtob_p vp = NULL; 382 m_vtob_p vp = NULL;
363 void *a = (void *)((unsigned long)m & !! 383 m_addr_t a = ((m_addr_t) m) & ~SYM_MEM_CLUSTER_MASK;
364 dma_addr_t b; <<
365 384
366 spin_lock_irqsave(&sym53c8xx_lock, fla <<
367 mp = ___get_dma_pool(dev_dmat); 385 mp = ___get_dma_pool(dev_dmat);
368 if (mp) { 386 if (mp) {
369 vp = mp->vtob[hc]; 387 vp = mp->vtob[hc];
370 while (vp && vp->vaddr != a) !! 388 while (vp && (m_addr_t) vp->vaddr != a)
371 vp = vp->next; 389 vp = vp->next;
372 } 390 }
373 if (!vp) 391 if (!vp)
374 panic("sym: VTOBUS FAILED!\n") 392 panic("sym: VTOBUS FAILED!\n");
375 b = vp->baddr + (m - a); !! 393 return (u32)(vp ? vp->baddr + (((m_addr_t) m) - a) : 0);
376 spin_unlock_irqrestore(&sym53c8xx_lock <<
377 return b; <<
378 } 394 }
379 395
|
This page was automatically generated by the
LXR engine.
|