summaryrefslogtreecommitdiffstats
path: root/drivers/nubus
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2018-01-13 17:37:13 -0500
committerGeert Uytterhoeven <geert@linux-m68k.org>2018-01-16 10:47:29 -0500
commit2f7dd07ecadac6bdc3d55c217d65efa2834ba1cb (patch)
treebd55d141cdf80fc39cb3aedb87f0621c9c1a51a1 /drivers/nubus
parent883b8cb31a8546b9921c98b255d5f7779d1bc9f6 (diff)
nubus: Rework /proc/bus/nubus/s/ implementation
The /proc/bus/nubus/s/ directory tree for any slot s is missing a lot of information. The struct file_operations methods have long been left unimplemented (hence the familiar compile-time warning, "Need to set some I/O handlers here"). Slot resources have a complex structure which varies depending on board function. The logic for interpreting these ROM data structures is found in nubus.c. Let's not duplicate that logic in proc.c. Create the /proc/bus/nubus/s/ inodes while scanning slot s. During descent through slot resource subdirectories, call the new nubus_proc_add_foo() functions to create the procfs inodes. Also add a new function, nubus_seq_write_rsrc_mem(), to write the contents of a particular slot resource to a given seq_file. This is used by the procfs file_operations methods, to finally give userspace access to slot ROM information, such as the available video modes. Tested-by: Stan Johnson <userm57@yahoo.com> Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'drivers/nubus')
-rw-r--r--drivers/nubus/nubus.c114
-rw-r--r--drivers/nubus/proc.c222
2 files changed, 223 insertions, 113 deletions
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index c56ac36d91f2..f05541914c21 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -15,6 +15,7 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/seq_file.h>
18#include <linux/slab.h> 19#include <linux/slab.h>
19#include <asm/setup.h> 20#include <asm/setup.h>
20#include <asm/page.h> 21#include <asm/page.h>
@@ -146,7 +147,7 @@ static inline void *nubus_rom_addr(int slot)
146 return (void *)(0xF1000000 + (slot << 24)); 147 return (void *)(0xF1000000 + (slot << 24));
147} 148}
148 149
149static unsigned char *nubus_dirptr(const struct nubus_dirent *nd) 150unsigned char *nubus_dirptr(const struct nubus_dirent *nd)
150{ 151{
151 unsigned char *p = nd->base; 152 unsigned char *p = nd->base;
152 153
@@ -173,8 +174,8 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent,
173} 174}
174EXPORT_SYMBOL(nubus_get_rsrc_mem); 175EXPORT_SYMBOL(nubus_get_rsrc_mem);
175 176
176void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, 177unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
177 unsigned int len) 178 unsigned int len)
178{ 179{
179 char *t = dest; 180 char *t = dest;
180 unsigned char *p = nubus_dirptr(dirent); 181 unsigned char *p = nubus_dirptr(dirent);
@@ -189,9 +190,33 @@ void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent,
189 } 190 }
190 if (len > 0) 191 if (len > 0)
191 *t = '\0'; 192 *t = '\0';
193 return t - dest;
192} 194}
193EXPORT_SYMBOL(nubus_get_rsrc_str); 195EXPORT_SYMBOL(nubus_get_rsrc_str);
194 196
197void nubus_seq_write_rsrc_mem(struct seq_file *m,
198 const struct nubus_dirent *dirent,
199 unsigned int len)
200{
201 unsigned long buf[32];
202 unsigned int buf_size = sizeof(buf);
203 unsigned char *p = nubus_dirptr(dirent);
204
205 /* If possible, write out full buffers */
206 while (len >= buf_size) {
207 unsigned int i;
208
209 for (i = 0; i < ARRAY_SIZE(buf); i++)
210 buf[i] = nubus_get_rom(&p, sizeof(buf[0]),
211 dirent->mask);
212 seq_write(m, buf, buf_size);
213 len -= buf_size;
214 }
215 /* If not, write out individual bytes */
216 while (len--)
217 seq_putc(m, nubus_get_rom(&p, 1, dirent->mask));
218}
219
195int nubus_get_root_dir(const struct nubus_board *board, 220int nubus_get_root_dir(const struct nubus_board *board,
196 struct nubus_dir *dir) 221 struct nubus_dir *dir)
197{ 222{
@@ -326,35 +351,35 @@ EXPORT_SYMBOL(nubus_find_rsrc);
326 looking at, and print out lots and lots of information from the 351 looking at, and print out lots and lots of information from the
327 resource blocks. */ 352 resource blocks. */
328 353
329/* FIXME: A lot of this stuff will eventually be useful after
330 initialization, for intelligently probing Ethernet and video chips,
331 among other things. The rest of it should go in the /proc code.
332 For now, we just use it to give verbose boot logs. */
333
334static int __init nubus_get_block_rsrc_dir(struct nubus_board *board, 354static int __init nubus_get_block_rsrc_dir(struct nubus_board *board,
355 struct proc_dir_entry *procdir,
335 const struct nubus_dirent *parent) 356 const struct nubus_dirent *parent)
336{ 357{
337 struct nubus_dir dir; 358 struct nubus_dir dir;
338 struct nubus_dirent ent; 359 struct nubus_dirent ent;
339 360
340 nubus_get_subdir(parent, &dir); 361 nubus_get_subdir(parent, &dir);
362 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
341 363
342 while (nubus_readdir(&dir, &ent) != -1) { 364 while (nubus_readdir(&dir, &ent) != -1) {
343 u32 size; 365 u32 size;
344 366
345 nubus_get_rsrc_mem(&size, &ent, 4); 367 nubus_get_rsrc_mem(&size, &ent, 4);
346 pr_debug(" block (0x%x), size %d\n", ent.type, size); 368 pr_debug(" block (0x%x), size %d\n", ent.type, size);
369 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
347 } 370 }
348 return 0; 371 return 0;
349} 372}
350 373
351static int __init nubus_get_display_vidmode(struct nubus_board *board, 374static int __init nubus_get_display_vidmode(struct nubus_board *board,
375 struct proc_dir_entry *procdir,
352 const struct nubus_dirent *parent) 376 const struct nubus_dirent *parent)
353{ 377{
354 struct nubus_dir dir; 378 struct nubus_dir dir;
355 struct nubus_dirent ent; 379 struct nubus_dirent ent;
356 380
357 nubus_get_subdir(parent, &dir); 381 nubus_get_subdir(parent, &dir);
382 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
358 383
359 while (nubus_readdir(&dir, &ent) != -1) { 384 while (nubus_readdir(&dir, &ent) != -1) {
360 switch (ent.type) { 385 switch (ent.type) {
@@ -366,37 +391,42 @@ static int __init nubus_get_display_vidmode(struct nubus_board *board,
366 nubus_get_rsrc_mem(&size, &ent, 4); 391 nubus_get_rsrc_mem(&size, &ent, 4);
367 pr_debug(" block (0x%x), size %d\n", ent.type, 392 pr_debug(" block (0x%x), size %d\n", ent.type,
368 size); 393 size);
394 nubus_proc_add_rsrc_mem(dir.procdir, &ent, size);
369 break; 395 break;
370 } 396 }
371 default: 397 default:
372 pr_debug(" unknown resource 0x%02x, data 0x%06x\n", 398 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
373 ent.type, ent.data); 399 ent.type, ent.data);
400 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
374 } 401 }
375 } 402 }
376 return 0; 403 return 0;
377} 404}
378 405
379static int __init nubus_get_display_resource(struct nubus_dev *dev, 406static int __init nubus_get_display_resource(struct nubus_dev *dev,
407 struct proc_dir_entry *procdir,
380 const struct nubus_dirent *ent) 408 const struct nubus_dirent *ent)
381{ 409{
382 switch (ent->type) { 410 switch (ent->type) {
383 case NUBUS_RESID_GAMMADIR: 411 case NUBUS_RESID_GAMMADIR:
384 pr_debug(" gamma directory offset: 0x%06x\n", ent->data); 412 pr_debug(" gamma directory offset: 0x%06x\n", ent->data);
385 nubus_get_block_rsrc_dir(dev->board, ent); 413 nubus_get_block_rsrc_dir(dev->board, procdir, ent);
386 break; 414 break;
387 case 0x0080 ... 0x0085: 415 case 0x0080 ... 0x0085:
388 pr_debug(" mode 0x%02x info offset: 0x%06x\n", 416 pr_debug(" mode 0x%02x info offset: 0x%06x\n",
389 ent->type, ent->data); 417 ent->type, ent->data);
390 nubus_get_display_vidmode(dev->board, ent); 418 nubus_get_display_vidmode(dev->board, procdir, ent);
391 break; 419 break;
392 default: 420 default:
393 pr_debug(" unknown resource 0x%02x, data 0x%06x\n", 421 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
394 ent->type, ent->data); 422 ent->type, ent->data);
423 nubus_proc_add_rsrc_mem(procdir, ent, 0);
395 } 424 }
396 return 0; 425 return 0;
397} 426}
398 427
399static int __init nubus_get_network_resource(struct nubus_dev *dev, 428static int __init nubus_get_network_resource(struct nubus_dev *dev,
429 struct proc_dir_entry *procdir,
400 const struct nubus_dirent *ent) 430 const struct nubus_dirent *ent)
401{ 431{
402 switch (ent->type) { 432 switch (ent->type) {
@@ -406,16 +436,19 @@ static int __init nubus_get_network_resource(struct nubus_dev *dev,
406 436
407 nubus_get_rsrc_mem(addr, ent, 6); 437 nubus_get_rsrc_mem(addr, ent, 6);
408 pr_debug(" MAC address: %pM\n", addr); 438 pr_debug(" MAC address: %pM\n", addr);
439 nubus_proc_add_rsrc_mem(procdir, ent, 6);
409 break; 440 break;
410 } 441 }
411 default: 442 default:
412 pr_debug(" unknown resource 0x%02x, data 0x%06x\n", 443 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
413 ent->type, ent->data); 444 ent->type, ent->data);
445 nubus_proc_add_rsrc_mem(procdir, ent, 0);
414 } 446 }
415 return 0; 447 return 0;
416} 448}
417 449
418static int __init nubus_get_cpu_resource(struct nubus_dev *dev, 450static int __init nubus_get_cpu_resource(struct nubus_dev *dev,
451 struct proc_dir_entry *procdir,
419 const struct nubus_dirent *ent) 452 const struct nubus_dirent *ent)
420{ 453{
421 switch (ent->type) { 454 switch (ent->type) {
@@ -426,6 +459,7 @@ static int __init nubus_get_cpu_resource(struct nubus_dev *dev,
426 nubus_get_rsrc_mem(&meminfo, ent, 8); 459 nubus_get_rsrc_mem(&meminfo, ent, 8);
427 pr_debug(" memory: [ 0x%08lx 0x%08lx ]\n", 460 pr_debug(" memory: [ 0x%08lx 0x%08lx ]\n",
428 meminfo[0], meminfo[1]); 461 meminfo[0], meminfo[1]);
462 nubus_proc_add_rsrc_mem(procdir, ent, 8);
429 break; 463 break;
430 } 464 }
431 case NUBUS_RESID_ROMINFO: 465 case NUBUS_RESID_ROMINFO:
@@ -435,31 +469,35 @@ static int __init nubus_get_cpu_resource(struct nubus_dev *dev,
435 nubus_get_rsrc_mem(&rominfo, ent, 8); 469 nubus_get_rsrc_mem(&rominfo, ent, 8);
436 pr_debug(" ROM: [ 0x%08lx 0x%08lx ]\n", 470 pr_debug(" ROM: [ 0x%08lx 0x%08lx ]\n",
437 rominfo[0], rominfo[1]); 471 rominfo[0], rominfo[1]);
472 nubus_proc_add_rsrc_mem(procdir, ent, 8);
438 break; 473 break;
439 } 474 }
440 default: 475 default:
441 pr_debug(" unknown resource 0x%02x, data 0x%06x\n", 476 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
442 ent->type, ent->data); 477 ent->type, ent->data);
478 nubus_proc_add_rsrc_mem(procdir, ent, 0);
443 } 479 }
444 return 0; 480 return 0;
445} 481}
446 482
447static int __init nubus_get_private_resource(struct nubus_dev *dev, 483static int __init nubus_get_private_resource(struct nubus_dev *dev,
484 struct proc_dir_entry *procdir,
448 const struct nubus_dirent *ent) 485 const struct nubus_dirent *ent)
449{ 486{
450 switch (dev->category) { 487 switch (dev->category) {
451 case NUBUS_CAT_DISPLAY: 488 case NUBUS_CAT_DISPLAY:
452 nubus_get_display_resource(dev, ent); 489 nubus_get_display_resource(dev, procdir, ent);
453 break; 490 break;
454 case NUBUS_CAT_NETWORK: 491 case NUBUS_CAT_NETWORK:
455 nubus_get_network_resource(dev, ent); 492 nubus_get_network_resource(dev, procdir, ent);
456 break; 493 break;
457 case NUBUS_CAT_CPU: 494 case NUBUS_CAT_CPU:
458 nubus_get_cpu_resource(dev, ent); 495 nubus_get_cpu_resource(dev, procdir, ent);
459 break; 496 break;
460 default: 497 default:
461 pr_debug(" unknown resource 0x%02x, data 0x%06x\n", 498 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
462 ent->type, ent->data); 499 ent->type, ent->data);
500 nubus_proc_add_rsrc_mem(procdir, ent, 0);
463 } 501 }
464 return 0; 502 return 0;
465} 503}
@@ -474,6 +512,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
474 512
475 pr_debug(" Functional resource 0x%02x:\n", parent->type); 513 pr_debug(" Functional resource 0x%02x:\n", parent->type);
476 nubus_get_subdir(parent, &dir); 514 nubus_get_subdir(parent, &dir);
515 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
477 516
478 /* Actually we should probably panic if this fails */ 517 /* Actually we should probably panic if this fails */
479 if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL) 518 if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
@@ -495,14 +534,17 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
495 dev->dr_hw = nbtdata[3]; 534 dev->dr_hw = nbtdata[3];
496 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", 535 pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
497 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); 536 nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
537 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
498 break; 538 break;
499 } 539 }
500 case NUBUS_RESID_NAME: 540 case NUBUS_RESID_NAME:
501 { 541 {
502 char name[64]; 542 char name[64];
543 unsigned int len;
503 544
504 nubus_get_rsrc_str(name, &ent, sizeof(name)); 545 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
505 pr_debug(" name: %s\n", name); 546 pr_debug(" name: %s\n", name);
547 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
506 break; 548 break;
507 } 549 }
508 case NUBUS_RESID_DRVRDIR: 550 case NUBUS_RESID_DRVRDIR:
@@ -511,7 +553,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
511 use this :-) */ 553 use this :-) */
512 pr_debug(" driver directory offset: 0x%06x\n", 554 pr_debug(" driver directory offset: 0x%06x\n",
513 ent.data); 555 ent.data);
514 nubus_get_block_rsrc_dir(board, &ent); 556 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
515 break; 557 break;
516 } 558 }
517 case NUBUS_RESID_MINOR_BASEOS: 559 case NUBUS_RESID_MINOR_BASEOS:
@@ -523,6 +565,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
523 565
524 nubus_get_rsrc_mem(&base_offset, &ent, 4); 566 nubus_get_rsrc_mem(&base_offset, &ent, 4);
525 pr_debug(" memory offset: 0x%08x\n", base_offset); 567 pr_debug(" memory offset: 0x%08x\n", base_offset);
568 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
526 break; 569 break;
527 } 570 }
528 case NUBUS_RESID_MINOR_LENGTH: 571 case NUBUS_RESID_MINOR_LENGTH:
@@ -532,18 +575,21 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
532 575
533 nubus_get_rsrc_mem(&length, &ent, 4); 576 nubus_get_rsrc_mem(&length, &ent, 4);
534 pr_debug(" memory length: 0x%08x\n", length); 577 pr_debug(" memory length: 0x%08x\n", length);
578 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4);
535 break; 579 break;
536 } 580 }
537 case NUBUS_RESID_FLAGS: 581 case NUBUS_RESID_FLAGS:
538 pr_debug(" flags: 0x%06x\n", ent.data); 582 pr_debug(" flags: 0x%06x\n", ent.data);
583 nubus_proc_add_rsrc(dir.procdir, &ent);
539 break; 584 break;
540 case NUBUS_RESID_HWDEVID: 585 case NUBUS_RESID_HWDEVID:
541 pr_debug(" hwdevid: 0x%06x\n", ent.data); 586 pr_debug(" hwdevid: 0x%06x\n", ent.data);
587 nubus_proc_add_rsrc(dir.procdir, &ent);
542 break; 588 break;
543 default: 589 default:
544 /* Local/Private resources have their own 590 /* Local/Private resources have their own
545 function */ 591 function */
546 nubus_get_private_resource(dev, &ent); 592 nubus_get_private_resource(dev, dir.procdir, &ent);
547 } 593 }
548 } 594 }
549 595
@@ -552,6 +598,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
552 598
553/* This is *really* cool. */ 599/* This is *really* cool. */
554static int __init nubus_get_icon(struct nubus_board *board, 600static int __init nubus_get_icon(struct nubus_board *board,
601 struct proc_dir_entry *procdir,
555 const struct nubus_dirent *ent) 602 const struct nubus_dirent *ent)
556{ 603{
557 /* Should be 32x32 if my memory serves me correctly */ 604 /* Should be 32x32 if my memory serves me correctly */
@@ -564,11 +611,13 @@ static int __init nubus_get_icon(struct nubus_board *board,
564 pr_debug(" %08x %08x %08x %08x\n", 611 pr_debug(" %08x %08x %08x %08x\n",
565 icon[i * 4 + 0], icon[i * 4 + 1], 612 icon[i * 4 + 0], icon[i * 4 + 1],
566 icon[i * 4 + 2], icon[i * 4 + 3]); 613 icon[i * 4 + 2], icon[i * 4 + 3]);
614 nubus_proc_add_rsrc_mem(procdir, ent, 128);
567 615
568 return 0; 616 return 0;
569} 617}
570 618
571static int __init nubus_get_vendorinfo(struct nubus_board *board, 619static int __init nubus_get_vendorinfo(struct nubus_board *board,
620 struct proc_dir_entry *procdir,
572 const struct nubus_dirent *parent) 621 const struct nubus_dirent *parent)
573{ 622{
574 struct nubus_dir dir; 623 struct nubus_dir dir;
@@ -578,15 +627,18 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board,
578 627
579 pr_debug(" vendor info:\n"); 628 pr_debug(" vendor info:\n");
580 nubus_get_subdir(parent, &dir); 629 nubus_get_subdir(parent, &dir);
630 dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board);
581 631
582 while (nubus_readdir(&dir, &ent) != -1) { 632 while (nubus_readdir(&dir, &ent) != -1) {
583 char name[64]; 633 char name[64];
634 unsigned int len;
584 635
585 /* These are all strings, we think */ 636 /* These are all strings, we think */
586 nubus_get_rsrc_str(name, &ent, sizeof(name)); 637 len = nubus_get_rsrc_str(name, &ent, sizeof(name));
587 if (ent.type < 1 || ent.type > 5) 638 if (ent.type < 1 || ent.type > 5)
588 ent.type = 5; 639 ent.type = 5;
589 pr_debug(" %s: %s\n", vendor_fields[ent.type - 1], name); 640 pr_debug(" %s: %s\n", vendor_fields[ent.type - 1], name);
641 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
590 } 642 }
591 return 0; 643 return 0;
592} 644}
@@ -599,6 +651,7 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
599 651
600 pr_debug(" Board resource 0x%02x:\n", parent->type); 652 pr_debug(" Board resource 0x%02x:\n", parent->type);
601 nubus_get_subdir(parent, &dir); 653 nubus_get_subdir(parent, &dir);
654 dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
602 655
603 while (nubus_readdir(&dir, &ent) != -1) { 656 while (nubus_readdir(&dir, &ent) != -1) {
604 switch (ent.type) { 657 switch (ent.type) {
@@ -615,49 +668,62 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
615 nbtdata[2] != 0 || nbtdata[3] != 0) 668 nbtdata[2] != 0 || nbtdata[3] != 0)
616 pr_err("Slot %X: sResource is not a board resource!\n", 669 pr_err("Slot %X: sResource is not a board resource!\n",
617 slot); 670 slot);
671 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
618 break; 672 break;
619 } 673 }
620 case NUBUS_RESID_NAME: 674 case NUBUS_RESID_NAME:
621 nubus_get_rsrc_str(board->name, &ent, 675 {
622 sizeof(board->name)); 676 unsigned int len;
677
678 len = nubus_get_rsrc_str(board->name, &ent,
679 sizeof(board->name));
623 pr_debug(" name: %s\n", board->name); 680 pr_debug(" name: %s\n", board->name);
681 nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1);
624 break; 682 break;
683 }
625 case NUBUS_RESID_ICON: 684 case NUBUS_RESID_ICON:
626 nubus_get_icon(board, &ent); 685 nubus_get_icon(board, dir.procdir, &ent);
627 break; 686 break;
628 case NUBUS_RESID_BOARDID: 687 case NUBUS_RESID_BOARDID:
629 pr_debug(" board id: 0x%x\n", ent.data); 688 pr_debug(" board id: 0x%x\n", ent.data);
689 nubus_proc_add_rsrc(dir.procdir, &ent);
630 break; 690 break;
631 case NUBUS_RESID_PRIMARYINIT: 691 case NUBUS_RESID_PRIMARYINIT:
632 pr_debug(" primary init offset: 0x%06x\n", ent.data); 692 pr_debug(" primary init offset: 0x%06x\n", ent.data);
693 nubus_proc_add_rsrc(dir.procdir, &ent);
633 break; 694 break;
634 case NUBUS_RESID_VENDORINFO: 695 case NUBUS_RESID_VENDORINFO:
635 nubus_get_vendorinfo(board, &ent); 696 nubus_get_vendorinfo(board, dir.procdir, &ent);
636 break; 697 break;
637 case NUBUS_RESID_FLAGS: 698 case NUBUS_RESID_FLAGS:
638 pr_debug(" flags: 0x%06x\n", ent.data); 699 pr_debug(" flags: 0x%06x\n", ent.data);
700 nubus_proc_add_rsrc(dir.procdir, &ent);
639 break; 701 break;
640 case NUBUS_RESID_HWDEVID: 702 case NUBUS_RESID_HWDEVID:
641 pr_debug(" hwdevid: 0x%06x\n", ent.data); 703 pr_debug(" hwdevid: 0x%06x\n", ent.data);
704 nubus_proc_add_rsrc(dir.procdir, &ent);
642 break; 705 break;
643 case NUBUS_RESID_SECONDINIT: 706 case NUBUS_RESID_SECONDINIT:
644 pr_debug(" secondary init offset: 0x%06x\n", 707 pr_debug(" secondary init offset: 0x%06x\n",
645 ent.data); 708 ent.data);
709 nubus_proc_add_rsrc(dir.procdir, &ent);
646 break; 710 break;
647 /* WTF isn't this in the functional resources? */ 711 /* WTF isn't this in the functional resources? */
648 case NUBUS_RESID_VIDNAMES: 712 case NUBUS_RESID_VIDNAMES:
649 pr_debug(" vidnames directory offset: 0x%06x\n", 713 pr_debug(" vidnames directory offset: 0x%06x\n",
650 ent.data); 714 ent.data);
651 nubus_get_block_rsrc_dir(board, &ent); 715 nubus_get_block_rsrc_dir(board, dir.procdir, &ent);
652 break; 716 break;
653 /* Same goes for this */ 717 /* Same goes for this */
654 case NUBUS_RESID_VIDMODES: 718 case NUBUS_RESID_VIDMODES:
655 pr_debug(" video mode parameter directory offset: 0x%06x\n", 719 pr_debug(" video mode parameter directory offset: 0x%06x\n",
656 ent.data); 720 ent.data);
721 nubus_proc_add_rsrc(dir.procdir, &ent);
657 break; 722 break;
658 default: 723 default:
659 pr_debug(" unknown resource 0x%02x, data 0x%06x\n", 724 pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
660 ent.type, ent.data); 725 ent.type, ent.data);
726 nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0);
661 } 727 }
662 } 728 }
663 return 0; 729 return 0;
@@ -748,6 +814,8 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
748 if (ent.type < 1 || ent.type > 127) 814 if (ent.type < 1 || ent.type > 127)
749 pr_warn("Slot %X: Board resource ID is invalid!\n", slot); 815 pr_warn("Slot %X: Board resource ID is invalid!\n", slot);
750 816
817 board->procdir = nubus_proc_add_board(board);
818
751 nubus_get_board_resource(board, slot, &ent); 819 nubus_get_board_resource(board, slot, &ent);
752 820
753 while (nubus_readdir(&dir, &ent) != -1) { 821 while (nubus_readdir(&dir, &ent) != -1) {
@@ -835,8 +903,8 @@ static int __init nubus_init(void)
835 if (!MACH_IS_MAC) 903 if (!MACH_IS_MAC)
836 return 0; 904 return 0;
837 905
838 nubus_scan_bus();
839 nubus_proc_init(); 906 nubus_proc_init();
907 nubus_scan_bus();
840 return 0; 908 return 0;
841} 909}
842 910
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index 41ec859bdd8b..f47d90924ab4 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -11,24 +11,28 @@
11 structure in /proc analogous to the structure of the NuBus ROM 11 structure in /proc analogous to the structure of the NuBus ROM
12 resources. 12 resources.
13 13
14 Therefore each NuBus device is in fact a directory, which may in 14 Therefore each board function gets a directory, which may in turn
15 turn contain subdirectories. The "files" correspond to NuBus 15 contain subdirectories. Each slot resource is a file. Unrecognized
16 resource records. For those types of records which we know how to 16 resources are empty files, since every resource ID requires a special
17 convert to formats that are meaningful to userspace (mostly just 17 case (e.g. if the resource ID implies a directory or block, then its
18 icons) these files will provide "cooked" data. Otherwise they will 18 value has to be interpreted as a slot ROM pointer etc.).
19 simply provide raw access (read-only of course) to the ROM. */ 19 */
20 20
21#include <linux/types.h> 21#include <linux/types.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/nubus.h> 23#include <linux/nubus.h>
24#include <linux/proc_fs.h> 24#include <linux/proc_fs.h>
25#include <linux/seq_file.h> 25#include <linux/seq_file.h>
26#include <linux/slab.h>
26#include <linux/init.h> 27#include <linux/init.h>
27#include <linux/module.h> 28#include <linux/module.h>
28
29#include <linux/uaccess.h> 29#include <linux/uaccess.h>
30#include <asm/byteorder.h> 30#include <asm/byteorder.h>
31 31
32/*
33 * /proc/bus/nubus/devices stuff
34 */
35
32static int 36static int
33nubus_devices_proc_show(struct seq_file *m, void *v) 37nubus_devices_proc_show(struct seq_file *m, void *v)
34{ 38{
@@ -61,96 +65,141 @@ static const struct file_operations nubus_devices_proc_fops = {
61 65
62static struct proc_dir_entry *proc_bus_nubus_dir; 66static struct proc_dir_entry *proc_bus_nubus_dir;
63 67
64static const struct file_operations nubus_proc_subdir_fops = { 68/*
65#warning Need to set some I/O handlers here 69 * /proc/bus/nubus/x/ stuff
70 */
71
72struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board)
73{
74 char name[2];
75
76 if (!proc_bus_nubus_dir)
77 return NULL;
78 snprintf(name, sizeof(name), "%x", board->slot);
79 return proc_mkdir(name, proc_bus_nubus_dir);
80}
81
82/* The PDE private data for any directory under /proc/bus/nubus/x/
83 * is the bytelanes value for the board in slot x.
84 */
85
86struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir,
87 const struct nubus_dirent *ent,
88 struct nubus_board *board)
89{
90 char name[9];
91 int lanes = board->lanes;
92
93 if (!procdir)
94 return NULL;
95 snprintf(name, sizeof(name), "%x", ent->type);
96 return proc_mkdir_data(name, 0555, procdir, (void *)lanes);
97}
98
99/* The PDE private data for a file under /proc/bus/nubus/x/ is a pointer to
100 * an instance of the following structure, which gives the location and size
101 * of the resource data in the slot ROM. For slot resources which hold only a
102 * small integer, this integer value is stored directly and size is set to 0.
103 * A NULL private data pointer indicates an unrecognized resource.
104 */
105
106struct nubus_proc_pde_data {
107 unsigned char *res_ptr;
108 unsigned int res_size;
66}; 109};
67 110
68static void nubus_proc_subdir(struct nubus_dev* dev, 111static struct nubus_proc_pde_data *
69 struct proc_dir_entry* parent, 112nubus_proc_alloc_pde_data(unsigned char *ptr, unsigned int size)
70 struct nubus_dir* dir)
71{ 113{
72 struct nubus_dirent ent; 114 struct nubus_proc_pde_data *pde_data;
73 115
74 /* Some of these are directories, others aren't */ 116 pde_data = kmalloc(sizeof(*pde_data), GFP_KERNEL);
75 while (nubus_readdir(dir, &ent) != -1) { 117 if (!pde_data)
76 char name[9]; 118 return NULL;
77 struct proc_dir_entry* e; 119
78 120 pde_data->res_ptr = ptr;
79 snprintf(name, sizeof(name), "%x", ent.type); 121 pde_data->res_size = size;
80 e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent, 122 return pde_data;
81 &nubus_proc_subdir_fops);
82 if (!e)
83 return;
84 }
85} 123}
86 124
87/* Can't do this recursively since the root directory is structured 125static int nubus_proc_rsrc_show(struct seq_file *m, void *v)
88 somewhat differently from the subdirectories */
89static void nubus_proc_populate(struct nubus_dev* dev,
90 struct proc_dir_entry* parent,
91 struct nubus_dir* root)
92{ 126{
93 struct nubus_dirent ent; 127 struct inode *inode = m->private;
94 128 struct nubus_proc_pde_data *pde_data;
95 /* We know these are all directories (board resource + one or 129
96 more functional resources) */ 130 pde_data = PDE_DATA(inode);
97 while (nubus_readdir(root, &ent) != -1) { 131 if (!pde_data)
98 char name[9]; 132 return 0;
99 struct proc_dir_entry* e; 133
100 struct nubus_dir dir; 134 if (pde_data->res_size > m->size)
101 135 return -EFBIG;
102 snprintf(name, sizeof(name), "%x", ent.type); 136
103 e = proc_mkdir(name, parent); 137 if (pde_data->res_size) {
104 if (!e) return; 138 int lanes = (int)proc_get_parent_data(inode);
105 139 struct nubus_dirent ent;
106 /* And descend */ 140
107 if (nubus_get_subdir(&ent, &dir) == -1) { 141 if (!lanes)
108 /* This shouldn't happen */ 142 return 0;
109 printk(KERN_ERR "NuBus root directory node %x:%x has no subdir!\n", 143
110 dev->board->slot, ent.type); 144 ent.mask = lanes;
111 continue; 145 ent.base = pde_data->res_ptr;
112 } else { 146 ent.data = 0;
113 nubus_proc_subdir(dev, e, &dir); 147 nubus_seq_write_rsrc_mem(m, &ent, pde_data->res_size);
114 } 148 } else {
149 unsigned int data = (unsigned int)pde_data->res_ptr;
150
151 seq_putc(m, data >> 16);
152 seq_putc(m, data >> 8);
153 seq_putc(m, data >> 0);
115 } 154 }
155 return 0;
116} 156}
117 157
118int nubus_proc_attach_device(struct nubus_dev *dev) 158static int nubus_proc_rsrc_open(struct inode *inode, struct file *file)
159{
160 return single_open(file, nubus_proc_rsrc_show, inode);
161}
162
163static const struct file_operations nubus_proc_rsrc_fops = {
164 .open = nubus_proc_rsrc_open,
165 .read = seq_read,
166 .llseek = seq_lseek,
167 .release = single_release,
168};
169
170void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir,
171 const struct nubus_dirent *ent,
172 unsigned int size)
119{ 173{
120 struct proc_dir_entry *e;
121 struct nubus_dir root;
122 char name[9]; 174 char name[9];
175 struct nubus_proc_pde_data *pde_data;
123 176
124 if (dev == NULL) { 177 if (!procdir)
125 printk(KERN_ERR 178 return;
126 "NULL pointer in nubus_proc_attach_device, shoot the programmer!\n");
127 return -1;
128 }
129
130 if (dev->board == NULL) {
131 printk(KERN_ERR
132 "NULL pointer in nubus_proc_attach_device, shoot the programmer!\n");
133 printk("dev = %p, dev->board = %p\n", dev, dev->board);
134 return -1;
135 }
136
137 if (dev->board->procdir)
138 return 0;
139 179
140 /* Create a directory */ 180 snprintf(name, sizeof(name), "%x", ent->type);
141 snprintf(name, sizeof(name), "%x", dev->board->slot); 181 if (size)
142 e = proc_mkdir(name, proc_bus_nubus_dir); 182 pde_data = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size);
143 dev->board->procdir = e; 183 else
144 if (!e) 184 pde_data = NULL;
145 return -ENOMEM; 185 proc_create_data(name, S_IFREG | 0444, procdir,
186 &nubus_proc_rsrc_fops, pde_data);
187}
146 188
147 /* Now recursively populate it with files */ 189void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
148 nubus_get_root_dir(dev->board, &root); 190 const struct nubus_dirent *ent)
149 nubus_proc_populate(dev, e, &root); 191{
192 char name[9];
193 unsigned char *data = (unsigned char *)ent->data;
150 194
151 return 0; 195 if (!procdir)
196 return;
197
198 snprintf(name, sizeof(name), "%x", ent->type);
199 proc_create_data(name, S_IFREG | 0444, procdir,
200 &nubus_proc_rsrc_fops,
201 nubus_proc_alloc_pde_data(data, 0));
152} 202}
153EXPORT_SYMBOL(nubus_proc_attach_device);
154 203
155/* 204/*
156 * /proc/nubus stuff 205 * /proc/nubus stuff
@@ -219,18 +268,11 @@ static const struct file_operations nubus_proc_fops = {
219 .release = seq_release, 268 .release = seq_release,
220}; 269};
221 270
222void __init proc_bus_nubus_add_devices(void)
223{
224 struct nubus_dev *dev;
225
226 for(dev = nubus_devices; dev; dev = dev->next)
227 nubus_proc_attach_device(dev);
228}
229
230void __init nubus_proc_init(void) 271void __init nubus_proc_init(void)
231{ 272{
232 proc_create("nubus", 0, NULL, &nubus_proc_fops); 273 proc_create("nubus", 0, NULL, &nubus_proc_fops);
233 proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL); 274 proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL);
275 if (!proc_bus_nubus_dir)
276 return;
234 proc_create("devices", 0, proc_bus_nubus_dir, &nubus_devices_proc_fops); 277 proc_create("devices", 0, proc_bus_nubus_dir, &nubus_devices_proc_fops);
235 proc_bus_nubus_add_devices();
236} 278}