nubus.c revision 1.32 1 /* $NetBSD: nubus.c,v 1.32 1997/02/28 07:54:02 scottr Exp $ */
2
3 /*
4 * Copyright (c) 1995, 1996 Allen Briggs. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Allen Briggs.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
35 #include <sys/buf.h>
36 #include <sys/conf.h>
37 #include <sys/dmap.h>
38
39 #include <vm/vm.h>
40 #include <vm/vm_kern.h>
41 #include <vm/vm_map.h>
42
43 #include <machine/autoconf.h>
44 #include <machine/bus.h>
45 #include <machine/vmparam.h>
46 #include <machine/param.h>
47 #include <machine/cpu.h>
48 #include <machine/pte.h>
49
50 #include <vm/vm.h>
51
52 #include "nubus.h"
53
54 #ifdef DEBUG
55 static int nubus_debug = 0x01;
56 #define NDB_PROBE 0x1
57 #define NDB_FOLLOW 0x2
58 #define NDB_ARITH 0x4
59 #endif
60
61 static int nubus_print __P((void *, const char *));
62 static int nubus_match __P((struct device *, struct cfdata *, void *));
63 static void nubus_attach __P((struct device *, struct device *, void *));
64 int nubus_video_resource __P((int));
65
66 static int probe_slot __P((int slot, nubus_slot *fmt));
67 static u_long IncPtr __P((nubus_slot *fmt, u_long base, long amt));
68 static u_long nubus_calc_CRC __P((nubus_slot *fmt));
69 static u_char GetByte __P((nubus_slot *fmt, u_long ptr));
70 #ifdef notyet
71 /* unused */ static u_short GetWord __P((nubus_slot *fmt, u_long ptr));
72 #endif
73 static u_long GetLong __P((nubus_slot *fmt, u_long ptr));
74
75 static int nubus_peek __P((vm_offset_t, int));
76 static char *nubus_mapin __P((int, int));
77
78 struct cfattach nubus_ca = {
79 sizeof(struct nubus_softc), nubus_match, nubus_attach
80 };
81
82 struct cfdriver nubus_cd = {
83 NULL, "nubus", DV_DULL,
84 };
85
86 static int
87 nubus_match(parent, cf, aux)
88 struct device *parent;
89 struct cfdata *cf;
90 void *aux;
91 {
92 static int nubus_matched = 0;
93
94 /* Allow only one instance. */
95 if (nubus_matched)
96 return (0);
97
98 nubus_matched = 1;
99 return (1);
100 }
101
102 static void
103 nubus_attach(parent, self, aux)
104 struct device *parent, *self;
105 void *aux;
106 {
107 struct nubus_attach_args na_args;
108 nubus_slot fmtblock;
109 nubus_dir dir;
110 nubus_dirent dirent;
111 nubus_type slottype;
112 int i, rsrcid;
113
114 printf("\n");
115
116 for (i = NUBUS_MIN_SLOT; i <= NUBUS_MAX_SLOT; i++) {
117 if (probe_slot(i, &fmtblock) <= 0)
118 continue;
119
120 if ((rsrcid = nubus_video_resource(i)) == (-1))
121 rsrcid = 0x80;
122
123 nubus_get_main_dir(&fmtblock, &dir);
124
125 if (nubus_find_rsrc(&fmtblock, &dir, rsrcid, &dirent) <= 0)
126 continue;
127
128 nubus_get_dir_from_rsrc(&fmtblock, &dirent, &dir);
129
130 if (nubus_find_rsrc(&fmtblock, &dir, NUBUS_RSRC_TYPE,
131 &dirent) <= 0)
132 continue;
133
134 if (nubus_get_ind_data(&fmtblock, &dirent,
135 (caddr_t) &slottype, sizeof(nubus_type)) <= 0)
136 continue;
137
138 na_args.slot = i;
139 na_args.rsrcid = rsrcid;
140 na_args.category = slottype.category;
141 na_args.type = slottype.type;
142 na_args.drsw = slottype.drsw;
143 na_args.drhw = slottype.drhw;
144 na_args.fmt = &fmtblock;
145
146 config_found(self, &na_args, nubus_print);
147 }
148 }
149
150 static int
151 nubus_print(aux, name)
152 void *aux;
153 const char *name;
154 {
155 struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
156
157 if (name) {
158 printf("%s: slot %x: %s ", name, na->fmt->slot,
159 nubus_get_card_name(na->fmt));
160 printf("(Vendor: %s, ",
161 nubus_get_vendor(na->fmt, NUBUS_RSRC_VEND_ID));
162 printf("Part: %s)",
163 nubus_get_vendor(na->fmt, NUBUS_RSRC_VEND_PART));
164 }
165 return (UNCONF);
166 }
167
168 int
169 nubus_video_resource(slot)
170 int slot;
171 {
172 extern u_int16_t mac68k_vrsrc_vec[];
173 int i;
174
175 for (i = 0 ; i < 6 ; i++)
176 if ((mac68k_vrsrc_vec[i] & 0xff) == slot)
177 return ((mac68k_vrsrc_vec[i] >> 8) & 0xff);
178 return (-1);
179 }
180
181 /*
182 * Probe a given nubus slot. If a card is there and we can get the
183 * format block from it's clutching decl. ROMs, fill the format block
184 * and return non-zero. If we can't find a card there with a valid
185 * decl. ROM, return 0.
186 *
187 * First, we check to see if we can access the memory at the tail
188 * end of the slot. If so, then we check for a bytelanes byte. We
189 * could probably just return a failure status if we bus error on
190 * the first try, but there really is little reason not to go ahead
191 * and check the other three locations in case there's a wierd card
192 * out there.
193 *
194 * Checking for a card involves locating the "bytelanes" byte which
195 * tells us how to interpret the declaration ROM's data. The format
196 * block is at the top of the card's standard memory space and the
197 * bytelanes byte is at the end of that block.
198 *
199 * After some inspection of the bytelanes byte, it appears that it
200 * takes the form 0xXY where Y is a bitmask of the bytelanes in use
201 * and X is a bitmask of the lanes to ignore. Hence, (X ^ Y) == 0
202 * and (less obviously), Y will have the upper N bits clear if it is
203 * found N bytes from the last possible location. Both that and
204 * the exclusive-or check are made.
205 *
206 * If a valid
207 */
208 static u_char nbits[]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
209 static int
210 probe_slot(slot, fmt)
211 int slot;
212 nubus_slot *fmt;
213 {
214 caddr_t rom_probe;
215 vm_offset_t hdr;
216 #ifdef DEBUG
217 vm_offset_t pa;
218 #endif
219 u_int data;
220 int hdr_size, i;
221
222 fmt->bytelanes = 0;
223 fmt->slot = (u_long)slot;
224
225 rom_probe = (caddr_t) (NUBUS_SLOT2PA(fmt->slot) + NBMEMSIZE);
226
227 #ifdef DEBUG
228 if (nubus_debug & NDB_PROBE) {
229 pa = pmap_extract(pmap_kernel(), (vm_offset_t) rom_probe - 1);
230 printf("probing slot %d, first probe at 0x%p (PA 0x%lx).\n",
231 slot, rom_probe - 1, pa);
232 }
233 #endif
234
235 for (i = 4; i && (fmt->bytelanes == 0); i--) {
236
237 rom_probe--;
238
239 data = nubus_peek((vm_offset_t) rom_probe, 1);
240 if (data == -1)
241 continue;
242
243 if (data == 0)
244 continue;
245
246 if ( ((((data & 0xf0) >> 4) ^ (data & 0x0f)) == 0x0f)
247 && ((data & 0x0f) < (1 << i)) ) {
248 fmt->bytelanes = data;
249 fmt->step = nbits[(data & 0x0f)];
250 }
251 }
252 #ifdef DEBUG
253 if (nubus_debug & NDB_PROBE)
254 if (fmt->bytelanes == 0)
255 printf("bytelanes not found for slot 0x%x.\n", slot);
256 #endif
257
258 if (fmt->bytelanes == 0)
259 return 0;
260
261 #ifdef DEBUG
262 if (nubus_debug & NDB_PROBE)
263 printf("bytelanes of 0x%x found for slot 0x%x.\n",
264 fmt->bytelanes, slot);
265 #endif
266
267 hdr_size = 20;
268
269 /*
270 * Go ahead and attempt to load format header.
271 * First, we need to find the first byte beyond memory that
272 * would be valid. This is necessary for NUBUS_ROM_offset()
273 * to work.
274 */
275 hdr = (vm_offset_t)
276 nubus_mapin(NUBUS_SLOT2PA(fmt->slot), NBMEMSIZE);
277 if (hdr == NULL) {
278 printf("Failed to map %d bytes for NuBUS slot %d probe. ",
279 NBMEMSIZE, fmt->slot);
280 printf("Physical slot address %x\n",
281 (unsigned int) NUBUS_SLOT2PA(fmt->slot));
282 }
283 fmt->virtual_base = hdr;
284 hdr += NBMEMSIZE;
285
286 i = 0x10 | (fmt->bytelanes & 0x0f);
287 while ((i & 1) == 0) {
288 hdr++;
289 i >>= 1;
290 }
291 fmt->top = hdr;
292 hdr = IncPtr(fmt, hdr, -hdr_size);
293 #ifdef DEBUG
294 if (nubus_debug & NDB_PROBE)
295 printf("fmt->top is 0x%lx, that minus 0x%x puts us at 0x%lx.\n",
296 fmt->top, hdr_size, hdr);
297 #if 0
298 for (i=1 ; i < 8 ; i++) {
299 printf("0x%x - 0x%x = 0x%x, + 0x%x = 0x%x.\n",
300 hdr, i, IncPtr(fmt, hdr, -i),
301 i, IncPtr(fmt, hdr, i));
302 }
303 #endif
304 #endif
305
306 fmt->directory_offset = 0xff000000 | GetLong(fmt, hdr);
307 hdr = IncPtr(fmt, hdr, 4);
308 fmt->length = GetLong(fmt, hdr);
309 hdr = IncPtr(fmt, hdr, 4);
310 fmt->crc = GetLong(fmt, hdr);
311 hdr = IncPtr(fmt, hdr, 4);
312 fmt->revision_level = GetByte(fmt, hdr);
313 hdr = IncPtr(fmt, hdr, 1);
314 fmt->format = GetByte(fmt, hdr);
315 hdr = IncPtr(fmt, hdr, 1);
316 fmt->test_pattern = GetLong(fmt, hdr);
317
318 #ifdef DEBUG
319 if (nubus_debug & NDB_PROBE) {
320 printf("Directory offset 0x%x\t", fmt->directory_offset);
321 printf("Length 0x%x\t", fmt->length);
322 printf("CRC 0x%x\n", fmt->crc);
323 printf("Revision level 0x%x\t", fmt->revision_level);
324 printf("Format 0x%x\t", fmt->format);
325 printf("Test Pattern 0x%x\n", fmt->test_pattern);
326 }
327 #endif
328
329 if ((fmt->directory_offset & 0x00ff0000) == 0) {
330 printf("Invalid looking directory offset (0x%x)!\n",
331 fmt->directory_offset);
332 return 0;
333 }
334 if (fmt->test_pattern != NUBUS_ROM_TEST_PATTERN) {
335 printf("Nubus--test pattern invalid:\n");
336 printf(" slot 0x%x, bytelanes 0x%x?\n",
337 fmt->slot, fmt->bytelanes);
338 printf(" read test 0x%x, compare with 0x%x.\n",
339 fmt->test_pattern, NUBUS_ROM_TEST_PATTERN);
340 return 0;
341 }
342
343 /* Perform CRC */
344 if (fmt->crc != nubus_calc_CRC(fmt)) {
345 printf("Nubus--crc check failed, slot 0x%x.\n",
346 fmt->slot);
347 return 0;
348 }
349
350 return 1;
351 }
352
353 /*
354 * Compute byte offset on card, taking into account bytelanes.
355 * Base must be on a valid bytelane for this function to work.
356 * Return the new address.
357 *
358 * XXX -- There has GOT to be a better way to do this.
359 */
360 static u_long
361 IncPtr(fmt, base, amt)
362 nubus_slot *fmt;
363 u_long base;
364 long amt;
365 {
366 u_char b, t;
367
368 if (!amt)
369 return base;
370
371 if (amt < 0) {
372 amt = -amt;
373 b = fmt->bytelanes;
374 t = (b << 4);
375 b <<= (3 - (base & 0x3));
376 while (amt) {
377 b <<= 1;
378 if (b == t)
379 b = fmt->bytelanes;
380 if (b & 0x08)
381 amt--;
382 base--;
383 }
384 return base;
385 }
386
387 t = (fmt->bytelanes & 0xf) | 0x10;
388 b = t >> (base & 0x3);
389 while (amt) {
390 b >>= 1;
391 if (b == 1)
392 b = t;
393 if (b & 1)
394 amt--;
395 base++;
396 }
397
398 return base;
399 }
400
401 static u_long
402 nubus_calc_CRC(fmt)
403 nubus_slot *fmt;
404 {
405 #if 0
406 u_long base, ptr, crc_loc, sum;
407 int i;
408
409 base = fmt->top;
410 crc_loc = NUBUS_ROM_offset(fmt, base, -12);
411 ptr = NUBUS_ROM_offset(fmt, base, -fmt->length);
412
413 sum = 0;
414 while (ptr < base)
415 roll #1, sum
416 if (ptr == crc_loc) {
417 roll #3, sum
418 ptr = IncPtr(fmt, ptr, 3);
419 } else {
420 sum += GetByte(fmt, ptr);
421 }
422 ptr = IncPtr(fmt, ptr, 1);
423 }
424
425 return sum;
426 #endif
427 return fmt->crc;
428 }
429
430 static u_char
431 GetByte(fmt, ptr)
432 nubus_slot *fmt;
433 u_long ptr;
434 {
435 return *(caddr_t)ptr;
436 }
437
438 #ifdef notyet
439 /* Nothing uses this, yet */
440 static u_short
441 GetWord(fmt, ptr)
442 nubus_slot *fmt;
443 u_long ptr;
444 {
445 u_short s;
446
447 s = (GetByte(fmt, ptr) << 8);
448 ptr = IncPtr(fmt, ptr, 1);
449 s |= GetByte(fmt, ptr);
450 return s;
451 }
452 #endif
453
454 static u_long
455 GetLong(fmt, ptr)
456 nubus_slot *fmt;
457 u_long ptr;
458 {
459 register u_long l;
460 register int i;
461
462 l = 0;
463 for ( i = 0; i < 4; i++) {
464 l = (l << 8) | GetByte(fmt, ptr);
465 ptr = IncPtr(fmt, ptr, 1);
466 }
467 return l;
468 }
469
470 void
471 nubus_get_main_dir(slot, dir_return)
472 nubus_slot *slot;
473 nubus_dir *dir_return;
474 {
475 #ifdef DEBUG
476 if (nubus_debug & NDB_FOLLOW)
477 printf("nubus_get_main_dir(0x%x, 0x%x)\n",
478 (u_int) slot, (u_int) dir_return);
479 #endif
480 dir_return->dirbase = IncPtr(slot, slot->top,
481 slot->directory_offset - 20);
482 dir_return->curr_ent = dir_return->dirbase;
483 }
484
485 int
486 nubus_find_rsrc(slot, dir, rsrcid, dirent_return)
487 nubus_slot *slot;
488 nubus_dir *dir;
489 u_int8_t rsrcid;
490 nubus_dirent *dirent_return;
491 {
492 u_long entry;
493 u_char byte;
494
495 #ifdef DEBUG
496 if (nubus_debug & NDB_FOLLOW)
497 printf("nubus_find_rsrc(0x%x, 0x%x, 0x%x, 0x%x)\n",
498 (u_int) slot, (u_int) dir, (u_int) rsrcid,
499 (u_int) dirent_return);
500 #endif
501 if (slot->test_pattern != NUBUS_ROM_TEST_PATTERN)
502 return -1;
503
504 entry = dir->curr_ent;
505 do {
506 byte = GetByte(slot, entry);
507 #ifdef DEBUG
508 if (nubus_debug & NDB_FOLLOW)
509 printf("\tFound rsrc 0x%x.\n", byte);
510 #endif
511 if (byte == rsrcid) {
512 dirent_return->myloc = entry;
513 dirent_return->rsrc_id = rsrcid;
514 entry = GetLong(slot, entry);
515 dirent_return->offset = (entry & 0x00ffffff);
516 return 1;
517 }
518 if (byte == 0xff) {
519 entry = dir->dirbase;
520 } else {
521 entry = IncPtr(slot, entry, 4);
522 }
523 } while (entry != (u_long) dir->curr_ent);
524 return 0;
525 }
526
527 void
528 nubus_get_dir_from_rsrc(slot, dirent, dir_return)
529 nubus_slot *slot;
530 nubus_dirent *dirent;
531 nubus_dir *dir_return;
532 {
533 u_long loc;
534
535 #ifdef DEBUG
536 if (nubus_debug & NDB_FOLLOW)
537 printf("nubus_get_dir_from_rsrc(0x%x, 0x%x, 0x%x).\n",
538 (u_int) slot, (u_int) dirent, (u_int) dir_return);
539 #endif
540 if ((loc = dirent->offset) & 0x800000) {
541 loc |= 0xff000000;
542 }
543 dir_return->dirbase = IncPtr(slot, dirent->myloc, loc);
544 dir_return->curr_ent = dir_return->dirbase;
545 }
546
547 int
548 nubus_get_ind_data(slot, dirent, data_return, nbytes)
549 nubus_slot *slot;
550 nubus_dirent *dirent;
551 caddr_t data_return;
552 int nbytes;
553 {
554 u_long loc;
555
556 #ifdef DEBUG
557 if (nubus_debug & NDB_FOLLOW)
558 printf("nubus_get_ind_data(0x%x, 0x%x, 0x%x, %d).\n",
559 (u_int) slot, (u_int) dirent, (u_int) data_return,
560 nbytes);
561 #endif
562 if ((loc = dirent->offset) & 0x800000) {
563 loc |= 0xff000000;
564 }
565 loc = IncPtr(slot, dirent->myloc, loc);
566
567 while (nbytes--) {
568 *data_return++ = GetByte(slot, loc);
569 loc = IncPtr(slot, loc, 1);
570 }
571 return 1;
572 }
573
574 int
575 nubus_get_c_string(slot, dirent, data_return, max_bytes)
576 nubus_slot *slot;
577 nubus_dirent *dirent;
578 caddr_t data_return;
579 int max_bytes;
580 {
581 u_long loc;
582
583 #ifdef DEBUG
584 if (nubus_debug & NDB_FOLLOW)
585 printf("nubus_get_c_string(0x%x, 0x%x, 0x%x, %d).\n",
586 (u_int) slot, (u_int) dirent, (u_int) data_return,
587 max_bytes);
588 #endif
589 if ((loc = dirent->offset) & 0x800000) {
590 loc |= 0xff000000;
591 }
592 loc = IncPtr(slot, dirent->myloc, loc);
593
594 *data_return = '\0';
595 while (max_bytes--) {
596 if ((*data_return++ = GetByte(slot, loc)) == 0)
597 return 1;
598 loc = IncPtr(slot, loc, 1);
599 }
600 return 0;
601 }
602
603 static char *huh = "???";
604
605 char *
606 nubus_get_vendor(slot, rsrc)
607 nubus_slot *slot;
608 int rsrc;
609 {
610 static char str_ret[64];
611 nubus_dir dir;
612 nubus_dirent ent;
613
614 #ifdef DEBUG
615 if (nubus_debug & NDB_FOLLOW)
616 printf("nubus_get_vendor(0x%x, 0x%x).\n", (u_int) slot, rsrc);
617 #endif
618 nubus_get_main_dir(slot, &dir);
619 if (nubus_find_rsrc(slot, &dir, 1, &ent) <= 0)
620 return huh;
621 nubus_get_dir_from_rsrc(slot, &ent, &dir);
622
623 if (nubus_find_rsrc(slot, &dir, NUBUS_RSRC_VENDORINFO, &ent) <= 0)
624 return huh;
625 nubus_get_dir_from_rsrc(slot, &ent, &dir);
626
627 if (nubus_find_rsrc(slot, &dir, rsrc, &ent) <= 0)
628 return huh;
629
630 nubus_get_c_string(slot, &ent, str_ret, 64);
631
632 return str_ret;
633 }
634
635 char *
636 nubus_get_card_name(slot)
637 nubus_slot *slot;
638 {
639 static char name_ret[64];
640 nubus_dir dir;
641 nubus_dirent ent;
642
643 #ifdef DEBUG
644 if (nubus_debug & NDB_FOLLOW)
645 printf("nubus_get_card_name(0x%lx).\n", (u_long) slot);
646 #endif
647 nubus_get_main_dir(slot, &dir);
648
649 if (nubus_find_rsrc(slot, &dir, 1, &ent) <= 0)
650 return huh;
651
652 nubus_get_dir_from_rsrc(slot, &ent, &dir);
653
654 if (nubus_find_rsrc(slot, &dir, NUBUS_RSRC_NAME, &ent) <= 0)
655 return huh;
656
657 nubus_get_c_string(slot, &ent, name_ret, 64);
658
659 return name_ret;
660 }
661
662 /*
663 * bus_*() functions adapted from sun3 generic "bus" support
664 * by Allen Briggs.
665 */
666
667 vm_offset_t tmp_vpages[1];
668
669 /*
670 * Read addr with size len (1,2,4) into val.
671 * If this generates a bus error, return -1
672 *
673 * Create a temporary mapping,
674 * Try the access using peek_*
675 * Clean up temp. mapping
676 */
677 static int
678 nubus_peek(paddr, sz)
679 vm_offset_t paddr;
680 int sz;
681 {
682 int off, pte, rv;
683 vm_offset_t pgva;
684 caddr_t va;
685
686 off = paddr & PGOFSET;
687 paddr -= off;
688 pte = (paddr & PG_FRAME) | (PG_V | PG_W | PG_CI);
689
690 pgva = tmp_vpages[0];
691 va = (caddr_t)pgva + off;
692
693 mac68k_set_pte(pgva, pte);
694 TBIS(pgva);
695
696 /*
697 * OK, try the access using one of the assembly routines
698 * that will set pcb_onfault and catch any bus errors.
699 */
700 rv = -1;
701 switch (sz) {
702 case 1:
703 if (!badbaddr(va))
704 rv = *((u_char *) va);
705 break;
706 case 2:
707 if (!badwaddr(va))
708 rv = *((u_int16_t *) va);
709 break;
710 case 4:
711 if (!badladdr(va))
712 rv = *((u_int32_t *) va);
713 break;
714 default:
715 printf("bus_peek: invalid size=%d\n", sz);
716 rv = -1;
717 }
718
719 mac68k_set_pte(pgva, PG_NV);
720 TBIS(pgva);
721
722 return rv;
723 }
724
725 static char *
726 nubus_mapin(paddr, sz)
727 int paddr, sz;
728 {
729 int off, pa, pmt=0;
730 vm_offset_t va, retval;
731
732 off = paddr & PGOFSET;
733 pa = paddr - off;
734 sz += off;
735 sz = mac68k_round_page(sz);
736
737 /* Get some kernel virtual address space. */
738 va = kmem_alloc_wait(kernel_map, sz);
739 if (va == 0)
740 panic("bus_mapin");
741 retval = va + off;
742
743 /* Map it to the specified bus. */
744 #if 0 /* XXX */
745 /* This has a problem with wrap-around... */
746 pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL);
747 #else
748 do {
749 pmap_enter(pmap_kernel(), va, pa | pmt, VM_PROT_ALL, FALSE);
750 va += NBPG;
751 pa += NBPG;
752 } while ((sz -= NBPG) > 0);
753 #endif
754
755 return ((char*)retval);
756 }
757