0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/types.h>
0012 #include <linux/kernel.h>
0013 #include <linux/string.h>
0014 #include <linux/nubus.h>
0015 #include <linux/errno.h>
0016 #include <linux/init.h>
0017 #include <linux/module.h>
0018 #include <linux/seq_file.h>
0019 #include <linux/slab.h>
0020 #include <asm/setup.h>
0021 #include <asm/page.h>
0022 #include <asm/hwtest.h>
0023
0024
0025
0026
0027
0028 #define FORMAT_BLOCK_SIZE 20
0029 #define ROM_DIR_OFFSET 0x24
0030
0031 #define NUBUS_TEST_PATTERN 0x5A932BC7
0032
0033
0034
0035 LIST_HEAD(nubus_func_rsrcs);
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 static inline int not_useful(void *p, int map)
0061 {
0062 unsigned long pv = (unsigned long)p;
0063
0064 pv &= 3;
0065 if (map & (1 << pv))
0066 return 0;
0067 return 1;
0068 }
0069
0070 static unsigned long nubus_get_rom(unsigned char **ptr, int len, int map)
0071 {
0072
0073 unsigned long v = 0;
0074 unsigned char *p = *ptr;
0075
0076 while (len) {
0077 v <<= 8;
0078 while (not_useful(p, map))
0079 p++;
0080 v |= *p++;
0081 len--;
0082 }
0083 *ptr = p;
0084 return v;
0085 }
0086
0087 static void nubus_rewind(unsigned char **ptr, int len, int map)
0088 {
0089 unsigned char *p = *ptr;
0090
0091 while (len) {
0092 do {
0093 p--;
0094 } while (not_useful(p, map));
0095 len--;
0096 }
0097 *ptr = p;
0098 }
0099
0100 static void nubus_advance(unsigned char **ptr, int len, int map)
0101 {
0102 unsigned char *p = *ptr;
0103
0104 while (len) {
0105 while (not_useful(p, map))
0106 p++;
0107 p++;
0108 len--;
0109 }
0110 *ptr = p;
0111 }
0112
0113 static void nubus_move(unsigned char **ptr, int len, int map)
0114 {
0115 unsigned long slot_space = (unsigned long)*ptr & 0xFF000000;
0116
0117 if (len > 0)
0118 nubus_advance(ptr, len, map);
0119 else if (len < 0)
0120 nubus_rewind(ptr, -len, map);
0121
0122 if (((unsigned long)*ptr & 0xFF000000) != slot_space)
0123 pr_err("%s: moved out of slot address space!\n", __func__);
0124 }
0125
0126
0127
0128
0129
0130
0131
0132
0133 static inline long nubus_expand32(long foo)
0134 {
0135 if (foo & 0x00800000)
0136 foo |= 0xFF000000;
0137 return foo;
0138 }
0139
0140 static inline void *nubus_rom_addr(int slot)
0141 {
0142
0143
0144
0145
0146 return (void *)(0xF1000000 + (slot << 24));
0147 }
0148
0149 unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
0150 {
0151 unsigned char *p = nd->base;
0152
0153
0154
0155 nubus_move(&p, nubus_expand32(nd->data), nd->mask);
0156
0157 return p;
0158 }
0159
0160
0161
0162
0163 void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
0164 unsigned int len)
0165 {
0166 unsigned char *t = dest;
0167 unsigned char *p = nubus_dirptr(dirent);
0168
0169 while (len) {
0170 *t++ = nubus_get_rom(&p, 1, dirent->mask);
0171 len--;
0172 }
0173 }
0174 EXPORT_SYMBOL(nubus_get_rsrc_mem);
0175
0176 unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
0177 unsigned int len)
0178 {
0179 char *t = dest;
0180 unsigned char *p = nubus_dirptr(dirent);
0181
0182 while (len > 1) {
0183 unsigned char c = nubus_get_rom(&p, 1, dirent->mask);
0184
0185 if (!c)
0186 break;
0187 *t++ = c;
0188 len--;
0189 }
0190 if (len > 0)
0191 *t = '\0';
0192 return t - dest;
0193 }
0194 EXPORT_SYMBOL(nubus_get_rsrc_str);
0195
0196 void nubus_seq_write_rsrc_mem(struct seq_file *m,
0197 const struct nubus_dirent *dirent,
0198 unsigned int len)
0199 {
0200 unsigned long buf[32];
0201 unsigned int buf_size = sizeof(buf);
0202 unsigned char *p = nubus_dirptr(dirent);
0203
0204
0205 while (len >= buf_size) {
0206 unsigned int i;
0207
0208 for (i = 0; i < ARRAY_SIZE(buf); i++)
0209 buf[i] = nubus_get_rom(&p, sizeof(buf[0]),
0210 dirent->mask);
0211 seq_write(m, buf, buf_size);
0212 len -= buf_size;
0213 }
0214
0215 while (len--)
0216 seq_putc(m, nubus_get_rom(&p, 1, dirent->mask));
0217 }
0218
0219 int nubus_get_root_dir(const struct nubus_board *board,
0220 struct nubus_dir *dir)
0221 {
0222 dir->ptr = dir->base = board->directory;
0223 dir->done = 0;
0224 dir->mask = board->lanes;
0225 return 0;
0226 }
0227 EXPORT_SYMBOL(nubus_get_root_dir);
0228
0229
0230 int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir)
0231 {
0232 dir->ptr = dir->base = fres->directory;
0233 dir->done = 0;
0234 dir->mask = fres->board->lanes;
0235 return 0;
0236 }
0237 EXPORT_SYMBOL(nubus_get_func_dir);
0238
0239 int nubus_get_board_dir(const struct nubus_board *board,
0240 struct nubus_dir *dir)
0241 {
0242 struct nubus_dirent ent;
0243
0244 dir->ptr = dir->base = board->directory;
0245 dir->done = 0;
0246 dir->mask = board->lanes;
0247
0248
0249
0250 if (nubus_readdir(dir, &ent) == -1)
0251 return -1;
0252 if (nubus_get_subdir(&ent, dir) == -1)
0253 return -1;
0254 return 0;
0255 }
0256 EXPORT_SYMBOL(nubus_get_board_dir);
0257
0258 int nubus_get_subdir(const struct nubus_dirent *ent,
0259 struct nubus_dir *dir)
0260 {
0261 dir->ptr = dir->base = nubus_dirptr(ent);
0262 dir->done = 0;
0263 dir->mask = ent->mask;
0264 return 0;
0265 }
0266 EXPORT_SYMBOL(nubus_get_subdir);
0267
0268 int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
0269 {
0270 u32 resid;
0271
0272 if (nd->done)
0273 return -1;
0274
0275
0276 ent->base = nd->ptr;
0277
0278
0279 resid = nubus_get_rom(&nd->ptr, 4, nd->mask);
0280
0281
0282 if ((resid & 0xff000000) == 0xff000000) {
0283
0284 nd->done = 1;
0285 return -1;
0286 }
0287
0288
0289 ent->type = resid >> 24;
0290
0291 ent->data = resid & 0xffffff;
0292 ent->mask = nd->mask;
0293 return 0;
0294 }
0295 EXPORT_SYMBOL(nubus_readdir);
0296
0297 int nubus_rewinddir(struct nubus_dir *dir)
0298 {
0299 dir->ptr = dir->base;
0300 dir->done = 0;
0301 return 0;
0302 }
0303 EXPORT_SYMBOL(nubus_rewinddir);
0304
0305
0306
0307 struct nubus_rsrc *nubus_first_rsrc_or_null(void)
0308 {
0309 return list_first_entry_or_null(&nubus_func_rsrcs, struct nubus_rsrc,
0310 list);
0311 }
0312 EXPORT_SYMBOL(nubus_first_rsrc_or_null);
0313
0314 struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)
0315 {
0316 if (list_is_last(&from->list, &nubus_func_rsrcs))
0317 return NULL;
0318 return list_next_entry(from, list);
0319 }
0320 EXPORT_SYMBOL(nubus_next_rsrc_or_null);
0321
0322 int
0323 nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type,
0324 struct nubus_dirent *ent)
0325 {
0326 while (nubus_readdir(dir, ent) != -1) {
0327 if (ent->type == rsrc_type)
0328 return 0;
0329 }
0330 return -1;
0331 }
0332 EXPORT_SYMBOL(nubus_find_rsrc);
0333
0334
0335
0336
0337
0338 static int __init nubus_get_block_rsrc_dir(struct nubus_board *board,
0339 struct proc_dir_entry *procdir,
0340 const struct nubus_dirent *parent)
0341 {
0342 struct nubus_dir dir;
0343 struct nubus_dirent ent;
0344
0345 nubus_get_subdir(parent, &dir);
0346 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
0347
0348 while (nubus_readdir(&dir, &ent) != -1) {
0349 u32 size;
0350
0351 nubus_get_rsrc_mem(&size, &ent, 4);
0352 pr_debug(" block (0x%x), size %d\n", ent.type, size);
0353 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
0354 }
0355 return 0;
0356 }
0357
0358 static int __init nubus_get_display_vidmode(struct nubus_board *board,
0359 struct proc_dir_entry *procdir,
0360 const struct nubus_dirent *parent)
0361 {
0362 struct nubus_dir dir;
0363 struct nubus_dirent ent;
0364
0365 nubus_get_subdir(parent, &dir);
0366 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
0367
0368 while (nubus_readdir(&dir, &ent) != -1) {
0369 switch (ent.type) {
0370 case 1:
0371 case 2:
0372 {
0373 u32 size;
0374
0375 nubus_get_rsrc_mem(&size, &ent, 4);
0376 pr_debug(" block (0x%x), size %d\n", ent.type,
0377 size);
0378 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
0379 break;
0380 }
0381 default:
0382 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
0383 ent.type, ent.data);
0384 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
0385 }
0386 }
0387 return 0;
0388 }
0389
0390 static int __init nubus_get_display_resource(struct nubus_rsrc *fres,
0391 struct proc_dir_entry *procdir,
0392 const struct nubus_dirent *ent)
0393 {
0394 switch (ent->type) {
0395 case NUBUS_RESID_GAMMADIR:
0396 pr_debug(" gamma directory offset: 0x%06x\n", ent->data);
0397 nubus_get_block_rsrc_dir(fres->board, procdir, ent);
0398 break;
0399 case 0x0080 ... 0x0085:
0400 pr_debug(" mode 0x%02x info offset: 0x%06x\n",
0401 ent->type, ent->data);
0402 nubus_get_display_vidmode(fres->board, procdir, ent);
0403 break;
0404 default:
0405 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
0406 ent->type, ent->data);
0407 nubus_proc_add_rsrc_mem(procdir, ent, 0);
0408 }
0409 return 0;
0410 }
0411
0412 static int __init nubus_get_network_resource(struct nubus_rsrc *fres,
0413 struct proc_dir_entry *procdir,
0414 const struct nubus_dirent *ent)
0415 {
0416 switch (ent->type) {
0417 case NUBUS_RESID_MAC_ADDRESS:
0418 {
0419 char addr[6];
0420
0421 nubus_get_rsrc_mem(addr, ent, 6);
0422 pr_debug(" MAC address: %pM\n", addr);
0423 nubus_proc_add_rsrc_mem(procdir, ent, 6);
0424 break;
0425 }
0426 default:
0427 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
0428 ent->type, ent->data);
0429 nubus_proc_add_rsrc_mem(procdir, ent, 0);
0430 }
0431 return 0;
0432 }
0433
0434 static int __init nubus_get_cpu_resource(struct nubus_rsrc *fres,
0435 struct proc_dir_entry *procdir,
0436 const struct nubus_dirent *ent)
0437 {
0438 switch (ent->type) {
0439 case NUBUS_RESID_MEMINFO:
0440 {
0441 unsigned long meminfo[2];
0442
0443 nubus_get_rsrc_mem(&meminfo, ent, 8);
0444 pr_debug(" memory: [ 0x%08lx 0x%08lx ]\n",
0445 meminfo[0], meminfo[1]);
0446 nubus_proc_add_rsrc_mem(procdir, ent, 8);
0447 break;
0448 }
0449 case NUBUS_RESID_ROMINFO:
0450 {
0451 unsigned long rominfo[2];
0452
0453 nubus_get_rsrc_mem(&rominfo, ent, 8);
0454 pr_debug(" ROM: [ 0x%08lx 0x%08lx ]\n",
0455 rominfo[0], rominfo[1]);
0456 nubus_proc_add_rsrc_mem(procdir, ent, 8);
0457 break;
0458 }
0459 default:
0460 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
0461 ent->type, ent->data);
0462 nubus_proc_add_rsrc_mem(procdir, ent, 0);
0463 }
0464 return 0;
0465 }
0466
0467 static int __init nubus_get_private_resource(struct nubus_rsrc *fres,
0468 struct proc_dir_entry *procdir,
0469 const struct nubus_dirent *ent)
0470 {
0471 switch (fres->category) {
0472 case NUBUS_CAT_DISPLAY:
0473 nubus_get_display_resource(fres, procdir, ent);
0474 break;
0475 case NUBUS_CAT_NETWORK:
0476 nubus_get_network_resource(fres, procdir, ent);
0477 break;
0478 case NUBUS_CAT_CPU:
0479 nubus_get_cpu_resource(fres, procdir, ent);
0480 break;
0481 default:
0482 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
0483 ent->type, ent->data);
0484 nubus_proc_add_rsrc_mem(procdir, ent, 0);
0485 }
0486 return 0;
0487 }
0488
0489 static struct nubus_rsrc * __init
0490 nubus_get_functional_resource(struct nubus_board *board, int slot,
0491 const struct nubus_dirent *parent)
0492 {
0493 struct nubus_dir dir;
0494 struct nubus_dirent ent;
0495 struct nubus_rsrc *fres;
0496
0497 pr_debug(" Functional resource 0x%02x:\n", parent->type);
0498 nubus_get_subdir(parent, &dir);
0499 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
0500
0501
0502 fres = kzalloc(sizeof(*fres), GFP_ATOMIC);
0503 if (!fres)
0504 return NULL;
0505 fres->resid = parent->type;
0506 fres->directory = dir.base;
0507 fres->board = board;
0508
0509 while (nubus_readdir(&dir, &ent) != -1) {
0510 switch (ent.type) {
0511 case NUBUS_RESID_TYPE:
0512 {
0513 unsigned short nbtdata[4];
0514
0515 nubus_get_rsrc_mem(nbtdata, &ent, 8);
0516 fres->category = nbtdata[0];
0517 fres->type = nbtdata[1];
0518 fres->dr_sw = nbtdata[2];
0519 fres->dr_hw = nbtdata[3];
0520 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
0521 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
0522 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
0523 break;
0524 }
0525 case NUBUS_RESID_NAME:
0526 {
0527 char name[64];
0528 unsigned int len;
0529
0530 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
0531 pr_debug(" name: %s\n", name);
0532 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
0533 break;
0534 }
0535 case NUBUS_RESID_DRVRDIR:
0536 {
0537
0538
0539 pr_debug(" driver directory offset: 0x%06x\n",
0540 ent.data);
0541 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
0542 break;
0543 }
0544 case NUBUS_RESID_MINOR_BASEOS:
0545 {
0546
0547
0548
0549 u32 base_offset;
0550
0551 nubus_get_rsrc_mem(&base_offset, &ent, 4);
0552 pr_debug(" memory offset: 0x%08x\n", base_offset);
0553 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
0554 break;
0555 }
0556 case NUBUS_RESID_MINOR_LENGTH:
0557 {
0558
0559 u32 length;
0560
0561 nubus_get_rsrc_mem(&length, &ent, 4);
0562 pr_debug(" memory length: 0x%08x\n", length);
0563 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
0564 break;
0565 }
0566 case NUBUS_RESID_FLAGS:
0567 pr_debug(" flags: 0x%06x\n", ent.data);
0568 nubus_proc_add_rsrc(dir.procdir, &ent);
0569 break;
0570 case NUBUS_RESID_HWDEVID:
0571 pr_debug(" hwdevid: 0x%06x\n", ent.data);
0572 nubus_proc_add_rsrc(dir.procdir, &ent);
0573 break;
0574 default:
0575
0576
0577 nubus_get_private_resource(fres, dir.procdir, &ent);
0578 }
0579 }
0580
0581 return fres;
0582 }
0583
0584
0585 static int __init nubus_get_icon(struct nubus_board *board,
0586 struct proc_dir_entry *procdir,
0587 const struct nubus_dirent *ent)
0588 {
0589
0590 u32 icon[32];
0591 int i;
0592
0593 nubus_get_rsrc_mem(&icon, ent, 128);
0594 pr_debug(" icon:\n");
0595 for (i = 0; i < 8; i++)
0596 pr_debug(" %08x %08x %08x %08x\n",
0597 icon[i * 4 + 0], icon[i * 4 + 1],
0598 icon[i * 4 + 2], icon[i * 4 + 3]);
0599 nubus_proc_add_rsrc_mem(procdir, ent, 128);
0600
0601 return 0;
0602 }
0603
0604 static int __init nubus_get_vendorinfo(struct nubus_board *board,
0605 struct proc_dir_entry *procdir,
0606 const struct nubus_dirent *parent)
0607 {
0608 struct nubus_dir dir;
0609 struct nubus_dirent ent;
0610 static char *vendor_fields[6] = { "ID", "serial", "revision",
0611 "part", "date", "unknown field" };
0612
0613 pr_debug(" vendor info:\n");
0614 nubus_get_subdir(parent, &dir);
0615 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
0616
0617 while (nubus_readdir(&dir, &ent) != -1) {
0618 char name[64];
0619 unsigned int len;
0620
0621
0622 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
0623 if (ent.type < 1 || ent.type > 5)
0624 ent.type = 5;
0625 pr_debug(" %s: %s\n", vendor_fields[ent.type - 1], name);
0626 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
0627 }
0628 return 0;
0629 }
0630
0631 static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
0632 const struct nubus_dirent *parent)
0633 {
0634 struct nubus_dir dir;
0635 struct nubus_dirent ent;
0636
0637 pr_debug(" Board resource 0x%02x:\n", parent->type);
0638 nubus_get_subdir(parent, &dir);
0639 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
0640
0641 while (nubus_readdir(&dir, &ent) != -1) {
0642 switch (ent.type) {
0643 case NUBUS_RESID_TYPE:
0644 {
0645 unsigned short nbtdata[4];
0646
0647
0648
0649 nubus_get_rsrc_mem(nbtdata, &ent, 8);
0650 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
0651 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
0652 if (nbtdata[0] != 1 || nbtdata[1] != 0 ||
0653 nbtdata[2] != 0 || nbtdata[3] != 0)
0654 pr_err("Slot %X: sResource is not a board resource!\n",
0655 slot);
0656 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
0657 break;
0658 }
0659 case NUBUS_RESID_NAME:
0660 {
0661 unsigned int len;
0662
0663 len = nubus_get_rsrc_str(board->name, &ent,
0664 sizeof(board->name));
0665 pr_debug(" name: %s\n", board->name);
0666 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
0667 break;
0668 }
0669 case NUBUS_RESID_ICON:
0670 nubus_get_icon(board, dir.procdir, &ent);
0671 break;
0672 case NUBUS_RESID_BOARDID:
0673 pr_debug(" board id: 0x%x\n", ent.data);
0674 nubus_proc_add_rsrc(dir.procdir, &ent);
0675 break;
0676 case NUBUS_RESID_PRIMARYINIT:
0677 pr_debug(" primary init offset: 0x%06x\n", ent.data);
0678 nubus_proc_add_rsrc(dir.procdir, &ent);
0679 break;
0680 case NUBUS_RESID_VENDORINFO:
0681 nubus_get_vendorinfo(board, dir.procdir, &ent);
0682 break;
0683 case NUBUS_RESID_FLAGS:
0684 pr_debug(" flags: 0x%06x\n", ent.data);
0685 nubus_proc_add_rsrc(dir.procdir, &ent);
0686 break;
0687 case NUBUS_RESID_HWDEVID:
0688 pr_debug(" hwdevid: 0x%06x\n", ent.data);
0689 nubus_proc_add_rsrc(dir.procdir, &ent);
0690 break;
0691 case NUBUS_RESID_SECONDINIT:
0692 pr_debug(" secondary init offset: 0x%06x\n",
0693 ent.data);
0694 nubus_proc_add_rsrc(dir.procdir, &ent);
0695 break;
0696
0697 case NUBUS_RESID_VIDNAMES:
0698 pr_debug(" vidnames directory offset: 0x%06x\n",
0699 ent.data);
0700 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
0701 break;
0702
0703 case NUBUS_RESID_VIDMODES:
0704 pr_debug(" video mode parameter directory offset: 0x%06x\n",
0705 ent.data);
0706 nubus_proc_add_rsrc(dir.procdir, &ent);
0707 break;
0708 default:
0709 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
0710 ent.type, ent.data);
0711 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
0712 }
0713 }
0714 return 0;
0715 }
0716
0717 static void __init nubus_add_board(int slot, int bytelanes)
0718 {
0719 struct nubus_board *board;
0720 unsigned char *rp;
0721 unsigned long dpat;
0722 struct nubus_dir dir;
0723 struct nubus_dirent ent;
0724 int prev_resid = -1;
0725
0726
0727 rp = nubus_rom_addr(slot);
0728 nubus_rewind(&rp, FORMAT_BLOCK_SIZE, bytelanes);
0729
0730
0731 if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL)
0732 return;
0733 board->fblock = rp;
0734
0735
0736 pr_debug("Slot %X, format block at 0x%p:\n", slot, rp);
0737 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0738 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0739 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0740 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0741 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0742 pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes));
0743 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0744 pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes));
0745 rp = board->fblock;
0746
0747 board->slot = slot;
0748 board->slot_addr = (unsigned long)nubus_slot_addr(slot);
0749 board->doffset = nubus_get_rom(&rp, 4, bytelanes);
0750
0751
0752
0753
0754
0755
0756 board->rom_length = nubus_get_rom(&rp, 4, bytelanes);
0757 board->crc = nubus_get_rom(&rp, 4, bytelanes);
0758 board->rev = nubus_get_rom(&rp, 1, bytelanes);
0759 board->format = nubus_get_rom(&rp, 1, bytelanes);
0760 board->lanes = bytelanes;
0761
0762
0763 if (!(board->doffset & 0x00FF0000))
0764 pr_warn("Slot %X: Dodgy doffset!\n", slot);
0765 dpat = nubus_get_rom(&rp, 4, bytelanes);
0766 if (dpat != NUBUS_TEST_PATTERN)
0767 pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat);
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777 board->directory = board->fblock;
0778 nubus_move(&board->directory, nubus_expand32(board->doffset),
0779 board->lanes);
0780
0781 nubus_get_root_dir(board, &dir);
0782
0783
0784 pr_debug("Slot %X resources:\n", slot);
0785
0786
0787
0788
0789
0790
0791
0792 if (nubus_readdir(&dir, &ent) == -1) {
0793
0794 pr_err("Slot %X: Board resource not found!\n", slot);
0795 kfree(board);
0796 return;
0797 }
0798
0799 if (ent.type < 1 || ent.type > 127)
0800 pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
0801
0802 board->procdir = nubus_proc_add_board(board);
0803
0804 nubus_get_board_resource(board, slot, &ent);
0805
0806 while (nubus_readdir(&dir, &ent) != -1) {
0807 struct nubus_rsrc *fres;
0808
0809 fres = nubus_get_functional_resource(board, slot, &ent);
0810 if (fres == NULL)
0811 continue;
0812
0813
0814
0815
0816 if (fres->resid <= prev_resid) {
0817 kfree(fres);
0818 continue;
0819 }
0820 prev_resid = fres->resid;
0821
0822 list_add_tail(&fres->list, &nubus_func_rsrcs);
0823 }
0824
0825 if (nubus_device_register(board))
0826 put_device(&board->dev);
0827 }
0828
0829 static void __init nubus_probe_slot(int slot)
0830 {
0831 unsigned char dp;
0832 unsigned char *rp;
0833 int i;
0834
0835 rp = nubus_rom_addr(slot);
0836 for (i = 4; i; i--) {
0837 rp--;
0838 if (!hwreg_present(rp))
0839 continue;
0840
0841 dp = *rp;
0842
0843
0844
0845
0846 if ((((dp >> 4) ^ dp) & 0x0F) != 0x0F)
0847 continue;
0848
0849
0850 if (not_useful(rp, dp))
0851 continue;
0852
0853
0854 nubus_add_board(slot, dp);
0855
0856 return;
0857 }
0858 }
0859
0860 static void __init nubus_scan_bus(void)
0861 {
0862 int slot;
0863
0864 pr_info("NuBus: Scanning NuBus slots.\n");
0865 for (slot = 9; slot < 15; slot++) {
0866 nubus_probe_slot(slot);
0867 }
0868 }
0869
0870 static int __init nubus_init(void)
0871 {
0872 int err;
0873
0874 if (!MACH_IS_MAC)
0875 return 0;
0876
0877 nubus_proc_init();
0878 err = nubus_parent_device_register();
0879 if (err)
0880 return err;
0881 nubus_scan_bus();
0882 return 0;
0883 }
0884
0885 subsys_initcall(nubus_init);