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