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