nubus.c revision 1.40.2.1 1 /* $NetBSD: nubus.c,v 1.40.2.1 1997/08/23 07:10:18 thorpej 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 #include <machine/viareg.h>
50
51 #include <vm/vm.h>
52
53 #include <mac68k/dev/nubus.h>
54
55 #ifdef DEBUG
56 #define NDB_PROBE 0x1
57 #define NDB_FOLLOW 0x2
58 #define NDB_ARITH 0x4
59 static int nubus_debug = 0 /* | NDB_PROBE */;
60 #endif
61
62 static int nubus_print __P((void *, const char *));
63 static int nubus_match __P((struct device *, struct cfdata *, void *));
64 static void nubus_attach __P((struct device *, struct device *, void *));
65 static int nubus_video_resource __P((int));
66
67 static int nubus_probe_slot __P((bus_space_tag_t, bus_space_handle_t,
68 int, nubus_slot *));
69 static u_int32_t nubus_calc_CRC __P((bus_space_tag_t, bus_space_handle_t,
70 nubus_slot *));
71
72 static u_long nubus_adjust_ptr __P((u_int8_t, u_long, long));
73 static u_int8_t nubus_read_1 __P((bus_space_tag_t, bus_space_handle_t,
74 u_int8_t, u_long));
75 #ifdef notyet
76 static u_int16_t nubus_read_2 __P((bus_space_tag_t, bus_space_handle_t,
77 u_int8_t, u_long));
78 #endif
79 static u_int32_t nubus_read_4 __P((bus_space_tag_t, bus_space_handle_t,
80 u_int8_t, u_long));
81
82 struct cfattach nubus_ca = {
83 sizeof(struct nubus_softc), nubus_match, nubus_attach
84 };
85
86 struct cfdriver nubus_cd = {
87 NULL, "nubus", DV_DULL,
88 };
89
90 static int
91 nubus_match(parent, cf, aux)
92 struct device *parent;
93 struct cfdata *cf;
94 void *aux;
95 {
96 static int nubus_matched = 0;
97
98 /* Allow only one instance. */
99 if (nubus_matched)
100 return (0);
101
102 nubus_matched = 1;
103 return (1);
104 }
105
106 static void
107 nubus_attach(parent, self, aux)
108 struct device *parent, *self;
109 void *aux;
110 {
111 struct nubus_attach_args na_args;
112 bus_space_tag_t bst;
113 bus_space_handle_t bsh;
114 nubus_slot fmtblock;
115 nubus_dir dir;
116 nubus_dirent dirent;
117 nubus_type slottype;
118 u_long entry;
119 int i, rsrcid;
120 u_int8_t lanes;
121
122 printf("\n");
123
124 for (i = NUBUS_MIN_SLOT; i <= NUBUS_MAX_SLOT; i++) {
125 na_args.slot = i;
126 na_args.na_tag = bst = MAC68K_BUS_SPACE_MEM;
127
128 if (bus_space_map(bst,
129 NUBUS_SLOT2PA(na_args.slot), NBMEMSIZE, 0, &bsh)) {
130 #ifdef DIAGNOSTIC
131 printf("%s: failed to map slot %x, address %p\n",
132 self->dv_xname, i, (void *)NUBUS_SLOT2PA(i));
133 #endif
134 continue;
135 }
136
137 if (nubus_probe_slot(bst, bsh, i, &fmtblock) <= 0) {
138 notfound:
139 bus_space_unmap(bst, bsh, NBMEMSIZE);
140 continue;
141 }
142
143 rsrcid = 0x80;
144 lanes = fmtblock.bytelanes;
145
146 nubus_get_main_dir(&fmtblock, &dir);
147
148 /*
149 * Get the resource for the first function on the card.
150 * This is assumed to be at resource ID 0x80. If we can
151 * not find this entry (as we can not on some video cards),
152 * check to see if we can get a different ID from the list
153 * of video resources given to us by the booter. If that
154 * doesn't work either, take the first resource following
155 * the board resource.
156 */
157 if (nubus_find_rsrc(bst, bsh,
158 &fmtblock, &dir, rsrcid, &dirent) <= 0) {
159 if ((rsrcid = nubus_video_resource(i)) == -1) {
160 /*
161 * Since nubus_find_rsrc failed, the directory
162 * is back at its base.
163 */
164 entry = dir.curr_ent;
165
166 /*
167 * All nubus cards should have a board
168 * resource, but be sure that's what it
169 * is before we skip it.
170 */
171 rsrcid = nubus_read_1(bst, bsh,
172 lanes, entry);
173 if (rsrcid == 0x1)
174 entry = nubus_adjust_ptr(lanes,
175 dir.curr_ent, 4);
176
177 rsrcid = nubus_read_1(bst, bsh, lanes, entry);
178 #ifdef DEBUG
179 if (nubus_debug & NDB_FOLLOW)
180 printf("\tUsing rsrc 0x%x.\n", rsrcid);
181 #endif
182 if (rsrcid == 0xff) /* end of chain */
183 goto notfound;
184 }
185 /*
186 * Try to find the resource passed by the booter
187 * or the one we just tracked down.
188 */
189 if (nubus_find_rsrc(bst, bsh,
190 &fmtblock, &dir, rsrcid, &dirent) <= 0)
191 goto notfound;
192 }
193
194 nubus_get_dir_from_rsrc(&fmtblock, &dirent, &dir);
195
196 if (nubus_find_rsrc(bst, bsh,
197 &fmtblock, &dir, NUBUS_RSRC_TYPE, &dirent) <= 0)
198 goto notfound;
199
200 if (nubus_get_ind_data(bst, bsh, &fmtblock, &dirent,
201 (caddr_t)&slottype, sizeof(nubus_type)) <= 0)
202 goto notfound;
203
204 /*
205 * If this is a display card, try to pull out the correct
206 * display mode as passed by the booter.
207 */
208 if (slottype.category == NUBUS_CATEGORY_DISPLAY) {
209 int r;
210
211 if ((r = nubus_video_resource(i)) != -1) {
212
213 nubus_get_main_dir(&fmtblock, &dir);
214
215 if (nubus_find_rsrc(bst, bsh,
216 &fmtblock, &dir, r, &dirent) <= 0)
217 goto notfound;
218
219 nubus_get_dir_from_rsrc(&fmtblock,
220 &dirent, &dir);
221
222 if (nubus_find_rsrc(bst, bsh, &fmtblock, &dir,
223 NUBUS_RSRC_TYPE, &dirent) <= 0)
224 goto notfound;
225
226 if (nubus_get_ind_data(bst, bsh,
227 &fmtblock, &dirent, (caddr_t)&slottype,
228 sizeof(nubus_type)) <= 0)
229 goto notfound;
230
231 rsrcid = r;
232 }
233 }
234
235 na_args.slot = i;
236 na_args.rsrcid = rsrcid;
237 na_args.category = slottype.category;
238 na_args.type = slottype.type;
239 na_args.drsw = slottype.drsw;
240 na_args.drhw = slottype.drhw;
241 na_args.fmt = &fmtblock;
242
243 bus_space_unmap(bst, bsh, NBMEMSIZE);
244
245 config_found(self, &na_args, nubus_print);
246 }
247
248 enable_nubus_intr();
249 }
250
251 static int
252 nubus_print(aux, pnp)
253 void *aux;
254 const char *pnp;
255 {
256 struct nubus_attach_args *na = (struct nubus_attach_args *)aux;
257 bus_space_tag_t bst = na->na_tag;
258 bus_space_handle_t bsh;
259
260 if (pnp) {
261 printf("%s slot %x", pnp, na->slot);
262 if (bus_space_map(bst,
263 NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh) == 0) {
264 printf(": %s", nubus_get_card_name(bst, bsh, na->fmt));
265 printf(" (Vendor: %s,", nubus_get_vendor(bst, bsh,
266 na->fmt, NUBUS_RSRC_VEND_ID));
267 printf(" Part: %s)", nubus_get_vendor(bst, bsh,
268 na->fmt, NUBUS_RSRC_VEND_PART));
269 bus_space_unmap(bst, bsh, NBMEMSIZE);
270 }
271 #ifdef DIAGNOSTIC
272 else
273 printf(":");
274 printf(" Type: %04x %04x %04x %04x",
275 na->category, na->type, na->drsw, na->drhw);
276 #endif
277 } else {
278 printf(" slot %x", na->slot);
279 }
280 return (UNCONF);
281 }
282
283 static int
284 nubus_video_resource(slot)
285 int slot;
286 {
287 extern u_int16_t mac68k_vrsrc_vec[];
288 int i;
289
290 for (i = 0 ; i < 6 ; i++)
291 if ((mac68k_vrsrc_vec[i] & 0xff) == slot)
292 return ((mac68k_vrsrc_vec[i] >> 8) & 0xff);
293 return (-1);
294 }
295
296 /*
297 * Probe a given nubus slot. If a card is there and we can get the
298 * format block from it's clutching decl. ROMs, fill the format block
299 * and return non-zero. If we can't find a card there with a valid
300 * decl. ROM, return 0.
301 *
302 * First, we check to see if we can access the memory at the tail
303 * end of the slot. If so, then we check for a bytelanes byte. We
304 * could probably just return a failure status if we bus error on
305 * the first try, but there really is little reason not to go ahead
306 * and check the other three locations in case there's a wierd card
307 * out there.
308 *
309 * Checking for a card involves locating the "bytelanes" byte which
310 * tells us how to interpret the declaration ROM's data. The format
311 * block is at the top of the card's standard memory space and the
312 * bytelanes byte is at the end of that block.
313 *
314 * After some inspection of the bytelanes byte, it appears that it
315 * takes the form 0xXY where Y is a bitmask of the bytelanes in use
316 * and X is a bitmask of the lanes to ignore. Hence, (X ^ Y) == 0
317 * and (less obviously), Y will have the upper N bits clear if it is
318 * found N bytes from the last possible location. Both that and
319 * the exclusive-or check are made.
320 *
321 * If a valid
322 */
323 static u_int8_t nbits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
324 static int
325 nubus_probe_slot(bst, bsh, slot, fmt)
326 bus_space_tag_t bst;
327 bus_space_handle_t bsh;
328 int slot;
329 nubus_slot *fmt;
330 {
331 u_long ofs, hdr;
332 int i, j, found, hdr_size;
333 u_int8_t lanes;
334
335 #ifdef DEBUG
336 if (nubus_debug & NDB_PROBE)
337 printf("probing slot %x\n", slot);
338 #endif
339
340 /*
341 * The idea behind this glorious work of art is to probe for only
342 * valid bytelanes values at appropriate locations (see DC&D p. 159
343 * for a list). Note the pattern: the first 8 values are at offset
344 * 0xffffff in the slot's space; the next 4 values at 0xfffffe; the
345 * next 2 values at 0xfffffd; and the last one at 0xfffffc.
346 *
347 * The nested loops implement an efficient search of this space,
348 * probing first for a valid address, then checking for each of the
349 * valid bytelanes values at that address.
350 */
351 ofs = NBMEMSIZE;
352 lanes = 0xf;
353
354 for (j = 8, found = 0; j > 0 && !found; j >>= 1) {
355 ofs--;
356 for (i = j; i > 0; i--, lanes--) {
357 if (!bus_probe(bst, bsh, ofs, 1)) {
358 lanes -= i;
359 break;
360 }
361 if (bus_space_read_1(bst, bsh, ofs) ==
362 (((~lanes & 0xf) << 4) | lanes)) {
363 found = 1;
364 break;
365 }
366 }
367 }
368
369 if (!found) {
370 #ifdef DEBUG
371 if (nubus_debug & NDB_PROBE)
372 printf("bytelanes not found for slot %x\n", slot);
373 #endif
374 return 0;
375 }
376
377 fmt->bytelanes = lanes;
378 fmt->step = nbits[(lanes & 0x0f)];
379 fmt->slot = slot; /* XXX redundant; get rid of this someday */
380
381 #ifdef DEBUG
382 if (nubus_debug & NDB_PROBE)
383 printf("bytelanes of 0x%x found for slot 0x%x.\n",
384 fmt->bytelanes, slot);
385 #endif
386
387 /*
388 * Go ahead and attempt to load format header.
389 * First, we need to find the first byte beyond memory that
390 * would be valid. This is necessary for NUBUS_ROM_offset()
391 * to work.
392 */
393 hdr = NBMEMSIZE;
394 hdr_size = 20;
395
396 i = 0x10 | (lanes & 0x0f);
397 while ((i & 1) == 0) {
398 hdr++;
399 i >>= 1;
400 }
401 fmt->top = hdr;
402 hdr = nubus_adjust_ptr(lanes, hdr, -hdr_size);
403 #ifdef DEBUG
404 if (nubus_debug & NDB_PROBE)
405 printf("fmt->top is 0x%lx, that minus 0x%x puts us at 0x%lx.\n",
406 fmt->top, hdr_size, hdr);
407 if (nubus_debug & NDB_ARITH)
408 for (i = 1 ; i < 8 ; i++)
409 printf("0x%lx - 0x%x = 0x%lx, + 0x%x = 0x%lx.\n",
410 hdr, i, nubus_adjust_ptr(lanes, hdr, -i),
411 i, nubus_adjust_ptr(lanes, hdr, i));
412 #endif
413
414 fmt->directory_offset =
415 0xff000000 | nubus_read_4(bst, bsh, lanes, hdr);
416 hdr = nubus_adjust_ptr(lanes, hdr, 4);
417 fmt->length = nubus_read_4(bst, bsh, lanes, hdr);
418 hdr = nubus_adjust_ptr(lanes, hdr, 4);
419 fmt->crc = nubus_read_4(bst, bsh, lanes, hdr);
420 hdr = nubus_adjust_ptr(lanes, hdr, 4);
421 fmt->revision_level = nubus_read_1(bst, bsh, lanes, hdr);
422 hdr = nubus_adjust_ptr(lanes, hdr, 1);
423 fmt->format = nubus_read_1(bst, bsh, lanes, hdr);
424 hdr = nubus_adjust_ptr(lanes, hdr, 1);
425 fmt->test_pattern = nubus_read_4(bst, bsh, lanes, hdr);
426
427 #ifdef DEBUG
428 if (nubus_debug & NDB_PROBE) {
429 printf("Directory offset 0x%x\t", fmt->directory_offset);
430 printf("Length 0x%x\t", fmt->length);
431 printf("CRC 0x%x\n", fmt->crc);
432 printf("Revision level 0x%x\t", fmt->revision_level);
433 printf("Format 0x%x\t", fmt->format);
434 printf("Test Pattern 0x%x\n", fmt->test_pattern);
435 }
436 #endif
437
438 if ((fmt->directory_offset & 0x00ff0000) == 0) {
439 printf("Invalid looking directory offset (0x%x)!\n",
440 fmt->directory_offset);
441 return 0;
442 }
443 if (fmt->test_pattern != NUBUS_ROM_TEST_PATTERN) {
444 printf("Nubus--test pattern invalid:\n");
445 printf(" slot 0x%x, bytelanes 0x%x?\n", fmt->slot, lanes);
446 printf(" read test 0x%x, compare with 0x%x.\n",
447 fmt->test_pattern, NUBUS_ROM_TEST_PATTERN);
448 return 0;
449 }
450
451 /* Perform CRC */
452 if (fmt->crc != nubus_calc_CRC(bst, bsh, fmt)) {
453 printf("Nubus--crc check failed, slot 0x%x.\n", fmt->slot);
454 return 0;
455 }
456
457 return 1;
458 }
459
460 static u_int32_t
461 nubus_calc_CRC(bst, bsh, fmt)
462 bus_space_tag_t bst;
463 bus_space_handle_t bsh;
464 nubus_slot *fmt;
465 {
466 #if 0
467 u_long base, ptr, crc_loc;
468 u_int32_t sum;
469 u_int8_t lanes = fmt->bytelanes;
470
471 base = fmt->top;
472 crc_loc = NUBUS_ROM_offset(fmt, base, -12);
473 ptr = NUBUS_ROM_offset(fmt, base, -fmt->length);
474
475 sum = 0;
476 while (ptr < base)
477 roll #1, sum
478 if (ptr == crc_loc) {
479 roll #3, sum
480 ptr = nubus_adjust_ptr(lanes, ptr, 3);
481 } else {
482 sum += nubus_read_1(bst, bsh, lanes, ptr);
483 }
484 ptr = nubus_adjust_ptr(lanes, ptr, 1);
485 }
486
487 return sum;
488 #endif
489 return fmt->crc;
490 }
491
492 /*
493 * Compute byte offset on card, taking into account bytelanes.
494 * Base must be on a valid bytelane for this function to work.
495 * Return the new address.
496 *
497 * XXX -- There has GOT to be a better way to do this.
498 */
499 static u_long
500 nubus_adjust_ptr(lanes, base, amt)
501 u_int8_t lanes;
502 u_long base;
503 long amt;
504 {
505 u_int8_t b, t;
506
507 if (!amt)
508 return base;
509
510 if (amt < 0) {
511 amt = -amt;
512 b = lanes;
513 t = (b << 4);
514 b <<= (3 - (base & 0x3));
515 while (amt) {
516 b <<= 1;
517 if (b == t)
518 b = lanes;
519 if (b & 0x08)
520 amt--;
521 base--;
522 }
523 return base;
524 }
525
526 t = (lanes & 0xf) | 0x10;
527 b = t >> (base & 0x3);
528 while (amt) {
529 b >>= 1;
530 if (b == 1)
531 b = t;
532 if (b & 1)
533 amt--;
534 base++;
535 }
536
537 return base;
538 }
539
540 static u_int8_t
541 nubus_read_1(bst, bsh, lanes, ofs)
542 bus_space_tag_t bst;
543 bus_space_handle_t bsh;
544 u_int8_t lanes;
545 u_long ofs;
546 {
547 return bus_space_read_1(bst, bsh, ofs);
548 }
549
550 #ifdef notyet
551 /* Nothing uses this, yet */
552 static u_int16_t
553 nubus_read_2(bst, bsh, lanes, ofs)
554 bus_space_tag_t bst;
555 bus_space_handle_t bsh;
556 u_int8_t lanes;
557 u_long ofs;
558 {
559 u_int16_t s;
560
561 s = (nubus_read_1(bst, bsh, lanes, ofs) << 8);
562 ofs = nubus_adjust_ptr(lanes, ofs, 1);
563 s |= nubus_read_1(bst, bsh, lanes, ofs);
564 return s;
565 }
566 #endif
567
568 static u_int32_t
569 nubus_read_4(bst, bsh, lanes, ofs)
570 bus_space_tag_t bst;
571 bus_space_handle_t bsh;
572 u_int8_t lanes;
573 u_long ofs;
574 {
575 u_int32_t l;
576 int i;
577
578 l = 0;
579 for (i = 0; i < 4; i++) {
580 l = (l << 8) | nubus_read_1(bst, bsh, lanes, ofs);
581 ofs = nubus_adjust_ptr(lanes, ofs, 1);
582 }
583 return l;
584 }
585
586 void
587 nubus_get_main_dir(fmt, dir_return)
588 nubus_slot *fmt;
589 nubus_dir *dir_return;
590 {
591 #ifdef DEBUG
592 if (nubus_debug & NDB_FOLLOW)
593 printf("nubus_get_main_dir(%p, %p)\n",
594 fmt, dir_return);
595 #endif
596 dir_return->dirbase = nubus_adjust_ptr(fmt->bytelanes, fmt->top,
597 fmt->directory_offset - 20);
598 dir_return->curr_ent = dir_return->dirbase;
599 }
600
601 void
602 nubus_get_dir_from_rsrc(fmt, dirent, dir_return)
603 nubus_slot *fmt;
604 nubus_dirent *dirent;
605 nubus_dir *dir_return;
606 {
607 u_long loc;
608
609 #ifdef DEBUG
610 if (nubus_debug & NDB_FOLLOW)
611 printf("nubus_get_dir_from_rsrc(%p, %p, %p).\n",
612 fmt, dirent, dir_return);
613 #endif
614 if ((loc = dirent->offset) & 0x800000) {
615 loc |= 0xff000000;
616 }
617 dir_return->dirbase =
618 nubus_adjust_ptr(fmt->bytelanes, dirent->myloc, loc);
619 dir_return->curr_ent = dir_return->dirbase;
620 }
621
622 int
623 nubus_find_rsrc(bst, bsh, fmt, dir, rsrcid, dirent_return)
624 bus_space_tag_t bst;
625 bus_space_handle_t bsh;
626 nubus_slot *fmt;
627 nubus_dir *dir;
628 u_int8_t rsrcid;
629 nubus_dirent *dirent_return;
630 {
631 u_long entry;
632 u_int8_t byte, lanes = fmt->bytelanes;
633
634 #ifdef DEBUG
635 if (nubus_debug & NDB_FOLLOW)
636 printf("nubus_find_rsrc(%p, %p, 0x%x, %p)\n",
637 fmt, dir, rsrcid, dirent_return);
638 #endif
639 if (fmt->test_pattern != NUBUS_ROM_TEST_PATTERN)
640 return -1;
641
642 entry = dir->curr_ent;
643 do {
644 byte = nubus_read_1(bst, bsh, lanes, entry);
645 #ifdef DEBUG
646 if (nubus_debug & NDB_FOLLOW)
647 printf("\tFound rsrc 0x%x.\n", byte);
648 #endif
649 if (byte == rsrcid) {
650 dirent_return->myloc = entry;
651 dirent_return->rsrc_id = rsrcid;
652 entry = nubus_read_4(bst, bsh, lanes, entry);
653 dirent_return->offset = (entry & 0x00ffffff);
654 return 1;
655 }
656 if (byte == 0xff) {
657 entry = dir->dirbase;
658 } else {
659 entry = nubus_adjust_ptr(lanes, entry, 4);
660 }
661 } while (entry != (u_long)dir->curr_ent);
662 return 0;
663 }
664
665 int
666 nubus_get_ind_data(bst, bsh, fmt, dirent, data_return, nbytes)
667 bus_space_tag_t bst;
668 bus_space_handle_t bsh;
669 nubus_slot *fmt;
670 nubus_dirent *dirent;
671 caddr_t data_return;
672 int nbytes;
673 {
674 u_long loc;
675 u_int8_t lanes = fmt->bytelanes;
676
677 #ifdef DEBUG
678 if (nubus_debug & NDB_FOLLOW)
679 printf("nubus_get_ind_data(%p, %p, %p, %d).\n",
680 fmt, dirent, data_return, nbytes);
681 #endif
682 if ((loc = dirent->offset) & 0x800000) {
683 loc |= 0xff000000;
684 }
685 loc = nubus_adjust_ptr(lanes, dirent->myloc, loc);
686
687 while (nbytes--) {
688 *data_return++ = nubus_read_1(bst, bsh, lanes, loc);
689 loc = nubus_adjust_ptr(lanes, loc, 1);
690 }
691 return 1;
692 }
693
694 int
695 nubus_get_c_string(bst, bsh, fmt, dirent, data_return, max_bytes)
696 bus_space_tag_t bst;
697 bus_space_handle_t bsh;
698 nubus_slot *fmt;
699 nubus_dirent *dirent;
700 caddr_t data_return;
701 int max_bytes;
702 {
703 u_long loc;
704 u_int8_t lanes = fmt->bytelanes;
705
706 #ifdef DEBUG
707 if (nubus_debug & NDB_FOLLOW)
708 printf("nubus_get_c_string(%p, %p, %p, %d).\n",
709 fmt, dirent, data_return, max_bytes);
710 #endif
711 if ((loc = dirent->offset) & 0x800000)
712 loc |= 0xff000000;
713
714 loc = nubus_adjust_ptr(lanes, dirent->myloc, loc);
715
716 *data_return = '\0';
717 while (max_bytes--) {
718 if ((*data_return++ =
719 nubus_read_1(bst, bsh, lanes, loc)) == 0)
720 return 1;
721 loc = nubus_adjust_ptr(lanes, loc, 1);
722 }
723 return 0;
724 }
725
726 static char *huh = "???";
727
728 char *
729 nubus_get_vendor(bst, bsh, fmt, rsrc)
730 bus_space_tag_t bst;
731 bus_space_handle_t bsh;
732 nubus_slot *fmt;
733 int rsrc;
734 {
735 static char str_ret[64];
736 nubus_dir dir;
737 nubus_dirent ent;
738
739 #ifdef DEBUG
740 if (nubus_debug & NDB_FOLLOW)
741 printf("nubus_get_vendor(%p, 0x%x).\n", fmt, rsrc);
742 #endif
743 nubus_get_main_dir(fmt, &dir);
744 if (nubus_find_rsrc(bst, bsh, fmt, &dir, 1, &ent) <= 0)
745 return huh;
746 nubus_get_dir_from_rsrc(fmt, &ent, &dir);
747
748 if (nubus_find_rsrc(bst, bsh, fmt, &dir, NUBUS_RSRC_VENDORINFO, &ent)
749 <= 0)
750 return huh;
751 nubus_get_dir_from_rsrc(fmt, &ent, &dir);
752
753 if (nubus_find_rsrc(bst, bsh, fmt, &dir, rsrc, &ent) <= 0)
754 return huh;
755
756 nubus_get_c_string(bst, bsh, fmt, &ent, str_ret, 64);
757
758 return str_ret;
759 }
760
761 char *
762 nubus_get_card_name(bst, bsh, fmt)
763 bus_space_tag_t bst;
764 bus_space_handle_t bsh;
765 nubus_slot *fmt;
766 {
767 static char name_ret[64];
768 nubus_dir dir;
769 nubus_dirent ent;
770
771 #ifdef DEBUG
772 if (nubus_debug & NDB_FOLLOW)
773 printf("nubus_get_card_name(%p).\n", fmt);
774 #endif
775 nubus_get_main_dir(fmt, &dir);
776
777 if (nubus_find_rsrc(bst, bsh, fmt, &dir, 1, &ent) <= 0)
778 return huh;
779
780 nubus_get_dir_from_rsrc(fmt, &ent, &dir);
781
782 if (nubus_find_rsrc(bst, bsh, fmt, &dir, NUBUS_RSRC_NAME, &ent) <= 0)
783 return huh;
784
785 nubus_get_c_string(bst, bsh, fmt, &ent, name_ret, 64);
786
787 return name_ret;
788 }
789