Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Macintosh Nubus Interface Code
0004  *
0005  *      Originally by Alan Cox
0006  *
0007  *      Mostly rewritten by David Huggins-Daines, C. Scott Ananian,
0008  *      and others.
0009  */
0010 
0011 #include <linux/types.h>
0012 #include <linux/kernel.h>
0013 #include <linux/string.h>
0014 #include <linux/nubus.h>
0015 #include <linux/errno.h>
0016 #include <linux/init.h>
0017 #include <linux/module.h>
0018 #include <linux/seq_file.h>
0019 #include <linux/slab.h>
0020 #include <asm/setup.h>
0021 #include <asm/page.h>
0022 #include <asm/hwtest.h>
0023 
0024 /* Constants */
0025 
0026 /* This is, of course, the size in bytelanes, rather than the size in
0027    actual bytes */
0028 #define FORMAT_BLOCK_SIZE 20
0029 #define ROM_DIR_OFFSET 0x24
0030 
0031 #define NUBUS_TEST_PATTERN 0x5A932BC7
0032 
0033 /* Globals */
0034 
0035 LIST_HEAD(nubus_func_rsrcs);
0036 
0037 /* Meaning of "bytelanes":
0038 
0039    The card ROM may appear on any or all bytes of each long word in
0040    NuBus memory.  The low 4 bits of the "map" value found in the
0041    format block (at the top of the slot address space, as well as at
0042    the top of the MacOS ROM) tells us which bytelanes, i.e. which byte
0043    offsets within each longword, are valid.  Thus:
0044 
0045    A map of 0x0f, as found in the MacOS ROM, means that all bytelanes
0046    are valid.
0047 
0048    A map of 0xf0 means that no bytelanes are valid (We pray that we
0049    will never encounter this, but stranger things have happened)
0050 
0051    A map of 0xe1 means that only the MSB of each long word is actually
0052    part of the card ROM.  (We hope to never encounter NuBus on a
0053    little-endian machine.  Again, stranger things have happened)
0054 
0055    A map of 0x78 means that only the LSB of each long word is valid.
0056 
0057    Etcetera, etcetera.  Hopefully this clears up some confusion over
0058    what the following code actually does.  */
0059 
0060 static inline int not_useful(void *p, int map)
0061 {
0062     unsigned long pv = (unsigned long)p;
0063 
0064     pv &= 3;
0065     if (map & (1 << pv))
0066         return 0;
0067     return 1;
0068 }
0069 
0070 static unsigned long nubus_get_rom(unsigned char **ptr, int len, int map)
0071 {
0072     /* This will hold the result */
0073     unsigned long v = 0;
0074     unsigned char *p = *ptr;
0075 
0076     while (len) {
0077         v <<= 8;
0078         while (not_useful(p, map))
0079             p++;
0080         v |= *p++;
0081         len--;
0082     }
0083     *ptr = p;
0084     return v;
0085 }
0086 
0087 static void nubus_rewind(unsigned char **ptr, int len, int map)
0088 {
0089     unsigned char *p = *ptr;
0090 
0091     while (len) {
0092         do {
0093             p--;
0094         } while (not_useful(p, map));
0095         len--;
0096     }
0097     *ptr = p;
0098 }
0099 
0100 static void nubus_advance(unsigned char **ptr, int len, int map)
0101 {
0102     unsigned char *p = *ptr;
0103 
0104     while (len) {
0105         while (not_useful(p, map))
0106             p++;
0107         p++;
0108         len--;
0109     }
0110     *ptr = p;
0111 }
0112 
0113 static void nubus_move(unsigned char **ptr, int len, int map)
0114 {
0115     unsigned long slot_space = (unsigned long)*ptr & 0xFF000000;
0116 
0117     if (len > 0)
0118         nubus_advance(ptr, len, map);
0119     else if (len < 0)
0120         nubus_rewind(ptr, -len, map);
0121 
0122     if (((unsigned long)*ptr & 0xFF000000) != slot_space)
0123         pr_err("%s: moved out of slot address space!\n", __func__);
0124 }
0125 
0126 /* Now, functions to read the sResource tree */
0127 
0128 /* Each sResource entry consists of a 1-byte ID and a 3-byte data
0129    field.  If that data field contains an offset, then obviously we
0130    have to expand it from a 24-bit signed number to a 32-bit signed
0131    number. */
0132 
0133 static inline long nubus_expand32(long foo)
0134 {
0135     if (foo & 0x00800000)   /* 24bit negative */
0136         foo |= 0xFF000000;
0137     return foo;
0138 }
0139 
0140 static inline void *nubus_rom_addr(int slot)
0141 {
0142     /*
0143      *  Returns the first byte after the card. We then walk
0144      *  backwards to get the lane register and the config
0145      */
0146     return (void *)(0xF1000000 + (slot << 24));
0147 }
0148 
0149 unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
0150 {
0151     unsigned char *p = nd->base;
0152 
0153     /* Essentially, just step over the bytelanes using whatever
0154        offset we might have found */
0155     nubus_move(&p, nubus_expand32(nd->data), nd->mask);
0156     /* And return the value */
0157     return p;
0158 }
0159 
0160 /* These two are for pulling resource data blocks (i.e. stuff that's
0161    pointed to with offsets) out of the card ROM. */
0162 
0163 void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
0164             unsigned int len)
0165 {
0166     unsigned char *t = dest;
0167     unsigned char *p = nubus_dirptr(dirent);
0168 
0169     while (len) {
0170         *t++ = nubus_get_rom(&p, 1, dirent->mask);
0171         len--;
0172     }
0173 }
0174 EXPORT_SYMBOL(nubus_get_rsrc_mem);
0175 
0176 unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
0177                 unsigned int len)
0178 {
0179     char *t = dest;
0180     unsigned char *p = nubus_dirptr(dirent);
0181 
0182     while (len > 1) {
0183         unsigned char c = nubus_get_rom(&p, 1, dirent->mask);
0184 
0185         if (!c)
0186             break;
0187         *t++ = c;
0188         len--;
0189     }
0190     if (len > 0)
0191         *t = '\0';
0192     return t - dest;
0193 }
0194 EXPORT_SYMBOL(nubus_get_rsrc_str);
0195 
0196 void nubus_seq_write_rsrc_mem(struct seq_file *m,
0197                   const struct nubus_dirent *dirent,
0198                   unsigned int len)
0199 {
0200     unsigned long buf[32];
0201     unsigned int buf_size = sizeof(buf);
0202     unsigned char *p = nubus_dirptr(dirent);
0203 
0204     /* If possible, write out full buffers */
0205     while (len >= buf_size) {
0206         unsigned int i;
0207 
0208         for (i = 0; i < ARRAY_SIZE(buf); i++)
0209             buf[i] = nubus_get_rom(&p, sizeof(buf[0]),
0210                            dirent->mask);
0211         seq_write(m, buf, buf_size);
0212         len -= buf_size;
0213     }
0214     /* If not, write out individual bytes */
0215     while (len--)
0216         seq_putc(m, nubus_get_rom(&p, 1, dirent->mask));
0217 }
0218 
0219 int nubus_get_root_dir(const struct nubus_board *board,
0220                struct nubus_dir *dir)
0221 {
0222     dir->ptr = dir->base = board->directory;
0223     dir->done = 0;
0224     dir->mask = board->lanes;
0225     return 0;
0226 }
0227 EXPORT_SYMBOL(nubus_get_root_dir);
0228 
0229 /* This is a slyly renamed version of the above */
0230 int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir)
0231 {
0232     dir->ptr = dir->base = fres->directory;
0233     dir->done = 0;
0234     dir->mask = fres->board->lanes;
0235     return 0;
0236 }
0237 EXPORT_SYMBOL(nubus_get_func_dir);
0238 
0239 int nubus_get_board_dir(const struct nubus_board *board,
0240             struct nubus_dir *dir)
0241 {
0242     struct nubus_dirent ent;
0243 
0244     dir->ptr = dir->base = board->directory;
0245     dir->done = 0;
0246     dir->mask = board->lanes;
0247 
0248     /* Now dereference it (the first directory is always the board
0249        directory) */
0250     if (nubus_readdir(dir, &ent) == -1)
0251         return -1;
0252     if (nubus_get_subdir(&ent, dir) == -1)
0253         return -1;
0254     return 0;
0255 }
0256 EXPORT_SYMBOL(nubus_get_board_dir);
0257 
0258 int nubus_get_subdir(const struct nubus_dirent *ent,
0259              struct nubus_dir *dir)
0260 {
0261     dir->ptr = dir->base = nubus_dirptr(ent);
0262     dir->done = 0;
0263     dir->mask = ent->mask;
0264     return 0;
0265 }
0266 EXPORT_SYMBOL(nubus_get_subdir);
0267 
0268 int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
0269 {
0270     u32 resid;
0271 
0272     if (nd->done)
0273         return -1;
0274 
0275     /* Do this first, otherwise nubus_rewind & co are off by 4 */
0276     ent->base = nd->ptr;
0277 
0278     /* This moves nd->ptr forward */
0279     resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
0280 
0281     /* EOL marker, as per the Apple docs */
0282     if ((resid & 0xff000000) == 0xff000000) {
0283         /* Mark it as done */
0284         nd->done = 1;
0285         return -1;
0286     }
0287 
0288     /* First byte is the resource ID */
0289     ent->type = resid >> 24;
0290     /* Low 3 bytes might contain data (or might not) */
0291     ent->data = resid & 0xffffff;
0292     ent->mask = nd->mask;
0293     return 0;
0294 }
0295 EXPORT_SYMBOL(nubus_readdir);
0296 
0297 int nubus_rewinddir(struct nubus_dir *dir)
0298 {
0299     dir->ptr = dir->base;
0300     dir->done = 0;
0301     return 0;
0302 }
0303 EXPORT_SYMBOL(nubus_rewinddir);
0304 
0305 /* Driver interface functions, more or less like in pci.c */
0306 
0307 struct nubus_rsrc *nubus_first_rsrc_or_null(void)
0308 {
0309     return list_first_entry_or_null(&nubus_func_rsrcs, struct nubus_rsrc,
0310                     list);
0311 }
0312 EXPORT_SYMBOL(nubus_first_rsrc_or_null);
0313 
0314 struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)
0315 {
0316     if (list_is_last(&from->list, &nubus_func_rsrcs))
0317         return NULL;
0318     return list_next_entry(from, list);
0319 }
0320 EXPORT_SYMBOL(nubus_next_rsrc_or_null);
0321 
0322 int
0323 nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type,
0324         struct nubus_dirent *ent)
0325 {
0326     while (nubus_readdir(dir, ent) != -1) {
0327         if (ent->type == rsrc_type)
0328             return 0;
0329     }
0330     return -1;
0331 }
0332 EXPORT_SYMBOL(nubus_find_rsrc);
0333 
0334 /* Initialization functions - decide which slots contain stuff worth
0335    looking at, and print out lots and lots of information from the
0336    resource blocks. */
0337 
0338 static int __init nubus_get_block_rsrc_dir(struct nubus_board *board,
0339                        struct proc_dir_entry *procdir,
0340                        const struct nubus_dirent *parent)
0341 {
0342     struct nubus_dir dir;
0343     struct nubus_dirent ent;
0344 
0345     nubus_get_subdir(parent, &dir);
0346     dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
0347 
0348     while (nubus_readdir(&dir, &ent) != -1) {
0349         u32 size;
0350 
0351         nubus_get_rsrc_mem(&size, &ent, 4);
0352         pr_debug("        block (0x%x), size %d\n", ent.type, size);
0353         nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
0354     }
0355     return 0;
0356 }
0357 
0358 static int __init nubus_get_display_vidmode(struct nubus_board *board,
0359                         struct proc_dir_entry *procdir,
0360                         const struct nubus_dirent *parent)
0361 {
0362     struct nubus_dir dir;
0363     struct nubus_dirent ent;
0364 
0365     nubus_get_subdir(parent, &dir);
0366     dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
0367 
0368     while (nubus_readdir(&dir, &ent) != -1) {
0369         switch (ent.type) {
0370         case 1: /* mVidParams */
0371         case 2: /* mTable */
0372         {
0373             u32 size;
0374 
0375             nubus_get_rsrc_mem(&size, &ent, 4);
0376             pr_debug("        block (0x%x), size %d\n", ent.type,
0377                 size);
0378             nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
0379             break;
0380         }
0381         default:
0382             pr_debug("        unknown resource 0x%02x, data 0x%06x\n",
0383                 ent.type, ent.data);
0384             nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
0385         }
0386     }
0387     return 0;
0388 }
0389 
0390 static int __init nubus_get_display_resource(struct nubus_rsrc *fres,
0391                          struct proc_dir_entry *procdir,
0392                          const struct nubus_dirent *ent)
0393 {
0394     switch (ent->type) {
0395     case NUBUS_RESID_GAMMADIR:
0396         pr_debug("    gamma directory offset: 0x%06x\n", ent->data);
0397         nubus_get_block_rsrc_dir(fres->board, procdir, ent);
0398         break;
0399     case 0x0080 ... 0x0085:
0400         pr_debug("    mode 0x%02x info offset: 0x%06x\n",
0401             ent->type, ent->data);
0402         nubus_get_display_vidmode(fres->board, procdir, ent);
0403         break;
0404     default:
0405         pr_debug("    unknown resource 0x%02x, data 0x%06x\n",
0406             ent->type, ent->data);
0407         nubus_proc_add_rsrc_mem(procdir, ent, 0);
0408     }
0409     return 0;
0410 }
0411 
0412 static int __init nubus_get_network_resource(struct nubus_rsrc *fres,
0413                          struct proc_dir_entry *procdir,
0414                          const struct nubus_dirent *ent)
0415 {
0416     switch (ent->type) {
0417     case NUBUS_RESID_MAC_ADDRESS:
0418     {
0419         char addr[6];
0420 
0421         nubus_get_rsrc_mem(addr, ent, 6);
0422         pr_debug("    MAC address: %pM\n", addr);
0423         nubus_proc_add_rsrc_mem(procdir, ent, 6);
0424         break;
0425     }
0426     default:
0427         pr_debug("    unknown resource 0x%02x, data 0x%06x\n",
0428             ent->type, ent->data);
0429         nubus_proc_add_rsrc_mem(procdir, ent, 0);
0430     }
0431     return 0;
0432 }
0433 
0434 static int __init nubus_get_cpu_resource(struct nubus_rsrc *fres,
0435                      struct proc_dir_entry *procdir,
0436                      const struct nubus_dirent *ent)
0437 {
0438     switch (ent->type) {
0439     case NUBUS_RESID_MEMINFO:
0440     {
0441         unsigned long meminfo[2];
0442 
0443         nubus_get_rsrc_mem(&meminfo, ent, 8);
0444         pr_debug("    memory: [ 0x%08lx 0x%08lx ]\n",
0445             meminfo[0], meminfo[1]);
0446         nubus_proc_add_rsrc_mem(procdir, ent, 8);
0447         break;
0448     }
0449     case NUBUS_RESID_ROMINFO:
0450     {
0451         unsigned long rominfo[2];
0452 
0453         nubus_get_rsrc_mem(&rominfo, ent, 8);
0454         pr_debug("    ROM:    [ 0x%08lx 0x%08lx ]\n",
0455             rominfo[0], rominfo[1]);
0456         nubus_proc_add_rsrc_mem(procdir, ent, 8);
0457         break;
0458     }
0459     default:
0460         pr_debug("    unknown resource 0x%02x, data 0x%06x\n",
0461             ent->type, ent->data);
0462         nubus_proc_add_rsrc_mem(procdir, ent, 0);
0463     }
0464     return 0;
0465 }
0466 
0467 static int __init nubus_get_private_resource(struct nubus_rsrc *fres,
0468                          struct proc_dir_entry *procdir,
0469                          const struct nubus_dirent *ent)
0470 {
0471     switch (fres->category) {
0472     case NUBUS_CAT_DISPLAY:
0473         nubus_get_display_resource(fres, procdir, ent);
0474         break;
0475     case NUBUS_CAT_NETWORK:
0476         nubus_get_network_resource(fres, procdir, ent);
0477         break;
0478     case NUBUS_CAT_CPU:
0479         nubus_get_cpu_resource(fres, procdir, ent);
0480         break;
0481     default:
0482         pr_debug("    unknown resource 0x%02x, data 0x%06x\n",
0483             ent->type, ent->data);
0484         nubus_proc_add_rsrc_mem(procdir, ent, 0);
0485     }
0486     return 0;
0487 }
0488 
0489 static struct nubus_rsrc * __init
0490 nubus_get_functional_resource(struct nubus_board *board, int slot,
0491                   const struct nubus_dirent *parent)
0492 {
0493     struct nubus_dir dir;
0494     struct nubus_dirent ent;
0495     struct nubus_rsrc *fres;
0496 
0497     pr_debug("  Functional resource 0x%02x:\n", parent->type);
0498     nubus_get_subdir(parent, &dir);
0499     dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
0500 
0501     /* Actually we should probably panic if this fails */
0502     fres = kzalloc(sizeof(*fres), GFP_ATOMIC);
0503     if (!fres)
0504         return NULL;
0505     fres->resid = parent->type;
0506     fres->directory = dir.base;
0507     fres->board = board;
0508 
0509     while (nubus_readdir(&dir, &ent) != -1) {
0510         switch (ent.type) {
0511         case NUBUS_RESID_TYPE:
0512         {
0513             unsigned short nbtdata[4];
0514 
0515             nubus_get_rsrc_mem(nbtdata, &ent, 8);
0516             fres->category = nbtdata[0];
0517             fres->type     = nbtdata[1];
0518             fres->dr_sw    = nbtdata[2];
0519             fres->dr_hw    = nbtdata[3];
0520             pr_debug("    type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
0521                 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
0522             nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
0523             break;
0524         }
0525         case NUBUS_RESID_NAME:
0526         {
0527             char name[64];
0528             unsigned int len;
0529 
0530             len = nubus_get_rsrc_str(name, &ent, sizeof(name));
0531             pr_debug("    name: %s\n", name);
0532             nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
0533             break;
0534         }
0535         case NUBUS_RESID_DRVRDIR:
0536         {
0537             /* MacOS driver.  If we were NetBSD we might
0538                use this :-) */
0539             pr_debug("    driver directory offset: 0x%06x\n",
0540                 ent.data);
0541             nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
0542             break;
0543         }
0544         case NUBUS_RESID_MINOR_BASEOS:
0545         {
0546             /* We will need this in order to support
0547                multiple framebuffers.  It might be handy
0548                for Ethernet as well */
0549             u32 base_offset;
0550 
0551             nubus_get_rsrc_mem(&base_offset, &ent, 4);
0552             pr_debug("    memory offset: 0x%08x\n", base_offset);
0553             nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
0554             break;
0555         }
0556         case NUBUS_RESID_MINOR_LENGTH:
0557         {
0558             /* Ditto */
0559             u32 length;
0560 
0561             nubus_get_rsrc_mem(&length, &ent, 4);
0562             pr_debug("    memory length: 0x%08x\n", length);
0563             nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
0564             break;
0565         }
0566         case NUBUS_RESID_FLAGS:
0567             pr_debug("    flags: 0x%06x\n", ent.data);
0568             nubus_proc_add_rsrc(dir.procdir, &ent);
0569             break;
0570         case NUBUS_RESID_HWDEVID:
0571             pr_debug("    hwdevid: 0x%06x\n", ent.data);
0572             nubus_proc_add_rsrc(dir.procdir, &ent);
0573             break;
0574         default:
0575             /* Local/Private resources have their own
0576                function */
0577             nubus_get_private_resource(fres, dir.procdir, &ent);
0578         }
0579     }
0580 
0581     return fres;
0582 }
0583 
0584 /* This is *really* cool. */
0585 static int __init nubus_get_icon(struct nubus_board *board,
0586                  struct proc_dir_entry *procdir,
0587                  const struct nubus_dirent *ent)
0588 {
0589     /* Should be 32x32 if my memory serves me correctly */
0590     u32 icon[32];
0591     int i;
0592 
0593     nubus_get_rsrc_mem(&icon, ent, 128);
0594     pr_debug("    icon:\n");
0595     for (i = 0; i < 8; i++)
0596         pr_debug("        %08x %08x %08x %08x\n",
0597             icon[i * 4 + 0], icon[i * 4 + 1],
0598             icon[i * 4 + 2], icon[i * 4 + 3]);
0599     nubus_proc_add_rsrc_mem(procdir, ent, 128);
0600 
0601     return 0;
0602 }
0603 
0604 static int __init nubus_get_vendorinfo(struct nubus_board *board,
0605                        struct proc_dir_entry *procdir,
0606                        const struct nubus_dirent *parent)
0607 {
0608     struct nubus_dir dir;
0609     struct nubus_dirent ent;
0610     static char *vendor_fields[6] = { "ID", "serial", "revision",
0611                                       "part", "date", "unknown field" };
0612 
0613     pr_debug("    vendor info:\n");
0614     nubus_get_subdir(parent, &dir);
0615     dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
0616 
0617     while (nubus_readdir(&dir, &ent) != -1) {
0618         char name[64];
0619         unsigned int len;
0620 
0621         /* These are all strings, we think */
0622         len = nubus_get_rsrc_str(name, &ent, sizeof(name));
0623         if (ent.type < 1 || ent.type > 5)
0624             ent.type = 5;
0625         pr_debug("    %s: %s\n", vendor_fields[ent.type - 1], name);
0626         nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
0627     }
0628     return 0;
0629 }
0630 
0631 static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
0632                        const struct nubus_dirent *parent)
0633 {
0634     struct nubus_dir dir;
0635     struct nubus_dirent ent;
0636 
0637     pr_debug("  Board resource 0x%02x:\n", parent->type);
0638     nubus_get_subdir(parent, &dir);
0639     dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
0640 
0641     while (nubus_readdir(&dir, &ent) != -1) {
0642         switch (ent.type) {
0643         case NUBUS_RESID_TYPE:
0644         {
0645             unsigned short nbtdata[4];
0646             /* This type is always the same, and is not
0647                useful except insofar as it tells us that
0648                we really are looking at a board resource. */
0649             nubus_get_rsrc_mem(nbtdata, &ent, 8);
0650             pr_debug("    type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
0651                 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
0652             if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
0653                 nbtdata[2] != 0 || nbtdata[3] != 0)
0654                 pr_err("Slot %X: sResource is not a board resource!\n",
0655                        slot);
0656             nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
0657             break;
0658         }
0659         case NUBUS_RESID_NAME:
0660         {
0661             unsigned int len;
0662 
0663             len = nubus_get_rsrc_str(board->name, &ent,
0664                          sizeof(board->name));
0665             pr_debug("    name: %s\n", board->name);
0666             nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
0667             break;
0668         }
0669         case NUBUS_RESID_ICON:
0670             nubus_get_icon(board, dir.procdir, &ent);
0671             break;
0672         case NUBUS_RESID_BOARDID:
0673             pr_debug("    board id: 0x%x\n", ent.data);
0674             nubus_proc_add_rsrc(dir.procdir, &ent);
0675             break;
0676         case NUBUS_RESID_PRIMARYINIT:
0677             pr_debug("    primary init offset: 0x%06x\n", ent.data);
0678             nubus_proc_add_rsrc(dir.procdir, &ent);
0679             break;
0680         case NUBUS_RESID_VENDORINFO:
0681             nubus_get_vendorinfo(board, dir.procdir, &ent);
0682             break;
0683         case NUBUS_RESID_FLAGS:
0684             pr_debug("    flags: 0x%06x\n", ent.data);
0685             nubus_proc_add_rsrc(dir.procdir, &ent);
0686             break;
0687         case NUBUS_RESID_HWDEVID:
0688             pr_debug("    hwdevid: 0x%06x\n", ent.data);
0689             nubus_proc_add_rsrc(dir.procdir, &ent);
0690             break;
0691         case NUBUS_RESID_SECONDINIT:
0692             pr_debug("    secondary init offset: 0x%06x\n",
0693                  ent.data);
0694             nubus_proc_add_rsrc(dir.procdir, &ent);
0695             break;
0696             /* WTF isn't this in the functional resources? */
0697         case NUBUS_RESID_VIDNAMES:
0698             pr_debug("    vidnames directory offset: 0x%06x\n",
0699                 ent.data);
0700             nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
0701             break;
0702             /* Same goes for this */
0703         case NUBUS_RESID_VIDMODES:
0704             pr_debug("    video mode parameter directory offset: 0x%06x\n",
0705                 ent.data);
0706             nubus_proc_add_rsrc(dir.procdir, &ent);
0707             break;
0708         default:
0709             pr_debug("    unknown resource 0x%02x, data 0x%06x\n",
0710                 ent.type, ent.data);
0711             nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
0712         }
0713     }
0714     return 0;
0715 }
0716 
0717 static void __init nubus_add_board(int slot, int bytelanes)
0718 {
0719     struct nubus_board *board;
0720     unsigned char *rp;
0721     unsigned long dpat;
0722     struct nubus_dir dir;
0723     struct nubus_dirent ent;
0724     int prev_resid = -1;
0725 
0726     /* Move to the start of the format block */
0727     rp = nubus_rom_addr(slot);
0728     nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
0729 
0730     /* Actually we should probably panic if this fails */
0731     if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
0732         return;
0733     board->fblock = rp;
0734 
0735     /* Dump the format block for debugging purposes */
0736     pr_debug("Slot %X, format block at 0x%p:\n", slot, rp);
0737     pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0738     pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0739     pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0740     pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0741     pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0742     pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0743     pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0744     pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0745     rp = board->fblock;
0746 
0747     board->slot = slot;
0748     board->slot_addr = (unsigned long)nubus_slot_addr(slot);
0749     board->doffset = nubus_get_rom(&rp, 4, bytelanes);
0750     /* rom_length is *supposed* to be the total length of the
0751      * ROM.  In practice it is the "amount of ROM used to compute
0752      * the CRC."  So some jokers decide to set it to zero and
0753      * set the crc to zero so they don't have to do any math.
0754      * See the Performa 460 ROM, for example.  Those Apple "engineers".
0755      */
0756     board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
0757     board->crc = nubus_get_rom(&rp, 4, bytelanes);
0758     board->rev = nubus_get_rom(&rp, 1, bytelanes);
0759     board->format = nubus_get_rom(&rp, 1, bytelanes);
0760     board->lanes = bytelanes;
0761 
0762     /* Directory offset should be small and negative... */
0763     if (!(board->doffset & 0x00FF0000))
0764         pr_warn("Slot %X: Dodgy doffset!\n", slot);
0765     dpat = nubus_get_rom(&rp, 4, bytelanes);
0766     if (dpat != NUBUS_TEST_PATTERN)
0767         pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);
0768 
0769     /*
0770      *  I wonder how the CRC is meant to work -
0771      *      any takers ?
0772      * CSA: According to MAC docs, not all cards pass the CRC anyway,
0773      * since the initial Macintosh ROM releases skipped the check.
0774      */
0775 
0776     /* Set up the directory pointer */
0777     board->directory = board->fblock;
0778     nubus_move(&board->directory, nubus_expand32(board->doffset),
0779                board->lanes);
0780 
0781     nubus_get_root_dir(board, &dir);
0782 
0783     /* We're ready to rock */
0784     pr_debug("Slot %X resources:\n", slot);
0785 
0786     /* Each slot should have one board resource and any number of
0787      * functional resources.  So we'll fill in some fields in the
0788      * struct nubus_board from the board resource, then walk down
0789      * the list of functional resources, spinning out a nubus_rsrc
0790      * for each of them.
0791      */
0792     if (nubus_readdir(&dir, &ent) == -1) {
0793         /* We can't have this! */
0794         pr_err("Slot %X: Board resource not found!\n", slot);
0795         kfree(board);
0796         return;
0797     }
0798 
0799     if (ent.type < 1 || ent.type > 127)
0800         pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
0801 
0802     board->procdir = nubus_proc_add_board(board);
0803 
0804     nubus_get_board_resource(board, slot, &ent);
0805 
0806     while (nubus_readdir(&dir, &ent) != -1) {
0807         struct nubus_rsrc *fres;
0808 
0809         fres = nubus_get_functional_resource(board, slot, &ent);
0810         if (fres == NULL)
0811             continue;
0812 
0813         /* Resources should appear in ascending ID order. This sanity
0814          * check prevents duplicate resource IDs.
0815          */
0816         if (fres->resid <= prev_resid) {
0817             kfree(fres);
0818             continue;
0819         }
0820         prev_resid = fres->resid;
0821 
0822         list_add_tail(&fres->list, &nubus_func_rsrcs);
0823     }
0824 
0825     if (nubus_device_register(board))
0826         put_device(&board->dev);
0827 }
0828 
0829 static void __init nubus_probe_slot(int slot)
0830 {
0831     unsigned char dp;
0832     unsigned char *rp;
0833     int i;
0834 
0835     rp = nubus_rom_addr(slot);
0836     for (i = 4; i; i--) {
0837         rp--;
0838         if (!hwreg_present(rp))
0839             continue;
0840 
0841         dp = *rp;
0842 
0843         /* The last byte of the format block consists of two
0844            nybbles which are "mirror images" of each other.
0845            These show us the valid bytelanes */
0846         if ((((dp >> 4) ^ dp) & 0x0F) != 0x0F)
0847             continue;
0848         /* Check that this value is actually *on* one of the
0849            bytelanes it claims are valid! */
0850         if (not_useful(rp, dp))
0851             continue;
0852 
0853         /* Looks promising.  Let's put it on the list. */
0854         nubus_add_board(slot, dp);
0855 
0856         return;
0857     }
0858 }
0859 
0860 static void __init nubus_scan_bus(void)
0861 {
0862     int slot;
0863 
0864     pr_info("NuBus: Scanning NuBus slots.\n");
0865     for (slot = 9; slot < 15; slot++) {
0866         nubus_probe_slot(slot);
0867     }
0868 }
0869 
0870 static int __init nubus_init(void)
0871 {
0872     int err;
0873 
0874     if (!MACH_IS_MAC)
0875         return 0;
0876 
0877     nubus_proc_init();
0878     err = nubus_parent_device_register();
0879     if (err)
0880         return err;
0881     nubus_scan_bus();
0882     return 0;
0883 }
0884 
0885 subsys_initcall(nubus_init);