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