]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/nubus/nubus.c
UBUNTU: Ubuntu-4.13.0-45.50
[mirror_ubuntu-artful-kernel.git] / drivers / nubus / nubus.c
CommitLineData
1da177e4
LT
1/*
2 * Macintosh Nubus Interface Code
3 *
4 * Originally by Alan Cox
5 *
6 * Mostly rewritten by David Huggins-Daines, C. Scott Ananian,
7 * and others.
8 */
9
1da177e4
LT
10#include <linux/types.h>
11#include <linux/kernel.h>
12#include <linux/string.h>
13#include <linux/nubus.h>
14#include <linux/errno.h>
15#include <linux/init.h>
99ffab81 16#include <linux/module.h>
5a0e3ad6 17#include <linux/slab.h>
1da177e4 18#include <asm/setup.h>
1da177e4
LT
19#include <asm/page.h>
20#include <asm/hwtest.h>
1da177e4
LT
21#include <asm/mac_via.h>
22#include <asm/mac_oss.h>
23
24extern void via_nubus_init(void);
25extern void oss_nubus_init(void);
26
27/* Constants */
28
29/* This is, of course, the size in bytelanes, rather than the size in
30 actual bytes */
31#define FORMAT_BLOCK_SIZE 20
32#define ROM_DIR_OFFSET 0x24
33
34#define NUBUS_TEST_PATTERN 0x5A932BC7
35
1da177e4
LT
36/* Globals */
37
f42e5550
FT
38struct nubus_dev *nubus_devices;
39struct nubus_board *nubus_boards;
1da177e4
LT
40
41/* Meaning of "bytelanes":
42
43 The card ROM may appear on any or all bytes of each long word in
44 NuBus memory. The low 4 bits of the "map" value found in the
45 format block (at the top of the slot address space, as well as at
46 the top of the MacOS ROM) tells us which bytelanes, i.e. which byte
47 offsets within each longword, are valid. Thus:
48
49 A map of 0x0f, as found in the MacOS ROM, means that all bytelanes
50 are valid.
51
52 A map of 0xf0 means that no bytelanes are valid (We pray that we
53 will never encounter this, but stranger things have happened)
54
55 A map of 0xe1 means that only the MSB of each long word is actually
56 part of the card ROM. (We hope to never encounter NuBus on a
57 little-endian machine. Again, stranger things have happened)
58
59 A map of 0x78 means that only the LSB of each long word is valid.
60
61 Etcetera, etcetera. Hopefully this clears up some confusion over
62 what the following code actually does. */
f42e5550 63
1da177e4
LT
64static inline int not_useful(void *p, int map)
65{
f42e5550
FT
66 unsigned long pv = (unsigned long)p;
67
1da177e4 68 pv &= 3;
f42e5550 69 if (map & (1 << pv))
1da177e4
LT
70 return 0;
71 return 1;
72}
f42e5550 73
1da177e4
LT
74static unsigned long nubus_get_rom(unsigned char **ptr, int len, int map)
75{
76 /* This will hold the result */
77 unsigned long v = 0;
78 unsigned char *p = *ptr;
79
f42e5550 80 while (len) {
1da177e4 81 v <<= 8;
f42e5550 82 while (not_useful(p, map))
1da177e4
LT
83 p++;
84 v |= *p++;
85 len--;
86 }
87 *ptr = p;
88 return v;
89}
90
91static void nubus_rewind(unsigned char **ptr, int len, int map)
92{
f42e5550 93 unsigned char *p = *ptr;
1da177e4 94
f42e5550
FT
95 while (len) {
96 do {
1da177e4 97 p--;
f42e5550 98 } while (not_useful(p, map));
1da177e4
LT
99 len--;
100 }
f42e5550 101 *ptr = p;
1da177e4
LT
102}
103
104static void nubus_advance(unsigned char **ptr, int len, int map)
105{
106 unsigned char *p = *ptr;
f42e5550 107
f42e5550
FT
108 while (len) {
109 while (not_useful(p, map))
1da177e4 110 p++;
2e0eb731 111 p++;
1da177e4
LT
112 len--;
113 }
114 *ptr = p;
115}
116
117static void nubus_move(unsigned char **ptr, int len, int map)
118{
85cc313a
FT
119 unsigned long slot_space = (unsigned long)*ptr & 0xFF000000;
120
f42e5550 121 if (len > 0)
1da177e4 122 nubus_advance(ptr, len, map);
f42e5550 123 else if (len < 0)
1da177e4 124 nubus_rewind(ptr, -len, map);
85cc313a
FT
125
126 if (((unsigned long)*ptr & 0xFF000000) != slot_space)
127 pr_err("%s: moved out of slot address space!\n", __func__);
1da177e4
LT
128}
129
130/* Now, functions to read the sResource tree */
131
132/* Each sResource entry consists of a 1-byte ID and a 3-byte data
133 field. If that data field contains an offset, then obviously we
134 have to expand it from a 24-bit signed number to a 32-bit signed
135 number. */
136
137static inline long nubus_expand32(long foo)
138{
f42e5550 139 if (foo & 0x00800000) /* 24bit negative */
1da177e4
LT
140 foo |= 0xFF000000;
141 return foo;
142}
143
144static inline void *nubus_rom_addr(int slot)
f42e5550 145{
1da177e4
LT
146 /*
147 * Returns the first byte after the card. We then walk
148 * backwards to get the lane register and the config
149 */
f42e5550 150 return (void *)(0xF1000000 + (slot << 24));
1da177e4
LT
151}
152
153static unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
154{
155 unsigned char *p = nd->base;
f42e5550 156
1da177e4
LT
157 /* Essentially, just step over the bytelanes using whatever
158 offset we might have found */
159 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
160 /* And return the value */
161 return p;
162}
163
164/* These two are for pulling resource data blocks (i.e. stuff that's
165 pointed to with offsets) out of the card ROM. */
166
f42e5550 167void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
1da177e4
LT
168 int len)
169{
170 unsigned char *t = (unsigned char *)dest;
171 unsigned char *p = nubus_dirptr(dirent);
f42e5550
FT
172
173 while (len) {
1da177e4
LT
174 *t++ = nubus_get_rom(&p, 1, dirent->mask);
175 len--;
176 }
177}
99ffab81 178EXPORT_SYMBOL(nubus_get_rsrc_mem);
1da177e4 179
f42e5550 180void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent,
1da177e4
LT
181 int len)
182{
f42e5550 183 unsigned char *t = (unsigned char *)dest;
1da177e4 184 unsigned char *p = nubus_dirptr(dirent);
f42e5550
FT
185
186 while (len) {
1da177e4 187 *t = nubus_get_rom(&p, 1, dirent->mask);
f42e5550 188 if (!*t++)
1da177e4
LT
189 break;
190 len--;
191 }
192}
99ffab81 193EXPORT_SYMBOL(nubus_get_rsrc_str);
1da177e4 194
f42e5550
FT
195int nubus_get_root_dir(const struct nubus_board *board,
196 struct nubus_dir *dir)
1da177e4
LT
197{
198 dir->ptr = dir->base = board->directory;
199 dir->done = 0;
200 dir->mask = board->lanes;
201 return 0;
202}
99ffab81 203EXPORT_SYMBOL(nubus_get_root_dir);
1da177e4
LT
204
205/* This is a slyly renamed version of the above */
f42e5550
FT
206int nubus_get_func_dir(const struct nubus_dev *dev,
207 struct nubus_dir *dir)
1da177e4
LT
208{
209 dir->ptr = dir->base = dev->directory;
210 dir->done = 0;
211 dir->mask = dev->board->lanes;
212 return 0;
213}
99ffab81 214EXPORT_SYMBOL(nubus_get_func_dir);
1da177e4 215
f42e5550
FT
216int nubus_get_board_dir(const struct nubus_board *board,
217 struct nubus_dir *dir)
1da177e4
LT
218{
219 struct nubus_dirent ent;
f42e5550 220
1da177e4
LT
221 dir->ptr = dir->base = board->directory;
222 dir->done = 0;
223 dir->mask = board->lanes;
224
225 /* Now dereference it (the first directory is always the board
226 directory) */
227 if (nubus_readdir(dir, &ent) == -1)
228 return -1;
229 if (nubus_get_subdir(&ent, dir) == -1)
230 return -1;
231 return 0;
232}
99ffab81 233EXPORT_SYMBOL(nubus_get_board_dir);
1da177e4
LT
234
235int nubus_get_subdir(const struct nubus_dirent *ent,
236 struct nubus_dir *dir)
237{
238 dir->ptr = dir->base = nubus_dirptr(ent);
239 dir->done = 0;
240 dir->mask = ent->mask;
241 return 0;
242}
99ffab81 243EXPORT_SYMBOL(nubus_get_subdir);
1da177e4
LT
244
245int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
246{
247 u32 resid;
f42e5550 248
1da177e4
LT
249 if (nd->done)
250 return -1;
251
252 /* Do this first, otherwise nubus_rewind & co are off by 4 */
253 ent->base = nd->ptr;
254
255 /* This moves nd->ptr forward */
256 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
257
258 /* EOL marker, as per the Apple docs */
f42e5550 259 if ((resid & 0xff000000) == 0xff000000) {
1da177e4
LT
260 /* Mark it as done */
261 nd->done = 1;
262 return -1;
263 }
264
265 /* First byte is the resource ID */
f42e5550 266 ent->type = resid >> 24;
1da177e4
LT
267 /* Low 3 bytes might contain data (or might not) */
268 ent->data = resid & 0xffffff;
f42e5550 269 ent->mask = nd->mask;
1da177e4
LT
270 return 0;
271}
99ffab81 272EXPORT_SYMBOL(nubus_readdir);
1da177e4 273
f42e5550 274int nubus_rewinddir(struct nubus_dir *dir)
1da177e4
LT
275{
276 dir->ptr = dir->base;
e36b9913 277 dir->done = 0;
1da177e4
LT
278 return 0;
279}
99ffab81 280EXPORT_SYMBOL(nubus_rewinddir);
1da177e4
LT
281
282/* Driver interface functions, more or less like in pci.c */
283
284struct nubus_dev*
f42e5550
FT
285nubus_find_device(unsigned short category, unsigned short type,
286 unsigned short dr_hw, unsigned short dr_sw,
287 const struct nubus_dev *from)
1da177e4 288{
f42e5550 289 struct nubus_dev *itor = from ? from->next : nubus_devices;
1da177e4
LT
290
291 while (itor) {
f42e5550
FT
292 if (itor->category == category && itor->type == type &&
293 itor->dr_hw == dr_hw && itor->dr_sw == dr_sw)
1da177e4
LT
294 return itor;
295 itor = itor->next;
296 }
297 return NULL;
298}
99ffab81 299EXPORT_SYMBOL(nubus_find_device);
1da177e4
LT
300
301struct nubus_dev*
f42e5550
FT
302nubus_find_type(unsigned short category, unsigned short type,
303 const struct nubus_dev *from)
1da177e4 304{
f42e5550 305 struct nubus_dev *itor = from ? from->next : nubus_devices;
1da177e4
LT
306
307 while (itor) {
f42e5550 308 if (itor->category == category && itor->type == type)
1da177e4
LT
309 return itor;
310 itor = itor->next;
311 }
312 return NULL;
313}
99ffab81 314EXPORT_SYMBOL(nubus_find_type);
1da177e4
LT
315
316struct nubus_dev*
f42e5550 317nubus_find_slot(unsigned int slot, const struct nubus_dev *from)
1da177e4 318{
f42e5550
FT
319 struct nubus_dev *itor = from ? from->next : nubus_devices;
320
1da177e4
LT
321 while (itor) {
322 if (itor->board->slot == slot)
323 return itor;
324 itor = itor->next;
325 }
326 return NULL;
327}
99ffab81 328EXPORT_SYMBOL(nubus_find_slot);
1da177e4
LT
329
330int
f42e5550
FT
331nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type,
332 struct nubus_dirent *ent)
1da177e4
LT
333{
334 while (nubus_readdir(dir, ent) != -1) {
335 if (ent->type == rsrc_type)
336 return 0;
f42e5550 337 }
1da177e4
LT
338 return -1;
339}
99ffab81 340EXPORT_SYMBOL(nubus_find_rsrc);
1da177e4
LT
341
342/* Initialization functions - decide which slots contain stuff worth
343 looking at, and print out lots and lots of information from the
344 resource blocks. */
345
346/* FIXME: A lot of this stuff will eventually be useful after
081985ac 347 initialization, for intelligently probing Ethernet and video chips,
1da177e4
LT
348 among other things. The rest of it should go in the /proc code.
349 For now, we just use it to give verbose boot logs. */
350
f42e5550
FT
351static int __init nubus_show_display_resource(struct nubus_dev *dev,
352 const struct nubus_dirent *ent)
1da177e4
LT
353{
354 switch (ent->type) {
355 case NUBUS_RESID_GAMMADIR:
71ae40e4 356 pr_info(" gamma directory offset: 0x%06x\n", ent->data);
1da177e4
LT
357 break;
358 case 0x0080 ... 0x0085:
71ae40e4 359 pr_info(" mode %02X info offset: 0x%06x\n",
1da177e4
LT
360 ent->type, ent->data);
361 break;
362 default:
71ae40e4 363 pr_info(" unknown resource %02X, data 0x%06x\n",
1da177e4
LT
364 ent->type, ent->data);
365 }
366 return 0;
367}
368
f42e5550
FT
369static int __init nubus_show_network_resource(struct nubus_dev *dev,
370 const struct nubus_dirent *ent)
1da177e4
LT
371{
372 switch (ent->type) {
373 case NUBUS_RESID_MAC_ADDRESS:
374 {
375 char addr[6];
f42e5550 376
1da177e4 377 nubus_get_rsrc_mem(addr, ent, 6);
71ae40e4 378 pr_info(" MAC address: %pM\n", addr);
1da177e4
LT
379 break;
380 }
381 default:
71ae40e4 382 pr_info(" unknown resource %02X, data 0x%06x\n",
1da177e4
LT
383 ent->type, ent->data);
384 }
385 return 0;
386}
387
f42e5550
FT
388static int __init nubus_show_cpu_resource(struct nubus_dev *dev,
389 const struct nubus_dirent *ent)
1da177e4
LT
390{
391 switch (ent->type) {
392 case NUBUS_RESID_MEMINFO:
393 {
394 unsigned long meminfo[2];
f42e5550 395
1da177e4 396 nubus_get_rsrc_mem(&meminfo, ent, 8);
71ae40e4 397 pr_info(" memory: [ 0x%08lx 0x%08lx ]\n",
1da177e4
LT
398 meminfo[0], meminfo[1]);
399 break;
400 }
401 case NUBUS_RESID_ROMINFO:
402 {
403 unsigned long rominfo[2];
f42e5550 404
1da177e4 405 nubus_get_rsrc_mem(&rominfo, ent, 8);
71ae40e4 406 pr_info(" ROM: [ 0x%08lx 0x%08lx ]\n",
1da177e4
LT
407 rominfo[0], rominfo[1]);
408 break;
409 }
410 default:
71ae40e4 411 pr_info(" unknown resource %02X, data 0x%06x\n",
1da177e4
LT
412 ent->type, ent->data);
413 }
414 return 0;
415}
416
f42e5550
FT
417static int __init nubus_show_private_resource(struct nubus_dev *dev,
418 const struct nubus_dirent *ent)
1da177e4
LT
419{
420 switch (dev->category) {
421 case NUBUS_CAT_DISPLAY:
422 nubus_show_display_resource(dev, ent);
423 break;
424 case NUBUS_CAT_NETWORK:
425 nubus_show_network_resource(dev, ent);
426 break;
427 case NUBUS_CAT_CPU:
428 nubus_show_cpu_resource(dev, ent);
429 break;
430 default:
71ae40e4 431 pr_info(" unknown resource %02X, data 0x%06x\n",
1da177e4
LT
432 ent->type, ent->data);
433 }
434 return 0;
435}
436
f42e5550
FT
437static struct nubus_dev * __init
438nubus_get_functional_resource(struct nubus_board *board, int slot,
439 const struct nubus_dirent *parent)
1da177e4 440{
f42e5550 441 struct nubus_dir dir;
1da177e4 442 struct nubus_dirent ent;
f42e5550
FT
443 struct nubus_dev *dev;
444
71ae40e4 445 pr_info(" Function 0x%02x:\n", parent->type);
1da177e4
LT
446 nubus_get_subdir(parent, &dir);
447
71ae40e4
DHD
448 pr_debug("%s: parent is 0x%p, dir is 0x%p\n",
449 __func__, parent->base, dir.base);
1da177e4
LT
450
451 /* Actually we should probably panic if this fails */
dd00cc48 452 if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
f42e5550 453 return NULL;
1da177e4
LT
454 dev->resid = parent->type;
455 dev->directory = dir.base;
456 dev->board = board;
f42e5550
FT
457
458 while (nubus_readdir(&dir, &ent) != -1) {
459 switch (ent.type) {
1da177e4
LT
460 case NUBUS_RESID_TYPE:
461 {
462 unsigned short nbtdata[4];
f42e5550 463
1da177e4
LT
464 nubus_get_rsrc_mem(nbtdata, &ent, 8);
465 dev->category = nbtdata[0];
466 dev->type = nbtdata[1];
467 dev->dr_sw = nbtdata[2];
468 dev->dr_hw = nbtdata[3];
71ae40e4
DHD
469 pr_info(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
470 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
1da177e4
LT
471 break;
472 }
473 case NUBUS_RESID_NAME:
474 {
475 nubus_get_rsrc_str(dev->name, &ent, 64);
71ae40e4 476 pr_info(" name: %s\n", dev->name);
1da177e4
LT
477 break;
478 }
479 case NUBUS_RESID_DRVRDIR:
480 {
481 /* MacOS driver. If we were NetBSD we might
482 use this :-) */
483 struct nubus_dir drvr_dir;
484 struct nubus_dirent drvr_ent;
f42e5550 485
1da177e4
LT
486 nubus_get_subdir(&ent, &drvr_dir);
487 nubus_readdir(&drvr_dir, &drvr_ent);
488 dev->driver = nubus_dirptr(&drvr_ent);
71ae40e4 489 pr_info(" driver at: 0x%p\n", dev->driver);
1da177e4
LT
490 break;
491 }
492 case NUBUS_RESID_MINOR_BASEOS:
493 /* We will need this in order to support
494 multiple framebuffers. It might be handy
495 for Ethernet as well */
496 nubus_get_rsrc_mem(&dev->iobase, &ent, 4);
71ae40e4 497 pr_info(" memory offset: 0x%08lx\n", dev->iobase);
1da177e4
LT
498 break;
499 case NUBUS_RESID_MINOR_LENGTH:
500 /* Ditto */
501 nubus_get_rsrc_mem(&dev->iosize, &ent, 4);
71ae40e4 502 pr_info(" memory length: 0x%08lx\n", dev->iosize);
f42e5550 503 break;
1da177e4
LT
504 case NUBUS_RESID_FLAGS:
505 dev->flags = ent.data;
71ae40e4 506 pr_info(" flags: 0x%06x\n", dev->flags);
1da177e4
LT
507 break;
508 case NUBUS_RESID_HWDEVID:
509 dev->hwdevid = ent.data;
71ae40e4 510 pr_info(" hwdevid: 0x%06x\n", dev->hwdevid);
1da177e4
LT
511 break;
512 default:
513 /* Local/Private resources have their own
514 function */
515 nubus_show_private_resource(dev, &ent);
516 }
517 }
f42e5550 518
1da177e4
LT
519 return dev;
520}
521
522/* This is cool. */
f42e5550
FT
523static int __init nubus_get_vidnames(struct nubus_board *board,
524 const struct nubus_dirent *parent)
1da177e4 525{
f42e5550 526 struct nubus_dir dir;
1da177e4 527 struct nubus_dirent ent;
f42e5550 528
1da177e4
LT
529 /* FIXME: obviously we want to put this in a header file soon */
530 struct vidmode {
531 u32 size;
532 /* Don't know what this is yet */
533 u16 id;
534 /* Longest one I've seen so far is 26 characters */
535 char name[32];
536 };
537
71ae40e4 538 pr_info(" video modes supported:\n");
1da177e4 539 nubus_get_subdir(parent, &dir);
71ae40e4
DHD
540 pr_debug("%s: parent is 0x%p, dir is 0x%p\n",
541 __func__, parent->base, dir.base);
1da177e4 542
f42e5550 543 while (nubus_readdir(&dir, &ent) != -1) {
1da177e4
LT
544 struct vidmode mode;
545 u32 size;
546
547 /* First get the length */
548 nubus_get_rsrc_mem(&size, &ent, 4);
f42e5550 549
1da177e4
LT
550 /* Now clobber the whole thing */
551 if (size > sizeof(mode) - 1)
552 size = sizeof(mode) - 1;
553 memset(&mode, 0, sizeof(mode));
554 nubus_get_rsrc_mem(&mode, &ent, size);
71ae40e4 555 pr_info(" %02X: (%02X) %s\n", ent.type,
1da177e4
LT
556 mode.id, mode.name);
557 }
558 return 0;
559}
560
561/* This is *really* cool. */
f42e5550
FT
562static int __init nubus_get_icon(struct nubus_board *board,
563 const struct nubus_dirent *ent)
1da177e4
LT
564{
565 /* Should be 32x32 if my memory serves me correctly */
566 unsigned char icon[128];
567 int x, y;
f42e5550 568
1da177e4 569 nubus_get_rsrc_mem(&icon, ent, 128);
71ae40e4 570 pr_info(" icon:\n");
1da177e4
LT
571
572 /* We should actually plot these somewhere in the framebuffer
573 init. This is just to demonstrate that they do, in fact,
574 exist */
575 for (y = 0; y < 32; y++) {
71ae40e4 576 pr_info(" ");
1da177e4 577 for (x = 0; x < 32; x++) {
f42e5550 578 if (icon[y * 4 + x / 8] & (0x80 >> (x % 8)))
71ae40e4 579 pr_cont("*");
1da177e4 580 else
71ae40e4 581 pr_cont(" ");
1da177e4 582 }
71ae40e4 583 pr_cont("\n");
1da177e4
LT
584 }
585 return 0;
586}
587
f42e5550
FT
588static int __init nubus_get_vendorinfo(struct nubus_board *board,
589 const struct nubus_dirent *parent)
1da177e4 590{
f42e5550 591 struct nubus_dir dir;
1da177e4 592 struct nubus_dirent ent;
f42e5550
FT
593 static char *vendor_fields[6] = { "ID", "serial", "revision",
594 "part", "date", "unknown field" };
1da177e4 595
71ae40e4 596 pr_info(" vendor info:\n");
1da177e4 597 nubus_get_subdir(parent, &dir);
71ae40e4
DHD
598 pr_debug("%s: parent is 0x%p, dir is 0x%p\n",
599 __func__, parent->base, dir.base);
1da177e4 600
f42e5550 601 while (nubus_readdir(&dir, &ent) != -1) {
1da177e4 602 char name[64];
f42e5550 603
1da177e4
LT
604 /* These are all strings, we think */
605 nubus_get_rsrc_str(name, &ent, 64);
606 if (ent.type > 5)
607 ent.type = 5;
71ae40e4 608 pr_info(" %s: %s\n", vendor_fields[ent.type - 1], name);
1da177e4
LT
609 }
610 return 0;
611}
612
f42e5550
FT
613static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
614 const struct nubus_dirent *parent)
1da177e4 615{
f42e5550 616 struct nubus_dir dir;
1da177e4 617 struct nubus_dirent ent;
f42e5550 618
1da177e4 619 nubus_get_subdir(parent, &dir);
71ae40e4
DHD
620 pr_debug("%s: parent is 0x%p, dir is 0x%p\n",
621 __func__, parent->base, dir.base);
1da177e4 622
f42e5550 623 while (nubus_readdir(&dir, &ent) != -1) {
1da177e4
LT
624 switch (ent.type) {
625 case NUBUS_RESID_TYPE:
626 {
627 unsigned short nbtdata[4];
628 /* This type is always the same, and is not
629 useful except insofar as it tells us that
630 we really are looking at a board resource. */
631 nubus_get_rsrc_mem(nbtdata, &ent, 8);
71ae40e4
DHD
632 pr_info(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
633 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
1da177e4
LT
634 if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
635 nbtdata[2] != 0 || nbtdata[3] != 0)
71ae40e4 636 pr_err("this sResource is not a board resource!\n");
1da177e4
LT
637 break;
638 }
639 case NUBUS_RESID_NAME:
640 nubus_get_rsrc_str(board->name, &ent, 64);
71ae40e4 641 pr_info(" name: %s\n", board->name);
1da177e4
LT
642 break;
643 case NUBUS_RESID_ICON:
644 nubus_get_icon(board, &ent);
645 break;
646 case NUBUS_RESID_BOARDID:
71ae40e4 647 pr_info(" board id: 0x%x\n", ent.data);
1da177e4
LT
648 break;
649 case NUBUS_RESID_PRIMARYINIT:
71ae40e4 650 pr_info(" primary init offset: 0x%06x\n", ent.data);
1da177e4
LT
651 break;
652 case NUBUS_RESID_VENDORINFO:
653 nubus_get_vendorinfo(board, &ent);
654 break;
655 case NUBUS_RESID_FLAGS:
71ae40e4 656 pr_info(" flags: 0x%06x\n", ent.data);
1da177e4
LT
657 break;
658 case NUBUS_RESID_HWDEVID:
71ae40e4 659 pr_info(" hwdevid: 0x%06x\n", ent.data);
1da177e4
LT
660 break;
661 case NUBUS_RESID_SECONDINIT:
71ae40e4 662 pr_info(" secondary init offset: 0x%06x\n", ent.data);
1da177e4 663 break;
f42e5550 664 /* WTF isn't this in the functional resources? */
1da177e4
LT
665 case NUBUS_RESID_VIDNAMES:
666 nubus_get_vidnames(board, &ent);
667 break;
668 /* Same goes for this */
669 case NUBUS_RESID_VIDMODES:
71ae40e4 670 pr_info(" video mode parameter directory offset: 0x%06x\n",
1da177e4 671 ent.data);
f42e5550 672 break;
1da177e4 673 default:
71ae40e4 674 pr_info(" unknown resource %02X, data 0x%06x\n",
1da177e4
LT
675 ent.type, ent.data);
676 }
677 }
678 return 0;
679}
680
1da177e4 681/* Add a board (might be many devices) to the list */
f42e5550 682static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
1da177e4 683{
f42e5550
FT
684 struct nubus_board *board;
685 struct nubus_board **boardp;
1da177e4
LT
686 unsigned char *rp;
687 unsigned long dpat;
688 struct nubus_dir dir;
689 struct nubus_dirent ent;
690
691 /* Move to the start of the format block */
f42e5550 692 rp = nubus_rom_addr(slot);
1da177e4
LT
693 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
694
695 /* Actually we should probably panic if this fails */
dd00cc48 696 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
f42e5550 697 return NULL;
1da177e4
LT
698 board->fblock = rp;
699
700 /* Dump the format block for debugging purposes */
71ae40e4
DHD
701 pr_debug("Slot %X, format block at 0x%p:\n", slot, rp);
702 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
703 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
704 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
705 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
706 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
707 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
708 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
709 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
710 rp = board->fblock;
711
1da177e4 712 board->slot = slot;
f42e5550 713 board->slot_addr = (unsigned long)nubus_slot_addr(slot);
1da177e4
LT
714 board->doffset = nubus_get_rom(&rp, 4, bytelanes);
715 /* rom_length is *supposed* to be the total length of the
716 * ROM. In practice it is the "amount of ROM used to compute
717 * the CRC." So some jokers decide to set it to zero and
718 * set the crc to zero so they don't have to do any math.
719 * See the Performa 460 ROM, for example. Those Apple "engineers".
720 */
721 board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
722 board->crc = nubus_get_rom(&rp, 4, bytelanes);
723 board->rev = nubus_get_rom(&rp, 1, bytelanes);
f42e5550 724 board->format = nubus_get_rom(&rp, 1, bytelanes);
1da177e4
LT
725 board->lanes = bytelanes;
726
727 /* Directory offset should be small and negative... */
f42e5550 728 if (!(board->doffset & 0x00FF0000))
71ae40e4 729 pr_warn("Dodgy doffset!\n");
1da177e4 730 dpat = nubus_get_rom(&rp, 4, bytelanes);
f42e5550 731 if (dpat != NUBUS_TEST_PATTERN)
71ae40e4 732 pr_warn("Wrong test pattern %08lx!\n", dpat);
f42e5550 733
1da177e4
LT
734 /*
735 * I wonder how the CRC is meant to work -
736 * any takers ?
737 * CSA: According to MAC docs, not all cards pass the CRC anyway,
738 * since the initial Macintosh ROM releases skipped the check.
739 */
740
475e6e15
DHD
741 /* Set up the directory pointer */
742 board->directory = board->fblock;
743 nubus_move(&board->directory, nubus_expand32(board->doffset),
744 board->lanes);
745
f42e5550 746 nubus_get_root_dir(board, &dir);
1da177e4
LT
747
748 /* We're ready to rock */
71ae40e4 749 pr_info("Slot %X:\n", slot);
1da177e4
LT
750
751 /* Each slot should have one board resource and any number of
752 functional resources. So we'll fill in some fields in the
753 struct nubus_board from the board resource, then walk down
754 the list of functional resources, spinning out a nubus_dev
755 for each of them. */
756 if (nubus_readdir(&dir, &ent) == -1) {
757 /* We can't have this! */
71ae40e4 758 pr_err("Board resource not found!\n");
1da177e4
LT
759 return NULL;
760 } else {
71ae40e4 761 pr_info(" Board resource:\n");
1da177e4
LT
762 nubus_get_board_resource(board, slot, &ent);
763 }
764
1da177e4 765 while (nubus_readdir(&dir, &ent) != -1) {
f42e5550
FT
766 struct nubus_dev *dev;
767 struct nubus_dev **devp;
768
1da177e4
LT
769 dev = nubus_get_functional_resource(board, slot, &ent);
770 if (dev == NULL)
771 continue;
772
773 /* We zeroed this out above */
774 if (board->first_dev == NULL)
775 board->first_dev = dev;
f42e5550 776
1da177e4 777 /* Put it on the global NuBus device chain. Keep entries in order. */
f42e5550
FT
778 for (devp = &nubus_devices; *devp != NULL;
779 devp = &((*devp)->next))
1da177e4
LT
780 /* spin */;
781 *devp = dev;
f42e5550 782 dev->next = NULL;
1da177e4
LT
783 }
784
785 /* Put it on the global NuBus board chain. Keep entries in order. */
f42e5550
FT
786 for (boardp = &nubus_boards; *boardp != NULL;
787 boardp = &((*boardp)->next))
1da177e4
LT
788 /* spin */;
789 *boardp = board;
790 board->next = NULL;
f42e5550 791
1da177e4
LT
792 return board;
793}
794
795void __init nubus_probe_slot(int slot)
796{
797 unsigned char dp;
f42e5550 798 unsigned char *rp;
1da177e4
LT
799 int i;
800
f42e5550
FT
801 rp = nubus_rom_addr(slot);
802 for (i = 4; i; i--) {
1da177e4
LT
803 int card_present;
804
805 rp--;
1da177e4 806 card_present = hwreg_present(rp);
1da177e4
LT
807 if (!card_present)
808 continue;
809
1da177e4 810 dp = *rp;
1da177e4
LT
811
812 /* The last byte of the format block consists of two
813 nybbles which are "mirror images" of each other.
814 These show us the valid bytelanes */
f42e5550 815 if ((((dp >> 4) ^ dp) & 0x0F) != 0x0F)
1da177e4
LT
816 continue;
817 /* Check that this value is actually *on* one of the
818 bytelanes it claims are valid! */
85cc313a 819 if (not_useful(rp, dp))
1da177e4
LT
820 continue;
821
822 /* Looks promising. Let's put it on the list. */
823 nubus_add_board(slot, dp);
824
825 return;
826 }
827}
828
1da177e4
LT
829void __init nubus_scan_bus(void)
830{
831 int slot;
f42e5550 832
f42e5550 833 for (slot = 9; slot < 15; slot++) {
1da177e4
LT
834 nubus_probe_slot(slot);
835 }
836}
837
838static int __init nubus_init(void)
839{
f42e5550 840 if (!MACH_IS_MAC)
1da177e4
LT
841 return 0;
842
843 /* Initialize the NuBus interrupts */
844 if (oss_present) {
845 oss_nubus_init();
846 } else {
847 via_nubus_init();
848 }
849
1da177e4 850 /* And probe */
71ae40e4 851 pr_info("NuBus: Scanning NuBus slots.\n");
1da177e4 852 nubus_devices = NULL;
f42e5550 853 nubus_boards = NULL;
1da177e4 854 nubus_scan_bus();
1da177e4 855 nubus_proc_init();
1da177e4
LT
856 return 0;
857}
858
859subsys_initcall(nubus_init);