root/drivers/nubus/nubus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. not_useful
  2. nubus_get_rom
  3. nubus_rewind
  4. nubus_advance
  5. nubus_move
  6. nubus_expand32
  7. nubus_rom_addr
  8. nubus_dirptr
  9. nubus_get_rsrc_mem
  10. nubus_get_rsrc_str
  11. nubus_seq_write_rsrc_mem
  12. nubus_get_root_dir
  13. nubus_get_func_dir
  14. nubus_get_board_dir
  15. nubus_get_subdir
  16. nubus_readdir
  17. nubus_rewinddir
  18. nubus_first_rsrc_or_null
  19. nubus_next_rsrc_or_null
  20. nubus_find_rsrc
  21. nubus_get_block_rsrc_dir
  22. nubus_get_display_vidmode
  23. nubus_get_display_resource
  24. nubus_get_network_resource
  25. nubus_get_cpu_resource
  26. nubus_get_private_resource
  27. nubus_get_functional_resource
  28. nubus_get_icon
  29. nubus_get_vendorinfo
  30. nubus_get_board_resource
  31. nubus_add_board
  32. nubus_probe_slot
  33. nubus_scan_bus
  34. nubus_init

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

/* [<][>][^][v][top][bottom][index][help] */