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