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